@comitor/ui 1.11.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/dist/data-grid/data-grid-cell-variants.js +10 -6
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
- package/dist/data-grid/data-grid-column-header.js +4 -2
- package/dist/data-grid/data-grid-column-header.js.map +1 -1
- package/dist/data-grid/data-grid-context-menu.js +4 -3
- package/dist/data-grid/data-grid-context-menu.js.map +1 -1
- package/dist/data-grid/data-grid-filter-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-filter-menu.js +28 -17
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +12 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.js +7 -5
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
- package/dist/data-grid/data-grid-locale.d.ts +24 -0
- package/dist/data-grid/data-grid-locale.js +25 -0
- package/dist/data-grid/data-grid-locale.js.map +1 -0
- package/dist/data-grid/data-grid-paste-dialog.js +2 -1
- package/dist/data-grid/data-grid-paste-dialog.js.map +1 -1
- package/dist/data-grid/data-grid-row-height-menu.d.ts +11 -1
- package/dist/data-grid/data-grid-row-height-menu.js +25 -28
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
- package/dist/data-grid/data-grid-search.js +5 -4
- package/dist/data-grid/data-grid-search.js.map +1 -1
- package/dist/data-grid/data-grid-select-column.js +3 -1
- package/dist/data-grid/data-grid-select-column.js.map +1 -1
- package/dist/data-grid/data-grid-sort-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-sort-menu.js +25 -13
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
- package/dist/data-grid/data-grid-view-menu.d.ts +12 -1
- package/dist/data-grid/data-grid-view-menu.js +12 -4
- package/dist/data-grid/data-grid-view-menu.js.map +1 -1
- package/dist/data-grid/data-grid.d.ts +14 -2
- package/dist/data-grid/data-grid.js +6 -3
- package/dist/data-grid/data-grid.js.map +1 -1
- package/dist/data-grid/filters.d.ts +17 -21
- package/dist/data-grid/filters.js +73 -52
- package/dist/data-grid/filters.js.map +1 -1
- package/dist/data-grid/index.d.ts +4 -1
- package/dist/data-grid/index.js +20 -2
- package/dist/data-grid/index.js.map +1 -1
- package/dist/data-grid/messages-en.d.ts +294 -0
- package/dist/data-grid/messages-en.js +279 -0
- package/dist/data-grid/messages-en.js.map +1 -0
- package/dist/data-grid/messages-vi.d.ts +12 -0
- package/dist/data-grid/messages-vi.js +279 -0
- package/dist/data-grid/messages-vi.js.map +1 -0
- package/dist/data-grid/messages.d.ts +549 -262
- package/dist/data-grid/messages.js +16 -275
- package/dist/data-grid/messages.js.map +1 -1
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +13 -1
- package/dist/data-grid/use-data-grid-undo-redo.js +11 -8
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
- package/dist/data-grid/use-data-grid.d.ts +281 -1
- package/dist/data-grid/use-data-grid.js +21 -16
- package/dist/data-grid/use-data-grid.js.map +1 -1
- package/dist/data-grid/utils.d.ts +9 -1
- package/dist/data-grid/utils.js +3 -2
- package/dist/data-grid/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -16,15 +16,24 @@ import {
|
|
|
16
16
|
import { Popover, PopoverContent, PopoverTrigger } from "../components/ui/popover.js";
|
|
17
17
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../components/ui/select.js";
|
|
18
18
|
import { cn } from "../lib/cn.js";
|
|
19
|
-
import {
|
|
19
|
+
import { DataGridLocaleProvider, useDataGridMessages, useResolvedDataGridMessages } from "./data-grid-locale.js";
|
|
20
20
|
import { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from "./sortable.js";
|
|
21
21
|
const SORT_SHORTCUT_KEY = "s";
|
|
22
22
|
const REMOVE_SORT_SHORTCUTS = /* @__PURE__ */ new Set(["backspace", "delete"]);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
function buildSortOrders(msg) {
|
|
24
|
+
return [
|
|
25
|
+
{ label: msg.sort.asc, value: "asc" },
|
|
26
|
+
{ label: msg.sort.desc, value: "desc" }
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function DataGridSortMenu({
|
|
30
|
+
table,
|
|
31
|
+
disabled,
|
|
32
|
+
className,
|
|
33
|
+
locale,
|
|
34
|
+
...props
|
|
35
|
+
}) {
|
|
36
|
+
const msg = useResolvedDataGridMessages(locale);
|
|
28
37
|
const dir = useDirection();
|
|
29
38
|
const id = React.useId();
|
|
30
39
|
const labelId = React.useId();
|
|
@@ -96,18 +105,19 @@ function DataGridSortMenu({ table, disabled, className, ...props }) {
|
|
|
96
105
|
},
|
|
97
106
|
[sorting.length, onSortingReset]
|
|
98
107
|
);
|
|
99
|
-
return /* @__PURE__ */ jsxs(Sortable, { value: sorting, onValueChange: onSortingChange, getItemValue: (item) => item.id, children: [
|
|
108
|
+
return /* @__PURE__ */ jsx(DataGridLocaleProvider, { locale: msg, children: /* @__PURE__ */ jsxs(Sortable, { value: sorting, onValueChange: onSortingChange, getItemValue: (item) => item.id, children: [
|
|
100
109
|
/* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
101
110
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
102
111
|
Button,
|
|
103
112
|
{
|
|
104
113
|
dir,
|
|
105
114
|
variant: "outline",
|
|
106
|
-
|
|
115
|
+
size: "sm",
|
|
116
|
+
className: "font-normal",
|
|
107
117
|
onKeyDown: onTriggerKeyDown,
|
|
108
118
|
disabled,
|
|
109
119
|
children: [
|
|
110
|
-
/* @__PURE__ */ jsx(ArrowDownUp, { "aria-hidden": "true", className: "text-muted-foreground" }),
|
|
120
|
+
/* @__PURE__ */ jsx(ArrowDownUp, { "aria-hidden": "true", className: "size-3.5 text-muted-foreground" }),
|
|
111
121
|
msg.sort.trigger,
|
|
112
122
|
sorting.length > 0 && /* @__PURE__ */ jsx(
|
|
113
123
|
"span",
|
|
@@ -175,7 +185,7 @@ function DataGridSortMenu({ table, disabled, className, ...props }) {
|
|
|
175
185
|
/* @__PURE__ */ jsx("div", { className: "size-8 shrink-0 rounded-sm bg-muted" }),
|
|
176
186
|
/* @__PURE__ */ jsx("div", { className: "size-8 shrink-0 rounded-sm bg-muted" })
|
|
177
187
|
] }) })
|
|
178
|
-
] });
|
|
188
|
+
] }) });
|
|
179
189
|
}
|
|
180
190
|
function DataTableSortItem({
|
|
181
191
|
sort,
|
|
@@ -186,6 +196,8 @@ function DataTableSortItem({
|
|
|
186
196
|
onSortUpdate,
|
|
187
197
|
onSortRemove
|
|
188
198
|
}) {
|
|
199
|
+
const msg = useDataGridMessages();
|
|
200
|
+
const sortOrders = React.useMemo(() => buildSortOrders(msg), [msg]);
|
|
189
201
|
const fieldListboxId = `${sortItemId}-field-listbox`;
|
|
190
202
|
const fieldTriggerId = `${sortItemId}-field-trigger`;
|
|
191
203
|
const directionListboxId = `${sortItemId}-direction-listbox`;
|
|
@@ -246,7 +258,7 @@ function DataTableSortItem({
|
|
|
246
258
|
onValueChange: (value) => onSortUpdate(sort.id, { desc: value === "desc" }),
|
|
247
259
|
children: [
|
|
248
260
|
/* @__PURE__ */ jsx(SelectTrigger, { "aria-controls": directionListboxId, "aria-label": msg.sort.title, className: "h-8 w-28 rounded", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
249
|
-
/* @__PURE__ */ jsx(SelectContent, { id: directionListboxId, className: "min-w-[--radix-select-trigger-width]", children: /* @__PURE__ */ jsx(SelectGroup, { children:
|
|
261
|
+
/* @__PURE__ */ jsx(SelectContent, { id: directionListboxId, className: "min-w-[--radix-select-trigger-width]", children: /* @__PURE__ */ jsx(SelectGroup, { children: sortOrders.map((order) => /* @__PURE__ */ jsx(SelectItem, { value: order.value, children: order.label }, order.value)) }) })
|
|
250
262
|
]
|
|
251
263
|
}
|
|
252
264
|
),
|
|
@@ -259,10 +271,10 @@ function DataTableSortItem({
|
|
|
259
271
|
size: "icon",
|
|
260
272
|
className: "size-8 shrink-0 rounded",
|
|
261
273
|
onClick: () => onSortRemove(sort.id),
|
|
262
|
-
children: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true" })
|
|
274
|
+
children: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true", className: "size-3.5" })
|
|
263
275
|
}
|
|
264
276
|
),
|
|
265
|
-
/* @__PURE__ */ jsx(SortableItemHandle, { asChild: true, children: /* @__PURE__ */ jsx(Button, { "aria-label": msg.sort.drag, variant: "outline", size: "icon", className: "size-8 shrink-0 rounded", children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true" }) }) })
|
|
277
|
+
/* @__PURE__ */ jsx(SortableItemHandle, { asChild: true, children: /* @__PURE__ */ jsx(Button, { "aria-label": msg.sort.drag, variant: "outline", size: "icon", className: "size-8 shrink-0 rounded", children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true", className: "size-3.5" }) }) })
|
|
266
278
|
] }) });
|
|
267
279
|
}
|
|
268
280
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data-grid/data-grid-sort-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { ColumnSort, SortDirection, Table } from \"@tanstack/react-table\";\nimport { ArrowDownUp, ChevronsUpDown, GripVertical, Trash2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { badgeVariants } from \"../components/ui/badge.js\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from \"../components/ui/select.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { msg } from \"./messages.js\";\nimport { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from \"./sortable.js\";\n\nconst SORT_SHORTCUT_KEY = \"s\";\nconst REMOVE_SORT_SHORTCUTS = new Set([\"backspace\", \"delete\"]);\nconst SORT_ORDERS = [\n { label: msg.sort.asc, value: \"asc\" },\n { label: msg.sort.desc, value: \"desc\" }\n];\n\ninterface DataGridSortMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n}\n\nexport function DataGridSortMenu<TData>({ table, disabled, className, ...props }: DataGridSortMenuProps<TData>) {\n const dir = useDirection();\n const id = React.useId();\n const labelId = React.useId();\n const descriptionId = React.useId();\n const [open, setOpen] = React.useState(false);\n const addButtonRef = React.useRef<HTMLButtonElement>(null);\n\n const sorting = table.getState().sorting;\n const onSortingChange = table.setSorting;\n\n const { columnLabels, columns } = React.useMemo(() => {\n const labels = new Map<string, string>();\n const sortingIds = new Set(sorting.map((s) => s.id));\n const availableColumns: { id: string; label: string }[] = [];\n\n for (const column of table.getAllColumns()) {\n if (!column.getCanSort()) continue;\n\n const label = column.columnDef.meta?.label ?? column.id;\n labels.set(column.id, label);\n\n if (!sortingIds.has(column.id)) {\n availableColumns.push({ id: column.id, label });\n }\n }\n\n return {\n columnLabels: labels,\n columns: availableColumns\n };\n }, [sorting, table]);\n\n const onSortAdd = React.useCallback(() => {\n const firstColumn = columns[0];\n if (!firstColumn) return;\n\n onSortingChange((prevSorting) => [...prevSorting, { id: firstColumn.id, desc: false }]);\n }, [columns, onSortingChange]);\n\n const onSortUpdate = React.useCallback(\n (sortId: string, updates: Partial<ColumnSort>) => {\n onSortingChange((prevSorting) => {\n if (!prevSorting) return prevSorting;\n return prevSorting.map((sort) => (sort.id === sortId ? { ...sort, ...updates } : sort));\n });\n },\n [onSortingChange]\n );\n\n const onSortRemove = React.useCallback(\n (sortId: string) => {\n onSortingChange((prevSorting) => prevSorting.filter((item) => item.id !== sortId));\n },\n [onSortingChange]\n );\n\n const onSortingReset = React.useCallback(\n () => onSortingChange(table.initialState.sorting),\n [onSortingChange, table.initialState.sorting]\n );\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLTextAreaElement ||\n (event.target instanceof HTMLElement && event.target.contentEditable === \"true\")\n ) {\n return;\n }\n\n if (event.key.toLowerCase() === SORT_SHORTCUT_KEY && (event.ctrlKey || event.metaKey) && event.shiftKey) {\n event.preventDefault();\n setOpen((prev) => !prev);\n }\n }\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, []);\n\n const onTriggerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase()) && sorting.length > 0) {\n event.preventDefault();\n onSortingReset();\n }\n },\n [sorting.length, onSortingReset]\n );\n\n return (\n <Sortable value={sorting} onValueChange={onSortingChange} getItemValue={(item) => item.id}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n dir={dir}\n variant=\"outline\"\n className=\"h-8 gap-2 font-normal\"\n onKeyDown={onTriggerKeyDown}\n disabled={disabled}\n >\n <ArrowDownUp aria-hidden=\"true\" className=\"text-muted-foreground\" />\n {msg.sort.trigger}\n {sorting.length > 0 && (\n <span\n className={cn(\n badgeVariants({ variant: \"secondary\" }),\n \"h-5 rounded px-1.5 font-mono text-[11px] font-medium\"\n )}\n >\n {sorting.length}\n </span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n aria-labelledby={labelId}\n aria-describedby={descriptionId}\n dir={dir}\n className={cn(\n \"flex w-full max-w-[--radix-popover-content-available-width] flex-col gap-3.5 p-4 sm:min-w-[380px]\",\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-1\">\n <h4 id={labelId} className=\"font-medium leading-none\">\n {sorting.length > 0 ? msg.sort.title : msg.sort.emptyTitle}\n </h4>\n <p id={descriptionId} className={cn(\"text-muted-foreground text-sm\", sorting.length > 0 && \"sr-only\")}>\n {sorting.length > 0 ? msg.sort.description : msg.sort.emptyDescription}\n </p>\n </div>\n {sorting.length > 0 && (\n <SortableContent asChild>\n <div role=\"list\" className=\"flex max-h-[300px] flex-col gap-2 overflow-y-auto p-1\">\n {sorting.map((sort) => (\n <DataTableSortItem\n key={sort.id}\n sort={sort}\n sortItemId={`${id}-sort-${sort.id}`}\n dir={dir}\n columns={columns}\n columnLabels={columnLabels}\n onSortUpdate={onSortUpdate}\n onSortRemove={onSortRemove}\n />\n ))}\n </div>\n </SortableContent>\n )}\n <div className=\"flex w-full items-center gap-2\">\n <Button\n size=\"sm\"\n className=\"rounded\"\n ref={addButtonRef}\n onClick={onSortAdd}\n disabled={columns.length === 0}\n >\n {msg.sort.add}\n </Button>\n {sorting.length > 0 && (\n <Button variant=\"outline\" size=\"sm\" className=\"rounded\" onClick={onSortingReset}>\n {msg.sort.reset}\n </Button>\n )}\n </div>\n </PopoverContent>\n </Popover>\n <SortableOverlay>\n <div dir={dir} className=\"flex items-center gap-2\">\n <div className=\"h-8 w-44 rounded-sm bg-muted\" />\n <div className=\"h-8 w-24 rounded-sm bg-muted\" />\n <div className=\"size-8 shrink-0 rounded-sm bg-muted\" />\n <div className=\"size-8 shrink-0 rounded-sm bg-muted\" />\n </div>\n </SortableOverlay>\n </Sortable>\n );\n}\n\ninterface DataTableSortItemProps {\n sort: ColumnSort;\n sortItemId: string;\n dir: \"ltr\" | \"rtl\";\n columns: { id: string; label: string }[];\n columnLabels: Map<string, string>;\n onSortUpdate: (sortId: string, updates: Partial<ColumnSort>) => void;\n onSortRemove: (sortId: string) => void;\n}\n\nfunction DataTableSortItem({\n sort,\n sortItemId,\n dir,\n columns,\n columnLabels,\n onSortUpdate,\n onSortRemove\n}: DataTableSortItemProps) {\n const fieldListboxId = `${sortItemId}-field-listbox`;\n const fieldTriggerId = `${sortItemId}-field-trigger`;\n const directionListboxId = `${sortItemId}-direction-listbox`;\n\n const [showFieldSelector, setShowFieldSelector] = React.useState(false);\n const [showDirectionSelector, setShowDirectionSelector] = React.useState(false);\n\n const onItemKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n if (showFieldSelector || showDirectionSelector) {\n return;\n }\n\n if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase())) {\n event.preventDefault();\n onSortRemove(sort.id);\n }\n },\n [sort.id, showFieldSelector, showDirectionSelector, onSortRemove]\n );\n\n return (\n <SortableItem value={sort.id} asChild>\n <div role=\"listitem\" id={sortItemId} tabIndex={-1} className=\"flex items-center gap-2\" onKeyDown={onItemKeyDown}>\n <Popover open={showFieldSelector} onOpenChange={setShowFieldSelector}>\n <PopoverTrigger asChild>\n <Button\n id={fieldTriggerId}\n aria-controls={fieldListboxId}\n variant=\"outline\"\n className=\"h-8 w-44 justify-between rounded font-normal\"\n >\n <span className=\"truncate\">{columnLabels.get(sort.id)}</span>\n <ChevronsUpDown aria-hidden=\"true\" className=\"opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent id={fieldListboxId} dir={dir} className=\"w-[--radix-popover-trigger-width] p-0\">\n <Command>\n <CommandInput placeholder={msg.sort.fieldPlaceholder} aria-label={msg.sort.fieldPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.sort.fieldEmpty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => (\n <CommandItem\n key={column.id}\n value={column.id}\n onSelect={(value) => onSortUpdate(sort.id, { id: value })}\n >\n <span className=\"truncate\">{column.label}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <Select\n open={showDirectionSelector}\n onOpenChange={setShowDirectionSelector}\n value={sort.desc ? \"desc\" : \"asc\"}\n onValueChange={(value: SortDirection) => onSortUpdate(sort.id, { desc: value === \"desc\" })}\n >\n <SelectTrigger aria-controls={directionListboxId} aria-label={msg.sort.title} className=\"h-8 w-28 rounded\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent id={directionListboxId} className=\"min-w-[--radix-select-trigger-width]\">\n <SelectGroup>\n {SORT_ORDERS.map((order) => (\n <SelectItem key={order.value} value={order.value}>\n {order.label}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n <Button\n aria-controls={sortItemId}\n aria-label={msg.sort.remove}\n variant=\"outline\"\n size=\"icon\"\n className=\"size-8 shrink-0 rounded\"\n onClick={() => onSortRemove(sort.id)}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n <SortableItemHandle asChild>\n <Button aria-label={msg.sort.drag} variant=\"outline\" size=\"icon\" className=\"size-8 shrink-0 rounded\">\n <GripVertical aria-hidden=\"true\" />\n </Button>\n </SortableItemHandle>\n </div>\n </SortableItem>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/data-grid-sort-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { ColumnSort, SortDirection, Table } from \"@tanstack/react-table\";\nimport { ArrowDownUp, ChevronsUpDown, GripVertical, Trash2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { badgeVariants } from \"../components/ui/badge.js\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from \"../components/ui/select.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { DataGridLocaleProvider, useDataGridMessages, useResolvedDataGridMessages } from \"./data-grid-locale.js\";\nimport type { DataGridLocale, DataGridMessages } from \"./messages.js\";\nimport { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from \"./sortable.js\";\n\nconst SORT_SHORTCUT_KEY = \"s\";\nconst REMOVE_SORT_SHORTCUTS = new Set([\"backspace\", \"delete\"]);\n/* Nhãn đổi theo ngôn ngữ, `value` thì không — nên đây là hàm, không phải hằng module. */\nfunction buildSortOrders(msg: DataGridMessages) {\n return [\n { label: msg.sort.asc, value: \"asc\" },\n { label: msg.sort.desc, value: \"desc\" }\n ];\n}\n\ninterface DataGridSortMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n /**\n * Ngôn ngữ của menu: `\"en\"` (mặc định) · `\"vi\"`, hoặc cả một bảng chuỗi tự soạn.\n *\n * ⚠ Thanh công cụ nằm NGOÀI `<DataGrid>`, nên `locale` truyền cho lưới không với tới đây. Bọc\n * cả màn bằng `DataGridLocaleProvider` (một lần, đúng cho mọi mảnh), hoặc truyền prop này cho\n * từng menu. Prop thắng provider.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\nexport function DataGridSortMenu<TData>({\n table,\n disabled,\n className,\n locale,\n ...props\n}: DataGridSortMenuProps<TData>) {\n // Menu TỰ giữ bảng chuỗi rồi PHÁT xuống cho `DataTableSortItem` bên dưới — nó là bên cung\n // cấp context nên không đọc context của chính mình được.\n const msg = useResolvedDataGridMessages(locale);\n const dir = useDirection();\n const id = React.useId();\n const labelId = React.useId();\n const descriptionId = React.useId();\n const [open, setOpen] = React.useState(false);\n const addButtonRef = React.useRef<HTMLButtonElement>(null);\n\n const sorting = table.getState().sorting;\n const onSortingChange = table.setSorting;\n\n const { columnLabels, columns } = React.useMemo(() => {\n const labels = new Map<string, string>();\n const sortingIds = new Set(sorting.map((s) => s.id));\n const availableColumns: { id: string; label: string }[] = [];\n\n for (const column of table.getAllColumns()) {\n if (!column.getCanSort()) continue;\n\n const label = column.columnDef.meta?.label ?? column.id;\n labels.set(column.id, label);\n\n if (!sortingIds.has(column.id)) {\n availableColumns.push({ id: column.id, label });\n }\n }\n\n return {\n columnLabels: labels,\n columns: availableColumns\n };\n }, [sorting, table]);\n\n const onSortAdd = React.useCallback(() => {\n const firstColumn = columns[0];\n if (!firstColumn) return;\n\n onSortingChange((prevSorting) => [...prevSorting, { id: firstColumn.id, desc: false }]);\n }, [columns, onSortingChange]);\n\n const onSortUpdate = React.useCallback(\n (sortId: string, updates: Partial<ColumnSort>) => {\n onSortingChange((prevSorting) => {\n if (!prevSorting) return prevSorting;\n return prevSorting.map((sort) => (sort.id === sortId ? { ...sort, ...updates } : sort));\n });\n },\n [onSortingChange]\n );\n\n const onSortRemove = React.useCallback(\n (sortId: string) => {\n onSortingChange((prevSorting) => prevSorting.filter((item) => item.id !== sortId));\n },\n [onSortingChange]\n );\n\n const onSortingReset = React.useCallback(\n () => onSortingChange(table.initialState.sorting),\n [onSortingChange, table.initialState.sorting]\n );\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLTextAreaElement ||\n (event.target instanceof HTMLElement && event.target.contentEditable === \"true\")\n ) {\n return;\n }\n\n if (event.key.toLowerCase() === SORT_SHORTCUT_KEY && (event.ctrlKey || event.metaKey) && event.shiftKey) {\n event.preventDefault();\n setOpen((prev) => !prev);\n }\n }\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, []);\n\n const onTriggerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase()) && sorting.length > 0) {\n event.preventDefault();\n onSortingReset();\n }\n },\n [sorting.length, onSortingReset]\n );\n\n return (\n <DataGridLocaleProvider locale={msg}>\n <Sortable value={sorting} onValueChange={onSortingChange} getItemValue={(item) => item.id}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n dir={dir}\n variant=\"outline\"\n size=\"sm\"\n className=\"font-normal\"\n onKeyDown={onTriggerKeyDown}\n disabled={disabled}\n >\n <ArrowDownUp aria-hidden=\"true\" className=\"size-3.5 text-muted-foreground\" />\n {msg.sort.trigger}\n {sorting.length > 0 && (\n <span\n className={cn(\n badgeVariants({ variant: \"secondary\" }),\n \"h-5 rounded px-1.5 font-mono text-[11px] font-medium\"\n )}\n >\n {sorting.length}\n </span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n aria-labelledby={labelId}\n aria-describedby={descriptionId}\n dir={dir}\n className={cn(\n \"flex w-full max-w-[--radix-popover-content-available-width] flex-col gap-3.5 p-4 sm:min-w-[380px]\",\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-1\">\n <h4 id={labelId} className=\"font-medium leading-none\">\n {sorting.length > 0 ? msg.sort.title : msg.sort.emptyTitle}\n </h4>\n <p id={descriptionId} className={cn(\"text-muted-foreground text-sm\", sorting.length > 0 && \"sr-only\")}>\n {sorting.length > 0 ? msg.sort.description : msg.sort.emptyDescription}\n </p>\n </div>\n {sorting.length > 0 && (\n <SortableContent asChild>\n <div role=\"list\" className=\"flex max-h-[300px] flex-col gap-2 overflow-y-auto p-1\">\n {sorting.map((sort) => (\n <DataTableSortItem\n key={sort.id}\n sort={sort}\n sortItemId={`${id}-sort-${sort.id}`}\n dir={dir}\n columns={columns}\n columnLabels={columnLabels}\n onSortUpdate={onSortUpdate}\n onSortRemove={onSortRemove}\n />\n ))}\n </div>\n </SortableContent>\n )}\n <div className=\"flex w-full items-center gap-2\">\n <Button\n size=\"sm\"\n className=\"rounded\"\n ref={addButtonRef}\n onClick={onSortAdd}\n disabled={columns.length === 0}\n >\n {msg.sort.add}\n </Button>\n {sorting.length > 0 && (\n <Button variant=\"outline\" size=\"sm\" className=\"rounded\" onClick={onSortingReset}>\n {msg.sort.reset}\n </Button>\n )}\n </div>\n </PopoverContent>\n </Popover>\n <SortableOverlay>\n <div dir={dir} className=\"flex items-center gap-2\">\n <div className=\"h-8 w-44 rounded-sm bg-muted\" />\n <div className=\"h-8 w-24 rounded-sm bg-muted\" />\n <div className=\"size-8 shrink-0 rounded-sm bg-muted\" />\n <div className=\"size-8 shrink-0 rounded-sm bg-muted\" />\n </div>\n </SortableOverlay>\n </Sortable>\n </DataGridLocaleProvider>\n );\n}\n\ninterface DataTableSortItemProps {\n sort: ColumnSort;\n sortItemId: string;\n dir: \"ltr\" | \"rtl\";\n columns: { id: string; label: string }[];\n columnLabels: Map<string, string>;\n onSortUpdate: (sortId: string, updates: Partial<ColumnSort>) => void;\n onSortRemove: (sortId: string) => void;\n}\n\nfunction DataTableSortItem({\n sort,\n sortItemId,\n dir,\n columns,\n columnLabels,\n onSortUpdate,\n onSortRemove\n}: DataTableSortItemProps) {\n const msg = useDataGridMessages();\n const sortOrders = React.useMemo(() => buildSortOrders(msg), [msg]);\n const fieldListboxId = `${sortItemId}-field-listbox`;\n const fieldTriggerId = `${sortItemId}-field-trigger`;\n const directionListboxId = `${sortItemId}-direction-listbox`;\n\n const [showFieldSelector, setShowFieldSelector] = React.useState(false);\n const [showDirectionSelector, setShowDirectionSelector] = React.useState(false);\n\n const onItemKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n if (showFieldSelector || showDirectionSelector) {\n return;\n }\n\n if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase())) {\n event.preventDefault();\n onSortRemove(sort.id);\n }\n },\n [sort.id, showFieldSelector, showDirectionSelector, onSortRemove]\n );\n\n return (\n <SortableItem value={sort.id} asChild>\n <div role=\"listitem\" id={sortItemId} tabIndex={-1} className=\"flex items-center gap-2\" onKeyDown={onItemKeyDown}>\n <Popover open={showFieldSelector} onOpenChange={setShowFieldSelector}>\n <PopoverTrigger asChild>\n <Button\n id={fieldTriggerId}\n aria-controls={fieldListboxId}\n variant=\"outline\"\n className=\"h-8 w-44 justify-between rounded font-normal\"\n >\n <span className=\"truncate\">{columnLabels.get(sort.id)}</span>\n <ChevronsUpDown aria-hidden=\"true\" className=\"opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent id={fieldListboxId} dir={dir} className=\"w-[--radix-popover-trigger-width] p-0\">\n <Command>\n <CommandInput placeholder={msg.sort.fieldPlaceholder} aria-label={msg.sort.fieldPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.sort.fieldEmpty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => (\n <CommandItem\n key={column.id}\n value={column.id}\n onSelect={(value) => onSortUpdate(sort.id, { id: value })}\n >\n <span className=\"truncate\">{column.label}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <Select\n open={showDirectionSelector}\n onOpenChange={setShowDirectionSelector}\n value={sort.desc ? \"desc\" : \"asc\"}\n onValueChange={(value: SortDirection) => onSortUpdate(sort.id, { desc: value === \"desc\" })}\n >\n <SelectTrigger aria-controls={directionListboxId} aria-label={msg.sort.title} className=\"h-8 w-28 rounded\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent id={directionListboxId} className=\"min-w-[--radix-select-trigger-width]\">\n <SelectGroup>\n {sortOrders.map((order) => (\n <SelectItem key={order.value} value={order.value}>\n {order.label}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n <Button\n aria-controls={sortItemId}\n aria-label={msg.sort.remove}\n variant=\"outline\"\n size=\"icon\"\n className=\"size-8 shrink-0 rounded\"\n onClick={() => onSortRemove(sort.id)}\n >\n <Trash2 aria-hidden=\"true\" className=\"size-3.5\" />\n </Button>\n <SortableItemHandle asChild>\n <Button aria-label={msg.sort.drag} variant=\"outline\" size=\"icon\" className=\"size-8 shrink-0 rounded\">\n <GripVertical aria-hidden=\"true\" className=\"size-3.5\" />\n </Button>\n </SortableItemHandle>\n </div>\n </SortableItem>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { Table } from '@tanstack/react-table';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { PopoverContent } from '../components/ui/popover.js';
|
|
4
|
+
import { DataGridLocale } from './messages.js';
|
|
5
|
+
import { DataGridMessages } from './messages-en.js';
|
|
4
6
|
import '@radix-ui/react-popover';
|
|
7
|
+
import './messages-vi.js';
|
|
5
8
|
|
|
6
9
|
interface DataGridViewMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {
|
|
7
10
|
table: Table<TData>;
|
|
8
11
|
disabled?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Ngôn ngữ của menu: `"en"` (mặc định) · `"vi"`, hoặc cả một bảng chuỗi tự soạn.
|
|
14
|
+
*
|
|
15
|
+
* ⚠ Thanh công cụ nằm NGOÀI `<DataGrid>`, nên `locale` truyền cho lưới không với tới đây. Bọc
|
|
16
|
+
* cả màn bằng `DataGridLocaleProvider` (một lần, đúng cho mọi mảnh), hoặc truyền prop này cho
|
|
17
|
+
* từng menu. Prop thắng provider.
|
|
18
|
+
*/
|
|
19
|
+
locale?: DataGridLocale | DataGridMessages;
|
|
9
20
|
}
|
|
10
21
|
/** Ẩn/hiện cột của lưới. Cột muốn khoá luôn hiển thị thì đặt `enableHiding: false`. */
|
|
11
|
-
declare function DataGridViewMenu<TData>({ table, disabled, className, ...props }: DataGridViewMenuProps<TData>): React.JSX.Element;
|
|
22
|
+
declare function DataGridViewMenu<TData>({ table, disabled, className, locale, ...props }: DataGridViewMenuProps<TData>): React.JSX.Element;
|
|
12
23
|
|
|
13
24
|
export { DataGridViewMenu };
|
|
@@ -14,8 +14,15 @@ import {
|
|
|
14
14
|
} from "../components/ui/command.js";
|
|
15
15
|
import { Popover, PopoverContent, PopoverTrigger } from "../components/ui/popover.js";
|
|
16
16
|
import { cn } from "../lib/cn.js";
|
|
17
|
-
import {
|
|
18
|
-
function DataGridViewMenu({
|
|
17
|
+
import { useResolvedDataGridMessages } from "./data-grid-locale.js";
|
|
18
|
+
function DataGridViewMenu({
|
|
19
|
+
table,
|
|
20
|
+
disabled,
|
|
21
|
+
className,
|
|
22
|
+
locale,
|
|
23
|
+
...props
|
|
24
|
+
}) {
|
|
25
|
+
const msg = useResolvedDataGridMessages(locale);
|
|
19
26
|
const dir = useDirection();
|
|
20
27
|
const columns = React.useMemo(
|
|
21
28
|
() => table.getAllColumns().filter((column) => typeof column.accessorFn !== "undefined" && column.getCanHide()),
|
|
@@ -29,10 +36,11 @@ function DataGridViewMenu({ table, disabled, className, ...props }) {
|
|
|
29
36
|
role: "combobox",
|
|
30
37
|
dir,
|
|
31
38
|
variant: "outline",
|
|
32
|
-
|
|
39
|
+
size: "sm",
|
|
40
|
+
className: "font-normal",
|
|
33
41
|
disabled,
|
|
34
42
|
children: [
|
|
35
|
-
/* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true", className: "text-muted-foreground" }),
|
|
43
|
+
/* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true", className: "size-3.5 text-muted-foreground" }),
|
|
36
44
|
msg.view.trigger
|
|
37
45
|
]
|
|
38
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data-grid/data-grid-view-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { Table } from \"@tanstack/react-table\";\nimport { Check, Settings2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { cn } from \"../lib/cn.js\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/data-grid-view-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { Table } from \"@tanstack/react-table\";\nimport { Check, Settings2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { useResolvedDataGridMessages } from \"./data-grid-locale.js\";\nimport type { DataGridLocale, DataGridMessages } from \"./messages.js\";\n\ninterface DataGridViewMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n /**\n * Ngôn ngữ của menu: `\"en\"` (mặc định) · `\"vi\"`, hoặc cả một bảng chuỗi tự soạn.\n *\n * ⚠ Thanh công cụ nằm NGOÀI `<DataGrid>`, nên `locale` truyền cho lưới không với tới đây. Bọc\n * cả màn bằng `DataGridLocaleProvider` (một lần, đúng cho mọi mảnh), hoặc truyền prop này cho\n * từng menu. Prop thắng provider.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\n/** Ẩn/hiện cột của lưới. Cột muốn khoá luôn hiển thị thì đặt `enableHiding: false`. */\nexport function DataGridViewMenu<TData>({\n table,\n disabled,\n className,\n locale,\n ...props\n}: DataGridViewMenuProps<TData>) {\n const msg = useResolvedDataGridMessages(locale);\n const dir = useDirection();\n\n const columns = React.useMemo(\n () => table.getAllColumns().filter((column) => typeof column.accessorFn !== \"undefined\" && column.getCanHide()),\n [table]\n );\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n aria-label={msg.view.toggleColumns}\n role=\"combobox\"\n dir={dir}\n variant=\"outline\"\n size=\"sm\"\n className=\"font-normal\"\n disabled={disabled}\n >\n <Settings2 aria-hidden=\"true\" className=\"size-3.5 text-muted-foreground\" />\n {msg.view.trigger}\n </Button>\n </PopoverTrigger>\n <PopoverContent dir={dir} align=\"end\" className={cn(\"w-52 p-0\", className)} {...props}>\n <Command>\n <CommandInput placeholder={msg.view.searchPlaceholder} aria-label={msg.view.searchPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.view.empty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => {\n const isVisible = column.getIsVisible();\n\n return (\n <CommandItem\n key={column.id}\n value={column.columnDef.meta?.label ?? column.id}\n onSelect={() => column.toggleVisibility(!isVisible)}\n >\n <span className=\"truncate\">{column.columnDef.meta?.label ?? column.id}</span>\n <Check className={cn(\"ms-auto size-4\", isVisible ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":";AAoDQ,SASE,KATF;AAlDR,SAAS,oBAAoB;AAE7B,SAAS,OAAO,iBAAiB;AACjC,YAAY,WAAW;AACvB,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AACnB,SAAS,mCAAmC;AAiBrC,SAAS,iBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiC;AAC/B,QAAM,MAAM,4BAA4B,MAAM;AAC9C,QAAM,MAAM,aAAa;AAEzB,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM,MAAM,cAAc,EAAE,OAAO,CAAC,WAAW,OAAO,OAAO,eAAe,eAAe,OAAO,WAAW,CAAC;AAAA,IAC9G,CAAC,KAAK;AAAA,EACR;AAEA,SACE,qBAAC,WACC;AAAA,wBAAC,kBAAe,SAAO,MACrB;AAAA,MAAC;AAAA;AAAA,QACC,cAAY,IAAI,KAAK;AAAA,QACrB,MAAK;AAAA,QACL;AAAA,QACA,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QACV;AAAA,QAEA;AAAA,8BAAC,aAAU,eAAY,QAAO,WAAU,kCAAiC;AAAA,UACxE,IAAI,KAAK;AAAA;AAAA;AAAA,IACZ,GACF;AAAA,IACA,oBAAC,kBAAe,KAAU,OAAM,OAAM,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,OAC9E,+BAAC,WACC;AAAA,0BAAC,gBAAa,aAAa,IAAI,KAAK,mBAAmB,cAAY,IAAI,KAAK,mBAAmB;AAAA,MAC/F,qBAAC,eACC;AAAA,4BAAC,gBAAc,cAAI,KAAK,OAAM;AAAA,QAC9B,oBAAC,gBACE,kBAAQ,IAAI,CAAC,WAAW;AACvB,gBAAM,YAAY,OAAO,aAAa;AAEtC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO,OAAO,UAAU,MAAM,SAAS,OAAO;AAAA,cAC9C,UAAU,MAAM,OAAO,iBAAiB,CAAC,SAAS;AAAA,cAElD;AAAA,oCAAC,UAAK,WAAU,YAAY,iBAAO,UAAU,MAAM,SAAS,OAAO,IAAG;AAAA,gBACtE,oBAAC,SAAM,WAAW,GAAG,kBAAkB,YAAY,gBAAgB,WAAW,GAAG;AAAA;AAAA;AAAA,YAL5E,OAAO;AAAA,UAMd;AAAA,QAEJ,CAAC,GACH;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { DataGridLocale } from './messages.js';
|
|
2
3
|
import { Direction } from './types.js';
|
|
3
4
|
import { useDataGrid } from './use-data-grid.js';
|
|
5
|
+
import { DataGridMessages } from './messages-en.js';
|
|
6
|
+
import './messages-vi.js';
|
|
4
7
|
import '@tanstack/react-table';
|
|
5
8
|
import '@tanstack/react-virtual';
|
|
6
9
|
|
|
7
|
-
interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>>, "dir">, Omit<React.ComponentProps<"div">, "contextMenu"> {
|
|
10
|
+
interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>>, "dir" | "locale">, Omit<React.ComponentProps<"div">, "contextMenu"> {
|
|
8
11
|
dir?: Direction;
|
|
9
12
|
/**
|
|
10
13
|
* Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ
|
|
@@ -13,6 +16,15 @@ interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>
|
|
|
13
16
|
height?: number | string;
|
|
14
17
|
/** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */
|
|
15
18
|
stretchColumns?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Ngôn ngữ của lưới: `"en"` (mặc định) · `"vi"`, hoặc cả một bảng chuỗi tự soạn.
|
|
21
|
+
*
|
|
22
|
+
* Thường nó đi theo kết quả của {@link useDataGrid} nên không phải truyền lại ở đây. Giá trị
|
|
23
|
+
* đặt thẳng lên `<DataGrid>` THẮNG giá trị từ hook — hữu ích khi một màn có hai lưới khác ngôn
|
|
24
|
+
* ngữ. Thanh công cụ nằm ngoài lưới nên nó KHÔNG nhận được giá trị này: bọc cả màn bằng
|
|
25
|
+
* `DataGridLocaleProvider`, hoặc truyền `locale` cho từng menu.
|
|
26
|
+
*/
|
|
27
|
+
locale?: DataGridLocale | DataGridMessages;
|
|
16
28
|
}
|
|
17
29
|
/**
|
|
18
30
|
* Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,
|
|
@@ -27,6 +39,6 @@ interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>
|
|
|
27
39
|
* `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang
|
|
28
40
|
* `role="grid"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).
|
|
29
41
|
*/
|
|
30
|
-
declare function DataGrid<TData>({ dataGridRef, headerRef, rowMapRef, footerRef, dir, table, tableMeta, virtualTotalSize, virtualItems, measureElement, columns, columnSizeVars, searchState, searchMatchesByRow, activeSearchMatch, cellSelectionMap, focusedCell, editingCell, rowHeight, contextMenu, pasteDialog, onRowAdd: onRowAddProp, height, stretchColumns, adjustLayout, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...props }: DataGridProps<TData>): React.JSX.Element;
|
|
42
|
+
declare function DataGrid<TData>({ dataGridRef, headerRef, rowMapRef, footerRef, dir, table, tableMeta, virtualTotalSize, virtualItems, measureElement, columns, columnSizeVars, searchState, searchMatchesByRow, activeSearchMatch, cellSelectionMap, focusedCell, editingCell, rowHeight, contextMenu, pasteDialog, onRowAdd: onRowAddProp, height, stretchColumns, locale, adjustLayout, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...props }: DataGridProps<TData>): React.JSX.Element;
|
|
31
43
|
|
|
32
44
|
export { DataGrid };
|
|
@@ -6,10 +6,11 @@ import { TooltipProvider } from "../components/ui/tooltip.js";
|
|
|
6
6
|
import { cn } from "../lib/cn.js";
|
|
7
7
|
import { DataGridColumnHeader } from "./data-grid-column-header.js";
|
|
8
8
|
import { DataGridContextMenu } from "./data-grid-context-menu.js";
|
|
9
|
+
import { DataGridLocaleProvider } from "./data-grid-locale.js";
|
|
9
10
|
import { DataGridPasteDialog } from "./data-grid-paste-dialog.js";
|
|
10
11
|
import { DataGridRow } from "./data-grid-row.js";
|
|
11
12
|
import { DataGridSearch } from "./data-grid-search.js";
|
|
12
|
-
import {
|
|
13
|
+
import { getDataGridMessages } from "./messages.js";
|
|
13
14
|
import { useAsRef } from "./use-as-ref.js";
|
|
14
15
|
import { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from "./utils.js";
|
|
15
16
|
const EMPTY_CELL_SELECTION_SET = /* @__PURE__ */ new Set();
|
|
@@ -38,6 +39,7 @@ function DataGrid({
|
|
|
38
39
|
onRowAdd: onRowAddProp,
|
|
39
40
|
height = 600,
|
|
40
41
|
stretchColumns = false,
|
|
42
|
+
locale,
|
|
41
43
|
adjustLayout = false,
|
|
42
44
|
className,
|
|
43
45
|
"aria-label": ariaLabel,
|
|
@@ -69,7 +71,8 @@ function DataGrid({
|
|
|
69
71
|
},
|
|
70
72
|
[onRowAddRef]
|
|
71
73
|
);
|
|
72
|
-
|
|
74
|
+
const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);
|
|
75
|
+
return /* @__PURE__ */ jsx(DataGridLocaleProvider, { locale, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs("div", { "data-slot": "grid-wrapper", dir, ...props, className: cn("relative flex w-full flex-col", className), children: [
|
|
73
76
|
searchState && /* @__PURE__ */ jsx(DataGridSearch, { ...searchState }),
|
|
74
77
|
/* @__PURE__ */ jsx(DataGridContextMenu, { tableMeta, columns, contextMenu }),
|
|
75
78
|
/* @__PURE__ */ jsx(DataGridPasteDialog, { tableMeta, pasteDialog }),
|
|
@@ -227,7 +230,7 @@ function DataGrid({
|
|
|
227
230
|
]
|
|
228
231
|
}
|
|
229
232
|
)
|
|
230
|
-
] }) });
|
|
233
|
+
] }) }) });
|
|
231
234
|
}
|
|
232
235
|
export {
|
|
233
236
|
DataGrid
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data-grid/data-grid.tsx"],"sourcesContent":["\"use client\";\n\nimport { Plus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { DataGridColumnHeader } from \"./data-grid-column-header.js\";\nimport { DataGridContextMenu } from \"./data-grid-context-menu.js\";\nimport { DataGridPasteDialog } from \"./data-grid-paste-dialog.js\";\nimport { DataGridRow } from \"./data-grid-row.js\";\nimport { DataGridSearch } from \"./data-grid-search.js\";\nimport { msg } from \"./messages.js\";\nimport type { Direction } from \"./types.js\";\nimport { useAsRef } from \"./use-as-ref.js\";\nimport type { useDataGrid } from \"./use-data-grid.js\";\nimport { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from \"./utils.js\";\n\nconst EMPTY_CELL_SELECTION_SET = new Set<string>();\n\ninterface DataGridProps<TData>\n extends Omit<ReturnType<typeof useDataGrid<TData>>, \"dir\">,\n Omit<React.ComponentProps<\"div\">, \"contextMenu\"> {\n dir?: Direction;\n /**\n * Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ\n * (vd `\"100%\"`, `\"calc(100dvh - 220px)\"` khi muốn lưới lấp đầy phần còn lại của trang).\n */\n height?: number | string;\n /** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */\n stretchColumns?: boolean;\n}\n\n/**\n * Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,\n * chọn vùng ô, sao chép/cắt/dán, ghim cột, đổi rộng cột.\n *\n * Nhận nguyên kết quả của {@link useDataGrid}:\n * ```tsx\n * const { table, ...dataGridProps } = useDataGrid({ data, columns, onDataChange });\n * <DataGrid {...dataGridProps} table={table} aria-label=\"Danh sách bệnh nhân\" />\n * ```\n *\n * `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang\n * `role=\"grid\"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).\n */\nexport function DataGrid<TData>({\n dataGridRef,\n headerRef,\n rowMapRef,\n footerRef,\n dir = \"ltr\",\n table,\n tableMeta,\n virtualTotalSize,\n virtualItems,\n measureElement,\n columns,\n columnSizeVars,\n searchState,\n searchMatchesByRow,\n activeSearchMatch,\n cellSelectionMap,\n focusedCell,\n editingCell,\n rowHeight,\n contextMenu,\n pasteDialog,\n onRowAdd: onRowAddProp,\n height = 600,\n stretchColumns = false,\n adjustLayout = false,\n className,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: DataGridProps<TData>) {\n const rows = table.getRowModel().rows;\n const readOnly = tableMeta?.readOnly ?? false;\n const columnVisibility = table.getState().columnVisibility;\n const columnPinning = table.getState().columnPinning;\n\n const onRowAddRef = useAsRef(onRowAddProp);\n\n const onRowAdd = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onRowAddRef.current?.(event);\n },\n [onRowAddRef]\n );\n\n const onDataGridContextMenu = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n event.preventDefault();\n }, []);\n\n const onFooterCellKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onRowAddRef.current) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowAddRef.current();\n }\n },\n [onRowAddRef]\n );\n\n return (\n <TooltipProvider delayDuration={200}>\n <div data-slot=\"grid-wrapper\" dir={dir} {...props} className={cn(\"relative flex w-full flex-col\", className)}>\n {searchState && <DataGridSearch {...searchState} />}\n <DataGridContextMenu tableMeta={tableMeta} columns={columns} contextMenu={contextMenu} />\n <DataGridPasteDialog tableMeta={tableMeta} pasteDialog={pasteDialog} />\n <div\n role=\"grid\"\n aria-label={ariaLabelledby ? undefined : (ariaLabel ?? msg.grid.label)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-rowcount={rows.length + (onRowAddProp ? 1 : 0)}\n aria-colcount={columns.length}\n data-slot=\"grid\"\n tabIndex={0}\n ref={dataGridRef}\n className=\"relative grid select-none overflow-auto rounded-lg border bg-card focus:outline-none focus-visible:outline-none\"\n style={{\n ...columnSizeVars,\n maxHeight: typeof height === \"number\" ? `${height}px` : height\n }}\n onContextMenu={onDataGridContextMenu}\n >\n <div\n role=\"rowgroup\"\n data-slot=\"grid-header\"\n ref={headerRef}\n className=\"sticky top-0 z-10 grid border-b bg-card\"\n >\n {table.getHeaderGroups().map((headerGroup, rowIndex) => (\n <div\n key={headerGroup.id}\n role=\"row\"\n aria-rowindex={rowIndex + 1}\n data-slot=\"grid-header-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n {headerGroup.headers.map((header, colIndex) => {\n const sorting = table.getState().sorting;\n const currentSort = sorting.find((sort) => sort.id === header.column.id);\n const isSortable = header.column.getCanSort();\n\n const nextHeader = headerGroup.headers[colIndex + 1];\n const isLastColumn = colIndex === headerGroup.headers.length - 1;\n\n const { showEndBorder, showStartBorder } = getColumnBorderVisibility({\n column: header.column,\n nextColumn: nextHeader?.column,\n isLastColumn\n });\n\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n aria-colindex={colIndex + 1}\n aria-sort={\n currentSort?.desc === false\n ? \"ascending\"\n : currentSort?.desc === true\n ? \"descending\"\n : isSortable\n ? \"none\"\n : undefined\n }\n data-slot=\"grid-header-cell\"\n tabIndex={-1}\n className={cn(\"relative\", {\n grow: stretchColumns && header.column.id !== \"select\",\n \"border-e\": showEndBorder && header.column.id !== \"select\",\n \"border-s\": showStartBorder && header.column.id !== \"select\"\n })}\n style={{\n ...getColumnPinningStyle({ column: header.column, dir }),\n width: `calc(var(--header-${header.id}-size) * 1px)`\n }}\n >\n {header.isPlaceholder ? null : typeof header.column.columnDef.header === \"function\" ? (\n <div className=\"size-full px-3 py-1.5\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n </div>\n ) : (\n <DataGridColumnHeader header={header} table={table} />\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div\n role=\"rowgroup\"\n data-slot=\"grid-body\"\n className=\"relative grid\"\n style={{\n height: `${virtualTotalSize}px`,\n contain: adjustLayout ? \"layout paint\" : \"strict\"\n }}\n >\n {virtualItems.map((virtualItem) => {\n const row = rows[virtualItem.index];\n if (!row) return null;\n\n const cellSelectionKeys = cellSelectionMap?.get(virtualItem.index) ?? EMPTY_CELL_SELECTION_SET;\n\n const searchMatchColumns = searchMatchesByRow?.get(virtualItem.index) ?? null;\n const isActiveSearchRow = activeSearchMatch?.rowIndex === virtualItem.index;\n\n return (\n <DataGridRow\n key={row.id}\n row={row}\n tableMeta={tableMeta}\n rowMapRef={rowMapRef}\n virtualItem={virtualItem}\n measureElement={measureElement}\n rowHeight={rowHeight}\n columnVisibility={columnVisibility}\n columnPinning={columnPinning}\n focusedCell={focusedCell}\n editingCell={editingCell}\n cellSelectionKeys={cellSelectionKeys}\n searchMatchColumns={searchMatchColumns}\n activeSearchMatch={isActiveSearchRow ? activeSearchMatch : null}\n dir={dir}\n adjustLayout={adjustLayout}\n stretchColumns={stretchColumns}\n readOnly={readOnly}\n />\n );\n })}\n </div>\n {/* Chỉ hiện dòng \"Thêm dòng\" khi ứng dụng thật sự truyền onRowAdd\n (biến `onRowAdd` bên dưới là callback bọc, luôn khác undefined). */}\n {!readOnly && onRowAddProp && (\n <div\n role=\"rowgroup\"\n data-slot=\"grid-footer\"\n ref={footerRef}\n className=\"sticky bottom-0 z-10 grid border-t bg-card\"\n >\n <div\n role=\"row\"\n aria-rowindex={rows.length + 2}\n data-slot=\"grid-add-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n <div\n role=\"gridcell\"\n tabIndex={0}\n className=\"relative flex h-9 grow items-center bg-muted/30 transition-colors hover:bg-muted/50 focus:bg-muted/50 focus:outline-none focus-visible:outline-none\"\n style={{\n width: table.getTotalSize(),\n minWidth: table.getTotalSize()\n }}\n onClick={onRowAdd}\n onKeyDown={onFooterCellKeyDown}\n >\n <div className=\"sticky start-0 flex items-center gap-2 px-3 text-muted-foreground\">\n <Plus className=\"size-3.5\" />\n <span className=\"text-sm\">{msg.grid.addRow}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </TooltipProvider>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/data-grid.tsx"],"sourcesContent":["\"use client\";\n\nimport { Plus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { DataGridColumnHeader } from \"./data-grid-column-header.js\";\nimport { DataGridContextMenu } from \"./data-grid-context-menu.js\";\nimport { DataGridLocaleProvider } from \"./data-grid-locale.js\";\nimport { DataGridPasteDialog } from \"./data-grid-paste-dialog.js\";\nimport { DataGridRow } from \"./data-grid-row.js\";\nimport { DataGridSearch } from \"./data-grid-search.js\";\nimport { type DataGridLocale, type DataGridMessages, getDataGridMessages } from \"./messages.js\";\nimport type { Direction } from \"./types.js\";\nimport { useAsRef } from \"./use-as-ref.js\";\nimport type { useDataGrid } from \"./use-data-grid.js\";\nimport { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from \"./utils.js\";\n\nconst EMPTY_CELL_SELECTION_SET = new Set<string>();\n\ninterface DataGridProps<TData>\n extends Omit<ReturnType<typeof useDataGrid<TData>>, \"dir\" | \"locale\">,\n Omit<React.ComponentProps<\"div\">, \"contextMenu\"> {\n dir?: Direction;\n /**\n * Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ\n * (vd `\"100%\"`, `\"calc(100dvh - 220px)\"` khi muốn lưới lấp đầy phần còn lại của trang).\n */\n height?: number | string;\n /** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */\n stretchColumns?: boolean;\n /**\n * Ngôn ngữ của lưới: `\"en\"` (mặc định) · `\"vi\"`, hoặc cả một bảng chuỗi tự soạn.\n *\n * Thường nó đi theo kết quả của {@link useDataGrid} nên không phải truyền lại ở đây. Giá trị\n * đặt thẳng lên `<DataGrid>` THẮNG giá trị từ hook — hữu ích khi một màn có hai lưới khác ngôn\n * ngữ. Thanh công cụ nằm ngoài lưới nên nó KHÔNG nhận được giá trị này: bọc cả màn bằng\n * `DataGridLocaleProvider`, hoặc truyền `locale` cho từng menu.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\n/**\n * Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,\n * chọn vùng ô, sao chép/cắt/dán, ghim cột, đổi rộng cột.\n *\n * Nhận nguyên kết quả của {@link useDataGrid}:\n * ```tsx\n * const { table, ...dataGridProps } = useDataGrid({ data, columns, onDataChange });\n * <DataGrid {...dataGridProps} table={table} aria-label=\"Danh sách bệnh nhân\" />\n * ```\n *\n * `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang\n * `role=\"grid\"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).\n */\nexport function DataGrid<TData>({\n dataGridRef,\n headerRef,\n rowMapRef,\n footerRef,\n dir = \"ltr\",\n table,\n tableMeta,\n virtualTotalSize,\n virtualItems,\n measureElement,\n columns,\n columnSizeVars,\n searchState,\n searchMatchesByRow,\n activeSearchMatch,\n cellSelectionMap,\n focusedCell,\n editingCell,\n rowHeight,\n contextMenu,\n pasteDialog,\n onRowAdd: onRowAddProp,\n height = 600,\n stretchColumns = false,\n locale,\n adjustLayout = false,\n className,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: DataGridProps<TData>) {\n const rows = table.getRowModel().rows;\n const readOnly = tableMeta?.readOnly ?? false;\n const columnVisibility = table.getState().columnVisibility;\n const columnPinning = table.getState().columnPinning;\n\n const onRowAddRef = useAsRef(onRowAddProp);\n\n const onRowAdd = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onRowAddRef.current?.(event);\n },\n [onRowAddRef]\n );\n\n const onDataGridContextMenu = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n event.preventDefault();\n }, []);\n\n const onFooterCellKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onRowAddRef.current) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowAddRef.current();\n }\n },\n [onRowAddRef]\n );\n\n const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);\n\n return (\n <DataGridLocaleProvider locale={locale}>\n <TooltipProvider delayDuration={200}>\n <div data-slot=\"grid-wrapper\" dir={dir} {...props} className={cn(\"relative flex w-full flex-col\", className)}>\n {searchState && <DataGridSearch {...searchState} />}\n <DataGridContextMenu tableMeta={tableMeta} columns={columns} contextMenu={contextMenu} />\n <DataGridPasteDialog tableMeta={tableMeta} pasteDialog={pasteDialog} />\n <div\n role=\"grid\"\n aria-label={ariaLabelledby ? undefined : (ariaLabel ?? msg.grid.label)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-rowcount={rows.length + (onRowAddProp ? 1 : 0)}\n aria-colcount={columns.length}\n data-slot=\"grid\"\n tabIndex={0}\n ref={dataGridRef}\n className=\"relative grid select-none overflow-auto rounded-lg border bg-card focus:outline-none focus-visible:outline-none\"\n style={{\n ...columnSizeVars,\n maxHeight: typeof height === \"number\" ? `${height}px` : height\n }}\n onContextMenu={onDataGridContextMenu}\n >\n <div\n role=\"rowgroup\"\n data-slot=\"grid-header\"\n ref={headerRef}\n className=\"sticky top-0 z-10 grid border-b bg-card\"\n >\n {table.getHeaderGroups().map((headerGroup, rowIndex) => (\n <div\n key={headerGroup.id}\n role=\"row\"\n aria-rowindex={rowIndex + 1}\n data-slot=\"grid-header-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n {headerGroup.headers.map((header, colIndex) => {\n const sorting = table.getState().sorting;\n const currentSort = sorting.find((sort) => sort.id === header.column.id);\n const isSortable = header.column.getCanSort();\n\n const nextHeader = headerGroup.headers[colIndex + 1];\n const isLastColumn = colIndex === headerGroup.headers.length - 1;\n\n const { showEndBorder, showStartBorder } = getColumnBorderVisibility({\n column: header.column,\n nextColumn: nextHeader?.column,\n isLastColumn\n });\n\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n aria-colindex={colIndex + 1}\n aria-sort={\n currentSort?.desc === false\n ? \"ascending\"\n : currentSort?.desc === true\n ? \"descending\"\n : isSortable\n ? \"none\"\n : undefined\n }\n data-slot=\"grid-header-cell\"\n tabIndex={-1}\n className={cn(\"relative\", {\n grow: stretchColumns && header.column.id !== \"select\",\n \"border-e\": showEndBorder && header.column.id !== \"select\",\n \"border-s\": showStartBorder && header.column.id !== \"select\"\n })}\n style={{\n ...getColumnPinningStyle({ column: header.column, dir }),\n width: `calc(var(--header-${header.id}-size) * 1px)`\n }}\n >\n {header.isPlaceholder ? null : typeof header.column.columnDef.header === \"function\" ? (\n <div className=\"size-full px-3 py-1.5\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n </div>\n ) : (\n <DataGridColumnHeader header={header} table={table} />\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div\n role=\"rowgroup\"\n data-slot=\"grid-body\"\n className=\"relative grid\"\n style={{\n height: `${virtualTotalSize}px`,\n contain: adjustLayout ? \"layout paint\" : \"strict\"\n }}\n >\n {virtualItems.map((virtualItem) => {\n const row = rows[virtualItem.index];\n if (!row) return null;\n\n const cellSelectionKeys = cellSelectionMap?.get(virtualItem.index) ?? EMPTY_CELL_SELECTION_SET;\n\n const searchMatchColumns = searchMatchesByRow?.get(virtualItem.index) ?? null;\n const isActiveSearchRow = activeSearchMatch?.rowIndex === virtualItem.index;\n\n return (\n <DataGridRow\n key={row.id}\n row={row}\n tableMeta={tableMeta}\n rowMapRef={rowMapRef}\n virtualItem={virtualItem}\n measureElement={measureElement}\n rowHeight={rowHeight}\n columnVisibility={columnVisibility}\n columnPinning={columnPinning}\n focusedCell={focusedCell}\n editingCell={editingCell}\n cellSelectionKeys={cellSelectionKeys}\n searchMatchColumns={searchMatchColumns}\n activeSearchMatch={isActiveSearchRow ? activeSearchMatch : null}\n dir={dir}\n adjustLayout={adjustLayout}\n stretchColumns={stretchColumns}\n readOnly={readOnly}\n />\n );\n })}\n </div>\n {/* Chỉ hiện dòng \"Thêm dòng\" khi ứng dụng thật sự truyền onRowAdd\n (biến `onRowAdd` bên dưới là callback bọc, luôn khác undefined). */}\n {!readOnly && onRowAddProp && (\n <div\n role=\"rowgroup\"\n data-slot=\"grid-footer\"\n ref={footerRef}\n className=\"sticky bottom-0 z-10 grid border-t bg-card\"\n >\n <div\n role=\"row\"\n aria-rowindex={rows.length + 2}\n data-slot=\"grid-add-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n <div\n role=\"gridcell\"\n tabIndex={0}\n className=\"relative flex h-9 grow items-center bg-muted/30 transition-colors hover:bg-muted/50 focus:bg-muted/50 focus:outline-none focus-visible:outline-none\"\n style={{\n width: table.getTotalSize(),\n minWidth: table.getTotalSize()\n }}\n onClick={onRowAdd}\n onKeyDown={onFooterCellKeyDown}\n >\n <div className=\"sticky start-0 flex items-center gap-2 px-3 text-muted-foreground\">\n <Plus className=\"size-3.5\" />\n <span className=\"text-sm\">{msg.grid.addRow}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </TooltipProvider>\n </DataGridLocaleProvider>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import { FilterFn } from '@tanstack/react-table';
|
|
2
|
-
import {
|
|
2
|
+
import { DataGridMessages } from './messages-en.js';
|
|
3
|
+
import { FilterOperator, BooleanFilterOperator, DateFilterOperator, NumberFilterOperator, SelectFilterOperator, TextFilterOperator } from './types.js';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
interface OperatorOption<TOperator extends FilterOperator> {
|
|
5
6
|
label: string;
|
|
6
|
-
value:
|
|
7
|
-
}
|
|
8
|
-
declare const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
declare const
|
|
13
|
-
label: string;
|
|
14
|
-
value: DateFilterOperator;
|
|
15
|
-
}>;
|
|
16
|
-
declare const SELECT_FILTER_OPERATORS: ReadonlyArray<{
|
|
17
|
-
label: string;
|
|
18
|
-
value: SelectFilterOperator;
|
|
19
|
-
}>;
|
|
20
|
-
declare const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<{
|
|
21
|
-
label: string;
|
|
22
|
-
value: BooleanFilterOperator;
|
|
23
|
-
}>;
|
|
7
|
+
value: TOperator;
|
|
8
|
+
}
|
|
9
|
+
declare const TEXT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<TextFilterOperator>>;
|
|
10
|
+
declare const NUMBER_FILTER_OPERATORS: ReadonlyArray<OperatorOption<NumberFilterOperator>>;
|
|
11
|
+
declare const DATE_FILTER_OPERATORS: ReadonlyArray<OperatorOption<DateFilterOperator>>;
|
|
12
|
+
declare const SELECT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<SelectFilterOperator>>;
|
|
13
|
+
declare const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<OperatorOption<BooleanFilterOperator>>;
|
|
24
14
|
declare function getDefaultOperator(variant: string): FilterOperator;
|
|
25
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Toán tử hợp lệ cho một kiểu ô, kèm nhãn đã dịch.
|
|
17
|
+
*
|
|
18
|
+
* `messages` bỏ trống = bảng mặc định (tiếng Anh) — giữ đúng chữ ký của `1.11.0` nên chỗ gọi cũ
|
|
19
|
+
* không phải sửa.
|
|
20
|
+
*/
|
|
21
|
+
declare function getOperatorsForVariant(variant: string, messages?: DataGridMessages): ReadonlyArray<{
|
|
26
22
|
label: string;
|
|
27
23
|
value: FilterOperator;
|
|
28
24
|
}>;
|