j
This commit is contained in:
@@ -95,6 +95,8 @@ import {
|
||||
addExtraSheetRow,
|
||||
clearExtraSheetCellFormatting,
|
||||
DEFAULT_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
MAX_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
MIN_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
deleteExtraSheetColumn,
|
||||
deleteExtraSheetRow,
|
||||
extraSheetRangeToTsv,
|
||||
@@ -408,6 +410,7 @@ export function ExtraSheetEditor({
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
const sheetRootRef = useRef<HTMLDivElement>(null);
|
||||
const spreadsheetRef = useRef<SpreadsheetRef>(null);
|
||||
const initialEditTextRef = useRef<string | null>(null);
|
||||
const [active, setActive] = useState<Point>({ row: 0, column: 0 });
|
||||
@@ -417,7 +420,6 @@ export function ExtraSheetEditor({
|
||||
const [removeOpen, setRemoveOpen] = useState(false);
|
||||
const [selectedCount, setSelectedCount] = useState(1);
|
||||
const [selectionKind, setSelectionKind] = useState<"cells" | "rows" | "columns">("cells");
|
||||
const [draftWidths, setDraftWidths] = useState<Record<number, number>>({});
|
||||
const [history, setHistory] = useState<SheetHistory>({
|
||||
items: [value],
|
||||
index: 0,
|
||||
@@ -548,17 +550,34 @@ export function ExtraSheetEditor({
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.closest("input, textarea, [contenteditable='true']")) return;
|
||||
const key = event.key.toLowerCase();
|
||||
const commandKey = event.metaKey || event.ctrlKey;
|
||||
const undo =
|
||||
(event.metaKey || event.ctrlKey) && !event.shiftKey && key === "z";
|
||||
commandKey && !event.shiftKey && key === "z";
|
||||
const redo =
|
||||
((event.metaKey || event.ctrlKey) && event.shiftKey && key === "z") ||
|
||||
(commandKey && event.shiftKey && key === "z") ||
|
||||
(event.ctrlKey && !event.shiftKey && key === "y");
|
||||
const format = commandKey && !event.altKey && !event.shiftKey
|
||||
? ({ b: "bold", i: "italic", u: "underline" } as const)[key as "b" | "i" | "u"]
|
||||
: event.altKey && event.shiftKey && key === "5"
|
||||
? "strike"
|
||||
: undefined;
|
||||
if (undo && canUndo) {
|
||||
event.preventDefault();
|
||||
travel(-1);
|
||||
} else if (redo && canRedo) {
|
||||
event.preventDefault();
|
||||
travel(1);
|
||||
} else if (format) {
|
||||
event.preventDefault();
|
||||
const activePattern = {
|
||||
bold: /<strong\b/i,
|
||||
italic: /<em\b/i,
|
||||
underline: /<u\b/i,
|
||||
strike: /<s\b/i,
|
||||
}[format];
|
||||
commitSheet(styleExtraSheetCells(value, selectedPointsRef.current, {
|
||||
[format]: !activePattern.test(activeValue),
|
||||
}));
|
||||
} else if (event.key === "Delete" || event.key === "Backspace") {
|
||||
event.preventDefault();
|
||||
commitSheet(updateExtraSheetCells(value, selectedPointsRef.current, { value: "" }));
|
||||
@@ -689,14 +708,18 @@ export function ExtraSheetEditor({
|
||||
};
|
||||
const resizeColumn = useCallback(
|
||||
(column: number, width: number, commit: boolean) => {
|
||||
setDraftWidths((current) => ({ ...current, [column]: width }));
|
||||
if (!commit) return;
|
||||
setDraftWidths((current) => {
|
||||
const next = { ...current };
|
||||
delete next[column];
|
||||
return next;
|
||||
});
|
||||
commitSheet(resizeExtraSheetColumn(value, column, width));
|
||||
const boundedWidth = Math.round(Math.max(
|
||||
MIN_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
Math.min(MAX_EXTRA_SHEET_COLUMN_WIDTH, width),
|
||||
));
|
||||
if (!commit) {
|
||||
const columnElement = sheetRootRef.current?.querySelector<HTMLTableColElement>(
|
||||
`col[data-sheet-column-index="${column}"]`,
|
||||
);
|
||||
if (columnElement) columnElement.style.width = `${boundedWidth}px`;
|
||||
return;
|
||||
}
|
||||
commitSheet(resizeExtraSheetColumn(value, column, boundedWidth));
|
||||
},
|
||||
[commitSheet, value],
|
||||
);
|
||||
@@ -707,12 +730,11 @@ export function ExtraSheetEditor({
|
||||
id={columnDragId(value.columns[props.column].id)}
|
||||
onRename={openRenameColumn}
|
||||
onResize={resizeColumn}
|
||||
width={draftWidths[props.column]
|
||||
?? value.columns[props.column].width
|
||||
width={value.columns[props.column].width
|
||||
?? DEFAULT_EXTRA_SHEET_COLUMN_WIDTH}
|
||||
/>
|
||||
),
|
||||
[draftWidths, openRenameColumn, resizeColumn, value.columns],
|
||||
[openRenameColumn, resizeColumn, value.columns],
|
||||
);
|
||||
const rowIndicator = useCallback(
|
||||
(props: RowIndicatorProps) => (
|
||||
@@ -744,9 +766,9 @@ export function ExtraSheetEditor({
|
||||
{Array.from({ length: columns }, (_, index) => (
|
||||
<col
|
||||
key={value.columns[index]?.id ?? index}
|
||||
data-sheet-column-index={index}
|
||||
style={{
|
||||
width: draftWidths[index]
|
||||
?? value.columns[index]?.width
|
||||
width: value.columns[index]?.width
|
||||
?? DEFAULT_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
}}
|
||||
/>
|
||||
@@ -755,7 +777,7 @@ export function ExtraSheetEditor({
|
||||
<tbody>{children}</tbody>
|
||||
</table>
|
||||
),
|
||||
[draftWidths, value.columns],
|
||||
[value.columns],
|
||||
);
|
||||
const activeFormats = [
|
||||
/<strong\b/i.test(activeValue) ? "bold" : null,
|
||||
@@ -768,6 +790,7 @@ export function ExtraSheetEditor({
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={sheetRootRef}
|
||||
className="flex min-w-0 flex-col gap-3"
|
||||
aria-label="ตารางข้อมูลเสริม"
|
||||
onKeyDown={handleSheetKeyDown}
|
||||
@@ -811,16 +834,16 @@ export function ExtraSheetEditor({
|
||||
if (Object.keys(patch).length) applyStyle(patch);
|
||||
}}
|
||||
>
|
||||
<ToggleGroupItem value="bold" aria-label="ตัวหนา">
|
||||
<ToggleGroupItem value="bold" aria-label="ตัวหนา" title="ตัวหนา (Ctrl/⌘ B)">
|
||||
<BoldIcon />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value="italic" aria-label="ตัวเอียง">
|
||||
<ToggleGroupItem value="italic" aria-label="ตัวเอียง" title="ตัวเอียง (Ctrl/⌘ I)">
|
||||
<ItalicIcon />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value="underline" aria-label="ขีดเส้นใต้">
|
||||
<ToggleGroupItem value="underline" aria-label="ขีดเส้นใต้" title="ขีดเส้นใต้ (Ctrl/⌘ U)">
|
||||
<UnderlineIcon />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem value="strike" aria-label="ขีดฆ่า">
|
||||
<ToggleGroupItem value="strike" aria-label="ขีดฆ่า" title="ขีดฆ่า (Alt/⌥ Shift 5)">
|
||||
<StrikethroughIcon />
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
|
||||
@@ -4829,7 +4829,7 @@ function ExtraEditor({ guide, extraSectionId, initial, characters, weapons, arti
|
||||
}
|
||||
>
|
||||
<PlusIcon data-icon="inline-start" />
|
||||
เพิ่มตาราง 2 × 2
|
||||
เพิ่มตาราง 4 × 6
|
||||
</Button>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
@@ -56,7 +56,10 @@ import {
|
||||
} from "@/lib/guides/talents";
|
||||
import { parseYouTubeUrl } from "@/lib/guides/youtube";
|
||||
import { normalizeExtraRichText } from "@/lib/rich-text";
|
||||
import { DEFAULT_EXTRA_SHEET_COLUMN_WIDTH } from "@/lib/guides/extra-sheet";
|
||||
import {
|
||||
DEFAULT_EXTRA_SHEET_COLUMN_WIDTH,
|
||||
extraSheetUsedRange,
|
||||
} from "@/lib/guides/extra-sheet";
|
||||
import { publicGuideSections } from "@/lib/guides/public-sections";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -1295,12 +1298,14 @@ function ExtraSectionContent({
|
||||
{action}
|
||||
</header>
|
||||
<div className={cn("relative z-10 grid gap-5 md:grid-cols-2", exporting && "grid-cols-2")}>
|
||||
{extra.rows.map((row) => (
|
||||
{extra.rows.map((row) => {
|
||||
const displaySheet = row.sheet ? extraSheetUsedRange(row.sheet) : null;
|
||||
return (
|
||||
<Card
|
||||
key={row.id}
|
||||
className={cn(
|
||||
"overflow-hidden py-0",
|
||||
row.sheet && (exporting ? "col-span-2" : "md:col-span-2"),
|
||||
displaySheet && (exporting ? "col-span-2" : "md:col-span-2"),
|
||||
)}
|
||||
style={row.backgroundColor ? { backgroundColor: row.backgroundColor } : undefined}
|
||||
>
|
||||
@@ -1355,7 +1360,7 @@ function ExtraSectionContent({
|
||||
</CardDescription>
|
||||
{row.percent ? <Badge>{metric(row.percent, exporting ? "en-US" : undefined)}</Badge> : null}
|
||||
</CardHeader>
|
||||
{row.sheet ? (
|
||||
{displaySheet ? (
|
||||
<CardContent
|
||||
className={cn(
|
||||
"pb-5",
|
||||
@@ -1365,14 +1370,14 @@ function ExtraSectionContent({
|
||||
<Table
|
||||
className={cn(exporting && "table-fixed")}
|
||||
style={{
|
||||
minWidth: `${row.sheet.columns.reduce(
|
||||
minWidth: `${displaySheet.columns.reduce(
|
||||
(total, column) => total + (column.width ?? DEFAULT_EXTRA_SHEET_COLUMN_WIDTH),
|
||||
0,
|
||||
)}px`,
|
||||
}}
|
||||
>
|
||||
<colgroup>
|
||||
{row.sheet.columns.map((column) => (
|
||||
{displaySheet.columns.map((column) => (
|
||||
<col
|
||||
key={column.id}
|
||||
style={{ width: column.width ?? DEFAULT_EXTRA_SHEET_COLUMN_WIDTH }}
|
||||
@@ -1381,7 +1386,7 @@ function ExtraSectionContent({
|
||||
</colgroup>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{row.sheet.columns.map((column) => (
|
||||
{displaySheet.columns.map((column) => (
|
||||
<TableHead key={column.id} className="border-l first:border-l-0 whitespace-normal">
|
||||
{column.label}
|
||||
</TableHead>
|
||||
@@ -1389,9 +1394,9 @@ function ExtraSectionContent({
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{row.sheet.rows.map((sheetRow) => (
|
||||
{displaySheet.rows.map((sheetRow) => (
|
||||
<TableRow key={sheetRow.id}>
|
||||
{row.sheet!.columns.map((column) => (
|
||||
{displaySheet.columns.map((column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
className="border-l first:border-l-0 whitespace-normal"
|
||||
@@ -1413,7 +1418,8 @@ function ExtraSectionContent({
|
||||
</CardContent>
|
||||
) : null}
|
||||
</Card>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user