@simplysm/solid 13.0.69 → 13.0.71

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 (495) hide show
  1. package/README.md +168 -195
  2. package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
  3. package/dist/components/data/calendar/Calendar.js +15 -2
  4. package/dist/components/data/calendar/Calendar.js.map +2 -2
  5. package/dist/components/data/kanban/KanbanContext.js +2 -2
  6. package/dist/components/data/kanban/KanbanContext.js.map +1 -1
  7. package/dist/components/data/list/List.d.ts +8 -8
  8. package/dist/components/data/list/ListContext.d.ts +1 -1
  9. package/dist/components/data/list/ListItem.d.ts +15 -15
  10. package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
  11. package/dist/components/data/sheet/DataSheet.js +6 -4
  12. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  13. package/dist/components/data/sheet/DataSheetConfigDialog.js +8 -8
  14. package/dist/components/data/sheet/DataSheetConfigDialog.js.map +1 -1
  15. package/dist/components/data/sheet/types.d.ts +4 -4
  16. package/dist/components/data/sheet/types.d.ts.map +1 -1
  17. package/dist/components/disclosure/Collapse.d.ts +4 -4
  18. package/dist/components/disclosure/Dialog.d.ts +24 -24
  19. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  20. package/dist/components/disclosure/Dialog.js +7 -2
  21. package/dist/components/disclosure/Dialog.js.map +2 -2
  22. package/dist/components/disclosure/DialogContext.d.ts +25 -25
  23. package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
  24. package/dist/components/disclosure/DialogContext.js +1 -1
  25. package/dist/components/disclosure/DialogContext.js.map +1 -1
  26. package/dist/components/disclosure/DialogInstanceContext.d.ts +7 -7
  27. package/dist/components/disclosure/DialogInstanceContext.d.ts.map +1 -1
  28. package/dist/components/disclosure/DialogProvider.d.ts +3 -3
  29. package/dist/components/disclosure/Dropdown.d.ts +26 -24
  30. package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
  31. package/dist/components/disclosure/Dropdown.js +24 -8
  32. package/dist/components/disclosure/Dropdown.js.map +2 -2
  33. package/dist/components/disclosure/Tabs.js +1 -1
  34. package/dist/components/disclosure/Tabs.js.map +1 -1
  35. package/dist/components/disclosure/dialogZIndex.d.ts +9 -7
  36. package/dist/components/disclosure/dialogZIndex.d.ts.map +1 -1
  37. package/dist/components/disclosure/dialogZIndex.js +4 -0
  38. package/dist/components/disclosure/dialogZIndex.js.map +1 -1
  39. package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
  40. package/dist/components/features/crud-detail/CrudDetail.js +34 -22
  41. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  42. package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
  43. package/dist/components/features/crud-sheet/CrudSheet.js +48 -33
  44. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  45. package/dist/components/features/crudRegistry.d.ts +16 -0
  46. package/dist/components/features/crudRegistry.d.ts.map +1 -0
  47. package/dist/components/features/crudRegistry.js +37 -0
  48. package/dist/components/features/crudRegistry.js.map +6 -0
  49. package/dist/components/features/data-select-button/DataSelectButton.d.ts +14 -14
  50. package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
  51. package/dist/components/features/data-select-button/DataSelectButton.js +27 -9
  52. package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
  53. package/dist/components/features/permission-table/PermissionTable.d.ts +3 -3
  54. package/dist/components/features/permission-table/PermissionTable.d.ts.map +1 -1
  55. package/dist/components/features/permission-table/PermissionTable.js +74 -85
  56. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  57. package/dist/components/features/shared-data/SharedDataSelect.d.ts +12 -12
  58. package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
  59. package/dist/components/features/shared-data/SharedDataSelect.js +10 -6
  60. package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
  61. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +10 -10
  62. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
  63. package/dist/components/features/shared-data/SharedDataSelectList.d.ts +23 -15
  64. package/dist/components/features/shared-data/SharedDataSelectList.d.ts.map +1 -1
  65. package/dist/components/features/shared-data/SharedDataSelectList.js +191 -65
  66. package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
  67. package/dist/components/features/shared-data/SharedDataSelectListContext.d.ts +15 -0
  68. package/dist/components/features/shared-data/SharedDataSelectListContext.d.ts.map +1 -0
  69. package/dist/components/features/shared-data/SharedDataSelectListContext.js +27 -0
  70. package/dist/components/features/shared-data/SharedDataSelectListContext.js.map +6 -0
  71. package/dist/components/feedback/Progress.d.ts +1 -1
  72. package/dist/components/feedback/Progress.d.ts.map +1 -1
  73. package/dist/components/feedback/busy/BusyContainer.d.ts +2 -2
  74. package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -1
  75. package/dist/components/feedback/busy/BusyContext.d.ts +11 -11
  76. package/dist/components/feedback/busy/BusyContext.d.ts.map +1 -1
  77. package/dist/components/feedback/busy/BusyContext.js +1 -1
  78. package/dist/components/feedback/busy/BusyContext.js.map +1 -1
  79. package/dist/components/feedback/busy/BusyProvider.d.ts +6 -6
  80. package/dist/components/feedback/busy/BusyProvider.d.ts.map +1 -1
  81. package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
  82. package/dist/components/feedback/notification/NotificationBanner.js +7 -3
  83. package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
  84. package/dist/components/feedback/notification/NotificationBell.js +2 -2
  85. package/dist/components/feedback/notification/NotificationBell.js.map +1 -1
  86. package/dist/components/feedback/notification/NotificationContext.d.ts +22 -22
  87. package/dist/components/feedback/notification/NotificationContext.d.ts.map +1 -1
  88. package/dist/components/feedback/notification/NotificationContext.js +1 -1
  89. package/dist/components/feedback/notification/NotificationContext.js.map +1 -1
  90. package/dist/components/feedback/notification/NotificationProvider.d.ts +5 -5
  91. package/dist/components/feedback/notification/NotificationProvider.js +1 -1
  92. package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
  93. package/dist/components/feedback/print/PrintContext.js +1 -1
  94. package/dist/components/feedback/print/PrintContext.js.map +1 -1
  95. package/dist/components/form-control/DropdownTrigger.styles.d.ts +1 -1
  96. package/dist/components/form-control/DropdownTrigger.styles.d.ts.map +1 -1
  97. package/dist/components/form-control/ThemeToggle.d.ts +7 -7
  98. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  99. package/dist/components/form-control/ThemeToggle.js +3 -3
  100. package/dist/components/form-control/checkbox/Checkbox.js +1 -1
  101. package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
  102. package/dist/components/form-control/checkbox/Radio.js +1 -1
  103. package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
  104. package/dist/components/form-control/color-picker/ColorPicker.d.ts +12 -12
  105. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  106. package/dist/components/form-control/color-picker/ColorPicker.js +2 -2
  107. package/dist/components/form-control/combobox/Combobox.d.ts +22 -22
  108. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  109. package/dist/components/form-control/combobox/Combobox.js +2 -2
  110. package/dist/components/form-control/combobox/ComboboxContext.d.ts +4 -4
  111. package/dist/components/form-control/combobox/ComboboxContext.d.ts.map +1 -1
  112. package/dist/components/form-control/combobox/ComboboxContext.js +1 -1
  113. package/dist/components/form-control/combobox/ComboboxContext.js.map +1 -1
  114. package/dist/components/form-control/combobox/ComboboxItem.d.ts +3 -3
  115. package/dist/components/form-control/combobox/ComboboxItem.d.ts.map +1 -1
  116. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +14 -14
  117. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
  118. package/dist/components/form-control/date-range-picker/DateRangePicker.js +20 -9
  119. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  120. package/dist/components/form-control/editor/EditorToolbar.d.ts.map +1 -1
  121. package/dist/components/form-control/editor/EditorToolbar.js +65 -20
  122. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  123. package/dist/components/form-control/editor/RichTextEditor.d.ts +6 -6
  124. package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
  125. package/dist/components/form-control/editor/RichTextEditor.js +1 -1
  126. package/dist/components/form-control/editor/editor.css +5 -5
  127. package/dist/components/form-control/field/DatePicker.d.ts +22 -22
  128. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  129. package/dist/components/form-control/field/DatePicker.js +4 -4
  130. package/dist/components/form-control/field/DatePicker.js.map +1 -1
  131. package/dist/components/form-control/field/DateTimePicker.d.ts +21 -21
  132. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  133. package/dist/components/form-control/field/DateTimePicker.js +4 -4
  134. package/dist/components/form-control/field/DateTimePicker.js.map +1 -1
  135. package/dist/components/form-control/field/FieldPlaceholder.d.ts +1 -1
  136. package/dist/components/form-control/field/FieldPlaceholder.d.ts.map +1 -1
  137. package/dist/components/form-control/field/NumberInput.d.ts +23 -23
  138. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  139. package/dist/components/form-control/field/NumberInput.js +4 -4
  140. package/dist/components/form-control/field/NumberInput.js.map +1 -1
  141. package/dist/components/form-control/field/TextInput.d.ts +25 -25
  142. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  143. package/dist/components/form-control/field/TextInput.js +5 -5
  144. package/dist/components/form-control/field/TextInput.js.map +1 -1
  145. package/dist/components/form-control/field/Textarea.d.ts +19 -19
  146. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  147. package/dist/components/form-control/field/Textarea.js +4 -4
  148. package/dist/components/form-control/field/Textarea.js.map +1 -1
  149. package/dist/components/form-control/field/TimePicker.d.ts +20 -20
  150. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  151. package/dist/components/form-control/field/TimePicker.js +4 -4
  152. package/dist/components/form-control/field/TimePicker.js.map +1 -1
  153. package/dist/components/form-control/numpad/Numpad.d.ts +11 -11
  154. package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
  155. package/dist/components/form-control/select/Select.d.ts +26 -26
  156. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  157. package/dist/components/form-control/select/Select.js +34 -23
  158. package/dist/components/form-control/select/Select.js.map +2 -2
  159. package/dist/components/form-control/select/SelectContext.d.ts +7 -7
  160. package/dist/components/form-control/select/SelectContext.d.ts.map +1 -1
  161. package/dist/components/form-control/select/SelectContext.js +1 -1
  162. package/dist/components/form-control/select/SelectContext.js.map +1 -1
  163. package/dist/components/form-control/select/SelectItem.d.ts +4 -4
  164. package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
  165. package/dist/components/form-control/state-preset/StatePreset.js +8 -8
  166. package/dist/components/form-control/state-preset/StatePreset.js.map +1 -1
  167. package/dist/components/layout/FormTable.js +4 -4
  168. package/dist/components/layout/sidebar/Sidebar.d.ts +5 -5
  169. package/dist/components/layout/sidebar/SidebarContainer.d.ts +11 -11
  170. package/dist/components/layout/sidebar/SidebarContainer.d.ts.map +1 -1
  171. package/dist/components/layout/sidebar/SidebarContainer.js +6 -1
  172. package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
  173. package/dist/components/layout/sidebar/SidebarContext.d.ts +7 -7
  174. package/dist/components/layout/sidebar/SidebarContext.js +1 -1
  175. package/dist/components/layout/sidebar/SidebarContext.js.map +1 -1
  176. package/dist/components/layout/sidebar/SidebarMenu.d.ts +11 -11
  177. package/dist/components/layout/sidebar/SidebarUser.d.ts +14 -14
  178. package/dist/components/layout/topbar/Topbar.d.ts +6 -6
  179. package/dist/components/layout/topbar/Topbar.d.ts.map +1 -1
  180. package/dist/components/layout/topbar/Topbar.js +11 -6
  181. package/dist/components/layout/topbar/Topbar.js.map +2 -2
  182. package/dist/components/layout/topbar/TopbarContainer.d.ts +6 -6
  183. package/dist/components/layout/topbar/TopbarContext.js +2 -2
  184. package/dist/components/layout/topbar/TopbarContext.js.map +1 -1
  185. package/dist/components/layout/topbar/TopbarMenu.d.ts +11 -11
  186. package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
  187. package/dist/components/layout/topbar/TopbarMenu.js +5 -1
  188. package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
  189. package/dist/components/layout/topbar/TopbarUser.d.ts +9 -9
  190. package/dist/directives/ripple.d.ts +5 -5
  191. package/dist/helpers/createAppStructure.d.ts.map +1 -1
  192. package/dist/helpers/createAppStructure.js +7 -3
  193. package/dist/helpers/createAppStructure.js.map +1 -1
  194. package/dist/helpers/createHmrSafeContext.d.ts +3 -0
  195. package/dist/helpers/createHmrSafeContext.d.ts.map +1 -0
  196. package/dist/helpers/createHmrSafeContext.js +10 -0
  197. package/dist/helpers/createHmrSafeContext.js.map +6 -0
  198. package/dist/helpers/createSlotComponent.d.ts +3 -3
  199. package/dist/helpers/mergeStyles.d.ts +8 -8
  200. package/dist/hooks/createControllableSignal.d.ts +10 -10
  201. package/dist/hooks/createControllableStore.d.ts +6 -6
  202. package/dist/hooks/createIMEHandler.d.ts +7 -7
  203. package/dist/hooks/createMountTransition.d.ts +4 -4
  204. package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
  205. package/dist/hooks/createSelectionGroup.js +4 -3
  206. package/dist/hooks/createSelectionGroup.js.map +2 -2
  207. package/dist/hooks/createSlotSignal.d.ts +2 -2
  208. package/dist/hooks/useLocalStorage.d.ts +11 -11
  209. package/dist/hooks/useLogger.d.ts +1 -1
  210. package/dist/hooks/useLogger.d.ts.map +1 -1
  211. package/dist/hooks/useLogger.js +1 -1
  212. package/dist/hooks/useLogger.js.map +1 -1
  213. package/dist/hooks/useRouterLink.d.ts +10 -10
  214. package/dist/hooks/useRouterLink.d.ts.map +1 -1
  215. package/dist/index.d.ts +2 -1
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +2 -1
  218. package/dist/index.js.map +1 -1
  219. package/dist/providers/ClipboardProvider.d.ts +5 -5
  220. package/dist/providers/ConfigContext.d.ts +6 -6
  221. package/dist/providers/ConfigContext.js +2 -2
  222. package/dist/providers/ConfigContext.js.map +1 -1
  223. package/dist/providers/ErrorLoggerProvider.d.ts +3 -3
  224. package/dist/providers/LoggerContext.d.ts +13 -13
  225. package/dist/providers/PwaUpdateProvider.d.ts +4 -4
  226. package/dist/providers/PwaUpdateProvider.js +2 -2
  227. package/dist/providers/PwaUpdateProvider.js.map +1 -1
  228. package/dist/providers/ServiceClientContext.d.ts +8 -8
  229. package/dist/providers/ServiceClientContext.d.ts.map +1 -1
  230. package/dist/providers/ServiceClientContext.js +1 -1
  231. package/dist/providers/ServiceClientContext.js.map +1 -1
  232. package/dist/providers/ServiceClientProvider.d.ts +6 -6
  233. package/dist/providers/ServiceClientProvider.js +7 -7
  234. package/dist/providers/ServiceClientProvider.js.map +1 -1
  235. package/dist/providers/SyncStorageContext.d.ts +14 -14
  236. package/dist/providers/SystemProvider.d.ts.map +1 -1
  237. package/dist/providers/SystemProvider.js +21 -16
  238. package/dist/providers/SystemProvider.js.map +2 -2
  239. package/dist/providers/ThemeContext.d.ts +20 -20
  240. package/dist/providers/ThemeContext.d.ts.map +1 -1
  241. package/dist/providers/ThemeContext.js +1 -1
  242. package/dist/providers/ThemeContext.js.map +1 -1
  243. package/dist/providers/i18n/I18nContext.d.ts +44 -0
  244. package/dist/providers/i18n/I18nContext.d.ts.map +1 -0
  245. package/dist/providers/i18n/I18nContext.js +73 -0
  246. package/dist/providers/i18n/I18nContext.js.map +6 -0
  247. package/dist/providers/i18n/I18nContext.types.d.ts +28 -0
  248. package/dist/providers/i18n/I18nContext.types.d.ts.map +1 -0
  249. package/dist/providers/i18n/I18nContext.types.js +1 -0
  250. package/dist/providers/i18n/I18nContext.types.js.map +6 -0
  251. package/dist/providers/i18n/i18nUtils.d.ts +18 -0
  252. package/dist/providers/i18n/i18nUtils.d.ts.map +1 -0
  253. package/dist/providers/i18n/i18nUtils.js +25 -0
  254. package/dist/providers/i18n/i18nUtils.js.map +6 -0
  255. package/dist/providers/i18n/locales/en.d.ts +163 -0
  256. package/dist/providers/i18n/locales/en.d.ts.map +1 -0
  257. package/dist/providers/i18n/locales/en.js +165 -0
  258. package/dist/providers/i18n/locales/en.js.map +6 -0
  259. package/dist/providers/i18n/locales/ko.d.ts +163 -0
  260. package/dist/providers/i18n/locales/ko.d.ts.map +1 -0
  261. package/dist/providers/i18n/locales/ko.js +165 -0
  262. package/dist/providers/i18n/locales/ko.js.map +6 -0
  263. package/dist/providers/shared-data/SharedDataChangeEvent.d.ts +4 -4
  264. package/dist/providers/shared-data/SharedDataContext.d.ts +28 -28
  265. package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
  266. package/dist/providers/shared-data/SharedDataContext.js +1 -1
  267. package/dist/providers/shared-data/SharedDataContext.js.map +1 -1
  268. package/dist/providers/shared-data/SharedDataProvider.d.ts +9 -9
  269. package/dist/providers/shared-data/SharedDataProvider.js +4 -4
  270. package/dist/providers/shared-data/SharedDataProvider.js.map +1 -1
  271. package/package.json +9 -8
  272. package/src/components/data/calendar/Calendar.tsx +10 -4
  273. package/src/components/data/kanban/Kanban.tsx +14 -14
  274. package/src/components/data/kanban/KanbanContext.ts +3 -3
  275. package/src/components/data/list/List.tsx +10 -10
  276. package/src/components/data/list/ListContext.ts +1 -1
  277. package/src/components/data/list/ListItem.styles.ts +8 -8
  278. package/src/components/data/list/ListItem.tsx +15 -15
  279. package/src/components/data/sheet/DataSheet.styles.ts +22 -22
  280. package/src/components/data/sheet/DataSheet.tsx +52 -48
  281. package/src/components/data/sheet/DataSheetColumn.tsx +1 -1
  282. package/src/components/data/sheet/DataSheetConfigDialog.tsx +9 -9
  283. package/src/components/data/sheet/sheetUtils.ts +7 -7
  284. package/src/components/data/sheet/types.ts +16 -16
  285. package/src/components/disclosure/Collapse.tsx +11 -11
  286. package/src/components/disclosure/Dialog.tsx +60 -57
  287. package/src/components/disclosure/DialogContext.ts +26 -26
  288. package/src/components/disclosure/DialogInstanceContext.ts +7 -7
  289. package/src/components/disclosure/DialogProvider.tsx +5 -5
  290. package/src/components/disclosure/Dropdown.tsx +89 -75
  291. package/src/components/disclosure/Tabs.tsx +1 -1
  292. package/src/components/disclosure/dialogZIndex.ts +16 -11
  293. package/src/components/display/Echarts.tsx +4 -4
  294. package/src/components/features/address/AddressSearch.tsx +2 -2
  295. package/src/components/features/crud-detail/CrudDetail.tsx +34 -21
  296. package/src/components/features/crud-detail/CrudDetailAfter.tsx +1 -1
  297. package/src/components/features/crud-detail/CrudDetailBefore.tsx +1 -1
  298. package/src/components/features/crud-detail/CrudDetailTools.tsx +1 -1
  299. package/src/components/features/crud-sheet/CrudSheet.tsx +52 -40
  300. package/src/components/features/crud-sheet/CrudSheetColumn.tsx +1 -1
  301. package/src/components/features/crud-sheet/CrudSheetFilter.tsx +1 -1
  302. package/src/components/features/crud-sheet/CrudSheetHeader.tsx +1 -1
  303. package/src/components/features/crud-sheet/CrudSheetTools.tsx +1 -1
  304. package/src/components/features/crudRegistry.ts +60 -0
  305. package/src/components/features/data-select-button/DataSelectButton.tsx +34 -32
  306. package/src/components/features/permission-table/PermissionTable.tsx +70 -64
  307. package/src/components/features/shared-data/SharedDataSelect.tsx +24 -22
  308. package/src/components/features/shared-data/SharedDataSelectButton.tsx +10 -10
  309. package/src/components/features/shared-data/SharedDataSelectList.tsx +231 -59
  310. package/src/components/features/shared-data/SharedDataSelectListContext.ts +39 -0
  311. package/src/components/feedback/Progress.tsx +1 -1
  312. package/src/components/feedback/busy/BusyContainer.tsx +6 -6
  313. package/src/components/feedback/busy/BusyContext.ts +12 -12
  314. package/src/components/feedback/busy/BusyProvider.tsx +6 -6
  315. package/src/components/feedback/notification/NotificationBanner.tsx +3 -1
  316. package/src/components/feedback/notification/NotificationBell.tsx +4 -4
  317. package/src/components/feedback/notification/NotificationContext.ts +28 -28
  318. package/src/components/feedback/notification/NotificationProvider.tsx +9 -9
  319. package/src/components/feedback/print/PrintContext.ts +1 -1
  320. package/src/components/form-control/Button.tsx +1 -1
  321. package/src/components/form-control/DropdownTrigger.styles.ts +1 -1
  322. package/src/components/form-control/Invalid.tsx +5 -5
  323. package/src/components/form-control/ThemeToggle.tsx +10 -10
  324. package/src/components/form-control/checkbox/Checkbox.styles.ts +8 -8
  325. package/src/components/form-control/checkbox/Checkbox.tsx +2 -2
  326. package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
  327. package/src/components/form-control/checkbox/Radio.tsx +2 -2
  328. package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
  329. package/src/components/form-control/color-picker/ColorPicker.tsx +17 -17
  330. package/src/components/form-control/combobox/Combobox.tsx +55 -55
  331. package/src/components/form-control/combobox/ComboboxContext.ts +5 -5
  332. package/src/components/form-control/combobox/ComboboxItem.tsx +3 -3
  333. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +40 -26
  334. package/src/components/form-control/editor/EditorToolbar.tsx +52 -50
  335. package/src/components/form-control/editor/RichTextEditor.tsx +16 -16
  336. package/src/components/form-control/editor/editor.css +5 -5
  337. package/src/components/form-control/field/DatePicker.tsx +39 -39
  338. package/src/components/form-control/field/DateTimePicker.tsx +38 -38
  339. package/src/components/form-control/field/Field.styles.ts +11 -11
  340. package/src/components/form-control/field/FieldPlaceholder.tsx +1 -1
  341. package/src/components/form-control/field/NumberInput.tsx +63 -63
  342. package/src/components/form-control/field/TextInput.tsx +48 -48
  343. package/src/components/form-control/field/Textarea.tsx +32 -32
  344. package/src/components/form-control/field/TimePicker.tsx +37 -37
  345. package/src/components/form-control/numpad/Numpad.tsx +26 -26
  346. package/src/components/form-control/select/Select.tsx +82 -86
  347. package/src/components/form-control/select/SelectContext.ts +8 -8
  348. package/src/components/form-control/select/SelectItem.tsx +5 -5
  349. package/src/components/form-control/state-preset/StatePreset.tsx +13 -13
  350. package/src/components/layout/FormTable.tsx +4 -4
  351. package/src/components/layout/sidebar/Sidebar.tsx +8 -8
  352. package/src/components/layout/sidebar/SidebarContainer.tsx +19 -17
  353. package/src/components/layout/sidebar/SidebarContext.ts +8 -8
  354. package/src/components/layout/sidebar/SidebarMenu.tsx +19 -19
  355. package/src/components/layout/sidebar/SidebarUser.tsx +14 -14
  356. package/src/components/layout/topbar/Topbar.tsx +15 -13
  357. package/src/components/layout/topbar/TopbarContainer.tsx +6 -6
  358. package/src/components/layout/topbar/TopbarContext.ts +2 -2
  359. package/src/components/layout/topbar/TopbarMenu.tsx +18 -16
  360. package/src/components/layout/topbar/TopbarUser.tsx +9 -9
  361. package/src/directives/ripple.ts +8 -8
  362. package/src/helpers/createAppStructure.ts +15 -8
  363. package/src/helpers/createHmrSafeContext.ts +8 -0
  364. package/src/helpers/createSlotComponent.ts +4 -4
  365. package/src/helpers/mergeStyles.ts +11 -11
  366. package/src/hooks/createControllableSignal.ts +11 -11
  367. package/src/hooks/createControllableStore.ts +8 -8
  368. package/src/hooks/createIMEHandler.ts +7 -7
  369. package/src/hooks/createMountTransition.ts +4 -4
  370. package/src/hooks/createSelectionGroup.tsx +5 -3
  371. package/src/hooks/createSlotSignal.ts +2 -2
  372. package/src/hooks/useLocalStorage.ts +13 -13
  373. package/src/hooks/useLogger.ts +2 -2
  374. package/src/hooks/useRouterLink.ts +15 -15
  375. package/src/index.ts +4 -3
  376. package/src/providers/ClipboardProvider.tsx +19 -19
  377. package/src/providers/ConfigContext.tsx +8 -8
  378. package/src/providers/ErrorLoggerProvider.tsx +3 -3
  379. package/src/providers/LoggerContext.tsx +13 -13
  380. package/src/providers/PwaUpdateProvider.tsx +6 -6
  381. package/src/providers/ServiceClientContext.ts +9 -9
  382. package/src/providers/ServiceClientProvider.tsx +15 -15
  383. package/src/providers/SyncStorageContext.tsx +15 -15
  384. package/src/providers/SystemProvider.tsx +15 -12
  385. package/src/providers/ThemeContext.tsx +26 -26
  386. package/src/providers/i18n/I18nContext.tsx +129 -0
  387. package/src/providers/i18n/I18nContext.types.ts +30 -0
  388. package/src/providers/i18n/i18nUtils.ts +38 -0
  389. package/src/providers/i18n/locales/en.ts +161 -0
  390. package/src/providers/i18n/locales/ko.ts +161 -0
  391. package/src/providers/shared-data/SharedDataChangeEvent.ts +4 -4
  392. package/src/providers/shared-data/SharedDataContext.ts +29 -29
  393. package/src/providers/shared-data/SharedDataProvider.tsx +21 -21
  394. package/src/styles/patterns.styles.ts +6 -6
  395. package/src/styles/tokens.styles.ts +5 -5
  396. package/tailwind.config.ts +1 -1
  397. package/tailwind.css +4 -4
  398. package/tests/components/data/List.spec.tsx +689 -0
  399. package/tests/components/data/Pagination.spec.tsx +336 -0
  400. package/tests/components/data/Table.spec.tsx +55 -0
  401. package/tests/components/data/kanban/Kanban.selection.spec.tsx +213 -0
  402. package/tests/components/data/sheet/DataSheet.spec.tsx +645 -0
  403. package/tests/components/disclosure/Collapse.spec.tsx +173 -0
  404. package/tests/components/disclosure/Dialog.spec.tsx +438 -0
  405. package/tests/components/disclosure/DialogProvider.spec.tsx +142 -0
  406. package/tests/components/disclosure/Dropdown.spec.tsx +333 -0
  407. package/tests/components/disclosure/Tabs.spec.tsx +220 -0
  408. package/tests/components/disclosure/dialogZIndex.spec.ts +45 -0
  409. package/tests/components/display/Alert.spec.tsx +47 -0
  410. package/tests/components/display/Barcode.spec.tsx +61 -0
  411. package/tests/components/display/Card.spec.tsx +41 -0
  412. package/tests/components/display/Link.spec.tsx +62 -0
  413. package/tests/components/display/Tag.spec.tsx +47 -0
  414. package/tests/components/features/address/AddressSearch.spec.tsx +45 -0
  415. package/tests/components/features/crud-detail/CrudDetail.spec.tsx +537 -0
  416. package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +491 -0
  417. package/tests/components/features/crudRegistry.spec.ts +119 -0
  418. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +482 -0
  419. package/tests/components/features/permission-table/PermissionTable.spec.tsx +288 -0
  420. package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +448 -0
  421. package/tests/components/feedback/busy/BusyContainer.spec.tsx +80 -0
  422. package/tests/components/feedback/notification/LiveRegion.spec.tsx +52 -0
  423. package/tests/components/feedback/notification/NotificationBanner.spec.tsx +187 -0
  424. package/tests/components/feedback/notification/NotificationBell.spec.tsx +226 -0
  425. package/tests/components/feedback/notification/NotificationContext.spec.tsx +362 -0
  426. package/tests/components/feedback/print/Print.spec.tsx +45 -0
  427. package/tests/components/form-control/Button.spec.tsx +119 -0
  428. package/tests/components/form-control/Invalid.spec.tsx +131 -0
  429. package/tests/components/form-control/checkbox/Checkbox.spec.tsx +137 -0
  430. package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +108 -0
  431. package/tests/components/form-control/checkbox/Radio.spec.tsx +138 -0
  432. package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +108 -0
  433. package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +94 -0
  434. package/tests/components/form-control/combobox/Combobox.spec.tsx +253 -0
  435. package/tests/components/form-control/combobox/ComboboxItem.spec.tsx +88 -0
  436. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +208 -0
  437. package/tests/components/form-control/field/DatePicker.spec.tsx +381 -0
  438. package/tests/components/form-control/field/DateTimePicker.spec.tsx +383 -0
  439. package/tests/components/form-control/field/NumberInput.spec.tsx +371 -0
  440. package/tests/components/form-control/field/TextInput.spec.tsx +341 -0
  441. package/tests/components/form-control/field/Textarea.spec.tsx +224 -0
  442. package/tests/components/form-control/field/TimePicker.spec.tsx +315 -0
  443. package/tests/components/form-control/numpad/Numpad.spec.tsx +248 -0
  444. package/tests/components/form-control/select/Select.spec.tsx +676 -0
  445. package/tests/components/form-control/select/SelectItem.spec.tsx +174 -0
  446. package/tests/components/layout/FormGroup.spec.tsx +104 -0
  447. package/tests/components/layout/FormTable.spec.tsx +43 -0
  448. package/tests/components/layout/sidebar/Sidebar.spec.tsx +192 -0
  449. package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +261 -0
  450. package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +219 -0
  451. package/tests/components/layout/sidebar/SidebarUser.spec.tsx +133 -0
  452. package/tests/components/layout/topbar/TopbarActions.spec.tsx +77 -0
  453. package/tests/components/layout/topbar/TopbarContainer.spec.tsx +38 -0
  454. package/tests/components/layout/topbar/createTopbarActions.spec.tsx +66 -0
  455. package/tests/directives/ripple.spec.tsx +130 -0
  456. package/tests/helpers/createAppStructure.spec.tsx +843 -0
  457. package/tests/helpers/mergeStyles.spec.ts +172 -0
  458. package/tests/hooks/createControllableSignal.spec.ts +194 -0
  459. package/tests/hooks/createIMEHandler.spec.ts +80 -0
  460. package/tests/hooks/createMountTransition.spec.ts +86 -0
  461. package/tests/hooks/useLocalStorage.spec.tsx +223 -0
  462. package/tests/hooks/useLogger.spec.tsx +116 -0
  463. package/tests/hooks/usePrint.spec.tsx +134 -0
  464. package/tests/hooks/useRouterLink.spec.tsx +183 -0
  465. package/tests/hooks/useSyncConfig.spec.tsx +304 -0
  466. package/tests/providers/ClipboardProvider.spec.tsx +20 -0
  467. package/tests/providers/ConfigContext.spec.tsx +42 -0
  468. package/tests/providers/ErrorLoggerProvider.spec.tsx +73 -0
  469. package/tests/providers/LoggerContext.spec.tsx +76 -0
  470. package/tests/providers/PwaUpdateProvider.spec.tsx +22 -0
  471. package/tests/providers/ServiceClientContext.spec.tsx +88 -0
  472. package/tests/providers/SyncStorageContext.spec.tsx +77 -0
  473. package/tests/providers/i18n/I18nContext.spec.tsx +110 -0
  474. package/tests/providers/shared-data/SharedDataProvider.spec.tsx +401 -0
  475. package/tests/vitest-env.d.ts +1 -0
  476. package/dist/components/form-control/select-list/SelectList.d.ts +0 -54
  477. package/dist/components/form-control/select-list/SelectList.d.ts.map +0 -1
  478. package/dist/components/form-control/select-list/SelectList.js +0 -280
  479. package/dist/components/form-control/select-list/SelectList.js.map +0 -6
  480. package/dist/components/form-control/select-list/SelectListContext.d.ts +0 -13
  481. package/dist/components/form-control/select-list/SelectListContext.d.ts.map +0 -1
  482. package/dist/components/form-control/select-list/SelectListContext.js +0 -14
  483. package/dist/components/form-control/select-list/SelectListContext.js.map +0 -6
  484. package/docs/data-components.md +0 -782
  485. package/docs/disclosure.md +0 -254
  486. package/docs/display.md +0 -153
  487. package/docs/feedback.md +0 -238
  488. package/docs/form-controls.md +0 -1068
  489. package/docs/helpers.md +0 -54
  490. package/docs/hooks.md +0 -588
  491. package/docs/layout.md +0 -384
  492. package/docs/providers.md +0 -211
  493. package/docs/styling.md +0 -184
  494. package/src/components/form-control/select-list/SelectList.tsx +0 -385
  495. package/src/components/form-control/select-list/SelectListContext.ts +0 -23
@@ -0,0 +1,261 @@
1
+ import { render, fireEvent } from "@solidjs/testing-library";
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
3
+ import type { Component, Setter } from "solid-js";
4
+
5
+ // Media query mock
6
+ const mockCreateMediaQuery = vi.fn(() => () => true as boolean);
7
+ vi.mock("@solid-primitives/media", () => ({
8
+ createMediaQuery: () => mockCreateMediaQuery(),
9
+ }));
10
+
11
+ // @solidjs/router mock
12
+ vi.mock("@solidjs/router", () => ({
13
+ useBeforeLeave: vi.fn(),
14
+ useLocation: vi.fn(() => ({ pathname: "/" })),
15
+ useNavigate: vi.fn(() => vi.fn()),
16
+ }));
17
+
18
+ import { Sidebar, useSidebarContext } from "../../../../src";
19
+ import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
20
+ import { ConfigProvider } from "../../../../src/providers/ConfigContext";
21
+
22
+ // ToggleCapture helper - Extract setToggle from Context for external control
23
+ const ToggleCapture: Component<{ onCapture: (setToggle: Setter<boolean>) => void }> = (props) => {
24
+ const { setToggle } = useSidebarContext();
25
+ props.onCapture(setToggle);
26
+ return null;
27
+ };
28
+
29
+ describe("SidebarContainer component", () => {
30
+ beforeEach(() => {
31
+ mockCreateMediaQuery.mockReturnValue(() => true); // Desktop mode
32
+ localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
33
+ });
34
+
35
+ afterEach(() => {
36
+ vi.clearAllMocks();
37
+ localStorage.removeItem("test.i18n-locale");
38
+ });
39
+
40
+ describe("basic rendering", () => {
41
+ it("displays children inside container", () => {
42
+ const { getByText } = render(() => (
43
+ <ConfigProvider clientName="test"><I18nProvider>
44
+ <Sidebar.Container>
45
+ <span>Content</span>
46
+ </Sidebar.Container>
47
+ </I18nProvider></ConfigProvider>
48
+ ));
49
+
50
+ expect(getByText("Content")).toBeTruthy();
51
+ });
52
+ });
53
+
54
+ describe("padding-left handling", () => {
55
+ it("applies padding-left when open on desktop", () => {
56
+ mockCreateMediaQuery.mockReturnValue(() => true); // Desktop
57
+
58
+ const { container } = render(() => (
59
+ <ConfigProvider clientName="test"><I18nProvider>
60
+ <Sidebar.Container>
61
+ <div>Content</div>
62
+ </Sidebar.Container>
63
+ </I18nProvider></ConfigProvider>
64
+ ));
65
+
66
+ // toggle=false (initial) → open on desktop
67
+ const containerEl = container.firstElementChild as HTMLElement;
68
+ expect(containerEl.style.paddingLeft).toBe("16rem");
69
+ });
70
+
71
+ it("removes padding-left when closed on desktop", () => {
72
+ mockCreateMediaQuery.mockReturnValue(() => true); // Desktop
73
+ let setToggle!: Setter<boolean>;
74
+
75
+ const { container } = render(() => (
76
+ <ConfigProvider clientName="test"><I18nProvider>
77
+ <Sidebar.Container>
78
+ <ToggleCapture onCapture={(fn) => (setToggle = fn)} />
79
+ <div>Content</div>
80
+ </Sidebar.Container>
81
+ </I18nProvider></ConfigProvider>
82
+ ));
83
+
84
+ setToggle(true); // Switch to closed
85
+ const containerEl = container.firstElementChild as HTMLElement;
86
+ expect(containerEl.style.paddingLeft).toBe("");
87
+ });
88
+
89
+ it("has no padding-left on mobile", () => {
90
+ mockCreateMediaQuery.mockReturnValue(() => false); // Mobile
91
+
92
+ const { container } = render(() => (
93
+ <ConfigProvider clientName="test"><I18nProvider>
94
+ <Sidebar.Container>
95
+ <div>Content</div>
96
+ </Sidebar.Container>
97
+ </I18nProvider></ConfigProvider>
98
+ ));
99
+
100
+ const containerEl = container.firstElementChild as HTMLElement;
101
+ expect(containerEl.style.paddingLeft).toBe("");
102
+ });
103
+ });
104
+
105
+ describe("backdrop rendering", () => {
106
+ it("renders backdrop when open on mobile", () => {
107
+ mockCreateMediaQuery.mockReturnValue(() => false); // Mobile
108
+ let setToggle!: Setter<boolean>;
109
+
110
+ const { container } = render(() => (
111
+ <ConfigProvider clientName="test"><I18nProvider>
112
+ <Sidebar.Container>
113
+ <ToggleCapture onCapture={(fn) => (setToggle = fn)} />
114
+ <div>Content</div>
115
+ </Sidebar.Container>
116
+ </I18nProvider></ConfigProvider>
117
+ ));
118
+
119
+ setToggle(true); // Open on mobile
120
+ const backdrop = container.querySelector('[role="button"][aria-label="Close sidebar"]');
121
+ expect(backdrop).toBeTruthy();
122
+ });
123
+
124
+ it("does not render backdrop when closed on mobile", () => {
125
+ mockCreateMediaQuery.mockReturnValue(() => false); // Mobile
126
+
127
+ const { container } = render(() => (
128
+ <ConfigProvider clientName="test"><I18nProvider>
129
+ <Sidebar.Container>
130
+ <div>Content</div>
131
+ </Sidebar.Container>
132
+ </I18nProvider></ConfigProvider>
133
+ ));
134
+
135
+ // toggle=false (initial) → closed on mobile
136
+ const backdrop = container.querySelector('[role="button"][aria-label="Close sidebar"]');
137
+ expect(backdrop).toBeFalsy();
138
+ });
139
+
140
+ it("does not render backdrop on desktop", () => {
141
+ mockCreateMediaQuery.mockReturnValue(() => true); // Desktop
142
+
143
+ const { container } = render(() => (
144
+ <ConfigProvider clientName="test"><I18nProvider>
145
+ <Sidebar.Container>
146
+ <div>Content</div>
147
+ </Sidebar.Container>
148
+ </I18nProvider></ConfigProvider>
149
+ ));
150
+
151
+ const backdrop = container.querySelector('[role="button"][aria-label="Close sidebar"]');
152
+ expect(backdrop).toBeFalsy();
153
+ });
154
+ });
155
+
156
+ describe("backdrop click events", () => {
157
+ it("closes sidebar when backdrop is clicked", () => {
158
+ mockCreateMediaQuery.mockReturnValue(() => false); // Mobile
159
+ let setToggle!: Setter<boolean>;
160
+ let toggleValue = false;
161
+
162
+ const { container } = render(() => (
163
+ <ConfigProvider clientName="test"><I18nProvider>
164
+ <Sidebar.Container>
165
+ <ToggleCapture
166
+ onCapture={(fn) => {
167
+ setToggle = fn;
168
+ }}
169
+ />
170
+ <Sidebar>Sidebar Content</Sidebar>
171
+ <div>Content</div>
172
+ </Sidebar.Container>
173
+ </I18nProvider></ConfigProvider>
174
+ ));
175
+
176
+ setToggle(true); // Switch to open state
177
+ // Wrap setToggle to track changes
178
+ const originalSetToggle = setToggle;
179
+ setToggle = ((val: boolean) => {
180
+ toggleValue = val;
181
+ originalSetToggle(val);
182
+ }) as Setter<boolean>;
183
+
184
+ const backdrop = container.querySelector(
185
+ '[role="button"][aria-label="Close sidebar"]',
186
+ ) as HTMLElement;
187
+ expect(backdrop).toBeTruthy();
188
+
189
+ fireEvent.click(backdrop);
190
+
191
+ // Verify toggle changed to false
192
+ expect(toggleValue).toBe(false);
193
+ });
194
+
195
+ it("closes sidebar when Escape key is pressed on backdrop", () => {
196
+ mockCreateMediaQuery.mockReturnValue(() => false); // Mobile
197
+ let setToggle!: Setter<boolean>;
198
+ let toggleValue = false;
199
+
200
+ const { container } = render(() => (
201
+ <ConfigProvider clientName="test"><I18nProvider>
202
+ <Sidebar.Container>
203
+ <ToggleCapture
204
+ onCapture={(fn) => {
205
+ setToggle = fn;
206
+ }}
207
+ />
208
+ <Sidebar>Sidebar Content</Sidebar>
209
+ <div>Content</div>
210
+ </Sidebar.Container>
211
+ </I18nProvider></ConfigProvider>
212
+ ));
213
+
214
+ setToggle(true); // Switch to open state
215
+ // Wrap setToggle to track changes
216
+ const originalSetToggle = setToggle;
217
+ setToggle = ((val: boolean) => {
218
+ toggleValue = val;
219
+ originalSetToggle(val);
220
+ }) as Setter<boolean>;
221
+
222
+ const backdrop = container.querySelector(
223
+ '[role="button"][aria-label="Close sidebar"]',
224
+ ) as HTMLElement;
225
+ expect(backdrop).toBeTruthy();
226
+
227
+ fireEvent.keyDown(backdrop, { key: "Escape" });
228
+
229
+ expect(toggleValue).toBe(false);
230
+ });
231
+ });
232
+
233
+ describe("style merging", () => {
234
+ it("merges custom classes", () => {
235
+ const { container } = render(() => (
236
+ <ConfigProvider clientName="test"><I18nProvider>
237
+ {/* eslint-disable-next-line tailwindcss/no-custom-classname */}
238
+ <Sidebar.Container class="my-custom-class">
239
+ <div>Content</div>
240
+ </Sidebar.Container>
241
+ </I18nProvider></ConfigProvider>
242
+ ));
243
+
244
+ const containerEl = container.firstElementChild as HTMLElement;
245
+ expect(containerEl.classList.contains("my-custom-class")).toBe(true);
246
+ });
247
+
248
+ it("merges custom styles", () => {
249
+ const { container } = render(() => (
250
+ <ConfigProvider clientName="test"><I18nProvider>
251
+ <Sidebar.Container style={{ "background-color": "red" }}>
252
+ <div>Content</div>
253
+ </Sidebar.Container>
254
+ </I18nProvider></ConfigProvider>
255
+ ));
256
+
257
+ const containerEl = container.firstElementChild as HTMLElement;
258
+ expect(containerEl.style.backgroundColor).toBe("red");
259
+ });
260
+ });
261
+ });
@@ -0,0 +1,219 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { render, fireEvent } from "@solidjs/testing-library";
3
+ import { Router } from "@solidjs/router";
4
+ import { Sidebar, type AppMenu } from "../../../../src";
5
+
6
+ // Mock pathname signal
7
+ import { createSignal } from "solid-js";
8
+ const [mockPathname, setMockPathname] = createSignal("/");
9
+
10
+ // Mock useNavigate and useLocation
11
+ const mockNavigate = vi.fn();
12
+ vi.mock("@solidjs/router", async () => {
13
+ const actual = await vi.importActual("@solidjs/router");
14
+ return {
15
+ ...actual,
16
+ useNavigate: () => mockNavigate,
17
+ useLocation: () => ({
18
+ get pathname() {
19
+ return mockPathname();
20
+ },
21
+ }),
22
+ };
23
+ });
24
+
25
+ // window.open mock
26
+ const mockWindowOpen = vi.fn();
27
+
28
+ describe("SidebarMenu", () => {
29
+ beforeEach(() => {
30
+ vi.clearAllMocks();
31
+ setMockPathname("/"); // Initialize pathname
32
+ vi.spyOn(window, "open").mockImplementation(mockWindowOpen);
33
+ // requestAnimationFrame mock (for Collapse animation)
34
+ vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => {
35
+ cb(0);
36
+ return 0;
37
+ });
38
+ });
39
+
40
+ afterEach(() => {
41
+ vi.restoreAllMocks();
42
+ });
43
+
44
+ const renderWithRouter = (menus: AppMenu[]) => {
45
+ return render(() => (
46
+ <Router base="" root={(props) => props.children}>
47
+ {[
48
+ {
49
+ path: "*",
50
+ component: () => <Sidebar.Menu menus={menus} />,
51
+ },
52
+ ]}
53
+ </Router>
54
+ ));
55
+ };
56
+
57
+ describe("rendering", () => {
58
+ it("renders menu items", () => {
59
+ const menus: AppMenu[] = [
60
+ { title: "Dashboard", href: "/dashboard" },
61
+ { title: "Settings", href: "/settings" },
62
+ ];
63
+
64
+ const { getByText } = renderWithRouter(menus);
65
+
66
+ expect(getByText("Dashboard")).toBeTruthy();
67
+ expect(getByText("Settings")).toBeTruthy();
68
+ });
69
+
70
+ it("displays MENU header", () => {
71
+ const menus: AppMenu[] = [{ title: "Home", href: "/" }];
72
+
73
+ const { getByText } = renderWithRouter(menus);
74
+
75
+ expect(getByText("MENU")).toBeTruthy();
76
+ });
77
+
78
+ it("renders nested menu", () => {
79
+ const menus: AppMenu[] = [
80
+ {
81
+ title: "Settings",
82
+ children: [
83
+ { title: "Profile", href: "/settings/profile" },
84
+ { title: "Security", href: "/settings/security" },
85
+ ],
86
+ },
87
+ ];
88
+
89
+ const { getByText } = renderWithRouter(menus);
90
+
91
+ expect(getByText("Settings")).toBeTruthy();
92
+ });
93
+
94
+ it("renders menu with icon", () => {
95
+ const MockIcon = (props: { class?: string }) => (
96
+ <svg data-testid="mock-icon" class={props.class} />
97
+ );
98
+
99
+ const menus: AppMenu[] = [{ title: "Dashboard", href: "/dashboard", icon: MockIcon }];
100
+
101
+ const { container } = renderWithRouter(menus);
102
+
103
+ expect(container.querySelector("[data-testid='mock-icon']")).toBeTruthy();
104
+ });
105
+ });
106
+
107
+ describe("link behavior", () => {
108
+ it("navigates using SPA routing on internal link click", () => {
109
+ const menus: AppMenu[] = [{ title: "Dashboard", href: "/dashboard" }];
110
+
111
+ const { getByText } = renderWithRouter(menus);
112
+
113
+ fireEvent.click(getByText("Dashboard"));
114
+
115
+ expect(mockNavigate).toHaveBeenCalledWith("/dashboard");
116
+ });
117
+
118
+ it("opens external link in new tab on click", () => {
119
+ const menus: AppMenu[] = [{ title: "External Link", href: "https://example.com" }];
120
+
121
+ const { getByText } = renderWithRouter(menus);
122
+
123
+ fireEvent.click(getByText("External Link"));
124
+
125
+ expect(mockWindowOpen).toHaveBeenCalledWith(
126
+ "https://example.com",
127
+ "_blank",
128
+ "noopener,noreferrer",
129
+ );
130
+ });
131
+ });
132
+
133
+ describe("expand/collapse behavior", () => {
134
+ it("toggles expanded when clicking menu with children", () => {
135
+ const menus: AppMenu[] = [
136
+ {
137
+ title: "Settings",
138
+ children: [{ title: "Profile", href: "/settings/profile" }],
139
+ },
140
+ ];
141
+
142
+ const { getByText, container } = renderWithRouter(menus);
143
+
144
+ // Initial state: collapsed
145
+ const listItem = container.querySelector("[data-list-item]") as HTMLElement;
146
+ expect(listItem.getAttribute("aria-expanded")).toBe("false");
147
+
148
+ // After click: expanded
149
+ fireEvent.click(getByText("Settings"));
150
+ expect(listItem.getAttribute("aria-expanded")).toBe("true");
151
+ });
152
+ });
153
+
154
+ describe("pathname reactivity", () => {
155
+ it("automatically expands parent menu when pathname matches nested menu", () => {
156
+ // Set initial pathname to nested menu path
157
+ setMockPathname("/settings/profile");
158
+
159
+ const menus: AppMenu[] = [
160
+ { title: "Dashboard", href: "/dashboard" },
161
+ {
162
+ title: "Settings",
163
+ children: [
164
+ { title: "Profile", href: "/settings/profile" },
165
+ { title: "Security", href: "/settings/security" },
166
+ ],
167
+ },
168
+ ];
169
+
170
+ const { container } = renderWithRouter(menus);
171
+
172
+ // "Settings" menu should automatically expand
173
+ const settingsItem = container.querySelectorAll("[data-list-item]")[1] as HTMLElement;
174
+ expect(settingsItem.getAttribute("aria-expanded")).toBe("true");
175
+ });
176
+
177
+ it("expands parent menu of matching pathname when pathname changes", () => {
178
+ const menus: AppMenu[] = [
179
+ { title: "Dashboard", href: "/dashboard" },
180
+ {
181
+ title: "Settings",
182
+ children: [{ title: "Profile", href: "/settings/profile" }],
183
+ },
184
+ ];
185
+
186
+ const { container } = renderWithRouter(menus);
187
+
188
+ // Initial state: Settings menu collapsed
189
+ const settingsItem = container.querySelectorAll("[data-list-item]")[1] as HTMLElement;
190
+ expect(settingsItem.getAttribute("aria-expanded")).toBe("false");
191
+
192
+ // Change pathname
193
+ setMockPathname("/settings/profile");
194
+
195
+ // Settings menu should expand
196
+ expect(settingsItem.getAttribute("aria-expanded")).toBe("true");
197
+ });
198
+ });
199
+
200
+ describe("style merging", () => {
201
+ it("merges custom classes", () => {
202
+ const menus: AppMenu[] = [{ title: "Home", href: "/" }];
203
+
204
+ const { container } = render(() => (
205
+ <Router base="" root={(props) => props.children}>
206
+ {[
207
+ {
208
+ path: "*",
209
+ // eslint-disable-next-line tailwindcss/no-custom-classname
210
+ component: () => <Sidebar.Menu menus={menus} class="my-custom-class" />,
211
+ },
212
+ ]}
213
+ </Router>
214
+ ));
215
+
216
+ expect(container.querySelector(".my-custom-class")).toBeTruthy();
217
+ });
218
+ });
219
+ });
@@ -0,0 +1,133 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { render, fireEvent } from "@solidjs/testing-library";
3
+ import { Sidebar, type SidebarUserMenu } from "../../../../src";
4
+
5
+ describe("SidebarUser", () => {
6
+ beforeEach(() => {
7
+ // requestAnimationFrame mock (for Collapse animation)
8
+ vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => {
9
+ cb(0);
10
+ return 0;
11
+ });
12
+ });
13
+
14
+ afterEach(() => {
15
+ vi.restoreAllMocks();
16
+ });
17
+
18
+ describe("rendering", () => {
19
+ it("renders name prop", () => {
20
+ const { getByText } = render(() => <Sidebar.User name="User Name" />);
21
+
22
+ expect(getByText("User Name")).toBeTruthy();
23
+ });
24
+
25
+ it("does not have aria-expanded when menus are not provided", () => {
26
+ const { container } = render(() => <Sidebar.User name="User" />);
27
+
28
+ const button = container.querySelector("button");
29
+ expect(button?.hasAttribute("aria-expanded")).toBe(false);
30
+ });
31
+
32
+ it("has aria-expanded=false when menus are provided", () => {
33
+ const menus: SidebarUserMenu[] = [{ title: "Logout", onClick: () => {} }];
34
+
35
+ const { container } = render(() => <Sidebar.User name="User" menus={menus} />);
36
+
37
+ const button = container.querySelector("button");
38
+ expect(button?.getAttribute("aria-expanded")).toBe("false");
39
+ });
40
+ });
41
+
42
+ describe("click behavior", () => {
43
+ it("does not open dropdown when clicked without menus", () => {
44
+ const { container } = render(() => <Sidebar.User name="User" />);
45
+
46
+ const button = container.querySelector("button")!;
47
+ fireEvent.click(button);
48
+
49
+ // aria-expanded not present or unchanged
50
+ expect(button.hasAttribute("aria-expanded")).toBe(false);
51
+ });
52
+
53
+ it("toggles dropdown when clicked with menus", () => {
54
+ const menus: SidebarUserMenu[] = [{ title: "Logout", onClick: () => {} }];
55
+
56
+ const { container } = render(() => <Sidebar.User name="User" menus={menus} />);
57
+
58
+ const button = container.querySelector("button")!;
59
+
60
+ // Initial state: closed
61
+ expect(button.getAttribute("aria-expanded")).toBe("false");
62
+
63
+ // First click: open
64
+ fireEvent.click(button);
65
+ expect(button.getAttribute("aria-expanded")).toBe("true");
66
+
67
+ // Second click: close
68
+ fireEvent.click(button);
69
+ expect(button.getAttribute("aria-expanded")).toBe("false");
70
+ });
71
+ });
72
+
73
+ describe("menu item click", () => {
74
+ it("calls onClick when menu item is clicked", () => {
75
+ const onLogout = vi.fn();
76
+ const menus: SidebarUserMenu[] = [{ title: "Logout", onClick: onLogout }];
77
+
78
+ const { container, getByText } = render(() => <Sidebar.User name="User" menus={menus} />);
79
+
80
+ // Open dropdown
81
+ const button = container.querySelector("button")!;
82
+ fireEvent.click(button);
83
+
84
+ // Click menu item
85
+ fireEvent.click(getByText("Logout"));
86
+
87
+ expect(onLogout).toHaveBeenCalledTimes(1);
88
+ });
89
+
90
+ it("closes dropdown when menu item is clicked", () => {
91
+ const menus: SidebarUserMenu[] = [{ title: "Profile", onClick: () => {} }];
92
+
93
+ const { container, getByText } = render(() => <Sidebar.User name="User" menus={menus} />);
94
+
95
+ const button = container.querySelector("button")!;
96
+
97
+ // Open dropdown
98
+ fireEvent.click(button);
99
+ expect(button.getAttribute("aria-expanded")).toBe("true");
100
+
101
+ // Click menu item
102
+ fireEvent.click(getByText("Profile"));
103
+
104
+ // Dropdown closed
105
+ expect(button.getAttribute("aria-expanded")).toBe("false");
106
+ });
107
+ });
108
+
109
+ describe("styles based on menu presence", () => {
110
+ it("styles differ based on menus prop", () => {
111
+ const menus: SidebarUserMenu[] = [{ title: "Logout", onClick: () => {} }];
112
+
113
+ const { container: withoutMenus } = render(() => <Sidebar.User name="User" />);
114
+ const { container: withMenus } = render(() => <Sidebar.User name="User" menus={menus} />);
115
+
116
+ const buttonWithout = withoutMenus.querySelector("button")!;
117
+ const buttonWith = withMenus.querySelector("button")!;
118
+
119
+ expect(buttonWithout.className).not.toBe(buttonWith.className);
120
+ });
121
+ });
122
+
123
+ describe("style merging", () => {
124
+ it("merges custom classes", () => {
125
+ const { container } = render(() => (
126
+ // eslint-disable-next-line tailwindcss/no-custom-classname
127
+ <Sidebar.User name="User" class="my-custom-class" />
128
+ ));
129
+
130
+ expect(container.querySelector(".my-custom-class")).toBeTruthy();
131
+ });
132
+ });
133
+ });
@@ -0,0 +1,77 @@
1
+ import { render, cleanup } from "@solidjs/testing-library";
2
+ import { describe, it, expect, afterEach } from "vitest";
3
+ import { createSignal, Show } from "solid-js";
4
+ import { Topbar, createTopbarActions } from "../../../../src";
5
+
6
+ describe("Topbar.Actions component", () => {
7
+ afterEach(() => {
8
+ cleanup();
9
+ });
10
+
11
+ it("renders registered actions at Topbar.Actions position", () => {
12
+ function PageWithActions() {
13
+ createTopbarActions(() => <button>Save</button>);
14
+ return <div>Page Content</div>;
15
+ }
16
+
17
+ const { getByText } = render(() => (
18
+ <Topbar.Container>
19
+ <Topbar>
20
+ <span>Title</span>
21
+ <Topbar.Actions />
22
+ </Topbar>
23
+ <PageWithActions />
24
+ </Topbar.Container>
25
+ ));
26
+
27
+ expect(getByText("Save")).toBeTruthy();
28
+ });
29
+
30
+ it("renders nothing when actions are not provided", () => {
31
+ const { container } = render(() => (
32
+ <Topbar.Container>
33
+ <Topbar>
34
+ <span>Title</span>
35
+ <Topbar.Actions />
36
+ </Topbar>
37
+ <div>Content</div>
38
+ </Topbar.Container>
39
+ ));
40
+
41
+ const actionsSlot = container.querySelector("[data-topbar-actions]");
42
+ expect(actionsSlot?.childNodes.length ?? 0).toBe(0);
43
+ });
44
+
45
+ it("releases previous actions and displays new actions when switching components", () => {
46
+ function PageA() {
47
+ createTopbarActions(() => <button>Save</button>);
48
+ return <div>Page A</div>;
49
+ }
50
+
51
+ function PageB() {
52
+ createTopbarActions(() => <button>Delete</button>);
53
+ return <div>Page B</div>;
54
+ }
55
+
56
+ const [page, setPage] = createSignal<"a" | "b">("a");
57
+
58
+ const { getByText, queryByText } = render(() => (
59
+ <Topbar.Container>
60
+ <Topbar>
61
+ <Topbar.Actions />
62
+ </Topbar>
63
+ <Show when={page() === "a"} fallback={<PageB />}>
64
+ <PageA />
65
+ </Show>
66
+ </Topbar.Container>
67
+ ));
68
+
69
+ expect(getByText("Save")).toBeTruthy();
70
+ expect(queryByText("Delete")).toBeNull();
71
+
72
+ setPage("b");
73
+
74
+ expect(queryByText("Save")).toBeNull();
75
+ expect(getByText("Delete")).toBeTruthy();
76
+ });
77
+ });