@simplysm/solid 13.0.28 → 13.0.30

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 (379) hide show
  1. package/README.md +15 -9
  2. package/dist/components/data/Pagination.d.ts +4 -5
  3. package/dist/components/data/Pagination.d.ts.map +1 -1
  4. package/dist/components/data/Pagination.js +14 -14
  5. package/dist/components/data/Pagination.js.map +2 -2
  6. package/dist/components/data/Table.js +1 -1
  7. package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
  8. package/dist/components/data/calendar/Calendar.js +1 -1
  9. package/dist/components/data/calendar/Calendar.js.map +1 -1
  10. package/dist/components/data/kanban/Kanban.d.ts +9 -9
  11. package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
  12. package/dist/components/data/kanban/Kanban.js +6 -6
  13. package/dist/components/data/kanban/Kanban.js.map +2 -2
  14. package/dist/components/data/list/List.d.ts.map +1 -1
  15. package/dist/components/data/list/List.js.map +1 -1
  16. package/dist/components/data/list/ListItem.d.ts.map +1 -1
  17. package/dist/components/data/list/ListItem.js.map +1 -1
  18. package/dist/components/data/permission-table/PermissionTable.d.ts.map +1 -1
  19. package/dist/components/data/permission-table/PermissionTable.js.map +1 -1
  20. package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
  21. package/dist/components/data/sheet/DataSheet.js +102 -107
  22. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  23. package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
  24. package/dist/components/data/sheet/DataSheet.styles.js +24 -6
  25. package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
  26. package/dist/components/data/sheet/DataSheetColumn.d.ts.map +1 -1
  27. package/dist/components/data/sheet/DataSheetColumn.js.map +1 -1
  28. package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
  29. package/dist/components/data/sheet/DataSheetConfigDialog.js.map +1 -1
  30. package/dist/components/data/sheet/sheetUtils.d.ts.map +1 -1
  31. package/dist/components/data/sheet/sheetUtils.js.map +1 -1
  32. package/dist/components/data/sheet/types.d.ts +2 -2
  33. package/dist/components/data/sheet/types.d.ts.map +1 -1
  34. package/dist/components/disclosure/Collapse.d.ts.map +1 -1
  35. package/dist/components/disclosure/Collapse.js +0 -3
  36. package/dist/components/disclosure/Collapse.js.map +1 -1
  37. package/dist/components/disclosure/Dialog.d.ts +8 -8
  38. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  39. package/dist/components/disclosure/Dialog.js +64 -69
  40. package/dist/components/disclosure/Dialog.js.map +2 -2
  41. package/dist/components/disclosure/DialogContext.d.ts +4 -4
  42. package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
  43. package/dist/components/disclosure/DialogContext.js.map +1 -1
  44. package/dist/components/disclosure/DialogProvider.d.ts.map +1 -1
  45. package/dist/components/disclosure/DialogProvider.js +8 -8
  46. package/dist/components/disclosure/DialogProvider.js.map +2 -2
  47. package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
  48. package/dist/components/disclosure/Dropdown.js.map +1 -1
  49. package/dist/components/disclosure/Tabs.d.ts.map +1 -1
  50. package/dist/components/disclosure/Tabs.js.map +1 -1
  51. package/dist/components/display/Alert.d.ts.map +1 -1
  52. package/dist/components/display/Alert.js.map +1 -1
  53. package/dist/components/display/Card.d.ts +0 -1
  54. package/dist/components/display/Card.d.ts.map +1 -1
  55. package/dist/components/display/Card.js +1 -2
  56. package/dist/components/display/Card.js.map +1 -1
  57. package/dist/components/display/Echarts.d.ts +1 -1
  58. package/dist/components/display/Echarts.d.ts.map +1 -1
  59. package/dist/components/display/Echarts.js +2 -2
  60. package/dist/components/display/Echarts.js.map +2 -2
  61. package/dist/components/display/Link.d.ts +5 -0
  62. package/dist/components/display/Link.d.ts.map +1 -0
  63. package/dist/components/display/Link.js +26 -0
  64. package/dist/components/display/Link.js.map +6 -0
  65. package/dist/components/feedback/Progress.d.ts +3 -3
  66. package/dist/components/feedback/Progress.d.ts.map +1 -1
  67. package/dist/components/feedback/Progress.js +1 -1
  68. package/dist/components/feedback/Progress.js.map +2 -2
  69. package/dist/components/feedback/busy/BusyContainer.d.ts +13 -0
  70. package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -0
  71. package/dist/components/feedback/{loading/LoadingContainer.js → busy/BusyContainer.js} +20 -13
  72. package/dist/components/feedback/busy/BusyContainer.js.map +6 -0
  73. package/dist/components/feedback/busy/BusyContext.d.ts +11 -0
  74. package/dist/components/feedback/busy/BusyContext.d.ts.map +1 -0
  75. package/dist/components/feedback/busy/BusyContext.js +14 -0
  76. package/dist/components/feedback/busy/BusyContext.js.map +6 -0
  77. package/dist/components/feedback/busy/BusyProvider.d.ts +7 -0
  78. package/dist/components/feedback/busy/BusyProvider.d.ts.map +1 -0
  79. package/dist/components/feedback/{loading/LoadingProvider.js → busy/BusyProvider.js} +7 -7
  80. package/dist/components/feedback/busy/BusyProvider.js.map +6 -0
  81. package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
  82. package/dist/components/feedback/notification/NotificationBanner.js +1 -1
  83. package/dist/components/feedback/notification/NotificationBanner.js.map +1 -1
  84. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  85. package/dist/components/feedback/notification/NotificationBell.js +4 -2
  86. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  87. package/dist/components/feedback/notification/NotificationContext.d.ts.map +1 -1
  88. package/dist/components/feedback/notification/NotificationContext.js.map +1 -1
  89. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  90. package/dist/components/feedback/notification/NotificationProvider.js +1 -0
  91. package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
  92. package/dist/components/form-control/Button.d.ts.map +1 -1
  93. package/dist/components/form-control/Button.js +2 -2
  94. package/dist/components/form-control/Button.js.map +1 -1
  95. package/dist/components/form-control/DropdownTrigger.styles.d.ts.map +1 -1
  96. package/dist/components/form-control/DropdownTrigger.styles.js +6 -1
  97. package/dist/components/form-control/DropdownTrigger.styles.js.map +1 -1
  98. package/dist/components/form-control/Invalid.d.ts +4 -2
  99. package/dist/components/form-control/Invalid.d.ts.map +1 -1
  100. package/dist/components/form-control/Invalid.js +81 -41
  101. package/dist/components/form-control/Invalid.js.map +2 -2
  102. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  103. package/dist/components/form-control/ThemeToggle.js +4 -5
  104. package/dist/components/form-control/ThemeToggle.js.map +2 -2
  105. package/dist/components/form-control/checkbox/Checkbox.d.ts +4 -2
  106. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  107. package/dist/components/form-control/checkbox/Checkbox.js +65 -52
  108. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  109. package/dist/components/form-control/checkbox/Checkbox.styles.d.ts +1 -2
  110. package/dist/components/form-control/checkbox/Checkbox.styles.d.ts.map +1 -1
  111. package/dist/components/form-control/checkbox/Checkbox.styles.js +8 -10
  112. package/dist/components/form-control/checkbox/Checkbox.styles.js.map +1 -1
  113. package/dist/components/form-control/checkbox/CheckboxGroup.d.ts +9 -9
  114. package/dist/components/form-control/checkbox/CheckboxGroup.d.ts.map +1 -1
  115. package/dist/components/form-control/checkbox/CheckboxGroup.js +10 -82
  116. package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
  117. package/dist/components/form-control/checkbox/Radio.d.ts +4 -2
  118. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  119. package/dist/components/form-control/checkbox/Radio.js +64 -51
  120. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  121. package/dist/components/form-control/checkbox/RadioGroup.d.ts +9 -9
  122. package/dist/components/form-control/checkbox/RadioGroup.d.ts.map +1 -1
  123. package/dist/components/form-control/checkbox/RadioGroup.js +10 -77
  124. package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
  125. package/dist/components/form-control/color-picker/ColorPicker.d.ts +8 -3
  126. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  127. package/dist/components/form-control/color-picker/ColorPicker.js +43 -26
  128. package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
  129. package/dist/components/form-control/combobox/Combobox.d.ts +8 -8
  130. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  131. package/dist/components/form-control/combobox/Combobox.js +72 -59
  132. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  133. package/dist/components/form-control/editor/EditorToolbar.d.ts.map +1 -1
  134. package/dist/components/form-control/editor/EditorToolbar.js +3 -2
  135. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  136. package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
  137. package/dist/components/form-control/editor/RichTextEditor.js.map +1 -1
  138. package/dist/components/form-control/field/DatePicker.d.ts +6 -0
  139. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  140. package/dist/components/form-control/field/DatePicker.js +138 -117
  141. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  142. package/dist/components/form-control/field/DateTimePicker.d.ts +6 -0
  143. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  144. package/dist/components/form-control/field/DateTimePicker.js +138 -115
  145. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  146. package/dist/components/form-control/field/Field.styles.d.ts +14 -0
  147. package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
  148. package/dist/components/form-control/field/Field.styles.js +47 -3
  149. package/dist/components/form-control/field/Field.styles.js.map +1 -1
  150. package/dist/components/form-control/field/FieldPlaceholder.d.ts +7 -0
  151. package/dist/components/form-control/field/FieldPlaceholder.d.ts.map +1 -0
  152. package/dist/components/form-control/field/FieldPlaceholder.js +34 -0
  153. package/dist/components/form-control/field/FieldPlaceholder.js.map +6 -0
  154. package/dist/components/form-control/field/NumberInput.d.ts +13 -0
  155. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  156. package/dist/components/form-control/field/NumberInput.js +163 -111
  157. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  158. package/dist/components/form-control/field/TextInput.d.ts +16 -1
  159. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  160. package/dist/components/form-control/field/TextInput.js +177 -114
  161. package/dist/components/form-control/field/TextInput.js.map +2 -2
  162. package/dist/components/form-control/field/Textarea.d.ts +10 -0
  163. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  164. package/dist/components/form-control/field/Textarea.js +156 -121
  165. package/dist/components/form-control/field/Textarea.js.map +2 -2
  166. package/dist/components/form-control/field/TimePicker.d.ts +10 -0
  167. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  168. package/dist/components/form-control/field/TimePicker.js +126 -94
  169. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  170. package/dist/components/form-control/select/Select.d.ts +7 -9
  171. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  172. package/dist/components/form-control/select/Select.js +71 -60
  173. package/dist/components/form-control/select/Select.js.map +2 -2
  174. package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
  175. package/dist/components/form-control/select/SelectItem.js.map +1 -1
  176. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  177. package/dist/components/form-control/state-preset/StatePreset.js +2 -1
  178. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  179. package/dist/components/layout/FormGroup.d.ts.map +1 -1
  180. package/dist/components/layout/FormGroup.js.map +1 -1
  181. package/dist/components/layout/sidebar/Sidebar.d.ts.map +1 -1
  182. package/dist/components/layout/sidebar/Sidebar.js +1 -1
  183. package/dist/components/layout/sidebar/Sidebar.js.map +1 -1
  184. package/dist/components/layout/sidebar/SidebarContainer.d.ts.map +1 -1
  185. package/dist/components/layout/sidebar/SidebarContainer.js.map +1 -1
  186. package/dist/components/layout/sidebar/SidebarMenu.js +1 -1
  187. package/dist/components/layout/sidebar/SidebarMenu.js.map +1 -1
  188. package/dist/components/layout/sidebar/SidebarUser.d.ts.map +1 -1
  189. package/dist/components/layout/sidebar/SidebarUser.js +4 -4
  190. package/dist/components/layout/sidebar/SidebarUser.js.map +1 -1
  191. package/dist/components/layout/topbar/Topbar.js +1 -1
  192. package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
  193. package/dist/components/layout/topbar/TopbarMenu.js.map +1 -1
  194. package/dist/components/layout/topbar/TopbarUser.d.ts.map +1 -1
  195. package/dist/components/layout/topbar/TopbarUser.js.map +1 -1
  196. package/dist/helpers/createAppStructure.d.ts.map +1 -1
  197. package/dist/helpers/createAppStructure.js +17 -12
  198. package/dist/helpers/createAppStructure.js.map +1 -1
  199. package/dist/helpers/mergeStyles.d.ts.map +1 -1
  200. package/dist/helpers/mergeStyles.js +4 -1
  201. package/dist/helpers/mergeStyles.js.map +1 -1
  202. package/dist/helpers/splitSlots.d.ts.map +1 -1
  203. package/dist/helpers/splitSlots.js.map +1 -1
  204. package/dist/hooks/createControllableSignal.d.ts.map +1 -1
  205. package/dist/hooks/createControllableSignal.js.map +1 -1
  206. package/dist/hooks/createItemTemplate.d.ts +17 -0
  207. package/dist/hooks/createItemTemplate.d.ts.map +1 -0
  208. package/dist/hooks/createItemTemplate.js +40 -0
  209. package/dist/hooks/createItemTemplate.js.map +6 -0
  210. package/dist/hooks/createPointerDrag.d.ts +13 -0
  211. package/dist/hooks/createPointerDrag.d.ts.map +1 -0
  212. package/dist/hooks/createPointerDrag.js +15 -0
  213. package/dist/hooks/createPointerDrag.js.map +6 -0
  214. package/dist/hooks/createSelectionGroup.d.ts +70 -0
  215. package/dist/hooks/createSelectionGroup.d.ts.map +1 -0
  216. package/dist/hooks/createSelectionGroup.js +141 -0
  217. package/dist/hooks/createSelectionGroup.js.map +6 -0
  218. package/dist/hooks/useClipboardValueCopy.js +3 -1
  219. package/dist/hooks/useClipboardValueCopy.js.map +1 -1
  220. package/dist/hooks/useLocalStorage.d.ts +5 -3
  221. package/dist/hooks/useLocalStorage.d.ts.map +1 -1
  222. package/dist/hooks/useLocalStorage.js.map +1 -1
  223. package/dist/hooks/usePrint.d.ts.map +1 -1
  224. package/dist/hooks/usePrint.js +5 -3
  225. package/dist/hooks/usePrint.js.map +1 -1
  226. package/dist/hooks/{createPwaUpdate.d.ts → usePwaUpdate.d.ts} +2 -2
  227. package/dist/hooks/usePwaUpdate.d.ts.map +1 -0
  228. package/dist/hooks/{createPwaUpdate.js → usePwaUpdate.js} +3 -3
  229. package/dist/hooks/usePwaUpdate.js.map +6 -0
  230. package/dist/hooks/useRouterLink.d.ts.map +1 -1
  231. package/dist/hooks/useRouterLink.js.map +1 -1
  232. package/dist/hooks/useSyncConfig.d.ts +3 -3
  233. package/dist/hooks/useSyncConfig.d.ts.map +1 -1
  234. package/dist/hooks/useSyncConfig.js +6 -7
  235. package/dist/hooks/useSyncConfig.js.map +1 -1
  236. package/dist/index.d.ts +5 -6
  237. package/dist/index.d.ts.map +1 -1
  238. package/dist/index.js +6 -7
  239. package/dist/index.js.map +1 -1
  240. package/dist/providers/ConfigContext.d.ts +2 -2
  241. package/dist/providers/ConfigContext.d.ts.map +1 -1
  242. package/dist/providers/InitializeProvider.js +5 -5
  243. package/dist/providers/InitializeProvider.js.map +2 -2
  244. package/dist/providers/ServiceClientProvider.d.ts.map +1 -1
  245. package/dist/providers/ServiceClientProvider.js.map +1 -1
  246. package/dist/providers/ThemeContext.d.ts.map +1 -1
  247. package/dist/providers/ThemeContext.js +2 -1
  248. package/dist/providers/ThemeContext.js.map +2 -2
  249. package/dist/providers/shared-data/SharedDataChangeEvent.d.ts.map +1 -1
  250. package/dist/providers/shared-data/SharedDataChangeEvent.js +1 -3
  251. package/dist/providers/shared-data/SharedDataChangeEvent.js.map +1 -1
  252. package/dist/providers/shared-data/SharedDataContext.d.ts +1 -1
  253. package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
  254. package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
  255. package/dist/providers/shared-data/SharedDataProvider.js +6 -6
  256. package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
  257. package/dist/styles/patterns.styles.d.ts +1 -0
  258. package/dist/styles/patterns.styles.d.ts.map +1 -1
  259. package/dist/styles/patterns.styles.js +12 -1
  260. package/dist/styles/patterns.styles.js.map +1 -1
  261. package/dist/styles/tokens.styles.d.ts +2 -1
  262. package/dist/styles/tokens.styles.d.ts.map +1 -1
  263. package/dist/styles/tokens.styles.js +1 -1
  264. package/dist/styles/tokens.styles.js.map +1 -1
  265. package/docs/data-components.md +34 -5
  266. package/docs/disclosure.md +28 -8
  267. package/docs/display.md +19 -2
  268. package/docs/feedback.md +35 -12
  269. package/docs/form-controls.md +289 -33
  270. package/docs/hooks.md +21 -9
  271. package/docs/layout.md +15 -3
  272. package/docs/providers.md +120 -8
  273. package/docs/styling.md +90 -0
  274. package/package.json +3 -3
  275. package/src/components/data/Pagination.tsx +26 -22
  276. package/src/components/data/Table.tsx +1 -1
  277. package/src/components/data/calendar/Calendar.tsx +19 -5
  278. package/src/components/data/kanban/Kanban.tsx +72 -35
  279. package/src/components/data/list/List.tsx +11 -4
  280. package/src/components/data/list/ListItem.tsx +12 -2
  281. package/src/components/data/permission-table/PermissionTable.tsx +32 -5
  282. package/src/components/data/sheet/DataSheet.styles.ts +24 -6
  283. package/src/components/data/sheet/DataSheet.tsx +215 -149
  284. package/src/components/data/sheet/DataSheetColumn.tsx +5 -1
  285. package/src/components/data/sheet/DataSheetConfigDialog.tsx +27 -5
  286. package/src/components/data/sheet/sheetUtils.ts +12 -3
  287. package/src/components/data/sheet/types.ts +2 -2
  288. package/src/components/disclosure/Collapse.tsx +14 -3
  289. package/src/components/disclosure/Dialog.tsx +122 -106
  290. package/src/components/disclosure/DialogContext.ts +8 -5
  291. package/src/components/disclosure/DialogProvider.tsx +19 -7
  292. package/src/components/disclosure/Dropdown.tsx +12 -2
  293. package/src/components/disclosure/Tabs.tsx +29 -5
  294. package/src/components/display/Alert.tsx +3 -4
  295. package/src/components/display/Card.tsx +1 -2
  296. package/src/components/display/Echarts.tsx +12 -5
  297. package/src/components/display/Link.tsx +22 -0
  298. package/src/components/feedback/Progress.tsx +9 -5
  299. package/src/components/feedback/{loading/LoadingContainer.tsx → busy/BusyContainer.tsx} +52 -19
  300. package/src/components/feedback/busy/BusyContext.ts +20 -0
  301. package/src/components/feedback/{loading/LoadingProvider.tsx → busy/BusyProvider.tsx} +10 -10
  302. package/src/components/feedback/notification/NotificationBanner.tsx +14 -3
  303. package/src/components/feedback/notification/NotificationBell.tsx +21 -15
  304. package/src/components/feedback/notification/NotificationContext.ts +4 -1
  305. package/src/components/feedback/notification/NotificationProvider.tsx +4 -1
  306. package/src/components/form-control/Button.tsx +8 -3
  307. package/src/components/form-control/DropdownTrigger.styles.ts +7 -1
  308. package/src/components/form-control/Invalid.tsx +114 -48
  309. package/src/components/form-control/ThemeToggle.tsx +9 -18
  310. package/src/components/form-control/checkbox/Checkbox.styles.ts +7 -10
  311. package/src/components/form-control/checkbox/Checkbox.tsx +39 -28
  312. package/src/components/form-control/checkbox/CheckboxGroup.tsx +18 -97
  313. package/src/components/form-control/checkbox/Radio.tsx +39 -28
  314. package/src/components/form-control/checkbox/RadioGroup.tsx +18 -92
  315. package/src/components/form-control/color-picker/ColorPicker.tsx +51 -18
  316. package/src/components/form-control/combobox/Combobox.tsx +53 -35
  317. package/src/components/form-control/editor/EditorToolbar.tsx +19 -19
  318. package/src/components/form-control/editor/RichTextEditor.tsx +22 -4
  319. package/src/components/form-control/field/DatePicker.tsx +99 -93
  320. package/src/components/form-control/field/DateTimePicker.tsx +115 -96
  321. package/src/components/form-control/field/Field.styles.ts +62 -3
  322. package/src/components/form-control/field/FieldPlaceholder.tsx +18 -0
  323. package/src/components/form-control/field/NumberInput.tsx +136 -84
  324. package/src/components/form-control/field/TextInput.tsx +135 -88
  325. package/src/components/form-control/field/Textarea.tsx +126 -99
  326. package/src/components/form-control/field/TimePicker.tsx +101 -71
  327. package/src/components/form-control/select/Select.tsx +75 -42
  328. package/src/components/form-control/select/SelectItem.tsx +3 -1
  329. package/src/components/form-control/state-preset/StatePreset.tsx +41 -22
  330. package/src/components/layout/FormGroup.tsx +11 -2
  331. package/src/components/layout/sidebar/Sidebar.tsx +3 -2
  332. package/src/components/layout/sidebar/SidebarContainer.tsx +8 -1
  333. package/src/components/layout/sidebar/SidebarMenu.tsx +8 -2
  334. package/src/components/layout/sidebar/SidebarUser.tsx +12 -7
  335. package/src/components/layout/topbar/Topbar.tsx +1 -1
  336. package/src/components/layout/topbar/TopbarMenu.tsx +27 -5
  337. package/src/components/layout/topbar/TopbarUser.tsx +5 -1
  338. package/src/helpers/createAppStructure.ts +29 -15
  339. package/src/helpers/mergeStyles.ts +6 -2
  340. package/src/helpers/splitSlots.ts +4 -1
  341. package/src/hooks/createControllableSignal.ts +2 -1
  342. package/src/hooks/createItemTemplate.tsx +42 -0
  343. package/src/hooks/createPointerDrag.ts +28 -0
  344. package/src/hooks/createSelectionGroup.tsx +235 -0
  345. package/src/hooks/useClipboardValueCopy.ts +5 -2
  346. package/src/hooks/useLocalStorage.ts +11 -5
  347. package/src/hooks/usePrint.ts +9 -4
  348. package/src/hooks/{createPwaUpdate.ts → usePwaUpdate.ts} +1 -1
  349. package/src/hooks/useRouterLink.ts +3 -1
  350. package/src/hooks/useSyncConfig.ts +9 -13
  351. package/src/index.ts +6 -7
  352. package/src/providers/ConfigContext.ts +2 -2
  353. package/src/providers/InitializeProvider.tsx +4 -4
  354. package/src/providers/ServiceClientProvider.tsx +14 -3
  355. package/src/providers/ThemeContext.tsx +12 -3
  356. package/src/providers/shared-data/SharedDataChangeEvent.ts +4 -3
  357. package/src/providers/shared-data/SharedDataContext.ts +1 -1
  358. package/src/providers/shared-data/SharedDataProvider.tsx +13 -8
  359. package/src/styles/patterns.styles.ts +13 -1
  360. package/src/styles/tokens.styles.ts +2 -1
  361. package/tailwind.config.ts +9 -0
  362. package/tailwind.css +1 -1
  363. package/dist/components/display/Card.css +0 -15
  364. package/dist/components/feedback/loading/LoadingContainer.d.ts +0 -12
  365. package/dist/components/feedback/loading/LoadingContainer.d.ts.map +0 -1
  366. package/dist/components/feedback/loading/LoadingContainer.js.map +0 -6
  367. package/dist/components/feedback/loading/LoadingContext.d.ts +0 -11
  368. package/dist/components/feedback/loading/LoadingContext.d.ts.map +0 -1
  369. package/dist/components/feedback/loading/LoadingContext.js +0 -14
  370. package/dist/components/feedback/loading/LoadingContext.js.map +0 -6
  371. package/dist/components/feedback/loading/LoadingProvider.d.ts +0 -7
  372. package/dist/components/feedback/loading/LoadingProvider.d.ts.map +0 -1
  373. package/dist/components/feedback/loading/LoadingProvider.js.map +0 -6
  374. package/dist/hooks/createPwaUpdate.d.ts.map +0 -1
  375. package/dist/hooks/createPwaUpdate.js.map +0 -6
  376. package/src/components/display/Card.css +0 -15
  377. package/src/components/feedback/loading/LoadingContext.ts +0 -20
  378. /package/dist/components/feedback/{loading/LoadingContainer.css → busy/BusyContainer.css} +0 -0
  379. /package/src/components/feedback/{loading/LoadingContainer.css → busy/BusyContainer.css} +0 -0
@@ -17,7 +17,7 @@ import { Button } from "@simplysm/solid";
17
17
  |------|------|---------|-------------|
18
18
  | `theme` | `"primary" \| "info" \| "success" \| "warning" \| "danger" \| "base"` | `"base"` | Color theme |
19
19
  | `variant` | `"solid" \| "outline" \| "ghost"` | `"outline"` | Style variant |
20
- | `size` | `"sm" \| "lg"` | - | Size |
20
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
21
21
  | `inset` | `boolean` | - | Inset style (removes border/rounded corners) |
22
22
  | `disabled` | `boolean` | - | Disabled state |
23
23
 
@@ -40,6 +40,14 @@ import { TextInput } from "@simplysm/solid";
40
40
 
41
41
  // Format mask (e.g., phone number)
42
42
  <TextInput format="XXX-XXXX-XXXX" value={phone()} onValueChange={setPhone} />
43
+
44
+ // With validation
45
+ <TextInput required minLength={3} value={name()} onValueChange={setName} />
46
+ <TextInput
47
+ validate={(v) => v.includes("@") ? undefined : "이메일 형식이 아닙니다"}
48
+ value={email()}
49
+ onValueChange={setEmail}
50
+ />
43
51
  ```
44
52
 
45
53
  | Prop | Type | Default | Description |
@@ -48,11 +56,22 @@ import { TextInput } from "@simplysm/solid";
48
56
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
49
57
  | `type` | `"text" \| "password" \| "email"` | `"text"` | Input type |
50
58
  | `format` | `string` | - | Input format (`X` represents character position, rest are separators) |
59
+ | `prefixIcon` | `Component<TablerIconProps>` | - | Prefix icon (Tabler Icons component) |
51
60
  | `placeholder` | `string` | - | Placeholder |
61
+ | `title` | `string` | - | Tooltip title |
62
+ | `autocomplete` | `JSX.HTMLAutocomplete` | - | HTML autocomplete attribute |
52
63
  | `disabled` | `boolean` | - | Disabled state |
53
64
  | `readonly` | `boolean` | - | Read-only state |
54
- | `size` | `"sm" \| "lg"` | - | Size |
65
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
55
66
  | `inset` | `boolean` | - | Inset style |
67
+ | `class` | `string` | - | Additional CSS class |
68
+ | `style` | `JSX.CSSProperties` | - | Inline style |
69
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
70
+ | `minLength` | `number` | - | Minimum character length (error: "최소 N자 이상 입력하세요") |
71
+ | `maxLength` | `number` | - | Maximum character length (error: "최대 N자까지 입력 가능합니다") |
72
+ | `pattern` | `string` | - | Regex pattern string (error: "입력 형식이 올바르지 않습니다") |
73
+ | `validate` | `(value: string) => string \| undefined` | - | Custom validation function |
74
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
56
75
 
57
76
  ---
58
77
 
@@ -71,6 +90,9 @@ import { NumberInput } from "@simplysm/solid";
71
90
 
72
91
  // Minimum 2 decimal places
73
92
  <NumberInput value={price()} minDigits={2} />
93
+
94
+ // With validation
95
+ <NumberInput required min={0} max={100} value={score()} onValueChange={setScore} />
74
96
  ```
75
97
 
76
98
  | Prop | Type | Default | Description |
@@ -79,11 +101,20 @@ import { NumberInput } from "@simplysm/solid";
79
101
  | `onValueChange` | `(value: number \| undefined) => void` | - | Value change callback |
80
102
  | `comma` | `boolean` | `true` | Show thousand separators |
81
103
  | `minDigits` | `number` | - | Minimum decimal places |
104
+ | `prefixIcon` | `Component<TablerIconProps>` | - | Prefix icon (Tabler Icons component) |
82
105
  | `placeholder` | `string` | - | Placeholder |
106
+ | `title` | `string` | - | Tooltip title |
83
107
  | `disabled` | `boolean` | - | Disabled state |
84
108
  | `readonly` | `boolean` | - | Read-only state |
85
- | `size` | `"sm" \| "lg"` | - | Size |
109
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
86
110
  | `inset` | `boolean` | - | Inset style |
111
+ | `class` | `string` | - | Additional CSS class |
112
+ | `style` | `JSX.CSSProperties` | - | Inline style |
113
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
114
+ | `min` | `number` | - | Minimum value (error: "최솟값은 N입니다") |
115
+ | `max` | `number` | - | Maximum value (error: "최댓값은 N입니다") |
116
+ | `validate` | `(value: number \| undefined) => string \| undefined` | - | Custom validation function |
117
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
87
118
 
88
119
  ---
89
120
 
@@ -112,6 +143,9 @@ import { DateOnly } from "@simplysm/core-common";
112
143
  min={new DateOnly(2025, 1, 1)}
113
144
  max={new DateOnly(2025, 12, 31)}
114
145
  />
146
+
147
+ // With validation
148
+ <DatePicker required value={date()} onValueChange={setDate} />
115
149
  ```
116
150
 
117
151
  | Prop | Type | Default | Description |
@@ -119,14 +153,112 @@ import { DateOnly } from "@simplysm/core-common";
119
153
  | `value` | `DateOnly` | - | Input value |
120
154
  | `onValueChange` | `(value: DateOnly \| undefined) => void` | - | Value change callback |
121
155
  | `unit` | `"year" \| "month" \| "date"` | `"date"` | Date unit |
122
- | `min` | `DateOnly` | - | Minimum date |
123
- | `max` | `DateOnly` | - | Maximum date |
156
+ | `min` | `DateOnly` | - | Minimum date (error: "{min}보다 크거나 같아야 합니다") |
157
+ | `max` | `DateOnly` | - | Maximum date (error: "{max}보다 작거나 같아야 합니다") |
158
+ | `title` | `string` | - | Tooltip title |
124
159
  | `disabled` | `boolean` | - | Disabled state |
125
160
  | `readonly` | `boolean` | - | Read-only state |
126
- | `size` | `"sm" \| "lg"` | - | Size |
161
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
127
162
  | `inset` | `boolean` | - | Inset style |
163
+ | `class` | `string` | - | Additional CSS class |
164
+ | `style` | `JSX.CSSProperties` | - | Inline style |
165
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
166
+ | `validate` | `(value: DateOnly \| undefined) => string \| undefined` | - | Custom validation function |
167
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
168
+
169
+ ---
170
+
171
+ ## DateTimePicker
172
+
173
+ Date-time input field supporting minute and second units. Values are handled using the `DateTime` type.
174
+
175
+ ```tsx
176
+ import { DateTimePicker } from "@simplysm/solid";
177
+ import { DateTime } from "@simplysm/core-common";
128
178
 
129
- > `DateTimePicker` and `TimePicker` follow the same pattern for datetime (`DateTime`) and time (`Time`) input.
179
+ // Date-time input (minute precision)
180
+ <DateTimePicker unit="minute" value={dateTime()} onValueChange={setDateTime} />
181
+
182
+ // Date-time input (second precision)
183
+ <DateTimePicker unit="second" value={dateTime()} onValueChange={setDateTime} />
184
+
185
+ // min/max constraints
186
+ <DateTimePicker
187
+ unit="minute"
188
+ value={dateTime()}
189
+ onValueChange={setDateTime}
190
+ min={new DateTime(2025, 1, 1, 0, 0, 0)}
191
+ max={new DateTime(2025, 12, 31, 23, 59, 0)}
192
+ />
193
+
194
+ // With validation
195
+ <DateTimePicker required value={dateTime()} onValueChange={setDateTime} />
196
+ ```
197
+
198
+ | Prop | Type | Default | Description |
199
+ |------|------|---------|-------------|
200
+ | `value` | `DateTime` | - | Input value |
201
+ | `onValueChange` | `(value: DateTime \| undefined) => void` | - | Value change callback |
202
+ | `unit` | `"minute" \| "second"` | `"minute"` | Date-time unit |
203
+ | `min` | `DateTime` | - | Minimum date-time (error: "{min}보다 크거나 같아야 합니다") |
204
+ | `max` | `DateTime` | - | Maximum date-time (error: "{max}보다 작거나 같아야 합니다") |
205
+ | `title` | `string` | - | Tooltip title |
206
+ | `disabled` | `boolean` | - | Disabled state |
207
+ | `readonly` | `boolean` | - | Read-only state |
208
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
209
+ | `inset` | `boolean` | - | Inset style |
210
+ | `class` | `string` | - | Additional CSS class |
211
+ | `style` | `JSX.CSSProperties` | - | Inline style |
212
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
213
+ | `validate` | `(value: DateTime \| undefined) => string \| undefined` | - | Custom validation function |
214
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
215
+
216
+ ---
217
+
218
+ ## TimePicker
219
+
220
+ Time input field supporting minute and second units. Values are handled using the `Time` type.
221
+
222
+ ```tsx
223
+ import { TimePicker } from "@simplysm/solid";
224
+ import { Time } from "@simplysm/core-common";
225
+
226
+ // Time input (minute precision)
227
+ <TimePicker unit="minute" value={time()} onValueChange={setTime} />
228
+
229
+ // Time input (second precision)
230
+ <TimePicker unit="second" value={time()} onValueChange={setTime} />
231
+
232
+ // min/max constraints
233
+ <TimePicker
234
+ unit="minute"
235
+ value={time()}
236
+ onValueChange={setTime}
237
+ min={new Time(9, 0, 0)}
238
+ max={new Time(18, 0, 0)}
239
+ />
240
+
241
+ // With validation
242
+ <TimePicker required value={time()} onValueChange={setTime} />
243
+ ```
244
+
245
+ | Prop | Type | Default | Description |
246
+ |------|------|---------|-------------|
247
+ | `value` | `Time` | - | Input value |
248
+ | `onValueChange` | `(value: Time \| undefined) => void` | - | Value change callback |
249
+ | `unit` | `"minute" \| "second"` | `"minute"` | Time unit |
250
+ | `min` | `Time` | - | Minimum time (error: "{min}보다 크거나 같아야 합니다") |
251
+ | `max` | `Time` | - | Maximum time (error: "{max}보다 작거나 같아야 합니다") |
252
+ | `title` | `string` | - | Tooltip title |
253
+ | `disabled` | `boolean` | - | Disabled state |
254
+ | `readonly` | `boolean` | - | Read-only state |
255
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
256
+ | `inset` | `boolean` | - | Inset style |
257
+ | `class` | `string` | - | Additional CSS class |
258
+ | `style` | `JSX.CSSProperties` | - | Inline style |
259
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
260
+ | `validate` | `(value: Time \| undefined) => string \| undefined` | - | Custom validation function |
261
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
130
262
 
131
263
  ---
132
264
 
@@ -161,9 +293,12 @@ const [to, setTo] = createSignal<DateOnly>();
161
293
  | `onFromChange` | `(value: DateOnly \| undefined) => void` | - | Start date change callback |
162
294
  | `to` | `DateOnly` | - | End date |
163
295
  | `onToChange` | `(value: DateOnly \| undefined) => void` | - | End date change callback |
296
+ | `required` | `boolean` | - | Required field |
164
297
  | `disabled` | `boolean` | - | Disabled state |
165
- | `size` | `"sm" \| "lg"` | - | Size |
166
- | `periodLabels` | `Partial<Record<DateRangePeriodType, string>>` | `{ day: "Day", month: "Month", range: "Range" }` | Period type labels |
298
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
299
+ | `periodLabels` | `Partial<Record<DateRangePeriodType, string>>` | `{ day: "", month: "", range: "범위" }` | Period type labels (Korean by default) |
300
+ | `class` | `string` | - | Additional CSS class |
301
+ | `style` | `JSX.CSSProperties` | - | Inline style |
167
302
 
168
303
  ---
169
304
 
@@ -178,6 +313,9 @@ import { Textarea } from "@simplysm/solid";
178
313
 
179
314
  // Minimum 3 rows height
180
315
  <Textarea minRows={3} value={text()} onValueChange={setText} />
316
+
317
+ // With validation
318
+ <Textarea required minLength={10} value={text()} onValueChange={setText} />
181
319
  ```
182
320
 
183
321
  | Prop | Type | Default | Description |
@@ -185,11 +323,19 @@ import { Textarea } from "@simplysm/solid";
185
323
  | `value` | `string` | `""` | Input value |
186
324
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
187
325
  | `placeholder` | `string` | - | Placeholder |
326
+ | `title` | `string` | - | Tooltip title |
188
327
  | `minRows` | `number` | `1` | Minimum number of rows |
189
328
  | `disabled` | `boolean` | - | Disabled state |
190
329
  | `readonly` | `boolean` | - | Read-only state |
191
- | `size` | `"sm" \| "lg"` | - | Size |
330
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
192
331
  | `inset` | `boolean` | - | Inset style |
332
+ | `class` | `string` | - | Additional CSS class |
333
+ | `style` | `JSX.CSSProperties` | - | Inline style |
334
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
335
+ | `minLength` | `number` | - | Minimum character length (error: "최소 N자 이상 입력하세요") |
336
+ | `maxLength` | `number` | - | Maximum character length (error: "최대 N자까지 입력 가능합니다") |
337
+ | `validate` | `(value: string) => string \| undefined` | - | Custom validation function |
338
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
193
339
 
194
340
  ---
195
341
 
@@ -241,6 +387,9 @@ import { Select } from "@simplysm/solid";
241
387
  <Select.Action onClick={handleAdd}>+</Select.Action>
242
388
  <Select.Item value={item1}>{item1.name}</Select.Item>
243
389
  </Select>
390
+
391
+ // With validation
392
+ <Select required value={selected()} onValueChange={setSelected} items={options} />
244
393
  ```
245
394
 
246
395
  | Prop | Type | Default | Description |
@@ -255,9 +404,13 @@ import { Select } from "@simplysm/solid";
255
404
  | `hideSelectAll` | `boolean` | - | Hide select all button (multiple selection) |
256
405
  | `placeholder` | `string` | - | Placeholder |
257
406
  | `disabled` | `boolean` | - | Disabled state |
258
- | `required` | `boolean` | - | Required field |
259
- | `size` | `"sm" \| "lg"` | - | Size |
407
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
408
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
260
409
  | `inset` | `boolean` | - | Inset style |
410
+ | `class` | `string` | - | Additional CSS class |
411
+ | `style` | `JSX.CSSProperties` | - | Inline style |
412
+ | `validate` | `(value: unknown) => string \| undefined` | - | Custom validation function |
413
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
261
414
 
262
415
  **Sub-components:**
263
416
  - `Select.Item` -- Selection item
@@ -289,6 +442,9 @@ import { Combobox } from "@simplysm/solid";
289
442
  {(item) => <>{item.name}</>}
290
443
  </Combobox.ItemTemplate>
291
444
  </Combobox>
445
+
446
+ // With validation
447
+ <Combobox required loadItems={loadItems} renderValue={(v) => v.name} value={selected()} onValueChange={setSelected} />
292
448
  ```
293
449
 
294
450
  | Prop | Type | Default | Description |
@@ -302,8 +458,13 @@ import { Combobox } from "@simplysm/solid";
302
458
  | `parseCustomValue` | `(text: string) => T` | - | Custom value parsing function |
303
459
  | `placeholder` | `string` | - | Placeholder |
304
460
  | `disabled` | `boolean` | - | Disabled state |
305
- | `size` | `"sm" \| "lg"` | - | Size |
461
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
306
462
  | `inset` | `boolean` | - | Inset style |
463
+ | `class` | `string` | - | Additional CSS class |
464
+ | `style` | `JSX.CSSProperties` | - | Inline style |
465
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
466
+ | `validate` | `(value: T \| undefined) => string \| undefined` | - | Custom validation function |
467
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
307
468
 
308
469
  **Sub-components:**
309
470
  - `Combobox.Item` -- Selection item
@@ -313,27 +474,33 @@ import { Combobox } from "@simplysm/solid";
313
474
 
314
475
  ## Checkbox / Radio
315
476
 
316
- Checkbox and radio button components.
477
+ Checkbox and radio button components. Always uses primary color.
317
478
 
318
479
  ```tsx
319
480
  import { Checkbox, Radio } from "@simplysm/solid";
320
481
 
321
482
  <Checkbox value={checked()} onValueChange={setChecked}>I agree</Checkbox>
322
- <Checkbox theme="success" value={active()} onValueChange={setActive}>Activate</Checkbox>
323
483
 
324
484
  <Radio value={option() === "a"} onValueChange={() => setOption("a")}>Option A</Radio>
325
485
  <Radio value={option() === "b"} onValueChange={() => setOption("b")}>Option B</Radio>
486
+
487
+ // With validation
488
+ <Checkbox required value={agreed()} onValueChange={setAgreed}>I agree to the terms</Checkbox>
326
489
  ```
327
490
 
328
491
  | Prop | Type | Default | Description |
329
492
  |------|------|---------|-------------|
330
493
  | `value` | `boolean` | `false` | Checked state |
331
494
  | `onValueChange` | `(value: boolean) => void` | - | Value change callback |
332
- | `theme` | `"primary" \| "info" \| "success" \| "warning" \| "danger" \| "base"` | `"primary"` | Color theme |
333
- | `size` | `"sm" \| "lg"` | - | Size |
495
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
334
496
  | `disabled` | `boolean` | - | Disabled state |
335
497
  | `inset` | `boolean` | - | Inset style |
336
498
  | `inline` | `boolean` | - | Inline style |
499
+ | `class` | `string` | - | Additional CSS class |
500
+ | `style` | `JSX.CSSProperties` | - | Inline style object |
501
+ | `required` | `boolean` | - | Required field (error: "필수 선택 항목입니다") |
502
+ | `validate` | `(value: boolean) => string \| undefined` | - | Custom validation function |
503
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
337
504
 
338
505
  ---
339
506
 
@@ -357,6 +524,11 @@ import { CheckboxGroup, RadioGroup } from "@simplysm/solid";
357
524
  <RadioGroup.Item value="md">Medium</RadioGroup.Item>
358
525
  <RadioGroup.Item value="lg">Large</RadioGroup.Item>
359
526
  </RadioGroup>
527
+
528
+ // With validation
529
+ <CheckboxGroup required value={selected()} onValueChange={setSelected}>
530
+ <CheckboxGroup.Item value="a">Option A</CheckboxGroup.Item>
531
+ </CheckboxGroup>
360
532
  ```
361
533
 
362
534
  **CheckboxGroup Props:**
@@ -365,11 +537,13 @@ import { CheckboxGroup, RadioGroup } from "@simplysm/solid";
365
537
  |------|------|---------|-------------|
366
538
  | `value` | `T[]` | `[]` | Selected values array |
367
539
  | `onValueChange` | `(value: T[]) => void` | - | Value change callback |
368
- | `theme` | `SemanticTheme` | `"primary"` | Color theme |
369
- | `size` | `"sm" \| "lg"` | - | Size |
540
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
370
541
  | `disabled` | `boolean` | - | Disable all items |
371
542
  | `inline` | `boolean` | - | Inline style |
372
543
  | `inset` | `boolean` | - | Inset style |
544
+ | `required` | `boolean` | - | Required field (error: "항목을 선택해 주세요") |
545
+ | `validate` | `(value: T[]) => string \| undefined` | - | Custom validation function |
546
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
373
547
 
374
548
  **RadioGroup Props:**
375
549
 
@@ -377,11 +551,13 @@ import { CheckboxGroup, RadioGroup } from "@simplysm/solid";
377
551
  |------|------|---------|-------------|
378
552
  | `value` | `T` | - | Selected value |
379
553
  | `onValueChange` | `(value: T) => void` | - | Value change callback |
380
- | `theme` | `SemanticTheme` | `"primary"` | Color theme |
381
- | `size` | `"sm" \| "lg"` | - | Size |
554
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
382
555
  | `disabled` | `boolean` | - | Disable all items |
383
556
  | `inline` | `boolean` | - | Inline style |
384
557
  | `inset` | `boolean` | - | Inset style |
558
+ | `required` | `boolean` | - | Required field (error: "항목을 선택해 주세요") |
559
+ | `validate` | `(value: T \| undefined) => string \| undefined` | - | Custom validation function |
560
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
385
561
 
386
562
  ---
387
563
 
@@ -394,14 +570,20 @@ import { ColorPicker } from "@simplysm/solid";
394
570
 
395
571
  <ColorPicker value={color()} onValueChange={setColor} />
396
572
  <ColorPicker value={color()} size="sm" disabled />
573
+
574
+ // With validation
575
+ <ColorPicker required value={color()} onValueChange={setColor} />
397
576
  ```
398
577
 
399
578
  | Prop | Type | Default | Description |
400
579
  |------|------|---------|-------------|
401
580
  | `value` | `string` | `"#000000"` | Color value (#RRGGBB format) |
402
581
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
403
- | `size` | `"sm" \| "lg"` | - | Size |
582
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
404
583
  | `disabled` | `boolean` | - | Disabled state |
584
+ | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
585
+ | `validate` | `(value: string \| undefined) => string \| undefined` | - | Custom validation function |
586
+ | `touchMode` | `boolean` | - | Show error only after field loses focus |
405
587
 
406
588
  ---
407
589
 
@@ -440,13 +622,13 @@ import { RichTextEditor } from "@simplysm/solid";
440
622
  | `value` | `string` | - | HTML string value |
441
623
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
442
624
  | `disabled` | `boolean` | - | Disabled state |
443
- | `size` | `"sm" \| "lg"` | - | Size |
625
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
444
626
 
445
627
  ---
446
628
 
447
629
  ## Invalid
448
630
 
449
- Wrapper component for form validation using native browser `setCustomValidity` API. Displays a red indicator dot and manages validation state for form fields. Useful for integrating with native form validation or custom validation frameworks.
631
+ Wrapper component for form validation using native browser `setCustomValidity` API. Renders as a Fragment (no wrapper element). Manages both native form validity and visual error indicators.
450
632
 
451
633
  ```tsx
452
634
  import { Invalid, TextInput } from "@simplysm/solid";
@@ -460,23 +642,97 @@ const handleChange = (val: string) => {
460
642
  setError(val.length < 3 ? "Must be at least 3 characters" : "");
461
643
  };
462
644
 
645
+ // variant="dot" — injects a red dot inside the first child element (default)
463
646
  <Invalid message={error()}>
464
647
  <TextInput value={value()} onValueChange={handleChange} />
465
648
  </Invalid>
466
- ```
467
649
 
468
- The `Invalid` component wraps any form field and displays a validation state using the browser's native validation API. A red indicator dot appears when a message is present.
650
+ // variant="border" adds danger border class to the first child element
651
+ <Invalid variant="border" message={error()}>
652
+ <div class="border rounded-lg p-2">Content</div>
653
+ </Invalid>
654
+
655
+ // touchMode — show visual feedback only after the field loses focus
656
+ <Invalid variant="border" message={error()} touchMode>
657
+ <TextInput value={value()} onValueChange={handleChange} />
658
+ </Invalid>
659
+ ```
469
660
 
470
661
  | Prop | Type | Default | Description |
471
662
  |------|------|---------|-------------|
472
663
  | `message` | `string` | - | Validation error message (non-empty = invalid state) |
473
- | `class` | `string` | - | Custom CSS class |
664
+ | `variant` | `"border" \| "dot"` | `"dot"` | Visual indicator style |
665
+ | `touchMode` | `boolean` | - | Show visual indicator only after the target element loses focus |
474
666
 
475
667
  **Key features:**
476
- - Uses native `setCustomValidity` for browser validation integration
477
- - Red indicator dot displayed when error message is present
478
- - Reactively updates validation state when message changes
479
- - Works with any form field component
668
+ - Renders as a Fragment does not add a wrapper DOM element
669
+ - Uses native `setCustomValidity` for browser form validation integration (always set, regardless of `touchMode`)
670
+ - `variant="dot"`: injects a small red dot (`position: absolute`) inside the first child element
671
+ - `variant="border"`: adds `border-danger-500` CSS class to the first child element
672
+ - `touchMode`: visual display is deferred until the target element fires a `focusout` event
673
+ - Works with any form field component or custom element
674
+
675
+ > Most form controls (`TextInput`, `NumberInput`, `Textarea`, `Select`, etc.) use `Invalid` internally and expose `validate` / `touchMode` props directly. Direct use of `Invalid` is for custom validation scenarios.
676
+
677
+ ---
678
+
679
+ ## Form Validation
680
+
681
+ All form controls integrate with native browser form validation via the `setCustomValidity` API. Use `form.reportValidity()` to trigger validation and show error messages.
682
+
683
+ ```tsx
684
+ import { Button, TextInput, NumberInput } from "@simplysm/solid";
685
+
686
+ <form onSubmit={(e) => {
687
+ e.preventDefault();
688
+ if (e.currentTarget.reportValidity()) {
689
+ // All fields are valid — proceed with submit
690
+ }
691
+ }}>
692
+ <TextInput required placeholder="이름" value={name()} onValueChange={setName} />
693
+ <TextInput required minLength={3} placeholder="최소 3자" value={nick()} onValueChange={setNick} />
694
+ <TextInput
695
+ validate={(v) => v.includes("@") ? undefined : "이메일 형식이 아닙니다"}
696
+ placeholder="이메일"
697
+ value={email()}
698
+ onValueChange={setEmail}
699
+ />
700
+ <NumberInput required min={0} max={100} value={score()} onValueChange={setScore} />
701
+ <Button type="submit">Submit</Button>
702
+ </form>
703
+ ```
704
+
705
+ **`validate` prop type:**
706
+
707
+ ```typescript
708
+ validate?: (value: T) => string | undefined
709
+ // T is the component's value type (string, number, boolean, DateOnly, etc.)
710
+ // Return a string for an error message, or undefined when valid
711
+ ```
712
+
713
+ **Built-in error messages (Korean):**
714
+
715
+ | Condition | Message |
716
+ |-----------|---------|
717
+ | `required` empty (text/number/date) | "필수 입력 항목입니다" |
718
+ | `required` unchecked (Checkbox/Radio) | "필수 선택 항목입니다" |
719
+ | `required` empty (CheckboxGroup/RadioGroup) | "항목을 선택해 주세요" |
720
+ | `minLength` not met | "최소 N자 이상 입력하세요" |
721
+ | `maxLength` exceeded | "최대 N자까지 입력 가능합니다" |
722
+ | `pattern` mismatch | "입력 형식이 올바르지 않습니다" |
723
+ | `min` underflow (NumberInput) | "최솟값은 N입니다" |
724
+ | `max` overflow (NumberInput) | "최댓값은 N입니다" |
725
+ | `min` underflow (DatePicker/DateTimePicker/TimePicker) | "{min}보다 크거나 같아야 합니다" |
726
+ | `max` overflow (DatePicker/DateTimePicker/TimePicker) | "{max}보다 작거나 같아야 합니다" |
727
+
728
+ **`touchMode` behavior:**
729
+
730
+ When `touchMode` is set, the visual error indicator (red dot or border) is shown only after the user has interacted with the field (i.e., after `focusout`). The native `setCustomValidity` is always set immediately, so `form.reportValidity()` works correctly regardless of `touchMode`.
731
+
732
+ ```tsx
733
+ // Error indicator appears only after the user leaves the field
734
+ <TextInput required touchMode value={name()} onValueChange={setName} />
735
+ ```
480
736
 
481
737
  ---
482
738
 
@@ -509,7 +765,7 @@ import { Numpad } from "@simplysm/solid";
509
765
  | `useEnterButton` | `boolean` | - | Show ENT button |
510
766
  | `useMinusButton` | `boolean` | - | Show minus button |
511
767
  | `onEnterButtonClick` | `() => void` | - | ENT click callback |
512
- | `size` | `"sm" \| "lg"` | - | Size |
768
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
513
769
 
514
770
  ---
515
771
 
@@ -532,4 +788,4 @@ import { StatePreset } from "@simplysm/solid";
532
788
  | `presetKey` | `string` | **(required)** | Preset storage key |
533
789
  | `value` | `T` | **(required)** | Current state value |
534
790
  | `onValueChange` | `(value: T) => void` | **(required)** | State restore callback |
535
- | `size` | `"sm" \| "lg"` | - | Size |
791
+ | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
package/docs/hooks.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hooks
2
2
 
3
- ## createPwaUpdate
3
+ ## usePwaUpdate
4
4
 
5
5
  PWA Service Worker update detection hook. Automatically polls for Service Worker updates every 5 minutes. When a new version is detected, shows a notification with a reload action button.
6
6
 
@@ -9,11 +9,11 @@ PWA Service Worker update detection hook. Automatically polls for Service Worker
9
9
  **Manual Usage (Custom Provider Tree):**
10
10
 
11
11
  ```tsx
12
- import { createPwaUpdate } from "@simplysm/solid";
12
+ import { usePwaUpdate } from "@simplysm/solid";
13
13
 
14
14
  function MyProvider(props) {
15
15
  // Must be called inside NotificationProvider
16
- createPwaUpdate();
16
+ usePwaUpdate();
17
17
 
18
18
  return (
19
19
  <NotificationProvider>
@@ -81,17 +81,17 @@ Syncable config hook. Uses `syncStorage` if configured, falls back to `localStor
81
81
  ```tsx
82
82
  import { useSyncConfig } from "@simplysm/solid";
83
83
 
84
- const [theme, setTheme, loading] = useSyncConfig("theme", "light");
84
+ const [theme, setTheme, ready] = useSyncConfig("theme", "light");
85
85
 
86
- // loading state is useful when syncStorage is async (e.g., DB-backed)
87
- // When syncStorage is not configured, loading is always false
86
+ // ready state indicates initialization is complete
87
+ // When syncStorage is not configured (localStorage), ready is immediately true
88
88
  ```
89
89
 
90
90
  | Return value | Type | Description |
91
91
  |--------------|------|-------------|
92
92
  | `[0]` | `Accessor<T>` | Value getter |
93
93
  | `[1]` | `Setter<T>` | Value setter |
94
- | `[2]` | `Accessor<boolean>` | Loading state (async storage only) |
94
+ | `[2]` | `Accessor<boolean>` | Ready state (`true` after initialization) |
95
95
 
96
96
  ---
97
97
 
@@ -126,9 +126,9 @@ Hook to access notification system. Must be used inside `InitializeProvider`. Se
126
126
 
127
127
  ---
128
128
 
129
- ## useLoading
129
+ ## useBusy
130
130
 
131
- Hook to access loading overlay. Must be used inside `InitializeProvider`. See [Loading](feedback.md#loading) for detailed API.
131
+ Hook to access busy overlay. Must be used inside `InitializeProvider`. See [Busy](feedback.md#busy) for detailed API.
132
132
 
133
133
  ---
134
134
 
@@ -151,6 +151,18 @@ console.log(config.clientName); // "my-app"
151
151
 
152
152
  ---
153
153
 
154
+ ## useServiceClient
155
+
156
+ Hook to access the WebSocket service client context. Must be used inside `ServiceClientProvider`. See [ServiceClientProvider](providers.md#serviceclientprovider) for detailed API.
157
+
158
+ ---
159
+
160
+ ## useSharedData
161
+
162
+ Hook to access shared data managed by `SharedDataProvider`. Must be used inside `SharedDataProvider`. See [SharedDataProvider](providers.md#shareddataprovider) for detailed API.
163
+
164
+ ---
165
+
154
166
  ## createControllableSignal
155
167
 
156
168
  Signal hook that automatically handles Controlled/Uncontrolled patterns. Operates in controlled mode when `onChange` is provided, uncontrolled mode otherwise.
package/docs/layout.md CHANGED
@@ -203,7 +203,7 @@ import { FormTable, TextInput, NumberInput } from "@simplysm/solid";
203
203
 
204
204
  ## Kanban
205
205
 
206
- Kanban board layout component with drag-and-drop cards, lane collapse, multi-select, and loading states.
206
+ Kanban board layout component with drag-and-drop cards, lane collapse, multi-select, and busy states.
207
207
 
208
208
  ```tsx
209
209
  import { createSignal, For } from "solid-js";
@@ -228,7 +228,7 @@ const handleDrop = (info: KanbanDropInfo) => {
228
228
  >
229
229
  <For each={lanes()}>
230
230
  {(lane) => (
231
- <Kanban.Lane value={lane.id} collapsible busy={lane.loading}>
231
+ <Kanban.Lane value={lane.id} collapsible busy={lane.busy}>
232
232
  <Kanban.LaneTitle>
233
233
  {lane.title} ({lane.cards.length})
234
234
  </Kanban.LaneTitle>
@@ -266,7 +266,7 @@ const handleDrop = (info: KanbanDropInfo) => {
266
266
  | Prop | Type | Default | Description |
267
267
  |------|------|---------|-------------|
268
268
  | `value` | `unknown` | - | Lane identifier |
269
- | `busy` | `boolean` | - | Show loading bar |
269
+ | `busy` | `boolean` | - | Show busy bar |
270
270
  | `collapsible` | `boolean` | - | Allow collapse/expand |
271
271
  | `collapsed` | `boolean` | - | Collapsed state (controlled) |
272
272
  | `onCollapsedChange` | `(collapsed: boolean) => void` | - | Collapse state callback |
@@ -287,3 +287,15 @@ const handleDrop = (info: KanbanDropInfo) => {
287
287
  - `Kanban.Card` -- Draggable card
288
288
 
289
289
  **Selection:** Shift+Click for multi-select, long press for single select. Lane header checkbox toggles all cards in the lane.
290
+
291
+ **KanbanContext:**
292
+
293
+ `KanbanContext` and `useKanbanContext` are exported for building custom Kanban card/lane sub-components. `useKanbanLaneContext` provides lane-scoped context. These are low-level APIs for advanced customization.
294
+
295
+ ```typescript
296
+ import { useKanbanContext, useKanbanLaneContext } from "@simplysm/solid";
297
+
298
+ // inside a custom card component
299
+ const kanban = useKanbanContext();
300
+ const lane = useKanbanLaneContext();
301
+ ```