@qijenchen/design-system 0.1.0-beta.10

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 (507) hide show
  1. package/README.md +163 -0
  2. package/dist/components/Accordion/accordion.d.ts +37 -0
  3. package/dist/components/Accordion/accordion.d.ts.map +1 -0
  4. package/dist/components/Accordion/accordion.js +78 -0
  5. package/dist/components/Accordion/accordion.js.map +1 -0
  6. package/dist/components/Alert/alert.d.ts +47 -0
  7. package/dist/components/Alert/alert.d.ts.map +1 -0
  8. package/dist/components/Alert/alert.js +132 -0
  9. package/dist/components/Alert/alert.js.map +1 -0
  10. package/dist/components/AppShell/_demo-helpers.d.ts +49 -0
  11. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -0
  12. package/dist/components/AppShell/app-shell.d.ts +76 -0
  13. package/dist/components/AppShell/app-shell.d.ts.map +1 -0
  14. package/dist/components/AppShell/app-shell.js +214 -0
  15. package/dist/components/AppShell/app-shell.js.map +1 -0
  16. package/dist/components/AspectRatio/aspect-ratio.d.ts +40 -0
  17. package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -0
  18. package/dist/components/AspectRatio/aspect-ratio.js +23 -0
  19. package/dist/components/AspectRatio/aspect-ratio.js.map +1 -0
  20. package/dist/components/Avatar/avatar.d.ts +85 -0
  21. package/dist/components/Avatar/avatar.d.ts.map +1 -0
  22. package/dist/components/Avatar/avatar.js +195 -0
  23. package/dist/components/Avatar/avatar.js.map +1 -0
  24. package/dist/components/Badge/badge.d.ts +43 -0
  25. package/dist/components/Badge/badge.d.ts.map +1 -0
  26. package/dist/components/Badge/badge.js +69 -0
  27. package/dist/components/Badge/badge.js.map +1 -0
  28. package/dist/components/Breadcrumb/breadcrumb.d.ts +163 -0
  29. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -0
  30. package/dist/components/Breadcrumb/breadcrumb.js +300 -0
  31. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -0
  32. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +46 -0
  33. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -0
  34. package/dist/components/BulkActionBar/bulk-action-bar.js +78 -0
  35. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -0
  36. package/dist/components/Button/button-group.d.ts +49 -0
  37. package/dist/components/Button/button-group.d.ts.map +1 -0
  38. package/dist/components/Button/button-group.js +46 -0
  39. package/dist/components/Button/button-group.js.map +1 -0
  40. package/dist/components/Button/button.d.ts +203 -0
  41. package/dist/components/Button/button.d.ts.map +1 -0
  42. package/dist/components/Button/button.js +309 -0
  43. package/dist/components/Button/button.js.map +1 -0
  44. package/dist/components/Calendar/calendar.d.ts +81 -0
  45. package/dist/components/Calendar/calendar.d.ts.map +1 -0
  46. package/dist/components/Calendar/calendar.js +282 -0
  47. package/dist/components/Calendar/calendar.js.map +1 -0
  48. package/dist/components/Carousel/carousel.d.ts +61 -0
  49. package/dist/components/Carousel/carousel.d.ts.map +1 -0
  50. package/dist/components/Carousel/carousel.js +276 -0
  51. package/dist/components/Carousel/carousel.js.map +1 -0
  52. package/dist/components/Chart/chart.d.ts +94 -0
  53. package/dist/components/Chart/chart.d.ts.map +1 -0
  54. package/dist/components/Chart/chart.js +233 -0
  55. package/dist/components/Chart/chart.js.map +1 -0
  56. package/dist/components/Checkbox/checkbox-group.d.ts +58 -0
  57. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -0
  58. package/dist/components/Checkbox/checkbox-group.js +28 -0
  59. package/dist/components/Checkbox/checkbox-group.js.map +1 -0
  60. package/dist/components/Checkbox/checkbox.d.ts +73 -0
  61. package/dist/components/Checkbox/checkbox.d.ts.map +1 -0
  62. package/dist/components/Checkbox/checkbox.js +125 -0
  63. package/dist/components/Checkbox/checkbox.js.map +1 -0
  64. package/dist/components/Chip/chip.d.ts +54 -0
  65. package/dist/components/Chip/chip.d.ts.map +1 -0
  66. package/dist/components/Chip/chip.js +224 -0
  67. package/dist/components/Chip/chip.js.map +1 -0
  68. package/dist/components/CircularProgress/circular-progress.d.ts +40 -0
  69. package/dist/components/CircularProgress/circular-progress.d.ts.map +1 -0
  70. package/dist/components/CircularProgress/circular-progress.js +118 -0
  71. package/dist/components/CircularProgress/circular-progress.js.map +1 -0
  72. package/dist/components/Coachmark/coachmark.d.ts +100 -0
  73. package/dist/components/Coachmark/coachmark.d.ts.map +1 -0
  74. package/dist/components/Coachmark/coachmark.js +107 -0
  75. package/dist/components/Coachmark/coachmark.js.map +1 -0
  76. package/dist/components/Combobox/combobox.d.ts +150 -0
  77. package/dist/components/Combobox/combobox.d.ts.map +1 -0
  78. package/dist/components/Combobox/combobox.js +595 -0
  79. package/dist/components/Combobox/combobox.js.map +1 -0
  80. package/dist/components/Command/command.d.ts +106 -0
  81. package/dist/components/Command/command.d.ts.map +1 -0
  82. package/dist/components/Command/command.js +123 -0
  83. package/dist/components/Command/command.js.map +1 -0
  84. package/dist/components/DataTable/active-editor-controller.d.ts +66 -0
  85. package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -0
  86. package/dist/components/DataTable/cell-registry.d.ts +37 -0
  87. package/dist/components/DataTable/cell-registry.d.ts.map +1 -0
  88. package/dist/components/DataTable/cell-registry.js +377 -0
  89. package/dist/components/DataTable/cell-registry.js.map +1 -0
  90. package/dist/components/DataTable/column-types.d.ts +145 -0
  91. package/dist/components/DataTable/column-types.d.ts.map +1 -0
  92. package/dist/components/DataTable/column-types.js +17 -0
  93. package/dist/components/DataTable/column-types.js.map +1 -0
  94. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +49 -0
  95. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -0
  96. package/dist/components/DataTable/data-table-filter-panel.d.ts +30 -0
  97. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -0
  98. package/dist/components/DataTable/data-table-interaction-layer.d.ts +78 -0
  99. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -0
  100. package/dist/components/DataTable/data-table-interaction-layer.js +220 -0
  101. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -0
  102. package/dist/components/DataTable/data-table-sort-manager.d.ts +19 -0
  103. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -0
  104. package/dist/components/DataTable/data-table.d.ts +181 -0
  105. package/dist/components/DataTable/data-table.d.ts.map +1 -0
  106. package/dist/components/DataTable/data-table.js +1851 -0
  107. package/dist/components/DataTable/data-table.js.map +1 -0
  108. package/dist/components/DataTable/filter-operators.d.ts +116 -0
  109. package/dist/components/DataTable/filter-operators.d.ts.map +1 -0
  110. package/dist/components/DataTable/filter-tree.d.ts +66 -0
  111. package/dist/components/DataTable/filter-tree.d.ts.map +1 -0
  112. package/dist/components/DataTable/lib/column-meta.d.ts +49 -0
  113. package/dist/components/DataTable/lib/column-meta.d.ts.map +1 -0
  114. package/dist/components/DateGrid/date-grid.d.ts +61 -0
  115. package/dist/components/DateGrid/date-grid.d.ts.map +1 -0
  116. package/dist/components/DateGrid/date-grid.js +168 -0
  117. package/dist/components/DateGrid/date-grid.js.map +1 -0
  118. package/dist/components/DatePicker/date-picker.d.ts +119 -0
  119. package/dist/components/DatePicker/date-picker.d.ts.map +1 -0
  120. package/dist/components/DatePicker/date-picker.js +743 -0
  121. package/dist/components/DatePicker/date-picker.js.map +1 -0
  122. package/dist/components/DescriptionList/description-list.d.ts +60 -0
  123. package/dist/components/DescriptionList/description-list.d.ts.map +1 -0
  124. package/dist/components/DescriptionList/description-list.js +77 -0
  125. package/dist/components/DescriptionList/description-list.js.map +1 -0
  126. package/dist/components/Dialog/dialog.d.ts +54 -0
  127. package/dist/components/Dialog/dialog.d.ts.map +1 -0
  128. package/dist/components/Dialog/dialog.js +151 -0
  129. package/dist/components/Dialog/dialog.js.map +1 -0
  130. package/dist/components/DropdownMenu/dropdown-menu.d.ts +111 -0
  131. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -0
  132. package/dist/components/DropdownMenu/dropdown-menu.js +288 -0
  133. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -0
  134. package/dist/components/Empty/empty.d.ts +40 -0
  135. package/dist/components/Empty/empty.d.ts.map +1 -0
  136. package/dist/components/Empty/empty.js +66 -0
  137. package/dist/components/Empty/empty.js.map +1 -0
  138. package/dist/components/Field/field-context.d.ts +77 -0
  139. package/dist/components/Field/field-context.d.ts.map +1 -0
  140. package/dist/components/Field/field-context.js +37 -0
  141. package/dist/components/Field/field-context.js.map +1 -0
  142. package/dist/components/Field/field-types.d.ts +5 -0
  143. package/dist/components/Field/field-types.d.ts.map +1 -0
  144. package/dist/components/Field/field-types.js +13 -0
  145. package/dist/components/Field/field-types.js.map +1 -0
  146. package/dist/components/Field/field-wrapper.d.ts +17 -0
  147. package/dist/components/Field/field-wrapper.d.ts.map +1 -0
  148. package/dist/components/Field/field-wrapper.js +252 -0
  149. package/dist/components/Field/field-wrapper.js.map +1 -0
  150. package/dist/components/Field/field.d.ts +127 -0
  151. package/dist/components/Field/field.d.ts.map +1 -0
  152. package/dist/components/Field/field.js +295 -0
  153. package/dist/components/Field/field.js.map +1 -0
  154. package/dist/components/FieldControlGroup/field-control-group.d.ts +74 -0
  155. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -0
  156. package/dist/components/FieldControlGroup/field-control-group.js +62 -0
  157. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -0
  158. package/dist/components/FileItem/file-item.d.ts +44 -0
  159. package/dist/components/FileItem/file-item.d.ts.map +1 -0
  160. package/dist/components/FileItem/file-item.js +202 -0
  161. package/dist/components/FileItem/file-item.js.map +1 -0
  162. package/dist/components/FileUpload/file-upload.d.ts +97 -0
  163. package/dist/components/FileUpload/file-upload.d.ts.map +1 -0
  164. package/dist/components/FileUpload/file-upload.js +231 -0
  165. package/dist/components/FileUpload/file-upload.js.map +1 -0
  166. package/dist/components/FileViewer/file-viewer-types.d.ts +73 -0
  167. package/dist/components/FileViewer/file-viewer-types.d.ts.map +1 -0
  168. package/dist/components/FileViewer/file-viewer.d.ts +82 -0
  169. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -0
  170. package/dist/components/FileViewer/file-viewer.js +752 -0
  171. package/dist/components/FileViewer/file-viewer.js.map +1 -0
  172. package/dist/components/FileViewer/image-renderer.d.ts +9 -0
  173. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -0
  174. package/dist/components/FileViewer/image-renderer.js +165 -0
  175. package/dist/components/FileViewer/image-renderer.js.map +1 -0
  176. package/dist/components/HoverCard/hover-card.d.ts +30 -0
  177. package/dist/components/HoverCard/hover-card.d.ts.map +1 -0
  178. package/dist/components/HoverCard/hover-card.js +61 -0
  179. package/dist/components/HoverCard/hover-card.js.map +1 -0
  180. package/dist/components/Input/input.d.ts +72 -0
  181. package/dist/components/Input/input.d.ts.map +1 -0
  182. package/dist/components/Input/input.js +148 -0
  183. package/dist/components/Input/input.js.map +1 -0
  184. package/dist/components/LinkInput/link-input.d.ts +46 -0
  185. package/dist/components/LinkInput/link-input.d.ts.map +1 -0
  186. package/dist/components/LinkInput/link-input.js +215 -0
  187. package/dist/components/LinkInput/link-input.js.map +1 -0
  188. package/dist/components/Menu/menu-item.d.ts +83 -0
  189. package/dist/components/Menu/menu-item.d.ts.map +1 -0
  190. package/dist/components/Menu/menu-item.js +209 -0
  191. package/dist/components/Menu/menu-item.js.map +1 -0
  192. package/dist/components/NameCard/name-card.d.ts +85 -0
  193. package/dist/components/NameCard/name-card.d.ts.map +1 -0
  194. package/dist/components/NameCard/name-card.js +153 -0
  195. package/dist/components/NameCard/name-card.js.map +1 -0
  196. package/dist/components/Notice/notice.d.ts +69 -0
  197. package/dist/components/Notice/notice.d.ts.map +1 -0
  198. package/dist/components/Notice/notice.js +121 -0
  199. package/dist/components/Notice/notice.js.map +1 -0
  200. package/dist/components/NumberInput/number-input.d.ts +57 -0
  201. package/dist/components/NumberInput/number-input.d.ts.map +1 -0
  202. package/dist/components/NumberInput/number-input.js +131 -0
  203. package/dist/components/NumberInput/number-input.js.map +1 -0
  204. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +23 -0
  205. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -0
  206. package/dist/components/OverflowIndicator/overflow-indicator.js +111 -0
  207. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -0
  208. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +57 -0
  209. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -0
  210. package/dist/components/PeoplePicker/avatar-stack-overflow.js +35 -0
  211. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -0
  212. package/dist/components/PeoplePicker/people-picker-helpers.d.ts +7 -0
  213. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -0
  214. package/dist/components/PeoplePicker/people-picker-helpers.js +25 -0
  215. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -0
  216. package/dist/components/PeoplePicker/people-picker.d.ts +77 -0
  217. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -0
  218. package/dist/components/PeoplePicker/people-picker.js +263 -0
  219. package/dist/components/PeoplePicker/people-picker.js.map +1 -0
  220. package/dist/components/PeoplePicker/person-display.d.ts +66 -0
  221. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -0
  222. package/dist/components/PeoplePicker/person-display.js +203 -0
  223. package/dist/components/PeoplePicker/person-display.js.map +1 -0
  224. package/dist/components/Popover/popover.d.ts +50 -0
  225. package/dist/components/Popover/popover.d.ts.map +1 -0
  226. package/dist/components/Popover/popover.js +113 -0
  227. package/dist/components/Popover/popover.js.map +1 -0
  228. package/dist/components/ProgressBar/progress-bar.d.ts +37 -0
  229. package/dist/components/ProgressBar/progress-bar.d.ts.map +1 -0
  230. package/dist/components/ProgressBar/progress-bar.js +86 -0
  231. package/dist/components/ProgressBar/progress-bar.js.map +1 -0
  232. package/dist/components/RadioGroup/radio-group.d.ts +78 -0
  233. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -0
  234. package/dist/components/RadioGroup/radio-group.js +153 -0
  235. package/dist/components/RadioGroup/radio-group.js.map +1 -0
  236. package/dist/components/Rating/rating.d.ts +46 -0
  237. package/dist/components/Rating/rating.d.ts.map +1 -0
  238. package/dist/components/Rating/rating.js +179 -0
  239. package/dist/components/Rating/rating.js.map +1 -0
  240. package/dist/components/ScrollArea/scroll-area.d.ts +45 -0
  241. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -0
  242. package/dist/components/ScrollArea/scroll-area.js +65 -0
  243. package/dist/components/ScrollArea/scroll-area.js.map +1 -0
  244. package/dist/components/SegmentedControl/segmented-control.d.ts +102 -0
  245. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -0
  246. package/dist/components/SegmentedControl/segmented-control.js +171 -0
  247. package/dist/components/SegmentedControl/segmented-control.js.map +1 -0
  248. package/dist/components/Select/select.d.ts +102 -0
  249. package/dist/components/Select/select.d.ts.map +1 -0
  250. package/dist/components/Select/select.js +435 -0
  251. package/dist/components/Select/select.js.map +1 -0
  252. package/dist/components/SelectMenu/select-menu.d.ts +103 -0
  253. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -0
  254. package/dist/components/SelectMenu/select-menu.js +239 -0
  255. package/dist/components/SelectMenu/select-menu.js.map +1 -0
  256. package/dist/components/SelectionControl/selection-item.d.ts +69 -0
  257. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -0
  258. package/dist/components/SelectionControl/selection-item.js +142 -0
  259. package/dist/components/SelectionControl/selection-item.js.map +1 -0
  260. package/dist/components/Separator/separator.d.ts +17 -0
  261. package/dist/components/Separator/separator.d.ts.map +1 -0
  262. package/dist/components/Separator/separator.js +39 -0
  263. package/dist/components/Separator/separator.js.map +1 -0
  264. package/dist/components/Sheet/sheet.d.ts +56 -0
  265. package/dist/components/Sheet/sheet.d.ts.map +1 -0
  266. package/dist/components/Sheet/sheet.js +145 -0
  267. package/dist/components/Sheet/sheet.js.map +1 -0
  268. package/dist/components/Sidebar/sidebar.d.ts +195 -0
  269. package/dist/components/Sidebar/sidebar.d.ts.map +1 -0
  270. package/dist/components/Sidebar/sidebar.js +826 -0
  271. package/dist/components/Sidebar/sidebar.js.map +1 -0
  272. package/dist/components/Skeleton/skeleton.d.ts +16 -0
  273. package/dist/components/Skeleton/skeleton.d.ts.map +1 -0
  274. package/dist/components/Skeleton/skeleton.js +30 -0
  275. package/dist/components/Skeleton/skeleton.js.map +1 -0
  276. package/dist/components/Slider/slider.d.ts +48 -0
  277. package/dist/components/Slider/slider.d.ts.map +1 -0
  278. package/dist/components/Slider/slider.js +108 -0
  279. package/dist/components/Slider/slider.js.map +1 -0
  280. package/dist/components/Steps/steps.d.ts +71 -0
  281. package/dist/components/Steps/steps.d.ts.map +1 -0
  282. package/dist/components/Steps/steps.js +583 -0
  283. package/dist/components/Steps/steps.js.map +1 -0
  284. package/dist/components/Switch/switch.d.ts +112 -0
  285. package/dist/components/Switch/switch.d.ts.map +1 -0
  286. package/dist/components/Switch/switch.js +179 -0
  287. package/dist/components/Switch/switch.js.map +1 -0
  288. package/dist/components/Tabs/tabs.d.ts +104 -0
  289. package/dist/components/Tabs/tabs.d.ts.map +1 -0
  290. package/dist/components/Tabs/tabs.js +316 -0
  291. package/dist/components/Tabs/tabs.js.map +1 -0
  292. package/dist/components/Tag/tag.d.ts +86 -0
  293. package/dist/components/Tag/tag.d.ts.map +1 -0
  294. package/dist/components/Tag/tag.js +172 -0
  295. package/dist/components/Tag/tag.js.map +1 -0
  296. package/dist/components/Textarea/textarea.d.ts +74 -0
  297. package/dist/components/Textarea/textarea.d.ts.map +1 -0
  298. package/dist/components/Textarea/textarea.js +224 -0
  299. package/dist/components/Textarea/textarea.js.map +1 -0
  300. package/dist/components/TimePicker/time-columns.d.ts +46 -0
  301. package/dist/components/TimePicker/time-columns.d.ts.map +1 -0
  302. package/dist/components/TimePicker/time-columns.js +173 -0
  303. package/dist/components/TimePicker/time-columns.js.map +1 -0
  304. package/dist/components/TimePicker/time-picker.d.ts +94 -0
  305. package/dist/components/TimePicker/time-picker.d.ts.map +1 -0
  306. package/dist/components/TimePicker/time-picker.js +253 -0
  307. package/dist/components/TimePicker/time-picker.js.map +1 -0
  308. package/dist/components/Toast/toast.d.ts +61 -0
  309. package/dist/components/Toast/toast.d.ts.map +1 -0
  310. package/dist/components/Toast/toast.js +76 -0
  311. package/dist/components/Toast/toast.js.map +1 -0
  312. package/dist/components/Tooltip/tooltip.d.ts +20 -0
  313. package/dist/components/Tooltip/tooltip.d.ts.map +1 -0
  314. package/dist/components/Tooltip/tooltip.js +53 -0
  315. package/dist/components/Tooltip/tooltip.js.map +1 -0
  316. package/dist/components/TreeView/tree-view.d.ts +166 -0
  317. package/dist/components/TreeView/tree-view.d.ts.map +1 -0
  318. package/dist/components/TreeView/tree-view.js +617 -0
  319. package/dist/components/TreeView/tree-view.js.map +1 -0
  320. package/dist/hooks/use-controllable.d.ts +16 -0
  321. package/dist/hooks/use-controllable.d.ts.map +1 -0
  322. package/dist/hooks/use-controllable.js +26 -0
  323. package/dist/hooks/use-controllable.js.map +1 -0
  324. package/dist/hooks/use-is-narrow-viewport.d.ts +2 -0
  325. package/dist/hooks/use-is-narrow-viewport.d.ts.map +1 -0
  326. package/dist/hooks/use-is-narrow-viewport.js +19 -0
  327. package/dist/hooks/use-is-narrow-viewport.js.map +1 -0
  328. package/dist/hooks/use-is-touch-device.d.ts +8 -0
  329. package/dist/hooks/use-is-touch-device.d.ts.map +1 -0
  330. package/dist/hooks/use-is-touch-device.js +16 -0
  331. package/dist/hooks/use-is-touch-device.js.map +1 -0
  332. package/dist/hooks/use-overflow-items.d.ts +124 -0
  333. package/dist/hooks/use-overflow-items.d.ts.map +1 -0
  334. package/dist/hooks/use-overflow-items.js +97 -0
  335. package/dist/hooks/use-overflow-items.js.map +1 -0
  336. package/dist/index.d.ts +74 -0
  337. package/dist/index.d.ts.map +1 -0
  338. package/dist/index.js +371 -0
  339. package/dist/index.js.map +1 -0
  340. package/dist/lib/drag-visual.d.ts +158 -0
  341. package/dist/lib/drag-visual.d.ts.map +1 -0
  342. package/dist/lib/drag-visual.js +96 -0
  343. package/dist/lib/drag-visual.js.map +1 -0
  344. package/dist/lib/i18n/i18n-context.d.ts +105 -0
  345. package/dist/lib/i18n/i18n-context.d.ts.map +1 -0
  346. package/dist/lib/multi-select-ordering.d.ts +54 -0
  347. package/dist/lib/multi-select-ordering.d.ts.map +1 -0
  348. package/dist/lib/multi-select-ordering.js +13 -0
  349. package/dist/lib/multi-select-ordering.js.map +1 -0
  350. package/dist/lib/utils.d.ts +12 -0
  351. package/dist/lib/utils.d.ts.map +1 -0
  352. package/dist/lib/utils.js +79 -0
  353. package/dist/lib/utils.js.map +1 -0
  354. package/dist/patterns/element-anatomy/item-anatomy.d.ts +370 -0
  355. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -0
  356. package/dist/patterns/element-anatomy/item-anatomy.js +272 -0
  357. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -0
  358. package/dist/patterns/header-canonical/chrome-header.d.ts +80 -0
  359. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -0
  360. package/dist/patterns/header-canonical/chrome-header.js +75 -0
  361. package/dist/patterns/header-canonical/chrome-header.js.map +1 -0
  362. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts +101 -0
  363. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -0
  364. package/dist/patterns/horizontal-overflow/horizontal-overflow.js +105 -0
  365. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -0
  366. package/dist/patterns/overlay-surface/overlay-surface.d.ts +28 -0
  367. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -0
  368. package/dist/patterns/overlay-surface/overlay-surface.js +85 -0
  369. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -0
  370. package/dist/patterns/resize-handle/resize-handle.d.ts +102 -0
  371. package/dist/patterns/resize-handle/resize-handle.d.ts.map +1 -0
  372. package/dist/patterns/resize-handle/resize-handle.js +74 -0
  373. package/dist/patterns/resize-handle/resize-handle.js.map +1 -0
  374. package/dist/react-day-picker.css +457 -0
  375. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts +40 -0
  376. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts.map +1 -0
  377. package/dist/tokens/elevation/overlay-geometry.d.ts +12 -0
  378. package/dist/tokens/elevation/overlay-geometry.d.ts.map +1 -0
  379. package/dist/tokens/elevation/overlay-geometry.js +7 -0
  380. package/dist/tokens/elevation/overlay-geometry.js.map +1 -0
  381. package/dist/tokens/motion/motion.d.ts +15 -0
  382. package/dist/tokens/motion/motion.d.ts.map +1 -0
  383. package/dist/tokens/motion/motion.js +9 -0
  384. package/dist/tokens/motion/motion.js.map +1 -0
  385. package/dist/tokens/uiSize/icon-size.d.ts +53 -0
  386. package/dist/tokens/uiSize/icon-size.d.ts.map +1 -0
  387. package/package.json +92 -0
  388. package/src/README.md +32 -0
  389. package/src/components/Accordion/accordion.tsx +104 -0
  390. package/src/components/Alert/alert.tsx +188 -0
  391. package/src/components/AppShell/_demo-helpers.tsx +198 -0
  392. package/src/components/AppShell/app-shell.tsx +364 -0
  393. package/src/components/AspectRatio/aspect-ratio.tsx +58 -0
  394. package/src/components/Avatar/avatar.tsx +368 -0
  395. package/src/components/Badge/badge.tsx +104 -0
  396. package/src/components/Breadcrumb/breadcrumb.tsx +619 -0
  397. package/src/components/BulkActionBar/bulk-action-bar.tsx +156 -0
  398. package/src/components/Button/button-group.tsx +96 -0
  399. package/src/components/Button/button.tsx +539 -0
  400. package/src/components/Calendar/calendar.tsx +411 -0
  401. package/src/components/Carousel/carousel.tsx +371 -0
  402. package/src/components/Chart/chart.tsx +376 -0
  403. package/src/components/Checkbox/checkbox-group.tsx +94 -0
  404. package/src/components/Checkbox/checkbox.tsx +237 -0
  405. package/src/components/Chip/chip.tsx +359 -0
  406. package/src/components/CircularProgress/circular-progress.tsx +204 -0
  407. package/src/components/Coachmark/coachmark.tsx +255 -0
  408. package/src/components/Combobox/combobox.tsx +826 -0
  409. package/src/components/Command/command.tsx +187 -0
  410. package/src/components/DataTable/active-editor-controller.ts +72 -0
  411. package/src/components/DataTable/cell-registry.tsx +520 -0
  412. package/src/components/DataTable/column-types.ts +180 -0
  413. package/src/components/DataTable/data-table-column-visibility-panel.tsx +261 -0
  414. package/src/components/DataTable/data-table-filter-panel.tsx +813 -0
  415. package/src/components/DataTable/data-table-interaction-layer.tsx +483 -0
  416. package/src/components/DataTable/data-table-sort-manager.tsx +210 -0
  417. package/src/components/DataTable/data-table.css +165 -0
  418. package/src/components/DataTable/data-table.tsx +2924 -0
  419. package/src/components/DataTable/filter-operators.ts +225 -0
  420. package/src/components/DataTable/filter-tree.ts +313 -0
  421. package/src/components/DataTable/lib/column-meta.ts +79 -0
  422. package/src/components/DateGrid/date-grid.tsx +209 -0
  423. package/src/components/DatePicker/date-picker.tsx +1114 -0
  424. package/src/components/DescriptionList/description-list.tsx +141 -0
  425. package/src/components/Dialog/dialog.tsx +267 -0
  426. package/src/components/DropdownMenu/dropdown-menu.tsx +475 -0
  427. package/src/components/Empty/empty.tsx +108 -0
  428. package/src/components/Field/field-context.ts +136 -0
  429. package/src/components/Field/field-types.ts +52 -0
  430. package/src/components/Field/field-wrapper.tsx +348 -0
  431. package/src/components/Field/field.tsx +535 -0
  432. package/src/components/FieldControlGroup/field-control-group.tsx +136 -0
  433. package/src/components/FileItem/file-item.tsx +322 -0
  434. package/src/components/FileUpload/file-upload.tsx +326 -0
  435. package/src/components/FileViewer/file-viewer-types.ts +76 -0
  436. package/src/components/FileViewer/file-viewer.tsx +1065 -0
  437. package/src/components/FileViewer/image-renderer.tsx +256 -0
  438. package/src/components/HoverCard/hover-card.tsx +79 -0
  439. package/src/components/Input/input.tsx +233 -0
  440. package/src/components/LinkInput/link-input.tsx +304 -0
  441. package/src/components/Menu/menu-item.tsx +334 -0
  442. package/src/components/NameCard/name-card.tsx +319 -0
  443. package/src/components/Notice/notice.tsx +196 -0
  444. package/src/components/NumberInput/number-input.tsx +203 -0
  445. package/src/components/OverflowIndicator/overflow-indicator.tsx +156 -0
  446. package/src/components/PeoplePicker/avatar-stack-overflow.ts +100 -0
  447. package/src/components/PeoplePicker/people-picker-helpers.ts +76 -0
  448. package/src/components/PeoplePicker/people-picker.tsx +455 -0
  449. package/src/components/PeoplePicker/person-display.tsx +358 -0
  450. package/src/components/Popover/popover.tsx +183 -0
  451. package/src/components/ProgressBar/progress-bar.tsx +157 -0
  452. package/src/components/README.md +58 -0
  453. package/src/components/RadioGroup/radio-group.tsx +261 -0
  454. package/src/components/Rating/rating.tsx +295 -0
  455. package/src/components/ScrollArea/scroll-area.tsx +110 -0
  456. package/src/components/SegmentedControl/segmented-control.tsx +304 -0
  457. package/src/components/Select/select.tsx +658 -0
  458. package/src/components/SelectMenu/select-menu.tsx +430 -0
  459. package/src/components/SelectionControl/selection-item.tsx +261 -0
  460. package/src/components/Separator/separator.tsx +48 -0
  461. package/src/components/Sheet/sheet.tsx +240 -0
  462. package/src/components/Sidebar/sidebar.tsx +1280 -0
  463. package/src/components/Skeleton/skeleton.tsx +35 -0
  464. package/src/components/Slider/slider.tsx +158 -0
  465. package/src/components/Steps/steps.tsx +850 -0
  466. package/src/components/Switch/switch.tsx +285 -0
  467. package/src/components/Tabs/tabs.tsx +515 -0
  468. package/src/components/Tag/tag.tsx +246 -0
  469. package/src/components/Textarea/textarea.tsx +280 -0
  470. package/src/components/TimePicker/time-columns.tsx +260 -0
  471. package/src/components/TimePicker/time-picker.tsx +419 -0
  472. package/src/components/Toast/toast.tsx +129 -0
  473. package/src/components/Tooltip/tooltip.tsx +68 -0
  474. package/src/components/TreeView/tree-view.tsx +1031 -0
  475. package/src/hooks/use-controllable.ts +40 -0
  476. package/src/hooks/use-is-narrow-viewport.ts +19 -0
  477. package/src/hooks/use-is-touch-device.ts +21 -0
  478. package/src/hooks/use-overflow-items.ts +256 -0
  479. package/src/index.ts +85 -0
  480. package/src/lib/README.md +82 -0
  481. package/src/lib/drag-visual.ts +272 -0
  482. package/src/lib/i18n/README.md +60 -0
  483. package/src/lib/i18n/i18n-context.tsx +129 -0
  484. package/src/lib/multi-select-ordering.ts +61 -0
  485. package/src/lib/utils.ts +93 -0
  486. package/src/patterns/README.md +67 -0
  487. package/src/patterns/element-anatomy/item-anatomy.tsx +744 -0
  488. package/src/patterns/header-canonical/chrome-header.tsx +175 -0
  489. package/src/patterns/header-canonical/header-canonical.css +27 -0
  490. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +217 -0
  491. package/src/patterns/overlay-surface/overlay-surface.tsx +191 -0
  492. package/src/patterns/resize-handle/resize-handle.tsx +188 -0
  493. package/src/stories-helpers/anatomy/anatomy-utils.tsx +64 -0
  494. package/src/styles/preset.css +31 -0
  495. package/src/styles/tokens.css +35 -0
  496. package/src/tokens/README.md +53 -0
  497. package/src/tokens/color/primitives.css +429 -0
  498. package/src/tokens/color/semantic.css +539 -0
  499. package/src/tokens/elevation/overlay-geometry.ts +13 -0
  500. package/src/tokens/layoutSpace/layoutSpace.css +36 -0
  501. package/src/tokens/motion/motion.css +30 -0
  502. package/src/tokens/motion/motion.ts +17 -0
  503. package/src/tokens/opacity/opacity.css +23 -0
  504. package/src/tokens/radius/radius.css +19 -0
  505. package/src/tokens/typography/typography.css +118 -0
  506. package/src/tokens/uiSize/icon-size.ts +52 -0
  507. package/src/tokens/uiSize/uiSize.css +125 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * filter-operators.ts — Advanced Filter Operator Registry SSOT
3
+ *
4
+ * Single source of truth for all filter operator definitions.
5
+ * 51 ops × 9 columnTypes × 12 ValueShapes.
6
+ *
7
+ * **禁止**:component 內 hardcode op 字串。一律走 `OPERATOR_REGISTRY[columnType]`。
8
+ *
9
+ * 設計路線:ClickUp baseline + 合理擴充(string +2, url 獨立 +4, date +2)。
10
+ * 詳細 spec:`./advanced-filter-operators.draft.md`
11
+ */
12
+
13
+ import type { ColumnType } from './column-types'
14
+
15
+ // ── ValueShape ───────────────────────────────────────────────────────────
16
+
17
+ /**
18
+ * Filter value 該用什麼 picker — panel 只認 ValueShape,不認 op。
19
+ * 新增 op 只需 map 到既有 shape。
20
+ */
21
+ export type ValueShape =
22
+ | 'none' // is_set / is_not_set / is_true / is_false 純 predicate
23
+ | 'text' // <Input>
24
+ | 'number' // <NumberInput>
25
+ | 'date_single' // <DatePicker> single date
26
+ | 'date_range' // <DatePickerRange> Ant-style split-input
27
+ | 'date_relative' // <Select> 預設選項(today/yesterday/this_week/...)
28
+ | 'datetime_single' // <DatePicker showTime>(includeTime=true)
29
+ | 'datetime_range' // <DatePickerRange showTime>(includeTime=true)
30
+ | 'select_single' // <Select>(預留,目前無 op 採用)
31
+ | 'select_multi' // <SelectMenu multiple>(select.is 也走這)
32
+ | 'person_single' // <PeoplePicker>(預留)
33
+ | 'person_multi' // <PeoplePicker multiple>(person.is 也走這)
34
+
35
+ // ── OperatorSpec ────────────────────────────────────────────────────────
36
+
37
+ export interface OperatorSpec {
38
+ /** Internal key, snake_case, immutable for FilterTree serialization */
39
+ op: string
40
+ /** UI label in zh-TW(暫硬編,留 i18n hook) */
41
+ label: string
42
+ /** Reference label for English / future i18n key */
43
+ labelEn: string
44
+ /**
45
+ * Value picker shape.
46
+ * date_* shapes auto-promote to datetime_* when includeTime=true(via `getValueShape`).
47
+ */
48
+ valueShape: ValueShape
49
+ }
50
+
51
+ // ── Date Relative Options(13 個,含分組)───────────────────────────────
52
+ // 群組順序 + 排列對齊 Linear / Notion / ClickUp 共識:Past → Current → Future
53
+ // 群內排列:由遠到近(Past:30 → 7 → 月 → 週 → 昨;Future:明 → 週 → 月 → 7 → 30)
54
+ // 中間語義 anchor today/this 排於 Current
55
+
56
+ export const DATE_RELATIVE_GROUPS = [
57
+ { key: 'past', label: '過去' },
58
+ { key: 'current', label: '目前' },
59
+ { key: 'future', label: '未來' },
60
+ ] as const
61
+
62
+ export const DATE_RELATIVE_OPTIONS = [
63
+ // Past
64
+ { value: 'past_30_days', label: '過去 30 天', group: 'past' },
65
+ { value: 'past_7_days', label: '過去 7 天', group: 'past' },
66
+ { value: 'last_month', label: '上月', group: 'past' },
67
+ { value: 'last_week', label: '上週', group: 'past' },
68
+ { value: 'yesterday', label: '昨天', group: 'past' },
69
+ // Current
70
+ { value: 'today', label: '今天', group: 'current' },
71
+ { value: 'this_week', label: '本週', group: 'current' },
72
+ { value: 'this_month', label: '本月', group: 'current' },
73
+ // Future
74
+ { value: 'tomorrow', label: '明天', group: 'future' },
75
+ { value: 'next_week', label: '下週', group: 'future' },
76
+ { value: 'next_month', label: '下月', group: 'future' },
77
+ { value: 'next_7_days', label: '未來 7 天', group: 'future' },
78
+ { value: 'next_30_days', label: '未來 30 天', group: 'future' },
79
+ ] as const
80
+
81
+ // ── Per-columnType op definitions ───────────────────────────────────────
82
+
83
+ const STRING_OPS: OperatorSpec[] = [
84
+ { op: 'contains', label: '包含', labelEn: 'contains', valueShape: 'text' },
85
+ { op: 'does_not_contain', label: '不包含', labelEn: 'does not contain', valueShape: 'text' },
86
+ { op: 'is', label: '等於', labelEn: 'is', valueShape: 'text' },
87
+ { op: 'is_not', label: '不等於', labelEn: 'is not', valueShape: 'text' },
88
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
89
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
90
+ ]
91
+
92
+ const URL_OPS: OperatorSpec[] = [
93
+ { op: 'contains', label: '包含', labelEn: 'contains', valueShape: 'text' },
94
+ { op: 'does_not_contain', label: '不包含', labelEn: 'does not contain', valueShape: 'text' },
95
+ { op: 'is', label: '等於', labelEn: 'is', valueShape: 'text' },
96
+ { op: 'is_not', label: '不等於', labelEn: 'is not', valueShape: 'text' },
97
+ { op: 'starts_with', label: '開頭為', labelEn: 'starts with', valueShape: 'text' },
98
+ { op: 'ends_with', label: '結尾為', labelEn: 'ends with', valueShape: 'text' },
99
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
100
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
101
+ ]
102
+
103
+ const NUMBER_OPS: OperatorSpec[] = [
104
+ { op: 'equals', label: '等於', labelEn: '=', valueShape: 'number' },
105
+ { op: 'not_equals', label: '不等於', labelEn: '≠', valueShape: 'number' },
106
+ { op: 'gt', label: '大於', labelEn: '>', valueShape: 'number' },
107
+ { op: 'gte', label: '大於等於', labelEn: '≥', valueShape: 'number' },
108
+ { op: 'lt', label: '小於', labelEn: '<', valueShape: 'number' },
109
+ { op: 'lte', label: '小於等於', labelEn: '≤', valueShape: 'number' },
110
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
111
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
112
+ ]
113
+
114
+ const DATE_OPS: OperatorSpec[] = [
115
+ { op: 'is', label: '是', labelEn: 'is', valueShape: 'date_single' },
116
+ { op: 'is_before', label: '早於', labelEn: 'before', valueShape: 'date_single' },
117
+ { op: 'is_after', label: '晚於', labelEn: 'after', valueShape: 'date_single' },
118
+ { op: 'is_on_or_before', label: '不晚於', labelEn: 'on or before', valueShape: 'date_single' },
119
+ { op: 'is_on_or_after', label: '不早於', labelEn: 'on or after', valueShape: 'date_single' },
120
+ { op: 'is_between', label: '介於', labelEn: 'between', valueShape: 'date_range' },
121
+ { op: 'is_relative', label: '相對', labelEn: 'relative', valueShape: 'date_relative' },
122
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
123
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
124
+ ]
125
+
126
+ const SELECT_OPS: OperatorSpec[] = [
127
+ { op: 'is', label: '是', labelEn: 'is', valueShape: 'select_multi' },
128
+ { op: 'is_not', label: '不是', labelEn: 'is not', valueShape: 'select_multi' },
129
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
130
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
131
+ ]
132
+
133
+ const MULTI_SELECT_OPS: OperatorSpec[] = [
134
+ { op: 'has_any_of', label: '含其中之一', labelEn: 'Any', valueShape: 'select_multi' },
135
+ { op: 'has_all_of', label: '全部包含', labelEn: 'All', valueShape: 'select_multi' },
136
+ { op: 'has_none_of', label: '不含其中任一', labelEn: 'None of', valueShape: 'select_multi' },
137
+ { op: 'is_set', label: '已設定', labelEn: 'is set', valueShape: 'none' },
138
+ { op: 'is_not_set', label: '未設定', labelEn: 'is not set', valueShape: 'none' },
139
+ ]
140
+
141
+ const PERSON_OPS: OperatorSpec[] = [
142
+ { op: 'is', label: '是', labelEn: 'is', valueShape: 'person_multi' },
143
+ { op: 'is_not', label: '不是', labelEn: 'is not', valueShape: 'person_multi' },
144
+ { op: 'is_set', label: '已指派', labelEn: 'is set', valueShape: 'none' },
145
+ { op: 'is_not_set', label: '未指派', labelEn: 'is not set', valueShape: 'none' },
146
+ ]
147
+
148
+ const MULTI_PERSON_OPS: OperatorSpec[] = [
149
+ { op: 'has_any_of', label: '含其中之一', labelEn: 'Any', valueShape: 'person_multi' },
150
+ { op: 'has_all_of', label: '全部包含', labelEn: 'All', valueShape: 'person_multi' },
151
+ { op: 'has_none_of', label: '不含其中任一', labelEn: 'None of', valueShape: 'person_multi' },
152
+ { op: 'is_set', label: '已指派', labelEn: 'is set', valueShape: 'none' },
153
+ { op: 'is_not_set', label: '未指派', labelEn: 'is not set', valueShape: 'none' },
154
+ ]
155
+
156
+ const BOOLEAN_OPS: OperatorSpec[] = [
157
+ { op: 'is_true', label: '是', labelEn: 'is checked', valueShape: 'none' },
158
+ { op: 'is_false', label: '否', labelEn: 'is not checked', valueShape: 'none' },
159
+ ]
160
+
161
+ /**
162
+ * SSOT canonical — 全部 51 ops, 9 columnTypes 對照表.
163
+ *
164
+ * **禁止繞過**:component 內勿 hardcode op 字串(M17 Rule-of-3 + Phase 5 Q3=c TypeScript-enforce 派)。
165
+ * `currency` 共用 `number` op set,渲染依 `column.meta.precision/prefix` 格式化。
166
+ */
167
+ export const OPERATOR_REGISTRY: Record<ColumnType, OperatorSpec[]> = {
168
+ string: STRING_OPS,
169
+ url: URL_OPS,
170
+ number: NUMBER_OPS,
171
+ currency: NUMBER_OPS,
172
+ date: DATE_OPS,
173
+ // Phase C(2026-05-05):time column 暫先 reuse DATE_OPS shape — advanced filter `time_*`
174
+ // ValueShape 整合留 Phase D+。consumer 走基本 cell render(無 advanced filter)不影響。
175
+ time: DATE_OPS,
176
+ select: SELECT_OPS,
177
+ multiSelect: MULTI_SELECT_OPS,
178
+ person: PERSON_OPS,
179
+ multiPerson: MULTI_PERSON_OPS,
180
+ boolean: BOOLEAN_OPS,
181
+ }
182
+
183
+ /** Default operator per columnType — 開新 condition 時的 op preset */
184
+ export const DEFAULT_OPERATOR: Record<ColumnType, string> = {
185
+ string: 'contains',
186
+ url: 'contains',
187
+ number: 'equals',
188
+ currency: 'equals',
189
+ date: 'is',
190
+ time: 'is',
191
+ select: 'is',
192
+ multiSelect: 'has_any_of',
193
+ person: 'is',
194
+ multiPerson: 'has_any_of',
195
+ boolean: 'is_true',
196
+ }
197
+
198
+ // ── Helpers ─────────────────────────────────────────────────────────────
199
+
200
+ /**
201
+ * Resolve ValueShape for a given op + columnType + includeTime flag.
202
+ *
203
+ * `date_single` / `date_range` shapes auto-promote to `datetime_single` /
204
+ * `datetime_range` when columnType=`date` && includeTime=true. All other
205
+ * shapes pass-through unchanged.
206
+ *
207
+ * `date_relative` stays as-is(relative 本質 day-level,e.g. `today` =
208
+ * 從今天 00:00 到 23:59:59,跟 includeTime 無關)。
209
+ */
210
+ export function getValueShape(
211
+ op: OperatorSpec,
212
+ columnType: ColumnType,
213
+ includeTime?: boolean,
214
+ ): ValueShape {
215
+ if (columnType === 'date' && includeTime) {
216
+ if (op.valueShape === 'date_single') return 'datetime_single'
217
+ if (op.valueShape === 'date_range') return 'datetime_range'
218
+ }
219
+ return op.valueShape
220
+ }
221
+
222
+ /** Get OperatorSpec by columnType + op key. Returns null if not found. */
223
+ export function getOperatorSpec(columnType: ColumnType, op: string): OperatorSpec | null {
224
+ return OPERATOR_REGISTRY[columnType]?.find((o) => o.op === op) ?? null
225
+ }
@@ -0,0 +1,313 @@
1
+ /**
2
+ * filter-tree.ts — FilterTree types + helpers + evaluator
3
+ *
4
+ * 抽自 data-table-filter-panel.tsx 為了 file-size budget(panel 拆分)。
5
+ * 純資料結構 + pure functions,無 UI dep。
6
+ *
7
+ * 詳:./advanced-filter.draft.md
8
+ */
9
+
10
+ import {
11
+ startOfDay, endOfDay,
12
+ startOfWeek, endOfWeek,
13
+ startOfMonth, endOfMonth,
14
+ addDays, addWeeks, addMonths, subDays,
15
+ } from 'date-fns'
16
+ import { OPERATOR_REGISTRY, type OperatorSpec } from './filter-operators'
17
+
18
+ /**
19
+ * 把 relative key 轉成 [start, end] 時間區間(local time,inclusive)。
20
+ * 對齊 Notion / ClickUp idiom — 以「今天」為錨點計算。
21
+ */
22
+ function relativeKeyToRange(key: string, now: Date = new Date()): [number, number] | null {
23
+ const today = startOfDay(now)
24
+ switch (key) {
25
+ case 'today': return [today.getTime(), endOfDay(now).getTime()]
26
+ case 'yesterday': return [startOfDay(subDays(now, 1)).getTime(), endOfDay(subDays(now, 1)).getTime()]
27
+ case 'tomorrow': return [startOfDay(addDays(now, 1)).getTime(), endOfDay(addDays(now, 1)).getTime()]
28
+ case 'this_week': return [startOfWeek(now, { weekStartsOn: 1 }).getTime(), endOfWeek(now, { weekStartsOn: 1 }).getTime()]
29
+ case 'last_week': return [startOfWeek(addWeeks(now, -1), { weekStartsOn: 1 }).getTime(), endOfWeek(addWeeks(now, -1), { weekStartsOn: 1 }).getTime()]
30
+ case 'next_week': return [startOfWeek(addWeeks(now, 1), { weekStartsOn: 1 }).getTime(), endOfWeek(addWeeks(now, 1), { weekStartsOn: 1 }).getTime()]
31
+ case 'this_month': return [startOfMonth(now).getTime(), endOfMonth(now).getTime()]
32
+ case 'last_month': return [startOfMonth(addMonths(now, -1)).getTime(), endOfMonth(addMonths(now, -1)).getTime()]
33
+ case 'next_month': return [startOfMonth(addMonths(now, 1)).getTime(), endOfMonth(addMonths(now, 1)).getTime()]
34
+ case 'past_7_days': return [startOfDay(subDays(now, 7)).getTime(), endOfDay(now).getTime()]
35
+ case 'past_30_days': return [startOfDay(subDays(now, 30)).getTime(), endOfDay(now).getTime()]
36
+ case 'next_7_days': return [startOfDay(now).getTime(), endOfDay(addDays(now, 7)).getTime()]
37
+ case 'next_30_days': return [startOfDay(now).getTime(), endOfDay(addDays(now, 30)).getTime()]
38
+ default: return null
39
+ }
40
+ }
41
+
42
+ // ── Types ────────────────────────────────────────────────────────────────
43
+
44
+ export type Conjunction = 'and' | 'or'
45
+
46
+ export interface FilterCondition {
47
+ kind: 'cond'
48
+ /** 唯一 row id(stable across renders) */
49
+ id: string
50
+ /** 對應 column id;空字串 = 尚未選 field(operator/value picker disabled) */
51
+ field: string
52
+ /** OperatorSpec.op key — 對齊 OPERATOR_REGISTRY */
53
+ op: string
54
+ /** 依 ValueShape 解讀的值 */
55
+ value: unknown
56
+ }
57
+
58
+ export interface FilterGroup {
59
+ kind: 'group'
60
+ id: string
61
+ /** group 內 children 共用的 join(全 AND 或全 OR;不允許混) */
62
+ conjunction: Conjunction
63
+ /** ⚠️ 型別鎖死:children 只能 condition,不可再 nested group(1-level cap) */
64
+ children: FilterCondition[]
65
+ }
66
+
67
+ export type FilterTreeFlat = {
68
+ mode: 'flat'
69
+ conjunction: Conjunction
70
+ children: FilterCondition[]
71
+ }
72
+
73
+ export type FilterTreeNested = {
74
+ mode: 'nested'
75
+ conjunction: Conjunction
76
+ children: FilterGroup[]
77
+ }
78
+
79
+ export type FilterTree = FilterTreeFlat | FilterTreeNested
80
+
81
+ // ── Helpers — public API ────────────────────────────────────────────────
82
+
83
+ /** Empty FilterTree — consumer 用來 init useState */
84
+ export function createEmptyFilterTree(mode: 'flat'): FilterTreeFlat
85
+ export function createEmptyFilterTree(mode: 'nested'): FilterTreeNested
86
+ export function createEmptyFilterTree(mode: 'flat' | 'nested'): FilterTree {
87
+ if (mode === 'flat') return { mode: 'flat', conjunction: 'and', children: [] }
88
+ return { mode: 'nested', conjunction: 'and', children: [] }
89
+ }
90
+
91
+ /** 是否有任何 active filter — DataTable trigger button checked state 用 */
92
+ export function isFilterTreeActive(tree: FilterTree): boolean {
93
+ if (tree.mode === 'flat') {
94
+ return tree.children.some((c) => isConditionComplete(c))
95
+ }
96
+ return tree.children.some((g) => g.children.some((c) => isConditionComplete(c)))
97
+ }
98
+
99
+ /** Condition 是否「已填齊」可參與 filter 求值 */
100
+ function isConditionComplete(c: FilterCondition): boolean {
101
+ if (!c.field || !c.op) return false
102
+ const spec = getOperatorSpecLoose(c.op)
103
+ if (!spec) return false
104
+ if (spec.valueShape === 'none') return true
105
+ return c.value !== '' && c.value !== null && c.value !== undefined
106
+ }
107
+
108
+ /** loose lookup — 我們不知 columnType,試所有 type */
109
+ function getOperatorSpecLoose(op: string): OperatorSpec | null {
110
+ for (const list of Object.values(OPERATOR_REGISTRY)) {
111
+ const found = list.find((o) => o.op === op)
112
+ if (found) return found
113
+ }
114
+ return null
115
+ }
116
+
117
+ // ── Deep-equal compare(refresh icon 顯示判定用) ─────────────────────────
118
+
119
+ /** Compare two FilterTrees structurally — 忽略內部 row id(refresh-detect 不該被內部 id 干擾)*/
120
+ export function isFilterTreeEqual(a: FilterTree, b: FilterTree): boolean {
121
+ if (a.mode !== b.mode || a.conjunction !== b.conjunction) return false
122
+ if (a.children.length !== b.children.length) return false
123
+ if (a.mode === 'flat' && b.mode === 'flat') {
124
+ return a.children.every((c, i) => isConditionEqual(c, b.children[i]))
125
+ }
126
+ if (a.mode === 'nested' && b.mode === 'nested') {
127
+ return a.children.every((g, i) => isGroupEqual(g, b.children[i]))
128
+ }
129
+ return false
130
+ }
131
+
132
+ function isGroupEqual(a: FilterGroup, b: FilterGroup): boolean {
133
+ if (a.conjunction !== b.conjunction) return false
134
+ if (a.children.length !== b.children.length) return false
135
+ return a.children.every((c, i) => isConditionEqual(c, b.children[i]))
136
+ }
137
+
138
+ function isConditionEqual(a: FilterCondition, b: FilterCondition): boolean {
139
+ if (a.field !== b.field || a.op !== b.op) return false
140
+ return JSON.stringify(a.value) === JSON.stringify(b.value)
141
+ }
142
+
143
+ // ── Tree Evaluation(globalFilter approach)──────────────────────────────
144
+
145
+ /**
146
+ * 整棵 FilterTree 對 row 求 boolean。
147
+ * 配合 useReactTable `globalFilterFn`:
148
+ *
149
+ * const tree = useState<FilterTree>(createEmptyFilterTree('flat'))
150
+ * useReactTable({
151
+ * state: { globalFilter: tree },
152
+ * onGlobalFilterChange: setTree,
153
+ * globalFilterFn: (row, _, t: FilterTree) => evaluateTree(t, row.original),
154
+ * getFilteredRowModel: getFilteredRowModel(),
155
+ * })
156
+ */
157
+ // any-allow: row-generic — TanStack row.original 是 generic,filter eval 跨 type 必走 any
158
+ export function evaluateTree(tree: FilterTree, row: any): boolean {
159
+ if (tree.children.length === 0) return true
160
+
161
+ if (tree.mode === 'flat') {
162
+ const completed = tree.children.filter(isConditionComplete)
163
+ if (completed.length === 0) return true
164
+ const results = completed.map((c) => evaluateCondition(c, row))
165
+ return tree.conjunction === 'and' ? results.every(Boolean) : results.some(Boolean)
166
+ }
167
+
168
+ // nested
169
+ const groupResults = tree.children.map((g) => evaluateGroup(g, row))
170
+ // group 沒任何 complete condition 的視為 pass-through(true)
171
+ const meaningful = groupResults.filter((_, i) => tree.children[i].children.some(isConditionComplete))
172
+ if (meaningful.length === 0) return true
173
+ return tree.conjunction === 'and' ? meaningful.every(Boolean) : meaningful.some(Boolean)
174
+ }
175
+
176
+ // any-allow: row-generic
177
+ function evaluateGroup(group: FilterGroup, row: any): boolean {
178
+ const completed = group.children.filter(isConditionComplete)
179
+ if (completed.length === 0) return true
180
+ const results = completed.map((c) => evaluateCondition(c, row))
181
+ return group.conjunction === 'and' ? results.every(Boolean) : results.some(Boolean)
182
+ }
183
+
184
+ // any-allow: row-generic
185
+ function evaluateCondition(cond: FilterCondition, row: any): boolean {
186
+ if (!cond.field || !cond.op) return true
187
+ const cellValue = row?.[cond.field]
188
+ return matchOperator(cond.op, cellValue, cond.value)
189
+ }
190
+
191
+ // PersonValue identity helper(2026-05-07):
192
+ // person/multiPerson cell value 是 `{ name, avatarUrl?, description? }` 物件 — 比對時用 `name`
193
+ // 當 stable id(PeoplePicker SSOT 沒有 id field,name 是唯一身分標識)。對齊 Notion / Linear /
194
+ // Asana 的 person filter 比對 idiom(都用 name/email 當 id)。
195
+ function personId(v: unknown): string {
196
+ if (v && typeof v === 'object' && 'name' in v) return String((v as { name: unknown }).name ?? '')
197
+ return String(v ?? '')
198
+ }
199
+ function isPersonObject(v: unknown): v is { name: string } {
200
+ return !!v && typeof v === 'object' && 'name' in v
201
+ }
202
+
203
+ // code-quality-allow: long-function — 13-operator switch dispatch table,table-driven 重構會把 op-specific guards 拆出反增 indirection
204
+ function matchOperator(op: string, cellValue: unknown, filterValue: unknown): boolean {
205
+ // 不需 value 的 op
206
+ switch (op) {
207
+ case 'is_set': return cellValue !== null && cellValue !== undefined && cellValue !== ''
208
+ case 'is_not_set': return cellValue === null || cellValue === undefined || cellValue === ''
209
+ case 'is_true': return cellValue === true
210
+ case 'is_false': return cellValue === false
211
+ }
212
+
213
+ // 需 value 但 value 空 → 視為 incomplete,pass-through
214
+ if (filterValue === null || filterValue === undefined || filterValue === '') return true
215
+ if (Array.isArray(filterValue) && filterValue.length === 0) return true
216
+
217
+ // Person-aware specialization(person_single / person_multi)— 物件透過 name 比對。
218
+ // 偵測:cellValue 或 filterValue 任一是 Person object(或包 Person 的陣列)→ 走 personId path。
219
+ const cellIsPerson = isPersonObject(cellValue) || (Array.isArray(cellValue) && cellValue.some(isPersonObject))
220
+ const filterIsPerson = isPersonObject(filterValue) || (Array.isArray(filterValue) && filterValue.some(isPersonObject))
221
+ if (cellIsPerson || filterIsPerson) {
222
+ const cellIds = Array.isArray(cellValue) ? cellValue.map(personId) : [personId(cellValue)]
223
+ const filterIds = Array.isArray(filterValue) ? filterValue.map(personId) : [personId(filterValue)]
224
+ switch (op) {
225
+ case 'is': return cellIds.length === 1 && filterIds.length >= 1 && filterIds.includes(cellIds[0])
226
+ case 'is_not': return !(cellIds.length === 1 && filterIds.length >= 1 && filterIds.includes(cellIds[0]))
227
+ case 'has_any_of': return cellIds.some((c) => filterIds.includes(c))
228
+ case 'has_all_of': return filterIds.every((f) => cellIds.includes(f))
229
+ case 'has_none_of':return !cellIds.some((c) => filterIds.includes(c))
230
+ default: return true
231
+ }
232
+ }
233
+
234
+ switch (op) {
235
+ case 'contains': return String(cellValue ?? '').toLowerCase().includes(String(filterValue).toLowerCase())
236
+ case 'does_not_contain': return !String(cellValue ?? '').toLowerCase().includes(String(filterValue).toLowerCase())
237
+ // 2026-05-12 Round 6 fix(user 抓 Roadmap 進階篩選「全部」結果空)— impl-vs-spec drift。
238
+ // Per `advanced-filter-operators.draft.md` L116「is 直接接受多值,不另設 is_any_of」+ L103-116
239
+ // select(is/is_not + select_multi ValueShape OR 語意)+ L31-32(select.is / person.is 都走
240
+ // select_multi / person_multi ValueShape)。原 impl 只做 single-value 比對,filterValue 是
241
+ // array(全選 options)→ String(array)= "v1,v2" → 永遠 != single cellValue → 結果空。
242
+ // Fix:加 array handling,走 OR 語意:any → match;is_not → every-not-match。
243
+ case 'is':
244
+ if (Array.isArray(filterValue))
245
+ return filterValue.some((v) => String(cellValue ?? '').toLowerCase() === String(v).toLowerCase())
246
+ return String(cellValue ?? '').toLowerCase() === String(filterValue).toLowerCase()
247
+ case 'is_not':
248
+ if (Array.isArray(filterValue))
249
+ return filterValue.every((v) => String(cellValue ?? '').toLowerCase() !== String(v).toLowerCase())
250
+ return String(cellValue ?? '').toLowerCase() !== String(filterValue).toLowerCase()
251
+ case 'starts_with': return String(cellValue ?? '').toLowerCase().startsWith(String(filterValue).toLowerCase())
252
+ case 'ends_with': return String(cellValue ?? '').toLowerCase().endsWith(String(filterValue).toLowerCase())
253
+
254
+ case 'equals': return Number(cellValue) === Number(filterValue)
255
+ case 'not_equals': return Number(cellValue) !== Number(filterValue)
256
+ case 'gt': return Number(cellValue) > Number(filterValue)
257
+ case 'gte': return Number(cellValue) >= Number(filterValue)
258
+ case 'lt': return Number(cellValue) < Number(filterValue)
259
+ case 'lte': return Number(cellValue) <= Number(filterValue)
260
+
261
+ case 'is_before': return new Date(String(cellValue)).getTime() < new Date(String(filterValue)).getTime()
262
+ case 'is_after': return new Date(String(cellValue)).getTime() > new Date(String(filterValue)).getTime()
263
+ case 'is_on_or_before': return new Date(String(cellValue)).getTime() <= new Date(String(filterValue)).getTime()
264
+ case 'is_on_or_after': return new Date(String(cellValue)).getTime() >= new Date(String(filterValue)).getTime()
265
+ case 'is_between': {
266
+ if (!Array.isArray(filterValue) || filterValue.length !== 2) return true
267
+ const cv = new Date(String(cellValue)).getTime()
268
+ const start = filterValue[0] ? new Date(String(filterValue[0])).getTime() : -Infinity
269
+ const end = filterValue[1] ? new Date(String(filterValue[1])).getTime() : Infinity
270
+ return cv >= start && cv <= end
271
+ }
272
+ case 'is_relative': {
273
+ // Phase D 完整實作 — relative key → time range → in-range test
274
+ const range = relativeKeyToRange(String(filterValue))
275
+ if (!range) return true // unknown key,pass-through
276
+ const cv = new Date(String(cellValue)).getTime()
277
+ if (Number.isNaN(cv)) return false // invalid cellValue → 不命中
278
+ const [start, end] = range
279
+ return cv >= start && cv <= end
280
+ }
281
+
282
+ case 'has_any_of': {
283
+ if (!Array.isArray(filterValue)) return true
284
+ if (Array.isArray(cellValue)) return cellValue.some((c) => filterValue.includes(c))
285
+ return filterValue.includes(cellValue)
286
+ }
287
+ case 'has_all_of': {
288
+ if (!Array.isArray(filterValue)) return true
289
+ if (Array.isArray(cellValue)) return filterValue.every((v) => cellValue.includes(v))
290
+ return false
291
+ }
292
+ case 'has_none_of': {
293
+ if (!Array.isArray(filterValue)) return true
294
+ if (Array.isArray(cellValue)) return !cellValue.some((c) => filterValue.includes(c))
295
+ return !filterValue.includes(cellValue)
296
+ }
297
+
298
+ default: return true
299
+ }
300
+ }
301
+
302
+ /**
303
+ * @deprecated v0.x — old per-column filterFn integration。
304
+ * 新版用 `evaluateTree` 配 TanStack `globalFilter`。
305
+ * 保留為了過渡期 backward-compat,新 consumer 不要用。
306
+ */
307
+ export function dataTableFilterMatch(cellValue: unknown, filterValue: unknown): boolean {
308
+ if (typeof filterValue === 'object' && filterValue !== null && 'operator' in filterValue && 'value' in filterValue) {
309
+ const fv = filterValue as { operator: string; value: unknown }
310
+ return matchOperator(fv.operator, cellValue, fv.value)
311
+ }
312
+ return String(cellValue ?? '').toLowerCase().includes(String(filterValue ?? '').toLowerCase())
313
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * column-meta — TanStack ColumnDef typed accessor helpers.
3
+ *
4
+ * **Scope:Internal-only — DataTable 自用,非 public API**(本檔不 re-export 出
5
+ * `data-table-filter-panel.tsx` / `data-table.tsx`,consumer 透過 panel / sort-manager
6
+ * 間接使用)。M21 (a) classification:lib/ folder 慣例 = internal helper。
7
+ *
8
+ * 為什麼存在:`ColumnDef<T, V>` 是 discriminated union(AccessorKey / AccessorFn /
9
+ * Display / Group),每個 variant 有不同欄位,直接 `col.id` 在型別上不安全。
10
+ * 既有 consumer 用 `(col as any).id` cast,3+ 處 hard-code = M17 違反。
11
+ * 抽成 typed helper 統一型別 narrowing,消除 `any` cast。
12
+ *
13
+ * Why not annotate each `as any`:DRY + single SSOT for column field access。
14
+ * 任一 helper 行為變更(e.g. 加 fallback 邏輯)只需改一處。
15
+ *
16
+ * 對齊 mindset #2 「優先消費既有」+ M17「同 hard-code 在 3+ consumer 必抽」。
17
+ */
18
+
19
+ import type { ColumnDef, ColumnMeta, RowData } from '@tanstack/react-table'
20
+
21
+ /**
22
+ * 取 column 的 stable identifier。
23
+ *
24
+ * 解析順序對齊 TanStack 內部行為:
25
+ * 1. `col.id`(顯式設定優先)
26
+ * 2. `col.accessorKey`(string version,fallback for accessor columns)
27
+ *
28
+ * 都無 → return undefined(display column 無 accessorKey 且未設 id)。
29
+ */
30
+ export function getColumnId<T extends RowData>(
31
+ col: ColumnDef<T, unknown>,
32
+ ): string | undefined {
33
+ if ('id' in col && typeof col.id === 'string' && col.id) return col.id
34
+ if (
35
+ 'accessorKey' in col &&
36
+ (typeof col.accessorKey === 'string' || typeof col.accessorKey === 'number')
37
+ ) {
38
+ return String(col.accessorKey)
39
+ }
40
+ return undefined
41
+ }
42
+
43
+ /**
44
+ * 取 column 的 header 定義(可為 string / React node / function — TanStack 規約)。
45
+ *
46
+ * 注意:本 helper 不執行 header function。consumer 若需 rendered string,
47
+ * 自行 narrow + call,或用 TanStack `flexRender` API。
48
+ */
49
+ export function getColumnHeader<T extends RowData>(
50
+ col: ColumnDef<T, unknown>,
51
+ ): ColumnDef<T, unknown>['header'] {
52
+ return 'header' in col ? col.header : undefined
53
+ }
54
+
55
+ /**
56
+ * 取 column 的 meta(本 DS 的 ColumnMeta 已 extend 加上 type / align / wrap 等)。
57
+ */
58
+ export function getColumnMeta<T extends RowData>(
59
+ col: ColumnDef<T, unknown>,
60
+ ): ColumnMeta<T, unknown> | undefined {
61
+ return col.meta
62
+ }
63
+
64
+ /**
65
+ * 從 header 定義抽 plain string label(filter / sort UI 顯示用)。
66
+ *
67
+ * 處理 3 種 header 形式:
68
+ * - string → 直接 return
69
+ * - function → 不執行(避過 React render context),fallback id
70
+ * - undefined / 其他 → fallback id
71
+ */
72
+ export function getColumnLabel<T extends RowData>(
73
+ col: ColumnDef<T, unknown>,
74
+ fallbackId?: string,
75
+ ): string {
76
+ const header = getColumnHeader(col)
77
+ if (typeof header === 'string') return header
78
+ return fallbackId ?? getColumnId(col) ?? ''
79
+ }