@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.
Files changed (101) hide show
  1. package/README.md +15 -4
  2. package/dist/data-grid/compose-refs.d.ts +19 -0
  3. package/dist/data-grid/compose-refs.js +41 -0
  4. package/dist/data-grid/compose-refs.js.map +1 -0
  5. package/dist/data-grid/data-grid-cell-variants.d.ts +15 -0
  6. package/dist/data-grid/data-grid-cell-variants.js +1734 -0
  7. package/dist/data-grid/data-grid-cell-variants.js.map +1 -0
  8. package/dist/data-grid/data-grid-cell-wrapper.d.ts +9 -0
  9. package/dist/data-grid/data-grid-cell-wrapper.js +179 -0
  10. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -0
  11. package/dist/data-grid/data-grid-cell.d.ts +8 -0
  12. package/dist/data-grid/data-grid-cell.js +101 -0
  13. package/dist/data-grid/data-grid-cell.js.map +1 -0
  14. package/dist/data-grid/data-grid-column-header.d.ts +12 -0
  15. package/dist/data-grid/data-grid-column-header.js +205 -0
  16. package/dist/data-grid/data-grid-column-header.js.map +1 -0
  17. package/dist/data-grid/data-grid-context-menu.d.ts +12 -0
  18. package/dist/data-grid/data-grid-context-menu.js +160 -0
  19. package/dist/data-grid/data-grid-context-menu.js.map +1 -0
  20. package/dist/data-grid/data-grid-filter-menu.d.ts +12 -0
  21. package/dist/data-grid/data-grid-filter-menu.js +714 -0
  22. package/dist/data-grid/data-grid-filter-menu.js.map +1 -0
  23. package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +20 -0
  24. package/dist/data-grid/data-grid-keyboard-shortcuts.js +227 -0
  25. package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -0
  26. package/dist/data-grid/data-grid-paste-dialog.d.ts +11 -0
  27. package/dist/data-grid/data-grid-paste-dialog.js +103 -0
  28. package/dist/data-grid/data-grid-paste-dialog.js.map +1 -0
  29. package/dist/data-grid/data-grid-presence.d.ts +14 -0
  30. package/dist/data-grid/data-grid-presence.js +16 -0
  31. package/dist/data-grid/data-grid-presence.js.map +1 -0
  32. package/dist/data-grid/data-grid-row-height-menu.d.ts +15 -0
  33. package/dist/data-grid/data-grid-row-height-menu.js +56 -0
  34. package/dist/data-grid/data-grid-row-height-menu.js.map +1 -0
  35. package/dist/data-grid/data-grid-row.d.ts +28 -0
  36. package/dist/data-grid/data-grid-row.js +206 -0
  37. package/dist/data-grid/data-grid-row.js.map +1 -0
  38. package/dist/data-grid/data-grid-search.d.ts +10 -0
  39. package/dist/data-grid/data-grid-search.js +183 -0
  40. package/dist/data-grid/data-grid-search.js.map +1 -0
  41. package/dist/data-grid/data-grid-select-column.d.ts +12 -0
  42. package/dist/data-grid/data-grid-select-column.js +177 -0
  43. package/dist/data-grid/data-grid-select-column.js.map +1 -0
  44. package/dist/data-grid/data-grid-skeleton.d.ts +13 -0
  45. package/dist/data-grid/data-grid-skeleton.js +52 -0
  46. package/dist/data-grid/data-grid-skeleton.js.map +1 -0
  47. package/dist/data-grid/data-grid-sort-menu.d.ts +12 -0
  48. package/dist/data-grid/data-grid-sort-menu.js +271 -0
  49. package/dist/data-grid/data-grid-sort-menu.js.map +1 -0
  50. package/dist/data-grid/data-grid-view-menu.d.ts +13 -0
  51. package/dist/data-grid/data-grid-view-menu.js +66 -0
  52. package/dist/data-grid/data-grid-view-menu.js.map +1 -0
  53. package/dist/data-grid/data-grid.d.ts +32 -0
  54. package/dist/data-grid/data-grid.js +235 -0
  55. package/dist/data-grid/data-grid.js.map +1 -0
  56. package/dist/data-grid/filters.d.ts +31 -0
  57. package/dist/data-grid/filters.js +212 -0
  58. package/dist/data-grid/filters.js.map +1 -0
  59. package/dist/data-grid/index.d.ts +22 -0
  60. package/dist/data-grid/index.js +77 -0
  61. package/dist/data-grid/index.js.map +1 -0
  62. package/dist/data-grid/messages.d.ts +280 -0
  63. package/dist/data-grid/messages.js +279 -0
  64. package/dist/data-grid/messages.js.map +1 -0
  65. package/dist/data-grid/sortable.d.ts +50 -0
  66. package/dist/data-grid/sortable.js +361 -0
  67. package/dist/data-grid/sortable.js.map +1 -0
  68. package/dist/data-grid/toast.d.ts +10 -0
  69. package/dist/data-grid/toast.js +21 -0
  70. package/dist/data-grid/toast.js.map +1 -0
  71. package/dist/data-grid/types.d.ts +189 -0
  72. package/dist/data-grid/types.js +1 -0
  73. package/dist/data-grid/types.js.map +1 -0
  74. package/dist/data-grid/use-as-ref.d.ts +5 -0
  75. package/dist/data-grid/use-as-ref.js +13 -0
  76. package/dist/data-grid/use-as-ref.js.map +1 -0
  77. package/dist/data-grid/use-badge-overflow.d.ts +24 -0
  78. package/dist/data-grid/use-badge-overflow.js +123 -0
  79. package/dist/data-grid/use-badge-overflow.js.map +1 -0
  80. package/dist/data-grid/use-callback-ref.d.ts +10 -0
  81. package/dist/data-grid/use-callback-ref.js +12 -0
  82. package/dist/data-grid/use-callback-ref.js.map +1 -0
  83. package/dist/data-grid/use-data-grid-undo-redo.d.ts +33 -0
  84. package/dist/data-grid/use-data-grid-undo-redo.js +345 -0
  85. package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -0
  86. package/dist/data-grid/use-data-grid.d.ts +92 -0
  87. package/dist/data-grid/use-data-grid.js +2692 -0
  88. package/dist/data-grid/use-data-grid.js.map +1 -0
  89. package/dist/data-grid/use-debounced-callback.d.ts +6 -0
  90. package/dist/data-grid/use-debounced-callback.js +19 -0
  91. package/dist/data-grid/use-debounced-callback.js.map +1 -0
  92. package/dist/data-grid/use-isomorphic-layout-effect.d.ts +5 -0
  93. package/dist/data-grid/use-isomorphic-layout-effect.js +6 -0
  94. package/dist/data-grid/use-isomorphic-layout-effect.js.map +1 -0
  95. package/dist/data-grid/use-lazy-ref.d.ts +5 -0
  96. package/dist/data-grid/use-lazy-ref.js +12 -0
  97. package/dist/data-grid/use-lazy-ref.js.map +1 -0
  98. package/dist/data-grid/utils.d.ts +73 -0
  99. package/dist/data-grid/utils.js +408 -0
  100. package/dist/data-grid/utils.js.map +1 -0
  101. 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 };