@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,315 @@
1
+ import { render, fireEvent } from "@solidjs/testing-library";
2
+ import { describe, it, expect, vi } from "vitest";
3
+ import { createSignal } from "solid-js";
4
+ import { Time } from "@simplysm/core-common";
5
+ import { TimePicker } from "../../../../src/components/form-control/field/TimePicker";
6
+
7
+ describe("TimePicker component", () => {
8
+ describe("basic rendering", () => {
9
+ it("renders input type=time when unit=minute", () => {
10
+ const { container } = render(() => <TimePicker unit="minute" />);
11
+ const input = container.querySelector("input") as HTMLInputElement;
12
+ expect(input).toBeTruthy();
13
+ expect(input.type).toBe("time");
14
+ });
15
+
16
+ it("renders input type=time when unit=second", () => {
17
+ const { container } = render(() => <TimePicker unit="second" />);
18
+ const input = container.querySelector("input") as HTMLInputElement;
19
+ expect(input).toBeTruthy();
20
+ expect(input.type).toBe("time");
21
+ });
22
+
23
+ it("defaults unit to minute", () => {
24
+ const { container } = render(() => <TimePicker />);
25
+ const input = container.querySelector("input") as HTMLInputElement;
26
+ expect(input.type).toBe("time");
27
+ });
28
+
29
+ it("defaults autocomplete to one-time-code", () => {
30
+ const { container } = render(() => <TimePicker />);
31
+ const input = container.querySelector("input") as HTMLInputElement;
32
+ expect(input.autocomplete).toBe("one-time-code");
33
+ });
34
+
35
+ it("sets step=1 when unit=second", () => {
36
+ const { container } = render(() => <TimePicker unit="second" />);
37
+ const input = container.querySelector("input") as HTMLInputElement;
38
+ expect(input.step).toBe("1");
39
+ });
40
+
41
+ it("does not set step when unit=minute", () => {
42
+ const { container } = render(() => <TimePicker unit="minute" />);
43
+ const input = container.querySelector("input") as HTMLInputElement;
44
+ expect(input.step).toBe("");
45
+ });
46
+ });
47
+
48
+ describe("value conversion", () => {
49
+ it("displays Time in HH:mm format for minute unit", () => {
50
+ const time = new Time(10, 30, 45);
51
+ const { container } = render(() => <TimePicker unit="minute" value={time} />);
52
+ const input = container.querySelector("input") as HTMLInputElement;
53
+ expect(input.value).toBe("10:30");
54
+ });
55
+
56
+ it("displays Time in HH:mm:ss format for second unit", () => {
57
+ const time = new Time(10, 30, 45);
58
+ const { container } = render(() => <TimePicker unit="second" value={time} />);
59
+ const input = container.querySelector("input") as HTMLInputElement;
60
+ expect(input.value).toBe("10:30:45");
61
+ });
62
+
63
+ it("passes Time converted from minute input to onValueChange", () => {
64
+ const handleChange = vi.fn();
65
+ const { container } = render(() => <TimePicker unit="minute" onValueChange={handleChange} />);
66
+ const input = container.querySelector("input") as HTMLInputElement;
67
+
68
+ fireEvent.change(input, { target: { value: "10:30" } });
69
+
70
+ expect(handleChange).toHaveBeenCalledTimes(1);
71
+ const result = handleChange.mock.calls[0][0] as Time;
72
+ expect(result.hour).toBe(10);
73
+ expect(result.minute).toBe(30);
74
+ expect(result.second).toBe(0);
75
+ });
76
+
77
+ it("passes Time converted from second input to onValueChange", () => {
78
+ const handleChange = vi.fn();
79
+ const { container } = render(() => <TimePicker unit="second" onValueChange={handleChange} />);
80
+ const input = container.querySelector("input") as HTMLInputElement;
81
+
82
+ fireEvent.change(input, { target: { value: "10:30:45" } });
83
+
84
+ expect(handleChange).toHaveBeenCalledTimes(1);
85
+ const result = handleChange.mock.calls[0][0] as Time;
86
+ expect(result.hour).toBe(10);
87
+ expect(result.minute).toBe(30);
88
+ expect(result.second).toBe(45);
89
+ });
90
+
91
+ it("passes undefined to onValueChange on empty input", () => {
92
+ const handleChange = vi.fn();
93
+ const time = new Time(10, 30, 45);
94
+ const { container } = render(() => (
95
+ <TimePicker unit="minute" value={time} onValueChange={handleChange} />
96
+ ));
97
+ const input = container.querySelector("input") as HTMLInputElement;
98
+
99
+ fireEvent.change(input, { target: { value: "" } });
100
+
101
+ expect(handleChange).toHaveBeenCalledWith(undefined);
102
+ });
103
+ });
104
+
105
+ describe("controlled pattern", () => {
106
+ it("updates input value when external state changes", () => {
107
+ const [value, setValue] = createSignal<Time | undefined>(new Time(10, 0, 0));
108
+ const { container } = render(() => (
109
+ <TimePicker unit="minute" value={value()} onValueChange={setValue} />
110
+ ));
111
+ const input = container.querySelector("input") as HTMLInputElement;
112
+
113
+ expect(input.value).toBe("10:00");
114
+
115
+ setValue(new Time(23, 59, 0));
116
+ expect(input.value).toBe("23:59");
117
+ });
118
+ });
119
+
120
+ describe("uncontrolled pattern", () => {
121
+ it("manages value internally without onValueChange", () => {
122
+ const { container } = render(() => <TimePicker unit="minute" value={new Time(10, 0, 0)} />);
123
+ const input = container.querySelector("input") as HTMLInputElement;
124
+
125
+ expect(input.value).toBe("10:00");
126
+
127
+ fireEvent.change(input, { target: { value: "14:30" } });
128
+ expect(input.value).toBe("14:30");
129
+ });
130
+ });
131
+
132
+ describe("disabled state", () => {
133
+ it("renders as div when disabled=true", () => {
134
+ const { container } = render(() => <TimePicker disabled value={new Time(10, 30, 0)} />);
135
+ const input = container.querySelector("input:not([aria-hidden])");
136
+ const div = container.querySelector("div.sd-time-field");
137
+
138
+ expect(input).toBeFalsy();
139
+ expect(div).toBeTruthy();
140
+ });
141
+
142
+ it("displays value when disabled", () => {
143
+ const { getByText } = render(() => (
144
+ <TimePicker unit="minute" disabled value={new Time(10, 30, 0)} />
145
+ ));
146
+ expect(getByText("10:30")).toBeTruthy();
147
+ });
148
+
149
+ it("applies disabled style", () => {
150
+ const { container } = render(() => <TimePicker disabled value={new Time(10, 30, 0)} />);
151
+ const div = container.querySelector("div.sd-time-field") as HTMLElement;
152
+ expect(div.classList.contains("bg-base-100")).toBe(true);
153
+ });
154
+ });
155
+
156
+ describe("readonly state", () => {
157
+ it("renders as div when readonly=true", () => {
158
+ const { container } = render(() => <TimePicker readonly value={new Time(10, 30, 0)} />);
159
+ const input = container.querySelector("input:not([aria-hidden])");
160
+ const div = container.querySelector("div.sd-time-field");
161
+
162
+ expect(input).toBeFalsy();
163
+ expect(div).toBeTruthy();
164
+ });
165
+
166
+ it("displays value when readonly", () => {
167
+ const { getByText } = render(() => (
168
+ <TimePicker unit="minute" readonly value={new Time(10, 30, 0)} />
169
+ ));
170
+ expect(getByText("10:30")).toBeTruthy();
171
+ });
172
+ });
173
+
174
+ describe("size option", () => {
175
+ it("applies small padding when size=sm", () => {
176
+ const { container } = render(() => <TimePicker size="sm" />);
177
+ const wrapper = container.firstChild as HTMLElement;
178
+ expect(wrapper.classList.contains("py-0.5")).toBe(true);
179
+ });
180
+
181
+ it("applies large padding when size=lg", () => {
182
+ const { container } = render(() => <TimePicker size="lg" />);
183
+ const wrapper = container.firstChild as HTMLElement;
184
+ expect(wrapper.classList.contains("py-2")).toBe(true);
185
+ });
186
+ });
187
+
188
+ describe("inset style", () => {
189
+ it("applies relative to outer and inset style to content when inset=true", () => {
190
+ const { container } = render(() => <TimePicker inset />);
191
+ const outer = container.firstChild as HTMLElement;
192
+ expect(outer.classList.contains("relative")).toBe(true);
193
+ expect(outer.classList.contains("border-none")).toBe(false);
194
+
195
+ const contentDiv = outer.querySelector("[data-time-field-content]") as HTMLElement;
196
+ expect(contentDiv.classList.contains("border-none")).toBe(true);
197
+ expect(contentDiv.classList.contains("bg-primary-50")).toBe(true);
198
+ });
199
+
200
+ it("shows content div and no input when inset + readonly", () => {
201
+ const { container } = render(() => <TimePicker inset readonly value={new Time(14, 30, 0)} />);
202
+ const outer = container.firstChild as HTMLElement;
203
+ expect(outer.classList.contains("relative")).toBe(true);
204
+
205
+ const contentDiv = outer.querySelector("[data-time-field-content]") as HTMLElement;
206
+ expect(contentDiv).toBeTruthy();
207
+ expect(contentDiv.textContent).toBe("14:30");
208
+
209
+ expect(outer.querySelector("input:not([aria-hidden])")).toBeFalsy();
210
+ });
211
+
212
+ it("shows hidden content div and input when inset + editable", () => {
213
+ const { container } = render(() => <TimePicker inset value={new Time(14, 30, 0)} />);
214
+ const outer = container.firstChild as HTMLElement;
215
+
216
+ const contentDiv = outer.querySelector("[data-time-field-content]") as HTMLElement;
217
+ expect(contentDiv).toBeTruthy();
218
+ expect(contentDiv.style.visibility).toBe("hidden");
219
+
220
+ expect(outer.querySelector("input")).toBeTruthy();
221
+ });
222
+
223
+ it("shows NBSP in content div when inset + empty value", () => {
224
+ const { container } = render(() => <TimePicker inset readonly />);
225
+ const outer = container.firstChild as HTMLElement;
226
+ const contentDiv = outer.querySelector("[data-time-field-content]") as HTMLElement;
227
+ expect(contentDiv.textContent).toBe("\u00A0");
228
+ });
229
+ });
230
+
231
+ describe("dark mode style", () => {
232
+ it("applies dark mode border style", () => {
233
+ const { container } = render(() => <TimePicker />);
234
+ const wrapper = container.firstChild as HTMLElement;
235
+ expect(wrapper.classList.contains("dark:border-base-700")).toBe(true);
236
+ });
237
+
238
+ it("applies dark mode background style", () => {
239
+ const { container } = render(() => <TimePicker />);
240
+ const wrapper = container.firstChild as HTMLElement;
241
+ expect(wrapper.classList.contains("dark:bg-primary-950/30")).toBe(true);
242
+ });
243
+ });
244
+
245
+ describe("class merging", () => {
246
+ it("merges custom class with existing styles", () => {
247
+ // eslint-disable-next-line tailwindcss/no-custom-classname
248
+ const { container } = render(() => <TimePicker class="my-custom-class" />);
249
+ const wrapper = container.firstChild as HTMLElement;
250
+ expect(wrapper.classList.contains("my-custom-class")).toBe(true);
251
+ });
252
+ });
253
+
254
+ describe("validation", () => {
255
+ it("sets error message when required and value is empty", () => {
256
+ const { container } = render(() => <TimePicker required value={undefined} />);
257
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
258
+ expect(hiddenInput.validationMessage).toBe("This field is required");
259
+ });
260
+
261
+ it("is valid when required and value exists", () => {
262
+ const { container } = render(() => <TimePicker required value={new Time(10, 0, 0)} />);
263
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
264
+ expect(hiddenInput.validity.valid).toBe(true);
265
+ });
266
+
267
+ it("sets error message when min is violated", () => {
268
+ const { container } = render(() => (
269
+ <TimePicker min={new Time(12, 0, 0)} value={new Time(8, 0, 0)} />
270
+ ));
271
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
272
+ expect(hiddenInput.validationMessage).not.toBe("");
273
+ });
274
+
275
+ it("is valid when min is satisfied", () => {
276
+ const { container } = render(() => (
277
+ <TimePicker min={new Time(8, 0, 0)} value={new Time(12, 0, 0)} />
278
+ ));
279
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
280
+ expect(hiddenInput.validity.valid).toBe(true);
281
+ });
282
+
283
+ it("sets error message when max is violated", () => {
284
+ const { container } = render(() => (
285
+ <TimePicker max={new Time(12, 0, 0)} value={new Time(18, 0, 0)} />
286
+ ));
287
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
288
+ expect(hiddenInput.validationMessage).not.toBe("");
289
+ });
290
+
291
+ it("is valid when max is satisfied", () => {
292
+ const { container } = render(() => (
293
+ <TimePicker max={new Time(23, 59, 59)} value={new Time(12, 0, 0)} />
294
+ ));
295
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
296
+ expect(hiddenInput.validity.valid).toBe(true);
297
+ });
298
+
299
+ it("sets error message returned by validate function", () => {
300
+ const { container } = render(() => (
301
+ <TimePicker value={new Time(10, 0, 0)} validate={() => "커스텀 에러"} />
302
+ ));
303
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
304
+ expect(hiddenInput.validationMessage).toBe("커스텀 에러");
305
+ });
306
+
307
+ it("is valid when validate function returns undefined", () => {
308
+ const { container } = render(() => (
309
+ <TimePicker value={new Time(10, 0, 0)} validate={() => undefined} />
310
+ ));
311
+ const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
312
+ expect(hiddenInput.validity.valid).toBe(true);
313
+ });
314
+ });
315
+ });
@@ -0,0 +1,248 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { render, fireEvent, screen } from "@solidjs/testing-library";
3
+ import { createSignal } from "solid-js";
4
+ import { Numpad } from "../../../../src/components/form-control/numpad/Numpad";
5
+
6
+ describe("Numpad", () => {
7
+ describe("basic rendering", () => {
8
+ it("renders root element with data-numpad attribute", () => {
9
+ const { container } = render(() => <Numpad />);
10
+ const root = container.querySelector("[data-numpad]");
11
+ expect(root).toBeTruthy();
12
+ });
13
+
14
+ it("renders digit buttons 0-9", () => {
15
+ render(() => <Numpad />);
16
+
17
+ for (let i = 0; i <= 9; i++) {
18
+ expect(screen.getByText(String(i))).toBeInTheDocument();
19
+ }
20
+ });
21
+
22
+ it("renders decimal point button", () => {
23
+ render(() => <Numpad />);
24
+ expect(screen.getByText(".")).toBeInTheDocument();
25
+ });
26
+
27
+ it("renders NumberInput (input)", () => {
28
+ render(() => <Numpad />);
29
+ const input = screen.getByRole("textbox");
30
+ expect(input).toBeInTheDocument();
31
+ });
32
+
33
+ it("renders C button with text-danger-500 class", () => {
34
+ render(() => <Numpad />);
35
+ const cButton = screen
36
+ .getAllByRole("button")
37
+ .find((btn) => btn.className.includes("text-danger-500"));
38
+ expect(cButton).toBeTruthy();
39
+ });
40
+
41
+ it("renders BS button with text-warning-500 class", () => {
42
+ render(() => <Numpad />);
43
+ const bsButton = screen
44
+ .getAllByRole("button")
45
+ .find((btn) => btn.className.includes("text-warning-500"));
46
+ expect(bsButton).toBeTruthy();
47
+ });
48
+
49
+ it("does not render ENT button by default", () => {
50
+ render(() => <Numpad />);
51
+ expect(screen.queryByText("ENT")).not.toBeInTheDocument();
52
+ });
53
+
54
+ it("does not render minus button by default", () => {
55
+ render(() => <Numpad />);
56
+ // without useMinusButton, there should be no button with "-" text
57
+ const minusButton = screen.getAllByRole("button").find((btn) => btn.textContent === "-");
58
+ expect(minusButton).toBeFalsy();
59
+ });
60
+ });
61
+
62
+ describe("digit input", () => {
63
+ it("updates value on digit button click", () => {
64
+ const handleChange = vi.fn();
65
+ render(() => <Numpad onValueChange={handleChange} />);
66
+
67
+ fireEvent.click(screen.getByText("1"));
68
+ fireEvent.click(screen.getByText("2"));
69
+ fireEvent.click(screen.getByText("3"));
70
+
71
+ expect(handleChange).toHaveBeenLastCalledWith(123);
72
+ });
73
+
74
+ it("appends decimal point on decimal button click", () => {
75
+ const handleChange = vi.fn();
76
+ render(() => <Numpad onValueChange={handleChange} />);
77
+
78
+ fireEvent.click(screen.getByText("1"));
79
+ fireEvent.click(screen.getByText("."));
80
+ fireEvent.click(screen.getByText("5"));
81
+
82
+ expect(handleChange).toHaveBeenLastCalledWith(1.5);
83
+ });
84
+
85
+ it("ignores duplicate decimal point", () => {
86
+ const handleChange = vi.fn();
87
+ render(() => <Numpad onValueChange={handleChange} />);
88
+
89
+ fireEvent.click(screen.getByText("1"));
90
+ fireEvent.click(screen.getByText("."));
91
+ fireEvent.click(screen.getByText(".")); // duplicate decimal
92
+ fireEvent.click(screen.getByText("5"));
93
+
94
+ expect(handleChange).toHaveBeenLastCalledWith(1.5);
95
+ });
96
+
97
+ it("allows clicking 0 multiple times", () => {
98
+ const handleChange = vi.fn();
99
+ render(() => <Numpad onValueChange={handleChange} />);
100
+
101
+ fireEvent.click(screen.getByText("1"));
102
+ fireEvent.click(screen.getByText("0"));
103
+ fireEvent.click(screen.getByText("0"));
104
+
105
+ expect(handleChange).toHaveBeenLastCalledWith(100);
106
+ });
107
+ });
108
+
109
+ describe("function buttons", () => {
110
+ it("clears value on C button click", () => {
111
+ const handleChange = vi.fn();
112
+ render(() => <Numpad onValueChange={handleChange} />);
113
+
114
+ // enter value
115
+ fireEvent.click(screen.getByText("5"));
116
+ fireEvent.click(screen.getByText("6"));
117
+
118
+ // click C button
119
+ const cButton = screen
120
+ .getAllByRole("button")
121
+ .find((btn) => btn.className.includes("text-danger-500"))!;
122
+ fireEvent.click(cButton);
123
+
124
+ expect(handleChange).toHaveBeenLastCalledWith(undefined);
125
+ });
126
+
127
+ it("removes last character on BS button click", () => {
128
+ const handleChange = vi.fn();
129
+ render(() => <Numpad onValueChange={handleChange} />);
130
+
131
+ // enter 123
132
+ fireEvent.click(screen.getByText("1"));
133
+ fireEvent.click(screen.getByText("2"));
134
+ fireEvent.click(screen.getByText("3"));
135
+
136
+ // click BS button
137
+ const bsButton = screen
138
+ .getAllByRole("button")
139
+ .find((btn) => btn.className.includes("text-warning-500"))!;
140
+ fireEvent.click(bsButton);
141
+
142
+ expect(handleChange).toHaveBeenLastCalledWith(12);
143
+ });
144
+
145
+ it("returns undefined when all characters are removed with BS", () => {
146
+ const handleChange = vi.fn();
147
+ render(() => <Numpad onValueChange={handleChange} />);
148
+
149
+ // enter 1
150
+ fireEvent.click(screen.getByText("1"));
151
+
152
+ // click BS button
153
+ const bsButton = screen
154
+ .getAllByRole("button")
155
+ .find((btn) => btn.className.includes("text-warning-500"))!;
156
+ fireEvent.click(bsButton);
157
+
158
+ expect(handleChange).toHaveBeenLastCalledWith(undefined);
159
+ });
160
+ });
161
+
162
+ describe("ENT button", () => {
163
+ it("renders ENT button when useEnterButton=true", () => {
164
+ render(() => <Numpad useEnterButton />);
165
+ expect(screen.getByText("ENT")).toBeInTheDocument();
166
+ });
167
+
168
+ it("calls onEnterButtonClick on ENT button click", () => {
169
+ const handleEnter = vi.fn();
170
+ render(() => <Numpad useEnterButton onEnterButtonClick={handleEnter} />);
171
+
172
+ fireEvent.click(screen.getByText("ENT"));
173
+ expect(handleEnter).toHaveBeenCalledTimes(1);
174
+ });
175
+
176
+ it("disables ENT button when required and no value", () => {
177
+ render(() => <Numpad useEnterButton required />);
178
+
179
+ const entButton = screen.getByText("ENT").closest("button")!;
180
+ expect(entButton.disabled).toBe(true);
181
+ });
182
+
183
+ it("enables ENT button when required and value exists", () => {
184
+ render(() => <Numpad useEnterButton required value={123} />);
185
+
186
+ const entButton = screen.getByText("ENT").closest("button")!;
187
+ expect(entButton.disabled).toBe(false);
188
+ });
189
+ });
190
+
191
+ describe("minus button", () => {
192
+ it("renders minus button when useMinusButton=true", () => {
193
+ render(() => <Numpad useMinusButton />);
194
+
195
+ const minusButton = screen.getAllByRole("button").find((btn) => btn.textContent === "-");
196
+ expect(minusButton).toBeTruthy();
197
+ });
198
+
199
+ it("toggles sign on minus button click (positive to negative)", () => {
200
+ const handleChange = vi.fn();
201
+ render(() => <Numpad useMinusButton onValueChange={handleChange} />);
202
+
203
+ // enter 5
204
+ fireEvent.click(screen.getByText("5"));
205
+
206
+ // click minus button
207
+ const minusButton = screen.getAllByRole("button").find((btn) => btn.textContent === "-")!;
208
+ fireEvent.click(minusButton);
209
+
210
+ expect(handleChange).toHaveBeenLastCalledWith(-5);
211
+ });
212
+
213
+ it("toggles sign on minus button click (negative to positive)", () => {
214
+ const handleChange = vi.fn();
215
+ render(() => <Numpad useMinusButton value={-5} onValueChange={handleChange} />);
216
+
217
+ // click minus button
218
+ const minusButton = screen.getAllByRole("button").find((btn) => btn.textContent === "-")!;
219
+ fireEvent.click(minusButton);
220
+
221
+ expect(handleChange).toHaveBeenLastCalledWith(5);
222
+ });
223
+ });
224
+
225
+ describe("controlled mode", () => {
226
+ it("reflects external value changes", () => {
227
+ const [value, setValue] = createSignal<number | undefined>(100);
228
+ render(() => <Numpad value={value()} onValueChange={setValue} />);
229
+
230
+ const input = screen.getByRole("textbox");
231
+ expect(input).toHaveValue("100");
232
+
233
+ setValue(200);
234
+ expect(input).toHaveValue("200");
235
+ });
236
+
237
+ it("clears input when set to undefined externally", () => {
238
+ const [value, setValue] = createSignal<number | undefined>(100);
239
+ render(() => <Numpad value={value()} onValueChange={setValue} />);
240
+
241
+ const input = screen.getByRole("textbox");
242
+ expect(input).toHaveValue("100");
243
+
244
+ setValue(undefined);
245
+ expect(input).toHaveValue("");
246
+ });
247
+ });
248
+ });