@comitor/ui 1.10.0 → 1.11.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 +15 -4
- package/dist/data-grid/compose-refs.d.ts +19 -0
- package/dist/data-grid/compose-refs.js +41 -0
- package/dist/data-grid/compose-refs.js.map +1 -0
- package/dist/data-grid/data-grid-cell-variants.d.ts +15 -0
- package/dist/data-grid/data-grid-cell-variants.js +1734 -0
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -0
- package/dist/data-grid/data-grid-cell-wrapper.d.ts +9 -0
- package/dist/data-grid/data-grid-cell-wrapper.js +179 -0
- package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -0
- package/dist/data-grid/data-grid-cell.d.ts +8 -0
- package/dist/data-grid/data-grid-cell.js +101 -0
- package/dist/data-grid/data-grid-cell.js.map +1 -0
- package/dist/data-grid/data-grid-column-header.d.ts +12 -0
- package/dist/data-grid/data-grid-column-header.js +205 -0
- package/dist/data-grid/data-grid-column-header.js.map +1 -0
- package/dist/data-grid/data-grid-context-menu.d.ts +12 -0
- package/dist/data-grid/data-grid-context-menu.js +160 -0
- package/dist/data-grid/data-grid-context-menu.js.map +1 -0
- package/dist/data-grid/data-grid-filter-menu.d.ts +12 -0
- package/dist/data-grid/data-grid-filter-menu.js +714 -0
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +20 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.js +227 -0
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -0
- package/dist/data-grid/data-grid-paste-dialog.d.ts +11 -0
- package/dist/data-grid/data-grid-paste-dialog.js +103 -0
- package/dist/data-grid/data-grid-paste-dialog.js.map +1 -0
- package/dist/data-grid/data-grid-presence.d.ts +14 -0
- package/dist/data-grid/data-grid-presence.js +16 -0
- package/dist/data-grid/data-grid-presence.js.map +1 -0
- package/dist/data-grid/data-grid-row-height-menu.d.ts +15 -0
- package/dist/data-grid/data-grid-row-height-menu.js +56 -0
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -0
- package/dist/data-grid/data-grid-row.d.ts +28 -0
- package/dist/data-grid/data-grid-row.js +206 -0
- package/dist/data-grid/data-grid-row.js.map +1 -0
- package/dist/data-grid/data-grid-search.d.ts +10 -0
- package/dist/data-grid/data-grid-search.js +183 -0
- package/dist/data-grid/data-grid-search.js.map +1 -0
- package/dist/data-grid/data-grid-select-column.d.ts +12 -0
- package/dist/data-grid/data-grid-select-column.js +177 -0
- package/dist/data-grid/data-grid-select-column.js.map +1 -0
- package/dist/data-grid/data-grid-skeleton.d.ts +13 -0
- package/dist/data-grid/data-grid-skeleton.js +52 -0
- package/dist/data-grid/data-grid-skeleton.js.map +1 -0
- package/dist/data-grid/data-grid-sort-menu.d.ts +12 -0
- package/dist/data-grid/data-grid-sort-menu.js +271 -0
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -0
- package/dist/data-grid/data-grid-view-menu.d.ts +13 -0
- package/dist/data-grid/data-grid-view-menu.js +66 -0
- package/dist/data-grid/data-grid-view-menu.js.map +1 -0
- package/dist/data-grid/data-grid.d.ts +32 -0
- package/dist/data-grid/data-grid.js +235 -0
- package/dist/data-grid/data-grid.js.map +1 -0
- package/dist/data-grid/filters.d.ts +31 -0
- package/dist/data-grid/filters.js +212 -0
- package/dist/data-grid/filters.js.map +1 -0
- package/dist/data-grid/index.d.ts +22 -0
- package/dist/data-grid/index.js +77 -0
- package/dist/data-grid/index.js.map +1 -0
- package/dist/data-grid/messages.d.ts +280 -0
- package/dist/data-grid/messages.js +279 -0
- package/dist/data-grid/messages.js.map +1 -0
- package/dist/data-grid/sortable.d.ts +50 -0
- package/dist/data-grid/sortable.js +361 -0
- package/dist/data-grid/sortable.js.map +1 -0
- package/dist/data-grid/toast.d.ts +10 -0
- package/dist/data-grid/toast.js +21 -0
- package/dist/data-grid/toast.js.map +1 -0
- package/dist/data-grid/types.d.ts +189 -0
- package/dist/data-grid/types.js +1 -0
- package/dist/data-grid/types.js.map +1 -0
- package/dist/data-grid/use-as-ref.d.ts +5 -0
- package/dist/data-grid/use-as-ref.js +13 -0
- package/dist/data-grid/use-as-ref.js.map +1 -0
- package/dist/data-grid/use-badge-overflow.d.ts +24 -0
- package/dist/data-grid/use-badge-overflow.js +123 -0
- package/dist/data-grid/use-badge-overflow.js.map +1 -0
- package/dist/data-grid/use-callback-ref.d.ts +10 -0
- package/dist/data-grid/use-callback-ref.js +12 -0
- package/dist/data-grid/use-callback-ref.js.map +1 -0
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +33 -0
- package/dist/data-grid/use-data-grid-undo-redo.js +345 -0
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -0
- package/dist/data-grid/use-data-grid.d.ts +92 -0
- package/dist/data-grid/use-data-grid.js +2692 -0
- package/dist/data-grid/use-data-grid.js.map +1 -0
- package/dist/data-grid/use-debounced-callback.d.ts +6 -0
- package/dist/data-grid/use-debounced-callback.js +19 -0
- package/dist/data-grid/use-debounced-callback.js.map +1 -0
- package/dist/data-grid/use-isomorphic-layout-effect.d.ts +5 -0
- package/dist/data-grid/use-isomorphic-layout-effect.js +6 -0
- package/dist/data-grid/use-isomorphic-layout-effect.js.map +1 -0
- package/dist/data-grid/use-lazy-ref.d.ts +5 -0
- package/dist/data-grid/use-lazy-ref.js +12 -0
- package/dist/data-grid/use-lazy-ref.js.map +1 -0
- package/dist/data-grid/utils.d.ts +73 -0
- package/dist/data-grid/utils.js +408 -0
- package/dist/data-grid/utils.js.map +1 -0
- package/package.json +33 -15
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Checkbox } from "../components/ui/checkbox.js";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { msg } from "./messages.js";
|
|
7
|
+
function DataGridSelectHitbox({ htmlFor, children, size, debug }) {
|
|
8
|
+
return /* @__PURE__ */ jsxs(
|
|
9
|
+
"div",
|
|
10
|
+
{
|
|
11
|
+
className: cn(
|
|
12
|
+
"group relative -my-1.5 h-[calc(100%+0.75rem)] py-1.5",
|
|
13
|
+
size === "default" && "-ms-3 -me-2 ps-3 pe-2",
|
|
14
|
+
size === "sm" && "-ms-3 -me-1.5 ps-3 pe-1.5",
|
|
15
|
+
size === "lg" && "-mx-3 px-3"
|
|
16
|
+
),
|
|
17
|
+
children: [
|
|
18
|
+
children,
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
"label",
|
|
21
|
+
{
|
|
22
|
+
htmlFor,
|
|
23
|
+
className: cn(
|
|
24
|
+
"absolute inset-0 cursor-pointer",
|
|
25
|
+
debug && "border border-destructive-ink border-dashed bg-destructive/20"
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function DataGridSelectCheckbox({
|
|
34
|
+
rowNumber,
|
|
35
|
+
hitboxSize,
|
|
36
|
+
debug,
|
|
37
|
+
checked,
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}) {
|
|
41
|
+
const id = React.useId();
|
|
42
|
+
if (rowNumber !== void 0) {
|
|
43
|
+
return /* @__PURE__ */ jsxs(DataGridSelectHitbox, { htmlFor: id, size: hitboxSize, debug, children: [
|
|
44
|
+
/* @__PURE__ */ jsx(
|
|
45
|
+
"div",
|
|
46
|
+
{
|
|
47
|
+
"aria-hidden": "true",
|
|
48
|
+
className: cn(
|
|
49
|
+
// Ẩn bằng `visibility`, KHÔNG bằng `opacity-0`: số thứ tự là chữ, và cổng
|
|
50
|
+
// `lint:a11y` nhân opacity vào màu chữ nên `opacity-0` đọc ra 1,00:1 — một chỗ
|
|
51
|
+
// "chữ không đọc được" mà cổng không thể biết là cố ý. `invisible` cũng đúng hơn
|
|
52
|
+
// về ngữ nghĩa: nó rút phần tử khỏi cây trợ năng thay vì để nó vẫn được đọc lên.
|
|
53
|
+
"pointer-events-none absolute start-3 top-1.5 flex size-4 items-center justify-center text-muted-foreground text-xs tabular-nums group-hover:invisible",
|
|
54
|
+
checked && "invisible"
|
|
55
|
+
),
|
|
56
|
+
children: rowNumber
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Checkbox,
|
|
61
|
+
{
|
|
62
|
+
id,
|
|
63
|
+
className: cn(
|
|
64
|
+
// Không ghi đè viền hover: `Checkbox` của gói đã đi qua `--choice-edge` /
|
|
65
|
+
// `--choice-edge-strong`. `border-primary/40` vừa sai vai trò (bậc tô NỀN đem vẽ
|
|
66
|
+
// NÉT) vừa chỉ 1,25:1 ở light.
|
|
67
|
+
"relative transition-[shadow,border,opacity]",
|
|
68
|
+
// Ở đây PHẢI là `opacity`, không phải `invisible` như số thứ tự bên trên: đây là
|
|
69
|
+
// checkbox thật, `visibility:hidden` sẽ làm nó mất luôn khả năng nhận Tab.
|
|
70
|
+
"opacity-0 group-hover:opacity-100 data-[state=checked]:opacity-100",
|
|
71
|
+
className
|
|
72
|
+
),
|
|
73
|
+
checked,
|
|
74
|
+
...props
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
] });
|
|
78
|
+
}
|
|
79
|
+
return /* @__PURE__ */ jsx(DataGridSelectHitbox, { htmlFor: id, size: hitboxSize, debug, children: /* @__PURE__ */ jsx(Checkbox, { id, className: cn("relative transition-[shadow,border]", className), checked, ...props }) });
|
|
80
|
+
}
|
|
81
|
+
function DataGridSelectHeader({ table, hitboxSize, readOnly, debug }) {
|
|
82
|
+
const onCheckedChange = React.useCallback((value) => table.toggleAllPageRowsSelected(value), [table]);
|
|
83
|
+
if (readOnly) {
|
|
84
|
+
return /* @__PURE__ */ jsx("div", { className: "mt-1 flex items-center ps-1 text-muted-foreground text-sm", children: "#" });
|
|
85
|
+
}
|
|
86
|
+
return /* @__PURE__ */ jsx(
|
|
87
|
+
DataGridSelectCheckbox,
|
|
88
|
+
{
|
|
89
|
+
"aria-label": msg.select.all,
|
|
90
|
+
checked: table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected() && "indeterminate",
|
|
91
|
+
onCheckedChange,
|
|
92
|
+
hitboxSize,
|
|
93
|
+
debug
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
function DataGridSelectCell({
|
|
98
|
+
row,
|
|
99
|
+
table,
|
|
100
|
+
hitboxSize,
|
|
101
|
+
enableRowMarkers,
|
|
102
|
+
readOnly,
|
|
103
|
+
debug
|
|
104
|
+
}) {
|
|
105
|
+
const meta = table.options.meta;
|
|
106
|
+
const rowNumber = enableRowMarkers ? meta?.getVisualRowIndex?.(row.id) ?? row.index + 1 : void 0;
|
|
107
|
+
const onCheckedChange = React.useCallback(
|
|
108
|
+
(value) => {
|
|
109
|
+
if (meta?.onRowSelect) {
|
|
110
|
+
meta.onRowSelect(row.id, value, false);
|
|
111
|
+
} else {
|
|
112
|
+
row.toggleSelected(value);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
[meta, row]
|
|
116
|
+
);
|
|
117
|
+
const onClick = React.useCallback(
|
|
118
|
+
(event) => {
|
|
119
|
+
if (event.shiftKey) {
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
meta?.onRowSelect?.(row.id, !row.getIsSelected(), true);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
[meta, row]
|
|
125
|
+
);
|
|
126
|
+
if (readOnly) {
|
|
127
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center ps-1 text-muted-foreground text-xs tabular-nums", children: rowNumber ?? row.index + 1 });
|
|
128
|
+
}
|
|
129
|
+
return /* @__PURE__ */ jsx(
|
|
130
|
+
DataGridSelectCheckbox,
|
|
131
|
+
{
|
|
132
|
+
"aria-label": rowNumber ? msg.select.rowNumber(rowNumber) : msg.select.row,
|
|
133
|
+
checked: row.getIsSelected(),
|
|
134
|
+
onCheckedChange,
|
|
135
|
+
onClick,
|
|
136
|
+
rowNumber,
|
|
137
|
+
hitboxSize,
|
|
138
|
+
debug
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function getDataGridSelectColumn({
|
|
143
|
+
size = 40,
|
|
144
|
+
hitboxSize = "default",
|
|
145
|
+
enableHiding = false,
|
|
146
|
+
enableResizing = false,
|
|
147
|
+
enableSorting = false,
|
|
148
|
+
enableRowMarkers = false,
|
|
149
|
+
readOnly = false,
|
|
150
|
+
debug = false,
|
|
151
|
+
...props
|
|
152
|
+
} = {}) {
|
|
153
|
+
return {
|
|
154
|
+
id: "select",
|
|
155
|
+
header: ({ table }) => /* @__PURE__ */ jsx(DataGridSelectHeader, { table, hitboxSize, readOnly, debug }),
|
|
156
|
+
cell: ({ row, table }) => /* @__PURE__ */ jsx(
|
|
157
|
+
DataGridSelectCell,
|
|
158
|
+
{
|
|
159
|
+
row,
|
|
160
|
+
table,
|
|
161
|
+
enableRowMarkers,
|
|
162
|
+
readOnly,
|
|
163
|
+
hitboxSize,
|
|
164
|
+
debug
|
|
165
|
+
}
|
|
166
|
+
),
|
|
167
|
+
size,
|
|
168
|
+
enableHiding,
|
|
169
|
+
enableResizing,
|
|
170
|
+
enableSorting,
|
|
171
|
+
...props
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
getDataGridSelectColumn
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=data-grid-select-column.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/data-grid-select-column.tsx"],"sourcesContent":["\"use client\";\n\nimport type { CellContext, ColumnDef, HeaderContext } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { Checkbox } from \"../components/ui/checkbox.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { msg } from \"./messages.js\";\n\ntype HitboxSize = \"default\" | \"sm\" | \"lg\";\n\ninterface DataGridSelectHitboxProps {\n htmlFor: string;\n children: React.ReactNode;\n size?: HitboxSize;\n debug?: boolean;\n}\n\nfunction DataGridSelectHitbox({ htmlFor, children, size, debug }: DataGridSelectHitboxProps) {\n return (\n <div\n className={cn(\n \"group relative -my-1.5 h-[calc(100%+0.75rem)] py-1.5\",\n size === \"default\" && \"-ms-3 -me-2 ps-3 pe-2\",\n size === \"sm\" && \"-ms-3 -me-1.5 ps-3 pe-1.5\",\n size === \"lg\" && \"-mx-3 px-3\"\n )}\n >\n {children}\n {/* biome-ignore lint/a11y/noLabelWithoutControl: htmlFor trỏ tới Checkbox ngay bên trên (vùng bấm mở rộng) */}\n <label\n htmlFor={htmlFor}\n className={cn(\n \"absolute inset-0 cursor-pointer\",\n debug && \"border border-destructive-ink border-dashed bg-destructive/20\"\n )}\n />\n </div>\n );\n}\n\ninterface DataGridSelectCheckboxProps extends Omit<React.ComponentProps<typeof Checkbox>, \"id\"> {\n rowNumber?: number;\n hitboxSize?: HitboxSize;\n debug?: boolean;\n}\n\nfunction DataGridSelectCheckbox({\n rowNumber,\n hitboxSize,\n debug,\n checked,\n className,\n ...props\n}: DataGridSelectCheckboxProps) {\n const id = React.useId();\n\n if (rowNumber !== undefined) {\n return (\n <DataGridSelectHitbox htmlFor={id} size={hitboxSize} debug={debug}>\n <div\n aria-hidden=\"true\"\n className={cn(\n // Ẩn bằng `visibility`, KHÔNG bằng `opacity-0`: số thứ tự là chữ, và cổng\n // `lint:a11y` nhân opacity vào màu chữ nên `opacity-0` đọc ra 1,00:1 — một chỗ\n // \"chữ không đọc được\" mà cổng không thể biết là cố ý. `invisible` cũng đúng hơn\n // về ngữ nghĩa: nó rút phần tử khỏi cây trợ năng thay vì để nó vẫn được đọc lên.\n \"pointer-events-none absolute start-3 top-1.5 flex size-4 items-center justify-center text-muted-foreground text-xs tabular-nums group-hover:invisible\",\n checked && \"invisible\"\n )}\n >\n {rowNumber}\n </div>\n <Checkbox\n id={id}\n className={cn(\n // Không ghi đè viền hover: `Checkbox` của gói đã đi qua `--choice-edge` /\n // `--choice-edge-strong`. `border-primary/40` vừa sai vai trò (bậc tô NỀN đem vẽ\n // NÉT) vừa chỉ 1,25:1 ở light.\n \"relative transition-[shadow,border,opacity]\",\n // Ở đây PHẢI là `opacity`, không phải `invisible` như số thứ tự bên trên: đây là\n // checkbox thật, `visibility:hidden` sẽ làm nó mất luôn khả năng nhận Tab.\n \"opacity-0 group-hover:opacity-100 data-[state=checked]:opacity-100\",\n className\n )}\n checked={checked}\n {...props}\n />\n </DataGridSelectHitbox>\n );\n }\n\n return (\n <DataGridSelectHitbox htmlFor={id} size={hitboxSize} debug={debug}>\n <Checkbox id={id} className={cn(\"relative transition-[shadow,border]\", className)} checked={checked} {...props} />\n </DataGridSelectHitbox>\n );\n}\n\ninterface DataGridSelectHeaderProps<TData> extends Pick<HeaderContext<TData, unknown>, \"table\"> {\n hitboxSize?: HitboxSize;\n readOnly?: boolean;\n debug?: boolean;\n}\n\nfunction DataGridSelectHeader<TData>({ table, hitboxSize, readOnly, debug }: DataGridSelectHeaderProps<TData>) {\n const onCheckedChange = React.useCallback((value: boolean) => table.toggleAllPageRowsSelected(value), [table]);\n\n if (readOnly) {\n return <div className=\"mt-1 flex items-center ps-1 text-muted-foreground text-sm\">#</div>;\n }\n\n return (\n <DataGridSelectCheckbox\n aria-label={msg.select.all}\n checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && \"indeterminate\")}\n onCheckedChange={onCheckedChange}\n hitboxSize={hitboxSize}\n debug={debug}\n />\n );\n}\n\ninterface DataGridSelectCellProps<TData> extends Pick<CellContext<TData, unknown>, \"row\" | \"table\"> {\n hitboxSize?: HitboxSize;\n enableRowMarkers?: boolean;\n readOnly?: boolean;\n debug?: boolean;\n}\n\nfunction DataGridSelectCell<TData>({\n row,\n table,\n hitboxSize,\n enableRowMarkers,\n readOnly,\n debug\n}: DataGridSelectCellProps<TData>) {\n const meta = table.options.meta;\n const rowNumber = enableRowMarkers ? (meta?.getVisualRowIndex?.(row.id) ?? row.index + 1) : undefined;\n\n const onCheckedChange = React.useCallback(\n (value: boolean) => {\n if (meta?.onRowSelect) {\n meta.onRowSelect(row.id, value, false);\n } else {\n row.toggleSelected(value);\n }\n },\n [meta, row]\n );\n\n const onClick = React.useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n if (event.shiftKey) {\n event.preventDefault();\n meta?.onRowSelect?.(row.id, !row.getIsSelected(), true);\n }\n },\n [meta, row]\n );\n\n if (readOnly) {\n return (\n <div className=\"flex items-center ps-1 text-muted-foreground text-xs tabular-nums\">\n {rowNumber ?? row.index + 1}\n </div>\n );\n }\n\n return (\n <DataGridSelectCheckbox\n aria-label={rowNumber ? msg.select.rowNumber(rowNumber) : msg.select.row}\n checked={row.getIsSelected()}\n onCheckedChange={onCheckedChange}\n onClick={onClick}\n rowNumber={rowNumber}\n hitboxSize={hitboxSize}\n debug={debug}\n />\n );\n}\n\ninterface GetDataGridSelectColumnOptions<TData> extends Omit<Partial<ColumnDef<TData>>, \"id\" | \"header\" | \"cell\"> {\n enableRowMarkers?: boolean;\n readOnly?: boolean;\n hitboxSize?: HitboxSize;\n debug?: boolean;\n}\n\nexport function getDataGridSelectColumn<TData>({\n size = 40,\n hitboxSize = \"default\",\n enableHiding = false,\n enableResizing = false,\n enableSorting = false,\n enableRowMarkers = false,\n readOnly = false,\n debug = false,\n ...props\n}: GetDataGridSelectColumnOptions<TData> = {}): ColumnDef<TData> {\n return {\n id: \"select\",\n header: ({ table }) => (\n <DataGridSelectHeader table={table} hitboxSize={hitboxSize} readOnly={readOnly} debug={debug} />\n ),\n cell: ({ row, table }) => (\n <DataGridSelectCell\n row={row}\n table={table}\n enableRowMarkers={enableRowMarkers}\n readOnly={readOnly}\n hitboxSize={hitboxSize}\n debug={debug}\n />\n ),\n size,\n enableHiding,\n enableResizing,\n enableSorting,\n ...props\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface DivProps extends React.ComponentProps<"div"> {
|
|
4
|
+
}
|
|
5
|
+
declare function DataGridSkeleton({ className, ...props }: DivProps): React.JSX.Element;
|
|
6
|
+
interface DataGridSkeletonToolbarProps extends DivProps {
|
|
7
|
+
align?: "start" | "center" | "end";
|
|
8
|
+
actionCount?: number;
|
|
9
|
+
}
|
|
10
|
+
declare function DataGridSkeletonToolbar({ align, actionCount, className, ...props }: DataGridSkeletonToolbarProps): React.JSX.Element;
|
|
11
|
+
declare function DataGridSkeletonGrid({ className, ...props }: DivProps): React.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { DataGridSkeleton, DataGridSkeletonGrid, DataGridSkeletonToolbar };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Skeleton } from "../components/ui/skeleton.js";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
function DataGridSkeleton({ className, ...props }) {
|
|
5
|
+
return /* @__PURE__ */ jsx(
|
|
6
|
+
"div",
|
|
7
|
+
{
|
|
8
|
+
"data-slot": "grid-skeleton",
|
|
9
|
+
className: cn(
|
|
10
|
+
"flex h-[calc(100dvh-4rem)] w-full flex-col gap-4 has-[>[data-slot=grid-skeleton-toolbar]]:h-[calc(100dvh-5rem)]",
|
|
11
|
+
className
|
|
12
|
+
),
|
|
13
|
+
...props
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
function DataGridSkeletonToolbar({
|
|
18
|
+
align = "end",
|
|
19
|
+
actionCount = 4,
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}) {
|
|
23
|
+
return /* @__PURE__ */ jsx(
|
|
24
|
+
"div",
|
|
25
|
+
{
|
|
26
|
+
"data-slot": "grid-skeleton-toolbar",
|
|
27
|
+
className: cn(
|
|
28
|
+
"flex items-center gap-2",
|
|
29
|
+
{
|
|
30
|
+
"justify-start": align === "start",
|
|
31
|
+
"justify-center": align === "center",
|
|
32
|
+
"justify-end": align === "end"
|
|
33
|
+
},
|
|
34
|
+
className
|
|
35
|
+
),
|
|
36
|
+
...props,
|
|
37
|
+
children: Array.from({ length: actionCount }).map((_, i) => (
|
|
38
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: danh sách placeholder tĩnh, index là key đúng
|
|
39
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-20 shrink-0" }, i)
|
|
40
|
+
))
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
function DataGridSkeletonGrid({ className, ...props }) {
|
|
45
|
+
return /* @__PURE__ */ jsx(Skeleton, { "data-slot": "grid-skeleton-grid", className: cn("flex-1", className), ...props });
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
DataGridSkeleton,
|
|
49
|
+
DataGridSkeletonGrid,
|
|
50
|
+
DataGridSkeletonToolbar
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=data-grid-skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/data-grid/data-grid-skeleton.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { Skeleton } from \"../components/ui/skeleton.js\";\nimport { cn } from \"../lib/cn.js\";\n\ninterface DivProps extends React.ComponentProps<\"div\"> {}\n\nfunction DataGridSkeleton({ className, ...props }: DivProps) {\n return (\n <div\n data-slot=\"grid-skeleton\"\n className={cn(\n \"flex h-[calc(100dvh-4rem)] w-full flex-col gap-4 has-[>[data-slot=grid-skeleton-toolbar]]:h-[calc(100dvh-5rem)]\",\n className\n )}\n {...props}\n />\n );\n}\n\ninterface DataGridSkeletonToolbarProps extends DivProps {\n align?: \"start\" | \"center\" | \"end\";\n actionCount?: number;\n}\n\nfunction DataGridSkeletonToolbar({\n align = \"end\",\n actionCount = 4,\n className,\n ...props\n}: DataGridSkeletonToolbarProps) {\n return (\n <div\n data-slot=\"grid-skeleton-toolbar\"\n className={cn(\n \"flex items-center gap-2\",\n {\n \"justify-start\": align === \"start\",\n \"justify-center\": align === \"center\",\n \"justify-end\": align === \"end\"\n },\n className\n )}\n {...props}\n >\n {Array.from({ length: actionCount }).map((_, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: danh sách placeholder tĩnh, index là key đúng\n <Skeleton key={i} className=\"h-7 w-20 shrink-0\" />\n ))}\n </div>\n );\n}\n\nfunction DataGridSkeletonGrid({ className, ...props }: DivProps) {\n return <Skeleton data-slot=\"grid-skeleton-grid\" className={cn(\"flex-1\", className)} {...props} />;\n}\n\nexport { DataGridSkeleton, DataGridSkeletonGrid, DataGridSkeletonToolbar };\n"],"mappings":"AAQI;AAPJ,SAAS,gBAAgB;AACzB,SAAS,UAAU;AAInB,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAAa;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAOA,SAAS,wBAAwB;AAAA,EAC/B,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AAAA,EACA,GAAG;AACL,GAAiC;AAC/B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,UACE,iBAAiB,UAAU;AAAA,UAC3B,kBAAkB,UAAU;AAAA,UAC5B,eAAe,UAAU;AAAA,QAC3B;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH,gBAAM,KAAK,EAAE,QAAQ,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG;AAAA;AAAA,QAE3C,oBAAC,YAAiB,WAAU,uBAAb,CAAiC;AAAA,OACjD;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,qBAAqB,EAAE,WAAW,GAAG,MAAM,GAAa;AAC/D,SAAO,oBAAC,YAAS,aAAU,sBAAqB,WAAW,GAAG,UAAU,SAAS,GAAI,GAAG,OAAO;AACjG;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { PopoverContent } from '../components/ui/popover.js';
|
|
4
|
+
import '@radix-ui/react-popover';
|
|
5
|
+
|
|
6
|
+
interface DataGridSortMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {
|
|
7
|
+
table: Table<TData>;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare function DataGridSortMenu<TData>({ table, disabled, className, ...props }: DataGridSortMenuProps<TData>): React.JSX.Element;
|
|
11
|
+
|
|
12
|
+
export { DataGridSortMenu };
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useDirection } from "@radix-ui/react-direction";
|
|
4
|
+
import { ArrowDownUp, ChevronsUpDown, GripVertical, Trash2 } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { badgeVariants } from "../components/ui/badge.js";
|
|
7
|
+
import { Button } from "../components/ui/button.js";
|
|
8
|
+
import {
|
|
9
|
+
Command,
|
|
10
|
+
CommandEmpty,
|
|
11
|
+
CommandGroup,
|
|
12
|
+
CommandInput,
|
|
13
|
+
CommandItem,
|
|
14
|
+
CommandList
|
|
15
|
+
} from "../components/ui/command.js";
|
|
16
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../components/ui/popover.js";
|
|
17
|
+
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../components/ui/select.js";
|
|
18
|
+
import { cn } from "../lib/cn.js";
|
|
19
|
+
import { msg } from "./messages.js";
|
|
20
|
+
import { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from "./sortable.js";
|
|
21
|
+
const SORT_SHORTCUT_KEY = "s";
|
|
22
|
+
const REMOVE_SORT_SHORTCUTS = /* @__PURE__ */ new Set(["backspace", "delete"]);
|
|
23
|
+
const SORT_ORDERS = [
|
|
24
|
+
{ label: msg.sort.asc, value: "asc" },
|
|
25
|
+
{ label: msg.sort.desc, value: "desc" }
|
|
26
|
+
];
|
|
27
|
+
function DataGridSortMenu({ table, disabled, className, ...props }) {
|
|
28
|
+
const dir = useDirection();
|
|
29
|
+
const id = React.useId();
|
|
30
|
+
const labelId = React.useId();
|
|
31
|
+
const descriptionId = React.useId();
|
|
32
|
+
const [open, setOpen] = React.useState(false);
|
|
33
|
+
const addButtonRef = React.useRef(null);
|
|
34
|
+
const sorting = table.getState().sorting;
|
|
35
|
+
const onSortingChange = table.setSorting;
|
|
36
|
+
const { columnLabels, columns } = React.useMemo(() => {
|
|
37
|
+
const labels = /* @__PURE__ */ new Map();
|
|
38
|
+
const sortingIds = new Set(sorting.map((s) => s.id));
|
|
39
|
+
const availableColumns = [];
|
|
40
|
+
for (const column of table.getAllColumns()) {
|
|
41
|
+
if (!column.getCanSort()) continue;
|
|
42
|
+
const label = column.columnDef.meta?.label ?? column.id;
|
|
43
|
+
labels.set(column.id, label);
|
|
44
|
+
if (!sortingIds.has(column.id)) {
|
|
45
|
+
availableColumns.push({ id: column.id, label });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
columnLabels: labels,
|
|
50
|
+
columns: availableColumns
|
|
51
|
+
};
|
|
52
|
+
}, [sorting, table]);
|
|
53
|
+
const onSortAdd = React.useCallback(() => {
|
|
54
|
+
const firstColumn = columns[0];
|
|
55
|
+
if (!firstColumn) return;
|
|
56
|
+
onSortingChange((prevSorting) => [...prevSorting, { id: firstColumn.id, desc: false }]);
|
|
57
|
+
}, [columns, onSortingChange]);
|
|
58
|
+
const onSortUpdate = React.useCallback(
|
|
59
|
+
(sortId, updates) => {
|
|
60
|
+
onSortingChange((prevSorting) => {
|
|
61
|
+
if (!prevSorting) return prevSorting;
|
|
62
|
+
return prevSorting.map((sort) => sort.id === sortId ? { ...sort, ...updates } : sort);
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
[onSortingChange]
|
|
66
|
+
);
|
|
67
|
+
const onSortRemove = React.useCallback(
|
|
68
|
+
(sortId) => {
|
|
69
|
+
onSortingChange((prevSorting) => prevSorting.filter((item) => item.id !== sortId));
|
|
70
|
+
},
|
|
71
|
+
[onSortingChange]
|
|
72
|
+
);
|
|
73
|
+
const onSortingReset = React.useCallback(
|
|
74
|
+
() => onSortingChange(table.initialState.sorting),
|
|
75
|
+
[onSortingChange, table.initialState.sorting]
|
|
76
|
+
);
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
function onKeyDown(event) {
|
|
79
|
+
if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLElement && event.target.contentEditable === "true") {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (event.key.toLowerCase() === SORT_SHORTCUT_KEY && (event.ctrlKey || event.metaKey) && event.shiftKey) {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
setOpen((prev) => !prev);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
window.addEventListener("keydown", onKeyDown);
|
|
88
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
89
|
+
}, []);
|
|
90
|
+
const onTriggerKeyDown = React.useCallback(
|
|
91
|
+
(event) => {
|
|
92
|
+
if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase()) && sorting.length > 0) {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
onSortingReset();
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
[sorting.length, onSortingReset]
|
|
98
|
+
);
|
|
99
|
+
return /* @__PURE__ */ jsxs(Sortable, { value: sorting, onValueChange: onSortingChange, getItemValue: (item) => item.id, children: [
|
|
100
|
+
/* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
101
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
102
|
+
Button,
|
|
103
|
+
{
|
|
104
|
+
dir,
|
|
105
|
+
variant: "outline",
|
|
106
|
+
className: "h-8 gap-2 font-normal",
|
|
107
|
+
onKeyDown: onTriggerKeyDown,
|
|
108
|
+
disabled,
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsx(ArrowDownUp, { "aria-hidden": "true", className: "text-muted-foreground" }),
|
|
111
|
+
msg.sort.trigger,
|
|
112
|
+
sorting.length > 0 && /* @__PURE__ */ jsx(
|
|
113
|
+
"span",
|
|
114
|
+
{
|
|
115
|
+
className: cn(
|
|
116
|
+
badgeVariants({ variant: "secondary" }),
|
|
117
|
+
"h-5 rounded px-1.5 font-mono text-[11px] font-medium"
|
|
118
|
+
),
|
|
119
|
+
children: sorting.length
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
) }),
|
|
125
|
+
/* @__PURE__ */ jsxs(
|
|
126
|
+
PopoverContent,
|
|
127
|
+
{
|
|
128
|
+
"aria-labelledby": labelId,
|
|
129
|
+
"aria-describedby": descriptionId,
|
|
130
|
+
dir,
|
|
131
|
+
className: cn(
|
|
132
|
+
"flex w-full max-w-[--radix-popover-content-available-width] flex-col gap-3.5 p-4 sm:min-w-[380px]",
|
|
133
|
+
className
|
|
134
|
+
),
|
|
135
|
+
...props,
|
|
136
|
+
children: [
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
138
|
+
/* @__PURE__ */ jsx("h4", { id: labelId, className: "font-medium leading-none", children: sorting.length > 0 ? msg.sort.title : msg.sort.emptyTitle }),
|
|
139
|
+
/* @__PURE__ */ jsx("p", { id: descriptionId, className: cn("text-muted-foreground text-sm", sorting.length > 0 && "sr-only"), children: sorting.length > 0 ? msg.sort.description : msg.sort.emptyDescription })
|
|
140
|
+
] }),
|
|
141
|
+
sorting.length > 0 && /* @__PURE__ */ jsx(SortableContent, { asChild: true, children: /* @__PURE__ */ jsx("div", { role: "list", className: "flex max-h-[300px] flex-col gap-2 overflow-y-auto p-1", children: sorting.map((sort) => /* @__PURE__ */ jsx(
|
|
142
|
+
DataTableSortItem,
|
|
143
|
+
{
|
|
144
|
+
sort,
|
|
145
|
+
sortItemId: `${id}-sort-${sort.id}`,
|
|
146
|
+
dir,
|
|
147
|
+
columns,
|
|
148
|
+
columnLabels,
|
|
149
|
+
onSortUpdate,
|
|
150
|
+
onSortRemove
|
|
151
|
+
},
|
|
152
|
+
sort.id
|
|
153
|
+
)) }) }),
|
|
154
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
155
|
+
/* @__PURE__ */ jsx(
|
|
156
|
+
Button,
|
|
157
|
+
{
|
|
158
|
+
size: "sm",
|
|
159
|
+
className: "rounded",
|
|
160
|
+
ref: addButtonRef,
|
|
161
|
+
onClick: onSortAdd,
|
|
162
|
+
disabled: columns.length === 0,
|
|
163
|
+
children: msg.sort.add
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
sorting.length > 0 && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", className: "rounded", onClick: onSortingReset, children: msg.sort.reset })
|
|
167
|
+
] })
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
] }),
|
|
172
|
+
/* @__PURE__ */ jsx(SortableOverlay, { children: /* @__PURE__ */ jsxs("div", { dir, className: "flex items-center gap-2", children: [
|
|
173
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-44 rounded-sm bg-muted" }),
|
|
174
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-24 rounded-sm bg-muted" }),
|
|
175
|
+
/* @__PURE__ */ jsx("div", { className: "size-8 shrink-0 rounded-sm bg-muted" }),
|
|
176
|
+
/* @__PURE__ */ jsx("div", { className: "size-8 shrink-0 rounded-sm bg-muted" })
|
|
177
|
+
] }) })
|
|
178
|
+
] });
|
|
179
|
+
}
|
|
180
|
+
function DataTableSortItem({
|
|
181
|
+
sort,
|
|
182
|
+
sortItemId,
|
|
183
|
+
dir,
|
|
184
|
+
columns,
|
|
185
|
+
columnLabels,
|
|
186
|
+
onSortUpdate,
|
|
187
|
+
onSortRemove
|
|
188
|
+
}) {
|
|
189
|
+
const fieldListboxId = `${sortItemId}-field-listbox`;
|
|
190
|
+
const fieldTriggerId = `${sortItemId}-field-trigger`;
|
|
191
|
+
const directionListboxId = `${sortItemId}-direction-listbox`;
|
|
192
|
+
const [showFieldSelector, setShowFieldSelector] = React.useState(false);
|
|
193
|
+
const [showDirectionSelector, setShowDirectionSelector] = React.useState(false);
|
|
194
|
+
const onItemKeyDown = React.useCallback(
|
|
195
|
+
(event) => {
|
|
196
|
+
if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (showFieldSelector || showDirectionSelector) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (REMOVE_SORT_SHORTCUTS.has(event.key.toLowerCase())) {
|
|
203
|
+
event.preventDefault();
|
|
204
|
+
onSortRemove(sort.id);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
[sort.id, showFieldSelector, showDirectionSelector, onSortRemove]
|
|
208
|
+
);
|
|
209
|
+
return /* @__PURE__ */ jsx(SortableItem, { value: sort.id, asChild: true, children: /* @__PURE__ */ jsxs("div", { role: "listitem", id: sortItemId, tabIndex: -1, className: "flex items-center gap-2", onKeyDown: onItemKeyDown, children: [
|
|
210
|
+
/* @__PURE__ */ jsxs(Popover, { open: showFieldSelector, onOpenChange: setShowFieldSelector, children: [
|
|
211
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
212
|
+
Button,
|
|
213
|
+
{
|
|
214
|
+
id: fieldTriggerId,
|
|
215
|
+
"aria-controls": fieldListboxId,
|
|
216
|
+
variant: "outline",
|
|
217
|
+
className: "h-8 w-44 justify-between rounded font-normal",
|
|
218
|
+
children: [
|
|
219
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: columnLabels.get(sort.id) }),
|
|
220
|
+
/* @__PURE__ */ jsx(ChevronsUpDown, { "aria-hidden": "true", className: "opacity-50" })
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
) }),
|
|
224
|
+
/* @__PURE__ */ jsx(PopoverContent, { id: fieldListboxId, dir, className: "w-[--radix-popover-trigger-width] p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
225
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder: msg.sort.fieldPlaceholder, "aria-label": msg.sort.fieldPlaceholder }),
|
|
226
|
+
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
227
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: msg.sort.fieldEmpty }),
|
|
228
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: columns.map((column) => /* @__PURE__ */ jsx(
|
|
229
|
+
CommandItem,
|
|
230
|
+
{
|
|
231
|
+
value: column.id,
|
|
232
|
+
onSelect: (value) => onSortUpdate(sort.id, { id: value }),
|
|
233
|
+
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: column.label })
|
|
234
|
+
},
|
|
235
|
+
column.id
|
|
236
|
+
)) })
|
|
237
|
+
] })
|
|
238
|
+
] }) })
|
|
239
|
+
] }),
|
|
240
|
+
/* @__PURE__ */ jsxs(
|
|
241
|
+
Select,
|
|
242
|
+
{
|
|
243
|
+
open: showDirectionSelector,
|
|
244
|
+
onOpenChange: setShowDirectionSelector,
|
|
245
|
+
value: sort.desc ? "desc" : "asc",
|
|
246
|
+
onValueChange: (value) => onSortUpdate(sort.id, { desc: value === "desc" }),
|
|
247
|
+
children: [
|
|
248
|
+
/* @__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: SORT_ORDERS.map((order) => /* @__PURE__ */ jsx(SelectItem, { value: order.value, children: order.label }, order.value)) }) })
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
),
|
|
253
|
+
/* @__PURE__ */ jsx(
|
|
254
|
+
Button,
|
|
255
|
+
{
|
|
256
|
+
"aria-controls": sortItemId,
|
|
257
|
+
"aria-label": msg.sort.remove,
|
|
258
|
+
variant: "outline",
|
|
259
|
+
size: "icon",
|
|
260
|
+
className: "size-8 shrink-0 rounded",
|
|
261
|
+
onClick: () => onSortRemove(sort.id),
|
|
262
|
+
children: /* @__PURE__ */ jsx(Trash2, { "aria-hidden": "true" })
|
|
263
|
+
}
|
|
264
|
+
),
|
|
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" }) }) })
|
|
266
|
+
] }) });
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
DataGridSortMenu
|
|
270
|
+
};
|
|
271
|
+
//# sourceMappingURL=data-grid-sort-menu.js.map
|
|
@@ -0,0 +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":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { PopoverContent } from '../components/ui/popover.js';
|
|
4
|
+
import '@radix-ui/react-popover';
|
|
5
|
+
|
|
6
|
+
interface DataGridViewMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {
|
|
7
|
+
table: Table<TData>;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Ẩ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;
|
|
12
|
+
|
|
13
|
+
export { DataGridViewMenu };
|