@comitor/ui 1.9.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 (105) 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/dist/shell/app-launcher.js +16 -16
  102. package/dist/shell/app-launcher.js.map +1 -1
  103. package/dist/shell/types.d.ts +13 -0
  104. package/dist/shell/types.js.map +1 -1
  105. package/package.json +33 -15
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/data-grid-filter-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { Column, ColumnFilter, Table } from \"@tanstack/react-table\";\nimport { vi } from \"date-fns/locale\";\nimport { CalendarIcon, Check, ChevronsUpDown, GripVertical, ListFilter, Trash2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { badgeVariants } from \"../components/ui/badge.js\";\nimport { Button } from \"../components/ui/button.js\";\nimport { Calendar } from \"../components/ui/calendar.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Input } from \"../components/ui/input.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 { getDefaultOperator, getOperatorsForVariant } from \"./filters.js\";\nimport { msg } from \"./messages.js\";\nimport { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from \"./sortable.js\";\nimport type { FilterOperator, FilterValue } from \"./types.js\";\nimport { useDebouncedCallback } from \"./use-debounced-callback.js\";\nimport { formatDate } from \"./utils.js\";\n\nconst FILTER_SHORTCUT_KEY = \"f\";\nconst REMOVE_FILTER_SHORTCUTS = new Set([\"backspace\", \"delete\"]);\nconst FILTER_DEBOUNCE_MS = 300;\nconst OPERATORS_WITHOUT_VALUE = new Set([\"isEmpty\", \"isNotEmpty\", \"isTrue\", \"isFalse\"]);\n\ninterface DataGridFilterMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n}\n\nexport function DataGridFilterMenu<TData>({ table, disabled, className, ...props }: DataGridFilterMenuProps<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 columnFilters = table.getState().columnFilters;\n\n const { columnLabels, columns, columnVariants } = React.useMemo(() => {\n const labels = new Map<string, string>();\n const variants = new Map<string, string>();\n const filteringIds = new Set(columnFilters.map((f) => f.id));\n const availableColumns: { id: string; label: string }[] = [];\n\n for (const column of table.getAllColumns()) {\n if (!column.getCanFilter()) continue;\n\n const label = column.columnDef.meta?.label ?? column.id;\n const variant = column.columnDef.meta?.cell?.variant ?? \"short-text\";\n\n labels.set(column.id, label);\n variants.set(column.id, variant);\n\n if (!filteringIds.has(column.id)) {\n availableColumns.push({ id: column.id, label });\n }\n }\n\n return {\n columnLabels: labels,\n columns: availableColumns,\n columnVariants: variants\n };\n }, [columnFilters, table]);\n\n const onFilterAdd = React.useCallback(() => {\n const firstColumn = columns[0];\n if (!firstColumn) return;\n\n const variant = columnVariants.get(firstColumn.id) ?? \"short-text\";\n const defaultOperator = getDefaultOperator(variant);\n\n table.setColumnFilters((prevFilters) => [\n ...prevFilters,\n {\n id: firstColumn.id,\n value: {\n operator: defaultOperator,\n value: \"\"\n }\n }\n ]);\n }, [columns, columnVariants, table]);\n\n const onFilterUpdate = React.useCallback(\n (filterId: string, updates: Partial<ColumnFilter>) => {\n table.setColumnFilters((prevFilters) => {\n if (!prevFilters) return prevFilters;\n return prevFilters.map((filter) => (filter.id === filterId ? { ...filter, ...updates } : filter));\n });\n },\n [table]\n );\n\n const onFilterRemove = React.useCallback(\n (filterId: string) => {\n table.setColumnFilters((prevFilters) => prevFilters.filter((item) => item.id !== filterId));\n },\n [table]\n );\n\n const onFiltersReset = React.useCallback(() => {\n table.setColumnFilters(table.initialState.columnFilters ?? []);\n }, [table]);\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() === FILTER_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_FILTER_SHORTCUTS.has(event.key.toLowerCase()) && columnFilters.length > 0) {\n event.preventDefault();\n onFiltersReset();\n }\n },\n [columnFilters.length, onFiltersReset]\n );\n\n return (\n <Sortable value={columnFilters} onValueChange={table.setColumnFilters} 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 <ListFilter aria-hidden=\"true\" className=\"text-muted-foreground\" />\n {msg.filter.trigger}\n {columnFilters.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 {columnFilters.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-[480px]\",\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-1\">\n <h4 id={labelId} className=\"font-medium leading-none\">\n {columnFilters.length > 0 ? msg.filter.title : msg.filter.emptyTitle}\n </h4>\n <p\n id={descriptionId}\n className={cn(\"text-muted-foreground text-sm\", columnFilters.length > 0 && \"sr-only\")}\n >\n {columnFilters.length > 0 ? msg.filter.description : msg.filter.emptyDescription}\n </p>\n </div>\n {columnFilters.length > 0 && (\n <SortableContent asChild>\n <div role=\"list\" className=\"flex max-h-[400px] flex-col gap-2 overflow-y-auto p-1\">\n {columnFilters.map((filter, index) => (\n <DataGridFilterItem\n key={filter.id}\n filter={filter}\n index={index}\n filterItemId={`${id}-filter-${filter.id}`}\n dir={dir}\n columns={columns}\n columnLabels={columnLabels}\n columnVariants={columnVariants}\n table={table}\n onFilterUpdate={onFilterUpdate}\n onFilterRemove={onFilterRemove}\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={onFilterAdd}\n disabled={columns.length === 0}\n >\n {msg.filter.add}\n </Button>\n {columnFilters.length > 0 && (\n <Button variant=\"outline\" size=\"sm\" className=\"rounded\" onClick={onFiltersReset}>\n {msg.filter.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 min-w-[72px] rounded-sm bg-muted\" />\n <div className=\"h-8 w-32 rounded-sm bg-muted\" />\n <div className=\"h-8 w-32 rounded-sm bg-muted\" />\n <div className=\"h-8 w-36 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 DataGridFilterItemProps<TData> {\n filter: ColumnFilter;\n index: number;\n filterItemId: string;\n dir: \"ltr\" | \"rtl\";\n columns: { id: string; label: string }[];\n columnLabels: Map<string, string>;\n columnVariants: Map<string, string>;\n table: Table<TData>;\n onFilterUpdate: (filterId: string, updates: Partial<ColumnFilter>) => void;\n onFilterRemove: (filterId: string) => void;\n}\n\nfunction DataGridFilterItem<TData>({\n filter,\n index,\n filterItemId,\n dir,\n columns,\n columnLabels,\n columnVariants,\n table,\n onFilterUpdate,\n onFilterRemove\n}: DataGridFilterItemProps<TData>) {\n const fieldListboxId = `${filterItemId}-field-listbox`;\n const fieldTriggerId = `${filterItemId}-field-trigger`;\n const operatorListboxId = `${filterItemId}-operator-listbox`;\n const inputId = `${filterItemId}-input`;\n\n const [showFieldSelector, setShowFieldSelector] = React.useState(false);\n const [showOperatorSelector, setShowOperatorSelector] = React.useState(false);\n\n const variant = columnVariants.get(filter.id) ?? \"short-text\";\n const filterValue = filter.value as FilterValue | undefined;\n const operator = filterValue?.operator ?? getDefaultOperator(variant);\n\n const operators = getOperatorsForVariant(variant);\n const needsValue = !OPERATORS_WITHOUT_VALUE.has(operator);\n\n const column = table.getColumn(filter.id);\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 || showOperatorSelector) {\n return;\n }\n\n if (REMOVE_FILTER_SHORTCUTS.has(event.key.toLowerCase())) {\n event.preventDefault();\n onFilterRemove(filter.id);\n }\n },\n [filter.id, showFieldSelector, showOperatorSelector, onFilterRemove]\n );\n\n const onOperatorChange = React.useCallback(\n (newOperator: FilterOperator) => {\n onFilterUpdate(filter.id, {\n value: {\n operator: newOperator,\n value: filterValue?.value,\n endValue: filterValue?.endValue\n }\n });\n },\n [filter.id, filterValue?.value, filterValue?.endValue, onFilterUpdate]\n );\n\n const onValueChange = React.useCallback(\n (newValue: string | number | string[] | undefined) => {\n onFilterUpdate(filter.id, {\n value: {\n operator,\n value: newValue,\n endValue: filterValue?.endValue\n }\n });\n },\n [filter.id, operator, filterValue?.endValue, onFilterUpdate]\n );\n\n const onEndValueChange = React.useCallback(\n (newValue: string | number | string[] | undefined) => {\n onFilterUpdate(filter.id, {\n value: {\n operator,\n value: filterValue?.value,\n endValue: newValue as string | number | undefined\n }\n });\n },\n [filter.id, operator, filterValue?.value, onFilterUpdate]\n );\n\n return (\n <SortableItem value={filter.id} asChild>\n <div\n role=\"listitem\"\n id={filterItemId}\n tabIndex={-1}\n className=\"flex items-center gap-2\"\n onKeyDown={onItemKeyDown}\n >\n <div className=\"min-w-[72px] text-center\">\n <span className=\"text-muted-foreground text-sm\">{index === 0 ? msg.filter.where : msg.filter.and}</span>\n </div>\n <Popover open={showFieldSelector} onOpenChange={setShowFieldSelector}>\n <PopoverTrigger asChild>\n <Button\n id={fieldTriggerId}\n aria-controls={fieldListboxId}\n dir={dir}\n variant=\"outline\"\n className=\"h-8 w-32 justify-between rounded font-normal\"\n >\n <span className=\"truncate\">{columnLabels.get(filter.id)}</span>\n <ChevronsUpDown aria-hidden=\"true\" className=\"opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent id={fieldListboxId} dir={dir} align=\"start\" className=\"w-40 p-0\">\n <Command>\n <CommandInput placeholder={msg.filter.fieldPlaceholder} aria-label={msg.filter.fieldPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.filter.fieldEmpty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => (\n <CommandItem\n key={column.id}\n value={column.id}\n onSelect={(value) => {\n const newVariant = columnVariants.get(value) ?? \"short-text\";\n const newOperator = getDefaultOperator(newVariant);\n\n table.setColumnFilters((prevFilters) =>\n prevFilters.map((f) =>\n f.id === filter.id\n ? {\n id: value,\n value: {\n operator: newOperator,\n value: \"\"\n }\n }\n : f\n )\n );\n setShowFieldSelector(false);\n }}\n >\n <span className=\"truncate\">{column.label}</span>\n <Check className={cn(\"ms-auto\", column.id === filter.id ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <Select\n open={showOperatorSelector}\n onOpenChange={setShowOperatorSelector}\n value={operator}\n onValueChange={onOperatorChange}\n >\n <SelectTrigger aria-controls={operatorListboxId} aria-label={msg.filter.title} className=\"h-8 w-36 rounded\">\n <div className=\"truncate\">\n <SelectValue />\n </div>\n </SelectTrigger>\n <SelectContent id={operatorListboxId}>\n <SelectGroup>\n {operators.map((op) => (\n <SelectItem key={op.value} value={op.value}>\n {op.label}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n <div className=\"min-w-36 max-w-60 flex-1\">\n {needsValue && column ? (\n <DataGridFilterInput\n key={filter.id}\n variant={variant}\n operator={operator}\n column={column}\n inputId={inputId}\n dir={dir}\n value={filterValue?.value}\n endValue={filterValue?.endValue}\n onValueChange={onValueChange}\n onEndValueChange={onEndValueChange}\n />\n ) : (\n <div\n id={inputId}\n role=\"status\"\n aria-label={msg.filter.emptyValue(columnLabels.get(filter.id) ?? filter.id)}\n aria-live=\"polite\"\n className=\"h-8 w-full rounded border bg-transparent\"\n />\n )}\n </div>\n <Button\n aria-controls={filterItemId}\n aria-label={msg.filter.remove}\n variant=\"outline\"\n size=\"icon\"\n className=\"size-8 rounded\"\n onClick={() => onFilterRemove(filter.id)}\n >\n <Trash2 aria-hidden=\"true\" />\n </Button>\n <SortableItemHandle asChild>\n <Button aria-label={msg.filter.drag} variant=\"outline\" size=\"icon\" className=\"size-8 rounded\">\n <GripVertical aria-hidden=\"true\" />\n </Button>\n </SortableItemHandle>\n </div>\n </SortableItem>\n );\n}\n\ninterface DataGridFilterInputProps<TData> {\n variant: string;\n operator: FilterOperator;\n dir: \"ltr\" | \"rtl\";\n placeholder?: string;\n value: string | number | string[] | undefined;\n endValue?: string | number;\n column: Column<TData>;\n inputId: string;\n onValueChange: (value: string | number | string[] | undefined) => void;\n onEndValueChange?: (value: string | number | string[] | undefined) => void;\n}\n\nfunction DataGridFilterInput<TData>({\n variant,\n operator,\n dir,\n placeholder = msg.filter.valuePlaceholder,\n value,\n endValue,\n column,\n inputId,\n onValueChange,\n onEndValueChange\n}: DataGridFilterInputProps<TData>) {\n const [showValueSelector, setShowValueSelector] = React.useState(false);\n const [localValue, setLocalValue] = React.useState(value);\n const [localEndValue, setLocalEndValue] = React.useState(endValue);\n\n const debouncedOnChange = useDebouncedCallback((newValue: string | number | string[] | undefined) => {\n onValueChange(newValue);\n }, FILTER_DEBOUNCE_MS);\n\n const debouncedOnEndValueChange = useDebouncedCallback((newValue: string | number | string[] | undefined) => {\n onEndValueChange?.(newValue);\n }, FILTER_DEBOUNCE_MS);\n\n const cellVariant = column.columnDef.meta?.cell;\n\n const selectOptions = React.useMemo(() => {\n return cellVariant?.variant === \"select\" || cellVariant?.variant === \"multi-select\" ? cellVariant.options : [];\n }, [cellVariant]);\n\n const isBetween = operator === \"isBetween\";\n\n if (variant === \"number\") {\n if (isBetween) {\n return (\n <div className=\"flex gap-2\">\n <Input\n id={inputId}\n type=\"number\"\n inputMode=\"numeric\"\n placeholder={msg.filter.rangeStart}\n aria-label={msg.filter.rangeStart}\n value={(localValue as number | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : Number(val);\n setLocalValue(newValue);\n debouncedOnChange(newValue);\n }}\n className=\"h-8 w-full flex-1 rounded\"\n />\n <Input\n id={`${inputId}-end`}\n type=\"number\"\n inputMode=\"numeric\"\n placeholder={msg.filter.rangeEnd}\n aria-label={msg.filter.rangeEnd}\n value={(localEndValue as number | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : Number(val);\n setLocalEndValue(newValue);\n debouncedOnEndValueChange(newValue);\n }}\n className=\"h-8 w-full flex-1 rounded\"\n />\n </div>\n );\n }\n\n return (\n <Input\n id={inputId}\n type=\"number\"\n inputMode=\"numeric\"\n placeholder={placeholder}\n aria-label={placeholder}\n value={(localValue as number | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : Number(val);\n setLocalValue(newValue);\n debouncedOnChange(newValue);\n }}\n className=\"h-8 w-full rounded\"\n />\n );\n }\n\n if (variant === \"date\") {\n const inputListboxId = `${inputId}-listbox`;\n\n if (isBetween) {\n const startDate = localValue && typeof localValue === \"string\" ? new Date(localValue) : undefined;\n const endDate = localEndValue && typeof localEndValue === \"string\" ? new Date(localEndValue) : undefined;\n\n const isSameDate = startDate && endDate && startDate.toDateString() === endDate.toDateString();\n\n const displayValue =\n startDate && endDate && !isSameDate\n ? `${formatDate(startDate)} - ${formatDate(endDate)}`\n : startDate\n ? formatDate(startDate)\n : msg.filter.pickRange;\n\n return (\n <Popover open={showValueSelector} onOpenChange={setShowValueSelector}>\n <PopoverTrigger asChild>\n <Button\n id={inputId}\n aria-controls={inputListboxId}\n dir={dir}\n variant=\"outline\"\n className={cn(\n \"h-8 w-full justify-start gap-2 rounded font-normal\",\n !startDate && \"text-muted-foreground\"\n )}\n >\n <CalendarIcon aria-hidden=\"true\" />\n <span className=\"truncate\">{displayValue}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent id={inputListboxId} dir={dir} align=\"start\" className=\"w-auto p-0\">\n <Calendar\n mode=\"range\"\n locale={vi}\n autoFocus\n selected={startDate ? { from: startDate, to: endDate } : undefined}\n onSelect={(range) => {\n const fromValue = range?.from ? range.from.toISOString() : undefined;\n const toValue = range?.to ? range.to.toISOString() : undefined;\n setLocalValue(fromValue);\n setLocalEndValue(toValue);\n onValueChange(fromValue);\n onEndValueChange?.(toValue);\n }}\n />\n </PopoverContent>\n </Popover>\n );\n }\n\n const dateValue = localValue && typeof localValue === \"string\" ? new Date(localValue) : undefined;\n\n return (\n <Popover open={showValueSelector} onOpenChange={setShowValueSelector}>\n <PopoverTrigger asChild>\n <Button\n id={inputId}\n aria-controls={inputListboxId}\n dir={dir}\n variant=\"outline\"\n className={cn(\"h-8 w-full justify-start gap-2 rounded font-normal\", !dateValue && \"text-muted-foreground\")}\n >\n <CalendarIcon aria-hidden=\"true\" />\n <span className=\"truncate\">{dateValue ? formatDate(dateValue) : msg.filter.pickDate}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent id={inputListboxId} dir={dir} align=\"start\" className=\"w-auto p-0\">\n <Calendar\n mode=\"single\"\n locale={vi}\n autoFocus\n selected={dateValue}\n onSelect={(date) => {\n if (!date) return;\n const newValue = date.toISOString();\n setLocalValue(newValue);\n onValueChange(newValue);\n setShowValueSelector(false);\n }}\n />\n </PopoverContent>\n </Popover>\n );\n }\n\n const isSelectVariant = variant === \"select\" || variant === \"multi-select\";\n const isMultiValueOperator = operator === \"isAnyOf\" || operator === \"isNoneOf\";\n\n if (isSelectVariant && selectOptions.length > 0) {\n const inputListboxId = `${inputId}-listbox`;\n\n if (isMultiValueOperator) {\n const selectedValues = Array.isArray(value) ? value : [];\n const selectedOptions = selectOptions.filter((option) => selectedValues.includes(option.value));\n\n const selectedOptionsWithIcons = selectedOptions.filter((selectedOption) => selectedOption.icon);\n\n return (\n <Popover open={showValueSelector} onOpenChange={setShowValueSelector}>\n <PopoverTrigger asChild>\n <Button\n id={inputId}\n aria-controls={inputListboxId}\n dir={dir}\n variant=\"outline\"\n className=\"h-8 w-full justify-start rounded font-normal\"\n >\n {selectedOptions.length === 0 ? (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n ) : (\n <>\n {selectedOptionsWithIcons.length > 0 && (\n <div className=\"flex items-center -space-x-2 rtl:space-x-reverse\">\n {selectedOptionsWithIcons.map(\n (selectedOption) =>\n selectedOption.icon && (\n <div key={selectedOption.value} className=\"rounded-full border bg-background p-0.5\">\n <selectedOption.icon className=\"size-3.5\" />\n </div>\n )\n )}\n </div>\n )}\n <span className=\"truncate\">\n {selectedOptions.length > 1\n ? msg.filter.selectedCount(selectedOptions.length)\n : selectedOptions[0]?.label}\n </span>\n </>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent id={inputListboxId} dir={dir} align=\"start\" className=\"w-48 p-0\">\n <Command>\n <CommandInput placeholder={msg.filter.optionPlaceholder} aria-label={msg.filter.optionPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.filter.optionEmpty}</CommandEmpty>\n <CommandGroup>\n {selectOptions.map((option) => {\n const isSelected = selectedValues.includes(option.value);\n return (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={() => {\n const newValues = isSelected\n ? selectedValues.filter((v) => v !== option.value)\n : [...selectedValues, option.value];\n onValueChange(newValues.length > 0 ? newValues : undefined);\n }}\n >\n {option.icon && <option.icon />}\n <span className=\"truncate\">{option.label}</span>\n {option.count && <span className=\"ms-auto font-mono text-xs\">{option.count}</span>}\n <Check className={cn(\"ms-auto\", isSelected ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n }\n\n const selectedOption = selectOptions.find((opt) => opt.value === (value as string));\n\n return (\n <Popover open={showValueSelector} onOpenChange={setShowValueSelector}>\n <PopoverTrigger asChild>\n <Button\n id={inputId}\n aria-controls={inputListboxId}\n dir={dir}\n variant=\"outline\"\n className=\"h-8 w-full justify-start rounded font-normal\"\n >\n {selectedOption ? (\n <>\n {selectedOption.icon && <selectedOption.icon />}\n <span className=\"truncate\">{selectedOption.label}</span>\n </>\n ) : (\n <span className=\"text-muted-foreground\">{placeholder}</span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent id={inputListboxId} dir={dir} align=\"start\" className=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder={msg.filter.optionPlaceholder} aria-label={msg.filter.optionPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.filter.optionEmpty}</CommandEmpty>\n <CommandGroup>\n {selectOptions.map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n onSelect={() => {\n onValueChange(option.value);\n setShowValueSelector(false);\n }}\n >\n {option.icon && <option.icon />}\n <span className=\"truncate\">{option.label}</span>\n {option.count && <span className=\"ms-auto font-mono text-xs\">{option.count}</span>}\n <Check className={cn(\"ms-auto\", value === option.value ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n }\n\n if (isBetween) {\n return (\n <div className=\"flex gap-2\">\n <Input\n id={inputId}\n type=\"text\"\n placeholder={msg.filter.rangeStart}\n aria-label={msg.filter.rangeStart}\n className=\"h-8 w-full flex-1 rounded\"\n value={(localValue as string | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : val;\n setLocalValue(newValue);\n debouncedOnChange(newValue);\n }}\n />\n <Input\n id={`${inputId}-end`}\n type=\"text\"\n placeholder={msg.filter.rangeEnd}\n aria-label={msg.filter.rangeEnd}\n className=\"h-8 w-full flex-1 rounded\"\n value={(localEndValue as string | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : val;\n setLocalEndValue(newValue);\n debouncedOnEndValueChange(newValue);\n }}\n />\n </div>\n );\n }\n\n return (\n <Input\n id={inputId}\n type=\"text\"\n placeholder={placeholder}\n aria-label={placeholder}\n className=\"h-8 w-full rounded\"\n value={(localValue as string | undefined) ?? \"\"}\n onChange={(event) => {\n const val = event.target.value;\n const newValue = val === \"\" ? undefined : val;\n setLocalValue(newValue);\n debouncedOnChange(newValue);\n }}\n />\n );\n}\n"],"mappings":"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","names":["column","selectedOption"]}
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+
3
+ interface DataGridKeyboardShortcutsProps {
4
+ /** Hiện phím tắt của ô tìm kiếm (bật cùng `enableSearch` của lưới) */
5
+ enableSearch?: boolean;
6
+ enableUndoRedo?: boolean;
7
+ enablePaste?: boolean;
8
+ enableRowAdd?: boolean;
9
+ enableRowsDelete?: boolean;
10
+ /** Ẩn nút mở trên thanh công cụ — vẫn mở được bằng Ctrl+/ */
11
+ hideTrigger?: boolean;
12
+ }
13
+ /**
14
+ * Hộp thoại liệt kê phím tắt của lưới (mở bằng Ctrl/⌘ + `/`, hoặc nút trên thanh công cụ).
15
+ * Danh sách hiển thị theo đúng những tính năng đang bật, nên truyền các cờ giống lưới.
16
+ */
17
+ declare const DataGridKeyboardShortcuts: React.MemoExoticComponent<typeof DataGridKeyboardShortcutsImpl>;
18
+ declare function DataGridKeyboardShortcutsImpl({ enableSearch, enableUndoRedo, enablePaste, enableRowAdd, enableRowsDelete, hideTrigger }: DataGridKeyboardShortcutsProps): React.JSX.Element;
19
+
20
+ export { DataGridKeyboardShortcuts };
@@ -0,0 +1,227 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useDirection } from "@radix-ui/react-direction";
4
+ import { Keyboard, SearchIcon } from "lucide-react";
5
+ import * as React from "react";
6
+ import { Button } from "../components/ui/button.js";
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ DialogTrigger
14
+ } from "../components/ui/dialog.js";
15
+ import { Input } from "../components/ui/input.js";
16
+ import { Kbd, KbdGroup } from "../components/ui/kbd.js";
17
+ import { Separator } from "../components/ui/separator.js";
18
+ import { msg } from "./messages.js";
19
+ const SHORTCUT_KEY = "/";
20
+ const DataGridKeyboardShortcuts = React.memo(DataGridKeyboardShortcutsImpl, (prev, next) => {
21
+ return prev.enableSearch === next.enableSearch && prev.enableUndoRedo === next.enableUndoRedo && prev.enablePaste === next.enablePaste && prev.enableRowAdd === next.enableRowAdd && prev.enableRowsDelete === next.enableRowsDelete && prev.hideTrigger === next.hideTrigger;
22
+ });
23
+ function DataGridKeyboardShortcutsImpl({
24
+ enableSearch = false,
25
+ enableUndoRedo = false,
26
+ enablePaste = false,
27
+ enableRowAdd = false,
28
+ enableRowsDelete = false,
29
+ hideTrigger = false
30
+ }) {
31
+ const dir = useDirection();
32
+ const [open, setOpen] = React.useState(false);
33
+ const [input, setInput] = React.useState("");
34
+ const inputRef = React.useRef(null);
35
+ const isMac = typeof navigator !== "undefined" ? /Mac|iPhone|iPad|iPod/.test(navigator.userAgent) : false;
36
+ const modKey = isMac ? "\u2318" : "Ctrl";
37
+ const altKey = isMac ? "\u2325" : "Alt";
38
+ const onOpenChange = React.useCallback((isOpen) => {
39
+ setOpen(isOpen);
40
+ if (!isOpen) {
41
+ setInput("");
42
+ }
43
+ }, []);
44
+ const onOpenAutoFocus = React.useCallback((event) => {
45
+ event.preventDefault();
46
+ inputRef.current?.focus();
47
+ }, []);
48
+ const onInputChange = React.useCallback((event) => {
49
+ setInput(event.target.value);
50
+ }, []);
51
+ const shortcutGroups = React.useMemo(
52
+ () => [
53
+ {
54
+ title: msg.shortcuts.groups.navigation,
55
+ shortcuts: [
56
+ { keys: ["\u2191", "\u2193", "\u2190", "\u2192"], description: msg.shortcuts.navigation.move },
57
+ { keys: ["Tab"], description: msg.shortcuts.navigation.nextCell },
58
+ { keys: ["Shift", "Tab"], description: msg.shortcuts.navigation.prevCell },
59
+ { keys: ["Home"], description: msg.shortcuts.navigation.firstColumn },
60
+ { keys: ["End"], description: msg.shortcuts.navigation.lastColumn },
61
+ { keys: [modKey, "\u2191"], description: msg.shortcuts.navigation.firstRowSameColumn },
62
+ { keys: [modKey, "\u2193"], description: msg.shortcuts.navigation.lastRowSameColumn },
63
+ { keys: [modKey, "\u2190"], description: msg.shortcuts.navigation.firstColumnSameRow },
64
+ { keys: [modKey, "\u2192"], description: msg.shortcuts.navigation.lastColumnSameRow },
65
+ { keys: [modKey, "Home"], description: msg.shortcuts.navigation.firstCell },
66
+ { keys: [modKey, "End"], description: msg.shortcuts.navigation.lastCell },
67
+ { keys: ["PgUp"], description: msg.shortcuts.navigation.pageUp },
68
+ { keys: ["PgDn"], description: msg.shortcuts.navigation.pageDown },
69
+ { keys: [altKey, "\u2191"], description: msg.shortcuts.navigation.scrollUp },
70
+ { keys: [altKey, "\u2193"], description: msg.shortcuts.navigation.scrollDown },
71
+ { keys: [altKey, "PgUp"], description: msg.shortcuts.navigation.scrollLeft },
72
+ { keys: [altKey, "PgDn"], description: msg.shortcuts.navigation.scrollRight }
73
+ ]
74
+ },
75
+ {
76
+ title: msg.shortcuts.groups.selection,
77
+ shortcuts: [
78
+ { keys: ["Shift", "\u2191\u2193\u2190\u2192"], description: msg.shortcuts.selection.extend },
79
+ { keys: [modKey, "Shift", "\u2191"], description: msg.shortcuts.selection.toTop },
80
+ { keys: [modKey, "Shift", "\u2193"], description: msg.shortcuts.selection.toBottom },
81
+ { keys: [modKey, "Shift", "\u2190"], description: msg.shortcuts.selection.toFirstColumn },
82
+ { keys: [modKey, "Shift", "\u2192"], description: msg.shortcuts.selection.toLastColumn },
83
+ { keys: [modKey, "A"], description: msg.shortcuts.selection.all },
84
+ { keys: [modKey, msg.shortcuts.keys.click], description: msg.shortcuts.selection.toggle },
85
+ { keys: ["Shift", msg.shortcuts.keys.click], description: msg.shortcuts.selection.range },
86
+ { keys: ["Esc"], description: msg.shortcuts.selection.clear }
87
+ ]
88
+ },
89
+ {
90
+ title: msg.shortcuts.groups.editing,
91
+ shortcuts: [
92
+ { keys: ["Enter"], description: msg.shortcuts.editing.start },
93
+ { keys: ["F2"], description: msg.shortcuts.editing.start },
94
+ { keys: [msg.shortcuts.keys.doubleClick], description: msg.shortcuts.editing.start },
95
+ ...enableRowAdd ? [{ keys: ["Shift", "Enter"], description: msg.shortcuts.editing.insertRow }] : [],
96
+ { keys: [modKey, "C"], description: msg.shortcuts.editing.copy },
97
+ { keys: [modKey, "X"], description: msg.shortcuts.editing.cut },
98
+ ...enablePaste ? [{ keys: [modKey, "V"], description: msg.shortcuts.editing.paste }] : [],
99
+ { keys: ["Delete"], description: msg.shortcuts.editing.clear },
100
+ { keys: ["Backspace"], description: msg.shortcuts.editing.clear },
101
+ ...enableRowsDelete ? [
102
+ { keys: [modKey, "Backspace"], description: msg.shortcuts.editing.deleteRows },
103
+ { keys: [modKey, "Delete"], description: msg.shortcuts.editing.deleteRows }
104
+ ] : [],
105
+ ...enableUndoRedo ? [
106
+ { keys: [modKey, "Z"], description: msg.shortcuts.editing.undo },
107
+ { keys: [modKey, "Shift", "Z"], description: msg.shortcuts.editing.redo }
108
+ ] : []
109
+ ]
110
+ },
111
+ ...enableSearch ? [
112
+ {
113
+ title: msg.shortcuts.groups.search,
114
+ shortcuts: [
115
+ { keys: [modKey, "F"], description: msg.shortcuts.search.open },
116
+ { keys: ["Enter"], description: msg.shortcuts.search.next },
117
+ { keys: ["Shift", "Enter"], description: msg.shortcuts.search.prev },
118
+ { keys: ["Esc"], description: msg.shortcuts.search.close }
119
+ ]
120
+ }
121
+ ] : [],
122
+ {
123
+ title: msg.shortcuts.groups.filtering,
124
+ shortcuts: [
125
+ { keys: [modKey, "Shift", "F"], description: msg.shortcuts.filtering.toggle },
126
+ { keys: ["Backspace"], description: msg.shortcuts.filtering.remove },
127
+ { keys: ["Delete"], description: msg.shortcuts.filtering.remove }
128
+ ]
129
+ },
130
+ {
131
+ title: msg.shortcuts.groups.sorting,
132
+ shortcuts: [
133
+ { keys: [modKey, "Shift", "S"], description: msg.shortcuts.sorting.toggle },
134
+ { keys: ["Backspace"], description: msg.shortcuts.sorting.remove },
135
+ { keys: ["Delete"], description: msg.shortcuts.sorting.remove }
136
+ ]
137
+ },
138
+ {
139
+ title: msg.shortcuts.groups.general,
140
+ shortcuts: [{ keys: [modKey, "/"], description: msg.shortcuts.general.shortcuts }]
141
+ }
142
+ ],
143
+ [modKey, altKey, enableSearch, enableUndoRedo, enablePaste, enableRowAdd, enableRowsDelete]
144
+ );
145
+ const filteredGroups = React.useMemo(() => {
146
+ if (!input.trim()) return shortcutGroups;
147
+ const query = input.toLowerCase();
148
+ return shortcutGroups.map((group) => ({
149
+ ...group,
150
+ shortcuts: group.shortcuts.filter(
151
+ (shortcut) => shortcut.description.toLowerCase().includes(query) || shortcut.keys.some((key) => key.toLowerCase().includes(query))
152
+ )
153
+ })).filter((group) => group.shortcuts.length > 0);
154
+ }, [shortcutGroups, input]);
155
+ React.useEffect(() => {
156
+ function onKeyDown(event) {
157
+ if ((event.ctrlKey || event.metaKey) && event.key === SHORTCUT_KEY) {
158
+ event.preventDefault();
159
+ setOpen(true);
160
+ }
161
+ }
162
+ window.addEventListener("keydown", onKeyDown);
163
+ return () => {
164
+ window.removeEventListener("keydown", onKeyDown);
165
+ };
166
+ }, []);
167
+ return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange, children: [
168
+ !hideTrigger && /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { "aria-label": msg.shortcuts.trigger, variant: "outline", size: "icon", className: "h-8 w-8", children: /* @__PURE__ */ jsx(Keyboard, { "aria-hidden": "true", className: "h-4 w-4 text-muted-foreground" }) }) }),
169
+ /* @__PURE__ */ jsxs(DialogContent, { dir, className: "max-w-2xl px-0", onOpenAutoFocus, children: [
170
+ /* @__PURE__ */ jsxs(DialogHeader, { className: "px-6", children: [
171
+ /* @__PURE__ */ jsx(DialogTitle, { children: msg.shortcuts.title }),
172
+ /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: msg.shortcuts.description })
173
+ ] }),
174
+ /* @__PURE__ */ jsx("div", { className: "px-6", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
175
+ /* @__PURE__ */ jsx(
176
+ SearchIcon,
177
+ {
178
+ "aria-hidden": "true",
179
+ className: "absolute start-3 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground"
180
+ }
181
+ ),
182
+ /* @__PURE__ */ jsx(
183
+ Input,
184
+ {
185
+ ref: inputRef,
186
+ placeholder: msg.shortcuts.searchPlaceholder,
187
+ "aria-label": msg.shortcuts.searchPlaceholder,
188
+ className: "h-8 ps-8",
189
+ value: input,
190
+ onChange: onInputChange
191
+ }
192
+ )
193
+ ] }) }),
194
+ /* @__PURE__ */ jsx(Separator, { className: "mx-auto w-[calc(100%-3rem)]" }),
195
+ /* @__PURE__ */ jsx("div", { className: "h-[40vh] overflow-y-auto px-6", children: filteredGroups.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 text-center", children: [
196
+ /* @__PURE__ */ jsx("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground", children: /* @__PURE__ */ jsx(SearchIcon, { "aria-hidden": "true", className: "pointer-events-none size-6" }) }),
197
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
198
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-lg tracking-tight", children: msg.shortcuts.emptyTitle }),
199
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: msg.shortcuts.emptyDescription })
200
+ ] })
201
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6", children: filteredGroups.map((shortcutGroup) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
202
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground text-sm", children: shortcutGroup.title }),
203
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-border rounded-md border", children: shortcutGroup.shortcuts.map((shortcut) => /* @__PURE__ */ jsx(
204
+ ShortcutCard,
205
+ {
206
+ keys: shortcut.keys,
207
+ description: shortcut.description
208
+ },
209
+ `${shortcut.description}-${shortcut.keys.join("+")}`
210
+ )) })
211
+ ] }, shortcutGroup.title)) }) })
212
+ ] })
213
+ ] });
214
+ }
215
+ function ShortcutCard({ keys, description }) {
216
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 px-3 py-2", children: [
217
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm", children: description }),
218
+ /* @__PURE__ */ jsx(KbdGroup, { className: "shrink-0", children: keys.map((key, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
219
+ index > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: "+" }),
220
+ /* @__PURE__ */ jsx(Kbd, { children: key })
221
+ ] }, key)) })
222
+ ] });
223
+ }
224
+ export {
225
+ DataGridKeyboardShortcuts
226
+ };
227
+ //# sourceMappingURL=data-grid-keyboard-shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/data-grid-keyboard-shortcuts.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { Keyboard, SearchIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger\n} from \"../components/ui/dialog.js\";\nimport { Input } from \"../components/ui/input.js\";\nimport { Kbd, KbdGroup } from \"../components/ui/kbd.js\";\nimport { Separator } from \"../components/ui/separator.js\";\nimport { msg } from \"./messages.js\";\n\nconst SHORTCUT_KEY = \"/\";\n\ninterface ShortcutGroup {\n title: string;\n shortcuts: Array<{\n keys: string[];\n description: string;\n }>;\n}\n\ninterface DataGridKeyboardShortcutsProps {\n /** Hiện phím tắt của ô tìm kiếm (bật cùng `enableSearch` của lưới) */\n enableSearch?: boolean;\n enableUndoRedo?: boolean;\n enablePaste?: boolean;\n enableRowAdd?: boolean;\n enableRowsDelete?: boolean;\n /** Ẩn nút mở trên thanh công cụ — vẫn mở được bằng Ctrl+/ */\n hideTrigger?: boolean;\n}\n\n/**\n * Hộp thoại liệt kê phím tắt của lưới (mở bằng Ctrl/⌘ + `/`, hoặc nút trên thanh công cụ).\n * Danh sách hiển thị theo đúng những tính năng đang bật, nên truyền các cờ giống lưới.\n */\nexport const DataGridKeyboardShortcuts = React.memo(DataGridKeyboardShortcutsImpl, (prev, next) => {\n return (\n prev.enableSearch === next.enableSearch &&\n prev.enableUndoRedo === next.enableUndoRedo &&\n prev.enablePaste === next.enablePaste &&\n prev.enableRowAdd === next.enableRowAdd &&\n prev.enableRowsDelete === next.enableRowsDelete &&\n prev.hideTrigger === next.hideTrigger\n );\n});\n\nfunction DataGridKeyboardShortcutsImpl({\n enableSearch = false,\n enableUndoRedo = false,\n enablePaste = false,\n enableRowAdd = false,\n enableRowsDelete = false,\n hideTrigger = false\n}: DataGridKeyboardShortcutsProps) {\n const dir = useDirection();\n const [open, setOpen] = React.useState(false);\n const [input, setInput] = React.useState(\"\");\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n const isMac = typeof navigator !== \"undefined\" ? /Mac|iPhone|iPad|iPod/.test(navigator.userAgent) : false;\n\n const modKey = isMac ? \"⌘\" : \"Ctrl\";\n const altKey = isMac ? \"⌥\" : \"Alt\";\n\n const onOpenChange = React.useCallback((isOpen: boolean) => {\n setOpen(isOpen);\n if (!isOpen) {\n setInput(\"\");\n }\n }, []);\n\n const onOpenAutoFocus = React.useCallback((event: Event) => {\n event.preventDefault();\n inputRef.current?.focus();\n }, []);\n\n const onInputChange = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n setInput(event.target.value);\n }, []);\n\n const shortcutGroups: ShortcutGroup[] = React.useMemo(\n () => [\n {\n title: msg.shortcuts.groups.navigation,\n shortcuts: [\n { keys: [\"↑\", \"↓\", \"←\", \"→\"], description: msg.shortcuts.navigation.move },\n { keys: [\"Tab\"], description: msg.shortcuts.navigation.nextCell },\n { keys: [\"Shift\", \"Tab\"], description: msg.shortcuts.navigation.prevCell },\n { keys: [\"Home\"], description: msg.shortcuts.navigation.firstColumn },\n { keys: [\"End\"], description: msg.shortcuts.navigation.lastColumn },\n { keys: [modKey, \"↑\"], description: msg.shortcuts.navigation.firstRowSameColumn },\n { keys: [modKey, \"↓\"], description: msg.shortcuts.navigation.lastRowSameColumn },\n { keys: [modKey, \"←\"], description: msg.shortcuts.navigation.firstColumnSameRow },\n { keys: [modKey, \"→\"], description: msg.shortcuts.navigation.lastColumnSameRow },\n { keys: [modKey, \"Home\"], description: msg.shortcuts.navigation.firstCell },\n { keys: [modKey, \"End\"], description: msg.shortcuts.navigation.lastCell },\n { keys: [\"PgUp\"], description: msg.shortcuts.navigation.pageUp },\n { keys: [\"PgDn\"], description: msg.shortcuts.navigation.pageDown },\n { keys: [altKey, \"↑\"], description: msg.shortcuts.navigation.scrollUp },\n { keys: [altKey, \"↓\"], description: msg.shortcuts.navigation.scrollDown },\n { keys: [altKey, \"PgUp\"], description: msg.shortcuts.navigation.scrollLeft },\n { keys: [altKey, \"PgDn\"], description: msg.shortcuts.navigation.scrollRight }\n ]\n },\n {\n title: msg.shortcuts.groups.selection,\n shortcuts: [\n { keys: [\"Shift\", \"↑↓←→\"], description: msg.shortcuts.selection.extend },\n { keys: [modKey, \"Shift\", \"↑\"], description: msg.shortcuts.selection.toTop },\n { keys: [modKey, \"Shift\", \"↓\"], description: msg.shortcuts.selection.toBottom },\n { keys: [modKey, \"Shift\", \"←\"], description: msg.shortcuts.selection.toFirstColumn },\n { keys: [modKey, \"Shift\", \"→\"], description: msg.shortcuts.selection.toLastColumn },\n { keys: [modKey, \"A\"], description: msg.shortcuts.selection.all },\n { keys: [modKey, msg.shortcuts.keys.click], description: msg.shortcuts.selection.toggle },\n { keys: [\"Shift\", msg.shortcuts.keys.click], description: msg.shortcuts.selection.range },\n { keys: [\"Esc\"], description: msg.shortcuts.selection.clear }\n ]\n },\n {\n title: msg.shortcuts.groups.editing,\n shortcuts: [\n { keys: [\"Enter\"], description: msg.shortcuts.editing.start },\n { keys: [\"F2\"], description: msg.shortcuts.editing.start },\n { keys: [msg.shortcuts.keys.doubleClick], description: msg.shortcuts.editing.start },\n ...(enableRowAdd ? [{ keys: [\"Shift\", \"Enter\"], description: msg.shortcuts.editing.insertRow }] : []),\n { keys: [modKey, \"C\"], description: msg.shortcuts.editing.copy },\n { keys: [modKey, \"X\"], description: msg.shortcuts.editing.cut },\n ...(enablePaste ? [{ keys: [modKey, \"V\"], description: msg.shortcuts.editing.paste }] : []),\n { keys: [\"Delete\"], description: msg.shortcuts.editing.clear },\n { keys: [\"Backspace\"], description: msg.shortcuts.editing.clear },\n ...(enableRowsDelete\n ? [\n { keys: [modKey, \"Backspace\"], description: msg.shortcuts.editing.deleteRows },\n { keys: [modKey, \"Delete\"], description: msg.shortcuts.editing.deleteRows }\n ]\n : []),\n ...(enableUndoRedo\n ? [\n { keys: [modKey, \"Z\"], description: msg.shortcuts.editing.undo },\n { keys: [modKey, \"Shift\", \"Z\"], description: msg.shortcuts.editing.redo }\n ]\n : [])\n ]\n },\n ...(enableSearch\n ? [\n {\n title: msg.shortcuts.groups.search,\n shortcuts: [\n { keys: [modKey, \"F\"], description: msg.shortcuts.search.open },\n { keys: [\"Enter\"], description: msg.shortcuts.search.next },\n { keys: [\"Shift\", \"Enter\"], description: msg.shortcuts.search.prev },\n { keys: [\"Esc\"], description: msg.shortcuts.search.close }\n ]\n }\n ]\n : []),\n {\n title: msg.shortcuts.groups.filtering,\n shortcuts: [\n { keys: [modKey, \"Shift\", \"F\"], description: msg.shortcuts.filtering.toggle },\n { keys: [\"Backspace\"], description: msg.shortcuts.filtering.remove },\n { keys: [\"Delete\"], description: msg.shortcuts.filtering.remove }\n ]\n },\n {\n title: msg.shortcuts.groups.sorting,\n shortcuts: [\n { keys: [modKey, \"Shift\", \"S\"], description: msg.shortcuts.sorting.toggle },\n { keys: [\"Backspace\"], description: msg.shortcuts.sorting.remove },\n { keys: [\"Delete\"], description: msg.shortcuts.sorting.remove }\n ]\n },\n {\n title: msg.shortcuts.groups.general,\n shortcuts: [{ keys: [modKey, \"/\"], description: msg.shortcuts.general.shortcuts }]\n }\n ],\n [modKey, altKey, enableSearch, enableUndoRedo, enablePaste, enableRowAdd, enableRowsDelete]\n );\n\n const filteredGroups = React.useMemo(() => {\n if (!input.trim()) return shortcutGroups;\n\n const query = input.toLowerCase();\n return shortcutGroups\n .map((group) => ({\n ...group,\n shortcuts: group.shortcuts.filter(\n (shortcut) =>\n shortcut.description.toLowerCase().includes(query) ||\n shortcut.keys.some((key) => key.toLowerCase().includes(query))\n )\n }))\n .filter((group) => group.shortcuts.length > 0);\n }, [shortcutGroups, input]);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if ((event.ctrlKey || event.metaKey) && event.key === SHORTCUT_KEY) {\n event.preventDefault();\n setOpen(true);\n }\n }\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, []);\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n {!hideTrigger && (\n <DialogTrigger asChild>\n <Button aria-label={msg.shortcuts.trigger} variant=\"outline\" size=\"icon\" className=\"h-8 w-8\">\n <Keyboard aria-hidden=\"true\" className=\"h-4 w-4 text-muted-foreground\" />\n </Button>\n </DialogTrigger>\n )}\n <DialogContent dir={dir} className=\"max-w-2xl px-0\" onOpenAutoFocus={onOpenAutoFocus}>\n <DialogHeader className=\"px-6\">\n <DialogTitle>{msg.shortcuts.title}</DialogTitle>\n <DialogDescription className=\"sr-only\">{msg.shortcuts.description}</DialogDescription>\n </DialogHeader>\n <div className=\"px-6\">\n <div className=\"relative\">\n <SearchIcon\n aria-hidden=\"true\"\n className=\"absolute start-3 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n ref={inputRef}\n placeholder={msg.shortcuts.searchPlaceholder}\n aria-label={msg.shortcuts.searchPlaceholder}\n className=\"h-8 ps-8\"\n value={input}\n onChange={onInputChange}\n />\n </div>\n </div>\n <Separator className=\"mx-auto w-[calc(100%-3rem)]\" />\n <div className=\"h-[40vh] overflow-y-auto px-6\">\n {filteredGroups.length === 0 ? (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 text-center\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground\">\n <SearchIcon aria-hidden=\"true\" className=\"pointer-events-none size-6\" />\n </div>\n <div className=\"flex flex-col gap-1\">\n <div className=\"font-medium text-lg tracking-tight\">{msg.shortcuts.emptyTitle}</div>\n <p className=\"text-muted-foreground text-sm\">{msg.shortcuts.emptyDescription}</p>\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col gap-6\">\n {filteredGroups.map((shortcutGroup) => (\n <div key={shortcutGroup.title} className=\"flex flex-col gap-2\">\n <h3 className=\"font-semibold text-foreground text-sm\">{shortcutGroup.title}</h3>\n <div className=\"divide-y divide-border rounded-md border\">\n {shortcutGroup.shortcuts.map((shortcut) => (\n <ShortcutCard\n key={`${shortcut.description}-${shortcut.keys.join(\"+\")}`}\n keys={shortcut.keys}\n description={shortcut.description}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ShortcutCard({ keys, description }: ShortcutGroup[\"shortcuts\"][number]) {\n return (\n <div className=\"flex items-center gap-4 px-3 py-2\">\n <span className=\"flex-1 text-sm\">{description}</span>\n <KbdGroup className=\"shrink-0\">\n {keys.map((key, index) => (\n <React.Fragment key={key}>\n {index > 0 && <span className=\"text-muted-foreground text-xs\">+</span>}\n <Kbd>{key}</Kbd>\n </React.Fragment>\n ))}\n </KbdGroup>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,11 @@
1
+ import { TableMeta } from '@tanstack/react-table';
2
+ import * as React from 'react';
3
+ import { PasteDialogState } from './types.js';
4
+
5
+ interface DataGridPasteDialogProps<TData> {
6
+ tableMeta: TableMeta<TData>;
7
+ pasteDialog: PasteDialogState;
8
+ }
9
+ declare function DataGridPasteDialog<TData>({ tableMeta, pasteDialog }: DataGridPasteDialogProps<TData>): React.JSX.Element | null;
10
+
11
+ export { DataGridPasteDialog };
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Button } from "../components/ui/button.js";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogHeader,
11
+ DialogTitle
12
+ } from "../components/ui/dialog.js";
13
+ import { cn } from "../lib/cn.js";
14
+ import { msg } from "./messages.js";
15
+ import { useAsRef } from "./use-as-ref.js";
16
+ function DataGridPasteDialog({ tableMeta, pasteDialog }) {
17
+ const onPasteDialogOpenChange = tableMeta?.onPasteDialogOpenChange;
18
+ const onCellsPaste = tableMeta?.onCellsPaste;
19
+ if (!pasteDialog.open) return null;
20
+ return /* @__PURE__ */ jsx(
21
+ PasteDialog,
22
+ {
23
+ pasteDialog,
24
+ onPasteDialogOpenChange,
25
+ onCellsPaste
26
+ }
27
+ );
28
+ }
29
+ const PasteDialog = React.memo(PasteDialogImpl, (prev, next) => {
30
+ if (prev.pasteDialog.open !== next.pasteDialog.open) return false;
31
+ if (!next.pasteDialog.open) return true;
32
+ if (prev.pasteDialog.rowsNeeded !== next.pasteDialog.rowsNeeded) return false;
33
+ return true;
34
+ });
35
+ function PasteDialogImpl({ pasteDialog, onPasteDialogOpenChange, onCellsPaste }) {
36
+ const propsRef = useAsRef({
37
+ onPasteDialogOpenChange,
38
+ onCellsPaste
39
+ });
40
+ const expandRadioRef = React.useRef(null);
41
+ const onOpenChange = React.useCallback(
42
+ (open) => {
43
+ propsRef.current.onPasteDialogOpenChange?.(open);
44
+ },
45
+ [propsRef]
46
+ );
47
+ const onCancel = React.useCallback(() => {
48
+ propsRef.current.onPasteDialogOpenChange?.(false);
49
+ }, [propsRef]);
50
+ const onContinue = React.useCallback(() => {
51
+ propsRef.current.onCellsPaste?.(expandRadioRef.current?.checked ?? false);
52
+ }, [propsRef]);
53
+ return /* @__PURE__ */ jsx(Dialog, { open: pasteDialog.open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { "data-grid-popover": "", children: [
54
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
55
+ /* @__PURE__ */ jsx(DialogTitle, { children: msg.pasteDialog.title }),
56
+ /* @__PURE__ */ jsx(DialogDescription, { children: msg.pasteDialog.description(pasteDialog.rowsNeeded) })
57
+ ] }),
58
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 py-1", children: [
59
+ /* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-start gap-3", children: [
60
+ /* @__PURE__ */ jsx(RadioItem, { ref: expandRadioRef, name: "expand-option", value: "expand", defaultChecked: true }),
61
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
62
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm leading-none", children: msg.pasteDialog.expandTitle }),
63
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: msg.pasteDialog.expandDescription(pasteDialog.rowsNeeded) })
64
+ ] })
65
+ ] }),
66
+ /* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-start gap-3", children: [
67
+ /* @__PURE__ */ jsx(RadioItem, { name: "expand-option", value: "no-expand" }),
68
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
69
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm leading-none", children: msg.pasteDialog.keepTitle }),
70
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: msg.pasteDialog.keepDescription })
71
+ ] })
72
+ ] })
73
+ ] }),
74
+ /* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2", children: [
75
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onCancel, children: msg.pasteDialog.cancel }),
76
+ /* @__PURE__ */ jsx(Button, { onClick: onContinue, children: msg.pasteDialog.confirm })
77
+ ] })
78
+ ] }) });
79
+ }
80
+ function RadioItem({ className, ...props }) {
81
+ return /* @__PURE__ */ jsx(
82
+ "input",
83
+ {
84
+ type: "radio",
85
+ className: cn(
86
+ // Cùng bộ token với `RadioGroupItem` của gói (`--choice-edge` cho viền nghỉ,
87
+ // `--control-on` cho viền + chấm khi chọn) — đừng quay lại `--primary`/`--ring`: đó là
88
+ // bậc tô NỀN, đem vẽ NÉT thì ở light chỉ 1,73:1.
89
+ "relative mt-0.5 size-4 shrink-0 appearance-none rounded-full border border-choice-edge outline-none transition-colors dark:bg-input-fill",
90
+ "hover:border-choice-edge-strong checked:border-control-on",
91
+ "focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
92
+ "disabled:cursor-not-allowed disabled:opacity-50",
93
+ "checked:before:absolute checked:before:start-1/2 checked:before:top-1/2 checked:before:size-2 checked:before:-translate-x-1/2 checked:before:-translate-y-1/2 checked:before:rounded-full checked:before:bg-control-on checked:before:content-['']",
94
+ className
95
+ ),
96
+ ...props
97
+ }
98
+ );
99
+ }
100
+ export {
101
+ DataGridPasteDialog
102
+ };
103
+ //# sourceMappingURL=data-grid-paste-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/data-grid-paste-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport type { TableMeta } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle\n} from \"../components/ui/dialog.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { msg } from \"./messages.js\";\nimport type { PasteDialogState } from \"./types.js\";\nimport { useAsRef } from \"./use-as-ref.js\";\n\ninterface DataGridPasteDialogProps<TData> {\n tableMeta: TableMeta<TData>;\n pasteDialog: PasteDialogState;\n}\n\nexport function DataGridPasteDialog<TData>({ tableMeta, pasteDialog }: DataGridPasteDialogProps<TData>) {\n const onPasteDialogOpenChange = tableMeta?.onPasteDialogOpenChange;\n const onCellsPaste = tableMeta?.onCellsPaste;\n\n if (!pasteDialog.open) return null;\n\n return (\n <PasteDialog\n pasteDialog={pasteDialog}\n onPasteDialogOpenChange={onPasteDialogOpenChange}\n onCellsPaste={onCellsPaste}\n />\n );\n}\n\ninterface PasteDialogProps\n extends Pick<TableMeta<unknown>, \"onPasteDialogOpenChange\" | \"onCellsPaste\">,\n Required<Pick<TableMeta<unknown>, \"pasteDialog\">> {}\n\nconst PasteDialog = React.memo(PasteDialogImpl, (prev, next) => {\n if (prev.pasteDialog.open !== next.pasteDialog.open) return false;\n if (!next.pasteDialog.open) return true;\n if (prev.pasteDialog.rowsNeeded !== next.pasteDialog.rowsNeeded) return false;\n\n return true;\n});\n\nfunction PasteDialogImpl({ pasteDialog, onPasteDialogOpenChange, onCellsPaste }: PasteDialogProps) {\n const propsRef = useAsRef({\n onPasteDialogOpenChange,\n onCellsPaste\n });\n\n const expandRadioRef = React.useRef<HTMLInputElement | null>(null);\n\n const onOpenChange = React.useCallback(\n (open: boolean) => {\n propsRef.current.onPasteDialogOpenChange?.(open);\n },\n [propsRef]\n );\n\n const onCancel = React.useCallback(() => {\n propsRef.current.onPasteDialogOpenChange?.(false);\n }, [propsRef]);\n\n const onContinue = React.useCallback(() => {\n propsRef.current.onCellsPaste?.(expandRadioRef.current?.checked ?? false);\n }, [propsRef]);\n\n return (\n <Dialog open={pasteDialog.open} onOpenChange={onOpenChange}>\n <DialogContent data-grid-popover=\"\">\n <DialogHeader>\n <DialogTitle>{msg.pasteDialog.title}</DialogTitle>\n <DialogDescription>{msg.pasteDialog.description(pasteDialog.rowsNeeded)}</DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-3 py-1\">\n {/* biome-ignore lint/a11y/noLabelWithoutControl: <RadioItem> bọc sẵn <input type=\"radio\"> bên trong */}\n <label className=\"flex cursor-pointer items-start gap-3\">\n <RadioItem ref={expandRadioRef} name=\"expand-option\" value=\"expand\" defaultChecked />\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium text-sm leading-none\">{msg.pasteDialog.expandTitle}</span>\n <span className=\"text-muted-foreground text-sm\">\n {msg.pasteDialog.expandDescription(pasteDialog.rowsNeeded)}\n </span>\n </div>\n </label>\n {/* biome-ignore lint/a11y/noLabelWithoutControl: <RadioItem> bọc sẵn <input type=\"radio\"> bên trong */}\n <label className=\"flex cursor-pointer items-start gap-3\">\n <RadioItem name=\"expand-option\" value=\"no-expand\" />\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium text-sm leading-none\">{msg.pasteDialog.keepTitle}</span>\n <span className=\"text-muted-foreground text-sm\">{msg.pasteDialog.keepDescription}</span>\n </div>\n </label>\n </div>\n <DialogFooter className=\"gap-2\">\n <Button variant=\"outline\" onClick={onCancel}>\n {msg.pasteDialog.cancel}\n </Button>\n <Button onClick={onContinue}>{msg.pasteDialog.confirm}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * Radio thuần HTML (không dùng RadioGroup của Radix) để bấm vào cả khối `<label>`\n * là chọn được, và để đọc trạng thái qua ref lúc bấm \"Tiếp tục\".\n */\nfunction RadioItem({ className, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type=\"radio\"\n className={cn(\n // Cùng bộ token với `RadioGroupItem` của gói (`--choice-edge` cho viền nghỉ,\n // `--control-on` cho viền + chấm khi chọn) — đừng quay lại `--primary`/`--ring`: đó là\n // bậc tô NỀN, đem vẽ NÉT thì ở light chỉ 1,73:1.\n \"relative mt-0.5 size-4 shrink-0 appearance-none rounded-full border border-choice-edge outline-none transition-colors dark:bg-input-fill\",\n \"hover:border-choice-edge-strong checked:border-control-on\",\n \"focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"checked:before:absolute checked:before:start-1/2 checked:before:top-1/2 checked:before:size-2 checked:before:-translate-x-1/2 checked:before:-translate-y-1/2 checked:before:rounded-full checked:before:bg-control-on checked:before:content-['']\",\n className\n )}\n {...props}\n />\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+
3
+ interface DataGridCellPresence {
4
+ color: string;
5
+ name: string;
6
+ }
7
+ interface DataGridPresenceProviderProps {
8
+ value: Map<string, DataGridCellPresence>;
9
+ children: React.ReactNode;
10
+ }
11
+ declare function DataGridPresenceProvider({ value, children }: DataGridPresenceProviderProps): React.JSX.Element;
12
+ declare function useDataGridPresence(cellKey: string): DataGridCellPresence | null;
13
+
14
+ export { type DataGridCellPresence, DataGridPresenceProvider, useDataGridPresence };
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ const DataGridCellPresenceContext = React.createContext(null);
5
+ function DataGridPresenceProvider({ value, children }) {
6
+ return /* @__PURE__ */ jsx(DataGridCellPresenceContext.Provider, { value, children });
7
+ }
8
+ function useDataGridPresence(cellKey) {
9
+ const map = React.useContext(DataGridCellPresenceContext);
10
+ return map?.get(cellKey) ?? null;
11
+ }
12
+ export {
13
+ DataGridPresenceProvider,
14
+ useDataGridPresence
15
+ };
16
+ //# sourceMappingURL=data-grid-presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-grid/data-grid-presence.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\ninterface DataGridCellPresence {\n color: string;\n name: string;\n}\n\nconst DataGridCellPresenceContext = React.createContext<Map<string, DataGridCellPresence> | null>(null);\n\ninterface DataGridPresenceProviderProps {\n value: Map<string, DataGridCellPresence>;\n children: React.ReactNode;\n}\n\nfunction DataGridPresenceProvider({ value, children }: DataGridPresenceProviderProps) {\n return <DataGridCellPresenceContext.Provider value={value}>{children}</DataGridCellPresenceContext.Provider>;\n}\n\nfunction useDataGridPresence(cellKey: string): DataGridCellPresence | null {\n const map = React.useContext(DataGridCellPresenceContext);\n return map?.get(cellKey) ?? null;\n}\n\nexport { type DataGridCellPresence, DataGridPresenceProvider, useDataGridPresence };\n"],"mappings":";AAiBS;AAfT,YAAY,WAAW;AAOvB,MAAM,8BAA8B,MAAM,cAAwD,IAAI;AAOtG,SAAS,yBAAyB,EAAE,OAAO,SAAS,GAAkC;AACpF,SAAO,oBAAC,4BAA4B,UAA5B,EAAqC,OAAe,UAAS;AACvE;AAEA,SAAS,oBAAoB,SAA8C;AACzE,QAAM,MAAM,MAAM,WAAW,2BAA2B;AACxD,SAAO,KAAK,IAAI,OAAO,KAAK;AAC9B;","names":[]}
@@ -0,0 +1,15 @@
1
+ import { Table } from '@tanstack/react-table';
2
+ import * as React from 'react';
3
+ import { SelectContent } from '../components/ui/select.js';
4
+ import '@radix-ui/react-select';
5
+
6
+ interface DataGridRowHeightMenuProps<TData> extends React.ComponentProps<typeof SelectContent> {
7
+ table: Table<TData>;
8
+ disabled?: boolean;
9
+ /** className cho nút mở menu (mặc định cao 8 như các nút khác trên thanh công cụ) */
10
+ triggerClassName?: string;
11
+ }
12
+ /** Chọn chiều cao dòng của lưới (thấp/vừa/cao/rất cao) — đặt trên thanh công cụ. */
13
+ declare function DataGridRowHeightMenu<TData>({ table, disabled, triggerClassName, ...props }: DataGridRowHeightMenuProps<TData>): React.JSX.Element;
14
+
15
+ export { DataGridRowHeightMenu };