@kosmeo-ui/react 0.1.1 → 1.0.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 (418) hide show
  1. package/README.md +3 -1
  2. package/dist/components/buttons/button/index.d.ts +2 -0
  3. package/dist/components/buttons/button/index.d.ts.map +1 -1
  4. package/dist/components/buttons/button/index.js +2 -2
  5. package/dist/components/buttons/button/index.js.map +1 -1
  6. package/dist/components/buttons/button/styles.css +45 -43
  7. package/dist/components/buttons/rowActions/index.d.ts.map +1 -1
  8. package/dist/components/buttons/rowActions/index.js +2 -1
  9. package/dist/components/buttons/rowActions/index.js.map +1 -1
  10. package/dist/components/buttons/rowActions/styles.css +7 -0
  11. package/dist/components/data-display/addressBlock/styles.css +2 -4
  12. package/dist/components/data-display/colorSwatch/index.d.ts +1 -1
  13. package/dist/components/data-display/colorSwatch/index.d.ts.map +1 -1
  14. package/dist/components/data-display/colorSwatch/index.js +1 -1
  15. package/dist/components/data-display/colorSwatch/index.js.map +1 -1
  16. package/dist/components/data-display/colorSwatch/styles.css +1 -1
  17. package/dist/components/data-display/dataTable/index.d.ts.map +1 -1
  18. package/dist/components/data-display/dataTable/index.js +7 -3
  19. package/dist/components/data-display/dataTable/index.js.map +1 -1
  20. package/dist/components/data-display/dataTable/styles.css +18 -2
  21. package/dist/components/data-display/dataTable/utils/parseDataKey.d.ts +8 -1
  22. package/dist/components/data-display/dataTable/utils/parseDataKey.d.ts.map +1 -1
  23. package/dist/components/data-display/dataTable/utils/parseDataKey.js +13 -41
  24. package/dist/components/data-display/dataTable/utils/parseDataKey.js.map +1 -1
  25. package/dist/components/data-display/imagePreview/styles.css +2 -2
  26. package/dist/components/data-display/infiniteScroll/filters/index.d.ts +4 -0
  27. package/dist/components/data-display/infiniteScroll/filters/index.d.ts.map +1 -1
  28. package/dist/components/data-display/infiniteScroll/filters/index.js +12 -2
  29. package/dist/components/data-display/infiniteScroll/filters/index.js.map +1 -1
  30. package/dist/components/data-display/infiniteScroll/filters/listFilter.d.ts.map +1 -1
  31. package/dist/components/data-display/infiniteScroll/filters/listFilter.js +1 -1
  32. package/dist/components/data-display/infiniteScroll/filters/listFilter.js.map +1 -1
  33. package/dist/components/data-display/infiniteScroll/filters/rangeFilter.d.ts +6 -0
  34. package/dist/components/data-display/infiniteScroll/filters/rangeFilter.d.ts.map +1 -1
  35. package/dist/components/data-display/infiniteScroll/filters/rangeFilter.js +55 -46
  36. package/dist/components/data-display/infiniteScroll/filters/rangeFilter.js.map +1 -1
  37. package/dist/components/data-display/infiniteScroll/filters/searchFilter.d.ts.map +1 -1
  38. package/dist/components/data-display/infiniteScroll/filters/searchFilter.js +4 -35
  39. package/dist/components/data-display/infiniteScroll/filters/searchFilter.js.map +1 -1
  40. package/dist/components/data-display/infiniteScroll/filters/selectFilter.d.ts.map +1 -1
  41. package/dist/components/data-display/infiniteScroll/filters/selectFilter.js +3 -5
  42. package/dist/components/data-display/infiniteScroll/filters/selectFilter.js.map +1 -1
  43. package/dist/components/data-display/infiniteScroll/filters/styles.css +34 -1
  44. package/dist/components/data-display/infiniteScroll/header/deleteButton.d.ts.map +1 -1
  45. package/dist/components/data-display/infiniteScroll/header/deleteButton.js +1 -1
  46. package/dist/components/data-display/infiniteScroll/header/deleteButton.js.map +1 -1
  47. package/dist/components/data-display/infiniteScroll/header/index.d.ts.map +1 -1
  48. package/dist/components/data-display/infiniteScroll/header/index.js +1 -1
  49. package/dist/components/data-display/infiniteScroll/header/index.js.map +1 -1
  50. package/dist/components/data-display/infiniteScroll/header/limit.d.ts.map +1 -1
  51. package/dist/components/data-display/infiniteScroll/header/limit.js +1 -1
  52. package/dist/components/data-display/infiniteScroll/header/limit.js.map +1 -1
  53. package/dist/components/data-display/infiniteScroll/header/sortBy.d.ts.map +1 -1
  54. package/dist/components/data-display/infiniteScroll/header/sortBy.js +1 -1
  55. package/dist/components/data-display/infiniteScroll/header/sortBy.js.map +1 -1
  56. package/dist/components/data-display/infiniteScroll/header/sortDirection.d.ts.map +1 -1
  57. package/dist/components/data-display/infiniteScroll/header/sortDirection.js +1 -1
  58. package/dist/components/data-display/infiniteScroll/header/sortDirection.js.map +1 -1
  59. package/dist/components/data-display/infiniteScroll/index.d.ts +8 -0
  60. package/dist/components/data-display/infiniteScroll/index.d.ts.map +1 -1
  61. package/dist/components/data-display/infiniteScroll/index.js +41 -23
  62. package/dist/components/data-display/infiniteScroll/index.js.map +1 -1
  63. package/dist/components/data-display/infiniteScroll/styles.css +2 -2
  64. package/dist/components/data-display/infiniteScroll/table/index.d.ts.map +1 -1
  65. package/dist/components/data-display/infiniteScroll/table/index.js +2 -2
  66. package/dist/components/data-display/infiniteScroll/table/index.js.map +1 -1
  67. package/dist/components/data-display/infiniteScroll/tags/index.d.ts.map +1 -1
  68. package/dist/components/data-display/infiniteScroll/tags/index.js +7 -11
  69. package/dist/components/data-display/infiniteScroll/tags/index.js.map +1 -1
  70. package/dist/components/data-display/infiniteScroll/tags/listFilterTag.d.ts.map +1 -1
  71. package/dist/components/data-display/infiniteScroll/tags/listFilterTag.js +8 -8
  72. package/dist/components/data-display/infiniteScroll/tags/listFilterTag.js.map +1 -1
  73. package/dist/components/data-display/infiniteScroll/tags/rangeFilterTag.d.ts.map +1 -1
  74. package/dist/components/data-display/infiniteScroll/tags/rangeFilterTag.js +6 -18
  75. package/dist/components/data-display/infiniteScroll/tags/rangeFilterTag.js.map +1 -1
  76. package/dist/components/data-display/infiniteScroll/tags/selectFilterTag.d.ts.map +1 -1
  77. package/dist/components/data-display/infiniteScroll/tags/selectFilterTag.js +3 -5
  78. package/dist/components/data-display/infiniteScroll/tags/selectFilterTag.js.map +1 -1
  79. package/dist/components/data-display/infiniteScroll/tags/styles.css +1 -29
  80. package/dist/components/data-display/infiniteScroll/utils/generateQueryString.d.ts +6 -0
  81. package/dist/components/data-display/infiniteScroll/utils/generateQueryString.d.ts.map +1 -1
  82. package/dist/components/data-display/infiniteScroll/utils/generateQueryString.js +24 -12
  83. package/dist/components/data-display/infiniteScroll/utils/generateQueryString.js.map +1 -1
  84. package/dist/components/data-display/infiniteScroll/utils/hasPendingChanges.d.ts +11 -1
  85. package/dist/components/data-display/infiniteScroll/utils/hasPendingChanges.d.ts.map +1 -1
  86. package/dist/components/data-display/infiniteScroll/utils/hasPendingChanges.js +37 -18
  87. package/dist/components/data-display/infiniteScroll/utils/hasPendingChanges.js.map +1 -1
  88. package/dist/components/data-display/listCard/styles.css +3 -3
  89. package/dist/components/data-display/listRow/styles.css +2 -2
  90. package/dist/components/data-display/recoveryCodeGrid/styles.css +3 -4
  91. package/dist/components/data-display/secretDisplay/styles.css +4 -4
  92. package/dist/components/data-display/statCard/styles.css +12 -12
  93. package/dist/components/data-display/summaryRow/styles.css +4 -4
  94. package/dist/components/data-display/table/index.d.ts.map +1 -1
  95. package/dist/components/data-display/table/index.js +2 -2
  96. package/dist/components/data-display/table/index.js.map +1 -1
  97. package/dist/components/data-display/table/styles.css +22 -11
  98. package/dist/components/data-display/tableFilters/index.d.ts +30 -0
  99. package/dist/components/data-display/tableFilters/index.d.ts.map +1 -0
  100. package/dist/components/data-display/tableFilters/index.js +67 -0
  101. package/dist/components/data-display/tableFilters/index.js.map +1 -0
  102. package/dist/components/data-display/tagCard/index.d.ts.map +1 -1
  103. package/dist/components/data-display/tagCard/index.js +1 -1
  104. package/dist/components/data-display/tagCard/index.js.map +1 -1
  105. package/dist/components/data-display/tagCard/styles.css +1 -1
  106. package/dist/components/feedback/alert/styles.css +15 -15
  107. package/dist/components/feedback/badge/index.d.ts.map +1 -1
  108. package/dist/components/feedback/badge/index.js +14 -8
  109. package/dist/components/feedback/badge/index.js.map +1 -1
  110. package/dist/components/feedback/badge/styles.css +45 -45
  111. package/dist/components/feedback/emptyState/styles.css +2 -4
  112. package/dist/components/feedback/loadingOverlay/styles.css +1 -1
  113. package/dist/components/feedback/progressBar/index.d.ts.map +1 -1
  114. package/dist/components/feedback/progressBar/index.js +7 -2
  115. package/dist/components/feedback/progressBar/index.js.map +1 -1
  116. package/dist/components/feedback/progressBar/styles.css +25 -16
  117. package/dist/components/feedback/spinner/styles.css +14 -24
  118. package/dist/components/feedback/tooltip/styles.css +9 -7
  119. package/dist/components/forms/detailField/styles.css +1 -1
  120. package/dist/components/forms/fieldShell/index.d.ts +3 -1
  121. package/dist/components/forms/fieldShell/index.d.ts.map +1 -1
  122. package/dist/components/forms/fieldShell/index.js +1 -1
  123. package/dist/components/forms/fieldShell/index.js.map +1 -1
  124. package/dist/components/forms/fieldShell/styles.css +5 -5
  125. package/dist/components/forms/form/styles.css +6 -6
  126. package/dist/components/forms/formActions/styles.css +4 -4
  127. package/dist/components/forms/formGrid/styles.css +32 -0
  128. package/dist/components/forms/infoRow/styles.css +2 -3
  129. package/dist/components/forms/optionsGroup/index.d.ts +3 -1
  130. package/dist/components/forms/optionsGroup/index.d.ts.map +1 -1
  131. package/dist/components/forms/optionsGroup/index.js +5 -1
  132. package/dist/components/forms/optionsGroup/index.js.map +1 -1
  133. package/dist/components/forms/optionsGroup/styles.css +1 -1
  134. package/dist/components/forms/requiredAsterisk/index.d.ts.map +1 -1
  135. package/dist/components/forms/requiredAsterisk/index.js +3 -2
  136. package/dist/components/forms/requiredAsterisk/index.js.map +1 -1
  137. package/dist/components/forms/requiredAsterisk/styles.css +1 -1
  138. package/dist/components/index.d.ts +4 -0
  139. package/dist/components/index.d.ts.map +1 -1
  140. package/dist/components/index.js +2 -0
  141. package/dist/components/index.js.map +1 -1
  142. package/dist/components/inputs/checkbox/index.d.ts +6 -1
  143. package/dist/components/inputs/checkbox/index.d.ts.map +1 -1
  144. package/dist/components/inputs/checkbox/index.js +12 -3
  145. package/dist/components/inputs/checkbox/index.js.map +1 -1
  146. package/dist/components/inputs/checkbox/styles.css +11 -3
  147. package/dist/components/inputs/colorPicker/index.d.ts.map +1 -1
  148. package/dist/components/inputs/colorPicker/index.js +3 -1
  149. package/dist/components/inputs/colorPicker/index.js.map +1 -1
  150. package/dist/components/inputs/colorPicker/styles.css +3 -3
  151. package/dist/components/inputs/dateInput/index.d.ts +6 -6
  152. package/dist/components/inputs/dateInput/index.d.ts.map +1 -1
  153. package/dist/components/inputs/dateInput/index.js +15 -5
  154. package/dist/components/inputs/dateInput/index.js.map +1 -1
  155. package/dist/components/inputs/dateInput/styles.css +5 -5
  156. package/dist/components/inputs/dateInput/utils.d.ts +0 -1
  157. package/dist/components/inputs/dateInput/utils.d.ts.map +1 -1
  158. package/dist/components/inputs/dateInput/utils.js +13 -8
  159. package/dist/components/inputs/dateInput/utils.js.map +1 -1
  160. package/dist/components/inputs/dropdown/index.d.ts +2 -0
  161. package/dist/components/inputs/dropdown/index.d.ts.map +1 -1
  162. package/dist/components/inputs/dropdown/index.js +2 -2
  163. package/dist/components/inputs/dropdown/index.js.map +1 -1
  164. package/dist/components/inputs/dropdown/styles.css +2 -2
  165. package/dist/components/inputs/dropdownArrowButton/index.d.ts.map +1 -1
  166. package/dist/components/inputs/dropdownArrowButton/index.js +1 -1
  167. package/dist/components/inputs/dropdownArrowButton/index.js.map +1 -1
  168. package/dist/components/inputs/dropdownArrowButton/styles.css +7 -5
  169. package/dist/components/inputs/fileDropZone/index.d.ts.map +1 -1
  170. package/dist/components/inputs/fileDropZone/index.js +3 -2
  171. package/dist/components/inputs/fileDropZone/index.js.map +1 -1
  172. package/dist/components/inputs/fileDropZone/styles.css +12 -12
  173. package/dist/components/inputs/fileUpload/index.d.ts.map +1 -1
  174. package/dist/components/inputs/fileUpload/index.js +11 -6
  175. package/dist/components/inputs/fileUpload/index.js.map +1 -1
  176. package/dist/components/inputs/fileUpload/styles.css +9 -9
  177. package/dist/components/inputs/input/index.d.ts +17 -1
  178. package/dist/components/inputs/input/index.d.ts.map +1 -1
  179. package/dist/components/inputs/input/index.js +27 -5
  180. package/dist/components/inputs/input/index.js.map +1 -1
  181. package/dist/components/inputs/input/styles.css +68 -24
  182. package/dist/components/inputs/languageSelect/index.d.ts.map +1 -1
  183. package/dist/components/inputs/languageSelect/index.js +15 -4
  184. package/dist/components/inputs/languageSelect/index.js.map +1 -1
  185. package/dist/components/inputs/multiSelect/dropDown.d.ts +7 -0
  186. package/dist/components/inputs/multiSelect/dropDown.d.ts.map +1 -1
  187. package/dist/components/inputs/multiSelect/dropDown.js +19 -12
  188. package/dist/components/inputs/multiSelect/dropDown.js.map +1 -1
  189. package/dist/components/inputs/multiSelect/index.d.ts.map +1 -1
  190. package/dist/components/inputs/multiSelect/index.js +49 -13
  191. package/dist/components/inputs/multiSelect/index.js.map +1 -1
  192. package/dist/components/inputs/multiSelect/styles.css +51 -43
  193. package/dist/components/inputs/multiSelect/utils.d.ts +7 -0
  194. package/dist/components/inputs/multiSelect/utils.d.ts.map +1 -0
  195. package/dist/components/inputs/multiSelect/utils.js +18 -0
  196. package/dist/components/inputs/multiSelect/utils.js.map +1 -0
  197. package/dist/components/inputs/phoneInput/index.d.ts.map +1 -1
  198. package/dist/components/inputs/phoneInput/index.js +11 -3
  199. package/dist/components/inputs/phoneInput/index.js.map +1 -1
  200. package/dist/components/inputs/phoneInput/styles.css +13 -13
  201. package/dist/components/inputs/radioGroup/index.d.ts.map +1 -1
  202. package/dist/components/inputs/radioGroup/index.js +1 -1
  203. package/dist/components/inputs/radioGroup/index.js.map +1 -1
  204. package/dist/components/inputs/richTextEditor/index.d.ts.map +1 -1
  205. package/dist/components/inputs/richTextEditor/index.js +30 -20
  206. package/dist/components/inputs/richTextEditor/index.js.map +1 -1
  207. package/dist/components/inputs/richTextEditor/styles.css +24 -24
  208. package/dist/components/inputs/searchList/index.d.ts +4 -1
  209. package/dist/components/inputs/searchList/index.d.ts.map +1 -1
  210. package/dist/components/inputs/searchList/index.js +46 -31
  211. package/dist/components/inputs/searchList/index.js.map +1 -1
  212. package/dist/components/inputs/searchList/styles.css +22 -22
  213. package/dist/components/inputs/searchSelect/index.d.ts.map +1 -1
  214. package/dist/components/inputs/searchSelect/index.js +8 -2
  215. package/dist/components/inputs/searchSelect/index.js.map +1 -1
  216. package/dist/components/inputs/select/index.js +3 -2
  217. package/dist/components/inputs/select/index.js.map +1 -1
  218. package/dist/components/inputs/select/styles.css +93 -15
  219. package/dist/components/inputs/switch/index.d.ts.map +1 -1
  220. package/dist/components/inputs/switch/index.js +3 -1
  221. package/dist/components/inputs/switch/index.js.map +1 -1
  222. package/dist/components/inputs/switch/styles.css +5 -5
  223. package/dist/components/inputs/textArea/index.d.ts.map +1 -1
  224. package/dist/components/inputs/textArea/index.js +3 -2
  225. package/dist/components/inputs/textArea/index.js.map +1 -1
  226. package/dist/components/inputs/textArea/styles.css +11 -11
  227. package/dist/components/inputs/typeahead/index.d.ts.map +1 -1
  228. package/dist/components/inputs/typeahead/index.js +21 -6
  229. package/dist/components/inputs/typeahead/index.js.map +1 -1
  230. package/dist/components/inputs/typeahead/styles.css +13 -13
  231. package/dist/components/layout/authPage/styles.css +6 -6
  232. package/dist/components/layout/borderedSection/index.d.ts +3 -1
  233. package/dist/components/layout/borderedSection/index.d.ts.map +1 -1
  234. package/dist/components/layout/borderedSection/index.js +2 -2
  235. package/dist/components/layout/borderedSection/index.js.map +1 -1
  236. package/dist/components/layout/borderedSection/styles.css +3 -3
  237. package/dist/components/layout/card/styles.css +53 -31
  238. package/dist/components/layout/col/styles.css +1 -1
  239. package/dist/components/layout/page/styles.css +25 -5
  240. package/dist/components/layout/sectionHeader/styles.css +3 -4
  241. package/dist/components/navigation/breadcrumbs/styles.css +7 -7
  242. package/dist/components/navigation/pagination/index.d.ts +23 -0
  243. package/dist/components/navigation/pagination/index.d.ts.map +1 -0
  244. package/dist/components/navigation/pagination/index.js +29 -0
  245. package/dist/components/navigation/pagination/index.js.map +1 -0
  246. package/dist/components/navigation/pagination/styles.css +113 -0
  247. package/dist/components/navigation/pagination/utils.d.ts +9 -0
  248. package/dist/components/navigation/pagination/utils.d.ts.map +1 -0
  249. package/dist/components/navigation/pagination/utils.js +25 -0
  250. package/dist/components/navigation/pagination/utils.js.map +1 -0
  251. package/dist/components/navigation/sidebar/styles.css +13 -5
  252. package/dist/components/navigation/stepper/styles.css +14 -14
  253. package/dist/components/navigation/tabButton/styles.css +59 -59
  254. package/dist/components/navigation/tabs/styles.css +5 -5
  255. package/dist/components/overlays/confirmationModal/index.d.ts +5 -0
  256. package/dist/components/overlays/confirmationModal/index.d.ts.map +1 -1
  257. package/dist/components/overlays/confirmationModal/index.js +23 -4
  258. package/dist/components/overlays/confirmationModal/index.js.map +1 -1
  259. package/dist/components/overlays/confirmationModal/styles.css +3 -0
  260. package/dist/components/overlays/modal/index.d.ts +2 -0
  261. package/dist/components/overlays/modal/index.d.ts.map +1 -1
  262. package/dist/components/overlays/modal/index.js +13 -4
  263. package/dist/components/overlays/modal/index.js.map +1 -1
  264. package/dist/components/overlays/modal/styles.css +19 -19
  265. package/dist/hooks/index.d.ts +1 -0
  266. package/dist/hooks/index.d.ts.map +1 -1
  267. package/dist/hooks/index.js +1 -0
  268. package/dist/hooks/index.js.map +1 -1
  269. package/dist/hooks/useInfinite.d.ts +3 -1
  270. package/dist/hooks/useInfinite.d.ts.map +1 -1
  271. package/dist/hooks/useInfinite.js +4 -2
  272. package/dist/hooks/useInfinite.js.map +1 -1
  273. package/dist/hooks/useInfiniteArchivableCursor.d.ts +1 -1
  274. package/dist/hooks/useInfiniteArchivableCursor.d.ts.map +1 -1
  275. package/dist/hooks/useInfiniteArchivableCursor.js +11 -4
  276. package/dist/hooks/useInfiniteArchivableCursor.js.map +1 -1
  277. package/dist/hooks/useInfiniteCursor.d.ts +1 -1
  278. package/dist/hooks/useInfiniteCursor.d.ts.map +1 -1
  279. package/dist/hooks/useInfiniteCursor.js +11 -4
  280. package/dist/hooks/useInfiniteCursor.js.map +1 -1
  281. package/dist/hooks/usePaginated.d.ts +43 -0
  282. package/dist/hooks/usePaginated.d.ts.map +1 -0
  283. package/dist/hooks/usePaginated.js +60 -0
  284. package/dist/hooks/usePaginated.js.map +1 -0
  285. package/dist/styles.css +161 -123
  286. package/package.json +15 -4
  287. package/src/components/buttons/button/index.tsx +14 -5
  288. package/src/components/buttons/button/styles.css +45 -43
  289. package/src/components/buttons/rowActions/index.tsx +6 -1
  290. package/src/components/buttons/rowActions/styles.css +7 -0
  291. package/src/components/data-display/addressBlock/styles.css +2 -4
  292. package/src/components/data-display/colorSwatch/index.tsx +2 -2
  293. package/src/components/data-display/colorSwatch/styles.css +1 -1
  294. package/src/components/data-display/dataTable/index.tsx +6 -3
  295. package/src/components/data-display/dataTable/styles.css +18 -2
  296. package/src/components/data-display/dataTable/utils/parseDataKey.ts +18 -36
  297. package/src/components/data-display/imagePreview/styles.css +2 -2
  298. package/src/components/data-display/infiniteScroll/filters/index.tsx +18 -1
  299. package/src/components/data-display/infiniteScroll/filters/listFilter.tsx +1 -0
  300. package/src/components/data-display/infiniteScroll/filters/rangeFilter.tsx +77 -33
  301. package/src/components/data-display/infiniteScroll/filters/searchFilter.tsx +16 -65
  302. package/src/components/data-display/infiniteScroll/filters/selectFilter.tsx +11 -17
  303. package/src/components/data-display/infiniteScroll/filters/styles.css +34 -1
  304. package/src/components/data-display/infiniteScroll/header/deleteButton.tsx +1 -0
  305. package/src/components/data-display/infiniteScroll/header/index.tsx +4 -0
  306. package/src/components/data-display/infiniteScroll/header/limit.tsx +1 -0
  307. package/src/components/data-display/infiniteScroll/header/sortBy.tsx +1 -0
  308. package/src/components/data-display/infiniteScroll/header/sortDirection.tsx +1 -0
  309. package/src/components/data-display/infiniteScroll/index.tsx +75 -29
  310. package/src/components/data-display/infiniteScroll/styles.css +2 -2
  311. package/src/components/data-display/infiniteScroll/table/index.tsx +2 -0
  312. package/src/components/data-display/infiniteScroll/tags/index.tsx +7 -16
  313. package/src/components/data-display/infiniteScroll/tags/listFilterTag.tsx +31 -28
  314. package/src/components/data-display/infiniteScroll/tags/rangeFilterTag.tsx +8 -25
  315. package/src/components/data-display/infiniteScroll/tags/selectFilterTag.tsx +4 -11
  316. package/src/components/data-display/infiniteScroll/tags/styles.css +1 -29
  317. package/src/components/data-display/infiniteScroll/utils/generateQueryString.ts +28 -13
  318. package/src/components/data-display/infiniteScroll/utils/hasPendingChanges.ts +48 -16
  319. package/src/components/data-display/listCard/styles.css +3 -3
  320. package/src/components/data-display/listRow/styles.css +2 -2
  321. package/src/components/data-display/recoveryCodeGrid/styles.css +3 -4
  322. package/src/components/data-display/secretDisplay/styles.css +4 -4
  323. package/src/components/data-display/statCard/styles.css +12 -12
  324. package/src/components/data-display/summaryRow/styles.css +4 -4
  325. package/src/components/data-display/table/index.tsx +2 -2
  326. package/src/components/data-display/table/styles.css +22 -11
  327. package/src/components/data-display/tableFilters/index.tsx +147 -0
  328. package/src/components/data-display/tagCard/index.tsx +7 -4
  329. package/src/components/data-display/tagCard/styles.css +1 -1
  330. package/src/components/feedback/alert/styles.css +15 -15
  331. package/src/components/feedback/badge/index.tsx +36 -16
  332. package/src/components/feedback/badge/styles.css +45 -45
  333. package/src/components/feedback/emptyState/styles.css +2 -4
  334. package/src/components/feedback/loadingOverlay/styles.css +1 -1
  335. package/src/components/feedback/progressBar/index.tsx +14 -8
  336. package/src/components/feedback/progressBar/styles.css +25 -16
  337. package/src/components/feedback/spinner/styles.css +14 -24
  338. package/src/components/feedback/tooltip/styles.css +9 -7
  339. package/src/components/forms/detailField/styles.css +1 -1
  340. package/src/components/forms/fieldShell/index.tsx +4 -1
  341. package/src/components/forms/fieldShell/styles.css +5 -5
  342. package/src/components/forms/form/styles.css +6 -6
  343. package/src/components/forms/formActions/styles.css +4 -4
  344. package/src/components/forms/formGrid/styles.css +32 -0
  345. package/src/components/forms/infoRow/styles.css +2 -3
  346. package/src/components/forms/optionsGroup/index.tsx +31 -12
  347. package/src/components/forms/optionsGroup/styles.css +1 -1
  348. package/src/components/forms/requiredAsterisk/index.tsx +5 -1
  349. package/src/components/forms/requiredAsterisk/styles.css +1 -1
  350. package/src/components/index.ts +4 -0
  351. package/src/components/inputs/checkbox/index.tsx +27 -6
  352. package/src/components/inputs/checkbox/styles.css +11 -3
  353. package/src/components/inputs/colorPicker/index.tsx +5 -2
  354. package/src/components/inputs/colorPicker/styles.css +3 -3
  355. package/src/components/inputs/dateInput/index.tsx +17 -9
  356. package/src/components/inputs/dateInput/styles.css +5 -5
  357. package/src/components/inputs/dateInput/utils.ts +12 -8
  358. package/src/components/inputs/dropdown/index.tsx +5 -1
  359. package/src/components/inputs/dropdown/styles.css +2 -2
  360. package/src/components/inputs/dropdownArrowButton/index.tsx +1 -0
  361. package/src/components/inputs/dropdownArrowButton/styles.css +7 -5
  362. package/src/components/inputs/fileDropZone/index.tsx +4 -3
  363. package/src/components/inputs/fileDropZone/styles.css +12 -12
  364. package/src/components/inputs/fileUpload/index.tsx +33 -23
  365. package/src/components/inputs/fileUpload/styles.css +9 -9
  366. package/src/components/inputs/input/index.tsx +67 -6
  367. package/src/components/inputs/input/styles.css +68 -24
  368. package/src/components/inputs/languageSelect/index.tsx +19 -4
  369. package/src/components/inputs/multiSelect/dropDown.tsx +83 -35
  370. package/src/components/inputs/multiSelect/index.tsx +87 -29
  371. package/src/components/inputs/multiSelect/styles.css +51 -43
  372. package/src/components/inputs/multiSelect/utils.ts +18 -0
  373. package/src/components/inputs/phoneInput/index.tsx +16 -4
  374. package/src/components/inputs/phoneInput/styles.css +13 -13
  375. package/src/components/inputs/radioGroup/index.tsx +2 -1
  376. package/src/components/inputs/richTextEditor/index.tsx +59 -37
  377. package/src/components/inputs/richTextEditor/styles.css +24 -24
  378. package/src/components/inputs/searchList/index.tsx +121 -109
  379. package/src/components/inputs/searchList/styles.css +22 -22
  380. package/src/components/inputs/searchSelect/index.tsx +8 -2
  381. package/src/components/inputs/select/index.tsx +3 -3
  382. package/src/components/inputs/select/styles.css +93 -15
  383. package/src/components/inputs/switch/index.tsx +3 -2
  384. package/src/components/inputs/switch/styles.css +5 -5
  385. package/src/components/inputs/textArea/index.tsx +3 -3
  386. package/src/components/inputs/textArea/styles.css +11 -11
  387. package/src/components/inputs/typeahead/index.tsx +84 -54
  388. package/src/components/inputs/typeahead/styles.css +13 -13
  389. package/src/components/layout/authPage/styles.css +6 -6
  390. package/src/components/layout/borderedSection/index.tsx +4 -1
  391. package/src/components/layout/borderedSection/styles.css +3 -3
  392. package/src/components/layout/card/styles.css +53 -31
  393. package/src/components/layout/col/styles.css +1 -1
  394. package/src/components/layout/page/styles.css +25 -5
  395. package/src/components/layout/sectionHeader/styles.css +3 -4
  396. package/src/components/navigation/breadcrumbs/styles.css +7 -7
  397. package/src/components/navigation/pagination/index.tsx +134 -0
  398. package/src/components/navigation/pagination/styles.css +113 -0
  399. package/src/components/navigation/pagination/utils.ts +32 -0
  400. package/src/components/navigation/sidebar/styles.css +13 -5
  401. package/src/components/navigation/stepper/styles.css +14 -14
  402. package/src/components/navigation/tabButton/styles.css +59 -59
  403. package/src/components/navigation/tabs/styles.css +5 -5
  404. package/src/components/overlays/confirmationModal/index.tsx +37 -1
  405. package/src/components/overlays/confirmationModal/styles.css +3 -0
  406. package/src/components/overlays/modal/index.tsx +23 -4
  407. package/src/components/overlays/modal/styles.css +19 -19
  408. package/src/hooks/index.ts +4 -0
  409. package/src/hooks/useInfinite.ts +7 -3
  410. package/src/hooks/useInfiniteArchivableCursor.ts +11 -4
  411. package/src/hooks/useInfiniteCursor.ts +11 -4
  412. package/src/hooks/usePaginated.ts +123 -0
  413. package/src/styles.css +161 -123
  414. package/dist/components/data-display/infiniteScroll/tags/searchFilterTag.d.ts +0 -10
  415. package/dist/components/data-display/infiniteScroll/tags/searchFilterTag.d.ts.map +0 -1
  416. package/dist/components/data-display/infiniteScroll/tags/searchFilterTag.js +0 -22
  417. package/dist/components/data-display/infiniteScroll/tags/searchFilterTag.js.map +0 -1
  418. package/src/components/data-display/infiniteScroll/tags/searchFilterTag.tsx +0 -41
@@ -46,126 +46,126 @@
46
46
 
47
47
  .k-button-shadow {
48
48
  box-shadow:
49
- 0 0.25rem 0.375rem -0.0625rem var(--shadow-color),
50
- 0 0.125rem 0.25rem -0.125rem var(--shadow-color);
49
+ 0 0.25rem 0.375rem -0.0625rem var(--k-shadow-color),
50
+ 0 0.125rem 0.25rem -0.125rem var(--k-shadow-color);
51
51
  }
52
52
 
53
53
  .k-button-sm {
54
54
  padding: 0.5rem 1rem;
55
- font-size: var(--text-size-sm);
55
+ font-size: var(--k-text-size-sm);
56
56
  }
57
57
 
58
58
  .k-button-md {
59
59
  padding: 0.75rem 1.5rem;
60
- font-size: var(--text-size-md);
60
+ font-size: var(--k-text-size-md);
61
61
  }
62
62
 
63
63
  .k-button-lg {
64
64
  padding: 1rem 2rem;
65
- font-size: var(--text-size-lg);
65
+ font-size: var(--k-text-size-lg);
66
66
  }
67
67
 
68
68
  .k-button:not(:disabled):hover {
69
69
  box-shadow:
70
- 0 0.625rem 0.9375rem -0.1875rem var(--shadow-color-hover),
71
- 0 0.25rem 0.375rem -0.25rem var(--shadow-color-hover);
70
+ 0 0.625rem 0.9375rem -0.1875rem var(--k-shadow-color-hover),
71
+ 0 0.25rem 0.375rem -0.25rem var(--k-shadow-color-hover);
72
72
  }
73
73
 
74
74
  .k-button:active {
75
- box-shadow: inset 0 0.125rem 0.25rem 0 var(--shadow-color-active);
75
+ box-shadow: inset 0 0.125rem 0.25rem 0 var(--k-shadow-color-active);
76
76
  }
77
77
 
78
78
  .k-button:focus {
79
- box-shadow: 0 0 0 0.1875rem var(--shadow-color-hover);
79
+ box-shadow: 0 0 0 0.1875rem var(--k-shadow-color-hover);
80
80
  }
81
81
 
82
82
  .k-button-primary {
83
- background-color: var(--primary-color);
84
- color: var(--text-color-light);
83
+ background-color: var(--k-primary-color);
84
+ color: var(--k-text-color-light);
85
85
  }
86
86
  .k-button-primary:not(:disabled):hover {
87
- background-color: var(--primary-color-hover);
87
+ background-color: var(--k-primary-color-hover);
88
88
  }
89
89
  .k-button-primary:active {
90
- background-color: var(--primary-color-active);
90
+ background-color: var(--k-primary-color-active);
91
91
  }
92
92
  .k-button-primary:focus {
93
- box-shadow: 0 0 0 0.1875rem var(--primary-color);
93
+ box-shadow: 0 0 0 0.1875rem var(--k-primary-color);
94
94
  }
95
95
 
96
96
  .k-button-secondary {
97
- background-color: var(--secondary-color);
98
- color: var(--text-color-light);
97
+ background-color: var(--k-secondary-color);
98
+ color: var(--k-text-color-light);
99
99
  }
100
100
  .k-button-secondary:not(:disabled):hover {
101
- background-color: var(--secondary-color-hover);
101
+ background-color: var(--k-secondary-color-hover);
102
102
  }
103
103
  .k-button-secondary:active {
104
- background-color: var(--secondary-color-active);
104
+ background-color: var(--k-secondary-color-active);
105
105
  }
106
106
  .k-button-secondary:focus {
107
- box-shadow: 0 0 0 0.1875rem var(--secondary-color);
107
+ box-shadow: 0 0 0 0.1875rem var(--k-secondary-color);
108
108
  }
109
109
 
110
110
  .k-button-light {
111
- background-color: var(--light-color);
112
- color: var(--text-color);
111
+ background-color: var(--k-light-color);
112
+ color: var(--k-text-color);
113
113
  }
114
114
  .k-button-light:not(:disabled):hover {
115
- background-color: var(--light-color-hover);
115
+ background-color: var(--k-light-color-hover);
116
116
  }
117
117
  .k-button-light:active {
118
- background-color: var(--light-color-active);
118
+ background-color: var(--k-light-color-active);
119
119
  }
120
120
  .k-button-light:focus {
121
- box-shadow: 0 0 0 0.1875rem var(--light-color);
121
+ box-shadow: 0 0 0 0.1875rem var(--k-light-color);
122
122
  }
123
123
 
124
124
  .k-button-danger {
125
- background-color: var(--danger-color);
126
- color: var(--text-color-light);
125
+ background-color: var(--k-danger-color);
126
+ color: var(--k-text-color-light);
127
127
  }
128
128
  .k-button-danger:not(:disabled):hover {
129
- background-color: var(--danger-color-hover);
129
+ background-color: var(--k-danger-color-hover);
130
130
  }
131
131
  .k-button-danger:active {
132
- background-color: var(--danger-color-active);
132
+ background-color: var(--k-danger-color-active);
133
133
  }
134
134
  .k-button-danger:focus {
135
- box-shadow: 0 0 0 0.1875rem var(--danger-color);
135
+ box-shadow: 0 0 0 0.1875rem var(--k-danger-color);
136
136
  }
137
137
 
138
138
  .k-button-success {
139
- background-color: var(--success-color);
140
- color: var(--text-color-light);
139
+ background-color: var(--k-success-color);
140
+ color: var(--k-text-color-light);
141
141
  }
142
142
  .k-button-success:not(:disabled):hover {
143
- background-color: var(--success-color-hover);
143
+ background-color: var(--k-success-color-hover);
144
144
  }
145
145
  .k-button-success:active {
146
- background-color: var(--success-color-active);
146
+ background-color: var(--k-success-color-active);
147
147
  }
148
148
  .k-button-success:focus {
149
- box-shadow: 0 0 0 0.1875rem var(--success-color);
149
+ box-shadow: 0 0 0 0.1875rem var(--k-success-color);
150
150
  }
151
151
 
152
152
  .k-button-warning {
153
- background-color: var(--warning-color);
154
- color: var(--text-color);
153
+ background-color: var(--k-warning-color);
154
+ color: var(--k-warning-color-contrast);
155
155
  }
156
156
  .k-button-warning:not(:disabled):hover {
157
- background-color: var(--warning-color-hover);
157
+ background-color: var(--k-warning-color-hover);
158
158
  }
159
159
  .k-button-warning:active {
160
- background-color: var(--warning-color-active);
160
+ background-color: var(--k-warning-color-active);
161
161
  }
162
162
  .k-button-warning:focus {
163
- box-shadow: 0 0 0 0.1875rem var(--warning-color);
163
+ box-shadow: 0 0 0 0.1875rem var(--k-warning-color);
164
164
  }
165
165
 
166
166
  .k-button-link {
167
167
  background-color: transparent;
168
- color: var(--primary-color);
168
+ color: var(--k-primary-color-text);
169
169
  padding: 0;
170
170
  border-radius: 0;
171
171
  font-weight: 500;
@@ -174,17 +174,19 @@
174
174
  box-shadow: none;
175
175
  }
176
176
  .k-button-link:not(:disabled):hover {
177
- color: var(--primary-color-hover);
177
+ color: var(--k-primary-color-text);
178
+ /* One text color keeps contrast in both themes; hover shows as a heavier underline. */
179
+ text-decoration-thickness: 0.125rem;
178
180
  background-color: transparent;
179
181
  box-shadow: none;
180
182
  }
181
183
  .k-button-link:active {
182
- color: var(--primary-color-active);
184
+ color: var(--k-primary-color-text);
183
185
  background-color: transparent;
184
186
  box-shadow: none;
185
187
  }
186
188
  .k-button-link:focus {
187
- outline: 0.125rem solid var(--primary-color);
189
+ outline: 0.125rem solid var(--k-primary-color);
188
190
  outline-offset: 0.125rem;
189
191
  box-shadow: none;
190
192
  }
@@ -21,7 +21,12 @@ const RowActions = ({
21
21
  `k-row-actions-${align}`,
22
22
  `k-row-actions-gap-${gap}`,
23
23
  ].join(" ");
24
- return <div className={classes}>{children}</div>;
24
+ // Actions sit inside clickable rows; a click on one is not a row click.
25
+ return (
26
+ <div className={classes} onClick={(e) => e.stopPropagation()}>
27
+ {children}
28
+ </div>
29
+ );
25
30
  };
26
31
 
27
32
  export default RowActions;
@@ -2,6 +2,13 @@
2
2
  display: flex;
3
3
  }
4
4
 
5
+ /* Never squeeze an action below its natural width: in a narrow table cell a
6
+ shrunk icon button collapses its icon to 0px (svg max-width: 100%). The
7
+ column grows to fit instead. */
8
+ .k-row-actions > * {
9
+ flex-shrink: 0;
10
+ }
11
+
5
12
  .k-row-actions-start {
6
13
  justify-content: flex-start;
7
14
  }
@@ -10,8 +10,7 @@
10
10
  font-weight: 600;
11
11
  text-transform: uppercase;
12
12
  letter-spacing: 0.04em;
13
- color: var(--text-color);
14
- opacity: 0.65;
13
+ color: var(--k-text-color-secondary);
15
14
  }
16
15
 
17
16
  .k-address-block-body {
@@ -30,8 +29,7 @@
30
29
 
31
30
  .k-address-block-contact {
32
31
  font-size: 0.8125rem;
33
- color: var(--text-color);
34
- opacity: 0.7;
32
+ color: var(--k-text-color-secondary);
35
33
  margin-top: 0.125rem;
36
34
  }
37
35
 
@@ -7,7 +7,7 @@ export interface ColorSwatchProps {
7
7
  size?: "sm" | "md" | "lg";
8
8
  /** Border around swatch. Defaults to true. */
9
9
  bordered?: boolean;
10
- /** Accessible label (rendered as title attribute). */
10
+ /** Accessible label and tooltip. Defaults to the colour value. */
11
11
  title?: string;
12
12
  }
13
13
 
@@ -15,7 +15,7 @@ const ColorSwatch = ({
15
15
  color,
16
16
  size = "md",
17
17
  bordered = true,
18
- title,
18
+ title = color,
19
19
  }: ColorSwatchProps) => {
20
20
  return (
21
21
  <span
@@ -6,7 +6,7 @@
6
6
  }
7
7
 
8
8
  .k-color-swatch-bordered {
9
- border: 0.0625rem solid var(--border-color);
9
+ border: 0.0625rem solid var(--k-border-color);
10
10
  }
11
11
 
12
12
  .k-color-swatch-sm {
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { TableColumn, TableLeadingColumn, TableRow } from "./types.js";
4
+ import parseDataKey, { cellText } from "./utils/parseDataKey.js";
4
5
  import { useVirtualizer } from "@tanstack/react-virtual";
5
- import parseDataKey from "./utils/parseDataKey.js";
6
6
  import { useMemo, type RefObject } from "react";
7
7
  import "../table/styles.css";
8
8
  import "./styles.css";
@@ -75,6 +75,7 @@ const DataTable = <TData extends object>(props: DataTableProps<TData>) => {
75
75
  );
76
76
  }
77
77
  for (const c of columns) {
78
+ if (c.hidden) continue;
78
79
  const content = c.headerElement ? c.headerElement(c.title) : c.title;
79
80
  const alignClass = c.align ? `k-data-table-align-${c.align}` : "";
80
81
  headers.push(
@@ -105,11 +106,12 @@ const DataTable = <TData extends object>(props: DataTableProps<TData>) => {
105
106
  );
106
107
  }
107
108
  for (const c of columns) {
109
+ if (c.hidden) continue;
108
110
  const alignClass = c.align ? `k-data-table-align-${c.align}` : "";
109
111
  const content = c.cellElement
110
112
  ? c.cellElement(row.data, row.index)
111
113
  : c.dataKey
112
- ? parseDataKey(c.dataKey, row.data)
114
+ ? cellText(parseDataKey(c.dataKey, row.data))
113
115
  : undefined;
114
116
  cells.push(
115
117
  <td
@@ -124,7 +126,8 @@ const DataTable = <TData extends object>(props: DataTableProps<TData>) => {
124
126
  return cells;
125
127
  };
126
128
 
127
- const columnSpan = columns.length + (leadingColumn ? 1 : 0);
129
+ const columnSpan =
130
+ columns.filter((c) => !c.hidden).length + (leadingColumn ? 1 : 0);
128
131
 
129
132
  const body = shouldVirtualize
130
133
  ? (() => {
@@ -4,13 +4,29 @@
4
4
  width: 3rem;
5
5
  }
6
6
 
7
+ /* Even padding, overriding the table's wider first-column inset, so the
8
+ checkbox stays centered. */
9
+ .k-table th.k-data-table-leading,
10
+ .k-table td.k-data-table-leading {
11
+ padding-left: 0.5rem;
12
+ padding-right: 0.5rem;
13
+ }
14
+
15
+ /* text-align doesn't move flex items, and Checkbox's container is a
16
+ full-width flex column, so center flex content on both axes too. */
17
+ .k-data-table-leading > * {
18
+ justify-content: center;
19
+ align-items: center;
20
+ }
21
+
7
22
  .k-data-table-spacer {
8
23
  padding: 0;
9
24
  border: 0;
10
25
  }
11
26
 
27
+ /* Headers follow their column's `align`, so they line up with the cells. */
12
28
  .k-data-table-header-cell {
13
- text-align: center;
29
+ text-align: left;
14
30
  }
15
31
 
16
32
  .k-data-table-row-clickable {
@@ -18,7 +34,7 @@
18
34
  }
19
35
 
20
36
  .k-data-table-row-clickable:hover {
21
- background-color: var(--bg-hover) !important;
37
+ background-color: var(--k-background-color-hover) !important;
22
38
  }
23
39
 
24
40
  /* Alignment classes using flexbox for reliable alignment of any content */
@@ -1,39 +1,21 @@
1
+ import { ReactNode } from "react";
2
+
3
+ /**
4
+ * Reads the value at `dataKey` ("name", "address.city", "tags[1]",
5
+ * "pets[0].name"), or undefined when any part of the path is missing.
6
+ */
1
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
- const parseDataKey = (dataKey: string, data: any) => {
3
- let value = data;
4
- let more = false;
5
- do {
6
- const dotIndex = dataKey.indexOf(".");
7
- const bracketIndex = dataKey.indexOf("[");
8
- if (bracketIndex === -1 && dotIndex === -1) {
9
- value = value[dataKey];
10
- more = false;
11
- } else if (bracketIndex === -1) {
12
- const key = dataKey.substring(0, dotIndex);
13
- value = value[key];
14
- dataKey = dataKey.substring(dotIndex + 1);
15
- more = true;
16
- } else if (dotIndex === -1) {
17
- const key = dataKey.substring(0, bracketIndex);
18
- const index = dataKey.substring(bracketIndex + 1, dataKey.indexOf("]"));
19
- value = value[key][parseInt(index)];
20
- dataKey = dataKey.substring(dataKey.indexOf("]") + 1);
21
- more = true;
22
- } else if (bracketIndex < dotIndex) {
23
- const key = dataKey.substring(0, bracketIndex);
24
- const index = dataKey.substring(bracketIndex + 1, dataKey.indexOf("]"));
25
- value = value[key][parseInt(index)];
26
- dataKey = dataKey.substring(dataKey.indexOf("]") + 1);
27
- more = true;
28
- } else {
29
- const key = dataKey.substring(0, dotIndex);
30
- value = value[key];
31
- dataKey = dataKey.substring(dotIndex + 1);
32
- more = true;
33
- }
34
- } while (more);
35
- if (value === undefined) throw new Error(`Invalid dataKey: ${dataKey}`);
36
- return value;
37
- };
8
+ const parseDataKey = (dataKey: string, data: any): unknown =>
9
+ dataKey
10
+ .replace(/\[(\d+)\]/g, ".$1")
11
+ .split(".")
12
+ .filter(Boolean)
13
+ .reduce((value, key) => (value == null ? undefined : value[key]), data);
14
+
15
+ /** What a cell shows for a value: the value, or an em dash when there is none. */
16
+ export const cellText = (value: unknown): ReactNode =>
17
+ value === undefined || value === null || value === ""
18
+ ? "—"
19
+ : (value as ReactNode);
38
20
 
39
21
  export default parseDataKey;
@@ -4,7 +4,7 @@
4
4
  align-items: center;
5
5
  gap: 0.5rem;
6
6
  width: 100%;
7
- border: 0.0625rem dashed var(--border-color);
7
+ border: 0.0625rem dashed var(--k-border-color);
8
8
  border-radius: 0.25rem;
9
9
  padding: 0.5rem;
10
10
  }
@@ -23,7 +23,7 @@
23
23
  .k-image-preview-item {
24
24
  object-fit: cover;
25
25
  border-radius: 0.25rem;
26
- box-shadow: 0 0.125rem 0.25rem var(--shadow-color);
26
+ box-shadow: 0 0.125rem 0.25rem var(--k-shadow-color);
27
27
  flex-shrink: 0;
28
28
  }
29
29
 
@@ -13,9 +13,19 @@ interface InfiniteScrollMenuFiltersProps {
13
13
  handleNewPendingFilters: (
14
14
  filters: SetStateAction<InfiniteScrollMenuGeneratedFilter[]>
15
15
  ) => void;
16
+ /** Applies the pending filters; Enter in a filter's text box calls it. Omit when there's nothing to apply. */
17
+ onApply?: () => void;
18
+ /** Range filters keep edits as a draft until their menu's Apply button. */
19
+ rangeApplyInMenu?: boolean;
16
20
  children?: ReactNode;
17
21
  }
18
22
 
23
+ // Enter in a search, number or date box applies, as in a form; checkboxes and
24
+ // buttons keep their own Enter behaviour.
25
+ const isTextEntry = (target: EventTarget) =>
26
+ target instanceof HTMLInputElement &&
27
+ !["checkbox", "radio", "button", "submit"].includes(target.type);
28
+
19
29
  const Filters = (props: InfiniteScrollMenuFiltersProps) => {
20
30
  const handleFilterChange = useCallback(
21
31
  (filter: InfiniteScrollMenuGeneratedFilter) => {
@@ -41,6 +51,7 @@ const Filters = (props: InfiniteScrollMenuFiltersProps) => {
41
51
  key={filter.filterId}
42
52
  filter={filter}
43
53
  onFilterChange={handleFilterChange}
54
+ applyInMenu={props.rangeApplyInMenu}
44
55
  />
45
56
  );
46
57
  } else if (filter.type === "SEARCH") {
@@ -62,8 +73,14 @@ const Filters = (props: InfiniteScrollMenuFiltersProps) => {
62
73
  }
63
74
  };
64
75
 
76
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
77
+ if (e.key !== "Enter" || !props.onApply || !isTextEntry(e.target)) return;
78
+ e.preventDefault();
79
+ props.onApply();
80
+ };
81
+
65
82
  return (
66
- <div className="k-menu-filters-container">
83
+ <div className="k-menu-filters-container" onKeyDown={handleKeyDown}>
67
84
  <div className="k-menu-filters">
68
85
  {props.pendingFilters.map(getFilter)}
69
86
  </div>
@@ -71,6 +71,7 @@ const ListFilter = (props: InfiniteScrollListFilterProps) => {
71
71
  onChange={handleChange}
72
72
  type="text"
73
73
  onKeyDown={handleKeydown}
74
+ aria-label={`${props.filter.title} values`}
74
75
  />
75
76
  <Button size="sm" disabled={!allowSubmit} onClick={handleSubmit}>
76
77
  Add Filter
@@ -1,7 +1,9 @@
1
1
  "use client";
2
2
 
3
3
  import { useCallback, useEffect, useMemo, useState } from "react";
4
+ import { hasRangeValue } from "../utils/hasPendingChanges.js";
4
5
  import Dropdown from "../../../inputs/dropdown/index.js";
6
+ import Button from "../../../buttons/button/index.js";
5
7
  import Input from "../../../inputs/input/index.js";
6
8
  import { DateTime } from "luxon";
7
9
  import "./styles.css";
@@ -19,8 +21,35 @@ import {
19
21
  interface InfiniteScrollRangeFilterProps {
20
22
  filter: GeneratedRangeFilter;
21
23
  onFilterChange: (filter: InfiniteScrollMenuGeneratedFilter) => void;
24
+ /**
25
+ * Edits stay a draft until the menu's Apply button (or Enter), so both
26
+ * bounds can be typed before anything is fetched. Closing the menu drops
27
+ * the draft. Without it, each edit reports at once.
28
+ */
29
+ applyInMenu?: boolean;
22
30
  }
23
31
 
32
+ // An empty or unparseable box is no bound, never NaN or a thrown error. A DATE
33
+ // range sends the picked calendar day (yyyy-mm-dd): converting local midnight
34
+ // to UTC moved it off the day the user chose.
35
+ const parseRangeInput = (
36
+ rangeType: GeneratedRangeFilter["rangeType"],
37
+ raw: string
38
+ ): RangeValue | undefined => {
39
+ if (raw === "") return undefined;
40
+ if (rangeType === "NUMBER") {
41
+ const n = Number(raw);
42
+ return Number.isNaN(n) ? undefined : n;
43
+ }
44
+ if (rangeType === "DATE") {
45
+ return DateTime.fromISO(raw).isValid ? raw : undefined;
46
+ }
47
+ if (rangeType === "DATETIME") {
48
+ return DateTime.fromISO(raw).toUTC().toISO() ?? undefined;
49
+ }
50
+ return raw;
51
+ };
52
+
24
53
  const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
25
54
  const [startValue, setStartValue] = useState<RangeValue | undefined>(
26
55
  props.filter.startValue
@@ -29,17 +58,41 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
29
58
  props.filter.endValue
30
59
  );
31
60
 
61
+ const [isOpen, setIsOpen] = useState(false);
62
+
63
+ // Follow the filter when it changes from outside (a tag removed, Reset),
64
+ // without undoing a draft in progress.
32
65
  useEffect(() => {
33
- if (props.filter.startValue === startValue) return;
34
66
  setStartValue(props.filter.startValue);
35
- return;
36
- }, [props.filter.startValue, startValue]);
67
+ }, [props.filter.startValue]);
37
68
 
38
69
  useEffect(() => {
39
- if (props.filter.endValue === endValue) return;
40
70
  setEndValue(props.filter.endValue);
41
- return;
42
- }, [props.filter.endValue, endValue]);
71
+ }, [props.filter.endValue]);
72
+
73
+ const isDirty =
74
+ startValue !== props.filter.startValue ||
75
+ endValue !== props.filter.endValue;
76
+
77
+ const commit = () => {
78
+ props.onFilterChange({ ...props.filter, startValue, endValue });
79
+ setIsOpen(false);
80
+ };
81
+
82
+ const handleOpenChange = (open: boolean) => {
83
+ setIsOpen(open);
84
+ if (open || !props.applyInMenu) return;
85
+ setStartValue(props.filter.startValue);
86
+ setEndValue(props.filter.endValue);
87
+ };
88
+
89
+ // Enter applies the draft here instead of reaching the filter bar.
90
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
91
+ if (!props.applyInMenu || e.key !== "Enter") return;
92
+ e.preventDefault();
93
+ e.stopPropagation();
94
+ if (isDirty) commit();
95
+ };
43
96
 
44
97
  const inputType = useMemo(() => {
45
98
  if (props.filter.rangeType === "NUMBER") {
@@ -62,7 +115,7 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
62
115
  }, [props.filter.rangeType]);
63
116
 
64
117
  const formattedStartValue = useMemo((): RangeValue => {
65
- if (!startValue) return "";
118
+ if (!hasRangeValue(startValue)) return "";
66
119
  if (props.filter.rangeType === "DATE") {
67
120
  return DateTime.fromISO(startValue as string).toFormat("yyyy-MM-dd");
68
121
  } else if (props.filter.rangeType === "DATETIME") {
@@ -73,7 +126,7 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
73
126
  }, [props.filter.rangeType, startValue]);
74
127
 
75
128
  const formattedEndValue = useMemo((): RangeValue => {
76
- if (!endValue) return "";
129
+ if (!hasRangeValue(endValue)) return "";
77
130
  if (props.filter.rangeType === "DATE") {
78
131
  return DateTime.fromISO(endValue as string).toFormat("yyyy-MM-dd");
79
132
  } else if (props.filter.rangeType === "DATETIME") {
@@ -85,19 +138,9 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
85
138
 
86
139
  const handleStartChange = useCallback(
87
140
  (e: React.ChangeEvent<HTMLInputElement>) => {
88
- let newValue: RangeValue;
89
- if (props.filter.rangeType === "NUMBER") {
90
- newValue = parseInt(e.target.value);
91
- } else if (props.filter.rangeType === "DATE") {
92
- const res = DateTime.fromISO(e.target.value).toUTC().toISO();
93
- if (!res) throw new Error("Invalid date");
94
- newValue = res;
95
- } else if (props.filter.rangeType === "DATETIME") {
96
- const res = DateTime.fromISO(e.target.value).toUTC().toISO();
97
- if (!res) throw new Error("Invalid date");
98
- newValue = res;
99
- } else newValue = e.target.value;
141
+ const newValue = parseRangeInput(props.filter.rangeType, e.target.value);
100
142
  setStartValue(newValue);
143
+ if (props.applyInMenu) return;
101
144
  props.onFilterChange({
102
145
  ...props.filter,
103
146
  startValue: newValue,
@@ -109,19 +152,9 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
109
152
 
110
153
  const handleEndChange = useCallback(
111
154
  (e: React.ChangeEvent<HTMLInputElement>) => {
112
- let newValue: RangeValue;
113
- if (props.filter.rangeType === "NUMBER") {
114
- newValue = parseInt(e.target.value);
115
- } else if (props.filter.rangeType === "DATE") {
116
- const res = DateTime.fromISO(e.target.value).toUTC().toISO();
117
- if (!res) throw new Error("Invalid date");
118
- newValue = res;
119
- } else if (props.filter.rangeType === "DATETIME") {
120
- const res = DateTime.fromISO(e.target.value).toUTC().toISO();
121
- if (!res) throw new Error("Invalid date");
122
- newValue = res;
123
- } else newValue = e.target.value;
155
+ const newValue = parseRangeInput(props.filter.rangeType, e.target.value);
124
156
  setEndValue(newValue);
157
+ if (props.applyInMenu) return;
125
158
  props.onFilterChange({
126
159
  ...props.filter,
127
160
  startValue,
@@ -138,8 +171,10 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
138
171
  label={props.filter.title}
139
172
  icon={iconToUse}
140
173
  align="left"
174
+ isOpen={isOpen}
175
+ onOpenChange={handleOpenChange}
141
176
  >
142
- <div className="k-filter-menu">
177
+ <div className="k-filter-menu" onKeyDown={handleKeyDown}>
143
178
  <div className="k-range-filter-menu-column">
144
179
  <p className="k-range-filter-menu-label">Start</p>
145
180
  <Input
@@ -147,6 +182,7 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
147
182
  type={inputType}
148
183
  value={formattedStartValue}
149
184
  onChange={handleStartChange}
185
+ aria-label={`${props.filter.title} start`}
150
186
  max={formattedEndValue}
151
187
  />
152
188
  </div>
@@ -157,9 +193,17 @@ const RangeFilter = (props: InfiniteScrollRangeFilterProps) => {
157
193
  type={inputType}
158
194
  value={formattedEndValue}
159
195
  onChange={handleEndChange}
196
+ aria-label={`${props.filter.title} end`}
160
197
  min={formattedStartValue}
161
198
  />
162
199
  </div>
200
+ {props.applyInMenu && (
201
+ <div className="k-range-filter-menu-actions">
202
+ <Button size="sm" disabled={!isDirty} onClick={commit}>
203
+ Apply
204
+ </Button>
205
+ </div>
206
+ )}
163
207
  </div>
164
208
  </Dropdown>
165
209
  );