@j2-health/design-system 0.2.0 → 0.3.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 (316) hide show
  1. package/README.md +38 -9
  2. package/dist/index.cjs +102 -3614
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +54 -3551
  5. package/dist/index.js.map +1 -1
  6. package/dist/src/AppConfigProvider.cjs +13 -0
  7. package/dist/src/AppConfigProvider.cjs.map +1 -0
  8. package/dist/src/AppConfigProvider.js +13 -0
  9. package/dist/src/AppConfigProvider.js.map +1 -0
  10. package/dist/src/appTheme.cjs +268 -0
  11. package/dist/src/appTheme.cjs.map +1 -0
  12. package/dist/src/appTheme.js +268 -0
  13. package/dist/src/appTheme.js.map +1 -0
  14. package/dist/src/components/alert/Alert.cjs +95 -0
  15. package/dist/src/components/alert/Alert.cjs.map +1 -0
  16. package/dist/src/components/alert/Alert.js +78 -0
  17. package/dist/src/components/alert/Alert.js.map +1 -0
  18. package/dist/src/components/alert/Alert.module.css.cjs +9 -0
  19. package/dist/src/components/alert/Alert.module.css.cjs.map +1 -0
  20. package/dist/src/components/alert/Alert.module.css.js +9 -0
  21. package/dist/src/components/alert/Alert.module.css.js.map +1 -0
  22. package/dist/src/components/barchart/BarChart.cjs +155 -0
  23. package/dist/src/components/barchart/BarChart.cjs.map +1 -0
  24. package/dist/src/components/barchart/BarChart.js +155 -0
  25. package/dist/src/components/barchart/BarChart.js.map +1 -0
  26. package/dist/src/components/barchart/chart.module.css.cjs +9 -0
  27. package/dist/src/components/barchart/chart.module.css.cjs.map +1 -0
  28. package/dist/src/components/barchart/chart.module.css.js +9 -0
  29. package/dist/src/components/barchart/chart.module.css.js.map +1 -0
  30. package/dist/src/components/breadcrumb/Breadcrumb.cjs +38 -0
  31. package/dist/src/components/breadcrumb/Breadcrumb.cjs.map +1 -0
  32. package/dist/src/components/breadcrumb/Breadcrumb.js +21 -0
  33. package/dist/src/components/breadcrumb/Breadcrumb.js.map +1 -0
  34. package/dist/src/components/bulkActionBar/BulkActionBar.cjs +81 -0
  35. package/dist/src/components/bulkActionBar/BulkActionBar.cjs.map +1 -0
  36. package/dist/src/components/bulkActionBar/BulkActionBar.js +81 -0
  37. package/dist/src/components/bulkActionBar/BulkActionBar.js.map +1 -0
  38. package/dist/src/components/button/Button.cjs +21 -0
  39. package/dist/src/components/button/Button.cjs.map +1 -0
  40. package/dist/src/components/button/Button.js +21 -0
  41. package/dist/src/components/button/Button.js.map +1 -0
  42. package/dist/src/components/card/Card.cjs +36 -0
  43. package/dist/src/components/card/Card.cjs.map +1 -0
  44. package/dist/src/components/card/Card.js +36 -0
  45. package/dist/src/components/card/Card.js.map +1 -0
  46. package/dist/src/components/checkbox/Checkbox.cjs +10 -0
  47. package/dist/src/components/checkbox/Checkbox.cjs.map +1 -0
  48. package/dist/src/components/checkbox/Checkbox.js +10 -0
  49. package/dist/src/components/checkbox/Checkbox.js.map +1 -0
  50. package/dist/src/components/checkboxTree/CheckboxTree.cjs +140 -0
  51. package/dist/src/components/checkboxTree/CheckboxTree.cjs.map +1 -0
  52. package/dist/src/components/checkboxTree/CheckboxTree.js +140 -0
  53. package/dist/src/components/checkboxTree/CheckboxTree.js.map +1 -0
  54. package/dist/src/components/checkboxTree/TreeNode.cjs +92 -0
  55. package/dist/src/components/checkboxTree/TreeNode.cjs.map +1 -0
  56. package/dist/src/components/checkboxTree/TreeNode.js +92 -0
  57. package/dist/src/components/checkboxTree/TreeNode.js.map +1 -0
  58. package/dist/src/components/checkboxTree/utils.cjs +59 -0
  59. package/dist/src/components/checkboxTree/utils.cjs.map +1 -0
  60. package/dist/src/components/checkboxTree/utils.js +59 -0
  61. package/dist/src/components/checkboxTree/utils.js.map +1 -0
  62. package/dist/src/components/collapse/Collapse.cjs +81 -0
  63. package/dist/src/components/collapse/Collapse.cjs.map +1 -0
  64. package/dist/src/components/collapse/Collapse.js +64 -0
  65. package/dist/src/components/collapse/Collapse.js.map +1 -0
  66. package/dist/src/components/collapse/Collapse.module.css.cjs +13 -0
  67. package/dist/src/components/collapse/Collapse.module.css.cjs.map +1 -0
  68. package/dist/src/components/collapse/Collapse.module.css.js +13 -0
  69. package/dist/src/components/collapse/Collapse.module.css.js.map +1 -0
  70. package/dist/src/components/drawer/Drawer.cjs +39 -0
  71. package/dist/src/components/drawer/Drawer.cjs.map +1 -0
  72. package/dist/src/components/drawer/Drawer.js +39 -0
  73. package/dist/src/components/drawer/Drawer.js.map +1 -0
  74. package/dist/src/components/dropdown/Dropdown.cjs +58 -0
  75. package/dist/src/components/dropdown/Dropdown.cjs.map +1 -0
  76. package/dist/src/components/dropdown/Dropdown.js +58 -0
  77. package/dist/src/components/dropdown/Dropdown.js.map +1 -0
  78. package/dist/src/components/filterform/FilterGroup.cjs +64 -0
  79. package/dist/src/components/filterform/FilterGroup.cjs.map +1 -0
  80. package/dist/src/components/filterform/FilterGroup.js +64 -0
  81. package/dist/src/components/filterform/FilterGroup.js.map +1 -0
  82. package/dist/src/components/filterform/FilterInput.cjs +238 -0
  83. package/dist/src/components/filterform/FilterInput.cjs.map +1 -0
  84. package/dist/src/components/filterform/FilterInput.d.ts +1 -0
  85. package/dist/src/components/filterform/FilterInput.js +221 -0
  86. package/dist/src/components/filterform/FilterInput.js.map +1 -0
  87. package/dist/src/components/filterform/FiltersForm.cjs +168 -0
  88. package/dist/src/components/filterform/FiltersForm.cjs.map +1 -0
  89. package/dist/src/components/filterform/FiltersForm.js +168 -0
  90. package/dist/src/components/filterform/FiltersForm.js.map +1 -0
  91. package/dist/src/components/filterform/FiltersForm.module.css.cjs +21 -0
  92. package/dist/src/components/filterform/FiltersForm.module.css.cjs.map +1 -0
  93. package/dist/src/components/filterform/FiltersForm.module.css.js +21 -0
  94. package/dist/src/components/filterform/FiltersForm.module.css.js.map +1 -0
  95. package/dist/src/components/filterform/filterHelpers.cjs +71 -0
  96. package/dist/src/components/filterform/filterHelpers.cjs.map +1 -0
  97. package/dist/src/components/filterform/filterHelpers.d.ts +18 -4
  98. package/dist/src/components/filterform/filterHelpers.js +71 -0
  99. package/dist/src/components/filterform/filterHelpers.js.map +1 -0
  100. package/dist/src/components/filterform/index.d.ts +3 -1
  101. package/dist/src/components/filterform/types.d.ts +4 -2
  102. package/dist/src/components/filterform/useFilterField.cjs +245 -0
  103. package/dist/src/components/filterform/useFilterField.cjs.map +1 -0
  104. package/dist/src/components/filterform/useFilterField.d.ts +17 -1
  105. package/dist/src/components/filterform/useFilterField.js +228 -0
  106. package/dist/src/components/filterform/useFilterField.js.map +1 -0
  107. package/dist/src/components/filterform/useFiltersForm.cjs +160 -0
  108. package/dist/src/components/filterform/useFiltersForm.cjs.map +1 -0
  109. package/dist/src/components/filterform/useFiltersForm.js +160 -0
  110. package/dist/src/components/filterform/useFiltersForm.js.map +1 -0
  111. package/dist/src/components/form/Form.cjs +11 -0
  112. package/dist/src/components/form/Form.cjs.map +1 -0
  113. package/dist/src/components/form/Form.js +11 -0
  114. package/dist/src/components/form/Form.js.map +1 -0
  115. package/dist/src/components/icons/index.cjs +27 -0
  116. package/dist/src/components/icons/index.cjs.map +1 -0
  117. package/dist/src/components/icons/index.js +3 -0
  118. package/dist/src/components/icons/index.js.map +1 -0
  119. package/dist/src/components/input/AntdInput.cjs +13 -0
  120. package/dist/src/components/input/AntdInput.cjs.map +1 -0
  121. package/dist/src/components/input/AntdInput.js +13 -0
  122. package/dist/src/components/input/AntdInput.js.map +1 -0
  123. package/dist/src/components/input/AntdSearchInput.cjs +13 -0
  124. package/dist/src/components/input/AntdSearchInput.cjs.map +1 -0
  125. package/dist/src/components/input/AntdSearchInput.js +13 -0
  126. package/dist/src/components/input/AntdSearchInput.js.map +1 -0
  127. package/dist/src/components/input/Input.cjs +9 -0
  128. package/dist/src/components/input/Input.cjs.map +1 -0
  129. package/dist/src/components/input/Input.js +9 -0
  130. package/dist/src/components/input/Input.js.map +1 -0
  131. package/dist/src/components/inputnumber/InputNumber.cjs +32 -0
  132. package/dist/src/components/inputnumber/InputNumber.cjs.map +1 -0
  133. package/dist/src/components/inputnumber/InputNumber.js +32 -0
  134. package/dist/src/components/inputnumber/InputNumber.js.map +1 -0
  135. package/dist/src/components/inputnumber/InputNumber.module.css.cjs +9 -0
  136. package/dist/src/components/inputnumber/InputNumber.module.css.cjs.map +1 -0
  137. package/dist/src/components/inputnumber/InputNumber.module.css.js +9 -0
  138. package/dist/src/components/inputnumber/InputNumber.module.css.js.map +1 -0
  139. package/dist/src/components/legacyNavMenu/LegacyNavMenu.cjs +52 -0
  140. package/dist/src/components/legacyNavMenu/LegacyNavMenu.cjs.map +1 -0
  141. package/dist/src/components/legacyNavMenu/LegacyNavMenu.js +52 -0
  142. package/dist/src/components/legacyNavMenu/LegacyNavMenu.js.map +1 -0
  143. package/dist/src/components/legacyNavMenu/LegacyNavMenu.module.css.cjs +48 -0
  144. package/dist/src/components/legacyNavMenu/LegacyNavMenu.module.css.cjs.map +1 -0
  145. package/dist/src/components/legacyNavMenu/LegacyNavMenu.module.css.js +48 -0
  146. package/dist/src/components/legacyNavMenu/LegacyNavMenu.module.css.js.map +1 -0
  147. package/dist/src/components/legacyNavMenu/UserProfile.cjs +78 -0
  148. package/dist/src/components/legacyNavMenu/UserProfile.cjs.map +1 -0
  149. package/dist/src/components/legacyNavMenu/UserProfile.js +78 -0
  150. package/dist/src/components/legacyNavMenu/UserProfile.js.map +1 -0
  151. package/dist/src/components/legacyNavMenu/UserProfile.module.css.cjs +42 -0
  152. package/dist/src/components/legacyNavMenu/UserProfile.module.css.cjs.map +1 -0
  153. package/dist/src/components/legacyNavMenu/UserProfile.module.css.js +42 -0
  154. package/dist/src/components/legacyNavMenu/UserProfile.module.css.js.map +1 -0
  155. package/dist/src/components/listpopover/ListPopover.cjs +125 -0
  156. package/dist/src/components/listpopover/ListPopover.cjs.map +1 -0
  157. package/dist/src/components/listpopover/ListPopover.js +125 -0
  158. package/dist/src/components/listpopover/ListPopover.js.map +1 -0
  159. package/dist/src/components/listpopover/ListPopover.module.css.cjs +9 -0
  160. package/dist/src/components/listpopover/ListPopover.module.css.cjs.map +1 -0
  161. package/dist/src/components/listpopover/ListPopover.module.css.js +9 -0
  162. package/dist/src/components/listpopover/ListPopover.module.css.js.map +1 -0
  163. package/dist/src/components/menu/Menu.cjs +18 -0
  164. package/dist/src/components/menu/Menu.cjs.map +1 -0
  165. package/dist/src/components/menu/Menu.js +18 -0
  166. package/dist/src/components/menu/Menu.js.map +1 -0
  167. package/dist/src/components/menu/Menu.module.css.cjs +12 -0
  168. package/dist/src/components/menu/Menu.module.css.cjs.map +1 -0
  169. package/dist/src/components/menu/Menu.module.css.js +12 -0
  170. package/dist/src/components/menu/Menu.module.css.js.map +1 -0
  171. package/dist/src/components/message/Message.module.css.cjs +9 -0
  172. package/dist/src/components/message/Message.module.css.cjs.map +1 -0
  173. package/dist/src/components/message/Message.module.css.js +9 -0
  174. package/dist/src/components/message/Message.module.css.js.map +1 -0
  175. package/dist/src/components/message/useMessage.cjs +55 -0
  176. package/dist/src/components/message/useMessage.cjs.map +1 -0
  177. package/dist/src/components/message/useMessage.js +55 -0
  178. package/dist/src/components/message/useMessage.js.map +1 -0
  179. package/dist/src/components/modal/Modal.cjs +32 -0
  180. package/dist/src/components/modal/Modal.cjs.map +1 -0
  181. package/dist/src/components/modal/Modal.js +32 -0
  182. package/dist/src/components/modal/Modal.js.map +1 -0
  183. package/dist/src/components/navMenu/NavMenu.cjs +132 -0
  184. package/dist/src/components/navMenu/NavMenu.cjs.map +1 -0
  185. package/dist/src/components/navMenu/NavMenu.js +115 -0
  186. package/dist/src/components/navMenu/NavMenu.js.map +1 -0
  187. package/dist/src/components/navMenu/NavMenu.module.css.cjs +18 -0
  188. package/dist/src/components/navMenu/NavMenu.module.css.cjs.map +1 -0
  189. package/dist/src/components/navMenu/NavMenu.module.css.js +18 -0
  190. package/dist/src/components/navMenu/NavMenu.module.css.js.map +1 -0
  191. package/dist/src/components/notification/Notification.module.css.cjs +9 -0
  192. package/dist/src/components/notification/Notification.module.css.cjs.map +1 -0
  193. package/dist/src/components/notification/Notification.module.css.js +9 -0
  194. package/dist/src/components/notification/Notification.module.css.js.map +1 -0
  195. package/dist/src/components/notification/useNotification.cjs +52 -0
  196. package/dist/src/components/notification/useNotification.cjs.map +1 -0
  197. package/dist/src/components/notification/useNotification.js +52 -0
  198. package/dist/src/components/notification/useNotification.js.map +1 -0
  199. package/dist/src/components/notificationModal/NotifcationModal.module.css.cjs +21 -0
  200. package/dist/src/components/notificationModal/NotifcationModal.module.css.cjs.map +1 -0
  201. package/dist/src/components/notificationModal/NotifcationModal.module.css.js +21 -0
  202. package/dist/src/components/notificationModal/NotifcationModal.module.css.js.map +1 -0
  203. package/dist/src/components/notificationModal/NotificationModal.cjs +57 -0
  204. package/dist/src/components/notificationModal/NotificationModal.cjs.map +1 -0
  205. package/dist/src/components/notificationModal/NotificationModal.js +57 -0
  206. package/dist/src/components/notificationModal/NotificationModal.js.map +1 -0
  207. package/dist/src/components/pagination/Pagination.cjs +65 -0
  208. package/dist/src/components/pagination/Pagination.cjs.map +1 -0
  209. package/dist/src/components/pagination/Pagination.js +65 -0
  210. package/dist/src/components/pagination/Pagination.js.map +1 -0
  211. package/dist/src/components/pagination/Pagination.module.css.cjs +6 -0
  212. package/dist/src/components/pagination/Pagination.module.css.cjs.map +1 -0
  213. package/dist/src/components/pagination/Pagination.module.css.js +7 -0
  214. package/dist/src/components/pagination/Pagination.module.css.js.map +1 -0
  215. package/dist/src/components/popover/Popover.cjs +41 -0
  216. package/dist/src/components/popover/Popover.cjs.map +1 -0
  217. package/dist/src/components/popover/Popover.js +41 -0
  218. package/dist/src/components/popover/Popover.js.map +1 -0
  219. package/dist/src/components/popover/Popover.module.css.cjs +33 -0
  220. package/dist/src/components/popover/Popover.module.css.cjs.map +1 -0
  221. package/dist/src/components/popover/Popover.module.css.js +33 -0
  222. package/dist/src/components/popover/Popover.module.css.js.map +1 -0
  223. package/dist/src/components/progress/Progress.cjs +9 -0
  224. package/dist/src/components/progress/Progress.cjs.map +1 -0
  225. package/dist/src/components/progress/Progress.js +9 -0
  226. package/dist/src/components/progress/Progress.js.map +1 -0
  227. package/dist/src/components/radio/Radio.cjs +24 -0
  228. package/dist/src/components/radio/Radio.cjs.map +1 -0
  229. package/dist/src/components/radio/Radio.js +24 -0
  230. package/dist/src/components/radio/Radio.js.map +1 -0
  231. package/dist/src/components/rate/Rate.cjs +22 -0
  232. package/dist/src/components/rate/Rate.cjs.map +1 -0
  233. package/dist/src/components/rate/Rate.js +22 -0
  234. package/dist/src/components/rate/Rate.js.map +1 -0
  235. package/dist/src/components/select/AntdSelect.cjs +76 -0
  236. package/dist/src/components/select/AntdSelect.cjs.map +1 -0
  237. package/dist/src/components/select/AntdSelect.js +60 -0
  238. package/dist/src/components/select/AntdSelect.js.map +1 -0
  239. package/dist/src/components/select/Select.cjs +107 -0
  240. package/dist/src/components/select/Select.cjs.map +1 -0
  241. package/dist/src/components/select/Select.js +107 -0
  242. package/dist/src/components/select/Select.js.map +1 -0
  243. package/dist/src/components/select/SummarizedSelect.cjs +455 -0
  244. package/dist/src/components/select/SummarizedSelect.cjs.map +1 -0
  245. package/dist/src/components/select/SummarizedSelect.js +455 -0
  246. package/dist/src/components/select/SummarizedSelect.js.map +1 -0
  247. package/dist/src/components/select/SummarizedSelect.module.css.cjs +30 -0
  248. package/dist/src/components/select/SummarizedSelect.module.css.cjs.map +1 -0
  249. package/dist/src/components/select/SummarizedSelect.module.css.js +30 -0
  250. package/dist/src/components/select/SummarizedSelect.module.css.js.map +1 -0
  251. package/dist/src/components/skeleton/Skeleton.cjs +14 -0
  252. package/dist/src/components/skeleton/Skeleton.cjs.map +1 -0
  253. package/dist/src/components/skeleton/Skeleton.js +14 -0
  254. package/dist/src/components/skeleton/Skeleton.js.map +1 -0
  255. package/dist/src/components/spinner/Spinner.cjs +20 -0
  256. package/dist/src/components/spinner/Spinner.cjs.map +1 -0
  257. package/dist/src/components/spinner/Spinner.js +20 -0
  258. package/dist/src/components/spinner/Spinner.js.map +1 -0
  259. package/dist/src/components/steps/Steps.cjs +50 -0
  260. package/dist/src/components/steps/Steps.cjs.map +1 -0
  261. package/dist/src/components/steps/Steps.js +50 -0
  262. package/dist/src/components/steps/Steps.js.map +1 -0
  263. package/dist/src/components/steps/useSteps.cjs +56 -0
  264. package/dist/src/components/steps/useSteps.cjs.map +1 -0
  265. package/dist/src/components/steps/useSteps.js +56 -0
  266. package/dist/src/components/steps/useSteps.js.map +1 -0
  267. package/dist/src/components/switch/Switch.cjs +28 -0
  268. package/dist/src/components/switch/Switch.cjs.map +1 -0
  269. package/dist/src/components/switch/Switch.js +28 -0
  270. package/dist/src/components/switch/Switch.js.map +1 -0
  271. package/dist/src/components/table/Table.cjs +117 -0
  272. package/dist/src/components/table/Table.cjs.map +1 -0
  273. package/dist/src/components/table/Table.js +117 -0
  274. package/dist/src/components/table/Table.js.map +1 -0
  275. package/dist/src/components/table/Table.module.css.cjs +12 -0
  276. package/dist/src/components/table/Table.module.css.cjs.map +1 -0
  277. package/dist/src/components/table/Table.module.css.js +12 -0
  278. package/dist/src/components/table/Table.module.css.js.map +1 -0
  279. package/dist/src/components/tabs/Tabs.cjs +10 -0
  280. package/dist/src/components/tabs/Tabs.cjs.map +1 -0
  281. package/dist/src/components/tabs/Tabs.js +10 -0
  282. package/dist/src/components/tabs/Tabs.js.map +1 -0
  283. package/dist/src/components/tag/Tag.cjs +74 -0
  284. package/dist/src/components/tag/Tag.cjs.map +1 -0
  285. package/dist/src/components/tag/Tag.js +57 -0
  286. package/dist/src/components/tag/Tag.js.map +1 -0
  287. package/dist/src/components/tooltip/Tooltip.cjs +14 -0
  288. package/dist/src/components/tooltip/Tooltip.cjs.map +1 -0
  289. package/dist/src/components/tooltip/Tooltip.js +14 -0
  290. package/dist/src/components/tooltip/Tooltip.js.map +1 -0
  291. package/dist/src/components/vennDiagram/VennDiagram.cjs +53 -0
  292. package/dist/src/components/vennDiagram/VennDiagram.cjs.map +1 -0
  293. package/dist/src/components/vennDiagram/VennDiagram.js +53 -0
  294. package/dist/src/components/vennDiagram/VennDiagram.js.map +1 -0
  295. package/dist/src/svgs/ProgressCircle.svg.cjs +22 -0
  296. package/dist/src/svgs/ProgressCircle.svg.cjs.map +1 -0
  297. package/dist/src/svgs/ProgressCircle.svg.js +6 -0
  298. package/dist/src/svgs/ProgressCircle.svg.js.map +1 -0
  299. package/dist/src/svgs/j2-logo-menu-collapse.svg.cjs +22 -0
  300. package/dist/src/svgs/j2-logo-menu-collapse.svg.cjs.map +1 -0
  301. package/dist/src/svgs/j2-logo-menu-collapse.svg.js +6 -0
  302. package/dist/src/svgs/j2-logo-menu-collapse.svg.js.map +1 -0
  303. package/dist/src/svgs/j2-logo-menu.svg.cjs +22 -0
  304. package/dist/src/svgs/j2-logo-menu.svg.cjs.map +1 -0
  305. package/dist/src/svgs/j2-logo-menu.svg.js +6 -0
  306. package/dist/src/svgs/j2-logo-menu.svg.js.map +1 -0
  307. package/dist/src/svgs/menu-sidebar-collapse.svg.cjs +22 -0
  308. package/dist/src/svgs/menu-sidebar-collapse.svg.cjs.map +1 -0
  309. package/dist/src/svgs/menu-sidebar-collapse.svg.js +6 -0
  310. package/dist/src/svgs/menu-sidebar-collapse.svg.js.map +1 -0
  311. package/dist/src/svgs/menu-sidebar-expand.svg.cjs +22 -0
  312. package/dist/src/svgs/menu-sidebar-expand.svg.cjs.map +1 -0
  313. package/dist/src/svgs/menu-sidebar-expand.svg.js +6 -0
  314. package/dist/src/svgs/menu-sidebar-expand.svg.js.map +1 -0
  315. package/dist/style.css +646 -646
  316. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterInput.cjs","sources":["../../../../src/components/filterform/FilterInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { FilterConfig } from '.'\nimport { useFilterField, ValueInputConfig } from './useFilterField'\nimport { Input, InputNumber, Select, Typography } from 'antd'\nimport { FormFilter } from './types'\nimport { normalizeMultiValues, tooManyValuesMessage } from './filterHelpers'\nimport cx from 'classnames'\nimport { SizeType } from 'antd/es/config-provider/SizeContext'\n\ntype FilterInputProps = {\n value?: FormFilter\n filterConfigs: FilterConfig[]\n onChange?: (value: FormFilter) => void\n onBlur?: (value: FormFilter) => void\n className?: string\n size?: SizeType\n}\n\nexport const FilterInput = ({\n value,\n filterConfigs,\n onChange,\n onBlur,\n className,\n size = 'middle',\n}: FilterInputProps) => {\n const {\n filter,\n operatorOptions,\n valueInputConfig,\n handleFieldChange,\n handleOperatorChange,\n handleValuesChange,\n } = useFilterField({\n filterConfigs,\n filter: value,\n })\n\n const fieldOptions = filterConfigs.map((config) => ({\n label: config.label,\n value: config.field,\n disabled: config.disabled,\n }))\n\n // Mirror of the reducer's filter for callbacks that run after a render.\n const latestFilterRef = React.useRef(filter)\n latestFilterRef.current = filter\n\n // Deferred a tick, and read from the ref rather than the closure. A tags\n // `Select` commits unseparated search text as a chip inside its own blur\n // handling, so `onChange` and `onBlur` arrive in the same browser event and\n // React flushes the resulting reducer update only after both return. A\n // synchronous `onBlur` would hand the parent the filter from *before* that\n // last chip — and for a new rule the parent finalizes and unmounts this\n // input, silently dropping the value. After the flush the ref holds it.\n const handleBlur = () => {\n setTimeout(() => {\n const latest = latestFilterRef.current\n if (latest) onBlur?.(latest)\n }, 0)\n }\n\n // Track if this is a user-driven change (not initialization)\n const isInitialMount = React.useRef(true)\n const prevFilterRef = React.useRef(filter)\n\n React.useEffect(() => {\n // Skip the initial mount to avoid calling onChange during initialization\n // — unless initialization itself corrected the persisted filter (an\n // operator the field no longer offers, or a chip list that needed\n // normalizing). Then the parent must learn about it, or it would keep\n // and submit the stale filter until the user happened to touch the rule.\n if (isInitialMount.current) {\n isInitialMount.current = false\n prevFilterRef.current = filter\n if (value && filter && wasCorrectedOnInit(value, filter)) {\n onChange?.(filter)\n }\n return\n }\n\n // Only call onChange if the filter actually changed\n if (filter && filter !== prevFilterRef.current) {\n prevFilterRef.current = filter\n onChange?.(filter)\n }\n }, [filter, onChange])\n\n return (\n <div className={cx('grid grid-cols-3 gap-2', className)}>\n <Select\n options={fieldOptions}\n value={filter?.field}\n showSearch\n optionFilterProp=\"label\"\n onChange={handleFieldChange}\n size={size}\n />\n <div className=\"col-span-2 flex gap-2\">\n <Select\n options={operatorOptions}\n value={filter?.operator}\n onChange={handleOperatorChange}\n onBlur={handleBlur}\n size={size}\n popupMatchSelectWidth={false}\n />\n {valueInputConfig && (\n <ValueInput\n valueInputConfig={valueInputConfig}\n values={filter?.values}\n onChange={handleValuesChange}\n onBlur={handleBlur}\n size={size}\n />\n )}\n </div>\n </div>\n )\n}\n\nconst sameList = (a: readonly unknown[], b: readonly unknown[]) =>\n a.length === b.length && a.every((item, i) => item === b[i])\n\n// Whether initializing from a persisted filter changed anything the parent\n// holds — operator, values, or the validation result. `errors` counts: a\n// persisted rule can be unchanged yet newly invalid (a lowered `maxValues`),\n// or arrive with no `errors` at all (a plain `FilterForm` from storage), and\n// the form's validity is computed from the errors it holds, not from ours.\nconst wasCorrectedOnInit = (persisted: FormFilter, current: FormFilter) =>\n persisted.operator !== current.operator ||\n !sameList(persisted.values, current.values) ||\n persisted.errors === undefined ||\n !sameList(persisted.errors, current.errors ?? [])\n\ntype ValueInputProps = {\n valueInputConfig: ValueInputConfig\n values?: (string | number | undefined | null)[]\n onChange: (value: (string | number | undefined | null)[]) => void\n onBlur: () => void\n size: SizeType\n}\n\nconst ValueInput = ({\n valueInputConfig,\n values,\n onChange,\n onBlur,\n size,\n}: ValueInputProps) => {\n const handleChange = (value: string | number | null) => {\n if (value === null) {\n onChange([])\n } else {\n onChange([value])\n }\n }\n\n const handleNumberChange = (value: string | number | null, index: number) => {\n const newValues: (string | number | undefined | null)[] = [\n ...(values ?? []),\n ]\n newValues[index] = value\n onChange(newValues)\n }\n\n switch (valueInputConfig.type) {\n case 'select':\n return (\n <Select\n options={valueInputConfig.valueOptions}\n onChange={onChange}\n showSearch\n allowClear\n mode=\"multiple\"\n onBlur={onBlur}\n value={values}\n className=\"w-full truncate\"\n size={size}\n optionFilterProp=\"label\"\n />\n )\n case 'number':\n return (\n <div className=\"flex gap-2 grow\">\n {Array.from({ length: valueInputConfig.inputCount }).map(\n (_, index) => (\n <React.Fragment key={`number-input-${index}`}>\n {index !== 0 && <span className=\"my-auto\">and</span>}\n <InputNumber\n onChange={(value) => handleNumberChange(value, index)}\n onBlur={onBlur}\n value={values?.[index]}\n className=\"basis-1/2\"\n size={size}\n {...(valueInputConfig.numberOptions ?? {})}\n />\n </React.Fragment>\n )\n )}\n </div>\n )\n case 'text':\n if (valueInputConfig.multiValue) {\n return (\n <MultiValueTextInput\n values={values}\n maxValues={valueInputConfig.maxValues}\n onChange={onChange}\n onBlur={onBlur}\n size={size}\n />\n )\n }\n return (\n <Input\n onBlur={onBlur}\n value={values?.[0] ?? undefined}\n onChange={(e) => handleChange(e.target.value)}\n className=\"w-full\"\n size={size}\n />\n )\n default:\n return null\n }\n}\n\n// Commas, newlines (both flavours) and tabs: a column pasted from Excel or a\n// comma-separated list from an email both land as one chip per value.\nexport const MULTI_VALUE_TOKEN_SEPARATORS = [',', '\\n', '\\r', '\\t']\n\n/**\n * Chips input for the multi-value text operators (`isAnyOf` / `isNoneOf`).\n *\n * A tags Select rather than a text box split at query time: every token is\n * visible and individually removable before Apply, so a pasted value that\n * itself contains a comma (street addresses do) can be seen and fixed\n * instead of being silently shredded. The dropdown is kept closed — there\n * are no options to pick from; Enter or a separator commits a chip.\n */\nconst MultiValueTextInput = ({\n values,\n maxValues,\n onChange,\n onBlur,\n size,\n}: {\n values?: (string | number | undefined | null)[]\n maxValues?: number\n onChange: (value: (string | number | undefined | null)[]) => void\n onBlur: () => void\n size: SizeType\n}) => {\n // Rendered as stored: `useFilterField` normalizes values on the way into\n // state, so what the chips show is exactly what validation counts and\n // what `onSubmit` emits. (Numbers/nulls can't occur for a text filter;\n // the map is only for the shared `values` type.)\n const chips = (values ?? []).flatMap((value) =>\n value === null || value === undefined ? [] : [String(value)]\n )\n const over = maxValues !== undefined && chips.length > maxValues\n\n return (\n <div className=\"flex flex-col gap-1 w-full min-w-0\">\n <Select\n mode=\"tags\"\n tokenSeparators={MULTI_VALUE_TOKEN_SEPARATORS}\n value={chips}\n onChange={(next: string[]) => onChange(normalizeMultiValues(next))}\n onBlur={onBlur}\n open={false}\n suffixIcon={null}\n placeholder=\"Type or paste values, separated by commas\"\n className=\"w-full\"\n size={size}\n status={over ? 'error' : undefined}\n aria-label=\"Values\"\n />\n {maxValues !== undefined && (\n <Typography.Text\n type={over ? 'danger' : 'secondary'}\n className=\"text-xs\"\n role={over ? 'alert' : undefined}\n >\n {over\n ? `${tooManyValuesMessage(maxValues)} — remove ${\n chips.length - maxValues\n } to apply`\n : `${chips.length} / ${maxValues} values`}\n </Typography.Text>\n )}\n </div>\n )\n}\n"],"names":["useFilterField","React","jsx","Select","jsxs","InputNumber","Input","normalizeMultiValues","Typography","tooManyValuesMessage"],"mappings":"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"}
@@ -11,4 +11,5 @@ type FilterInputProps = {
11
11
  size?: SizeType;
12
12
  };
13
13
  export declare const FilterInput: ({ value, filterConfigs, onChange, onBlur, className, size, }: FilterInputProps) => React.JSX.Element;
14
+ export declare const MULTI_VALUE_TOKEN_SEPARATORS: string[];
14
15
  export {};
@@ -0,0 +1,221 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { useFilterField } from "./useFilterField.js";
4
+ import { Select, Input, InputNumber, Typography } from "antd";
5
+ import { normalizeMultiValues, tooManyValuesMessage } from "./filterHelpers.js";
6
+ import cx from "classnames";
7
+ const FilterInput = ({
8
+ value,
9
+ filterConfigs,
10
+ onChange,
11
+ onBlur,
12
+ className,
13
+ size = "middle"
14
+ }) => {
15
+ const {
16
+ filter,
17
+ operatorOptions,
18
+ valueInputConfig,
19
+ handleFieldChange,
20
+ handleOperatorChange,
21
+ handleValuesChange
22
+ } = useFilterField({
23
+ filterConfigs,
24
+ filter: value
25
+ });
26
+ const fieldOptions = filterConfigs.map((config) => ({
27
+ label: config.label,
28
+ value: config.field,
29
+ disabled: config.disabled
30
+ }));
31
+ const latestFilterRef = React.useRef(filter);
32
+ latestFilterRef.current = filter;
33
+ const handleBlur = () => {
34
+ setTimeout(() => {
35
+ const latest = latestFilterRef.current;
36
+ if (latest) onBlur == null ? void 0 : onBlur(latest);
37
+ }, 0);
38
+ };
39
+ const isInitialMount = React.useRef(true);
40
+ const prevFilterRef = React.useRef(filter);
41
+ React.useEffect(() => {
42
+ if (isInitialMount.current) {
43
+ isInitialMount.current = false;
44
+ prevFilterRef.current = filter;
45
+ if (value && filter && wasCorrectedOnInit(value, filter)) {
46
+ onChange == null ? void 0 : onChange(filter);
47
+ }
48
+ return;
49
+ }
50
+ if (filter && filter !== prevFilterRef.current) {
51
+ prevFilterRef.current = filter;
52
+ onChange == null ? void 0 : onChange(filter);
53
+ }
54
+ }, [filter, onChange]);
55
+ return /* @__PURE__ */ jsxs("div", { className: cx("grid grid-cols-3 gap-2", className), children: [
56
+ /* @__PURE__ */ jsx(
57
+ Select,
58
+ {
59
+ options: fieldOptions,
60
+ value: filter == null ? void 0 : filter.field,
61
+ showSearch: true,
62
+ optionFilterProp: "label",
63
+ onChange: handleFieldChange,
64
+ size
65
+ }
66
+ ),
67
+ /* @__PURE__ */ jsxs("div", { className: "col-span-2 flex gap-2", children: [
68
+ /* @__PURE__ */ jsx(
69
+ Select,
70
+ {
71
+ options: operatorOptions,
72
+ value: filter == null ? void 0 : filter.operator,
73
+ onChange: handleOperatorChange,
74
+ onBlur: handleBlur,
75
+ size,
76
+ popupMatchSelectWidth: false
77
+ }
78
+ ),
79
+ valueInputConfig && /* @__PURE__ */ jsx(
80
+ ValueInput,
81
+ {
82
+ valueInputConfig,
83
+ values: filter == null ? void 0 : filter.values,
84
+ onChange: handleValuesChange,
85
+ onBlur: handleBlur,
86
+ size
87
+ }
88
+ )
89
+ ] })
90
+ ] });
91
+ };
92
+ const sameList = (a, b) => a.length === b.length && a.every((item, i) => item === b[i]);
93
+ const wasCorrectedOnInit = (persisted, current) => persisted.operator !== current.operator || !sameList(persisted.values, current.values) || persisted.errors === void 0 || !sameList(persisted.errors, current.errors ?? []);
94
+ const ValueInput = ({
95
+ valueInputConfig,
96
+ values,
97
+ onChange,
98
+ onBlur,
99
+ size
100
+ }) => {
101
+ const handleChange = (value) => {
102
+ if (value === null) {
103
+ onChange([]);
104
+ } else {
105
+ onChange([value]);
106
+ }
107
+ };
108
+ const handleNumberChange = (value, index) => {
109
+ const newValues = [
110
+ ...values ?? []
111
+ ];
112
+ newValues[index] = value;
113
+ onChange(newValues);
114
+ };
115
+ switch (valueInputConfig.type) {
116
+ case "select":
117
+ return /* @__PURE__ */ jsx(
118
+ Select,
119
+ {
120
+ options: valueInputConfig.valueOptions,
121
+ onChange,
122
+ showSearch: true,
123
+ allowClear: true,
124
+ mode: "multiple",
125
+ onBlur,
126
+ value: values,
127
+ className: "w-full truncate",
128
+ size,
129
+ optionFilterProp: "label"
130
+ }
131
+ );
132
+ case "number":
133
+ return /* @__PURE__ */ jsx("div", { className: "flex gap-2 grow", children: Array.from({ length: valueInputConfig.inputCount }).map(
134
+ (_, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
135
+ index !== 0 && /* @__PURE__ */ jsx("span", { className: "my-auto", children: "and" }),
136
+ /* @__PURE__ */ jsx(
137
+ InputNumber,
138
+ {
139
+ onChange: (value) => handleNumberChange(value, index),
140
+ onBlur,
141
+ value: values == null ? void 0 : values[index],
142
+ className: "basis-1/2",
143
+ size,
144
+ ...valueInputConfig.numberOptions ?? {}
145
+ }
146
+ )
147
+ ] }, `number-input-${index}`)
148
+ ) });
149
+ case "text":
150
+ if (valueInputConfig.multiValue) {
151
+ return /* @__PURE__ */ jsx(
152
+ MultiValueTextInput,
153
+ {
154
+ values,
155
+ maxValues: valueInputConfig.maxValues,
156
+ onChange,
157
+ onBlur,
158
+ size
159
+ }
160
+ );
161
+ }
162
+ return /* @__PURE__ */ jsx(
163
+ Input,
164
+ {
165
+ onBlur,
166
+ value: (values == null ? void 0 : values[0]) ?? void 0,
167
+ onChange: (e) => handleChange(e.target.value),
168
+ className: "w-full",
169
+ size
170
+ }
171
+ );
172
+ default:
173
+ return null;
174
+ }
175
+ };
176
+ const MULTI_VALUE_TOKEN_SEPARATORS = [",", "\n", "\r", " "];
177
+ const MultiValueTextInput = ({
178
+ values,
179
+ maxValues,
180
+ onChange,
181
+ onBlur,
182
+ size
183
+ }) => {
184
+ const chips = (values ?? []).flatMap(
185
+ (value) => value === null || value === void 0 ? [] : [String(value)]
186
+ );
187
+ const over = maxValues !== void 0 && chips.length > maxValues;
188
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 w-full min-w-0", children: [
189
+ /* @__PURE__ */ jsx(
190
+ Select,
191
+ {
192
+ mode: "tags",
193
+ tokenSeparators: MULTI_VALUE_TOKEN_SEPARATORS,
194
+ value: chips,
195
+ onChange: (next) => onChange(normalizeMultiValues(next)),
196
+ onBlur,
197
+ open: false,
198
+ suffixIcon: null,
199
+ placeholder: "Type or paste values, separated by commas",
200
+ className: "w-full",
201
+ size,
202
+ status: over ? "error" : void 0,
203
+ "aria-label": "Values"
204
+ }
205
+ ),
206
+ maxValues !== void 0 && /* @__PURE__ */ jsx(
207
+ Typography.Text,
208
+ {
209
+ type: over ? "danger" : "secondary",
210
+ className: "text-xs",
211
+ role: over ? "alert" : void 0,
212
+ children: over ? `${tooManyValuesMessage(maxValues)} — remove ${chips.length - maxValues} to apply` : `${chips.length} / ${maxValues} values`
213
+ }
214
+ )
215
+ ] });
216
+ };
217
+ export {
218
+ FilterInput,
219
+ MULTI_VALUE_TOKEN_SEPARATORS
220
+ };
221
+ //# sourceMappingURL=FilterInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterInput.js","sources":["../../../../src/components/filterform/FilterInput.tsx"],"sourcesContent":["import * as React from 'react'\nimport { FilterConfig } from '.'\nimport { useFilterField, ValueInputConfig } from './useFilterField'\nimport { Input, InputNumber, Select, Typography } from 'antd'\nimport { FormFilter } from './types'\nimport { normalizeMultiValues, tooManyValuesMessage } from './filterHelpers'\nimport cx from 'classnames'\nimport { SizeType } from 'antd/es/config-provider/SizeContext'\n\ntype FilterInputProps = {\n value?: FormFilter\n filterConfigs: FilterConfig[]\n onChange?: (value: FormFilter) => void\n onBlur?: (value: FormFilter) => void\n className?: string\n size?: SizeType\n}\n\nexport const FilterInput = ({\n value,\n filterConfigs,\n onChange,\n onBlur,\n className,\n size = 'middle',\n}: FilterInputProps) => {\n const {\n filter,\n operatorOptions,\n valueInputConfig,\n handleFieldChange,\n handleOperatorChange,\n handleValuesChange,\n } = useFilterField({\n filterConfigs,\n filter: value,\n })\n\n const fieldOptions = filterConfigs.map((config) => ({\n label: config.label,\n value: config.field,\n disabled: config.disabled,\n }))\n\n // Mirror of the reducer's filter for callbacks that run after a render.\n const latestFilterRef = React.useRef(filter)\n latestFilterRef.current = filter\n\n // Deferred a tick, and read from the ref rather than the closure. A tags\n // `Select` commits unseparated search text as a chip inside its own blur\n // handling, so `onChange` and `onBlur` arrive in the same browser event and\n // React flushes the resulting reducer update only after both return. A\n // synchronous `onBlur` would hand the parent the filter from *before* that\n // last chip — and for a new rule the parent finalizes and unmounts this\n // input, silently dropping the value. After the flush the ref holds it.\n const handleBlur = () => {\n setTimeout(() => {\n const latest = latestFilterRef.current\n if (latest) onBlur?.(latest)\n }, 0)\n }\n\n // Track if this is a user-driven change (not initialization)\n const isInitialMount = React.useRef(true)\n const prevFilterRef = React.useRef(filter)\n\n React.useEffect(() => {\n // Skip the initial mount to avoid calling onChange during initialization\n // — unless initialization itself corrected the persisted filter (an\n // operator the field no longer offers, or a chip list that needed\n // normalizing). Then the parent must learn about it, or it would keep\n // and submit the stale filter until the user happened to touch the rule.\n if (isInitialMount.current) {\n isInitialMount.current = false\n prevFilterRef.current = filter\n if (value && filter && wasCorrectedOnInit(value, filter)) {\n onChange?.(filter)\n }\n return\n }\n\n // Only call onChange if the filter actually changed\n if (filter && filter !== prevFilterRef.current) {\n prevFilterRef.current = filter\n onChange?.(filter)\n }\n }, [filter, onChange])\n\n return (\n <div className={cx('grid grid-cols-3 gap-2', className)}>\n <Select\n options={fieldOptions}\n value={filter?.field}\n showSearch\n optionFilterProp=\"label\"\n onChange={handleFieldChange}\n size={size}\n />\n <div className=\"col-span-2 flex gap-2\">\n <Select\n options={operatorOptions}\n value={filter?.operator}\n onChange={handleOperatorChange}\n onBlur={handleBlur}\n size={size}\n popupMatchSelectWidth={false}\n />\n {valueInputConfig && (\n <ValueInput\n valueInputConfig={valueInputConfig}\n values={filter?.values}\n onChange={handleValuesChange}\n onBlur={handleBlur}\n size={size}\n />\n )}\n </div>\n </div>\n )\n}\n\nconst sameList = (a: readonly unknown[], b: readonly unknown[]) =>\n a.length === b.length && a.every((item, i) => item === b[i])\n\n// Whether initializing from a persisted filter changed anything the parent\n// holds — operator, values, or the validation result. `errors` counts: a\n// persisted rule can be unchanged yet newly invalid (a lowered `maxValues`),\n// or arrive with no `errors` at all (a plain `FilterForm` from storage), and\n// the form's validity is computed from the errors it holds, not from ours.\nconst wasCorrectedOnInit = (persisted: FormFilter, current: FormFilter) =>\n persisted.operator !== current.operator ||\n !sameList(persisted.values, current.values) ||\n persisted.errors === undefined ||\n !sameList(persisted.errors, current.errors ?? [])\n\ntype ValueInputProps = {\n valueInputConfig: ValueInputConfig\n values?: (string | number | undefined | null)[]\n onChange: (value: (string | number | undefined | null)[]) => void\n onBlur: () => void\n size: SizeType\n}\n\nconst ValueInput = ({\n valueInputConfig,\n values,\n onChange,\n onBlur,\n size,\n}: ValueInputProps) => {\n const handleChange = (value: string | number | null) => {\n if (value === null) {\n onChange([])\n } else {\n onChange([value])\n }\n }\n\n const handleNumberChange = (value: string | number | null, index: number) => {\n const newValues: (string | number | undefined | null)[] = [\n ...(values ?? []),\n ]\n newValues[index] = value\n onChange(newValues)\n }\n\n switch (valueInputConfig.type) {\n case 'select':\n return (\n <Select\n options={valueInputConfig.valueOptions}\n onChange={onChange}\n showSearch\n allowClear\n mode=\"multiple\"\n onBlur={onBlur}\n value={values}\n className=\"w-full truncate\"\n size={size}\n optionFilterProp=\"label\"\n />\n )\n case 'number':\n return (\n <div className=\"flex gap-2 grow\">\n {Array.from({ length: valueInputConfig.inputCount }).map(\n (_, index) => (\n <React.Fragment key={`number-input-${index}`}>\n {index !== 0 && <span className=\"my-auto\">and</span>}\n <InputNumber\n onChange={(value) => handleNumberChange(value, index)}\n onBlur={onBlur}\n value={values?.[index]}\n className=\"basis-1/2\"\n size={size}\n {...(valueInputConfig.numberOptions ?? {})}\n />\n </React.Fragment>\n )\n )}\n </div>\n )\n case 'text':\n if (valueInputConfig.multiValue) {\n return (\n <MultiValueTextInput\n values={values}\n maxValues={valueInputConfig.maxValues}\n onChange={onChange}\n onBlur={onBlur}\n size={size}\n />\n )\n }\n return (\n <Input\n onBlur={onBlur}\n value={values?.[0] ?? undefined}\n onChange={(e) => handleChange(e.target.value)}\n className=\"w-full\"\n size={size}\n />\n )\n default:\n return null\n }\n}\n\n// Commas, newlines (both flavours) and tabs: a column pasted from Excel or a\n// comma-separated list from an email both land as one chip per value.\nexport const MULTI_VALUE_TOKEN_SEPARATORS = [',', '\\n', '\\r', '\\t']\n\n/**\n * Chips input for the multi-value text operators (`isAnyOf` / `isNoneOf`).\n *\n * A tags Select rather than a text box split at query time: every token is\n * visible and individually removable before Apply, so a pasted value that\n * itself contains a comma (street addresses do) can be seen and fixed\n * instead of being silently shredded. The dropdown is kept closed — there\n * are no options to pick from; Enter or a separator commits a chip.\n */\nconst MultiValueTextInput = ({\n values,\n maxValues,\n onChange,\n onBlur,\n size,\n}: {\n values?: (string | number | undefined | null)[]\n maxValues?: number\n onChange: (value: (string | number | undefined | null)[]) => void\n onBlur: () => void\n size: SizeType\n}) => {\n // Rendered as stored: `useFilterField` normalizes values on the way into\n // state, so what the chips show is exactly what validation counts and\n // what `onSubmit` emits. (Numbers/nulls can't occur for a text filter;\n // the map is only for the shared `values` type.)\n const chips = (values ?? []).flatMap((value) =>\n value === null || value === undefined ? [] : [String(value)]\n )\n const over = maxValues !== undefined && chips.length > maxValues\n\n return (\n <div className=\"flex flex-col gap-1 w-full min-w-0\">\n <Select\n mode=\"tags\"\n tokenSeparators={MULTI_VALUE_TOKEN_SEPARATORS}\n value={chips}\n onChange={(next: string[]) => onChange(normalizeMultiValues(next))}\n onBlur={onBlur}\n open={false}\n suffixIcon={null}\n placeholder=\"Type or paste values, separated by commas\"\n className=\"w-full\"\n size={size}\n status={over ? 'error' : undefined}\n aria-label=\"Values\"\n />\n {maxValues !== undefined && (\n <Typography.Text\n type={over ? 'danger' : 'secondary'}\n className=\"text-xs\"\n role={over ? 'alert' : undefined}\n >\n {over\n ? `${tooManyValuesMessage(maxValues)} — remove ${\n chips.length - maxValues\n } to apply`\n : `${chips.length} / ${maxValues} values`}\n </Typography.Text>\n )}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("@phosphor-icons/react");
5
+ const FiltersForm_module = require("./FiltersForm.module.css.cjs");
6
+ const cx = require("classnames");
7
+ const filterHelpers = require("./filterHelpers.cjs");
8
+ const React = require("react");
9
+ const FilterInput = require("./FilterInput.cjs");
10
+ const useFiltersForm = require("./useFiltersForm.cjs");
11
+ const FilterGroup = require("./FilterGroup.cjs");
12
+ const Button = require("../button/Button.cjs");
13
+ const FiltersForm = ({
14
+ title,
15
+ filterConfigs,
16
+ onSubmit,
17
+ initialValues,
18
+ maxFiltersPerField = 5
19
+ }) => {
20
+ const { dispatch, filterGroups, isNewFilterInputOpen, isValid, isEmpty } = useFiltersForm.useFiltersForm({
21
+ initialValues
22
+ });
23
+ const handleSubmit = () => {
24
+ onSubmit({
25
+ filters: filterGroups.flatMap((group) => group.filters).filter((filter) => filterHelpers.isFilter(filter)).filter((filter) => !filterHelpers.isEmptyFilter(filter))
26
+ });
27
+ };
28
+ const availableFilterConfigs = React.useMemo(() => {
29
+ const filterFieldCounts = filterGroups.reduce(
30
+ (acc, filterGroup) => {
31
+ acc[filterGroup.field] = filterGroup.filters.length;
32
+ return acc;
33
+ },
34
+ {}
35
+ );
36
+ return filterConfigs.map((config) => ({
37
+ ...config,
38
+ disabled: (filterFieldCounts[config.field] || 0) >= maxFiltersPerField
39
+ }));
40
+ }, [
41
+ filterConfigs,
42
+ filterGroups.map((g) => `${g.field}-${g.filters.length}`).join(","),
43
+ maxFiltersPerField
44
+ ]);
45
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx(FiltersForm_module.default.j2FilterForm), children: [
46
+ /* @__PURE__ */ jsxRuntime.jsxs(
47
+ "div",
48
+ {
49
+ className: cx(
50
+ FiltersForm_module.default.filterFormFieldsContainer,
51
+ "flex flex-col gap-4",
52
+ "p-4 mb-6"
53
+ ),
54
+ children: [
55
+ title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: FiltersForm_module.default.filterFormTitle, children: title }),
56
+ filterGroups.map((filterGroup, groupIndex) => /* @__PURE__ */ jsxRuntime.jsxs(
57
+ "div",
58
+ {
59
+ className: cx("flex gap-3", {
60
+ "items-center": filterGroup.filters.length === 1
61
+ }),
62
+ children: [
63
+ groupIndex > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
64
+ "span",
65
+ {
66
+ className: cx(FiltersForm_module.default.filterFormConjunction, {
67
+ "pt-4": filterGroup.filters.length > 1
68
+ }),
69
+ children: "and"
70
+ }
71
+ ) : null,
72
+ /* @__PURE__ */ jsxRuntime.jsx(
73
+ FilterGroup.FilterGroup,
74
+ {
75
+ filterGroup,
76
+ groupIndex,
77
+ filterConfigs: availableFilterConfigs,
78
+ className: "grow",
79
+ onChange: (filter, filterIndex) => {
80
+ dispatch({
81
+ type: "changeFilter",
82
+ payload: { groupIndex, filterIndex, filter }
83
+ });
84
+ },
85
+ onDone: (filter, filterIndex) => {
86
+ dispatch({
87
+ type: "updateFilter",
88
+ payload: { groupIndex, filterIndex, filter }
89
+ });
90
+ },
91
+ onRemove: (filterIndex) => {
92
+ dispatch({
93
+ type: "removeFilter",
94
+ payload: { groupIndex, filterIndex }
95
+ });
96
+ }
97
+ }
98
+ )
99
+ ]
100
+ },
101
+ `filter-group-${filterGroup.field}-${filterGroup.filters.length}`
102
+ )),
103
+ isNewFilterInputOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex gap-3 items-center"), children: [
104
+ filterGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx(FiltersForm_module.default.filterFormConjunction), children: "and" }) : null,
105
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("flex items-center justify-between", "grow"), children: [
106
+ /* @__PURE__ */ jsxRuntime.jsx(
107
+ FilterInput.FilterInput,
108
+ {
109
+ filterConfigs: availableFilterConfigs,
110
+ className: "flex-1",
111
+ onChange: (filter) => {
112
+ dispatch({ type: "changeNewFilter", payload: filter });
113
+ },
114
+ onBlur: (filter) => {
115
+ dispatch({ type: "addNewFilter", payload: filter });
116
+ }
117
+ },
118
+ JSON.stringify(filterGroups)
119
+ ),
120
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mr-3", children: filterGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
121
+ Button.Button,
122
+ {
123
+ type: "text",
124
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.TrashIcon, {}),
125
+ onClick: () => dispatch({ type: "removeNewFilter" })
126
+ }
127
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8" }) })
128
+ ] })
129
+ ] }),
130
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
131
+ /* @__PURE__ */ jsxRuntime.jsx(
132
+ Button.Button,
133
+ {
134
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.PlusCircleIcon, {}),
135
+ onClick: () => dispatch({ type: "openNewFilterInput" }),
136
+ disabled: !isValid,
137
+ children: "Add Rule"
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsxRuntime.jsx(
141
+ Button.Button,
142
+ {
143
+ type: "text",
144
+ onClick: () => {
145
+ dispatch({
146
+ type: "clearAllFilters"
147
+ });
148
+ },
149
+ children: "Clear All Rules"
150
+ }
151
+ )
152
+ ] })
153
+ ]
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
157
+ Button.Button,
158
+ {
159
+ onClick: handleSubmit,
160
+ type: "primary",
161
+ disabled: isEmpty ? false : !isValid,
162
+ children: "Apply Filters"
163
+ }
164
+ ) })
165
+ ] });
166
+ };
167
+ exports.FiltersForm = FiltersForm;
168
+ //# sourceMappingURL=FiltersForm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FiltersForm.cjs","sources":["../../../../src/components/filterform/FiltersForm.tsx"],"sourcesContent":["import { Button } from '../button'\nimport { PlusCircleIcon, TrashIcon } from '@phosphor-icons/react'\nimport s from './FiltersForm.module.css'\nimport cx from 'classnames'\nimport { FilterForm, FilterConfig } from '.'\nimport { isEmptyFilter, isFilter } from './filterHelpers'\nimport { useMemo } from 'react'\nimport { FilterInput } from './FilterInput'\nimport { useFiltersForm } from './useFiltersForm'\nimport { FilterGroup } from './FilterGroup'\n\ntype Props = {\n filterConfigs: FilterConfig[]\n title?: string\n onSubmit: (values: FilterForm) => void\n initialValues?: FilterForm\n maxFiltersPerField?: number\n}\n\nexport const FiltersForm = ({\n title,\n filterConfigs,\n onSubmit,\n initialValues,\n maxFiltersPerField = 5,\n}: Props) => {\n const { dispatch, filterGroups, isNewFilterInputOpen, isValid, isEmpty } =\n useFiltersForm({\n initialValues,\n })\n\n const handleSubmit = () => {\n onSubmit({\n filters: filterGroups\n .flatMap((group) => group.filters)\n .filter((filter) => isFilter(filter))\n .filter((filter) => !isEmptyFilter(filter)),\n })\n }\n\n const availableFilterConfigs = useMemo(() => {\n const filterFieldCounts = filterGroups.reduce(\n (acc, filterGroup) => {\n acc[filterGroup.field] = filterGroup.filters.length\n return acc\n },\n {} as Record<string, number>\n )\n\n return filterConfigs.map((config) => ({\n ...config,\n disabled: (filterFieldCounts[config.field] || 0) >= maxFiltersPerField,\n }))\n }, [\n filterConfigs,\n filterGroups.map((g) => `${g.field}-${g.filters.length}`).join(','),\n maxFiltersPerField,\n ])\n\n return (\n <div className={cx(s.j2FilterForm)}>\n <div\n className={cx(\n s.filterFormFieldsContainer,\n 'flex flex-col gap-4',\n 'p-4 mb-6'\n )}\n >\n {title && <span className={s.filterFormTitle}>{title}</span>}\n {filterGroups.map((filterGroup, groupIndex) => (\n <div\n key={`filter-group-${filterGroup.field}-${filterGroup.filters.length}`}\n className={cx('flex gap-3', {\n 'items-center': filterGroup.filters.length === 1,\n })}\n >\n {groupIndex > 0 ? (\n <span\n className={cx(s.filterFormConjunction, {\n 'pt-4': filterGroup.filters.length > 1,\n })}\n >\n and\n </span>\n ) : null}\n <FilterGroup\n filterGroup={filterGroup}\n groupIndex={groupIndex}\n filterConfigs={availableFilterConfigs}\n className=\"grow\"\n onChange={(filter, filterIndex) => {\n dispatch({\n type: 'changeFilter',\n payload: { groupIndex, filterIndex, filter },\n })\n }}\n onDone={(filter, filterIndex) => {\n dispatch({\n type: 'updateFilter',\n payload: { groupIndex, filterIndex, filter },\n })\n }}\n onRemove={(filterIndex) => {\n dispatch({\n type: 'removeFilter',\n payload: { groupIndex, filterIndex },\n })\n }}\n />\n </div>\n ))}\n {isNewFilterInputOpen && (\n <div className={cx('flex gap-3 items-center')}>\n {filterGroups.length > 0 ? (\n <span className={cx(s.filterFormConjunction)}>and</span>\n ) : null}\n <div className={cx('flex items-center justify-between', 'grow')}>\n <FilterInput\n key={JSON.stringify(filterGroups)}\n filterConfigs={availableFilterConfigs}\n className=\"flex-1\"\n onChange={(filter) => {\n dispatch({ type: 'changeNewFilter', payload: filter })\n }}\n onBlur={(filter) => {\n dispatch({ type: 'addNewFilter', payload: filter })\n }}\n />\n <div className=\"mr-3\">\n {filterGroups.length > 0 ? (\n <Button\n type=\"text\"\n icon={<TrashIcon />}\n onClick={() => dispatch({ type: 'removeNewFilter' })}\n />\n ) : (\n <div className=\"w-8\" />\n )}\n </div>\n </div>\n </div>\n )}\n <div className=\"flex items-center\">\n <Button\n icon={<PlusCircleIcon />}\n onClick={() => dispatch({ type: 'openNewFilterInput' })}\n disabled={!isValid}\n >\n Add Rule\n </Button>\n <Button\n type=\"text\"\n onClick={() => {\n dispatch({\n type: 'clearAllFilters',\n })\n }}\n >\n Clear All Rules\n </Button>\n </div>\n </div>\n <div className=\"flex justify-end\">\n <Button\n onClick={handleSubmit}\n type=\"primary\"\n disabled={isEmpty ? false : !isValid}\n >\n Apply Filters\n </Button>\n </div>\n </div>\n )\n}\n"],"names":["useFiltersForm","isFilter","isEmptyFilter","useMemo","s","jsxs","jsx","FilterGroup","FilterInput","Button","TrashIcon","PlusCircleIcon"],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { TrashIcon, PlusCircleIcon } from "@phosphor-icons/react";
3
+ import s from "./FiltersForm.module.css.js";
4
+ import cx from "classnames";
5
+ import { isFilter, isEmptyFilter } from "./filterHelpers.js";
6
+ import { useMemo } from "react";
7
+ import { FilterInput } from "./FilterInput.js";
8
+ import { useFiltersForm } from "./useFiltersForm.js";
9
+ import { FilterGroup } from "./FilterGroup.js";
10
+ import { Button } from "../button/Button.js";
11
+ const FiltersForm = ({
12
+ title,
13
+ filterConfigs,
14
+ onSubmit,
15
+ initialValues,
16
+ maxFiltersPerField = 5
17
+ }) => {
18
+ const { dispatch, filterGroups, isNewFilterInputOpen, isValid, isEmpty } = useFiltersForm({
19
+ initialValues
20
+ });
21
+ const handleSubmit = () => {
22
+ onSubmit({
23
+ filters: filterGroups.flatMap((group) => group.filters).filter((filter) => isFilter(filter)).filter((filter) => !isEmptyFilter(filter))
24
+ });
25
+ };
26
+ const availableFilterConfigs = useMemo(() => {
27
+ const filterFieldCounts = filterGroups.reduce(
28
+ (acc, filterGroup) => {
29
+ acc[filterGroup.field] = filterGroup.filters.length;
30
+ return acc;
31
+ },
32
+ {}
33
+ );
34
+ return filterConfigs.map((config) => ({
35
+ ...config,
36
+ disabled: (filterFieldCounts[config.field] || 0) >= maxFiltersPerField
37
+ }));
38
+ }, [
39
+ filterConfigs,
40
+ filterGroups.map((g) => `${g.field}-${g.filters.length}`).join(","),
41
+ maxFiltersPerField
42
+ ]);
43
+ return /* @__PURE__ */ jsxs("div", { className: cx(s.j2FilterForm), children: [
44
+ /* @__PURE__ */ jsxs(
45
+ "div",
46
+ {
47
+ className: cx(
48
+ s.filterFormFieldsContainer,
49
+ "flex flex-col gap-4",
50
+ "p-4 mb-6"
51
+ ),
52
+ children: [
53
+ title && /* @__PURE__ */ jsx("span", { className: s.filterFormTitle, children: title }),
54
+ filterGroups.map((filterGroup, groupIndex) => /* @__PURE__ */ jsxs(
55
+ "div",
56
+ {
57
+ className: cx("flex gap-3", {
58
+ "items-center": filterGroup.filters.length === 1
59
+ }),
60
+ children: [
61
+ groupIndex > 0 ? /* @__PURE__ */ jsx(
62
+ "span",
63
+ {
64
+ className: cx(s.filterFormConjunction, {
65
+ "pt-4": filterGroup.filters.length > 1
66
+ }),
67
+ children: "and"
68
+ }
69
+ ) : null,
70
+ /* @__PURE__ */ jsx(
71
+ FilterGroup,
72
+ {
73
+ filterGroup,
74
+ groupIndex,
75
+ filterConfigs: availableFilterConfigs,
76
+ className: "grow",
77
+ onChange: (filter, filterIndex) => {
78
+ dispatch({
79
+ type: "changeFilter",
80
+ payload: { groupIndex, filterIndex, filter }
81
+ });
82
+ },
83
+ onDone: (filter, filterIndex) => {
84
+ dispatch({
85
+ type: "updateFilter",
86
+ payload: { groupIndex, filterIndex, filter }
87
+ });
88
+ },
89
+ onRemove: (filterIndex) => {
90
+ dispatch({
91
+ type: "removeFilter",
92
+ payload: { groupIndex, filterIndex }
93
+ });
94
+ }
95
+ }
96
+ )
97
+ ]
98
+ },
99
+ `filter-group-${filterGroup.field}-${filterGroup.filters.length}`
100
+ )),
101
+ isNewFilterInputOpen && /* @__PURE__ */ jsxs("div", { className: cx("flex gap-3 items-center"), children: [
102
+ filterGroups.length > 0 ? /* @__PURE__ */ jsx("span", { className: cx(s.filterFormConjunction), children: "and" }) : null,
103
+ /* @__PURE__ */ jsxs("div", { className: cx("flex items-center justify-between", "grow"), children: [
104
+ /* @__PURE__ */ jsx(
105
+ FilterInput,
106
+ {
107
+ filterConfigs: availableFilterConfigs,
108
+ className: "flex-1",
109
+ onChange: (filter) => {
110
+ dispatch({ type: "changeNewFilter", payload: filter });
111
+ },
112
+ onBlur: (filter) => {
113
+ dispatch({ type: "addNewFilter", payload: filter });
114
+ }
115
+ },
116
+ JSON.stringify(filterGroups)
117
+ ),
118
+ /* @__PURE__ */ jsx("div", { className: "mr-3", children: filterGroups.length > 0 ? /* @__PURE__ */ jsx(
119
+ Button,
120
+ {
121
+ type: "text",
122
+ icon: /* @__PURE__ */ jsx(TrashIcon, {}),
123
+ onClick: () => dispatch({ type: "removeNewFilter" })
124
+ }
125
+ ) : /* @__PURE__ */ jsx("div", { className: "w-8" }) })
126
+ ] })
127
+ ] }),
128
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
129
+ /* @__PURE__ */ jsx(
130
+ Button,
131
+ {
132
+ icon: /* @__PURE__ */ jsx(PlusCircleIcon, {}),
133
+ onClick: () => dispatch({ type: "openNewFilterInput" }),
134
+ disabled: !isValid,
135
+ children: "Add Rule"
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx(
139
+ Button,
140
+ {
141
+ type: "text",
142
+ onClick: () => {
143
+ dispatch({
144
+ type: "clearAllFilters"
145
+ });
146
+ },
147
+ children: "Clear All Rules"
148
+ }
149
+ )
150
+ ] })
151
+ ]
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
155
+ Button,
156
+ {
157
+ onClick: handleSubmit,
158
+ type: "primary",
159
+ disabled: isEmpty ? false : !isValid,
160
+ children: "Apply Filters"
161
+ }
162
+ ) })
163
+ ] });
164
+ };
165
+ export {
166
+ FiltersForm
167
+ };
168
+ //# sourceMappingURL=FiltersForm.js.map