@comitor/ui 1.11.0 → 2.1.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 (176) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +23 -7
  3. package/dist/components/ui/action-bar-constants.d.ts +31 -0
  4. package/dist/components/ui/action-bar-constants.js +9 -0
  5. package/dist/components/ui/action-bar-constants.js.map +1 -0
  6. package/dist/components/ui/action-bar.d.ts +67 -0
  7. package/dist/components/ui/action-bar.js +522 -0
  8. package/dist/components/ui/action-bar.js.map +1 -0
  9. package/dist/components/ui/badge-overflow.d.ts +30 -0
  10. package/dist/components/ui/badge-overflow.js +179 -0
  11. package/dist/components/ui/badge-overflow.js.map +1 -0
  12. package/dist/components/ui/banner.d.ts +79 -0
  13. package/dist/components/ui/banner.js +518 -0
  14. package/dist/components/ui/banner.js.map +1 -0
  15. package/dist/components/ui/circular-progress.d.ts +50 -0
  16. package/dist/components/ui/circular-progress.js +266 -0
  17. package/dist/components/ui/circular-progress.js.map +1 -0
  18. package/dist/components/ui/cropper-constants.d.ts +34 -0
  19. package/dist/components/ui/cropper-constants.js +10 -0
  20. package/dist/components/ui/cropper-constants.js.map +1 -0
  21. package/dist/components/ui/cropper.d.ts +106 -0
  22. package/dist/components/ui/cropper.js +1269 -0
  23. package/dist/components/ui/cropper.js.map +1 -0
  24. package/dist/components/ui/drawer.d.ts +1 -1
  25. package/dist/components/ui/drawer.js +2 -2
  26. package/dist/components/ui/drawer.js.map +1 -1
  27. package/dist/components/ui/kanban-constants.d.ts +61 -0
  28. package/dist/components/ui/kanban-constants.js +21 -0
  29. package/dist/components/ui/kanban-constants.js.map +1 -0
  30. package/dist/components/ui/kanban.d.ts +72 -0
  31. package/dist/components/ui/kanban.js +787 -0
  32. package/dist/components/ui/kanban.js.map +1 -0
  33. package/dist/components/ui/key-value-constants.d.ts +33 -0
  34. package/dist/components/ui/key-value-constants.js +11 -0
  35. package/dist/components/ui/key-value-constants.js.map +1 -0
  36. package/dist/components/ui/key-value.d.ts +96 -0
  37. package/dist/components/ui/key-value.js +641 -0
  38. package/dist/components/ui/key-value.js.map +1 -0
  39. package/dist/components/ui/mask-input-constants.d.ts +99 -0
  40. package/dist/components/ui/mask-input-constants.js +601 -0
  41. package/dist/components/ui/mask-input-constants.js.map +1 -0
  42. package/dist/components/ui/mask-input.d.ts +36 -0
  43. package/dist/components/ui/mask-input.js +558 -0
  44. package/dist/components/ui/mask-input.js.map +1 -0
  45. package/dist/components/ui/mention.d.ts +31 -0
  46. package/dist/components/ui/mention.js +128 -0
  47. package/dist/components/ui/mention.js.map +1 -0
  48. package/dist/components/ui/phone-input-constants.d.ts +54 -0
  49. package/dist/components/ui/phone-input-constants.js +9 -0
  50. package/dist/components/ui/phone-input-constants.js.map +1 -0
  51. package/dist/components/ui/phone-input.d.ts +85 -0
  52. package/dist/components/ui/phone-input.js +743 -0
  53. package/dist/components/ui/phone-input.js.map +1 -0
  54. package/dist/components/ui/rating.d.ts +56 -0
  55. package/dist/components/ui/rating.js +646 -0
  56. package/dist/components/ui/rating.js.map +1 -0
  57. package/dist/components/ui/responsive-dialog.d.ts +35 -0
  58. package/dist/components/ui/responsive-dialog.js +193 -0
  59. package/dist/components/ui/responsive-dialog.js.map +1 -0
  60. package/dist/components/ui/scroll-spy.d.ts +42 -0
  61. package/dist/components/ui/scroll-spy.js +334 -0
  62. package/dist/components/ui/scroll-spy.js.map +1 -0
  63. package/dist/components/ui/stepper-constants.d.ts +29 -0
  64. package/dist/components/ui/stepper-constants.js +9 -0
  65. package/dist/components/ui/stepper-constants.js.map +1 -0
  66. package/dist/components/ui/stepper.d.ts +80 -0
  67. package/dist/components/ui/stepper.js +902 -0
  68. package/dist/components/ui/stepper.js.map +1 -0
  69. package/dist/components/ui/tags-input.d.ts +41 -0
  70. package/dist/components/ui/tags-input.js +127 -0
  71. package/dist/components/ui/tags-input.js.map +1 -0
  72. package/dist/components/ui/time-picker-constants.d.ts +48 -0
  73. package/dist/components/ui/time-picker-constants.js +14 -0
  74. package/dist/components/ui/time-picker-constants.js.map +1 -0
  75. package/dist/components/ui/time-picker.d.ts +115 -0
  76. package/dist/components/ui/time-picker.js +1620 -0
  77. package/dist/components/ui/time-picker.js.map +1 -0
  78. package/dist/components/ui/timeline.d.ts +32 -0
  79. package/dist/components/ui/timeline.js +559 -0
  80. package/dist/components/ui/timeline.js.map +1 -0
  81. package/dist/components/ui/tour-constants.d.ts +39 -0
  82. package/dist/components/ui/tour-constants.js +12 -0
  83. package/dist/components/ui/tour-constants.js.map +1 -0
  84. package/dist/components/ui/tour.d.ts +124 -0
  85. package/dist/components/ui/tour.js +1207 -0
  86. package/dist/components/ui/tour.js.map +1 -0
  87. package/dist/data-grid/data-grid-cell-variants.js +10 -6
  88. package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
  89. package/dist/data-grid/data-grid-cell-wrapper.js +1 -1
  90. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
  91. package/dist/data-grid/data-grid-column-header.js +4 -2
  92. package/dist/data-grid/data-grid-column-header.js.map +1 -1
  93. package/dist/data-grid/data-grid-context-menu.js +5 -4
  94. package/dist/data-grid/data-grid-context-menu.js.map +1 -1
  95. package/dist/data-grid/data-grid-filter-menu.d.ts +12 -1
  96. package/dist/data-grid/data-grid-filter-menu.js +28 -17
  97. package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
  98. package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +12 -1
  99. package/dist/data-grid/data-grid-keyboard-shortcuts.js +7 -5
  100. package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
  101. package/dist/data-grid/data-grid-locale.d.ts +24 -0
  102. package/dist/data-grid/data-grid-locale.js +25 -0
  103. package/dist/data-grid/data-grid-locale.js.map +1 -0
  104. package/dist/data-grid/data-grid-paste-dialog.js +3 -2
  105. package/dist/data-grid/data-grid-paste-dialog.js.map +1 -1
  106. package/dist/data-grid/data-grid-row-height-menu.d.ts +11 -1
  107. package/dist/data-grid/data-grid-row-height-menu.js +25 -28
  108. package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
  109. package/dist/data-grid/data-grid-row.js +1 -1
  110. package/dist/data-grid/data-grid-row.js.map +1 -1
  111. package/dist/data-grid/data-grid-search.js +6 -5
  112. package/dist/data-grid/data-grid-search.js.map +1 -1
  113. package/dist/data-grid/data-grid-select-column.js +3 -1
  114. package/dist/data-grid/data-grid-select-column.js.map +1 -1
  115. package/dist/data-grid/data-grid-sort-menu.d.ts +12 -1
  116. package/dist/data-grid/data-grid-sort-menu.js +25 -13
  117. package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
  118. package/dist/data-grid/data-grid-view-menu.d.ts +12 -1
  119. package/dist/data-grid/data-grid-view-menu.js +12 -4
  120. package/dist/data-grid/data-grid-view-menu.js.map +1 -1
  121. package/dist/data-grid/data-grid.d.ts +14 -2
  122. package/dist/data-grid/data-grid.js +7 -4
  123. package/dist/data-grid/data-grid.js.map +1 -1
  124. package/dist/data-grid/filters.d.ts +17 -21
  125. package/dist/data-grid/filters.js +73 -52
  126. package/dist/data-grid/filters.js.map +1 -1
  127. package/dist/data-grid/index.d.ts +4 -1
  128. package/dist/data-grid/index.js +20 -2
  129. package/dist/data-grid/index.js.map +1 -1
  130. package/dist/data-grid/messages-en.d.ts +294 -0
  131. package/dist/data-grid/messages-en.js +279 -0
  132. package/dist/data-grid/messages-en.js.map +1 -0
  133. package/dist/data-grid/messages-vi.d.ts +12 -0
  134. package/dist/data-grid/messages-vi.js +279 -0
  135. package/dist/data-grid/messages-vi.js.map +1 -0
  136. package/dist/data-grid/messages.d.ts +549 -262
  137. package/dist/data-grid/messages.js +16 -275
  138. package/dist/data-grid/messages.js.map +1 -1
  139. package/dist/data-grid/sortable.js +1 -1
  140. package/dist/data-grid/sortable.js.map +1 -1
  141. package/dist/data-grid/use-data-grid-undo-redo.d.ts +13 -1
  142. package/dist/data-grid/use-data-grid-undo-redo.js +13 -10
  143. package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
  144. package/dist/data-grid/use-data-grid.d.ts +281 -1
  145. package/dist/data-grid/use-data-grid.js +24 -19
  146. package/dist/data-grid/use-data-grid.js.map +1 -1
  147. package/dist/data-grid/utils.d.ts +9 -1
  148. package/dist/data-grid/utils.js +3 -2
  149. package/dist/data-grid/utils.js.map +1 -1
  150. package/dist/index.d.ts +31 -0
  151. package/dist/index.js +42 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/lib/compose-refs.js.map +1 -0
  154. package/dist/lib/use-as-ref.js.map +1 -0
  155. package/dist/lib/use-is-mobile.d.ts +10 -0
  156. package/dist/lib/use-is-mobile.js +21 -0
  157. package/dist/lib/use-is-mobile.js.map +1 -0
  158. package/dist/lib/use-isomorphic-layout-effect.js.map +1 -0
  159. package/dist/lib/use-lazy-ref.js.map +1 -0
  160. package/dist/lib/visually-hidden-input.d.ts +12 -0
  161. package/dist/lib/visually-hidden-input.js +105 -0
  162. package/dist/lib/visually-hidden-input.js.map +1 -0
  163. package/package.json +5 -1
  164. package/styles.css +19 -0
  165. package/dist/data-grid/compose-refs.js.map +0 -1
  166. package/dist/data-grid/use-as-ref.js.map +0 -1
  167. package/dist/data-grid/use-isomorphic-layout-effect.js.map +0 -1
  168. package/dist/data-grid/use-lazy-ref.js.map +0 -1
  169. /package/dist/{data-grid → lib}/compose-refs.d.ts +0 -0
  170. /package/dist/{data-grid → lib}/compose-refs.js +0 -0
  171. /package/dist/{data-grid → lib}/use-as-ref.d.ts +0 -0
  172. /package/dist/{data-grid → lib}/use-as-ref.js +0 -0
  173. /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.d.ts +0 -0
  174. /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.js +0 -0
  175. /package/dist/{data-grid → lib}/use-lazy-ref.d.ts +0 -0
  176. /package/dist/{data-grid → lib}/use-lazy-ref.js +0 -0
@@ -14,8 +14,15 @@ import {
14
14
  } from "../components/ui/command.js";
15
15
  import { Popover, PopoverContent, PopoverTrigger } from "../components/ui/popover.js";
16
16
  import { cn } from "../lib/cn.js";
17
- import { msg } from "./messages.js";
18
- function DataGridViewMenu({ table, disabled, className, ...props }) {
17
+ import { useResolvedDataGridMessages } from "./data-grid-locale.js";
18
+ function DataGridViewMenu({
19
+ table,
20
+ disabled,
21
+ className,
22
+ locale,
23
+ ...props
24
+ }) {
25
+ const msg = useResolvedDataGridMessages(locale);
19
26
  const dir = useDirection();
20
27
  const columns = React.useMemo(
21
28
  () => table.getAllColumns().filter((column) => typeof column.accessorFn !== "undefined" && column.getCanHide()),
@@ -29,10 +36,11 @@ function DataGridViewMenu({ table, disabled, className, ...props }) {
29
36
  role: "combobox",
30
37
  dir,
31
38
  variant: "outline",
32
- className: "h-8 gap-2 font-normal",
39
+ size: "sm",
40
+ className: "font-normal",
33
41
  disabled,
34
42
  children: [
35
- /* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true", className: "text-muted-foreground" }),
43
+ /* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true", className: "size-3.5 text-muted-foreground" }),
36
44
  msg.view.trigger
37
45
  ]
38
46
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-grid/data-grid-view-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { Table } from \"@tanstack/react-table\";\nimport { Check, Settings2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { msg } from \"./messages.js\";\n\ninterface DataGridViewMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n}\n\n/** Ẩn/hiện cột của lưới. Cột muốn khoá luôn hiển thị thì đặt `enableHiding: false`. */\nexport function DataGridViewMenu<TData>({ table, disabled, className, ...props }: DataGridViewMenuProps<TData>) {\n const dir = useDirection();\n\n const columns = React.useMemo(\n () => table.getAllColumns().filter((column) => typeof column.accessorFn !== \"undefined\" && column.getCanHide()),\n [table]\n );\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n aria-label={msg.view.toggleColumns}\n role=\"combobox\"\n dir={dir}\n variant=\"outline\"\n className=\"h-8 gap-2 font-normal\"\n disabled={disabled}\n >\n <Settings2 aria-hidden=\"true\" className=\"text-muted-foreground\" />\n {msg.view.trigger}\n </Button>\n </PopoverTrigger>\n <PopoverContent dir={dir} align=\"end\" className={cn(\"w-52 p-0\", className)} {...props}>\n <Command>\n <CommandInput placeholder={msg.view.searchPlaceholder} aria-label={msg.view.searchPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.view.empty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => {\n const isVisible = column.getIsVisible();\n\n return (\n <CommandItem\n key={column.id}\n value={column.columnDef.meta?.label ?? column.id}\n onSelect={() => column.toggleVisibility(!isVisible)}\n >\n <span className=\"truncate\">{column.columnDef.meta?.label ?? column.id}</span>\n <Check className={cn(\"ms-auto size-4\", isVisible ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":";AAoCQ,SAQE,KARF;AAlCR,SAAS,oBAAoB;AAE7B,SAAS,OAAO,iBAAiB;AACjC,YAAY,WAAW;AACvB,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AACnB,SAAS,WAAW;AAQb,SAAS,iBAAwB,EAAE,OAAO,UAAU,WAAW,GAAG,MAAM,GAAiC;AAC9G,QAAM,MAAM,aAAa;AAEzB,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM,MAAM,cAAc,EAAE,OAAO,CAAC,WAAW,OAAO,OAAO,eAAe,eAAe,OAAO,WAAW,CAAC;AAAA,IAC9G,CAAC,KAAK;AAAA,EACR;AAEA,SACE,qBAAC,WACC;AAAA,wBAAC,kBAAe,SAAO,MACrB;AAAA,MAAC;AAAA;AAAA,QACC,cAAY,IAAI,KAAK;AAAA,QACrB,MAAK;AAAA,QACL;AAAA,QACA,SAAQ;AAAA,QACR,WAAU;AAAA,QACV;AAAA,QAEA;AAAA,8BAAC,aAAU,eAAY,QAAO,WAAU,yBAAwB;AAAA,UAC/D,IAAI,KAAK;AAAA;AAAA;AAAA,IACZ,GACF;AAAA,IACA,oBAAC,kBAAe,KAAU,OAAM,OAAM,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,OAC9E,+BAAC,WACC;AAAA,0BAAC,gBAAa,aAAa,IAAI,KAAK,mBAAmB,cAAY,IAAI,KAAK,mBAAmB;AAAA,MAC/F,qBAAC,eACC;AAAA,4BAAC,gBAAc,cAAI,KAAK,OAAM;AAAA,QAC9B,oBAAC,gBACE,kBAAQ,IAAI,CAAC,WAAW;AACvB,gBAAM,YAAY,OAAO,aAAa;AAEtC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO,OAAO,UAAU,MAAM,SAAS,OAAO;AAAA,cAC9C,UAAU,MAAM,OAAO,iBAAiB,CAAC,SAAS;AAAA,cAElD;AAAA,oCAAC,UAAK,WAAU,YAAY,iBAAO,UAAU,MAAM,SAAS,OAAO,IAAG;AAAA,gBACtE,oBAAC,SAAM,WAAW,GAAG,kBAAkB,YAAY,gBAAgB,WAAW,GAAG;AAAA;AAAA;AAAA,YAL5E,OAAO;AAAA,UAMd;AAAA,QAEJ,CAAC,GACH;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/data-grid/data-grid-view-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport type { Table } from \"@tanstack/react-table\";\nimport { Check, Settings2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"../components/ui/button.js\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList\n} from \"../components/ui/command.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../components/ui/popover.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { useResolvedDataGridMessages } from \"./data-grid-locale.js\";\nimport type { DataGridLocale, DataGridMessages } from \"./messages.js\";\n\ninterface DataGridViewMenuProps<TData> extends React.ComponentProps<typeof PopoverContent> {\n table: Table<TData>;\n disabled?: boolean;\n /**\n * Ngôn ngữ của menu: `\"en\"` (mặc định) · `\"vi\"`, hoặc cả một bảng chuỗi tự soạn.\n *\n * ⚠ Thanh công cụ nằm NGOÀI `<DataGrid>`, nên `locale` truyền cho lưới không với tới đây. Bọc\n * cả màn bằng `DataGridLocaleProvider` (một lần, đúng cho mọi mảnh), hoặc truyền prop này cho\n * từng menu. Prop thắng provider.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\n/** Ẩn/hiện cột của lưới. Cột muốn khoá luôn hiển thị thì đặt `enableHiding: false`. */\nexport function DataGridViewMenu<TData>({\n table,\n disabled,\n className,\n locale,\n ...props\n}: DataGridViewMenuProps<TData>) {\n const msg = useResolvedDataGridMessages(locale);\n const dir = useDirection();\n\n const columns = React.useMemo(\n () => table.getAllColumns().filter((column) => typeof column.accessorFn !== \"undefined\" && column.getCanHide()),\n [table]\n );\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button\n aria-label={msg.view.toggleColumns}\n role=\"combobox\"\n dir={dir}\n variant=\"outline\"\n size=\"sm\"\n className=\"font-normal\"\n disabled={disabled}\n >\n <Settings2 aria-hidden=\"true\" className=\"size-3.5 text-muted-foreground\" />\n {msg.view.trigger}\n </Button>\n </PopoverTrigger>\n <PopoverContent dir={dir} align=\"end\" className={cn(\"w-52 p-0\", className)} {...props}>\n <Command>\n <CommandInput placeholder={msg.view.searchPlaceholder} aria-label={msg.view.searchPlaceholder} />\n <CommandList>\n <CommandEmpty>{msg.view.empty}</CommandEmpty>\n <CommandGroup>\n {columns.map((column) => {\n const isVisible = column.getIsVisible();\n\n return (\n <CommandItem\n key={column.id}\n value={column.columnDef.meta?.label ?? column.id}\n onSelect={() => column.toggleVisibility(!isVisible)}\n >\n <span className=\"truncate\">{column.columnDef.meta?.label ?? column.id}</span>\n <Check className={cn(\"ms-auto size-4\", isVisible ? \"opacity-100\" : \"opacity-0\")} />\n </CommandItem>\n );\n })}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":";AAoDQ,SASE,KATF;AAlDR,SAAS,oBAAoB;AAE7B,SAAS,OAAO,iBAAiB;AACjC,YAAY,WAAW;AACvB,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AACnB,SAAS,mCAAmC;AAiBrC,SAAS,iBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiC;AAC/B,QAAM,MAAM,4BAA4B,MAAM;AAC9C,QAAM,MAAM,aAAa;AAEzB,QAAM,UAAU,MAAM;AAAA,IACpB,MAAM,MAAM,cAAc,EAAE,OAAO,CAAC,WAAW,OAAO,OAAO,eAAe,eAAe,OAAO,WAAW,CAAC;AAAA,IAC9G,CAAC,KAAK;AAAA,EACR;AAEA,SACE,qBAAC,WACC;AAAA,wBAAC,kBAAe,SAAO,MACrB;AAAA,MAAC;AAAA;AAAA,QACC,cAAY,IAAI,KAAK;AAAA,QACrB,MAAK;AAAA,QACL;AAAA,QACA,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QACV;AAAA,QAEA;AAAA,8BAAC,aAAU,eAAY,QAAO,WAAU,kCAAiC;AAAA,UACxE,IAAI,KAAK;AAAA;AAAA;AAAA,IACZ,GACF;AAAA,IACA,oBAAC,kBAAe,KAAU,OAAM,OAAM,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,OAC9E,+BAAC,WACC;AAAA,0BAAC,gBAAa,aAAa,IAAI,KAAK,mBAAmB,cAAY,IAAI,KAAK,mBAAmB;AAAA,MAC/F,qBAAC,eACC;AAAA,4BAAC,gBAAc,cAAI,KAAK,OAAM;AAAA,QAC9B,oBAAC,gBACE,kBAAQ,IAAI,CAAC,WAAW;AACvB,gBAAM,YAAY,OAAO,aAAa;AAEtC,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO,OAAO,UAAU,MAAM,SAAS,OAAO;AAAA,cAC9C,UAAU,MAAM,OAAO,iBAAiB,CAAC,SAAS;AAAA,cAElD;AAAA,oCAAC,UAAK,WAAU,YAAY,iBAAO,UAAU,MAAM,SAAS,OAAO,IAAG;AAAA,gBACtE,oBAAC,SAAM,WAAW,GAAG,kBAAkB,YAAY,gBAAgB,WAAW,GAAG;AAAA;AAAA;AAAA,YAL5E,OAAO;AAAA,UAMd;AAAA,QAEJ,CAAC,GACH;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -1,10 +1,13 @@
1
1
  import * as React from 'react';
2
+ import { DataGridLocale } from './messages.js';
2
3
  import { Direction } from './types.js';
3
4
  import { useDataGrid } from './use-data-grid.js';
5
+ import { DataGridMessages } from './messages-en.js';
6
+ import './messages-vi.js';
4
7
  import '@tanstack/react-table';
5
8
  import '@tanstack/react-virtual';
6
9
 
7
- interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>>, "dir">, Omit<React.ComponentProps<"div">, "contextMenu"> {
10
+ interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>>, "dir" | "locale">, Omit<React.ComponentProps<"div">, "contextMenu"> {
8
11
  dir?: Direction;
9
12
  /**
10
13
  * Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ
@@ -13,6 +16,15 @@ interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>
13
16
  height?: number | string;
14
17
  /** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */
15
18
  stretchColumns?: boolean;
19
+ /**
20
+ * Ngôn ngữ của lưới: `"en"` (mặc định) · `"vi"`, hoặc cả một bảng chuỗi tự soạn.
21
+ *
22
+ * Thường nó đi theo kết quả của {@link useDataGrid} nên không phải truyền lại ở đây. Giá trị
23
+ * đặt thẳng lên `<DataGrid>` THẮNG giá trị từ hook — hữu ích khi một màn có hai lưới khác ngôn
24
+ * ngữ. Thanh công cụ nằm ngoài lưới nên nó KHÔNG nhận được giá trị này: bọc cả màn bằng
25
+ * `DataGridLocaleProvider`, hoặc truyền `locale` cho từng menu.
26
+ */
27
+ locale?: DataGridLocale | DataGridMessages;
16
28
  }
17
29
  /**
18
30
  * Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,
@@ -27,6 +39,6 @@ interface DataGridProps<TData> extends Omit<ReturnType<typeof useDataGrid<TData>
27
39
  * `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang
28
40
  * `role="grid"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).
29
41
  */
30
- declare function DataGrid<TData>({ dataGridRef, headerRef, rowMapRef, footerRef, dir, table, tableMeta, virtualTotalSize, virtualItems, measureElement, columns, columnSizeVars, searchState, searchMatchesByRow, activeSearchMatch, cellSelectionMap, focusedCell, editingCell, rowHeight, contextMenu, pasteDialog, onRowAdd: onRowAddProp, height, stretchColumns, adjustLayout, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...props }: DataGridProps<TData>): React.JSX.Element;
42
+ declare function DataGrid<TData>({ dataGridRef, headerRef, rowMapRef, footerRef, dir, table, tableMeta, virtualTotalSize, virtualItems, measureElement, columns, columnSizeVars, searchState, searchMatchesByRow, activeSearchMatch, cellSelectionMap, focusedCell, editingCell, rowHeight, contextMenu, pasteDialog, onRowAdd: onRowAddProp, height, stretchColumns, locale, adjustLayout, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...props }: DataGridProps<TData>): React.JSX.Element;
31
43
 
32
44
  export { DataGrid };
@@ -4,13 +4,14 @@ import { Plus } from "lucide-react";
4
4
  import * as React from "react";
5
5
  import { TooltipProvider } from "../components/ui/tooltip.js";
6
6
  import { cn } from "../lib/cn.js";
7
+ import { useAsRef } from "../lib/use-as-ref.js";
7
8
  import { DataGridColumnHeader } from "./data-grid-column-header.js";
8
9
  import { DataGridContextMenu } from "./data-grid-context-menu.js";
10
+ import { DataGridLocaleProvider } from "./data-grid-locale.js";
9
11
  import { DataGridPasteDialog } from "./data-grid-paste-dialog.js";
10
12
  import { DataGridRow } from "./data-grid-row.js";
11
13
  import { DataGridSearch } from "./data-grid-search.js";
12
- import { msg } from "./messages.js";
13
- import { useAsRef } from "./use-as-ref.js";
14
+ import { getDataGridMessages } from "./messages.js";
14
15
  import { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from "./utils.js";
15
16
  const EMPTY_CELL_SELECTION_SET = /* @__PURE__ */ new Set();
16
17
  function DataGrid({
@@ -38,6 +39,7 @@ function DataGrid({
38
39
  onRowAdd: onRowAddProp,
39
40
  height = 600,
40
41
  stretchColumns = false,
42
+ locale,
41
43
  adjustLayout = false,
42
44
  className,
43
45
  "aria-label": ariaLabel,
@@ -69,7 +71,8 @@ function DataGrid({
69
71
  },
70
72
  [onRowAddRef]
71
73
  );
72
- return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs("div", { "data-slot": "grid-wrapper", dir, ...props, className: cn("relative flex w-full flex-col", className), children: [
74
+ const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);
75
+ return /* @__PURE__ */ jsx(DataGridLocaleProvider, { locale, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs("div", { "data-slot": "grid-wrapper", dir, ...props, className: cn("relative flex w-full flex-col", className), children: [
73
76
  searchState && /* @__PURE__ */ jsx(DataGridSearch, { ...searchState }),
74
77
  /* @__PURE__ */ jsx(DataGridContextMenu, { tableMeta, columns, contextMenu }),
75
78
  /* @__PURE__ */ jsx(DataGridPasteDialog, { tableMeta, pasteDialog }),
@@ -227,7 +230,7 @@ function DataGrid({
227
230
  ]
228
231
  }
229
232
  )
230
- ] }) });
233
+ ] }) }) });
231
234
  }
232
235
  export {
233
236
  DataGrid
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-grid/data-grid.tsx"],"sourcesContent":["\"use client\";\n\nimport { Plus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { DataGridColumnHeader } from \"./data-grid-column-header.js\";\nimport { DataGridContextMenu } from \"./data-grid-context-menu.js\";\nimport { DataGridPasteDialog } from \"./data-grid-paste-dialog.js\";\nimport { DataGridRow } from \"./data-grid-row.js\";\nimport { DataGridSearch } from \"./data-grid-search.js\";\nimport { msg } from \"./messages.js\";\nimport type { Direction } from \"./types.js\";\nimport { useAsRef } from \"./use-as-ref.js\";\nimport type { useDataGrid } from \"./use-data-grid.js\";\nimport { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from \"./utils.js\";\n\nconst EMPTY_CELL_SELECTION_SET = new Set<string>();\n\ninterface DataGridProps<TData>\n extends Omit<ReturnType<typeof useDataGrid<TData>>, \"dir\">,\n Omit<React.ComponentProps<\"div\">, \"contextMenu\"> {\n dir?: Direction;\n /**\n * Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ\n * (vd `\"100%\"`, `\"calc(100dvh - 220px)\"` khi muốn lưới lấp đầy phần còn lại của trang).\n */\n height?: number | string;\n /** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */\n stretchColumns?: boolean;\n}\n\n/**\n * Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,\n * chọn vùng ô, sao chép/cắt/dán, ghim cột, đổi rộng cột.\n *\n * Nhận nguyên kết quả của {@link useDataGrid}:\n * ```tsx\n * const { table, ...dataGridProps } = useDataGrid({ data, columns, onDataChange });\n * <DataGrid {...dataGridProps} table={table} aria-label=\"Danh sách bệnh nhân\" />\n * ```\n *\n * `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang\n * `role=\"grid\"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).\n */\nexport function DataGrid<TData>({\n dataGridRef,\n headerRef,\n rowMapRef,\n footerRef,\n dir = \"ltr\",\n table,\n tableMeta,\n virtualTotalSize,\n virtualItems,\n measureElement,\n columns,\n columnSizeVars,\n searchState,\n searchMatchesByRow,\n activeSearchMatch,\n cellSelectionMap,\n focusedCell,\n editingCell,\n rowHeight,\n contextMenu,\n pasteDialog,\n onRowAdd: onRowAddProp,\n height = 600,\n stretchColumns = false,\n adjustLayout = false,\n className,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: DataGridProps<TData>) {\n const rows = table.getRowModel().rows;\n const readOnly = tableMeta?.readOnly ?? false;\n const columnVisibility = table.getState().columnVisibility;\n const columnPinning = table.getState().columnPinning;\n\n const onRowAddRef = useAsRef(onRowAddProp);\n\n const onRowAdd = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onRowAddRef.current?.(event);\n },\n [onRowAddRef]\n );\n\n const onDataGridContextMenu = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n event.preventDefault();\n }, []);\n\n const onFooterCellKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onRowAddRef.current) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowAddRef.current();\n }\n },\n [onRowAddRef]\n );\n\n return (\n <TooltipProvider delayDuration={200}>\n <div data-slot=\"grid-wrapper\" dir={dir} {...props} className={cn(\"relative flex w-full flex-col\", className)}>\n {searchState && <DataGridSearch {...searchState} />}\n <DataGridContextMenu tableMeta={tableMeta} columns={columns} contextMenu={contextMenu} />\n <DataGridPasteDialog tableMeta={tableMeta} pasteDialog={pasteDialog} />\n <div\n role=\"grid\"\n aria-label={ariaLabelledby ? undefined : (ariaLabel ?? msg.grid.label)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-rowcount={rows.length + (onRowAddProp ? 1 : 0)}\n aria-colcount={columns.length}\n data-slot=\"grid\"\n tabIndex={0}\n ref={dataGridRef}\n className=\"relative grid select-none overflow-auto rounded-lg border bg-card focus:outline-none focus-visible:outline-none\"\n style={{\n ...columnSizeVars,\n maxHeight: typeof height === \"number\" ? `${height}px` : height\n }}\n onContextMenu={onDataGridContextMenu}\n >\n <div\n role=\"rowgroup\"\n data-slot=\"grid-header\"\n ref={headerRef}\n className=\"sticky top-0 z-10 grid border-b bg-card\"\n >\n {table.getHeaderGroups().map((headerGroup, rowIndex) => (\n <div\n key={headerGroup.id}\n role=\"row\"\n aria-rowindex={rowIndex + 1}\n data-slot=\"grid-header-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n {headerGroup.headers.map((header, colIndex) => {\n const sorting = table.getState().sorting;\n const currentSort = sorting.find((sort) => sort.id === header.column.id);\n const isSortable = header.column.getCanSort();\n\n const nextHeader = headerGroup.headers[colIndex + 1];\n const isLastColumn = colIndex === headerGroup.headers.length - 1;\n\n const { showEndBorder, showStartBorder } = getColumnBorderVisibility({\n column: header.column,\n nextColumn: nextHeader?.column,\n isLastColumn\n });\n\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n aria-colindex={colIndex + 1}\n aria-sort={\n currentSort?.desc === false\n ? \"ascending\"\n : currentSort?.desc === true\n ? \"descending\"\n : isSortable\n ? \"none\"\n : undefined\n }\n data-slot=\"grid-header-cell\"\n tabIndex={-1}\n className={cn(\"relative\", {\n grow: stretchColumns && header.column.id !== \"select\",\n \"border-e\": showEndBorder && header.column.id !== \"select\",\n \"border-s\": showStartBorder && header.column.id !== \"select\"\n })}\n style={{\n ...getColumnPinningStyle({ column: header.column, dir }),\n width: `calc(var(--header-${header.id}-size) * 1px)`\n }}\n >\n {header.isPlaceholder ? null : typeof header.column.columnDef.header === \"function\" ? (\n <div className=\"size-full px-3 py-1.5\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n </div>\n ) : (\n <DataGridColumnHeader header={header} table={table} />\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div\n role=\"rowgroup\"\n data-slot=\"grid-body\"\n className=\"relative grid\"\n style={{\n height: `${virtualTotalSize}px`,\n contain: adjustLayout ? \"layout paint\" : \"strict\"\n }}\n >\n {virtualItems.map((virtualItem) => {\n const row = rows[virtualItem.index];\n if (!row) return null;\n\n const cellSelectionKeys = cellSelectionMap?.get(virtualItem.index) ?? EMPTY_CELL_SELECTION_SET;\n\n const searchMatchColumns = searchMatchesByRow?.get(virtualItem.index) ?? null;\n const isActiveSearchRow = activeSearchMatch?.rowIndex === virtualItem.index;\n\n return (\n <DataGridRow\n key={row.id}\n row={row}\n tableMeta={tableMeta}\n rowMapRef={rowMapRef}\n virtualItem={virtualItem}\n measureElement={measureElement}\n rowHeight={rowHeight}\n columnVisibility={columnVisibility}\n columnPinning={columnPinning}\n focusedCell={focusedCell}\n editingCell={editingCell}\n cellSelectionKeys={cellSelectionKeys}\n searchMatchColumns={searchMatchColumns}\n activeSearchMatch={isActiveSearchRow ? activeSearchMatch : null}\n dir={dir}\n adjustLayout={adjustLayout}\n stretchColumns={stretchColumns}\n readOnly={readOnly}\n />\n );\n })}\n </div>\n {/* Chỉ hiện dòng \"Thêm dòng\" khi ứng dụng thật sự truyền onRowAdd\n (biến `onRowAdd` bên dưới là callback bọc, luôn khác undefined). */}\n {!readOnly && onRowAddProp && (\n <div\n role=\"rowgroup\"\n data-slot=\"grid-footer\"\n ref={footerRef}\n className=\"sticky bottom-0 z-10 grid border-t bg-card\"\n >\n <div\n role=\"row\"\n aria-rowindex={rows.length + 2}\n data-slot=\"grid-add-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n <div\n role=\"gridcell\"\n tabIndex={0}\n className=\"relative flex h-9 grow items-center bg-muted/30 transition-colors hover:bg-muted/50 focus:bg-muted/50 focus:outline-none focus-visible:outline-none\"\n style={{\n width: table.getTotalSize(),\n minWidth: table.getTotalSize()\n }}\n onClick={onRowAdd}\n onKeyDown={onFooterCellKeyDown}\n >\n <div className=\"sticky start-0 flex items-center gap-2 px-3 text-muted-foreground\">\n <Plus className=\"size-3.5\" />\n <span className=\"text-sm\">{msg.grid.addRow}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </TooltipProvider>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/data-grid/data-grid.tsx"],"sourcesContent":["\"use client\";\n\nimport { Plus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { useAsRef } from \"../lib/use-as-ref.js\";\nimport { DataGridColumnHeader } from \"./data-grid-column-header.js\";\nimport { DataGridContextMenu } from \"./data-grid-context-menu.js\";\nimport { DataGridLocaleProvider } from \"./data-grid-locale.js\";\nimport { DataGridPasteDialog } from \"./data-grid-paste-dialog.js\";\nimport { DataGridRow } from \"./data-grid-row.js\";\nimport { DataGridSearch } from \"./data-grid-search.js\";\nimport { type DataGridLocale, type DataGridMessages, getDataGridMessages } from \"./messages.js\";\nimport type { Direction } from \"./types.js\";\nimport type { useDataGrid } from \"./use-data-grid.js\";\nimport { flexRender, getColumnBorderVisibility, getColumnPinningStyle } from \"./utils.js\";\n\nconst EMPTY_CELL_SELECTION_SET = new Set<string>();\n\ninterface DataGridProps<TData>\n extends Omit<ReturnType<typeof useDataGrid<TData>>, \"dir\" | \"locale\">,\n Omit<React.ComponentProps<\"div\">, \"contextMenu\"> {\n dir?: Direction;\n /**\n * Chiều cao tối đa của hộp cuộn: số = px, chuỗi = giá trị CSS bất kỳ\n * (vd `\"100%\"`, `\"calc(100dvh - 220px)\"` khi muốn lưới lấp đầy phần còn lại của trang).\n */\n height?: number | string;\n /** Kéo giãn các cột cho vừa bề ngang khi tổng bề rộng cột nhỏ hơn khung */\n stretchColumns?: boolean;\n /**\n * Ngôn ngữ của lưới: `\"en\"` (mặc định) · `\"vi\"`, hoặc cả một bảng chuỗi tự soạn.\n *\n * Thường nó đi theo kết quả của {@link useDataGrid} nên không phải truyền lại ở đây. Giá trị\n * đặt thẳng lên `<DataGrid>` THẮNG giá trị từ hook — hữu ích khi một màn có hai lưới khác ngôn\n * ngữ. Thanh công cụ nằm ngoài lưới nên nó KHÔNG nhận được giá trị này: bọc cả màn bằng\n * `DataGridLocaleProvider`, hoặc truyền `locale` cho từng menu.\n */\n locale?: DataGridLocale | DataGridMessages;\n}\n\n/**\n * Lưới dữ liệu sửa trực tiếp (như bảng tính): ảo hoá dòng, điều hướng bằng bàn phím,\n * chọn vùng ô, sao chép/cắt/dán, ghim cột, đổi rộng cột.\n *\n * Nhận nguyên kết quả của {@link useDataGrid}:\n * ```tsx\n * const { table, ...dataGridProps } = useDataGrid({ data, columns, onDataChange });\n * <DataGrid {...dataGridProps} table={table} aria-label=\"Danh sách bệnh nhân\" />\n * ```\n *\n * `aria-label` / `aria-labelledby` / `aria-describedby` được đặt lên đúng thẻ mang\n * `role=\"grid\"` (thẻ bọc ngoài chỉ là hộp bố cục, gắn nhãn lên đó trình đọc màn hình bỏ qua).\n */\nexport function DataGrid<TData>({\n dataGridRef,\n headerRef,\n rowMapRef,\n footerRef,\n dir = \"ltr\",\n table,\n tableMeta,\n virtualTotalSize,\n virtualItems,\n measureElement,\n columns,\n columnSizeVars,\n searchState,\n searchMatchesByRow,\n activeSearchMatch,\n cellSelectionMap,\n focusedCell,\n editingCell,\n rowHeight,\n contextMenu,\n pasteDialog,\n onRowAdd: onRowAddProp,\n height = 600,\n stretchColumns = false,\n locale,\n adjustLayout = false,\n className,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n ...props\n}: DataGridProps<TData>) {\n const rows = table.getRowModel().rows;\n const readOnly = tableMeta?.readOnly ?? false;\n const columnVisibility = table.getState().columnVisibility;\n const columnPinning = table.getState().columnPinning;\n\n const onRowAddRef = useAsRef(onRowAddProp);\n\n const onRowAdd = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onRowAddRef.current?.(event);\n },\n [onRowAddRef]\n );\n\n const onDataGridContextMenu = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => {\n event.preventDefault();\n }, []);\n\n const onFooterCellKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!onRowAddRef.current) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowAddRef.current();\n }\n },\n [onRowAddRef]\n );\n\n const msg = React.useMemo(() => getDataGridMessages(locale), [locale]);\n\n return (\n <DataGridLocaleProvider locale={locale}>\n <TooltipProvider delayDuration={200}>\n <div data-slot=\"grid-wrapper\" dir={dir} {...props} className={cn(\"relative flex w-full flex-col\", className)}>\n {searchState && <DataGridSearch {...searchState} />}\n <DataGridContextMenu tableMeta={tableMeta} columns={columns} contextMenu={contextMenu} />\n <DataGridPasteDialog tableMeta={tableMeta} pasteDialog={pasteDialog} />\n <div\n role=\"grid\"\n aria-label={ariaLabelledby ? undefined : (ariaLabel ?? msg.grid.label)}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-rowcount={rows.length + (onRowAddProp ? 1 : 0)}\n aria-colcount={columns.length}\n data-slot=\"grid\"\n tabIndex={0}\n ref={dataGridRef}\n className=\"relative grid select-none overflow-auto rounded-lg border bg-card focus:outline-none focus-visible:outline-none\"\n style={{\n ...columnSizeVars,\n maxHeight: typeof height === \"number\" ? `${height}px` : height\n }}\n onContextMenu={onDataGridContextMenu}\n >\n <div\n role=\"rowgroup\"\n data-slot=\"grid-header\"\n ref={headerRef}\n className=\"sticky top-0 z-10 grid border-b bg-card\"\n >\n {table.getHeaderGroups().map((headerGroup, rowIndex) => (\n <div\n key={headerGroup.id}\n role=\"row\"\n aria-rowindex={rowIndex + 1}\n data-slot=\"grid-header-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n {headerGroup.headers.map((header, colIndex) => {\n const sorting = table.getState().sorting;\n const currentSort = sorting.find((sort) => sort.id === header.column.id);\n const isSortable = header.column.getCanSort();\n\n const nextHeader = headerGroup.headers[colIndex + 1];\n const isLastColumn = colIndex === headerGroup.headers.length - 1;\n\n const { showEndBorder, showStartBorder } = getColumnBorderVisibility({\n column: header.column,\n nextColumn: nextHeader?.column,\n isLastColumn\n });\n\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n aria-colindex={colIndex + 1}\n aria-sort={\n currentSort?.desc === false\n ? \"ascending\"\n : currentSort?.desc === true\n ? \"descending\"\n : isSortable\n ? \"none\"\n : undefined\n }\n data-slot=\"grid-header-cell\"\n tabIndex={-1}\n className={cn(\"relative\", {\n grow: stretchColumns && header.column.id !== \"select\",\n \"border-e\": showEndBorder && header.column.id !== \"select\",\n \"border-s\": showStartBorder && header.column.id !== \"select\"\n })}\n style={{\n ...getColumnPinningStyle({ column: header.column, dir }),\n width: `calc(var(--header-${header.id}-size) * 1px)`\n }}\n >\n {header.isPlaceholder ? null : typeof header.column.columnDef.header === \"function\" ? (\n <div className=\"size-full px-3 py-1.5\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n </div>\n ) : (\n <DataGridColumnHeader header={header} table={table} />\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n <div\n role=\"rowgroup\"\n data-slot=\"grid-body\"\n className=\"relative grid\"\n style={{\n height: `${virtualTotalSize}px`,\n contain: adjustLayout ? \"layout paint\" : \"strict\"\n }}\n >\n {virtualItems.map((virtualItem) => {\n const row = rows[virtualItem.index];\n if (!row) return null;\n\n const cellSelectionKeys = cellSelectionMap?.get(virtualItem.index) ?? EMPTY_CELL_SELECTION_SET;\n\n const searchMatchColumns = searchMatchesByRow?.get(virtualItem.index) ?? null;\n const isActiveSearchRow = activeSearchMatch?.rowIndex === virtualItem.index;\n\n return (\n <DataGridRow\n key={row.id}\n row={row}\n tableMeta={tableMeta}\n rowMapRef={rowMapRef}\n virtualItem={virtualItem}\n measureElement={measureElement}\n rowHeight={rowHeight}\n columnVisibility={columnVisibility}\n columnPinning={columnPinning}\n focusedCell={focusedCell}\n editingCell={editingCell}\n cellSelectionKeys={cellSelectionKeys}\n searchMatchColumns={searchMatchColumns}\n activeSearchMatch={isActiveSearchRow ? activeSearchMatch : null}\n dir={dir}\n adjustLayout={adjustLayout}\n stretchColumns={stretchColumns}\n readOnly={readOnly}\n />\n );\n })}\n </div>\n {/* Chỉ hiện dòng \"Thêm dòng\" khi ứng dụng thật sự truyền onRowAdd\n (biến `onRowAdd` bên dưới là callback bọc, luôn khác undefined). */}\n {!readOnly && onRowAddProp && (\n <div\n role=\"rowgroup\"\n data-slot=\"grid-footer\"\n ref={footerRef}\n className=\"sticky bottom-0 z-10 grid border-t bg-card\"\n >\n <div\n role=\"row\"\n aria-rowindex={rows.length + 2}\n data-slot=\"grid-add-row\"\n tabIndex={-1}\n className=\"flex w-full\"\n >\n <div\n role=\"gridcell\"\n tabIndex={0}\n className=\"relative flex h-9 grow items-center bg-muted/30 transition-colors hover:bg-muted/50 focus:bg-muted/50 focus:outline-none focus-visible:outline-none\"\n style={{\n width: table.getTotalSize(),\n minWidth: table.getTotalSize()\n }}\n onClick={onRowAdd}\n onKeyDown={onFooterCellKeyDown}\n >\n <div className=\"sticky start-0 flex items-center gap-2 px-3 text-muted-foreground\">\n <Plus className=\"size-3.5\" />\n <span className=\"text-sm\">{msg.grid.addRow}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </TooltipProvider>\n </DataGridLocaleProvider>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,28 +1,24 @@
1
1
  import { FilterFn } from '@tanstack/react-table';
2
- import { BooleanFilterOperator, DateFilterOperator, NumberFilterOperator, SelectFilterOperator, TextFilterOperator, FilterOperator } from './types.js';
2
+ import { DataGridMessages } from './messages-en.js';
3
+ import { FilterOperator, BooleanFilterOperator, DateFilterOperator, NumberFilterOperator, SelectFilterOperator, TextFilterOperator } from './types.js';
3
4
 
4
- declare const TEXT_FILTER_OPERATORS: ReadonlyArray<{
5
+ interface OperatorOption<TOperator extends FilterOperator> {
5
6
  label: string;
6
- value: TextFilterOperator;
7
- }>;
8
- declare const NUMBER_FILTER_OPERATORS: ReadonlyArray<{
9
- label: string;
10
- value: NumberFilterOperator;
11
- }>;
12
- declare const DATE_FILTER_OPERATORS: ReadonlyArray<{
13
- label: string;
14
- value: DateFilterOperator;
15
- }>;
16
- declare const SELECT_FILTER_OPERATORS: ReadonlyArray<{
17
- label: string;
18
- value: SelectFilterOperator;
19
- }>;
20
- declare const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<{
21
- label: string;
22
- value: BooleanFilterOperator;
23
- }>;
7
+ value: TOperator;
8
+ }
9
+ declare const TEXT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<TextFilterOperator>>;
10
+ declare const NUMBER_FILTER_OPERATORS: ReadonlyArray<OperatorOption<NumberFilterOperator>>;
11
+ declare const DATE_FILTER_OPERATORS: ReadonlyArray<OperatorOption<DateFilterOperator>>;
12
+ declare const SELECT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<SelectFilterOperator>>;
13
+ declare const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<OperatorOption<BooleanFilterOperator>>;
24
14
  declare function getDefaultOperator(variant: string): FilterOperator;
25
- declare function getOperatorsForVariant(variant: string): ReadonlyArray<{
15
+ /**
16
+ * Toán tử hợp lệ cho một kiểu ô, kèm nhãn đã dịch.
17
+ *
18
+ * `messages` bỏ trống = bảng mặc định (tiếng Anh) — giữ đúng chữ ký của `1.11.0` nên chỗ gọi cũ
19
+ * không phải sửa.
20
+ */
21
+ declare function getOperatorsForVariant(variant: string, messages?: DataGridMessages): ReadonlyArray<{
26
22
  label: string;
27
23
  value: FilterOperator;
28
24
  }>;
@@ -1,49 +1,69 @@
1
- import { msg } from "./messages.js";
2
- const op = msg.filter.operators;
3
- const TEXT_FILTER_OPERATORS = [
4
- { label: op.contains, value: "contains" },
5
- { label: op.notContains, value: "notContains" },
6
- { label: op.equals, value: "equals" },
7
- { label: op.notEquals, value: "notEquals" },
8
- { label: op.startsWith, value: "startsWith" },
9
- { label: op.endsWith, value: "endsWith" },
10
- { label: op.isEmpty, value: "isEmpty" },
11
- { label: op.isNotEmpty, value: "isNotEmpty" }
12
- ];
13
- const NUMBER_FILTER_OPERATORS = [
14
- { label: op.equals, value: "equals" },
15
- { label: op.notEquals, value: "notEquals" },
16
- { label: op.lessThan, value: "lessThan" },
17
- { label: op.lessThanOrEqual, value: "lessThanOrEqual" },
18
- { label: op.greaterThan, value: "greaterThan" },
19
- { label: op.greaterThanOrEqual, value: "greaterThanOrEqual" },
20
- { label: op.isBetween, value: "isBetween" },
21
- { label: op.isEmpty, value: "isEmpty" },
22
- { label: op.isNotEmpty, value: "isNotEmpty" }
23
- ];
24
- const DATE_FILTER_OPERATORS = [
25
- { label: op.dateEquals, value: "equals" },
26
- { label: op.dateNotEquals, value: "notEquals" },
27
- { label: op.before, value: "before" },
28
- { label: op.after, value: "after" },
29
- { label: op.onOrBefore, value: "onOrBefore" },
30
- { label: op.onOrAfter, value: "onOrAfter" },
31
- { label: op.isBetween, value: "isBetween" },
32
- { label: op.isEmpty, value: "isEmpty" },
33
- { label: op.isNotEmpty, value: "isNotEmpty" }
34
- ];
35
- const SELECT_FILTER_OPERATORS = [
36
- { label: op.is, value: "is" },
37
- { label: op.isNot, value: "isNot" },
38
- { label: op.isAnyOf, value: "isAnyOf" },
39
- { label: op.isNoneOf, value: "isNoneOf" },
40
- { label: op.isEmpty, value: "isEmpty" },
41
- { label: op.isNotEmpty, value: "isNotEmpty" }
42
- ];
43
- const BOOLEAN_FILTER_OPERATORS = [
44
- { label: op.isTrue, value: "isTrue" },
45
- { label: op.isFalse, value: "isFalse" }
46
- ];
1
+ import { getDataGridMessages } from "./messages.js";
2
+ function buildTextOperators(m) {
3
+ const op = m.filter.operators;
4
+ return [
5
+ { label: op.contains, value: "contains" },
6
+ { label: op.notContains, value: "notContains" },
7
+ { label: op.equals, value: "equals" },
8
+ { label: op.notEquals, value: "notEquals" },
9
+ { label: op.startsWith, value: "startsWith" },
10
+ { label: op.endsWith, value: "endsWith" },
11
+ { label: op.isEmpty, value: "isEmpty" },
12
+ { label: op.isNotEmpty, value: "isNotEmpty" }
13
+ ];
14
+ }
15
+ function buildNumberOperators(m) {
16
+ const op = m.filter.operators;
17
+ return [
18
+ { label: op.equals, value: "equals" },
19
+ { label: op.notEquals, value: "notEquals" },
20
+ { label: op.lessThan, value: "lessThan" },
21
+ { label: op.lessThanOrEqual, value: "lessThanOrEqual" },
22
+ { label: op.greaterThan, value: "greaterThan" },
23
+ { label: op.greaterThanOrEqual, value: "greaterThanOrEqual" },
24
+ { label: op.isBetween, value: "isBetween" },
25
+ { label: op.isEmpty, value: "isEmpty" },
26
+ { label: op.isNotEmpty, value: "isNotEmpty" }
27
+ ];
28
+ }
29
+ function buildDateOperators(m) {
30
+ const op = m.filter.operators;
31
+ return [
32
+ { label: op.dateEquals, value: "equals" },
33
+ { label: op.dateNotEquals, value: "notEquals" },
34
+ { label: op.before, value: "before" },
35
+ { label: op.after, value: "after" },
36
+ { label: op.onOrBefore, value: "onOrBefore" },
37
+ { label: op.onOrAfter, value: "onOrAfter" },
38
+ { label: op.isBetween, value: "isBetween" },
39
+ { label: op.isEmpty, value: "isEmpty" },
40
+ { label: op.isNotEmpty, value: "isNotEmpty" }
41
+ ];
42
+ }
43
+ function buildSelectOperators(m) {
44
+ const op = m.filter.operators;
45
+ return [
46
+ { label: op.is, value: "is" },
47
+ { label: op.isNot, value: "isNot" },
48
+ { label: op.isAnyOf, value: "isAnyOf" },
49
+ { label: op.isNoneOf, value: "isNoneOf" },
50
+ { label: op.isEmpty, value: "isEmpty" },
51
+ { label: op.isNotEmpty, value: "isNotEmpty" }
52
+ ];
53
+ }
54
+ function buildBooleanOperators(m) {
55
+ const op = m.filter.operators;
56
+ return [
57
+ { label: op.isTrue, value: "isTrue" },
58
+ { label: op.isFalse, value: "isFalse" }
59
+ ];
60
+ }
61
+ const DEFAULT_MESSAGES = getDataGridMessages();
62
+ const TEXT_FILTER_OPERATORS = buildTextOperators(DEFAULT_MESSAGES);
63
+ const NUMBER_FILTER_OPERATORS = buildNumberOperators(DEFAULT_MESSAGES);
64
+ const DATE_FILTER_OPERATORS = buildDateOperators(DEFAULT_MESSAGES);
65
+ const SELECT_FILTER_OPERATORS = buildSelectOperators(DEFAULT_MESSAGES);
66
+ const BOOLEAN_FILTER_OPERATORS = buildBooleanOperators(DEFAULT_MESSAGES);
47
67
  function getDefaultOperator(variant) {
48
68
  switch (variant) {
49
69
  case "number":
@@ -59,19 +79,20 @@ function getDefaultOperator(variant) {
59
79
  return "contains";
60
80
  }
61
81
  }
62
- function getOperatorsForVariant(variant) {
82
+ function getOperatorsForVariant(variant, messages) {
83
+ const m = messages ?? DEFAULT_MESSAGES;
63
84
  switch (variant) {
64
85
  case "number":
65
- return NUMBER_FILTER_OPERATORS;
86
+ return buildNumberOperators(m);
66
87
  case "date":
67
- return DATE_FILTER_OPERATORS;
88
+ return buildDateOperators(m);
68
89
  case "select":
69
90
  case "multi-select":
70
- return SELECT_FILTER_OPERATORS;
91
+ return buildSelectOperators(m);
71
92
  case "checkbox":
72
- return BOOLEAN_FILTER_OPERATORS;
93
+ return buildBooleanOperators(m);
73
94
  default:
74
- return TEXT_FILTER_OPERATORS;
95
+ return buildTextOperators(m);
75
96
  }
76
97
  }
77
98
  function getFilterFn() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-grid/filters.ts"],"sourcesContent":["import type { FilterFn, Row } from \"@tanstack/react-table\";\nimport { msg } from \"./messages.js\";\nimport type {\n BooleanFilterOperator,\n DateFilterOperator,\n FilterOperator,\n FilterValue,\n NumberFilterOperator,\n SelectFilterOperator,\n TextFilterOperator\n} from \"./types.js\";\n\nconst op = msg.filter.operators;\n\nexport const TEXT_FILTER_OPERATORS: ReadonlyArray<{\n label: string;\n value: TextFilterOperator;\n}> = [\n { label: op.contains, value: \"contains\" },\n { label: op.notContains, value: \"notContains\" },\n { label: op.equals, value: \"equals\" },\n { label: op.notEquals, value: \"notEquals\" },\n { label: op.startsWith, value: \"startsWith\" },\n { label: op.endsWith, value: \"endsWith\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n];\n\nexport const NUMBER_FILTER_OPERATORS: ReadonlyArray<{\n label: string;\n value: NumberFilterOperator;\n}> = [\n { label: op.equals, value: \"equals\" },\n { label: op.notEquals, value: \"notEquals\" },\n { label: op.lessThan, value: \"lessThan\" },\n { label: op.lessThanOrEqual, value: \"lessThanOrEqual\" },\n { label: op.greaterThan, value: \"greaterThan\" },\n { label: op.greaterThanOrEqual, value: \"greaterThanOrEqual\" },\n { label: op.isBetween, value: \"isBetween\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n];\n\nexport const DATE_FILTER_OPERATORS: ReadonlyArray<{\n label: string;\n value: DateFilterOperator;\n}> = [\n { label: op.dateEquals, value: \"equals\" },\n { label: op.dateNotEquals, value: \"notEquals\" },\n { label: op.before, value: \"before\" },\n { label: op.after, value: \"after\" },\n { label: op.onOrBefore, value: \"onOrBefore\" },\n { label: op.onOrAfter, value: \"onOrAfter\" },\n { label: op.isBetween, value: \"isBetween\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n];\n\nexport const SELECT_FILTER_OPERATORS: ReadonlyArray<{\n label: string;\n value: SelectFilterOperator;\n}> = [\n { label: op.is, value: \"is\" },\n { label: op.isNot, value: \"isNot\" },\n { label: op.isAnyOf, value: \"isAnyOf\" },\n { label: op.isNoneOf, value: \"isNoneOf\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n];\n\nexport const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<{\n label: string;\n value: BooleanFilterOperator;\n}> = [\n { label: op.isTrue, value: \"isTrue\" },\n { label: op.isFalse, value: \"isFalse\" }\n];\n\nexport function getDefaultOperator(variant: string): FilterOperator {\n switch (variant) {\n case \"number\":\n return \"equals\";\n case \"date\":\n return \"equals\";\n case \"select\":\n case \"multi-select\":\n return \"is\";\n case \"checkbox\":\n return \"isTrue\";\n default:\n return \"contains\";\n }\n}\n\nexport function getOperatorsForVariant(variant: string): ReadonlyArray<{\n label: string;\n value: FilterOperator;\n}> {\n switch (variant) {\n case \"number\":\n return NUMBER_FILTER_OPERATORS;\n case \"date\":\n return DATE_FILTER_OPERATORS;\n case \"select\":\n case \"multi-select\":\n return SELECT_FILTER_OPERATORS;\n case \"checkbox\":\n return BOOLEAN_FILTER_OPERATORS;\n default:\n return TEXT_FILTER_OPERATORS;\n }\n}\n\nexport function getFilterFn<TData>(): FilterFn<TData> {\n return (row: Row<TData>, columnId: string, filterValue: unknown): boolean => {\n if (!filterValue || typeof filterValue !== \"object\") {\n return true;\n }\n\n const filter = filterValue as FilterValue;\n const { operator, value, endValue } = filter;\n\n const cellValue = row.getValue(columnId);\n\n if (operator === \"isEmpty\") {\n return (\n cellValue === null ||\n cellValue === undefined ||\n cellValue === \"\" ||\n (Array.isArray(cellValue) && cellValue.length === 0)\n );\n }\n\n if (operator === \"isNotEmpty\") {\n return !(\n cellValue === null ||\n cellValue === undefined ||\n cellValue === \"\" ||\n (Array.isArray(cellValue) && cellValue.length === 0)\n );\n }\n\n if (operator === \"isTrue\") {\n return cellValue === true;\n }\n\n if (operator === \"isFalse\") {\n return cellValue === false || !cellValue;\n }\n\n if (value === undefined || value === null || value === \"\") {\n return true;\n }\n\n const cellValueStr = String(cellValue ?? \"\").toLowerCase();\n const filterValueStr = typeof value === \"string\" ? value.toLowerCase() : String(value);\n\n if (operator === \"contains\") {\n return cellValueStr.includes(filterValueStr);\n }\n\n if (operator === \"notContains\") {\n return !cellValueStr.includes(filterValueStr);\n }\n\n if (operator === \"equals\") {\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n return cellValue === value;\n }\n if (cellValue instanceof Date && typeof value === \"string\") {\n const cellDate = new Date(cellValue);\n const filterDate = new Date(value);\n return cellDate.toDateString() === filterDate.toDateString();\n }\n return cellValueStr === filterValueStr;\n }\n\n if (operator === \"notEquals\") {\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n return cellValue !== value;\n }\n if (cellValue instanceof Date && typeof value === \"string\") {\n const cellDate = new Date(cellValue);\n const filterDate = new Date(value);\n return cellDate.toDateString() !== filterDate.toDateString();\n }\n return cellValueStr !== filterValueStr;\n }\n\n if (operator === \"startsWith\") {\n return cellValueStr.startsWith(filterValueStr);\n }\n\n if (operator === \"endsWith\") {\n return cellValueStr.endsWith(filterValueStr);\n }\n\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n if (operator === \"greaterThan\") {\n return cellValue > value;\n }\n\n if (operator === \"greaterThanOrEqual\") {\n return cellValue >= value;\n }\n\n if (operator === \"lessThan\") {\n return cellValue < value;\n }\n\n if (operator === \"lessThanOrEqual\") {\n return cellValue <= value;\n }\n\n if (operator === \"isBetween\" && typeof endValue === \"number\") {\n return cellValue >= value && cellValue <= endValue;\n }\n }\n\n if (cellValue instanceof Date || typeof cellValue === \"string\") {\n const cellDate = new Date(cellValue);\n if (!Number.isNaN(cellDate.getTime()) && typeof value === \"string\") {\n const filterDate = new Date(value);\n\n if (operator === \"before\") {\n return cellDate < filterDate;\n }\n\n if (operator === \"after\") {\n return cellDate > filterDate;\n }\n\n if (operator === \"onOrBefore\") {\n return cellDate <= filterDate;\n }\n\n if (operator === \"onOrAfter\") {\n return cellDate >= filterDate;\n }\n\n if (operator === \"isBetween\" && typeof endValue === \"string\") {\n const filterDate2 = new Date(endValue);\n return cellDate >= filterDate && cellDate <= filterDate2;\n }\n }\n }\n\n if (operator === \"is\") {\n if (Array.isArray(cellValue)) {\n return cellValue.some((v) => String(v) === String(value));\n }\n return String(cellValue) === String(value);\n }\n\n if (operator === \"isNot\") {\n if (Array.isArray(cellValue)) {\n return !cellValue.some((v) => String(v) === String(value));\n }\n return String(cellValue) !== String(value);\n }\n\n if (operator === \"isAnyOf\" && Array.isArray(value)) {\n if (Array.isArray(cellValue)) {\n return cellValue.some((v) => value.some((fv) => String(v) === String(fv)));\n }\n return value.some((fv) => String(cellValue) === String(fv));\n }\n\n if (operator === \"isNoneOf\" && Array.isArray(value)) {\n if (Array.isArray(cellValue)) {\n return !cellValue.some((v) => value.some((fv) => String(v) === String(fv)));\n }\n return !value.some((fv) => String(cellValue) === String(fv));\n }\n\n return true;\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/data-grid/filters.ts"],"sourcesContent":["import type { FilterFn, Row } from \"@tanstack/react-table\";\nimport { type DataGridMessages, getDataGridMessages } from \"./messages.js\";\nimport type {\n BooleanFilterOperator,\n DateFilterOperator,\n FilterOperator,\n FilterValue,\n NumberFilterOperator,\n SelectFilterOperator,\n TextFilterOperator\n} from \"./types.js\";\n\ninterface OperatorOption<TOperator extends FilterOperator> {\n label: string;\n value: TOperator;\n}\n\n/*\n * ⚠ Nhãn toán tử phụ thuộc NGÔN NGỮ, nên chúng phải dựng theo bảng chuỗi chứ không đóng băng vào\n * một mảng hằng ở đầu module. Sáu `build*` bên dưới là khuôn; sáu hằng `*_FILTER_OPERATORS` là\n * khuôn ấy áp cho bảng MẶC ĐỊNH (tiếng Anh), giữ lại vì chúng là API công khai từ `1.11.0` và vì\n * phần lớn app chỉ cần đúng bản đó.\n * Chỗ nào dựng giao diện theo `locale` thì gọi `getOperatorsForVariant(variant, messages)` —\n * đọc hằng ở trên là khoá cứng tiếng Anh.\n */\nfunction buildTextOperators(m: DataGridMessages): OperatorOption<TextFilterOperator>[] {\n const op = m.filter.operators;\n return [\n { label: op.contains, value: \"contains\" },\n { label: op.notContains, value: \"notContains\" },\n { label: op.equals, value: \"equals\" },\n { label: op.notEquals, value: \"notEquals\" },\n { label: op.startsWith, value: \"startsWith\" },\n { label: op.endsWith, value: \"endsWith\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n ];\n}\n\nfunction buildNumberOperators(m: DataGridMessages): OperatorOption<NumberFilterOperator>[] {\n const op = m.filter.operators;\n return [\n { label: op.equals, value: \"equals\" },\n { label: op.notEquals, value: \"notEquals\" },\n { label: op.lessThan, value: \"lessThan\" },\n { label: op.lessThanOrEqual, value: \"lessThanOrEqual\" },\n { label: op.greaterThan, value: \"greaterThan\" },\n { label: op.greaterThanOrEqual, value: \"greaterThanOrEqual\" },\n { label: op.isBetween, value: \"isBetween\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n ];\n}\n\nfunction buildDateOperators(m: DataGridMessages): OperatorOption<DateFilterOperator>[] {\n const op = m.filter.operators;\n return [\n { label: op.dateEquals, value: \"equals\" },\n { label: op.dateNotEquals, value: \"notEquals\" },\n { label: op.before, value: \"before\" },\n { label: op.after, value: \"after\" },\n { label: op.onOrBefore, value: \"onOrBefore\" },\n { label: op.onOrAfter, value: \"onOrAfter\" },\n { label: op.isBetween, value: \"isBetween\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n ];\n}\n\nfunction buildSelectOperators(m: DataGridMessages): OperatorOption<SelectFilterOperator>[] {\n const op = m.filter.operators;\n return [\n { label: op.is, value: \"is\" },\n { label: op.isNot, value: \"isNot\" },\n { label: op.isAnyOf, value: \"isAnyOf\" },\n { label: op.isNoneOf, value: \"isNoneOf\" },\n { label: op.isEmpty, value: \"isEmpty\" },\n { label: op.isNotEmpty, value: \"isNotEmpty\" }\n ];\n}\n\nfunction buildBooleanOperators(m: DataGridMessages): OperatorOption<BooleanFilterOperator>[] {\n const op = m.filter.operators;\n return [\n { label: op.isTrue, value: \"isTrue\" },\n { label: op.isFalse, value: \"isFalse\" }\n ];\n}\n\nconst DEFAULT_MESSAGES = getDataGridMessages();\n\nexport const TEXT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<TextFilterOperator>> =\n buildTextOperators(DEFAULT_MESSAGES);\nexport const NUMBER_FILTER_OPERATORS: ReadonlyArray<OperatorOption<NumberFilterOperator>> =\n buildNumberOperators(DEFAULT_MESSAGES);\nexport const DATE_FILTER_OPERATORS: ReadonlyArray<OperatorOption<DateFilterOperator>> =\n buildDateOperators(DEFAULT_MESSAGES);\nexport const SELECT_FILTER_OPERATORS: ReadonlyArray<OperatorOption<SelectFilterOperator>> =\n buildSelectOperators(DEFAULT_MESSAGES);\nexport const BOOLEAN_FILTER_OPERATORS: ReadonlyArray<OperatorOption<BooleanFilterOperator>> =\n buildBooleanOperators(DEFAULT_MESSAGES);\n\nexport function getDefaultOperator(variant: string): FilterOperator {\n switch (variant) {\n case \"number\":\n return \"equals\";\n case \"date\":\n return \"equals\";\n case \"select\":\n case \"multi-select\":\n return \"is\";\n case \"checkbox\":\n return \"isTrue\";\n default:\n return \"contains\";\n }\n}\n\n/**\n * Toán tử hợp lệ cho một kiểu ô, kèm nhãn đã dịch.\n *\n * `messages` bỏ trống = bảng mặc định (tiếng Anh) — giữ đúng chữ ký của `1.11.0` nên chỗ gọi cũ\n * không phải sửa.\n */\nexport function getOperatorsForVariant(\n variant: string,\n messages?: DataGridMessages\n): ReadonlyArray<{\n label: string;\n value: FilterOperator;\n}> {\n const m = messages ?? DEFAULT_MESSAGES;\n switch (variant) {\n case \"number\":\n return buildNumberOperators(m);\n case \"date\":\n return buildDateOperators(m);\n case \"select\":\n case \"multi-select\":\n return buildSelectOperators(m);\n case \"checkbox\":\n return buildBooleanOperators(m);\n default:\n return buildTextOperators(m);\n }\n}\n\nexport function getFilterFn<TData>(): FilterFn<TData> {\n return (row: Row<TData>, columnId: string, filterValue: unknown): boolean => {\n if (!filterValue || typeof filterValue !== \"object\") {\n return true;\n }\n\n const filter = filterValue as FilterValue;\n const { operator, value, endValue } = filter;\n\n const cellValue = row.getValue(columnId);\n\n if (operator === \"isEmpty\") {\n return (\n cellValue === null ||\n cellValue === undefined ||\n cellValue === \"\" ||\n (Array.isArray(cellValue) && cellValue.length === 0)\n );\n }\n\n if (operator === \"isNotEmpty\") {\n return !(\n cellValue === null ||\n cellValue === undefined ||\n cellValue === \"\" ||\n (Array.isArray(cellValue) && cellValue.length === 0)\n );\n }\n\n if (operator === \"isTrue\") {\n return cellValue === true;\n }\n\n if (operator === \"isFalse\") {\n return cellValue === false || !cellValue;\n }\n\n if (value === undefined || value === null || value === \"\") {\n return true;\n }\n\n const cellValueStr = String(cellValue ?? \"\").toLowerCase();\n const filterValueStr = typeof value === \"string\" ? value.toLowerCase() : String(value);\n\n if (operator === \"contains\") {\n return cellValueStr.includes(filterValueStr);\n }\n\n if (operator === \"notContains\") {\n return !cellValueStr.includes(filterValueStr);\n }\n\n if (operator === \"equals\") {\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n return cellValue === value;\n }\n if (cellValue instanceof Date && typeof value === \"string\") {\n const cellDate = new Date(cellValue);\n const filterDate = new Date(value);\n return cellDate.toDateString() === filterDate.toDateString();\n }\n return cellValueStr === filterValueStr;\n }\n\n if (operator === \"notEquals\") {\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n return cellValue !== value;\n }\n if (cellValue instanceof Date && typeof value === \"string\") {\n const cellDate = new Date(cellValue);\n const filterDate = new Date(value);\n return cellDate.toDateString() !== filterDate.toDateString();\n }\n return cellValueStr !== filterValueStr;\n }\n\n if (operator === \"startsWith\") {\n return cellValueStr.startsWith(filterValueStr);\n }\n\n if (operator === \"endsWith\") {\n return cellValueStr.endsWith(filterValueStr);\n }\n\n if (typeof cellValue === \"number\" && typeof value === \"number\") {\n if (operator === \"greaterThan\") {\n return cellValue > value;\n }\n\n if (operator === \"greaterThanOrEqual\") {\n return cellValue >= value;\n }\n\n if (operator === \"lessThan\") {\n return cellValue < value;\n }\n\n if (operator === \"lessThanOrEqual\") {\n return cellValue <= value;\n }\n\n if (operator === \"isBetween\" && typeof endValue === \"number\") {\n return cellValue >= value && cellValue <= endValue;\n }\n }\n\n if (cellValue instanceof Date || typeof cellValue === \"string\") {\n const cellDate = new Date(cellValue);\n if (!Number.isNaN(cellDate.getTime()) && typeof value === \"string\") {\n const filterDate = new Date(value);\n\n if (operator === \"before\") {\n return cellDate < filterDate;\n }\n\n if (operator === \"after\") {\n return cellDate > filterDate;\n }\n\n if (operator === \"onOrBefore\") {\n return cellDate <= filterDate;\n }\n\n if (operator === \"onOrAfter\") {\n return cellDate >= filterDate;\n }\n\n if (operator === \"isBetween\" && typeof endValue === \"string\") {\n const filterDate2 = new Date(endValue);\n return cellDate >= filterDate && cellDate <= filterDate2;\n }\n }\n }\n\n if (operator === \"is\") {\n if (Array.isArray(cellValue)) {\n return cellValue.some((v) => String(v) === String(value));\n }\n return String(cellValue) === String(value);\n }\n\n if (operator === \"isNot\") {\n if (Array.isArray(cellValue)) {\n return !cellValue.some((v) => String(v) === String(value));\n }\n return String(cellValue) !== String(value);\n }\n\n if (operator === \"isAnyOf\" && Array.isArray(value)) {\n if (Array.isArray(cellValue)) {\n return cellValue.some((v) => value.some((fv) => String(v) === String(fv)));\n }\n return value.some((fv) => String(cellValue) === String(fv));\n }\n\n if (operator === \"isNoneOf\" && Array.isArray(value)) {\n if (Array.isArray(cellValue)) {\n return !cellValue.some((v) => value.some((fv) => String(v) === String(fv)));\n }\n return !value.some((fv) => String(cellValue) === String(fv));\n }\n\n return true;\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  export { DataGrid } from './data-grid.js';
2
2
  export { DataGridFilterMenu } from './data-grid-filter-menu.js';
3
3
  export { DataGridKeyboardShortcuts } from './data-grid-keyboard-shortcuts.js';
4
+ export { DataGridLocaleProvider, DataGridLocaleProviderProps, useDataGridMessages } from './data-grid-locale.js';
4
5
  export { DataGridCellPresence, DataGridPresenceProvider, useDataGridPresence } from './data-grid-presence.js';
5
6
  export { DataGridRowHeightMenu } from './data-grid-row-height-menu.js';
6
7
  export { getDataGridSelectColumn } from './data-grid-select-column.js';
@@ -8,11 +9,13 @@ export { DataGridSkeleton, DataGridSkeletonGrid, DataGridSkeletonToolbar } from
8
9
  export { DataGridSortMenu } from './data-grid-sort-menu.js';
9
10
  export { DataGridViewMenu } from './data-grid-view-menu.js';
10
11
  export { BOOLEAN_FILTER_OPERATORS, DATE_FILTER_OPERATORS, NUMBER_FILTER_OPERATORS, SELECT_FILTER_OPERATORS, TEXT_FILTER_OPERATORS, getDefaultOperator, getFilterFn, getOperatorsForVariant } from './filters.js';
11
- export { DataGridMessages, msg as dataGridMessages } from './messages.js';
12
+ export { DATA_GRID_MESSAGES, DEFAULT_DATA_GRID_LOCALE, DataGridLocale, getDataGridMessages } from './messages.js';
12
13
  export { BooleanFilterOperator, CellOpts, CellPosition, CellRange, CellSelectOption, CellUpdate, ContextMenuState, DataGridCellProps, DateFilterOperator, Direction, FileCellData, FilterOperator, FilterValue, NavigationDirection, NumberFilterOperator, PasteDialogState, RowHeightValue, SearchState, SelectFilterOperator, SelectionState, TextFilterOperator } from './types.js';
13
14
  export { UseDataGridProps, useDataGrid } from './use-data-grid.js';
14
15
  export { UndoRedoCellUpdate, useDataGridUndoRedo } from './use-data-grid-undo-redo.js';
15
16
  export { formatDate, formatDateForDisplay, formatDateToString, formatFileSize, generateFileId, getCellKey, getColumnVariant, getEmptyCellValue, getLineCount, getRowHeightValue, parseCellKey, parseLocalDate } from './utils.js';
17
+ export { DataGridMessages, messagesEn as dataGridMessages, messagesEn as dataGridMessagesEn } from './messages-en.js';
18
+ export { messagesVi as dataGridMessagesVi } from './messages-vi.js';
16
19
  import 'react';
17
20
  import '@tanstack/react-table';
18
21
  import '../components/ui/popover.js';
@@ -1,6 +1,10 @@
1
1
  import { DataGrid } from "./data-grid.js";
2
2
  import { DataGridFilterMenu } from "./data-grid-filter-menu.js";
3
3
  import { DataGridKeyboardShortcuts } from "./data-grid-keyboard-shortcuts.js";
4
+ import {
5
+ DataGridLocaleProvider,
6
+ useDataGridMessages
7
+ } from "./data-grid-locale.js";
4
8
  import {
5
9
  DataGridPresenceProvider,
6
10
  useDataGridPresence
@@ -20,7 +24,14 @@ import {
20
24
  SELECT_FILTER_OPERATORS,
21
25
  TEXT_FILTER_OPERATORS
22
26
  } from "./filters.js";
23
- import { msg } from "./messages.js";
27
+ import {
28
+ DATA_GRID_MESSAGES,
29
+ DEFAULT_DATA_GRID_LOCALE,
30
+ getDataGridMessages,
31
+ messagesEn,
32
+ messagesEn as messagesEn2,
33
+ messagesVi
34
+ } from "./messages.js";
24
35
  import { useDataGrid } from "./use-data-grid.js";
25
36
  import { useDataGridUndoRedo } from "./use-data-grid-undo-redo.js";
26
37
  import {
@@ -39,10 +50,13 @@ import {
39
50
  } from "./utils.js";
40
51
  export {
41
52
  BOOLEAN_FILTER_OPERATORS,
53
+ DATA_GRID_MESSAGES,
42
54
  DATE_FILTER_OPERATORS,
55
+ DEFAULT_DATA_GRID_LOCALE,
43
56
  DataGrid,
44
57
  DataGridFilterMenu,
45
58
  DataGridKeyboardShortcuts,
59
+ DataGridLocaleProvider,
46
60
  DataGridPresenceProvider,
47
61
  DataGridRowHeightMenu,
48
62
  DataGridSkeleton,
@@ -53,7 +67,9 @@ export {
53
67
  NUMBER_FILTER_OPERATORS,
54
68
  SELECT_FILTER_OPERATORS,
55
69
  TEXT_FILTER_OPERATORS,
56
- msg as dataGridMessages,
70
+ messagesEn as dataGridMessages,
71
+ messagesEn2 as dataGridMessagesEn,
72
+ messagesVi as dataGridMessagesVi,
57
73
  formatDate,
58
74
  formatDateForDisplay,
59
75
  formatDateToString,
@@ -61,6 +77,7 @@ export {
61
77
  generateFileId,
62
78
  getCellKey,
63
79
  getColumnVariant,
80
+ getDataGridMessages,
64
81
  getDataGridSelectColumn,
65
82
  getDefaultOperator,
66
83
  getEmptyCellValue,
@@ -71,6 +88,7 @@ export {
71
88
  parseCellKey,
72
89
  parseLocalDate,
73
90
  useDataGrid,
91
+ useDataGridMessages,
74
92
  useDataGridPresence,
75
93
  useDataGridUndoRedo
76
94
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-grid/index.ts"],"sourcesContent":["// @comitor/ui/data-grid — lưới dữ liệu sửa trực tiếp (như bảng tính).\n//\n// Port từ tablecn (https://tablecn.com) — MIT License, Copyright (c) 2024 Sadman Sakib —\n// và chỉnh lại để dùng primitive/token của package, chuỗi tiếng Việt, không phụ thuộc backend.\n// Xem docs/data-grid.md (§10) để biết danh sách khác biệt so với bản gốc.\n//\n// Tách khỏi barrel chính vì kéo theo @tanstack/react-table (peer), @tanstack/react-virtual và @dnd-kit,\n// đồng thời khoanh vùng phần `declare module \"@tanstack/react-table\"` (thêm `meta.cell`, `TableMeta`)\n// để ứng dụng không dùng lưới không bị ảnh hưởng.\n\n// Components\nexport { DataGrid } from \"./data-grid.js\";\nexport { DataGridFilterMenu } from \"./data-grid-filter-menu.js\";\nexport { DataGridKeyboardShortcuts } from \"./data-grid-keyboard-shortcuts.js\";\nexport {\n type DataGridCellPresence,\n DataGridPresenceProvider,\n useDataGridPresence\n} from \"./data-grid-presence.js\";\nexport { DataGridRowHeightMenu } from \"./data-grid-row-height-menu.js\";\nexport { getDataGridSelectColumn } from \"./data-grid-select-column.js\";\nexport { DataGridSkeleton, DataGridSkeletonGrid, DataGridSkeletonToolbar } from \"./data-grid-skeleton.js\";\nexport { DataGridSortMenu } from \"./data-grid-sort-menu.js\";\nexport { DataGridViewMenu } from \"./data-grid-view-menu.js\";\n// Bộ lọc\nexport {\n BOOLEAN_FILTER_OPERATORS,\n DATE_FILTER_OPERATORS,\n getDefaultOperator,\n getFilterFn,\n getOperatorsForVariant,\n NUMBER_FILTER_OPERATORS,\n SELECT_FILTER_OPERATORS,\n TEXT_FILTER_OPERATORS\n} from \"./filters.js\";\n// Chuỗi hiển thị (dùng lại khi app muốn nhất quán từ ngữ)\nexport { type DataGridMessages, msg as dataGridMessages } from \"./messages.js\";\n// Types\nexport type * from \"./types.js\";\n// Hooks\nexport { type UseDataGridProps, useDataGrid } from \"./use-data-grid.js\";\nexport { type UndoRedoCellUpdate, useDataGridUndoRedo } from \"./use-data-grid-undo-redo.js\";\n// Tiện ích hay dùng ở phía ứng dụng\nexport {\n formatDate,\n formatDateForDisplay,\n formatDateToString,\n formatFileSize,\n generateFileId,\n getCellKey,\n getColumnVariant,\n getEmptyCellValue,\n getLineCount,\n getRowHeightValue,\n parseCellKey,\n parseLocalDate\n} from \"./utils.js\";\n"],"mappings":"AAWA,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,iCAAiC;AAC1C;AAAA,EAEE;AAAA,EACA;AAAA,OACK;AACP,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,kBAAkB,sBAAsB,+BAA+B;AAChF,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAEjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAuC,WAAwB;AAI/D,SAAgC,mBAAmB;AACnD,SAAkC,2BAA2B;AAE7D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
1
+ {"version":3,"sources":["../../src/data-grid/index.ts"],"sourcesContent":["// @comitor/ui/data-grid — lưới dữ liệu sửa trực tiếp (như bảng tính).\n//\n// Port từ tablecn (https://tablecn.com) — MIT License, Copyright (c) 2024 Sadman Sakib —\n// và chỉnh lại để dùng primitive/token của package, chuỗi tiếng Việt, không phụ thuộc backend.\n// Xem docs/data-grid.md (§10) để biết danh sách khác biệt so với bản gốc.\n//\n// Tách khỏi barrel chính vì kéo theo @tanstack/react-table (peer), @tanstack/react-virtual và @dnd-kit,\n// đồng thời khoanh vùng phần `declare module \"@tanstack/react-table\"` (thêm `meta.cell`, `TableMeta`)\n// để ứng dụng không dùng lưới không bị ảnh hưởng.\n\n// Components\nexport { DataGrid } from \"./data-grid.js\";\nexport { DataGridFilterMenu } from \"./data-grid-filter-menu.js\";\nexport { DataGridKeyboardShortcuts } from \"./data-grid-keyboard-shortcuts.js\";\n// Ngôn ngữ\nexport {\n DataGridLocaleProvider,\n type DataGridLocaleProviderProps,\n useDataGridMessages\n} from \"./data-grid-locale.js\";\nexport {\n type DataGridCellPresence,\n DataGridPresenceProvider,\n useDataGridPresence\n} from \"./data-grid-presence.js\";\nexport { DataGridRowHeightMenu } from \"./data-grid-row-height-menu.js\";\nexport { getDataGridSelectColumn } from \"./data-grid-select-column.js\";\nexport { DataGridSkeleton, DataGridSkeletonGrid, DataGridSkeletonToolbar } from \"./data-grid-skeleton.js\";\nexport { DataGridSortMenu } from \"./data-grid-sort-menu.js\";\nexport { DataGridViewMenu } from \"./data-grid-view-menu.js\";\n// Bộ lọc\nexport {\n BOOLEAN_FILTER_OPERATORS,\n DATE_FILTER_OPERATORS,\n getDefaultOperator,\n getFilterFn,\n getOperatorsForVariant,\n NUMBER_FILTER_OPERATORS,\n SELECT_FILTER_OPERATORS,\n TEXT_FILTER_OPERATORS\n} from \"./filters.js\";\n/*\n * Chuỗi hiển thị. `dataGridMessages` là bảng ĐANG MẶC ĐỊNH (tiếng Anh từ `2.0.0`) — dùng khi app\n * muốn từ ngữ ở chỗ khác trên màn khớp với lưới. Muốn một ngôn ngữ cụ thể thì gọi\n * `getDataGridMessages(\"vi\")`, đừng đọc hằng rồi đoán.\n */\nexport {\n DATA_GRID_MESSAGES,\n type DataGridLocale,\n type DataGridMessages,\n DEFAULT_DATA_GRID_LOCALE,\n getDataGridMessages,\n messagesEn as dataGridMessages,\n messagesEn as dataGridMessagesEn,\n messagesVi as dataGridMessagesVi\n} from \"./messages.js\";\n// Types\nexport type * from \"./types.js\";\n// Hooks\nexport { type UseDataGridProps, useDataGrid } from \"./use-data-grid.js\";\nexport { type UndoRedoCellUpdate, useDataGridUndoRedo } from \"./use-data-grid-undo-redo.js\";\n// Tiện ích hay dùng ở phía ứng dụng\nexport {\n formatDate,\n formatDateForDisplay,\n formatDateToString,\n formatFileSize,\n generateFileId,\n getCellKey,\n getColumnVariant,\n getEmptyCellValue,\n getLineCount,\n getRowHeightValue,\n parseCellKey,\n parseLocalDate\n} from \"./utils.js\";\n"],"mappings":"AAWA,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,iCAAiC;AAE1C;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,OACK;AACP,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,kBAAkB,sBAAsB,+BAA+B;AAChF,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAEjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMP;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACc;AAAA,EACA,cAAdA;AAAA,EACc;AAAA,OACT;AAIP,SAAgC,mBAAmB;AACnD,SAAkC,2BAA2B;AAE7D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":["messagesEn"]}