@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/features.md CHANGED
@@ -1,175 +1,198 @@
1
1
  # Feature Components
2
2
 
3
- Source: `src/components/features/**/*.tsx`
3
+ Source: `src/components/features/**`
4
4
 
5
- ## AddressSearchContent
5
+ ## `AddressSearchContent`
6
6
 
7
- Korean address search component using Daum Postcode API.
7
+ Korean address search dialog content using Daum Postcode API.
8
8
 
9
- ```ts
10
- interface AddressSearchResult {
9
+ ```typescript
10
+ export interface AddressSearchResult {
11
11
  postNumber: string | undefined;
12
12
  address: string | undefined;
13
13
  buildingName: string | undefined;
14
14
  }
15
-
16
- const AddressSearchContent: Component<{
17
- close?: (result?: AddressSearchResult) => void;
18
- }>;
19
15
  ```
20
16
 
21
- Designed for use with `useDialog().show()`. Loads the Daum Postcode script on mount.
17
+ Props: `{ close?: (result?: AddressSearchResult) => void }`
22
18
 
23
- ## SharedDataSelect
19
+ Designed to be used with `useDialog().show()`.
24
20
 
25
- Select component bound to a shared data definition. Supports single and multiple modes with the same prop variants as `Select`.
21
+ ---
26
22
 
27
- ```ts
28
- type SharedDataSelectProps<TItem, TDataKey extends string> = {
29
- dataKey: TDataKey;
30
- // ...inherits Select props (value, onValueChange, multiple, etc.)
31
- // plus shared data specific:
32
- getItemSearchText?: (item: TItem) => string;
33
- isItemHidden?: (item: TItem) => boolean;
34
- };
35
- ```
23
+ ## `SharedDataSelect`
36
24
 
37
- ### Sub-components
25
+ Select component integrated with `SharedDataAccessor` for reactive shared data selection. Supports single and multiple modes with search, tree structure, and dialog selection.
38
26
 
39
- - **`SharedDataSelect.ItemTemplate`** -- Render template for items.
27
+ | Prop | Type | Description |
28
+ |------|------|-------------|
29
+ | `data` | `SharedDataAccessor<TItem>` | Shared data accessor |
30
+ | `value` | `TKey \| TKey[]` | Selected key(s) |
31
+ | `onValueChange` | `(value) => void` | Value change callback |
32
+ | `multiple` | `boolean` | Multiple selection mode |
33
+ | `required` | `boolean` | Required input |
34
+ | `disabled` | `boolean` | Disabled state |
35
+ | `size` | `ComponentSize` | Trigger size |
36
+ | `inset` | `boolean` | Borderless style |
37
+ | `filterFn` | `(item, index) => boolean` | Item filter function |
38
+ | `dialog` | `Component<TDialogProps>` | Selection dialog component |
39
+ | `dialogOptions` | `DialogShowOptions` | Dialog display options |
40
40
 
41
- ## SharedDataSelectButton
41
+ ---
42
42
 
43
- Button that opens a shared data selection dialog.
43
+ ## `SharedDataSelectButton`
44
44
 
45
- ```ts
46
- type SharedDataSelectButtonProps<TItem, TDataKey extends string> = {
47
- dataKey: TDataKey;
48
- value?: TItem | TItem[];
49
- onValueChange?: (value: TItem | TItem[] | undefined) => void;
50
- renderValue?: (value: TItem) => JSX.Element;
51
- // ...plus button/validation props
52
- };
53
- ```
45
+ Button-based select component for shared data. Opens a dialog for selection. Supports single and multiple modes.
46
+
47
+ | Prop | Type | Description |
48
+ |------|------|-------------|
49
+ | `data` | `SharedDataAccessor<TItem>` | Shared data accessor |
50
+ | `value` | `string \| number \| (string \| number)[]` | Selected key(s) |
51
+ | `onValueChange` | `(value) => void` | Value change callback |
52
+ | `multiple` | `boolean` | Multiple selection mode |
53
+ | `required` | `boolean` | Required input |
54
+ | `disabled` | `boolean` | Disabled state |
55
+ | `size` | `ComponentSize` | Trigger size |
56
+ | `inset` | `boolean` | Borderless style |
57
+ | `dialog` | `Component<TDialogProps>` | Selection dialog component (required) |
58
+ | `dialogOptions` | `DialogShowOptions` | Dialog display options |
59
+ | `children` | `(item: TItem) => JSX.Element` | Item rendering function |
54
60
 
55
- ## SharedDataSelectList
61
+ ---
56
62
 
57
- List component bound to shared data, rendering items from a shared data definition.
63
+ ## `SharedDataSelectList`
58
64
 
59
- ```ts
60
- interface SharedDataSelectListProps<TItem> {
61
- dataKey: string;
62
- value?: unknown[];
63
- onValueChange?: (value: unknown[]) => void;
64
- // ...list configuration props
65
+ List-based selection component for shared data with pagination and search.
66
+
67
+ ```typescript
68
+ export interface SharedDataSelectListProps<TItem> {
69
+ data: SharedDataAccessor<TItem>;
70
+ value?: TItem;
71
+ onValueChange?: (value: TItem | undefined) => void;
72
+ required?: boolean;
73
+ disabled?: boolean;
74
+ filterFn?: (item: TItem, index: number) => boolean;
65
75
  }
66
76
  ```
67
77
 
68
78
  ### Sub-components
69
79
 
70
- - **`SharedDataSelectList.ItemTemplate`** -- Render template for list items.
71
-
72
- ## DataSelectButton
80
+ - **`SharedDataSelectList.ItemTemplate`** -- Template for item rendering
81
+ - **`SharedDataSelectList.Filter`** -- Custom filter UI slot
73
82
 
74
- Button that opens a custom data selection dialog. Generic over key type and dialog props.
83
+ ### `SharedDataSelectListContextValue`
75
84
 
76
- ```ts
77
- interface DataSelectButtonProps<TKey, TDialogProps> {
78
- value?: TKey | TKey[];
79
- onValueChange?: (value: TKey | TKey[] | undefined) => void;
80
- renderValue?: (value: TKey) => JSX.Element;
81
- dialog: Component<TDialogProps>;
82
- dialogProps?: Omit<TDialogProps, "close">;
83
- multiple?: boolean;
84
- disabled?: boolean;
85
- required?: boolean;
86
- size?: ComponentSize;
87
- inset?: boolean;
88
- class?: string;
89
- style?: JSX.CSSProperties;
85
+ ```typescript
86
+ export interface SharedDataSelectListContextValue {
87
+ setItemTemplate: (fn: ((...args: unknown[]) => JSX.Element) | undefined) => void;
90
88
  }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## `DataSelectButton`
94
+
95
+ Generic button-based select component that opens a dialog for selection. Works with any data source (not tied to SharedData).
96
+
97
+ ### `SelectDialogBaseProps`
91
98
 
92
- interface DataSelectDialogResult<TKey> {
99
+ ```typescript
100
+ export interface SelectDialogBaseProps<TKey = string | number> {
101
+ close?: (result?: DataSelectDialogResult<TKey>) => void;
102
+ selectionMode: "single" | "multiple";
93
103
  selectedKeys: TKey[];
94
104
  }
105
+ ```
95
106
 
96
- interface SelectDialogBaseProps<TKey> {
97
- close?: (result?: DataSelectDialogResult<TKey>) => void;
98
- initialSelectedKeys?: TKey[];
99
- selectionMode?: "single" | "multiple";
107
+ ### `DataSelectDialogResult`
108
+
109
+ ```typescript
110
+ export interface DataSelectDialogResult<TKey> {
111
+ selectedKeys: TKey[];
100
112
  }
101
113
  ```
102
114
 
103
- ## CrudSheet
115
+ ### `DialogPropsField`
104
116
 
105
- Full-featured CRUD data grid combining DataSheet with search, pagination, sorting, inline/dialog editing, selection, and Excel import/export.
117
+ Conditional type that makes `dialogProps` required only when the dialog component has required custom props.
106
118
 
107
- ```ts
108
- type CrudSheetProps<TItem, TFilter extends Record<string, unknown>> = {
109
- search: (filter: TFilter, page: number | undefined, sorts: SortingDef[]) => Promise<SearchResult<TItem>>;
110
- getItemKey: (item: TItem) => string | number | undefined;
111
- storageKey?: string;
112
- editable?: boolean;
113
- isItemEditable?: (item: TItem) => boolean;
114
- isItemDeletable?: (item: TItem) => boolean;
115
- isItemDeleted?: (item: TItem) => boolean;
116
- isItemSelectable?: (item: TItem) => boolean | string;
117
- lastModifiedAtProp?: string;
118
- lastModifiedByProp?: string;
119
- filterInitial?: TFilter;
120
- items?: TItem[];
121
- onItemsChange?: (items: TItem[]) => void;
122
- excel?: ExcelConfig<TItem>;
123
- selectionMode?: "single" | "multiple";
124
- selectedKeys?: (string | number)[];
125
- onSelectedKeysChange?: (keys: (string | number)[]) => void;
126
- onSelect?: (result: SelectResult<TItem>) => void;
127
- onSubmitComplete?: () => void;
128
- hideAutoTools?: boolean;
129
- close?: () => void;
130
- class?: string;
131
- children: JSX.Element;
132
- } & (
133
- | { inlineEdit: InlineEditConfig<TItem>; dialogEdit?: never }
134
- | { dialogEdit: DialogEditConfig<TItem>; inlineEdit?: never }
135
- | { inlineEdit?: never; dialogEdit?: never }
136
- );
137
-
138
- interface SearchResult<TItem> {
119
+ ```typescript
120
+ export type DialogPropsField<P, TKey = string | number> =
121
+ {} extends UserDialogProps<P, TKey>
122
+ ? { dialogProps?: UserDialogProps<P, TKey> }
123
+ : { dialogProps: UserDialogProps<P, TKey> };
124
+ ```
125
+
126
+ ---
127
+
128
+ ## `CrudSheet`
129
+
130
+ Full-featured CRUD data grid with inline/dialog editing, sorting, pagination, selection, excel import/export, and toolbar management.
131
+
132
+ ```typescript
133
+ export type CrudSheetProps<TItem, TFilter extends Record<string, unknown>> =
134
+ CrudSheetBaseProps<TItem, TFilter> & (
135
+ | { inlineEdit: InlineEditConfig<TItem>; dialogEdit?: never }
136
+ | { dialogEdit: DialogEditConfig<TItem>; inlineEdit?: never }
137
+ | { inlineEdit?: never; dialogEdit?: never }
138
+ );
139
+ ```
140
+
141
+ | Prop | Type | Description |
142
+ |------|------|-------------|
143
+ | `search` | `(filter, page, sorts) => Promise<SearchResult<TItem>>` | Data fetch function |
144
+ | `getItemKey` | `(item) => string \| number \| undefined` | Item key extractor |
145
+ | `storageKey` | `string` | Config persistence key |
146
+ | `editable` | `boolean` | Enable editing |
147
+ | `inlineEdit` | `InlineEditConfig<TItem>` | Inline editing configuration |
148
+ | `dialogEdit` | `DialogEditConfig<TItem>` | Dialog editing configuration |
149
+ | `excel` | `ExcelConfig<TItem>` | Excel download/upload |
150
+ | `selectionMode` | `"single" \| "multiple"` | Selection mode |
151
+ | `filterInitial` | `TFilter` | Initial filter state |
152
+
153
+ ### `SearchResult`
154
+
155
+ ```typescript
156
+ export interface SearchResult<TItem> {
139
157
  items: TItem[];
140
158
  pageCount?: number;
141
159
  }
160
+ ```
142
161
 
143
- interface InlineEditConfig<TItem> {
162
+ ### `InlineEditConfig`
163
+
164
+ ```typescript
165
+ export interface InlineEditConfig<TItem> {
144
166
  submit: (diffs: ArrayOneWayDiffResult<TItem>[]) => Promise<void>;
145
167
  newItem: () => TItem;
146
168
  deleteProp?: keyof TItem & string;
147
169
  diffsExcludes?: string[];
148
170
  }
171
+ ```
149
172
 
150
- interface DialogEditConfig<TItem> {
173
+ ### `DialogEditConfig`
174
+
175
+ ```typescript
176
+ export interface DialogEditConfig<TItem> {
151
177
  editItem: (item?: TItem) => Promise<boolean | undefined>;
152
178
  deleteItems?: (items: TItem[]) => Promise<boolean>;
153
179
  restoreItems?: (items: TItem[]) => Promise<boolean>;
154
180
  }
181
+ ```
182
+
183
+ ### `ExcelConfig`
155
184
 
156
- interface ExcelConfig<TItem> {
185
+ ```typescript
186
+ export interface ExcelConfig<TItem> {
157
187
  download: (items: TItem[]) => Promise<void>;
158
188
  upload?: (file: File) => Promise<void>;
159
189
  }
160
190
  ```
161
191
 
162
- ### Sub-components
163
-
164
- - **`CrudSheet.Column<TItem>`** -- Column definition with cell context.
165
-
166
- ```ts
167
- interface CrudSheetColumnProps<TItem> extends Omit<DataSheetColumnProps<TItem>, "children"> {
168
- editTrigger?: boolean;
169
- children: (ctx: CrudSheetCellContext<TItem>) => JSX.Element;
170
- }
192
+ ### `CrudSheetCellContext`
171
193
 
172
- interface CrudSheetCellContext<TItem> {
194
+ ```typescript
195
+ export interface CrudSheetCellContext<TItem> {
173
196
  item: TItem;
174
197
  index: number;
175
198
  row: number;
@@ -178,23 +201,10 @@ interface CrudSheetCellContext<TItem> {
178
201
  }
179
202
  ```
180
203
 
181
- - **`CrudSheet.Filter<TFilter>`** -- Filter panel slot.
204
+ ### `CrudSheetContext`
182
205
 
183
- ```ts
184
- interface CrudSheetFilterSlotProps<TFilter> {
185
- filter: TFilter;
186
- setFilter: SetStoreFunction<TFilter>;
187
- }
188
- ```
189
-
190
- - **`CrudSheet.Tools<TItem>`** -- Toolbar slot with context.
191
-
192
- ```ts
193
- interface CrudSheetToolsSlotProps<TItem> {
194
- ctx: CrudSheetContext<TItem>;
195
- }
196
-
197
- interface CrudSheetContext<TItem> {
206
+ ```typescript
207
+ export interface CrudSheetContext<TItem> {
198
208
  items(): TItem[];
199
209
  selection(): TItem[];
200
210
  page(): number;
@@ -210,12 +220,32 @@ interface CrudSheetContext<TItem> {
210
220
  }
211
221
  ```
212
222
 
213
- ## CrudDetail
223
+ ### `SelectResult`
224
+
225
+ ```typescript
226
+ export interface SelectResult<TItem> {
227
+ items: TItem[];
228
+ keys: (string | number)[];
229
+ }
230
+ ```
231
+
232
+ ### `CrudSheetColumnProps`
233
+
234
+ ```typescript
235
+ export interface CrudSheetColumnProps<TItem> extends Omit<DataSheetColumnProps<TItem>, "children"> {
236
+ editTrigger?: boolean;
237
+ children: (ctx: CrudSheetCellContext<TItem>) => JSX.Element;
238
+ }
239
+ ```
240
+
241
+ ---
214
242
 
215
- CRUD detail form with load, save, delete, and change tracking.
243
+ ## `CrudDetail`
216
244
 
217
- ```ts
218
- interface CrudDetailProps<TData extends object> {
245
+ CRUD detail view with controlled store, save/refresh lifecycle, and delete toggle.
246
+
247
+ ```typescript
248
+ export interface CrudDetailProps<TData extends object> {
219
249
  load: () => Promise<{ data: TData; info: CrudDetailInfo }>;
220
250
  children: (ctx: CrudDetailContext<TData>) => JSX.Element;
221
251
  submit?: (data: TData) => Promise<boolean | undefined>;
@@ -227,15 +257,23 @@ interface CrudDetailProps<TData extends object> {
227
257
  close?: (result?: boolean) => void;
228
258
  class?: string;
229
259
  }
260
+ ```
230
261
 
231
- interface CrudDetailInfo {
262
+ ### `CrudDetailInfo`
263
+
264
+ ```typescript
265
+ export interface CrudDetailInfo {
232
266
  isNew: boolean;
233
267
  isDeleted: boolean;
234
268
  lastModifiedAt?: DateTime;
235
269
  lastModifiedBy?: string;
236
270
  }
271
+ ```
237
272
 
238
- interface CrudDetailContext<TData> {
273
+ ### `CrudDetailContext`
274
+
275
+ ```typescript
276
+ export interface CrudDetailContext<TData> {
239
277
  data: TData;
240
278
  setData: SetStoreFunction<TData>;
241
279
  info: () => CrudDetailInfo;
@@ -246,34 +284,27 @@ interface CrudDetailContext<TData> {
246
284
  }
247
285
  ```
248
286
 
249
- ### Sub-components
250
-
251
- - **`CrudDetail.Header`** -- Header content slot.
287
+ ---
252
288
 
253
- ## PermissionTable
289
+ ## `PermissionTable`
254
290
 
255
- Permission matrix table displaying app permissions with checkboxes.
291
+ Permission management table displaying a tree of `AppPerm` items with checkbox columns for each permission type.
256
292
 
257
- ```ts
258
- interface PermissionTableProps<TModule = string> {
259
- perms: AppPerm<TModule>[];
260
- value?: string[];
261
- onValueChange?: (value: string[]) => void;
293
+ ```typescript
294
+ export interface PermissionTableProps<TModule = string> {
295
+ items?: AppPerm<TModule>[];
296
+ value?: Record<string, boolean>;
297
+ onValueChange?: (value: Record<string, boolean>) => void;
298
+ modules?: TModule[];
262
299
  disabled?: boolean;
263
300
  class?: string;
264
301
  style?: JSX.CSSProperties;
265
302
  }
266
303
  ```
267
304
 
268
- ### Helper Functions
269
-
270
- ```ts
271
- function collectAllPerms<TModule>(items: AppPerm<TModule>[]): string[];
272
- function filterByModules<TModule>(items: AppPerm<TModule>[], enabledModules: TModule[]): AppPerm<TModule>[];
273
- function changePermCheck<TModule>(
274
- items: AppPerm<TModule>[],
275
- currentPerms: string[],
276
- changedPerm: string,
277
- checked: boolean,
278
- ): string[];
305
+ ### Utility Functions
306
+
307
+ ```typescript
308
+ export function collectAllPerms<TModule>(items: AppPerm<TModule>[]): string[];
309
+ export function filterByModules<TModule>(items: AppPerm<TModule>[], modules: TModule[]): AppPerm<TModule>[];
279
310
  ```