@furystack/shades-common-components 13.5.0 → 15.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 (540) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +3 -3
  3. package/esm/components/accordion/accordion-item.d.ts.map +1 -1
  4. package/esm/components/accordion/accordion-item.js +7 -10
  5. package/esm/components/accordion/accordion-item.js.map +1 -1
  6. package/esm/components/accordion/accordion.d.ts +7 -0
  7. package/esm/components/accordion/accordion.d.ts.map +1 -1
  8. package/esm/components/accordion/accordion.js +5 -2
  9. package/esm/components/accordion/accordion.js.map +1 -1
  10. package/esm/components/accordion/accordion.spec.js +91 -50
  11. package/esm/components/accordion/accordion.spec.js.map +1 -1
  12. package/esm/components/alert.js +1 -1
  13. package/esm/components/alert.js.map +1 -1
  14. package/esm/components/app-bar-link.js +1 -1
  15. package/esm/components/app-bar-link.js.map +1 -1
  16. package/esm/components/app-bar.js +1 -1
  17. package/esm/components/app-bar.js.map +1 -1
  18. package/esm/components/avatar.js +1 -1
  19. package/esm/components/avatar.js.map +1 -1
  20. package/esm/components/badge.js +1 -1
  21. package/esm/components/badge.js.map +1 -1
  22. package/esm/components/breadcrumb.js +1 -1
  23. package/esm/components/breadcrumb.js.map +1 -1
  24. package/esm/components/breadcrumb.spec.js +3 -3
  25. package/esm/components/breadcrumb.spec.js.map +1 -1
  26. package/esm/components/button-group.js +4 -4
  27. package/esm/components/button-group.js.map +1 -1
  28. package/esm/components/button.js +1 -1
  29. package/esm/components/button.js.map +1 -1
  30. package/esm/components/button.spec.js +1 -1
  31. package/esm/components/button.spec.js.map +1 -1
  32. package/esm/components/cache-view.js +1 -1
  33. package/esm/components/cache-view.js.map +1 -1
  34. package/esm/components/cache-view.spec.js +2 -2
  35. package/esm/components/cache-view.spec.js.map +1 -1
  36. package/esm/components/card.js +5 -5
  37. package/esm/components/card.js.map +1 -1
  38. package/esm/components/carousel.js +2 -2
  39. package/esm/components/carousel.js.map +1 -1
  40. package/esm/components/chip.d.ts.map +1 -1
  41. package/esm/components/chip.js +5 -3
  42. package/esm/components/chip.js.map +1 -1
  43. package/esm/components/chip.spec.js +42 -0
  44. package/esm/components/chip.spec.js.map +1 -1
  45. package/esm/components/circular-progress.d.ts +2 -4
  46. package/esm/components/circular-progress.d.ts.map +1 -1
  47. package/esm/components/circular-progress.js +3 -6
  48. package/esm/components/circular-progress.js.map +1 -1
  49. package/esm/components/circular-progress.spec.js +19 -14
  50. package/esm/components/circular-progress.spec.js.map +1 -1
  51. package/esm/components/command-palette/command-palette-input.js +1 -1
  52. package/esm/components/command-palette/command-palette-input.js.map +1 -1
  53. package/esm/components/command-palette/command-palette-suggestion-list.js +1 -1
  54. package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
  55. package/esm/components/command-palette/command-palette-suggestion-list.spec.js +1 -1
  56. package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -1
  57. package/esm/components/command-palette/index.d.ts.map +1 -1
  58. package/esm/components/command-palette/index.js +15 -2
  59. package/esm/components/command-palette/index.js.map +1 -1
  60. package/esm/components/command-palette/index.spec.js +78 -33
  61. package/esm/components/command-palette/index.spec.js.map +1 -1
  62. package/esm/components/context-menu/context-menu-item.js +1 -1
  63. package/esm/components/context-menu/context-menu-item.js.map +1 -1
  64. package/esm/components/context-menu/context-menu.js +1 -1
  65. package/esm/components/context-menu/context-menu.js.map +1 -1
  66. package/esm/components/data-grid/body.js +1 -1
  67. package/esm/components/data-grid/body.js.map +1 -1
  68. package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
  69. package/esm/components/data-grid/data-grid-row.js +19 -3
  70. package/esm/components/data-grid/data-grid-row.js.map +1 -1
  71. package/esm/components/data-grid/data-grid.d.ts +12 -2
  72. package/esm/components/data-grid/data-grid.d.ts.map +1 -1
  73. package/esm/components/data-grid/data-grid.js +33 -13
  74. package/esm/components/data-grid/data-grid.js.map +1 -1
  75. package/esm/components/data-grid/data-grid.spec.js +170 -90
  76. package/esm/components/data-grid/data-grid.spec.js.map +1 -1
  77. package/esm/components/data-grid/filters/boolean-filter.d.ts +2 -2
  78. package/esm/components/data-grid/filters/boolean-filter.d.ts.map +1 -1
  79. package/esm/components/data-grid/filters/boolean-filter.js +4 -4
  80. package/esm/components/data-grid/filters/boolean-filter.js.map +1 -1
  81. package/esm/components/data-grid/filters/boolean-filter.spec.js +18 -17
  82. package/esm/components/data-grid/filters/boolean-filter.spec.js.map +1 -1
  83. package/esm/components/data-grid/filters/date-filter.d.ts +2 -2
  84. package/esm/components/data-grid/filters/date-filter.d.ts.map +1 -1
  85. package/esm/components/data-grid/filters/date-filter.js +6 -6
  86. package/esm/components/data-grid/filters/date-filter.js.map +1 -1
  87. package/esm/components/data-grid/filters/date-filter.spec.js +26 -21
  88. package/esm/components/data-grid/filters/date-filter.spec.js.map +1 -1
  89. package/esm/components/data-grid/filters/enum-filter.d.ts +2 -2
  90. package/esm/components/data-grid/filters/enum-filter.d.ts.map +1 -1
  91. package/esm/components/data-grid/filters/enum-filter.js +5 -5
  92. package/esm/components/data-grid/filters/enum-filter.js.map +1 -1
  93. package/esm/components/data-grid/filters/enum-filter.spec.js +21 -19
  94. package/esm/components/data-grid/filters/enum-filter.spec.js.map +1 -1
  95. package/esm/components/data-grid/filters/filter-dropdown.js +1 -1
  96. package/esm/components/data-grid/filters/filter-dropdown.js.map +1 -1
  97. package/esm/components/data-grid/filters/number-filter.d.ts +2 -2
  98. package/esm/components/data-grid/filters/number-filter.d.ts.map +1 -1
  99. package/esm/components/data-grid/filters/number-filter.js +5 -5
  100. package/esm/components/data-grid/filters/number-filter.js.map +1 -1
  101. package/esm/components/data-grid/filters/number-filter.spec.js +23 -21
  102. package/esm/components/data-grid/filters/number-filter.spec.js.map +1 -1
  103. package/esm/components/data-grid/filters/string-filter.d.ts +2 -2
  104. package/esm/components/data-grid/filters/string-filter.d.ts.map +1 -1
  105. package/esm/components/data-grid/filters/string-filter.js +5 -5
  106. package/esm/components/data-grid/filters/string-filter.js.map +1 -1
  107. package/esm/components/data-grid/filters/string-filter.spec.js +21 -19
  108. package/esm/components/data-grid/filters/string-filter.spec.js.map +1 -1
  109. package/esm/components/data-grid/footer.d.ts +2 -2
  110. package/esm/components/data-grid/footer.d.ts.map +1 -1
  111. package/esm/components/data-grid/footer.js +8 -13
  112. package/esm/components/data-grid/footer.js.map +1 -1
  113. package/esm/components/data-grid/footer.spec.js +38 -27
  114. package/esm/components/data-grid/footer.spec.js.map +1 -1
  115. package/esm/components/data-grid/header.d.ts +6 -6
  116. package/esm/components/data-grid/header.d.ts.map +1 -1
  117. package/esm/components/data-grid/header.js +16 -17
  118. package/esm/components/data-grid/header.js.map +1 -1
  119. package/esm/components/data-grid/header.spec.js +66 -60
  120. package/esm/components/data-grid/header.spec.js.map +1 -1
  121. package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
  122. package/esm/components/data-grid/selection-cell.js +2 -2
  123. package/esm/components/data-grid/selection-cell.js.map +1 -1
  124. package/esm/components/dialog.d.ts +11 -0
  125. package/esm/components/dialog.d.ts.map +1 -1
  126. package/esm/components/dialog.js +3 -3
  127. package/esm/components/dialog.js.map +1 -1
  128. package/esm/components/dialog.spec.js +54 -2
  129. package/esm/components/dialog.spec.js.map +1 -1
  130. package/esm/components/divider.js +1 -1
  131. package/esm/components/divider.js.map +1 -1
  132. package/esm/components/drawer/drawer-toggle-button.js +1 -1
  133. package/esm/components/drawer/drawer-toggle-button.js.map +1 -1
  134. package/esm/components/drawer/index.js +1 -1
  135. package/esm/components/drawer/index.js.map +1 -1
  136. package/esm/components/dropdown.d.ts.map +1 -1
  137. package/esm/components/dropdown.js +2 -2
  138. package/esm/components/dropdown.js.map +1 -1
  139. package/esm/components/dropdown.spec.js +8 -0
  140. package/esm/components/dropdown.spec.js.map +1 -1
  141. package/esm/components/fab.js +1 -1
  142. package/esm/components/fab.js.map +1 -1
  143. package/esm/components/form.js +1 -1
  144. package/esm/components/form.js.map +1 -1
  145. package/esm/components/grid.js +1 -1
  146. package/esm/components/grid.js.map +1 -1
  147. package/esm/components/icons/icon.js +1 -1
  148. package/esm/components/icons/icon.js.map +1 -1
  149. package/esm/components/image.d.ts.map +1 -1
  150. package/esm/components/image.js +17 -8
  151. package/esm/components/image.js.map +1 -1
  152. package/esm/components/image.spec.js +60 -0
  153. package/esm/components/image.spec.js.map +1 -1
  154. package/esm/components/inputs/autocomplete.js +1 -1
  155. package/esm/components/inputs/autocomplete.js.map +1 -1
  156. package/esm/components/inputs/checkbox.d.ts.map +1 -1
  157. package/esm/components/inputs/checkbox.js +2 -1
  158. package/esm/components/inputs/checkbox.js.map +1 -1
  159. package/esm/components/inputs/checkbox.spec.js +1 -1
  160. package/esm/components/inputs/checkbox.spec.js.map +1 -1
  161. package/esm/components/inputs/input-number.js +1 -1
  162. package/esm/components/inputs/input-number.js.map +1 -1
  163. package/esm/components/inputs/input-number.spec.js +1 -1
  164. package/esm/components/inputs/input-number.spec.js.map +1 -1
  165. package/esm/components/inputs/input.js +1 -1
  166. package/esm/components/inputs/input.js.map +1 -1
  167. package/esm/components/inputs/input.spec.js +1 -1
  168. package/esm/components/inputs/input.spec.js.map +1 -1
  169. package/esm/components/inputs/radio-group.js +1 -1
  170. package/esm/components/inputs/radio-group.js.map +1 -1
  171. package/esm/components/inputs/radio-group.spec.js +1 -1
  172. package/esm/components/inputs/radio-group.spec.js.map +1 -1
  173. package/esm/components/inputs/radio.d.ts.map +1 -1
  174. package/esm/components/inputs/radio.js +2 -1
  175. package/esm/components/inputs/radio.js.map +1 -1
  176. package/esm/components/inputs/radio.spec.js +1 -1
  177. package/esm/components/inputs/radio.spec.js.map +1 -1
  178. package/esm/components/inputs/select.js +1 -1
  179. package/esm/components/inputs/select.js.map +1 -1
  180. package/esm/components/inputs/slider.d.ts.map +1 -1
  181. package/esm/components/inputs/slider.js +2 -1
  182. package/esm/components/inputs/slider.js.map +1 -1
  183. package/esm/components/inputs/switch.d.ts.map +1 -1
  184. package/esm/components/inputs/switch.js +2 -1
  185. package/esm/components/inputs/switch.js.map +1 -1
  186. package/esm/components/inputs/switch.spec.js +1 -1
  187. package/esm/components/inputs/switch.spec.js.map +1 -1
  188. package/esm/components/inputs/text-area.js +1 -1
  189. package/esm/components/inputs/text-area.js.map +1 -1
  190. package/esm/components/inputs/text-area.spec.js +1 -1
  191. package/esm/components/inputs/text-area.spec.js.map +1 -1
  192. package/esm/components/linear-progress.d.ts +2 -4
  193. package/esm/components/linear-progress.d.ts.map +1 -1
  194. package/esm/components/linear-progress.js +3 -6
  195. package/esm/components/linear-progress.js.map +1 -1
  196. package/esm/components/linear-progress.spec.js +21 -18
  197. package/esm/components/linear-progress.spec.js.map +1 -1
  198. package/esm/components/list/list-item.d.ts.map +1 -1
  199. package/esm/components/list/list-item.js +22 -6
  200. package/esm/components/list/list-item.js.map +1 -1
  201. package/esm/components/list/list.d.ts +7 -0
  202. package/esm/components/list/list.d.ts.map +1 -1
  203. package/esm/components/list/list.js +29 -9
  204. package/esm/components/list/list.js.map +1 -1
  205. package/esm/components/list/list.spec.js +117 -23
  206. package/esm/components/list/list.spec.js.map +1 -1
  207. package/esm/components/loader.js +1 -1
  208. package/esm/components/loader.js.map +1 -1
  209. package/esm/components/loader.spec.js +1 -1
  210. package/esm/components/loader.spec.js.map +1 -1
  211. package/esm/components/markdown/markdown-display.d.ts.map +1 -1
  212. package/esm/components/markdown/markdown-display.js +12 -2
  213. package/esm/components/markdown/markdown-display.js.map +1 -1
  214. package/esm/components/markdown/markdown-display.spec.js +98 -1
  215. package/esm/components/markdown/markdown-display.spec.js.map +1 -1
  216. package/esm/components/markdown/markdown-editor.js +1 -1
  217. package/esm/components/markdown/markdown-editor.js.map +1 -1
  218. package/esm/components/markdown/markdown-editor.spec.js +88 -1
  219. package/esm/components/markdown/markdown-editor.spec.js.map +1 -1
  220. package/esm/components/markdown/markdown-input.js +1 -1
  221. package/esm/components/markdown/markdown-input.js.map +1 -1
  222. package/esm/components/markdown/markdown-input.spec.js +1 -1
  223. package/esm/components/markdown/markdown-input.spec.js.map +1 -1
  224. package/esm/components/menu/menu.js +2 -2
  225. package/esm/components/menu/menu.js.map +1 -1
  226. package/esm/components/modal.d.ts +10 -0
  227. package/esm/components/modal.d.ts.map +1 -1
  228. package/esm/components/modal.js +25 -5
  229. package/esm/components/modal.js.map +1 -1
  230. package/esm/components/modal.spec.js +89 -4
  231. package/esm/components/modal.spec.js.map +1 -1
  232. package/esm/components/noty-list.js +2 -2
  233. package/esm/components/noty-list.js.map +1 -1
  234. package/esm/components/page-container/index.js +1 -1
  235. package/esm/components/page-container/index.js.map +1 -1
  236. package/esm/components/page-container/page-header.js +1 -1
  237. package/esm/components/page-container/page-header.js.map +1 -1
  238. package/esm/components/page-layout/index.js +2 -2
  239. package/esm/components/page-layout/index.js.map +1 -1
  240. package/esm/components/page-layout/index.spec.js +14 -0
  241. package/esm/components/page-layout/index.spec.js.map +1 -1
  242. package/esm/components/pagination.js +1 -1
  243. package/esm/components/pagination.js.map +1 -1
  244. package/esm/components/paper.js +1 -1
  245. package/esm/components/paper.js.map +1 -1
  246. package/esm/components/rating.d.ts.map +1 -1
  247. package/esm/components/rating.js +29 -22
  248. package/esm/components/rating.js.map +1 -1
  249. package/esm/components/rating.spec.js +152 -5
  250. package/esm/components/rating.spec.js.map +1 -1
  251. package/esm/components/result.js +1 -1
  252. package/esm/components/result.js.map +1 -1
  253. package/esm/components/skeleton.js +1 -1
  254. package/esm/components/skeleton.js.map +1 -1
  255. package/esm/components/suggest/index.d.ts.map +1 -1
  256. package/esm/components/suggest/index.js +15 -2
  257. package/esm/components/suggest/index.js.map +1 -1
  258. package/esm/components/suggest/index.spec.js +99 -44
  259. package/esm/components/suggest/index.spec.js.map +1 -1
  260. package/esm/components/suggest/suggest-input.js +1 -1
  261. package/esm/components/suggest/suggest-input.js.map +1 -1
  262. package/esm/components/suggest/suggest-input.spec.js +1 -1
  263. package/esm/components/suggest/suggest-input.spec.js.map +1 -1
  264. package/esm/components/suggest/suggestion-list.js +1 -1
  265. package/esm/components/suggest/suggestion-list.js.map +1 -1
  266. package/esm/components/suggest/suggestion-list.spec.js +1 -1
  267. package/esm/components/suggest/suggestion-list.spec.js.map +1 -1
  268. package/esm/components/tabs.d.ts.map +1 -1
  269. package/esm/components/tabs.js +6 -2
  270. package/esm/components/tabs.js.map +1 -1
  271. package/esm/components/timeline.js +2 -2
  272. package/esm/components/timeline.js.map +1 -1
  273. package/esm/components/tooltip.js +1 -1
  274. package/esm/components/tooltip.js.map +1 -1
  275. package/esm/components/tree/tree-item.d.ts.map +1 -1
  276. package/esm/components/tree/tree-item.js +19 -6
  277. package/esm/components/tree/tree-item.js.map +1 -1
  278. package/esm/components/tree/tree.d.ts +7 -0
  279. package/esm/components/tree/tree.d.ts.map +1 -1
  280. package/esm/components/tree/tree.js +13 -4
  281. package/esm/components/tree/tree.js.map +1 -1
  282. package/esm/components/tree/tree.spec.js +64 -2
  283. package/esm/components/tree/tree.spec.js.map +1 -1
  284. package/esm/components/typography.js +1 -1
  285. package/esm/components/typography.js.map +1 -1
  286. package/esm/components/wizard/index.js +1 -1
  287. package/esm/components/wizard/index.js.map +1 -1
  288. package/esm/components/wizard/index.spec.js +3 -3
  289. package/esm/components/wizard/index.spec.js.map +1 -1
  290. package/esm/services/collection-service.d.ts +9 -0
  291. package/esm/services/collection-service.d.ts.map +1 -1
  292. package/esm/services/collection-service.js +33 -11
  293. package/esm/services/collection-service.js.map +1 -1
  294. package/esm/services/collection-service.spec.js +33 -24
  295. package/esm/services/collection-service.spec.js.map +1 -1
  296. package/esm/services/css-variable-theme.d.ts +7 -0
  297. package/esm/services/css-variable-theme.d.ts.map +1 -1
  298. package/esm/services/css-variable-theme.js +23 -0
  299. package/esm/services/css-variable-theme.js.map +1 -1
  300. package/esm/services/css-variable-theme.spec.js +1 -0
  301. package/esm/services/css-variable-theme.spec.js.map +1 -1
  302. package/esm/services/list-service.d.ts +9 -0
  303. package/esm/services/list-service.d.ts.map +1 -1
  304. package/esm/services/list-service.js +13 -13
  305. package/esm/services/list-service.js.map +1 -1
  306. package/esm/services/list-service.spec.js +13 -33
  307. package/esm/services/list-service.spec.js.map +1 -1
  308. package/esm/services/theme-provider-service.d.ts +3 -0
  309. package/esm/services/theme-provider-service.d.ts.map +1 -1
  310. package/esm/services/theme-provider-service.js.map +1 -1
  311. package/esm/services/tree-service.d.ts.map +1 -1
  312. package/esm/services/tree-service.js +5 -9
  313. package/esm/services/tree-service.js.map +1 -1
  314. package/esm/services/tree-service.spec.js +12 -9
  315. package/esm/services/tree-service.spec.js.map +1 -1
  316. package/esm/themes/architect-theme.d.ts +1 -0
  317. package/esm/themes/architect-theme.d.ts.map +1 -1
  318. package/esm/themes/architect-theme.js +1 -0
  319. package/esm/themes/architect-theme.js.map +1 -1
  320. package/esm/themes/auditore-theme.d.ts +1 -0
  321. package/esm/themes/auditore-theme.d.ts.map +1 -1
  322. package/esm/themes/auditore-theme.js +1 -0
  323. package/esm/themes/auditore-theme.js.map +1 -1
  324. package/esm/themes/black-mesa-theme.d.ts +1 -0
  325. package/esm/themes/black-mesa-theme.d.ts.map +1 -1
  326. package/esm/themes/black-mesa-theme.js +1 -0
  327. package/esm/themes/black-mesa-theme.js.map +1 -1
  328. package/esm/themes/chieftain-theme.d.ts +1 -0
  329. package/esm/themes/chieftain-theme.d.ts.map +1 -1
  330. package/esm/themes/chieftain-theme.js +1 -0
  331. package/esm/themes/chieftain-theme.js.map +1 -1
  332. package/esm/themes/default-dark-theme.d.ts +1 -0
  333. package/esm/themes/default-dark-theme.d.ts.map +1 -1
  334. package/esm/themes/default-dark-theme.js +1 -0
  335. package/esm/themes/default-dark-theme.js.map +1 -1
  336. package/esm/themes/default-light-theme.d.ts +1 -0
  337. package/esm/themes/default-light-theme.d.ts.map +1 -1
  338. package/esm/themes/default-light-theme.js +1 -0
  339. package/esm/themes/default-light-theme.js.map +1 -1
  340. package/esm/themes/dragonborn-theme.d.ts +1 -0
  341. package/esm/themes/dragonborn-theme.d.ts.map +1 -1
  342. package/esm/themes/dragonborn-theme.js +1 -0
  343. package/esm/themes/dragonborn-theme.js.map +1 -1
  344. package/esm/themes/hawkins-theme.d.ts +1 -0
  345. package/esm/themes/hawkins-theme.d.ts.map +1 -1
  346. package/esm/themes/hawkins-theme.js +1 -0
  347. package/esm/themes/hawkins-theme.js.map +1 -1
  348. package/esm/themes/jedi-theme.d.ts +1 -0
  349. package/esm/themes/jedi-theme.d.ts.map +1 -1
  350. package/esm/themes/jedi-theme.js +1 -0
  351. package/esm/themes/jedi-theme.js.map +1 -1
  352. package/esm/themes/neon-runner-theme.d.ts +1 -0
  353. package/esm/themes/neon-runner-theme.d.ts.map +1 -1
  354. package/esm/themes/neon-runner-theme.js +1 -0
  355. package/esm/themes/neon-runner-theme.js.map +1 -1
  356. package/esm/themes/paladin-theme.d.ts +1 -0
  357. package/esm/themes/paladin-theme.d.ts.map +1 -1
  358. package/esm/themes/paladin-theme.js +1 -0
  359. package/esm/themes/paladin-theme.js.map +1 -1
  360. package/esm/themes/plumber-theme.d.ts +1 -0
  361. package/esm/themes/plumber-theme.d.ts.map +1 -1
  362. package/esm/themes/plumber-theme.js +1 -0
  363. package/esm/themes/plumber-theme.js.map +1 -1
  364. package/esm/themes/replicant-theme.d.ts +1 -0
  365. package/esm/themes/replicant-theme.d.ts.map +1 -1
  366. package/esm/themes/replicant-theme.js +1 -0
  367. package/esm/themes/replicant-theme.js.map +1 -1
  368. package/esm/themes/sandworm-theme.d.ts +1 -0
  369. package/esm/themes/sandworm-theme.d.ts.map +1 -1
  370. package/esm/themes/sandworm-theme.js +1 -0
  371. package/esm/themes/sandworm-theme.js.map +1 -1
  372. package/esm/themes/shadow-broker-theme.d.ts +1 -0
  373. package/esm/themes/shadow-broker-theme.d.ts.map +1 -1
  374. package/esm/themes/shadow-broker-theme.js +1 -0
  375. package/esm/themes/shadow-broker-theme.js.map +1 -1
  376. package/esm/themes/sith-theme.d.ts +1 -0
  377. package/esm/themes/sith-theme.d.ts.map +1 -1
  378. package/esm/themes/sith-theme.js +1 -0
  379. package/esm/themes/sith-theme.js.map +1 -1
  380. package/esm/themes/vault-dweller-theme.d.ts +1 -0
  381. package/esm/themes/vault-dweller-theme.d.ts.map +1 -1
  382. package/esm/themes/vault-dweller-theme.js +1 -0
  383. package/esm/themes/vault-dweller-theme.js.map +1 -1
  384. package/esm/themes/wild-hunt-theme.d.ts +1 -0
  385. package/esm/themes/wild-hunt-theme.d.ts.map +1 -1
  386. package/esm/themes/wild-hunt-theme.js +1 -0
  387. package/esm/themes/wild-hunt-theme.js.map +1 -1
  388. package/esm/themes/xenomorph-theme.d.ts +1 -0
  389. package/esm/themes/xenomorph-theme.d.ts.map +1 -1
  390. package/esm/themes/xenomorph-theme.js +1 -0
  391. package/esm/themes/xenomorph-theme.js.map +1 -1
  392. package/package.json +3 -3
  393. package/src/components/accordion/accordion-item.tsx +10 -15
  394. package/src/components/accordion/accordion.spec.tsx +134 -79
  395. package/src/components/accordion/accordion.tsx +14 -2
  396. package/src/components/alert.tsx +1 -1
  397. package/src/components/app-bar-link.tsx +1 -1
  398. package/src/components/app-bar.tsx +1 -1
  399. package/src/components/avatar.tsx +1 -1
  400. package/src/components/badge.tsx +1 -1
  401. package/src/components/breadcrumb.spec.tsx +3 -3
  402. package/src/components/breadcrumb.tsx +1 -1
  403. package/src/components/button-group.tsx +4 -4
  404. package/src/components/button.spec.tsx +1 -1
  405. package/src/components/button.tsx +1 -1
  406. package/src/components/cache-view.spec.tsx +2 -2
  407. package/src/components/cache-view.tsx +3 -3
  408. package/src/components/card.tsx +5 -5
  409. package/src/components/carousel.tsx +2 -2
  410. package/src/components/chip.spec.tsx +64 -0
  411. package/src/components/chip.tsx +5 -2
  412. package/src/components/circular-progress.spec.tsx +20 -14
  413. package/src/components/circular-progress.tsx +5 -11
  414. package/src/components/command-palette/command-palette-input.tsx +1 -1
  415. package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +1 -1
  416. package/src/components/command-palette/command-palette-suggestion-list.tsx +1 -1
  417. package/src/components/command-palette/index.spec.tsx +95 -33
  418. package/src/components/command-palette/index.tsx +16 -4
  419. package/src/components/context-menu/context-menu-item.tsx +1 -1
  420. package/src/components/context-menu/context-menu.tsx +1 -1
  421. package/src/components/data-grid/body.tsx +1 -1
  422. package/src/components/data-grid/data-grid-row.tsx +21 -3
  423. package/src/components/data-grid/data-grid.spec.tsx +246 -92
  424. package/src/components/data-grid/data-grid.tsx +52 -21
  425. package/src/components/data-grid/filters/boolean-filter.spec.tsx +29 -18
  426. package/src/components/data-grid/filters/boolean-filter.tsx +6 -6
  427. package/src/components/data-grid/filters/date-filter.spec.tsx +35 -22
  428. package/src/components/data-grid/filters/date-filter.tsx +8 -8
  429. package/src/components/data-grid/filters/enum-filter.spec.tsx +35 -20
  430. package/src/components/data-grid/filters/enum-filter.tsx +7 -7
  431. package/src/components/data-grid/filters/filter-dropdown.tsx +1 -1
  432. package/src/components/data-grid/filters/number-filter.spec.tsx +32 -22
  433. package/src/components/data-grid/filters/number-filter.tsx +7 -7
  434. package/src/components/data-grid/filters/string-filter.spec.tsx +32 -20
  435. package/src/components/data-grid/filters/string-filter.tsx +7 -7
  436. package/src/components/data-grid/footer.spec.tsx +79 -31
  437. package/src/components/data-grid/footer.tsx +10 -15
  438. package/src/components/data-grid/header.spec.tsx +152 -68
  439. package/src/components/data-grid/header.tsx +64 -27
  440. package/src/components/data-grid/selection-cell.tsx +2 -1
  441. package/src/components/dialog.spec.tsx +77 -2
  442. package/src/components/dialog.tsx +15 -2
  443. package/src/components/divider.tsx +1 -1
  444. package/src/components/drawer/drawer-toggle-button.tsx +1 -1
  445. package/src/components/drawer/index.tsx +1 -1
  446. package/src/components/dropdown.spec.tsx +9 -0
  447. package/src/components/dropdown.tsx +2 -1
  448. package/src/components/fab.tsx +1 -1
  449. package/src/components/form.tsx +1 -1
  450. package/src/components/grid.tsx +1 -1
  451. package/src/components/icons/icon.tsx +1 -1
  452. package/src/components/image.spec.tsx +82 -0
  453. package/src/components/image.tsx +18 -9
  454. package/src/components/inputs/autocomplete.tsx +1 -1
  455. package/src/components/inputs/checkbox.spec.tsx +1 -1
  456. package/src/components/inputs/checkbox.tsx +2 -1
  457. package/src/components/inputs/input-number.spec.tsx +1 -1
  458. package/src/components/inputs/input-number.tsx +1 -1
  459. package/src/components/inputs/input.spec.tsx +1 -1
  460. package/src/components/inputs/input.tsx +1 -1
  461. package/src/components/inputs/radio-group.spec.tsx +1 -1
  462. package/src/components/inputs/radio-group.tsx +1 -1
  463. package/src/components/inputs/radio.spec.tsx +1 -1
  464. package/src/components/inputs/radio.tsx +2 -1
  465. package/src/components/inputs/select.tsx +1 -1
  466. package/src/components/inputs/slider.tsx +2 -1
  467. package/src/components/inputs/switch.spec.tsx +1 -1
  468. package/src/components/inputs/switch.tsx +2 -1
  469. package/src/components/inputs/text-area.spec.tsx +1 -1
  470. package/src/components/inputs/text-area.tsx +1 -1
  471. package/src/components/linear-progress.spec.tsx +22 -18
  472. package/src/components/linear-progress.tsx +5 -11
  473. package/src/components/list/list-item.tsx +23 -5
  474. package/src/components/list/list.spec.tsx +165 -32
  475. package/src/components/list/list.tsx +38 -11
  476. package/src/components/loader.spec.tsx +1 -1
  477. package/src/components/loader.tsx +1 -1
  478. package/src/components/markdown/markdown-display.spec.tsx +133 -1
  479. package/src/components/markdown/markdown-display.tsx +13 -2
  480. package/src/components/markdown/markdown-editor.spec.tsx +124 -1
  481. package/src/components/markdown/markdown-editor.tsx +1 -1
  482. package/src/components/markdown/markdown-input.spec.tsx +1 -1
  483. package/src/components/markdown/markdown-input.tsx +1 -1
  484. package/src/components/menu/menu.tsx +2 -2
  485. package/src/components/modal.spec.tsx +127 -4
  486. package/src/components/modal.tsx +42 -4
  487. package/src/components/noty-list.tsx +2 -2
  488. package/src/components/page-container/index.tsx +1 -1
  489. package/src/components/page-container/page-header.tsx +1 -1
  490. package/src/components/page-layout/index.spec.tsx +20 -0
  491. package/src/components/page-layout/index.tsx +2 -2
  492. package/src/components/pagination.tsx +1 -1
  493. package/src/components/paper.tsx +1 -1
  494. package/src/components/rating.spec.tsx +200 -5
  495. package/src/components/rating.tsx +29 -23
  496. package/src/components/result.tsx +1 -1
  497. package/src/components/skeleton.tsx +1 -1
  498. package/src/components/suggest/index.spec.tsx +148 -44
  499. package/src/components/suggest/index.tsx +16 -3
  500. package/src/components/suggest/suggest-input.spec.tsx +1 -1
  501. package/src/components/suggest/suggest-input.tsx +1 -1
  502. package/src/components/suggest/suggestion-list.spec.tsx +1 -1
  503. package/src/components/suggest/suggestion-list.tsx +1 -1
  504. package/src/components/tabs.tsx +6 -2
  505. package/src/components/timeline.tsx +2 -2
  506. package/src/components/tooltip.tsx +1 -1
  507. package/src/components/tree/tree-item.tsx +20 -5
  508. package/src/components/tree/tree.spec.tsx +101 -2
  509. package/src/components/tree/tree.tsx +22 -4
  510. package/src/components/typography.tsx +1 -1
  511. package/src/components/wizard/index.spec.tsx +3 -3
  512. package/src/components/wizard/index.tsx +1 -1
  513. package/src/services/collection-service.spec.ts +33 -24
  514. package/src/services/collection-service.ts +35 -13
  515. package/src/services/css-variable-theme.spec.ts +1 -0
  516. package/src/services/css-variable-theme.ts +25 -0
  517. package/src/services/list-service.spec.ts +13 -42
  518. package/src/services/list-service.ts +15 -13
  519. package/src/services/theme-provider-service.ts +2 -0
  520. package/src/services/tree-service.spec.ts +12 -9
  521. package/src/services/tree-service.ts +5 -8
  522. package/src/themes/architect-theme.ts +1 -0
  523. package/src/themes/auditore-theme.ts +1 -0
  524. package/src/themes/black-mesa-theme.ts +1 -0
  525. package/src/themes/chieftain-theme.ts +1 -0
  526. package/src/themes/default-dark-theme.ts +1 -0
  527. package/src/themes/default-light-theme.ts +1 -0
  528. package/src/themes/dragonborn-theme.ts +1 -0
  529. package/src/themes/hawkins-theme.ts +1 -0
  530. package/src/themes/jedi-theme.ts +1 -0
  531. package/src/themes/neon-runner-theme.ts +1 -0
  532. package/src/themes/paladin-theme.ts +1 -0
  533. package/src/themes/plumber-theme.ts +1 -0
  534. package/src/themes/replicant-theme.ts +1 -0
  535. package/src/themes/sandworm-theme.ts +1 -0
  536. package/src/themes/shadow-broker-theme.ts +1 -0
  537. package/src/themes/sith-theme.ts +1 -0
  538. package/src/themes/vault-dweller-theme.ts +1 -0
  539. package/src/themes/wild-hunt-theme.ts +1 -0
  540. package/src/themes/xenomorph-theme.ts +1 -0
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
- import { ObservableValue, usingAsync } from '@furystack/utils'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
  import type { FilterableFindOptions } from '../data-grid.js'
6
6
  import { EnumFilter } from './enum-filter.js'
@@ -20,25 +20,34 @@ describe('EnumFilter', () => {
20
20
  document.body.innerHTML = ''
21
21
  })
22
22
 
23
- const createFindOptions = (options: Partial<FilterableFindOptions> = {}): ObservableValue<FilterableFindOptions> => {
24
- return new ObservableValue<FilterableFindOptions>(options)
23
+ const createFindOptions = (options: Partial<FilterableFindOptions> = {}): FilterableFindOptions => {
24
+ return options as FilterableFindOptions
25
25
  }
26
26
 
27
27
  const renderEnumFilter = async (
28
- findOptions: ObservableValue<FilterableFindOptions>,
28
+ findOptions: FilterableFindOptions,
29
29
  field = 'role',
30
30
  values = enumValues,
31
31
  onClose = vi.fn(),
32
+ onFindOptionsChange = vi.fn(),
32
33
  ) => {
33
34
  const injector = new Injector()
34
35
  const rootElement = document.getElementById('root')!
35
36
  initializeShadeRoot({
36
37
  injector,
37
38
  rootElement,
38
- jsxElement: <EnumFilter field={field} values={values} findOptions={findOptions} onClose={onClose} />,
39
+ jsxElement: (
40
+ <EnumFilter
41
+ field={field}
42
+ values={values}
43
+ findOptions={findOptions}
44
+ onFindOptionsChange={onFindOptionsChange}
45
+ onClose={onClose}
46
+ />
47
+ ),
39
48
  })
40
49
  await flushUpdates()
41
- return { injector, onClose }
50
+ return { injector, onClose, onFindOptionsChange }
42
51
  }
43
52
 
44
53
  it('should render mode control and checkboxes for each value', async () => {
@@ -54,7 +63,7 @@ describe('EnumFilter', () => {
54
63
 
55
64
  it('should apply $in filter when values are selected and Apply is clicked', async () => {
56
65
  const findOptions = createFindOptions()
57
- const { injector, onClose } = await renderEnumFilter(findOptions)
66
+ const { injector, onClose, onFindOptionsChange } = await renderEnumFilter(findOptions)
58
67
  await usingAsync(injector, async () => {
59
68
  const checkboxes = document.querySelectorAll('shade-checkbox input[type="checkbox"]')
60
69
  const adminCheckbox = checkboxes[0] as HTMLInputElement
@@ -65,14 +74,16 @@ describe('EnumFilter', () => {
65
74
  applyButton?.click()
66
75
  await flushUpdates()
67
76
 
68
- expect(findOptions.getValue().filter).toEqual({ role: { $in: ['admin'] } })
77
+ expect(onFindOptionsChange).toHaveBeenCalledWith(
78
+ expect.objectContaining({ filter: { role: { $in: ['admin'] } } }),
79
+ )
69
80
  expect(onClose).toHaveBeenCalled()
70
81
  })
71
82
  })
72
83
 
73
84
  it('should apply $nin filter when exclude mode is selected', async () => {
74
85
  const findOptions = createFindOptions()
75
- const { injector, onClose } = await renderEnumFilter(findOptions)
86
+ const { injector, onClose, onFindOptionsChange } = await renderEnumFilter(findOptions)
76
87
  await usingAsync(injector, async () => {
77
88
  const excludeButton = document.querySelector(
78
89
  'shade-segmented-control button[data-value="exclude"]',
@@ -89,14 +100,16 @@ describe('EnumFilter', () => {
89
100
  applyButton?.click()
90
101
  await flushUpdates()
91
102
 
92
- expect(findOptions.getValue().filter).toEqual({ role: { $nin: ['guest'] } })
103
+ expect(onFindOptionsChange).toHaveBeenCalledWith(
104
+ expect.objectContaining({ filter: { role: { $nin: ['guest'] } } }),
105
+ )
93
106
  expect(onClose).toHaveBeenCalled()
94
107
  })
95
108
  })
96
109
 
97
110
  it('should remove filter when no values are selected', async () => {
98
111
  const findOptions = createFindOptions({ filter: { role: { $in: ['admin'] } } })
99
- const { injector, onClose } = await renderEnumFilter(findOptions)
112
+ const { injector, onClose, onFindOptionsChange } = await renderEnumFilter(findOptions)
100
113
  await usingAsync(injector, async () => {
101
114
  const checkboxes = document.querySelectorAll('shade-checkbox input[type="checkbox"]')
102
115
  const adminCheckbox = checkboxes[0] as HTMLInputElement
@@ -107,41 +120,43 @@ describe('EnumFilter', () => {
107
120
  applyButton?.click()
108
121
  await flushUpdates()
109
122
 
110
- expect(findOptions.getValue().filter?.role).toBeUndefined()
123
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
124
+ expect(updatedOptions.filter?.role).toBeUndefined()
111
125
  expect(onClose).toHaveBeenCalled()
112
126
  })
113
127
  })
114
128
 
115
129
  it('should clear filter when Clear button is clicked', async () => {
116
130
  const findOptions = createFindOptions({ filter: { role: { $in: ['admin', 'user'] } } })
117
- const { injector, onClose } = await renderEnumFilter(findOptions)
131
+ const { injector, onClose, onFindOptionsChange } = await renderEnumFilter(findOptions)
118
132
  await usingAsync(injector, async () => {
119
133
  const clearButton = Array.from(document.querySelectorAll('button')).find((b) => b.textContent?.trim() === 'Clear')
120
134
  clearButton?.click()
121
135
  await flushUpdates()
122
136
 
123
- expect(findOptions.getValue().filter?.role).toBeUndefined()
137
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
138
+ expect(updatedOptions.filter?.role).toBeUndefined()
124
139
  expect(onClose).toHaveBeenCalled()
125
140
  })
126
141
  })
127
142
 
128
143
  it('should preserve filters on other fields', async () => {
129
144
  const findOptions = createFindOptions({ filter: { role: { $in: ['admin'] }, name: { $regex: 'keep' } } })
130
- const { injector } = await renderEnumFilter(findOptions)
145
+ const { injector, onFindOptionsChange } = await renderEnumFilter(findOptions)
131
146
  await usingAsync(injector, async () => {
132
147
  const clearButton = Array.from(document.querySelectorAll('button')).find((b) => b.textContent?.trim() === 'Clear')
133
148
  clearButton?.click()
134
149
  await flushUpdates()
135
150
 
136
- const updatedFilter = findOptions.getValue().filter
137
- expect(updatedFilter?.role).toBeUndefined()
138
- expect(updatedFilter?.name).toEqual({ $regex: 'keep' })
151
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
152
+ expect(updatedOptions.filter?.role).toBeUndefined()
153
+ expect(updatedOptions.filter?.name).toEqual({ $regex: 'keep' })
139
154
  })
140
155
  })
141
156
 
142
157
  it('should reset skip to 0 when applying filter', async () => {
143
158
  const findOptions = createFindOptions({ skip: 20 })
144
- const { injector } = await renderEnumFilter(findOptions)
159
+ const { injector, onFindOptionsChange } = await renderEnumFilter(findOptions)
145
160
  await usingAsync(injector, async () => {
146
161
  const checkboxes = document.querySelectorAll('shade-checkbox input[type="checkbox"]')
147
162
  const checkbox = checkboxes[0] as HTMLInputElement
@@ -152,7 +167,7 @@ describe('EnumFilter', () => {
152
167
  applyButton?.click()
153
168
  await flushUpdates()
154
169
 
155
- expect(findOptions.getValue().skip).toBe(0)
170
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ skip: 0 }))
156
171
  })
157
172
  })
158
173
 
@@ -1,5 +1,4 @@
1
1
  import { createComponent, Shade } from '@furystack/shades'
2
- import type { ObservableValue } from '@furystack/utils'
3
2
  import { SegmentedControl } from '../../button-group.js'
4
3
  import { Button } from '../../button.js'
5
4
  import { close as closeIcon, search as searchIcon } from '../../icons/icon-definitions.js'
@@ -14,10 +13,11 @@ type EnumMode = 'include' | 'exclude'
14
13
  export const EnumFilter = Shade<{
15
14
  field: string
16
15
  values: Array<{ label: string; value: string }>
17
- findOptions: ObservableValue<FilterableFindOptions>
16
+ findOptions: FilterableFindOptions
17
+ onFindOptionsChange: (options: FilterableFindOptions) => void
18
18
  onClose: () => void
19
19
  }>({
20
- shadowDomName: 'data-grid-enum-filter',
20
+ customElementName: 'data-grid-enum-filter',
21
21
  css: {
22
22
  ...filterBaseCss,
23
23
  fontFamily: cssVariableTheme.typography.fontFamily,
@@ -36,8 +36,8 @@ export const EnumFilter = Shade<{
36
36
  marginBottom: '0',
37
37
  },
38
38
  },
39
- render: ({ props, useObservable, useState }) => {
40
- const [findOptions, setFindOptions] = useObservable('findOptions', props.findOptions)
39
+ render: ({ props, useState }) => {
40
+ const { findOptions } = props
41
41
 
42
42
  const currentFilter = findOptions.filter?.[props.field] as { $in?: string[]; $nin?: string[] } | undefined
43
43
  const isExcludeMode = !!currentFilter?.$nin
@@ -54,14 +54,14 @@ export const EnumFilter = Shade<{
54
54
  const operator = mode === 'include' ? '$in' : '$nin'
55
55
  filter[props.field] = { [operator]: Array.from(selected) }
56
56
  }
57
- setFindOptions({ ...findOptions, filter, skip: 0 })
57
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
58
58
  props.onClose()
59
59
  }
60
60
 
61
61
  const clearFilter = () => {
62
62
  const filter = { ...findOptions.filter }
63
63
  delete filter[props.field]
64
- setFindOptions({ ...findOptions, filter, skip: 0 })
64
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
65
65
  props.onClose()
66
66
  }
67
67
 
@@ -8,7 +8,7 @@ export type FilterDropdownProps = {
8
8
  }
9
9
 
10
10
  export const FilterDropdown: (props: FilterDropdownProps, children: ChildrenList) => JSX.Element = Shade({
11
- shadowDomName: 'data-grid-filter-dropdown',
11
+ customElementName: 'data-grid-filter-dropdown',
12
12
  css: {
13
13
  fontFamily: cssVariableTheme.typography.fontFamily,
14
14
  display: 'block',
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
- import { ObservableValue, usingAsync } from '@furystack/utils'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
  import type { FilterableFindOptions } from '../data-grid.js'
6
6
  import { NumberFilter } from './number-filter.js'
@@ -14,24 +14,32 @@ describe('NumberFilter', () => {
14
14
  document.body.innerHTML = ''
15
15
  })
16
16
 
17
- const createFindOptions = (options: Partial<FilterableFindOptions> = {}): ObservableValue<FilterableFindOptions> => {
18
- return new ObservableValue<FilterableFindOptions>(options)
17
+ const createFindOptions = (options: Partial<FilterableFindOptions> = {}): FilterableFindOptions => {
18
+ return options as FilterableFindOptions
19
19
  }
20
20
 
21
21
  const renderNumberFilter = async (
22
- findOptions: ObservableValue<FilterableFindOptions>,
22
+ findOptions: FilterableFindOptions,
23
23
  field = 'level',
24
24
  onClose = vi.fn(),
25
+ onFindOptionsChange = vi.fn(),
25
26
  ) => {
26
27
  const injector = new Injector()
27
28
  const rootElement = document.getElementById('root')!
28
29
  initializeShadeRoot({
29
30
  injector,
30
31
  rootElement,
31
- jsxElement: <NumberFilter field={field} findOptions={findOptions} onClose={onClose} />,
32
+ jsxElement: (
33
+ <NumberFilter
34
+ field={field}
35
+ findOptions={findOptions}
36
+ onFindOptionsChange={onFindOptionsChange}
37
+ onClose={onClose}
38
+ />
39
+ ),
32
40
  })
33
41
  await flushUpdates()
34
- return { injector, onClose }
42
+ return { injector, onClose, onFindOptionsChange }
35
43
  }
36
44
 
37
45
  it('should render operator segmented control and input', async () => {
@@ -47,7 +55,7 @@ describe('NumberFilter', () => {
47
55
 
48
56
  it('should apply $eq filter on submit', async () => {
49
57
  const findOptions = createFindOptions()
50
- const { injector, onClose } = await renderNumberFilter(findOptions)
58
+ const { injector, onClose, onFindOptionsChange } = await renderNumberFilter(findOptions)
51
59
  await usingAsync(injector, async () => {
52
60
  const input = document.querySelector('[data-testid="number-filter-value"]') as HTMLInputElement
53
61
  input.value = '42'
@@ -57,14 +65,14 @@ describe('NumberFilter', () => {
57
65
  form.dispatchEvent(new Event('submit', { bubbles: true }))
58
66
  await flushUpdates()
59
67
 
60
- expect(findOptions.getValue().filter).toEqual({ level: { $eq: 42 } })
68
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ filter: { level: { $eq: 42 } } }))
61
69
  expect(onClose).toHaveBeenCalled()
62
70
  })
63
71
  })
64
72
 
65
73
  it('should apply $gt operator when selected', async () => {
66
74
  const findOptions = createFindOptions()
67
- const { injector, onClose } = await renderNumberFilter(findOptions)
75
+ const { injector, onClose, onFindOptionsChange } = await renderNumberFilter(findOptions)
68
76
  await usingAsync(injector, async () => {
69
77
  const gtButton = document.querySelector('shade-segmented-control button[data-value="$gt"]') as HTMLButtonElement
70
78
  gtButton?.click()
@@ -78,14 +86,14 @@ describe('NumberFilter', () => {
78
86
  form.dispatchEvent(new Event('submit', { bubbles: true }))
79
87
  await flushUpdates()
80
88
 
81
- expect(findOptions.getValue().filter).toEqual({ level: { $gt: 10 } })
89
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ filter: { level: { $gt: 10 } } }))
82
90
  expect(onClose).toHaveBeenCalled()
83
91
  })
84
92
  })
85
93
 
86
94
  it('should apply $lte operator when selected', async () => {
87
95
  const findOptions = createFindOptions()
88
- const { injector, onClose } = await renderNumberFilter(findOptions)
96
+ const { injector, onClose, onFindOptionsChange } = await renderNumberFilter(findOptions)
89
97
  await usingAsync(injector, async () => {
90
98
  const lteButton = document.querySelector('shade-segmented-control button[data-value="$lte"]') as HTMLButtonElement
91
99
  lteButton?.click()
@@ -99,27 +107,28 @@ describe('NumberFilter', () => {
99
107
  form.dispatchEvent(new Event('submit', { bubbles: true }))
100
108
  await flushUpdates()
101
109
 
102
- expect(findOptions.getValue().filter).toEqual({ level: { $lte: 99.5 } })
110
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ filter: { level: { $lte: 99.5 } } }))
103
111
  expect(onClose).toHaveBeenCalled()
104
112
  })
105
113
  })
106
114
 
107
115
  it('should clear filter when Clear button is clicked', async () => {
108
116
  const findOptions = createFindOptions({ filter: { level: { $eq: 5 } } })
109
- const { injector, onClose } = await renderNumberFilter(findOptions)
117
+ const { injector, onClose, onFindOptionsChange } = await renderNumberFilter(findOptions)
110
118
  await usingAsync(injector, async () => {
111
119
  const clearButton = Array.from(document.querySelectorAll('button')).find((b) => b.textContent?.trim() === 'Clear')
112
120
  clearButton?.click()
113
121
  await flushUpdates()
114
122
 
115
- expect(findOptions.getValue().filter?.level).toBeUndefined()
123
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
124
+ expect(updatedOptions.filter?.level).toBeUndefined()
116
125
  expect(onClose).toHaveBeenCalled()
117
126
  })
118
127
  })
119
128
 
120
129
  it('should remove filter when submitting NaN value', async () => {
121
130
  const findOptions = createFindOptions({ filter: { level: { $eq: 5 } } })
122
- const { injector, onClose } = await renderNumberFilter(findOptions)
131
+ const { injector, onClose, onFindOptionsChange } = await renderNumberFilter(findOptions)
123
132
  await usingAsync(injector, async () => {
124
133
  const input = document.querySelector('[data-testid="number-filter-value"]') as HTMLInputElement
125
134
  input.value = ''
@@ -129,28 +138,29 @@ describe('NumberFilter', () => {
129
138
  form.dispatchEvent(new Event('submit', { bubbles: true }))
130
139
  await flushUpdates()
131
140
 
132
- expect(findOptions.getValue().filter?.level).toBeUndefined()
141
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
142
+ expect(updatedOptions.filter?.level).toBeUndefined()
133
143
  expect(onClose).toHaveBeenCalled()
134
144
  })
135
145
  })
136
146
 
137
147
  it('should preserve filters on other fields', async () => {
138
148
  const findOptions = createFindOptions({ filter: { level: { $gt: 10 }, name: { $regex: 'keep' } } })
139
- const { injector } = await renderNumberFilter(findOptions)
149
+ const { injector, onFindOptionsChange } = await renderNumberFilter(findOptions)
140
150
  await usingAsync(injector, async () => {
141
151
  const clearButton = Array.from(document.querySelectorAll('button')).find((b) => b.textContent?.trim() === 'Clear')
142
152
  clearButton?.click()
143
153
  await flushUpdates()
144
154
 
145
- const updatedFilter = findOptions.getValue().filter
146
- expect(updatedFilter?.level).toBeUndefined()
147
- expect(updatedFilter?.name).toEqual({ $regex: 'keep' })
155
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
156
+ expect(updatedOptions.filter?.level).toBeUndefined()
157
+ expect(updatedOptions.filter?.name).toEqual({ $regex: 'keep' })
148
158
  })
149
159
  })
150
160
 
151
161
  it('should reset skip to 0 when applying filter', async () => {
152
162
  const findOptions = createFindOptions({ skip: 20 })
153
- const { injector } = await renderNumberFilter(findOptions)
163
+ const { injector, onFindOptionsChange } = await renderNumberFilter(findOptions)
154
164
  await usingAsync(injector, async () => {
155
165
  const input = document.querySelector('[data-testid="number-filter-value"]') as HTMLInputElement
156
166
  input.value = '5'
@@ -160,7 +170,7 @@ describe('NumberFilter', () => {
160
170
  form.dispatchEvent(new Event('submit', { bubbles: true }))
161
171
  await flushUpdates()
162
172
 
163
- expect(findOptions.getValue().skip).toBe(0)
173
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ skip: 0 }))
164
174
  })
165
175
  })
166
176
 
@@ -1,5 +1,4 @@
1
1
  import { createComponent, Shade } from '@furystack/shades'
2
- import type { ObservableValue } from '@furystack/utils'
3
2
  import { Button } from '../../button.js'
4
3
  import { SegmentedControl } from '../../button-group.js'
5
4
  import { Icon } from '../../icons/icon.js'
@@ -20,17 +19,18 @@ const operatorLabels: Record<NumberOperator, string> = {
20
19
 
21
20
  export const NumberFilter = Shade<{
22
21
  field: string
23
- findOptions: ObservableValue<FilterableFindOptions>
22
+ findOptions: FilterableFindOptions
23
+ onFindOptionsChange: (options: FilterableFindOptions) => void
24
24
  onClose: () => void
25
25
  }>({
26
- shadowDomName: 'data-grid-number-filter',
26
+ customElementName: 'data-grid-number-filter',
27
27
  css: {
28
28
  ...filterBaseCss,
29
29
  fontFamily: cssVariableTheme.typography.fontFamily,
30
30
  '& input': filterInputCss,
31
31
  },
32
- render: ({ props, useObservable, useState }) => {
33
- const [findOptions, setFindOptions] = useObservable('findOptions', props.findOptions)
32
+ render: ({ props, useState }) => {
33
+ const { findOptions } = props
34
34
 
35
35
  const currentFilter = findOptions.filter?.[props.field] as Record<string, number> | undefined
36
36
  const currentOperator: NumberOperator = currentFilter
@@ -46,14 +46,14 @@ export const NumberFilter = Shade<{
46
46
  } else {
47
47
  filter[props.field] = { [operator]: num }
48
48
  }
49
- setFindOptions({ ...findOptions, filter, skip: 0 })
49
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
50
50
  props.onClose()
51
51
  }
52
52
 
53
53
  const clearFilter = () => {
54
54
  const filter = { ...findOptions.filter }
55
55
  delete filter[props.field]
56
- setFindOptions({ ...findOptions, filter, skip: 0 })
56
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
57
57
  props.onClose()
58
58
  }
59
59
 
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
- import { ObservableValue, usingAsync } from '@furystack/utils'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
  import type { FilterableFindOptions } from '../data-grid.js'
6
6
  import { StringFilter } from './string-filter.js'
@@ -14,24 +14,32 @@ describe('StringFilter', () => {
14
14
  document.body.innerHTML = ''
15
15
  })
16
16
 
17
- const createFindOptions = (options: Partial<FilterableFindOptions> = {}): ObservableValue<FilterableFindOptions> => {
18
- return new ObservableValue<FilterableFindOptions>(options)
17
+ const createFindOptions = (options: Partial<FilterableFindOptions> = {}): FilterableFindOptions => {
18
+ return options as FilterableFindOptions
19
19
  }
20
20
 
21
21
  const renderStringFilter = async (
22
- findOptions: ObservableValue<FilterableFindOptions>,
22
+ findOptions: FilterableFindOptions,
23
23
  field = 'name',
24
24
  onClose = vi.fn(),
25
+ onFindOptionsChange = vi.fn(),
25
26
  ) => {
26
27
  const injector = new Injector()
27
28
  const rootElement = document.getElementById('root')!
28
29
  initializeShadeRoot({
29
30
  injector,
30
31
  rootElement,
31
- jsxElement: <StringFilter field={field} findOptions={findOptions} onClose={onClose} />,
32
+ jsxElement: (
33
+ <StringFilter
34
+ field={field}
35
+ findOptions={findOptions}
36
+ onFindOptionsChange={onFindOptionsChange}
37
+ onClose={onClose}
38
+ />
39
+ ),
32
40
  })
33
41
  await flushUpdates()
34
- return { injector, onClose }
42
+ return { injector, onClose, onFindOptionsChange }
35
43
  }
36
44
 
37
45
  it('should render operator segmented control and input', async () => {
@@ -47,7 +55,7 @@ describe('StringFilter', () => {
47
55
 
48
56
  it('should apply $regex filter on submit', async () => {
49
57
  const findOptions = createFindOptions()
50
- const { injector, onClose } = await renderStringFilter(findOptions)
58
+ const { injector, onClose, onFindOptionsChange } = await renderStringFilter(findOptions)
51
59
  await usingAsync(injector, async () => {
52
60
  const input = document.querySelector('[data-testid="string-filter-value"]') as HTMLInputElement
53
61
  input.value = 'test-value'
@@ -57,27 +65,30 @@ describe('StringFilter', () => {
57
65
  form.dispatchEvent(new Event('submit', { bubbles: true }))
58
66
  await flushUpdates()
59
67
 
60
- expect(findOptions.getValue().filter).toEqual({ name: { $regex: 'test-value' } })
68
+ expect(onFindOptionsChange).toHaveBeenCalledWith(
69
+ expect.objectContaining({ filter: { name: { $regex: 'test-value' } } }),
70
+ )
61
71
  expect(onClose).toHaveBeenCalled()
62
72
  })
63
73
  })
64
74
 
65
75
  it('should clear filter when Clear button is clicked', async () => {
66
76
  const findOptions = createFindOptions({ filter: { name: { $regex: 'existing' } } })
67
- const { injector, onClose } = await renderStringFilter(findOptions)
77
+ const { injector, onClose, onFindOptionsChange } = await renderStringFilter(findOptions)
68
78
  await usingAsync(injector, async () => {
69
79
  const clearButton = Array.from(document.querySelectorAll('button')).find((b) => b.textContent?.trim() === 'Clear')
70
80
  clearButton?.click()
71
81
  await flushUpdates()
72
82
 
73
- expect(findOptions.getValue().filter?.name).toBeUndefined()
83
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
84
+ expect(updatedOptions.filter?.name).toBeUndefined()
74
85
  expect(onClose).toHaveBeenCalled()
75
86
  })
76
87
  })
77
88
 
78
89
  it('should remove filter when submitting empty value', async () => {
79
90
  const findOptions = createFindOptions({ filter: { name: { $regex: 'existing' } } })
80
- const { injector, onClose } = await renderStringFilter(findOptions)
91
+ const { injector, onClose, onFindOptionsChange } = await renderStringFilter(findOptions)
81
92
  await usingAsync(injector, async () => {
82
93
  const input = document.querySelector('[data-testid="string-filter-value"]') as HTMLInputElement
83
94
  input.value = ''
@@ -87,14 +98,15 @@ describe('StringFilter', () => {
87
98
  form.dispatchEvent(new Event('submit', { bubbles: true }))
88
99
  await flushUpdates()
89
100
 
90
- expect(findOptions.getValue().filter?.name).toBeUndefined()
101
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
102
+ expect(updatedOptions.filter?.name).toBeUndefined()
91
103
  expect(onClose).toHaveBeenCalled()
92
104
  })
93
105
  })
94
106
 
95
107
  it('should preserve filters on other fields', async () => {
96
108
  const findOptions = createFindOptions({ filter: { name: { $regex: 'old' }, email: { $regex: 'keep' } } })
97
- const { injector } = await renderStringFilter(findOptions)
109
+ const { injector, onFindOptionsChange } = await renderStringFilter(findOptions)
98
110
  await usingAsync(injector, async () => {
99
111
  const input = document.querySelector('[data-testid="string-filter-value"]') as HTMLInputElement
100
112
  input.value = 'new-value'
@@ -104,15 +116,15 @@ describe('StringFilter', () => {
104
116
  form.dispatchEvent(new Event('submit', { bubbles: true }))
105
117
  await flushUpdates()
106
118
 
107
- const updatedFilter = findOptions.getValue().filter
108
- expect(updatedFilter?.name).toEqual({ $regex: 'new-value' })
109
- expect(updatedFilter?.email).toEqual({ $regex: 'keep' })
119
+ const updatedOptions = onFindOptionsChange.mock.lastCall?.[0] as FilterableFindOptions
120
+ expect(updatedOptions.filter?.name).toEqual({ $regex: 'new-value' })
121
+ expect(updatedOptions.filter?.email).toEqual({ $regex: 'keep' })
110
122
  })
111
123
  })
112
124
 
113
125
  it('should apply selected operator', async () => {
114
126
  const findOptions = createFindOptions()
115
- const { injector, onClose } = await renderStringFilter(findOptions)
127
+ const { injector, onClose, onFindOptionsChange } = await renderStringFilter(findOptions)
116
128
  await usingAsync(injector, async () => {
117
129
  const eqButton = document.querySelector('shade-segmented-control button[data-value="$eq"]') as HTMLButtonElement
118
130
  eqButton?.click()
@@ -126,14 +138,14 @@ describe('StringFilter', () => {
126
138
  form.dispatchEvent(new Event('submit', { bubbles: true }))
127
139
  await flushUpdates()
128
140
 
129
- expect(findOptions.getValue().filter).toEqual({ name: { $eq: 'exact' } })
141
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ filter: { name: { $eq: 'exact' } } }))
130
142
  expect(onClose).toHaveBeenCalled()
131
143
  })
132
144
  })
133
145
 
134
146
  it('should reset skip to 0 when applying filter', async () => {
135
147
  const findOptions = createFindOptions({ skip: 20 })
136
- const { injector } = await renderStringFilter(findOptions)
148
+ const { injector, onFindOptionsChange } = await renderStringFilter(findOptions)
137
149
  await usingAsync(injector, async () => {
138
150
  const input = document.querySelector('[data-testid="string-filter-value"]') as HTMLInputElement
139
151
  input.value = 'test'
@@ -143,7 +155,7 @@ describe('StringFilter', () => {
143
155
  form.dispatchEvent(new Event('submit', { bubbles: true }))
144
156
  await flushUpdates()
145
157
 
146
- expect(findOptions.getValue().skip).toBe(0)
158
+ expect(onFindOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ skip: 0 }))
147
159
  })
148
160
  })
149
161
 
@@ -1,5 +1,4 @@
1
1
  import { createComponent, Shade } from '@furystack/shades'
2
- import type { ObservableValue } from '@furystack/utils'
3
2
  import { Button } from '../../button.js'
4
3
  import { SegmentedControl } from '../../button-group.js'
5
4
  import { Icon } from '../../icons/icon.js'
@@ -19,17 +18,18 @@ const operatorLabels: Record<StringOperator, string> = {
19
18
 
20
19
  export const StringFilter = Shade<{
21
20
  field: string
22
- findOptions: ObservableValue<FilterableFindOptions>
21
+ findOptions: FilterableFindOptions
22
+ onFindOptionsChange: (options: FilterableFindOptions) => void
23
23
  onClose: () => void
24
24
  }>({
25
- shadowDomName: 'data-grid-string-filter',
25
+ customElementName: 'data-grid-string-filter',
26
26
  css: {
27
27
  ...filterBaseCss,
28
28
  fontFamily: cssVariableTheme.typography.fontFamily,
29
29
  '& input': filterInputCss,
30
30
  },
31
- render: ({ props, useObservable, useState }) => {
32
- const [findOptions, setFindOptions] = useObservable('findOptions', props.findOptions)
31
+ render: ({ props, useState }) => {
32
+ const { findOptions } = props
33
33
 
34
34
  const currentFilter = findOptions.filter?.[props.field] as Record<string, string> | undefined
35
35
  const currentOperator: StringOperator = currentFilter
@@ -44,14 +44,14 @@ export const StringFilter = Shade<{
44
44
  } else {
45
45
  filter[props.field] = { [operator]: value }
46
46
  }
47
- setFindOptions({ ...findOptions, filter, skip: 0 })
47
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
48
48
  props.onClose()
49
49
  }
50
50
 
51
51
  const clearFilter = () => {
52
52
  const filter = { ...findOptions.filter }
53
53
  delete filter[props.field]
54
- setFindOptions({ ...findOptions, filter, skip: 0 })
54
+ props.onFindOptionsChange({ ...findOptions, filter, skip: 0 })
55
55
  props.onClose()
56
56
  }
57
57