@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 { CollectionService } from '../../services/collection-service.js';
6
6
  import { DataGrid } from './data-grid.js';
@@ -26,20 +26,20 @@ describe('DataGrid', () => {
26
26
  const withTestGrid = async (fn, opts) => {
27
27
  await usingAsync(new Injector(), async (injector) => {
28
28
  await usingAsync(opts?.createService?.() ?? createTestService(), async (service) => {
29
- await usingAsync(new ObservableValue({}), async (findOptions) => {
30
- await fn({ injector, service, findOptions });
31
- });
29
+ const findOptions = {};
30
+ const onFindOptionsChange = vi.fn();
31
+ await fn({ injector, service, findOptions, onFindOptionsChange });
32
32
  });
33
33
  });
34
34
  };
35
35
  describe('rendering', () => {
36
36
  it('should render with columns', async () => {
37
- await withTestGrid(async ({ injector, service, findOptions }) => {
37
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
38
38
  const rootElement = document.getElementById('root');
39
39
  initializeShadeRoot({
40
40
  injector,
41
41
  rootElement,
42
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
42
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
43
43
  });
44
44
  await flushUpdates();
45
45
  const grid = document.querySelector('shade-data-grid');
@@ -49,12 +49,12 @@ describe('DataGrid', () => {
49
49
  });
50
50
  });
51
51
  it('should render table structure', async () => {
52
- await withTestGrid(async ({ injector, service, findOptions }) => {
52
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
53
53
  const rootElement = document.getElementById('root');
54
54
  initializeShadeRoot({
55
55
  injector,
56
56
  rootElement,
57
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
57
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
58
58
  });
59
59
  await flushUpdates();
60
60
  const grid = document.querySelector('shade-data-grid');
@@ -67,12 +67,12 @@ describe('DataGrid', () => {
67
67
  });
68
68
  });
69
69
  it('should render custom header components when provided', async () => {
70
- await withTestGrid(async ({ injector, service, findOptions }) => {
70
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
71
71
  const rootElement = document.getElementById('root');
72
72
  initializeShadeRoot({
73
73
  injector,
74
74
  rootElement,
75
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {
75
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {
76
76
  id: () => createComponent("span", { "data-testid": "custom-header-id" }, "Custom ID Header"),
77
77
  }, rowComponents: {} })),
78
78
  });
@@ -84,12 +84,12 @@ describe('DataGrid', () => {
84
84
  });
85
85
  });
86
86
  it('should render default header components from headerComponents.default', async () => {
87
- await withTestGrid(async ({ injector, service, findOptions }) => {
87
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
88
88
  const rootElement = document.getElementById('root');
89
89
  initializeShadeRoot({
90
90
  injector,
91
91
  rootElement,
92
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {
92
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {
93
93
  default: (name) => createComponent("span", { "data-testid": `default-header-${name}` },
94
94
  "Default: ",
95
95
  name),
@@ -104,12 +104,12 @@ describe('DataGrid', () => {
104
104
  });
105
105
  });
106
106
  it('should render DataGridHeader when no custom header is provided', async () => {
107
- await withTestGrid(async ({ injector, service, findOptions }) => {
107
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
108
108
  const rootElement = document.getElementById('root');
109
109
  initializeShadeRoot({
110
110
  injector,
111
111
  rootElement,
112
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
112
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
113
113
  });
114
114
  await flushUpdates();
115
115
  const grid = document.querySelector('shade-data-grid');
@@ -118,12 +118,12 @@ describe('DataGrid', () => {
118
118
  });
119
119
  });
120
120
  it('should render filter buttons when columnFilters are provided', async () => {
121
- await withTestGrid(async ({ injector, service, findOptions }) => {
121
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
122
122
  const rootElement = document.getElementById('root');
123
123
  initializeShadeRoot({
124
124
  injector,
125
125
  rootElement,
126
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, columnFilters: { name: { type: 'string' } } })),
126
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, columnFilters: { name: { type: 'string' } } })),
127
127
  });
128
128
  await flushUpdates();
129
129
  const grid = document.querySelector('shade-data-grid');
@@ -132,12 +132,12 @@ describe('DataGrid', () => {
132
132
  });
133
133
  });
134
134
  it('should not render filter buttons when columnFilters is not provided', async () => {
135
- await withTestGrid(async ({ injector, service, findOptions }) => {
135
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
136
136
  const rootElement = document.getElementById('root');
137
137
  initializeShadeRoot({
138
138
  injector,
139
139
  rootElement,
140
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {} })),
140
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {} })),
141
141
  });
142
142
  await flushUpdates();
143
143
  const grid = document.querySelector('shade-data-grid');
@@ -146,12 +146,12 @@ describe('DataGrid', () => {
146
146
  });
147
147
  });
148
148
  it('should render without headerComponents and rowComponents', async () => {
149
- await withTestGrid(async ({ injector, service, findOptions }) => {
149
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
150
150
  const rootElement = document.getElementById('root');
151
151
  initializeShadeRoot({
152
152
  injector,
153
153
  rootElement,
154
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {} })),
154
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {} })),
155
155
  });
156
156
  await flushUpdates();
157
157
  const grid = document.querySelector('shade-data-grid');
@@ -160,55 +160,102 @@ describe('DataGrid', () => {
160
160
  expect(headers?.length).toBe(2);
161
161
  });
162
162
  });
163
+ it('should render with auto-generated data-nav-section attribute', async () => {
164
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
165
+ const rootElement = document.getElementById('root');
166
+ initializeShadeRoot({
167
+ injector,
168
+ rootElement,
169
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
170
+ });
171
+ await flushUpdates();
172
+ const wrapper = document.querySelector('.shade-grid-wrapper');
173
+ const navSection = wrapper?.getAttribute('data-nav-section');
174
+ expect(navSection).toBeTruthy();
175
+ expect(navSection).toMatch(/^data-grid-/);
176
+ });
177
+ });
178
+ it('should render with custom navSection', async () => {
179
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
180
+ const rootElement = document.getElementById('root');
181
+ initializeShadeRoot({
182
+ injector,
183
+ rootElement,
184
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, navSection: "my-grid" })),
185
+ });
186
+ await flushUpdates();
187
+ const wrapper = document.querySelector('.shade-grid-wrapper');
188
+ expect(wrapper?.getAttribute('data-nav-section')).toBe('my-grid');
189
+ });
190
+ });
163
191
  });
164
192
  describe('focus management', () => {
165
- it('should set focus on click', async () => {
166
- await withTestGrid(async ({ injector, service, findOptions }) => {
193
+ it('should clear hasFocus on focusout when focus leaves the grid', async () => {
194
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
167
195
  const rootElement = document.getElementById('root');
196
+ const outsideBtn = document.createElement('button');
197
+ document.body.appendChild(outsideBtn);
198
+ initializeShadeRoot({
199
+ injector,
200
+ rootElement,
201
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
202
+ });
203
+ await flushUpdates();
204
+ await new Promise((r) => setTimeout(r, 0));
205
+ service.hasFocus.setValue(true);
206
+ const wrapper = document.querySelector('.shade-grid-wrapper');
207
+ wrapper?.dispatchEvent(new FocusEvent('focusout', { bubbles: true, relatedTarget: outsideBtn }));
168
208
  expect(service.hasFocus.getValue()).toBe(false);
209
+ outsideBtn.remove();
210
+ });
211
+ });
212
+ it('should clear hasFocus on focusout when focus moves outside', async () => {
213
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
214
+ const rootElement = document.getElementById('root');
215
+ const outsideEl = document.createElement('button');
216
+ outsideEl.textContent = 'Outside';
217
+ document.body.appendChild(outsideEl);
169
218
  initializeShadeRoot({
170
219
  injector,
171
220
  rootElement,
172
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
221
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
173
222
  });
174
223
  await flushUpdates();
175
- const grid = document.querySelector('shade-data-grid');
176
- const wrapper = grid?.querySelector('.shade-grid-wrapper');
177
- wrapper?.click();
178
- expect(service.hasFocus.getValue()).toBe(true);
224
+ await new Promise((r) => setTimeout(r, 0));
225
+ service.hasFocus.setValue(true);
226
+ const wrapper = document.querySelector('.shade-grid-wrapper');
227
+ wrapper?.dispatchEvent(new FocusEvent('focusout', { bubbles: true, relatedTarget: outsideEl }));
228
+ expect(service.hasFocus.getValue()).toBe(false);
229
+ outsideEl.remove();
179
230
  });
180
231
  });
181
- it('should lose focus on click outside', async () => {
182
- await withTestGrid(async ({ injector, service, findOptions }) => {
232
+ it('should clear hasFocus on focusout when relatedTarget is null', async () => {
233
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
183
234
  const rootElement = document.getElementById('root');
184
235
  initializeShadeRoot({
185
236
  injector,
186
237
  rootElement,
187
- jsxElement: (createComponent(createComponent, null,
188
- createComponent("div", { "data-testid": "outside" }, "Outside"),
189
- createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} }))),
238
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
190
239
  });
191
240
  await flushUpdates();
192
- const grid = document.querySelector('shade-data-grid');
193
- const wrapper = grid?.querySelector('.shade-grid-wrapper');
194
- wrapper?.click();
195
- expect(service.hasFocus.getValue()).toBe(true);
196
- const outside = document.querySelector('[data-testid="outside"]');
197
- outside?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
241
+ await new Promise((r) => setTimeout(r, 0));
242
+ service.hasFocus.setValue(true);
243
+ const wrapper = document.querySelector('.shade-grid-wrapper');
244
+ wrapper?.dispatchEvent(new FocusEvent('focusout', { bubbles: true, relatedTarget: null }));
198
245
  expect(service.hasFocus.getValue()).toBe(false);
199
246
  });
200
247
  });
201
248
  });
202
249
  describe('keyboard navigation', () => {
203
- it('should handle ArrowDown to move focus to next entry', async () => {
204
- await withTestGrid(async ({ injector, service, findOptions }) => {
250
+ it('should move focus to next entry on ArrowDown', async () => {
251
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
205
252
  const rootElement = document.getElementById('root');
206
253
  service.hasFocus.setValue(true);
207
254
  service.focusedEntry.setValue(service.data.getValue().entries[0]);
208
255
  initializeShadeRoot({
209
256
  injector,
210
257
  rootElement,
211
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
258
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
212
259
  });
213
260
  await flushUpdates();
214
261
  const keydownEvent = new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true });
@@ -216,15 +263,15 @@ describe('DataGrid', () => {
216
263
  expect(service.focusedEntry.getValue()).toEqual({ id: 2, name: 'Second' });
217
264
  });
218
265
  });
219
- it('should handle ArrowUp to move focus to previous entry', async () => {
220
- await withTestGrid(async ({ injector, service, findOptions }) => {
266
+ it('should move focus to previous entry on ArrowUp', async () => {
267
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
221
268
  const rootElement = document.getElementById('root');
222
269
  service.hasFocus.setValue(true);
223
270
  service.focusedEntry.setValue(service.data.getValue().entries[1]);
224
271
  initializeShadeRoot({
225
272
  injector,
226
273
  rootElement,
227
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
274
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
228
275
  });
229
276
  await flushUpdates();
230
277
  const keydownEvent = new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true });
@@ -233,14 +280,14 @@ describe('DataGrid', () => {
233
280
  });
234
281
  });
235
282
  it('should handle Home to move focus to first entry', async () => {
236
- await withTestGrid(async ({ injector, service, findOptions }) => {
283
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
237
284
  const rootElement = document.getElementById('root');
238
285
  service.hasFocus.setValue(true);
239
286
  service.focusedEntry.setValue(service.data.getValue().entries[2]);
240
287
  initializeShadeRoot({
241
288
  injector,
242
289
  rootElement,
243
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
290
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
244
291
  });
245
292
  await flushUpdates();
246
293
  const keydownEvent = new KeyboardEvent('keydown', { key: 'Home', bubbles: true });
@@ -249,14 +296,14 @@ describe('DataGrid', () => {
249
296
  });
250
297
  });
251
298
  it('should handle End to move focus to last entry', async () => {
252
- await withTestGrid(async ({ injector, service, findOptions }) => {
299
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
253
300
  const rootElement = document.getElementById('root');
254
301
  service.hasFocus.setValue(true);
255
302
  service.focusedEntry.setValue(service.data.getValue().entries[0]);
256
303
  initializeShadeRoot({
257
304
  injector,
258
305
  rootElement,
259
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
306
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
260
307
  });
261
308
  await flushUpdates();
262
309
  const keydownEvent = new KeyboardEvent('keydown', { key: 'End', bubbles: true });
@@ -264,23 +311,8 @@ describe('DataGrid', () => {
264
311
  expect(service.focusedEntry.getValue()).toEqual({ id: 3, name: 'Third' });
265
312
  });
266
313
  });
267
- it('should handle Tab to toggle focus', async () => {
268
- await withTestGrid(async ({ injector, service, findOptions }) => {
269
- const rootElement = document.getElementById('root');
270
- service.hasFocus.setValue(true);
271
- initializeShadeRoot({
272
- injector,
273
- rootElement,
274
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
275
- });
276
- await flushUpdates();
277
- const keydownEvent = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true });
278
- window.dispatchEvent(keydownEvent);
279
- expect(service.hasFocus.getValue()).toBe(false);
280
- });
281
- });
282
314
  it('should handle Escape to clear selection and search', async () => {
283
- await withTestGrid(async ({ injector, service, findOptions }) => {
315
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
284
316
  const rootElement = document.getElementById('root');
285
317
  const { entries } = service.data.getValue();
286
318
  service.hasFocus.setValue(true);
@@ -289,7 +321,7 @@ describe('DataGrid', () => {
289
321
  initializeShadeRoot({
290
322
  injector,
291
323
  rootElement,
292
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
324
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
293
325
  });
294
326
  await flushUpdates();
295
327
  const keydownEvent = new KeyboardEvent('keydown', { key: 'Escape', bubbles: true });
@@ -299,7 +331,7 @@ describe('DataGrid', () => {
299
331
  });
300
332
  });
301
333
  it('should handle Space to toggle selection of focused entry', async () => {
302
- await withTestGrid(async ({ injector, service, findOptions }) => {
334
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
303
335
  const rootElement = document.getElementById('root');
304
336
  const { entries } = service.data.getValue();
305
337
  service.hasFocus.setValue(true);
@@ -307,7 +339,7 @@ describe('DataGrid', () => {
307
339
  initializeShadeRoot({
308
340
  injector,
309
341
  rootElement,
310
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
342
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
311
343
  });
312
344
  await flushUpdates();
313
345
  const keydownEvent = new KeyboardEvent('keydown', { key: ' ', bubbles: true });
@@ -318,13 +350,13 @@ describe('DataGrid', () => {
318
350
  });
319
351
  });
320
352
  it('should handle + to select all entries', async () => {
321
- await withTestGrid(async ({ injector, service, findOptions }) => {
353
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
322
354
  const rootElement = document.getElementById('root');
323
355
  service.hasFocus.setValue(true);
324
356
  initializeShadeRoot({
325
357
  injector,
326
358
  rootElement,
327
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
359
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
328
360
  });
329
361
  await flushUpdates();
330
362
  const keydownEvent = new KeyboardEvent('keydown', { key: '+', bubbles: true });
@@ -333,7 +365,7 @@ describe('DataGrid', () => {
333
365
  });
334
366
  });
335
367
  it('should handle - to deselect all entries', async () => {
336
- await withTestGrid(async ({ injector, service, findOptions }) => {
368
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
337
369
  const rootElement = document.getElementById('root');
338
370
  const { entries } = service.data.getValue();
339
371
  service.hasFocus.setValue(true);
@@ -341,7 +373,7 @@ describe('DataGrid', () => {
341
373
  initializeShadeRoot({
342
374
  injector,
343
375
  rootElement,
344
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
376
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
345
377
  });
346
378
  await flushUpdates();
347
379
  const keydownEvent = new KeyboardEvent('keydown', { key: '-', bubbles: true });
@@ -350,7 +382,7 @@ describe('DataGrid', () => {
350
382
  });
351
383
  });
352
384
  it('should handle * to invert selection', async () => {
353
- await withTestGrid(async ({ injector, service, findOptions }) => {
385
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
354
386
  const rootElement = document.getElementById('root');
355
387
  const { entries } = service.data.getValue();
356
388
  service.hasFocus.setValue(true);
@@ -358,7 +390,7 @@ describe('DataGrid', () => {
358
390
  initializeShadeRoot({
359
391
  injector,
360
392
  rootElement,
361
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
393
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
362
394
  });
363
395
  await flushUpdates();
364
396
  const keydownEvent = new KeyboardEvent('keydown', { key: '*', bubbles: true });
@@ -370,23 +402,23 @@ describe('DataGrid', () => {
370
402
  });
371
403
  });
372
404
  it('should not handle keyboard when not focused', async () => {
373
- await withTestGrid(async ({ injector, service, findOptions }) => {
405
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
374
406
  const rootElement = document.getElementById('root');
375
- service.hasFocus.setValue(false);
376
407
  service.focusedEntry.setValue(service.data.getValue().entries[0]);
377
408
  initializeShadeRoot({
378
409
  injector,
379
410
  rootElement,
380
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
411
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
381
412
  });
382
413
  await flushUpdates();
414
+ service.hasFocus.setValue(false);
383
415
  const keydownEvent = new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true });
384
416
  window.dispatchEvent(keydownEvent);
385
417
  expect(service.focusedEntry.getValue()).toEqual({ id: 1, name: 'First' });
386
418
  });
387
419
  });
388
420
  it('should handle Insert to toggle selection and move to next', async () => {
389
- await withTestGrid(async ({ injector, service, findOptions }) => {
421
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
390
422
  const rootElement = document.getElementById('root');
391
423
  const { entries } = service.data.getValue();
392
424
  service.hasFocus.setValue(true);
@@ -394,7 +426,7 @@ describe('DataGrid', () => {
394
426
  initializeShadeRoot({
395
427
  injector,
396
428
  rootElement,
397
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
429
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
398
430
  });
399
431
  await flushUpdates();
400
432
  const keydownEvent = new KeyboardEvent('keydown', { key: 'Insert', bubbles: true });
@@ -406,12 +438,12 @@ describe('DataGrid', () => {
406
438
  });
407
439
  describe('styles', () => {
408
440
  it('should apply wrapper styles when provided', async () => {
409
- await withTestGrid(async ({ injector, service, findOptions }) => {
441
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
410
442
  const rootElement = document.getElementById('root');
411
443
  initializeShadeRoot({
412
444
  injector,
413
445
  rootElement,
414
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {
446
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {
415
447
  wrapper: { backgroundColor: 'red' },
416
448
  }, headerComponents: {}, rowComponents: {} })),
417
449
  });
@@ -421,12 +453,12 @@ describe('DataGrid', () => {
421
453
  });
422
454
  });
423
455
  it('should apply header styles when provided', async () => {
424
- await withTestGrid(async ({ injector, service, findOptions }) => {
456
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
425
457
  const rootElement = document.getElementById('root');
426
458
  initializeShadeRoot({
427
459
  injector,
428
460
  rootElement,
429
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {
461
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {
430
462
  header: { color: 'blue' },
431
463
  }, headerComponents: {}, rowComponents: {} })),
432
464
  });
@@ -439,12 +471,12 @@ describe('DataGrid', () => {
439
471
  });
440
472
  describe('empty and loading states', () => {
441
473
  it('should show empty component when no data', async () => {
442
- await withTestGrid(async ({ injector, service, findOptions }) => {
474
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
443
475
  const rootElement = document.getElementById('root');
444
476
  initializeShadeRoot({
445
477
  injector,
446
478
  rootElement,
447
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {}, emptyComponent: createComponent("div", { "data-testid": "empty-state" }, "No data available") })),
479
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {}, emptyComponent: createComponent("div", { "data-testid": "empty-state" }, "No data available") })),
448
480
  });
449
481
  await flushUpdates();
450
482
  const grid = document.querySelector('shade-data-grid');
@@ -457,7 +489,7 @@ describe('DataGrid', () => {
457
489
  describe('row interactions', () => {
458
490
  it('should pass row click to collectionService', async () => {
459
491
  const onRowClick = vi.fn();
460
- await withTestGrid(async ({ injector, service, findOptions }) => {
492
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
461
493
  const rootElement = document.getElementById('root');
462
494
  service.data.setValue({
463
495
  count: 1,
@@ -466,7 +498,7 @@ describe('DataGrid', () => {
466
498
  initializeShadeRoot({
467
499
  injector,
468
500
  rootElement,
469
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
501
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
470
502
  });
471
503
  await flushUpdates();
472
504
  const grid = document.querySelector('shade-data-grid');
@@ -477,7 +509,7 @@ describe('DataGrid', () => {
477
509
  });
478
510
  it('should pass row double click to collectionService', async () => {
479
511
  const onRowDoubleClick = vi.fn();
480
- await withTestGrid(async ({ injector, service, findOptions }) => {
512
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
481
513
  const rootElement = document.getElementById('root');
482
514
  service.data.setValue({
483
515
  count: 1,
@@ -486,7 +518,7 @@ describe('DataGrid', () => {
486
518
  initializeShadeRoot({
487
519
  injector,
488
520
  rootElement,
489
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
521
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
490
522
  });
491
523
  await flushUpdates();
492
524
  const grid = document.querySelector('shade-data-grid');
@@ -497,16 +529,64 @@ describe('DataGrid', () => {
497
529
  }, { createService: () => new CollectionService({ onRowDoubleClick }) });
498
530
  });
499
531
  });
532
+ describe('row spatial navigation attributes', () => {
533
+ it('should set data-spatial-nav-target on rows', async () => {
534
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
535
+ const rootElement = document.getElementById('root');
536
+ initializeShadeRoot({
537
+ injector,
538
+ rootElement,
539
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
540
+ });
541
+ await flushUpdates();
542
+ const rows = document.querySelectorAll('shades-data-grid-row');
543
+ for (const row of rows) {
544
+ expect(row.hasAttribute('data-spatial-nav-target')).toBe(true);
545
+ }
546
+ });
547
+ });
548
+ it('should set tabIndex 0 on focused row and -1 on others', async () => {
549
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
550
+ const rootElement = document.getElementById('root');
551
+ service.focusedEntry.setValue(service.data.getValue().entries[1]);
552
+ initializeShadeRoot({
553
+ injector,
554
+ rootElement,
555
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
556
+ });
557
+ await flushUpdates();
558
+ const rows = document.querySelectorAll('shades-data-grid-row');
559
+ expect(rows[0]?.tabIndex).toBe(-1);
560
+ expect(rows[1]?.tabIndex).toBe(0);
561
+ expect(rows[2]?.tabIndex).toBe(-1);
562
+ });
563
+ });
564
+ it('should sync focusedEntry on row onfocus', async () => {
565
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
566
+ const rootElement = document.getElementById('root');
567
+ initializeShadeRoot({
568
+ injector,
569
+ rootElement,
570
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange })),
571
+ });
572
+ await flushUpdates();
573
+ const rows = document.querySelectorAll('shades-data-grid-row');
574
+ rows[2]?.dispatchEvent(new FocusEvent('focus'));
575
+ expect(service.focusedEntry.getValue()).toEqual({ id: 3, name: 'Third' });
576
+ expect(service.hasFocus.getValue()).toBe(true);
577
+ });
578
+ });
579
+ });
500
580
  describe('keyboard listener cleanup', () => {
501
581
  it('should remove keyboard listener when component is disconnected', async () => {
502
- await withTestGrid(async ({ injector, service, findOptions }) => {
582
+ await withTestGrid(async ({ injector, service, findOptions, onFindOptionsChange }) => {
503
583
  const rootElement = document.getElementById('root');
504
584
  service.hasFocus.setValue(true);
505
585
  service.focusedEntry.setValue(service.data.getValue().entries[0]);
506
586
  initializeShadeRoot({
507
587
  injector,
508
588
  rootElement,
509
- jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, styles: {}, headerComponents: {}, rowComponents: {} })),
589
+ jsxElement: (createComponent(DataGrid, { columns: ['id', 'name'], collectionService: service, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, styles: {}, headerComponents: {}, rowComponents: {} })),
510
590
  });
511
591
  await flushUpdates();
512
592
  const grid = document.querySelector('shade-data-grid');