@simplysm/solid 13.0.98 → 13.0.100

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.
package/docs/layout.md CHANGED
@@ -1,143 +1,177 @@
1
- # Layout
1
+ # Layout Components
2
2
 
3
- Source: `src/components/layout/**/*.tsx`
3
+ Source: `src/components/layout/**`
4
4
 
5
- ## FormGroup
5
+ ## `FormGroup`
6
6
 
7
- Vertical or inline form field group.
7
+ Vertical or inline form field grouping component.
8
8
 
9
- ```ts
10
- interface FormGroupProps extends JSX.HTMLAttributes<HTMLDivElement> {
11
- inline?: boolean; // horizontal layout with wrapping
9
+ ```typescript
10
+ export interface FormGroupProps extends JSX.HTMLAttributes<HTMLDivElement> {
11
+ inline?: boolean;
12
12
  }
13
13
  ```
14
14
 
15
+ | Prop | Type | Description |
16
+ |------|------|-------------|
17
+ | `inline` | `boolean` | Display items horizontally in a row |
18
+
15
19
  ### Sub-components
16
20
 
17
- - **`FormGroup.Item`** -- Labeled form item.
21
+ - **`FormGroup.Item`** -- Individual form field with optional label
18
22
 
19
- ```ts
20
- interface FormGroupItemProps extends JSX.HTMLAttributes<HTMLDivElement> {
23
+ ```typescript
24
+ export interface FormGroupItemProps extends JSX.HTMLAttributes<HTMLDivElement> {
21
25
  label?: JSX.Element;
22
26
  }
23
27
  ```
24
28
 
25
- ## FormTable
29
+ ---
30
+
31
+ ## `FormTable`
26
32
 
27
- Table-based form layout using `<table>` elements.
33
+ Table-based form layout with label-value pairs.
28
34
 
29
- ```ts
30
- interface FormTableProps extends JSX.HTMLAttributes<HTMLTableElement> {}
35
+ ```typescript
36
+ export interface FormTableProps extends JSX.HTMLAttributes<HTMLTableElement> {}
31
37
  ```
32
38
 
33
39
  ### Sub-components
34
40
 
35
- - **`FormTable.Row`** -- Table row. Extends `JSX.HTMLAttributes<HTMLTableRowElement>`.
36
- - **`FormTable.Item`** -- Labeled table cell. When `label` is omitted, the cell spans the label column.
41
+ - **`FormTable.Row`** -- Table row wrapper
42
+ - **`FormTable.Item`** -- Table cell with optional label (`th` + `td`)
37
43
 
38
- ```ts
39
- interface FormTableItemProps extends JSX.TdHTMLAttributes<HTMLTableCellElement> {
44
+ ```typescript
45
+ export interface FormTableItemProps extends JSX.TdHTMLAttributes<HTMLTableCellElement> {
40
46
  label?: JSX.Element;
41
47
  }
42
48
  ```
43
49
 
44
- ## Sidebar
50
+ ---
51
+
52
+ ## `Sidebar`
45
53
 
46
- Collapsible sidebar panel. Must be used inside `Sidebar.Container`.
54
+ Responsive sidebar navigation with user info and menu sections. Collapses on mobile with overlay backdrop.
47
55
 
48
- ```ts
49
- interface SidebarProps extends JSX.HTMLAttributes<HTMLElement> {
56
+ ```typescript
57
+ export interface SidebarProps extends JSX.HTMLAttributes<HTMLElement> {
50
58
  children: JSX.Element;
51
59
  }
52
60
  ```
53
61
 
54
- ### Sidebar.Container
62
+ ### Sub-components
63
+
64
+ - **`Sidebar.Container`** -- Root container providing sidebar context and responsive padding
65
+ - **`Sidebar.Menu`** -- Recursive menu list with pathname-based selection
66
+ - **`Sidebar.User`** -- User info section with optional dropdown menus
55
67
 
56
- Layout container that holds the Sidebar and content area. Provides `SidebarContext` for toggle state. Parent element must have height specified (use `h-full`).
68
+ ### `Sidebar.Container`
57
69
 
58
- ```ts
59
- interface SidebarContainerProps extends JSX.HTMLAttributes<HTMLDivElement> {
70
+ ```typescript
71
+ export interface SidebarContainerProps extends JSX.HTMLAttributes<HTMLDivElement> {
60
72
  children: JSX.Element;
61
73
  }
62
74
  ```
63
75
 
64
- - Desktop (640px+): uses `padding-left` transition to expand/collapse.
65
- - Mobile (<640px): renders backdrop overlay. Auto-closes on navigation.
76
+ ### `Sidebar.Menu`
66
77
 
67
- ### Sidebar.Menu
68
-
69
- Recursive sidebar menu with route-based selection.
70
-
71
- ```ts
72
- interface SidebarMenuProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> {
78
+ ```typescript
79
+ export interface SidebarMenuProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> {
73
80
  menus: AppMenu[];
74
- defaultOpen?: boolean; // expand all nested menus on initial render (default: false)
81
+ defaultOpen?: boolean;
75
82
  }
76
83
  ```
77
84
 
78
- - Parent items of the selected route auto-expand on initial render.
79
- - External links (containing `://`) open in a new tab.
85
+ | Prop | Type | Description |
86
+ |------|------|-------------|
87
+ | `menus` | `AppMenu[]` | Menu items array |
88
+ | `defaultOpen` | `boolean` | Expand all nested menus initially. Default: `false` |
80
89
 
81
- ### Sidebar.User
90
+ ### `Sidebar.User`
82
91
 
83
- User information area with optional dropdown menu.
84
-
85
- ```ts
86
- interface SidebarUserProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "onClick"> {
92
+ ```typescript
93
+ export interface SidebarUserProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "onClick"> {
87
94
  name: string;
88
95
  icon?: Component<TablerIconProps>;
89
96
  description?: string;
90
97
  menus?: SidebarUserMenu[];
91
98
  }
99
+ ```
92
100
 
93
- interface SidebarUserMenu {
101
+ | Prop | Type | Description |
102
+ |------|------|-------------|
103
+ | `name` | `string` | User name (required) |
104
+ | `icon` | `Component<TablerIconProps>` | Avatar icon. Default: user icon |
105
+ | `description` | `string` | Additional info (email, etc.) |
106
+ | `menus` | `SidebarUserMenu[]` | Dropdown menu items |
107
+
108
+ ### `SidebarUserMenu`
109
+
110
+ ```typescript
111
+ export interface SidebarUserMenu {
94
112
  title: string;
95
113
  onClick: () => void;
96
114
  }
97
115
  ```
98
116
 
99
- ### useSidebar()
117
+ ### `SidebarContextValue`
100
118
 
101
- Hook to access sidebar toggle state. Throws if used outside `Sidebar.Container`.
102
-
103
- ```ts
104
- function useSidebar(): {
119
+ ```typescript
120
+ export interface SidebarContextValue {
105
121
  toggle: Accessor<boolean>;
106
122
  setToggle: Setter<boolean>;
107
- };
108
- // Also available: useSidebar.optional() returns undefined if no context
123
+ }
109
124
  ```
110
125
 
111
- ## Topbar
126
+ ### `useSidebar`
127
+
128
+ Hook to access sidebar toggle state. Also has `useSidebar.optional()` variant.
129
+
130
+ ### `SM_MEDIA_QUERY`
131
+
132
+ ```typescript
133
+ export const SM_MEDIA_QUERY = "(min-width: 640px)";
134
+ ```
112
135
 
113
- Top navigation bar. Automatically shows a sidebar toggle button if used inside `Sidebar.Container`.
136
+ ---
114
137
 
115
- ```ts
116
- interface TopbarProps extends JSX.HTMLAttributes<HTMLElement> {
138
+ ## `Topbar`
139
+
140
+ Top navigation bar with sidebar toggle integration, dropdown menus, user section, and dynamic actions.
141
+
142
+ ```typescript
143
+ export interface TopbarProps extends JSX.HTMLAttributes<HTMLElement> {
117
144
  children: JSX.Element;
118
145
  }
119
146
  ```
120
147
 
121
- ### Topbar.Container
148
+ ### Sub-components
149
+
150
+ - **`Topbar.Container`** -- Layout container wrapping Topbar and content, provides actions context
151
+ - **`Topbar.Menu`** -- Dropdown navigation menu (responsive: desktop buttons / mobile hamburger)
152
+ - **`Topbar.User`** -- User information section with optional dropdown
153
+ - **`Topbar.Actions`** -- Renders actions set via `useTopbarActions()`
122
154
 
123
- Vertical layout container wrapping Topbar and content area. Provides `TopbarContext` for actions.
155
+ ### `Topbar.Container`
124
156
 
125
- ```ts
126
- interface TopbarContainerProps extends JSX.HTMLAttributes<HTMLDivElement> {
157
+ ```typescript
158
+ export interface TopbarContainerProps extends JSX.HTMLAttributes<HTMLDivElement> {
127
159
  children: JSX.Element;
128
160
  }
129
161
  ```
130
162
 
131
- ### Topbar.Menu
163
+ ### `Topbar.Menu`
132
164
 
133
- Dropdown navigation menu. Shows desktop buttons on 640px+ and a hamburger menu on mobile.
134
-
135
- ```ts
136
- interface TopbarMenuProps extends Omit<JSX.HTMLAttributes<HTMLElement>, "children"> {
165
+ ```typescript
166
+ export interface TopbarMenuProps extends Omit<JSX.HTMLAttributes<HTMLElement>, "children"> {
137
167
  menus: TopbarMenuItem[];
138
168
  }
169
+ ```
139
170
 
140
- interface TopbarMenuItem {
171
+ ### `TopbarMenuItem`
172
+
173
+ ```typescript
174
+ export interface TopbarMenuItem {
141
175
  title: string;
142
176
  href?: string;
143
177
  icon?: Component<IconProps>;
@@ -145,38 +179,34 @@ interface TopbarMenuItem {
145
179
  }
146
180
  ```
147
181
 
148
- ### Topbar.User
149
-
150
- User information component with optional dropdown menu.
182
+ ### `Topbar.User`
151
183
 
152
- ```ts
153
- interface TopbarUserProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "onClick"> {
184
+ ```typescript
185
+ export interface TopbarUserProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "onClick"> {
154
186
  menus?: TopbarUserMenu[];
155
187
  children: JSX.Element;
156
188
  }
189
+ ```
190
+
191
+ ### `TopbarUserMenu`
157
192
 
158
- interface TopbarUserMenu {
193
+ ```typescript
194
+ export interface TopbarUserMenu {
159
195
  title: string;
160
196
  onClick: () => void;
161
197
  }
162
198
  ```
163
199
 
164
- ### Topbar.Actions
165
-
166
- Renders action elements registered by `useTopbarActions()`.
167
-
168
- ### useTopbarActions()
200
+ ### `TopbarContextValue`
169
201
 
170
- Register action elements that appear in the Topbar. Automatically cleaned up on component unmount.
171
-
172
- ```ts
173
- function useTopbarActions(accessor: () => JSX.Element): void;
202
+ ```typescript
203
+ export interface TopbarContextValue {
204
+ actions: Accessor<JSX.Element | undefined>;
205
+ setActions: Setter<JSX.Element | undefined>;
206
+ }
174
207
  ```
175
208
 
176
- ### useTopbarActionsAccessor()
209
+ ### Hooks
177
210
 
178
- Read the current topbar actions signal.
179
-
180
- ```ts
181
- function useTopbarActionsAccessor(): Accessor<JSX.Element | undefined>;
182
- ```
211
+ - **`useTopbarActions(accessor: () => JSX.Element)`** -- Register dynamic actions for display in Topbar
212
+ - **`useTopbarActionsAccessor()`** -- Read registered actions
package/docs/providers.md CHANGED
@@ -1,177 +1,197 @@
1
1
  # Providers
2
2
 
3
- Source: `src/providers/**/*.tsx`
3
+ Source: `src/providers/**`
4
4
 
5
- ## ConfigContext / ConfigProvider
5
+ ## `ConfigProvider`
6
6
 
7
- App-level configuration providing the `clientName` used as a prefix for storage keys.
7
+ App-wide configuration context providing `clientName` used as storage key prefix.
8
8
 
9
- ```ts
10
- interface AppConfig {
9
+ ```typescript
10
+ export interface AppConfig {
11
11
  clientName: string;
12
12
  }
13
13
 
14
- const ConfigContext: Context<AppConfig>;
15
-
16
- function useConfig(): AppConfig;
17
-
18
- const ConfigProvider: ParentComponent<{ clientName: string }>;
14
+ export const ConfigContext: Context<AppConfig>;
15
+ export function useConfig(): AppConfig;
16
+ export const ConfigProvider: ParentComponent<{ clientName: string }>;
19
17
  ```
20
18
 
21
- ## SyncStorageProvider / useSyncStorage
19
+ ---
22
20
 
23
- Pluggable storage provider. Components use this adapter for persistent storage (localStorage fallback when no adapter is configured).
21
+ ## `SyncStorageProvider`
24
22
 
25
- ```ts
26
- interface StorageAdapter {
27
- getItem: (key: string) => Promise<string | null>;
28
- setItem: (key: string, value: string) => Promise<void>;
29
- removeItem: (key: string) => Promise<void>;
30
- }
23
+ Sync storage provider with configurable adapter (defaults to localStorage). Supports async adapters for cross-device sync.
31
24
 
32
- interface SyncStorageContextValue {
33
- adapter: Accessor<StorageAdapter | undefined>;
34
- configure: (adapter: StorageAdapter | undefined) => void;
25
+ ```typescript
26
+ export interface StorageAdapter {
27
+ getItem(key: string): string | null | Promise<string | null>;
28
+ setItem(key: string, value: string): void | Promise<unknown>;
29
+ removeItem(key: string): void | Promise<void>;
35
30
  }
36
31
 
37
- const SyncStorageContext: Context<SyncStorageContextValue>;
38
-
39
- function useSyncStorage(): SyncStorageContextValue | undefined;
32
+ export interface SyncStorageContextValue {
33
+ adapter: Accessor<StorageAdapter>;
34
+ configure: (fn: (origin: StorageAdapter) => StorageAdapter) => void;
35
+ }
40
36
 
41
- const SyncStorageProvider: ParentComponent;
37
+ export const SyncStorageContext: Context<SyncStorageContextValue>;
38
+ export function useSyncStorage(): SyncStorageContextValue | undefined;
39
+ export const SyncStorageProvider: ParentComponent;
42
40
  ```
43
41
 
44
- ## LoggerProvider
42
+ ---
43
+
44
+ ## `LoggerProvider`
45
45
 
46
- Logging adapter provider. Allows plugging in custom log writers.
46
+ Logger adapter provider. Defaults to consola. Configurable via decorator pattern.
47
47
 
48
- ```ts
49
- interface LogAdapter {
50
- write: (level: "log" | "info" | "warn" | "error", ...args: unknown[]) => void | Promise<void>;
48
+ ```typescript
49
+ export interface LogAdapter {
50
+ write(severity: "error" | "warn" | "info" | "log", ...data: any[]): Promise<void> | void;
51
51
  }
52
52
 
53
- interface LoggerContextValue {
54
- adapter: Accessor<LogAdapter | undefined>;
53
+ export interface LoggerContextValue {
54
+ adapter: Accessor<LogAdapter>;
55
55
  configure: (fn: (origin: LogAdapter) => LogAdapter) => void;
56
56
  }
57
57
 
58
- const LoggerContext: Context<LoggerContextValue>;
59
-
60
- const LoggerProvider: ParentComponent;
58
+ export const LoggerContext: Context<LoggerContextValue>;
59
+ export const LoggerProvider: ParentComponent;
61
60
  ```
62
61
 
63
- ## ThemeContext / ThemeProvider / useTheme
62
+ ---
63
+
64
+ ## `ThemeProvider`
64
65
 
65
- Light/dark/system theme management. Persists mode to synced storage.
66
+ Theme mode provider with OS dark mode detection. Persists to storage via `useSyncConfig`. Toggles `dark` class on `<html>`.
66
67
 
67
- ```ts
68
- type ThemeMode = "light" | "dark" | "system";
69
- type ResolvedTheme = "light" | "dark";
68
+ ```typescript
69
+ export type ThemeMode = "light" | "dark" | "system";
70
+ export type ResolvedTheme = "light" | "dark";
70
71
 
71
- interface ThemeContextValue {
72
- mode: Accessor<ThemeMode>;
73
- resolved: Accessor<ResolvedTheme>;
72
+ export function useTheme(): {
73
+ mode: () => ThemeMode;
74
74
  setMode: (mode: ThemeMode) => void;
75
+ resolvedTheme: () => ResolvedTheme;
75
76
  cycleMode: () => void;
76
- }
77
+ };
77
78
 
78
- function useTheme(): ThemeContextValue;
79
-
80
- const ThemeProvider: ParentComponent;
79
+ export const ThemeProvider: ParentComponent;
81
80
  ```
82
81
 
83
- - `cycleMode()`: light -> system -> dark -> light.
84
- - `resolved`: the actual applied theme after resolving "system" via `prefers-color-scheme`.
82
+ ---
85
83
 
86
- ## ServiceClientProvider / useServiceClient
84
+ ## `ServiceClientProvider`
87
85
 
88
- Service client connection provider for `@simplysm/service-client`.
86
+ WebSocket service client provider with key-based multi-connection management. Displays request/response progress via notifications.
89
87
 
90
- ```ts
91
- interface ServiceClientContextValue {
92
- client: Accessor<SdServiceClient | undefined>;
93
- connected: Accessor<boolean>;
94
- configure: (url: string) => void;
88
+ ```typescript
89
+ export interface ServiceClientContextValue {
90
+ connect: (key?: string, options?: Partial<ServiceConnectionOptions>) => Promise<void>;
91
+ close: (key?: string) => Promise<void>;
92
+ get: (key?: string) => ServiceClient;
93
+ isConnected: (key?: string) => boolean;
95
94
  }
96
95
 
97
- const ServiceClientContext: Context<ServiceClientContextValue>;
96
+ export const ServiceClientContext: Context<ServiceClientContextValue>;
97
+ export function useServiceClient(): ServiceClientContextValue;
98
+ export const ServiceClientProvider: ParentComponent;
99
+ ```
98
100
 
99
- function useServiceClient(): ServiceClientContextValue;
101
+ ---
100
102
 
101
- const ServiceClientProvider: ParentComponent;
102
- ```
103
+ ## `SharedDataProvider`
103
104
 
104
- ## SystemProvider
105
+ Reactive shared data provider that subscribes to server events for real-time data updates.
105
106
 
106
- Composite provider that bundles commonly used providers together.
107
+ ### `SharedDataDefinition`
107
108
 
108
- ```ts
109
- const SystemProvider: ParentComponent<{
110
- clientName: string;
111
- busyVariant?: BusyVariant;
112
- }>;
109
+ ```typescript
110
+ export interface SharedDataDefinition<TData> {
111
+ serviceKey?: string;
112
+ fetch: (changeKeys?: Array<string | number>) => Promise<TData[]>;
113
+ getKey: (item: TData) => string | number;
114
+ orderBy: [(item: TData) => unknown, "asc" | "desc"][];
115
+ filter?: unknown;
116
+ itemSearchText?: (item: TData) => string;
117
+ isItemHidden?: (item: TData) => boolean;
118
+ getParentKey?: (item: TData) => string | number | undefined;
119
+ }
113
120
  ```
114
121
 
115
- Internally wraps: `ConfigProvider`, `I18nProvider`, `SyncStorageProvider`, `LoggerProvider`, `ThemeProvider`, `BusyProvider`, `NotificationProvider`, `DialogProvider`, `PrintProvider`, `ErrorLoggerProvider`, `ClipboardProvider`, `PwaUpdateProvider`.
122
+ ### `SharedDataAccessor`
116
123
 
117
- ## I18nProvider / useI18n
124
+ ```typescript
125
+ export interface SharedDataAccessor<TData> {
126
+ items: Accessor<TData[]>;
127
+ get: (key: string | number | undefined) => TData | undefined;
128
+ emit: (changeKeys?: Array<string | number>) => Promise<void>;
129
+ getKey: (item: TData) => string | number;
130
+ itemSearchText?: (item: TData) => string;
131
+ isItemHidden?: (item: TData) => boolean;
132
+ getParentKey?: (item: TData) => string | number | undefined;
133
+ }
134
+ ```
118
135
 
119
- Internationalization provider with flat dictionary-based translations.
136
+ ---
120
137
 
121
- ```ts
122
- interface I18nContextValue {
123
- locale: Accessor<string>;
124
- t: (key: string, params?: Record<string, string>) => string;
125
- configure: (options: I18nConfigureOptions) => void;
126
- }
138
+ ## `SharedDataChangeEvent`
127
139
 
128
- interface I18nConfigureOptions {
129
- locale?: string;
130
- dict?: Record<string, unknown>; // nested dict, auto-flattened
131
- flatDict?: FlatDict; // pre-flattened dict
132
- }
140
+ Server-client shared data change event definition.
141
+
142
+ ```typescript
143
+ export const SharedDataChangeEvent: EventDefinition<
144
+ { name: string; filter: unknown },
145
+ (string | number)[] | undefined
146
+ >;
147
+ ```
133
148
 
134
- type FlatDict = Record<string, string>;
149
+ ---
135
150
 
136
- function useI18n(): I18nContextValue;
151
+ ## `SystemProvider`
137
152
 
138
- const I18nProvider: ParentComponent;
153
+ All-in-one provider that composes Config, I18n, SyncStorage, Logger, Notification, ErrorLogger, PwaUpdate, Clipboard, Theme, ServiceClient, SharedData, and Busy providers.
154
+
155
+ ```typescript
156
+ export const SystemProvider: ParentComponent<{
157
+ clientName: string;
158
+ busyVariant?: BusyVariant;
159
+ }>;
139
160
  ```
140
161
 
141
- - `t("key", { name: "value" })`: interpolates `{name}` placeholders.
142
- - `configure()`: merges new dictionaries into existing translations.
162
+ ---
143
163
 
144
- ## SharedDataProvider / useSharedData
164
+ ## `I18nProvider`
145
165
 
146
- Shared data cache provider. Loads and caches data from service, auto-refreshes on change events.
166
+ Internationalization provider with built-in `en` and `ko` dictionaries.
147
167
 
148
- ```ts
149
- interface SharedDataDefinition<TData> {
150
- key: string;
151
- loader: () => Promise<TData[]>;
152
- getKey: (item: TData) => string | number;
153
- getSearchText?: (item: TData) => string;
154
- getChildren?: (item: TData, allItems: TData[]) => TData[];
155
- }
168
+ ```typescript
169
+ export function useI18n(): I18nContextValue;
170
+ export const I18nProvider: ParentComponent;
171
+ ```
156
172
 
157
- interface SharedDataAccessor<TData> {
158
- items: Accessor<TData[]>;
159
- loading: Accessor<boolean>;
160
- refresh: () => Promise<void>;
161
- getByKey: (key: string | number) => TData | undefined;
173
+ ### `I18nContextValue`
174
+
175
+ ```typescript
176
+ export interface I18nContextValue {
177
+ t: (key: string, params?: Record<string, string>) => string;
178
+ locale: Accessor<string>;
179
+ setLocale: (locale: string) => void;
180
+ configure: (options: I18nConfigureOptions) => void;
162
181
  }
182
+ ```
163
183
 
164
- function useSharedData<TSharedData extends Record<string, unknown>>(): SharedDataValue<TSharedData>;
184
+ ### `I18nConfigureOptions`
165
185
 
166
- function SharedDataProvider(props: { children: JSX.Element }): JSX.Element;
186
+ ```typescript
187
+ export interface I18nConfigureOptions {
188
+ locale?: string;
189
+ dict?: Record<string, Record<string, unknown>>;
190
+ }
167
191
  ```
168
192
 
169
- ### SharedDataChangeEvent
193
+ ### `FlatDict`
170
194
 
171
- Event emitted when shared data changes, triggering refresh.
172
-
173
- ```ts
174
- const SharedDataChangeEvent: EventDefinition<{
175
- key: string;
176
- }>;
195
+ ```typescript
196
+ export type FlatDict = Record<string, string>;
177
197
  ```