@simplysm/solid 13.0.29 → 13.0.31

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 (220) hide show
  1. package/README.md +10 -5
  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.js +1 -1
  8. package/dist/components/data/kanban/Kanban.d.ts +9 -9
  9. package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
  10. package/dist/components/data/kanban/Kanban.js +4 -4
  11. package/dist/components/data/kanban/Kanban.js.map +2 -2
  12. package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
  13. package/dist/components/data/sheet/DataSheet.js +102 -107
  14. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  15. package/dist/components/data/sheet/DataSheet.styles.js +1 -1
  16. package/dist/components/data/sheet/types.d.ts +2 -2
  17. package/dist/components/data/sheet/types.d.ts.map +1 -1
  18. package/dist/components/disclosure/Dialog.d.ts +8 -8
  19. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  20. package/dist/components/disclosure/Dialog.js +64 -69
  21. package/dist/components/disclosure/Dialog.js.map +2 -2
  22. package/dist/components/disclosure/DialogContext.d.ts +4 -4
  23. package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
  24. package/dist/components/disclosure/DialogProvider.js +8 -8
  25. package/dist/components/disclosure/DialogProvider.js.map +2 -2
  26. package/dist/components/feedback/Progress.d.ts +3 -3
  27. package/dist/components/feedback/Progress.d.ts.map +1 -1
  28. package/dist/components/feedback/Progress.js +1 -1
  29. package/dist/components/feedback/Progress.js.map +2 -2
  30. package/dist/components/feedback/busy/BusyContainer.d.ts +1 -0
  31. package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -1
  32. package/dist/components/feedback/busy/BusyContainer.js +13 -6
  33. package/dist/components/feedback/busy/BusyContainer.js.map +2 -2
  34. package/dist/components/feedback/notification/NotificationBanner.js +1 -1
  35. package/dist/components/feedback/notification/NotificationBanner.js.map +1 -1
  36. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  37. package/dist/components/feedback/notification/NotificationBell.js +4 -2
  38. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  39. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  40. package/dist/components/feedback/notification/NotificationProvider.js +1 -0
  41. package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
  42. package/dist/components/form-control/Invalid.d.ts +4 -2
  43. package/dist/components/form-control/Invalid.d.ts.map +1 -1
  44. package/dist/components/form-control/Invalid.js +81 -41
  45. package/dist/components/form-control/Invalid.js.map +2 -2
  46. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  47. package/dist/components/form-control/ThemeToggle.js +4 -5
  48. package/dist/components/form-control/ThemeToggle.js.map +2 -2
  49. package/dist/components/form-control/checkbox/Checkbox.d.ts +4 -2
  50. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  51. package/dist/components/form-control/checkbox/Checkbox.js +65 -52
  52. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  53. package/dist/components/form-control/checkbox/Checkbox.styles.d.ts +1 -2
  54. package/dist/components/form-control/checkbox/Checkbox.styles.d.ts.map +1 -1
  55. package/dist/components/form-control/checkbox/Checkbox.styles.js +3 -9
  56. package/dist/components/form-control/checkbox/Checkbox.styles.js.map +1 -1
  57. package/dist/components/form-control/checkbox/CheckboxGroup.d.ts +9 -9
  58. package/dist/components/form-control/checkbox/CheckboxGroup.d.ts.map +1 -1
  59. package/dist/components/form-control/checkbox/CheckboxGroup.js +10 -82
  60. package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
  61. package/dist/components/form-control/checkbox/Radio.d.ts +4 -2
  62. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  63. package/dist/components/form-control/checkbox/Radio.js +64 -51
  64. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  65. package/dist/components/form-control/checkbox/RadioGroup.d.ts +9 -9
  66. package/dist/components/form-control/checkbox/RadioGroup.d.ts.map +1 -1
  67. package/dist/components/form-control/checkbox/RadioGroup.js +10 -77
  68. package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
  69. package/dist/components/form-control/color-picker/ColorPicker.d.ts +8 -3
  70. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  71. package/dist/components/form-control/color-picker/ColorPicker.js +43 -26
  72. package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
  73. package/dist/components/form-control/combobox/Combobox.d.ts +8 -8
  74. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  75. package/dist/components/form-control/combobox/Combobox.js +72 -59
  76. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  77. package/dist/components/form-control/editor/EditorToolbar.d.ts.map +1 -1
  78. package/dist/components/form-control/editor/EditorToolbar.js +3 -2
  79. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  80. package/dist/components/form-control/field/DatePicker.d.ts +6 -0
  81. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  82. package/dist/components/form-control/field/DatePicker.js +138 -117
  83. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  84. package/dist/components/form-control/field/DateTimePicker.d.ts +6 -0
  85. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  86. package/dist/components/form-control/field/DateTimePicker.js +138 -115
  87. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  88. package/dist/components/form-control/field/Field.styles.d.ts +14 -0
  89. package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
  90. package/dist/components/form-control/field/Field.styles.js +30 -0
  91. package/dist/components/form-control/field/Field.styles.js.map +1 -1
  92. package/dist/components/form-control/field/FieldPlaceholder.d.ts +7 -0
  93. package/dist/components/form-control/field/FieldPlaceholder.d.ts.map +1 -0
  94. package/dist/components/form-control/field/FieldPlaceholder.js +34 -0
  95. package/dist/components/form-control/field/FieldPlaceholder.js.map +6 -0
  96. package/dist/components/form-control/field/NumberInput.d.ts +10 -0
  97. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  98. package/dist/components/form-control/field/NumberInput.js +149 -115
  99. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  100. package/dist/components/form-control/field/TextInput.d.ts +12 -0
  101. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  102. package/dist/components/form-control/field/TextInput.js +162 -116
  103. package/dist/components/form-control/field/TextInput.js.map +2 -2
  104. package/dist/components/form-control/field/Textarea.d.ts +10 -0
  105. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  106. package/dist/components/form-control/field/Textarea.js +156 -121
  107. package/dist/components/form-control/field/Textarea.js.map +2 -2
  108. package/dist/components/form-control/field/TimePicker.d.ts +10 -0
  109. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  110. package/dist/components/form-control/field/TimePicker.js +126 -94
  111. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  112. package/dist/components/form-control/select/Select.d.ts +7 -9
  113. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  114. package/dist/components/form-control/select/Select.js +71 -60
  115. package/dist/components/form-control/select/Select.js.map +2 -2
  116. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  117. package/dist/components/form-control/state-preset/StatePreset.js +2 -1
  118. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  119. package/dist/components/layout/sidebar/SidebarMenu.js +1 -1
  120. package/dist/components/layout/sidebar/SidebarMenu.js.map +1 -1
  121. package/dist/components/layout/sidebar/SidebarUser.js +2 -2
  122. package/dist/components/layout/sidebar/SidebarUser.js.map +1 -1
  123. package/dist/hooks/createItemTemplate.d.ts +17 -0
  124. package/dist/hooks/createItemTemplate.d.ts.map +1 -0
  125. package/dist/hooks/createItemTemplate.js +40 -0
  126. package/dist/hooks/createItemTemplate.js.map +6 -0
  127. package/dist/hooks/createPointerDrag.d.ts +13 -0
  128. package/dist/hooks/createPointerDrag.d.ts.map +1 -0
  129. package/dist/hooks/createPointerDrag.js +15 -0
  130. package/dist/hooks/createPointerDrag.js.map +6 -0
  131. package/dist/hooks/createSelectionGroup.d.ts +70 -0
  132. package/dist/hooks/createSelectionGroup.d.ts.map +1 -0
  133. package/dist/hooks/createSelectionGroup.js +141 -0
  134. package/dist/hooks/createSelectionGroup.js.map +6 -0
  135. package/dist/hooks/useLocalStorage.d.ts +5 -3
  136. package/dist/hooks/useLocalStorage.d.ts.map +1 -1
  137. package/dist/hooks/useLocalStorage.js.map +1 -1
  138. package/dist/hooks/{createPwaUpdate.d.ts → usePwaUpdate.d.ts} +2 -2
  139. package/dist/hooks/usePwaUpdate.d.ts.map +1 -0
  140. package/dist/hooks/{createPwaUpdate.js → usePwaUpdate.js} +3 -3
  141. package/dist/hooks/usePwaUpdate.js.map +6 -0
  142. package/dist/hooks/useSyncConfig.d.ts +3 -3
  143. package/dist/hooks/useSyncConfig.d.ts.map +1 -1
  144. package/dist/hooks/useSyncConfig.js +6 -7
  145. package/dist/hooks/useSyncConfig.js.map +1 -1
  146. package/dist/index.d.ts +1 -3
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +2 -4
  149. package/dist/index.js.map +1 -1
  150. package/dist/providers/InitializeProvider.js +2 -2
  151. package/dist/providers/InitializeProvider.js.map +2 -2
  152. package/dist/providers/ThemeContext.d.ts.map +1 -1
  153. package/dist/providers/ThemeContext.js +2 -1
  154. package/dist/providers/ThemeContext.js.map +2 -2
  155. package/dist/styles/patterns.styles.d.ts +1 -0
  156. package/dist/styles/patterns.styles.d.ts.map +1 -1
  157. package/dist/styles/patterns.styles.js +11 -0
  158. package/dist/styles/patterns.styles.js.map +1 -1
  159. package/dist/styles/tokens.styles.d.ts +1 -0
  160. package/dist/styles/tokens.styles.d.ts.map +1 -1
  161. package/dist/styles/tokens.styles.js.map +1 -1
  162. package/docs/data-components.md +34 -5
  163. package/docs/disclosure.md +28 -8
  164. package/docs/feedback.md +25 -2
  165. package/docs/form-controls.md +289 -33
  166. package/docs/hooks.md +19 -7
  167. package/docs/layout.md +12 -0
  168. package/docs/providers.md +120 -8
  169. package/docs/styling.md +90 -0
  170. package/package.json +3 -3
  171. package/src/components/data/Pagination.tsx +20 -21
  172. package/src/components/data/Table.tsx +1 -1
  173. package/src/components/data/calendar/Calendar.tsx +1 -1
  174. package/src/components/data/kanban/Kanban.tsx +18 -25
  175. package/src/components/data/sheet/DataSheet.styles.ts +1 -1
  176. package/src/components/data/sheet/DataSheet.tsx +122 -131
  177. package/src/components/data/sheet/types.ts +2 -2
  178. package/src/components/disclosure/Dialog.tsx +87 -100
  179. package/src/components/disclosure/DialogContext.ts +4 -4
  180. package/src/components/disclosure/DialogProvider.tsx +4 -4
  181. package/src/components/feedback/Progress.tsx +9 -5
  182. package/src/components/feedback/busy/BusyContainer.tsx +9 -5
  183. package/src/components/feedback/notification/NotificationBanner.tsx +1 -1
  184. package/src/components/feedback/notification/NotificationBell.tsx +4 -12
  185. package/src/components/feedback/notification/NotificationProvider.tsx +1 -0
  186. package/src/components/form-control/Invalid.tsx +114 -52
  187. package/src/components/form-control/ThemeToggle.tsx +4 -17
  188. package/src/components/form-control/checkbox/Checkbox.styles.ts +2 -9
  189. package/src/components/form-control/checkbox/Checkbox.tsx +39 -28
  190. package/src/components/form-control/checkbox/CheckboxGroup.tsx +18 -97
  191. package/src/components/form-control/checkbox/Radio.tsx +39 -28
  192. package/src/components/form-control/checkbox/RadioGroup.tsx +18 -92
  193. package/src/components/form-control/color-picker/ColorPicker.tsx +36 -16
  194. package/src/components/form-control/combobox/Combobox.tsx +43 -33
  195. package/src/components/form-control/editor/EditorToolbar.tsx +3 -14
  196. package/src/components/form-control/field/DatePicker.tsx +99 -97
  197. package/src/components/form-control/field/DateTimePicker.tsx +107 -95
  198. package/src/components/form-control/field/Field.styles.ts +45 -0
  199. package/src/components/form-control/field/FieldPlaceholder.tsx +18 -0
  200. package/src/components/form-control/field/NumberInput.tsx +122 -94
  201. package/src/components/form-control/field/TextInput.tsx +119 -95
  202. package/src/components/form-control/field/Textarea.tsx +124 -98
  203. package/src/components/form-control/field/TimePicker.tsx +101 -75
  204. package/src/components/form-control/select/Select.tsx +52 -44
  205. package/src/components/form-control/state-preset/StatePreset.tsx +2 -8
  206. package/src/components/layout/sidebar/SidebarMenu.tsx +1 -1
  207. package/src/components/layout/sidebar/SidebarUser.tsx +3 -3
  208. package/src/hooks/createItemTemplate.tsx +42 -0
  209. package/src/hooks/createPointerDrag.ts +28 -0
  210. package/src/hooks/createSelectionGroup.tsx +235 -0
  211. package/src/hooks/useLocalStorage.ts +8 -4
  212. package/src/hooks/{createPwaUpdate.ts → usePwaUpdate.ts} +1 -1
  213. package/src/hooks/useSyncConfig.ts +9 -13
  214. package/src/index.ts +1 -3
  215. package/src/providers/InitializeProvider.tsx +2 -2
  216. package/src/providers/ThemeContext.tsx +2 -1
  217. package/src/styles/patterns.styles.ts +12 -0
  218. package/src/styles/tokens.styles.ts +1 -0
  219. package/dist/hooks/createPwaUpdate.d.ts.map +0 -1
  220. package/dist/hooks/createPwaUpdate.js.map +0 -6
package/docs/providers.md CHANGED
@@ -2,34 +2,146 @@
2
2
 
3
3
  ## InitializeProvider
4
4
 
5
- Root provider that wraps the entire application. Automatically sets up all required providers: configuration context, theme (dark/light/system), notification system with banner, global error capturing (window.onerror, unhandledrejection), busy overlay, and programmatic dialog support.
5
+ Root provider that wraps the entire application. Automatically sets up all required providers: configuration context, theme (dark/light/system), notification system with banner, global error capturing (window.onerror, unhandledrejection), busy overlay, programmatic dialog support, and form control clipboard value copy.
6
6
 
7
- See [Getting Started](getting-started.md#provider-setup) for setup instructions and `AppConfig` options.
7
+ See the [Configuration](../README.md#configuration) section in the main README for setup instructions and `AppConfig` options.
8
8
 
9
9
  ---
10
10
 
11
11
  ## ServiceClientProvider
12
12
 
13
- WebSocket client provider for RPC communication with `@simplysm/service-server`. Wraps `ServiceClient` from `@simplysm/service-client`.
13
+ WebSocket client provider for RPC communication with `@simplysm/service-server`. Wraps `ServiceClient` from `@simplysm/service-client`. Provides `useServiceClient` hook to components.
14
+
15
+ `ServiceClientProvider` takes no props. After mounting, use `useServiceClient()` to connect, close, and access client instances by key.
14
16
 
15
17
  ```tsx
16
- import { ServiceClientProvider } from "@simplysm/solid";
18
+ import { ServiceClientProvider, useServiceClient } from "@simplysm/solid";
17
19
 
18
- <ServiceClientProvider url="ws://localhost:3000">
20
+ // Wrap your app
21
+ <ServiceClientProvider>
19
22
  <App />
20
23
  </ServiceClientProvider>
24
+
25
+ // In a component
26
+ function App() {
27
+ const client = useServiceClient();
28
+
29
+ onMount(async () => {
30
+ await client.connect("main", { host: "localhost", port: 3000, ssl: false });
31
+ });
32
+
33
+ onCleanup(async () => {
34
+ await client.close("main");
35
+ });
36
+
37
+ const handleCall = async () => {
38
+ const svc = client.get("main");
39
+ const result = await svc.call("MyService", "myMethod", [arg1, arg2]);
40
+ };
41
+ }
21
42
  ```
22
43
 
44
+ **useServiceClient API:**
45
+
46
+ | Method | Signature | Description |
47
+ |--------|-----------|-------------|
48
+ | `connect` | `(key: string, options?: Partial<ServiceConnectionConfig>) => Promise<void>` | Open WebSocket connection |
49
+ | `close` | `(key: string) => Promise<void>` | Close connection by key |
50
+ | `get` | `(key: string) => ServiceClient` | Get connected client by key (throws if not connected) |
51
+ | `isConnected` | `(key: string) => boolean` | Check connection state |
52
+
53
+ `ServiceConnectionConfig`: `{ host: string; port: number; ssl: boolean }`
54
+
55
+ Defaults for `host`, `port`, and `ssl` are derived from `window.location` when omitted.
56
+
23
57
  ---
24
58
 
25
59
  ## SharedDataProvider
26
60
 
27
- Shared data provider for managing server-side data subscriptions. Works with `ServiceClientProvider` to provide reactive shared data across components.
61
+ Shared data provider for managing server-side data subscriptions. Works with `ServiceClientProvider` to provide reactive shared data across components via `useSharedData`.
28
62
 
29
63
  ```tsx
30
- import { SharedDataProvider, SharedDataChangeEvent } from "@simplysm/solid";
64
+ import { SharedDataProvider, type SharedDataDefinition } from "@simplysm/solid";
65
+
66
+ interface MySharedData {
67
+ users: UserRecord;
68
+ products: ProductRecord;
69
+ }
31
70
 
32
- <SharedDataProvider>
71
+ const definitions: { [K in keyof MySharedData]: SharedDataDefinition<MySharedData[K]> } = {
72
+ users: {
73
+ serviceKey: "main",
74
+ fetch: async (changeKeys) => fetchUsers(changeKeys),
75
+ getKey: (item) => item.id,
76
+ orderBy: [(item) => item.name, "asc"],
77
+ },
78
+ products: {
79
+ serviceKey: "main",
80
+ fetch: async (changeKeys) => fetchProducts(changeKeys),
81
+ getKey: (item) => item.id,
82
+ orderBy: [(item) => item.name, "asc"],
83
+ },
84
+ };
85
+
86
+ <SharedDataProvider definitions={definitions}>
33
87
  <App />
34
88
  </SharedDataProvider>
35
89
  ```
90
+
91
+ **SharedDataProvider Props:**
92
+
93
+ | Prop | Type | Description |
94
+ |------|------|-------------|
95
+ | `definitions` | `{ [K in keyof TSharedData]: SharedDataDefinition<TSharedData[K]> }` | Map of data key to fetch definition |
96
+
97
+ **SharedDataDefinition type:**
98
+
99
+ ```typescript
100
+ interface SharedDataDefinition<TData> {
101
+ serviceKey: string; // Connection key (matches useServiceClient key)
102
+ fetch: (changeKeys?: Array<string | number>) => Promise<TData[]>; // Data fetch function
103
+ getKey: (item: TData) => string | number; // Primary key extractor
104
+ orderBy: [(item: TData) => unknown, "asc" | "desc"][]; // Sort order
105
+ filter?: unknown; // Optional filter for change events
106
+ }
107
+ ```
108
+
109
+ **useSharedData API:**
110
+
111
+ ```tsx
112
+ import { useSharedData } from "@simplysm/solid";
113
+
114
+ function MyComponent() {
115
+ const sharedData = useSharedData<MySharedData>();
116
+
117
+ const users = () => sharedData.users.items(); // Accessor<TData[]>
118
+ const user = () => sharedData.users.get(userId()); // TData | undefined
119
+
120
+ const handleUpdate = async () => {
121
+ await sharedData.users.emit([updatedUserId]); // trigger refetch for keys
122
+ };
123
+ }
124
+ ```
125
+
126
+ **SharedDataAccessor API:**
127
+
128
+ | Property/Method | Type | Description |
129
+ |-----------------|------|-------------|
130
+ | `items` | `Accessor<TData[]>` | Reactive item array |
131
+ | `get` | `(key: string \| number \| undefined) => TData \| undefined` | Get item by key |
132
+ | `emit` | `(changeKeys?: Array<string \| number>) => Promise<void>` | Emit change event to server (triggers refetch in all subscribers) |
133
+
134
+ **SharedDataValue extras:**
135
+
136
+ | Property/Method | Type | Description |
137
+ |-----------------|------|-------------|
138
+ | `wait` | `() => Promise<void>` | Wait until all initial fetches complete |
139
+ | `busy` | `Accessor<boolean>` | True while any fetch is in progress |
140
+
141
+ **SharedDataChangeEvent:**
142
+
143
+ `SharedDataChangeEvent` is the event definition used internally by `SharedDataProvider` to communicate data changes between server and clients. Export it if you need to emit changes from the server side.
144
+
145
+ ```typescript
146
+ import { SharedDataChangeEvent } from "@simplysm/solid";
147
+ ```
package/docs/styling.md CHANGED
@@ -22,9 +22,11 @@
22
22
  | `h-field` / `size-field` | Default field height (based on `py-1`) |
23
23
  | `h-field-sm` / `size-field-sm` | Small field height (based on `py-0.5`) |
24
24
  | `h-field-lg` / `size-field-lg` | Large field height (based on `py-2`) |
25
+ | `h-field-xl` / `size-field-xl` | Extra-large field height (based on `py-3`) |
25
26
  | `h-field-inset` / `size-field-inset` | Inset field height (excludes border) |
26
27
  | `h-field-inset-sm` / `size-field-inset-sm` | Small inset field height |
27
28
  | `h-field-inset-lg` / `size-field-inset-lg` | Large inset field height |
29
+ | `h-field-inset-xl` / `size-field-inset-xl` | Extra-large inset field height |
28
30
 
29
31
  ## z-index Layers
30
32
 
@@ -65,3 +67,91 @@ const baseClass = clsx(
65
67
 
66
68
  const className = twMerge(baseClass, props.class);
67
69
  ```
70
+
71
+ ## Exported Style Tokens
72
+
73
+ `@simplysm/solid` exports TypeScript style constants and type definitions for use when building custom components that integrate with the library's design system.
74
+
75
+ ### tokens.styles
76
+
77
+ ```typescript
78
+ import {
79
+ type ComponentSize, // "sm" | "lg" | "xl"
80
+ type SemanticTheme, // "primary" | "info" | "success" | "warning" | "danger" | "base"
81
+ borderDefault, // Tailwind classes for default border color
82
+ borderSubtle, // Tailwind classes for subtle border color
83
+ bgSurface, // Tailwind classes for surface background
84
+ textDefault, // Tailwind classes for default text color
85
+ textMuted, // Tailwind classes for muted text color
86
+ textPlaceholder, // Tailwind classes for placeholder text color
87
+ disabledOpacity, // Tailwind classes for disabled state opacity
88
+ paddingSm, // Tailwind classes for small padding (px-1.5 py-0.5)
89
+ paddingLg, // Tailwind classes for large padding (px-3 py-2)
90
+ paddingXl, // Tailwind classes for extra-large padding (px-4 py-3)
91
+ themeTokens, // Record<SemanticTheme, { solid, solidHover, light, text, hoverBg, border }>
92
+ } from "@simplysm/solid";
93
+ ```
94
+
95
+ ### patterns.styles
96
+
97
+ ```typescript
98
+ import {
99
+ iconButtonBase, // Base classes for icon-only buttons
100
+ insetFocusOutline, // Focus outline (focus-within) for inset fields
101
+ insetFocusOutlineSelf, // Focus outline (focus) for inset trigger elements
102
+ insetBase, // Base layout classes for inset mode
103
+ fieldSurface, // Field surface (background, border, focus ring)
104
+ inputBase, // Base classes for <input> elements
105
+ } from "@simplysm/solid";
106
+ ```
107
+
108
+ ### Field.styles
109
+
110
+ ```typescript
111
+ import {
112
+ type FieldSize, // "sm" | "lg" | "xl"
113
+ getFieldWrapperClass, // Utility to build field wrapper class string
114
+ getTextareaWrapperClass, // Utility to build textarea wrapper class string
115
+ fieldInputClass, // Base classes for field <input> element
116
+ fieldGapClasses, // Gap classes per size (with prefix icon)
117
+ } from "@simplysm/solid";
118
+ ```
119
+
120
+ ### Checkbox.styles
121
+
122
+ ```typescript
123
+ import {
124
+ type CheckboxSize, // "sm" | "lg" | "xl"
125
+ checkboxBaseClass, // Base wrapper classes
126
+ indicatorBaseClass, // Base indicator (box) classes
127
+ checkedClass, // Checked state classes (primary color)
128
+ checkboxSizeClasses, // Size variant classes
129
+ checkboxInsetClass, // Inset mode classes
130
+ checkboxInlineClass, // Inline display classes
131
+ checkboxDisabledClass, // Disabled state classes
132
+ } from "@simplysm/solid";
133
+ ```
134
+
135
+ ### DataSheet.styles
136
+
137
+ ```typescript
138
+ import {
139
+ dataSheetContainerClass, tableClass, thClass, thContentClass, tdClass,
140
+ summaryThClass, insetContainerClass, insetTableClass, defaultContainerClass,
141
+ sortableThClass, sortIconClass, toolbarClass, fixedClass, fixedLastClass,
142
+ resizerClass, resizeIndicatorClass, featureThClass, featureTdClass,
143
+ expandIndentGuideClass, expandIndentGuideLineClass, expandToggleClass,
144
+ reorderHandleClass, reorderIndicatorClass, configButtonClass,
145
+ // etc.
146
+ } from "@simplysm/solid";
147
+ ```
148
+
149
+ ### ListItem.styles
150
+
151
+ ```typescript
152
+ import {
153
+ listItemBaseClass, listItemSizeClasses, listItemSelectedClass,
154
+ listItemDisabledClass, listItemReadonlyClass, listItemIndentGuideClass,
155
+ listItemContentClass, getListItemSelectedIconClass,
156
+ } from "@simplysm/solid";
157
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/solid",
3
- "version": "13.0.29",
3
+ "version": "13.0.31",
4
4
  "description": "심플리즘 패키지 - SolidJS 라이브러리",
5
5
  "author": "김석래",
6
6
  "license": "Apache-2.0",
@@ -49,8 +49,8 @@
49
49
  "solid-tiptap": "^0.8.0",
50
50
  "tailwind-merge": "^3.4.1",
51
51
  "tailwindcss": "^3.4.19",
52
- "@simplysm/core-browser": "13.0.29",
53
- "@simplysm/core-common": "13.0.29"
52
+ "@simplysm/core-browser": "13.0.31",
53
+ "@simplysm/core-common": "13.0.31"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@solidjs/testing-library": "^0.8.10"
@@ -9,22 +9,21 @@ import {
9
9
  } from "@tabler/icons-solidjs";
10
10
  import { Button } from "../form-control/Button";
11
11
  import { Icon } from "../display/Icon";
12
-
13
- type PaginationSize = "sm" | "lg";
12
+ import { type ComponentSizeCompact } from "../../styles/tokens.styles";
14
13
 
15
14
  export interface PaginationProps extends JSX.HTMLAttributes<HTMLElement> {
16
- pageIndex: number;
17
- onPageIndexChange?: (pageIndex: number) => void;
15
+ page: number;
16
+ onPageChange?: (page: number) => void;
18
17
  totalPageCount: number;
19
18
  displayPageCount?: number;
20
- size?: PaginationSize;
19
+ size?: ComponentSizeCompact;
21
20
  }
22
21
 
23
22
  const baseClass = clsx("inline-flex items-center");
24
23
 
25
24
  const btnClass = clsx("border-none font-normal");
26
25
 
27
- const gapClasses: Record<PaginationSize | "default", string> = {
26
+ const gapClasses: Record<ComponentSizeCompact | "default", string> = {
28
27
  default: "gap-1",
29
28
  sm: "gap-0.5",
30
29
  lg: "gap-1.5",
@@ -33,8 +32,8 @@ const gapClasses: Record<PaginationSize | "default", string> = {
33
32
  export const Pagination: Component<PaginationProps> = (props) => {
34
33
  const [local, rest] = splitProps(props, [
35
34
  "class",
36
- "pageIndex",
37
- "onPageIndexChange",
35
+ "page",
36
+ "onPageChange",
38
37
  "totalPageCount",
39
38
  "displayPageCount",
40
39
  "size",
@@ -43,17 +42,17 @@ export const Pagination: Component<PaginationProps> = (props) => {
43
42
  const visibleCount = () => local.displayPageCount ?? 10;
44
43
 
45
44
  const pages = () => {
46
- const from = Math.floor(local.pageIndex / visibleCount()) * visibleCount();
47
- const to = Math.min(from + visibleCount(), local.totalPageCount);
45
+ const from = Math.floor((local.page - 1) / visibleCount()) * visibleCount() + 1;
46
+ const to = Math.min(from + visibleCount() - 1, local.totalPageCount);
48
47
  const result: number[] = [];
49
- for (let i = from; i < to; i++) {
48
+ for (let i = from; i <= to; i++) {
50
49
  result.push(i);
51
50
  }
52
51
  return result;
53
52
  };
54
53
 
55
- const hasPrev = () => (pages()[0] ?? 0) > 0;
56
- const hasNext = () => (pages()[pages().length - 1] ?? 0) < local.totalPageCount - 1;
54
+ const hasPrev = () => (pages()[0] ?? 1) > 1;
55
+ const hasNext = () => (pages()[pages().length - 1] ?? 1) < local.totalPageCount;
57
56
 
58
57
  const getClassName = () => twMerge(baseClass, gapClasses[local.size ?? "default"], local.class);
59
58
 
@@ -65,7 +64,7 @@ export const Pagination: Component<PaginationProps> = (props) => {
65
64
  variant="ghost"
66
65
  size={local.size}
67
66
  disabled={!hasPrev()}
68
- onClick={() => local.onPageIndexChange?.(0)}
67
+ onClick={() => local.onPageChange?.(1)}
69
68
  >
70
69
  <Icon icon={IconChevronsLeft} size="1em" />
71
70
  </Button>
@@ -75,7 +74,7 @@ export const Pagination: Component<PaginationProps> = (props) => {
75
74
  variant="ghost"
76
75
  size={local.size}
77
76
  disabled={!hasPrev()}
78
- onClick={() => local.onPageIndexChange?.((pages()[0] ?? 1) - 1)}
77
+ onClick={() => local.onPageChange?.((pages()[0] ?? 2) - 1)}
79
78
  >
80
79
  <Icon icon={IconChevronLeft} size="1em" />
81
80
  </Button>
@@ -83,12 +82,12 @@ export const Pagination: Component<PaginationProps> = (props) => {
83
82
  {(p) => (
84
83
  <Button
85
84
  class={btnClass}
86
- theme={p === local.pageIndex ? "primary" : "base"}
87
- variant={p === local.pageIndex ? "solid" : "ghost"}
85
+ theme={p === local.page ? "primary" : "base"}
86
+ variant={p === local.page ? "solid" : "ghost"}
88
87
  size={local.size}
89
- onClick={() => local.onPageIndexChange?.(p)}
88
+ onClick={() => local.onPageChange?.(p)}
90
89
  >
91
- {p + 1}
90
+ {p}
92
91
  </Button>
93
92
  )}
94
93
  </For>
@@ -98,7 +97,7 @@ export const Pagination: Component<PaginationProps> = (props) => {
98
97
  variant="ghost"
99
98
  size={local.size}
100
99
  disabled={!hasNext()}
101
- onClick={() => local.onPageIndexChange?.((pages()[pages().length - 1] ?? 0) + 1)}
100
+ onClick={() => local.onPageChange?.((pages()[pages().length - 1] ?? 0) + 1)}
102
101
  >
103
102
  <Icon icon={IconChevronRight} size="1em" />
104
103
  </Button>
@@ -108,7 +107,7 @@ export const Pagination: Component<PaginationProps> = (props) => {
108
107
  variant="ghost"
109
108
  size={local.size}
110
109
  disabled={!hasNext()}
111
- onClick={() => local.onPageIndexChange?.(local.totalPageCount - 1)}
110
+ onClick={() => local.onPageChange?.(local.totalPageCount)}
112
111
  >
113
112
  <Icon icon={IconChevronsRight} size="1em" />
114
113
  </Button>
@@ -15,7 +15,7 @@ const baseClass = clsx(
15
15
  // th
16
16
  "[&_th]:border-l [&_th]:border-t [&_th]:border-base-300 [&_th]:dark:border-base-600",
17
17
  "[&_th]:px-2 [&_th]:py-1",
18
- "[&_th]:bg-base-100 [&_th]:text-left [&_th]:font-semibold",
18
+ "[&_th]:bg-base-100 [&_th]:text-left [&_th]:font-bold",
19
19
  "[&_th]:dark:bg-base-800",
20
20
  // td
21
21
  "[&_td]:border-l [&_td]:border-t [&_td]:border-base-300 [&_td]:dark:border-base-600",
@@ -28,7 +28,7 @@ const baseClass = clsx(
28
28
  // th
29
29
  "[&_th]:border-l [&_th]:border-t [&_th]:border-base-300 [&_th]:dark:border-base-600",
30
30
  "[&_th]:px-2 [&_th]:py-1",
31
- "[&_th]:bg-base-100 [&_th]:text-center [&_th]:text-sm [&_th]:font-semibold",
31
+ "[&_th]:bg-base-100 [&_th]:text-center [&_th]:text-sm [&_th]:font-bold",
32
32
  "[&_th]:dark:bg-base-800",
33
33
  // td
34
34
  "[&_td]:border-l [&_td]:border-t [&_td]:border-base-300 [&_td]:dark:border-base-600",
@@ -20,6 +20,7 @@ import { BusyContainer } from "../../feedback/busy/BusyContainer";
20
20
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
21
21
  import { splitSlots } from "../../../helpers/splitSlots";
22
22
  import "./Kanban.css";
23
+ import { iconButtonBase } from "../../../styles/patterns.styles";
23
24
  import {
24
25
  KanbanContext,
25
26
  KanbanLaneContext,
@@ -46,11 +47,11 @@ const KanbanLaneTools: ParentComponent = (props) => (
46
47
 
47
48
  // ─── KanbanCard ──────────────────────────────────────────────────
48
49
 
49
- export interface KanbanCardProps extends Omit<
50
+ export interface KanbanCardProps<TCardValue = unknown> extends Omit<
50
51
  JSX.HTMLAttributes<HTMLDivElement>,
51
52
  "children" | "draggable"
52
53
  > {
53
- value?: unknown;
54
+ value?: TCardValue;
54
55
  draggable?: boolean;
55
56
  selectable?: boolean;
56
57
  contentClass?: string;
@@ -225,8 +226,11 @@ const KanbanCard: ParentComponent<KanbanCardProps> = (props) => {
225
226
 
226
227
  // ─── KanbanLane ──────────────────────────────────────────────────
227
228
 
228
- export interface KanbanLaneProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> {
229
- value?: unknown;
229
+ export interface KanbanLaneProps<TLaneValue = unknown> extends Omit<
230
+ JSX.HTMLAttributes<HTMLDivElement>,
231
+ "children"
232
+ > {
233
+ value?: TLaneValue;
230
234
  busy?: boolean;
231
235
  collapsible?: boolean;
232
236
  collapsed?: boolean;
@@ -248,20 +252,12 @@ const laneDragOverClass = clsx("bg-primary-50 dark:bg-primary-950");
248
252
  const laneHeaderBaseClass = clsx(
249
253
  "flex items-center gap-2",
250
254
  "px-3 py-2",
251
- "font-semibold",
255
+ "font-bold",
252
256
  "text-base-700 dark:text-base-200",
253
257
  "select-none",
254
258
  );
255
259
 
256
- const collapseButtonClass = clsx(
257
- "flex items-center justify-center",
258
- "size-6 rounded",
259
- "text-base-500",
260
- "hover:bg-base-200 hover:text-primary-500",
261
- "dark:hover:bg-base-800",
262
- "transition-colors duration-150",
263
- "cursor-pointer",
264
- );
260
+ const collapseButtonClass = twMerge(iconButtonBase, "size-6", "hover:text-primary-500");
265
261
 
266
262
  const laneToolsClass = clsx("flex items-center", "gap-1");
267
263
 
@@ -462,12 +458,7 @@ const KanbanLane: ParentComponent<KanbanLaneProps> = (props) => {
462
458
  </button>
463
459
  </Show>
464
460
  <Show when={hasSelectableCards()}>
465
- <Checkbox
466
- value={isAllSelected()}
467
- onValueChange={handleSelectAll}
468
- inline
469
- theme="primary"
470
- />
461
+ <Checkbox value={isAllSelected()} onValueChange={handleSelectAll} inline />
471
462
  </Show>
472
463
  <div class="flex-1">{slots().kanbanLaneTitle}</div>
473
464
  <Show when={slots().kanbanLaneTools.length > 0}>
@@ -494,20 +485,22 @@ const KanbanLane: ParentComponent<KanbanLaneProps> = (props) => {
494
485
 
495
486
  // ─── Kanban (Board) ──────────────────────────────────────────────
496
487
 
497
- export interface KanbanProps extends Omit<
488
+ export interface KanbanProps<TCardValue = unknown, TLaneValue = unknown> extends Omit<
498
489
  JSX.HTMLAttributes<HTMLDivElement>,
499
490
  "children" | "onDrop"
500
491
  > {
501
- onDrop?: (info: KanbanDropInfo) => void;
502
- selectedValues?: unknown[];
503
- onSelectedValuesChange?: (values: unknown[]) => void;
492
+ onDrop?: (info: KanbanDropInfo<TLaneValue, TCardValue>) => void;
493
+ selectedValues?: TCardValue[];
494
+ onSelectedValuesChange?: (values: TCardValue[]) => void;
504
495
  children?: JSX.Element;
505
496
  }
506
497
 
507
498
  const boardBaseClass = clsx("inline-flex flex-nowrap", "h-full", "gap-4");
508
499
 
509
500
  interface KanbanComponent {
510
- (props: KanbanProps): JSX.Element;
501
+ <TCardValue = unknown, TLaneValue = unknown>(
502
+ props: KanbanProps<TCardValue, TLaneValue>,
503
+ ): JSX.Element;
511
504
  Lane: typeof KanbanLane;
512
505
  Card: typeof KanbanCard;
513
506
  LaneTitle: typeof KanbanLaneTitle;
@@ -15,7 +15,7 @@ export const thClass = clsx(
15
15
  "border-b border-r border-base-300 dark:border-base-800",
16
16
  "overflow-hidden whitespace-nowrap",
17
17
  "p-0",
18
- "text-left font-semibold",
18
+ "text-left font-bold",
19
19
  "align-middle",
20
20
  );
21
21