@simplysm/solid 13.0.96 → 13.0.98
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/README.md +314 -123
- package/docs/data.md +216 -0
- package/docs/disclosure.md +164 -0
- package/docs/display.md +94 -0
- package/docs/features.md +211 -625
- package/docs/feedback.md +210 -0
- package/docs/form-control.md +537 -0
- package/docs/helpers.md +168 -0
- package/docs/hooks.md +143 -0
- package/docs/layout.md +182 -0
- package/docs/providers.md +177 -0
- package/docs/styles.md +127 -0
- package/package.json +19 -26
- package/docs/display-feedback.md +0 -404
- package/docs/form-controls.md +0 -587
- package/docs/layout-data.md +0 -392
- package/docs/providers-hooks.md +0 -516
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
# Form Controls
|
|
2
|
+
|
|
3
|
+
Source: `src/components/form-control/**/*.tsx`
|
|
4
|
+
|
|
5
|
+
## Button
|
|
6
|
+
|
|
7
|
+
Themed button with ripple effect. Extends `JSX.ButtonHTMLAttributes<HTMLButtonElement>`.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface ButtonProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
11
|
+
theme?: SemanticTheme; // "primary" | "info" | "success" | "warning" | "danger" | "base" (default: "base")
|
|
12
|
+
variant?: "solid" | "outline" | "ghost"; // default: "outline"
|
|
13
|
+
size?: ComponentSize; // "xs" | "sm" | "md" | "lg" | "xl" (default: "md")
|
|
14
|
+
inset?: boolean; // borderless style
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Select
|
|
19
|
+
|
|
20
|
+
Single or multiple select dropdown. Supports two modes: `items` prop mode and `children` mode.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
// Common props
|
|
24
|
+
interface SelectCommonProps<TValue> {
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
size?: ComponentSize;
|
|
29
|
+
inset?: boolean;
|
|
30
|
+
validate?: (value: unknown) => string | undefined;
|
|
31
|
+
lazyValidation?: boolean;
|
|
32
|
+
itemSearchText?: (item: TValue) => string; // enables search input
|
|
33
|
+
isItemHidden?: (item: TValue) => boolean;
|
|
34
|
+
class?: string;
|
|
35
|
+
style?: JSX.CSSProperties;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Single select
|
|
39
|
+
interface SelectSingleProps<TValue> extends SelectCommonProps<TValue> {
|
|
40
|
+
multiple?: false;
|
|
41
|
+
value?: TValue;
|
|
42
|
+
onValueChange?: (value: TValue | undefined) => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Multiple select
|
|
46
|
+
interface SelectMultipleProps<TValue> extends SelectCommonProps<TValue> {
|
|
47
|
+
multiple: true;
|
|
48
|
+
value?: TValue[];
|
|
49
|
+
onValueChange?: (value: TValue[]) => void;
|
|
50
|
+
tagDirection?: "horizontal" | "vertical";
|
|
51
|
+
hideSelectAll?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Items mode: pass items array + ItemTemplate
|
|
55
|
+
// Children mode: pass children + renderValue
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Sub-components
|
|
59
|
+
|
|
60
|
+
- **`Select.Item<TValue>`** -- Selectable item. Props: `value: TValue`, `disabled?: boolean`. Supports nested items via `Select.Item.Children`.
|
|
61
|
+
- **`Select.Header`** -- Custom header slot rendered above dropdown list.
|
|
62
|
+
- **`Select.Action`** -- Action button appended to the trigger. Extends button attributes.
|
|
63
|
+
- **`Select.ItemTemplate`** -- Render template for `items` mode. Child is a function: `(item, index, depth) => JSX.Element`.
|
|
64
|
+
|
|
65
|
+
## Combobox
|
|
66
|
+
|
|
67
|
+
Autocomplete component with async search and debounced loading.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
interface ComboboxBaseProps<TValue> {
|
|
71
|
+
value?: TValue;
|
|
72
|
+
onValueChange?: (value: TValue) => void;
|
|
73
|
+
loadItems: (query: string) => TValue[] | Promise<TValue[]>; // required
|
|
74
|
+
debounceMs?: number; // default: 300
|
|
75
|
+
renderValue: (value: TValue) => JSX.Element; // required
|
|
76
|
+
disabled?: boolean;
|
|
77
|
+
required?: boolean;
|
|
78
|
+
validate?: (value: TValue | undefined) => string | undefined;
|
|
79
|
+
lazyValidation?: boolean;
|
|
80
|
+
placeholder?: string;
|
|
81
|
+
size?: ComponentSize;
|
|
82
|
+
inset?: boolean;
|
|
83
|
+
class?: string;
|
|
84
|
+
style?: JSX.CSSProperties;
|
|
85
|
+
children?: JSX.Element;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Custom value variants
|
|
89
|
+
interface ComboboxCustomParserProps<TValue> extends ComboboxBaseProps<TValue> {
|
|
90
|
+
allowsCustomValue: true;
|
|
91
|
+
parseCustomValue: (text: string) => TValue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface ComboboxCustomStringProps extends ComboboxBaseProps<string> {
|
|
95
|
+
allowsCustomValue: true;
|
|
96
|
+
parseCustomValue?: undefined; // TValue must be string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface ComboboxDefaultProps<TValue> extends ComboboxBaseProps<TValue> {
|
|
100
|
+
allowsCustomValue?: false;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Sub-components
|
|
105
|
+
|
|
106
|
+
- **`Combobox.Item<TValue>`** -- Selectable item. Props: `value: TValue`, `disabled?: boolean`.
|
|
107
|
+
- **`Combobox.ItemTemplate`** -- Render template for loaded items. Child is a function: `(item, index) => JSX.Element`.
|
|
108
|
+
|
|
109
|
+
## TextInput
|
|
110
|
+
|
|
111
|
+
Text input field with format support and IME handling.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
interface TextInputProps {
|
|
115
|
+
value?: string;
|
|
116
|
+
onValueChange?: (value: string) => void;
|
|
117
|
+
type?: "text" | "password" | "email";
|
|
118
|
+
placeholder?: string;
|
|
119
|
+
title?: string;
|
|
120
|
+
autocomplete?: JSX.HTMLAutocomplete;
|
|
121
|
+
disabled?: boolean;
|
|
122
|
+
readOnly?: boolean;
|
|
123
|
+
size?: ComponentSize;
|
|
124
|
+
inset?: boolean;
|
|
125
|
+
format?: string; // e.g., "XXX-XXXX-XXXX"
|
|
126
|
+
required?: boolean;
|
|
127
|
+
minLength?: number;
|
|
128
|
+
maxLength?: number;
|
|
129
|
+
pattern?: string | RegExp;
|
|
130
|
+
validate?: (value: string) => string | undefined;
|
|
131
|
+
lazyValidation?: boolean;
|
|
132
|
+
class?: string;
|
|
133
|
+
style?: JSX.CSSProperties;
|
|
134
|
+
children?: JSX.Element; // TextInput.Prefix slot
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Sub-components
|
|
139
|
+
|
|
140
|
+
- **`TextInput.Prefix`** -- Prefix content displayed before the input.
|
|
141
|
+
|
|
142
|
+
## NumberInput
|
|
143
|
+
|
|
144
|
+
Numeric input with thousand separator and decimal formatting.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
interface NumberInputProps {
|
|
148
|
+
value?: number;
|
|
149
|
+
onValueChange?: (value: number | undefined) => void;
|
|
150
|
+
useGrouping?: boolean; // default: true
|
|
151
|
+
minimumFractionDigits?: number;
|
|
152
|
+
placeholder?: string;
|
|
153
|
+
title?: string;
|
|
154
|
+
disabled?: boolean;
|
|
155
|
+
readOnly?: boolean;
|
|
156
|
+
size?: ComponentSize;
|
|
157
|
+
inset?: boolean;
|
|
158
|
+
class?: string;
|
|
159
|
+
style?: JSX.CSSProperties;
|
|
160
|
+
required?: boolean;
|
|
161
|
+
min?: number;
|
|
162
|
+
max?: number;
|
|
163
|
+
validate?: (value: number | undefined) => string | undefined;
|
|
164
|
+
lazyValidation?: boolean;
|
|
165
|
+
children?: JSX.Element; // NumberInput.Prefix slot
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Sub-components
|
|
170
|
+
|
|
171
|
+
- **`NumberInput.Prefix`** -- Prefix content displayed before the input.
|
|
172
|
+
|
|
173
|
+
## DatePicker
|
|
174
|
+
|
|
175
|
+
Date input supporting year, month, and date units. Uses `DateOnly` from `@simplysm/core-common`.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
type DatePickerUnit = "year" | "month" | "date";
|
|
179
|
+
|
|
180
|
+
interface DatePickerProps {
|
|
181
|
+
value?: DateOnly;
|
|
182
|
+
onValueChange?: (value: DateOnly | undefined) => void;
|
|
183
|
+
unit?: DatePickerUnit; // default: "date"
|
|
184
|
+
min?: DateOnly;
|
|
185
|
+
max?: DateOnly;
|
|
186
|
+
title?: string;
|
|
187
|
+
disabled?: boolean;
|
|
188
|
+
readOnly?: boolean;
|
|
189
|
+
size?: ComponentSize;
|
|
190
|
+
inset?: boolean;
|
|
191
|
+
class?: string;
|
|
192
|
+
style?: JSX.CSSProperties;
|
|
193
|
+
required?: boolean;
|
|
194
|
+
validate?: (value: DateOnly | undefined) => string | undefined;
|
|
195
|
+
lazyValidation?: boolean;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## DateTimePicker
|
|
200
|
+
|
|
201
|
+
DateTime input supporting minute and second units. Uses `DateTime` from `@simplysm/core-common`.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
type DateTimePickerUnit = "minute" | "second";
|
|
205
|
+
|
|
206
|
+
interface DateTimePickerProps {
|
|
207
|
+
value?: DateTime;
|
|
208
|
+
onValueChange?: (value: DateTime | undefined) => void;
|
|
209
|
+
unit?: DateTimePickerUnit; // default: "minute"
|
|
210
|
+
min?: DateTime;
|
|
211
|
+
max?: DateTime;
|
|
212
|
+
title?: string;
|
|
213
|
+
disabled?: boolean;
|
|
214
|
+
readOnly?: boolean;
|
|
215
|
+
size?: ComponentSize;
|
|
216
|
+
inset?: boolean;
|
|
217
|
+
class?: string;
|
|
218
|
+
style?: JSX.CSSProperties;
|
|
219
|
+
required?: boolean;
|
|
220
|
+
validate?: (value: DateTime | undefined) => string | undefined;
|
|
221
|
+
lazyValidation?: boolean;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## TimePicker
|
|
226
|
+
|
|
227
|
+
Time input supporting minute and second units. Uses `Time` from `@simplysm/core-common`.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
type TimePickerUnit = "minute" | "second";
|
|
231
|
+
|
|
232
|
+
interface TimePickerProps {
|
|
233
|
+
value?: Time;
|
|
234
|
+
onValueChange?: (value: Time | undefined) => void;
|
|
235
|
+
unit?: TimePickerUnit; // default: "minute"
|
|
236
|
+
title?: string;
|
|
237
|
+
disabled?: boolean;
|
|
238
|
+
readOnly?: boolean;
|
|
239
|
+
size?: ComponentSize;
|
|
240
|
+
inset?: boolean;
|
|
241
|
+
class?: string;
|
|
242
|
+
style?: JSX.CSSProperties;
|
|
243
|
+
min?: Time;
|
|
244
|
+
max?: Time;
|
|
245
|
+
required?: boolean;
|
|
246
|
+
validate?: (value: Time | undefined) => string | undefined;
|
|
247
|
+
lazyValidation?: boolean;
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Textarea
|
|
252
|
+
|
|
253
|
+
Auto-resizing textarea with IME handling.
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
interface TextareaProps {
|
|
257
|
+
value?: string;
|
|
258
|
+
onValueChange?: (value: string) => void;
|
|
259
|
+
placeholder?: string;
|
|
260
|
+
title?: string;
|
|
261
|
+
disabled?: boolean;
|
|
262
|
+
readOnly?: boolean;
|
|
263
|
+
size?: ComponentSize;
|
|
264
|
+
inset?: boolean;
|
|
265
|
+
minRows?: number; // default: 1
|
|
266
|
+
required?: boolean;
|
|
267
|
+
minLength?: number;
|
|
268
|
+
maxLength?: number;
|
|
269
|
+
validate?: (value: string) => string | undefined;
|
|
270
|
+
lazyValidation?: boolean;
|
|
271
|
+
class?: string;
|
|
272
|
+
style?: JSX.CSSProperties;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Checkbox
|
|
277
|
+
|
|
278
|
+
Checkbox with check indicator. Renders via `SelectableBase`.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
interface CheckboxProps {
|
|
282
|
+
checked?: boolean;
|
|
283
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
284
|
+
disabled?: boolean;
|
|
285
|
+
size?: ComponentSize;
|
|
286
|
+
inset?: boolean;
|
|
287
|
+
inline?: boolean;
|
|
288
|
+
required?: boolean;
|
|
289
|
+
validate?: (checked: boolean) => string | undefined;
|
|
290
|
+
lazyValidation?: boolean;
|
|
291
|
+
class?: string;
|
|
292
|
+
style?: JSX.CSSProperties;
|
|
293
|
+
children?: JSX.Element;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Radio
|
|
298
|
+
|
|
299
|
+
Radio button with dot indicator. Always selects on click (never deselects).
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
interface RadioProps {
|
|
303
|
+
checked?: boolean;
|
|
304
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
305
|
+
disabled?: boolean;
|
|
306
|
+
size?: ComponentSize;
|
|
307
|
+
inset?: boolean;
|
|
308
|
+
inline?: boolean;
|
|
309
|
+
required?: boolean;
|
|
310
|
+
validate?: (checked: boolean) => string | undefined;
|
|
311
|
+
lazyValidation?: boolean;
|
|
312
|
+
class?: string;
|
|
313
|
+
style?: JSX.CSSProperties;
|
|
314
|
+
children?: JSX.Element;
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## CheckboxGroup
|
|
319
|
+
|
|
320
|
+
Multi-select group of checkboxes.
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
interface CheckboxGroupProps<TValue> {
|
|
324
|
+
value?: TValue[];
|
|
325
|
+
onValueChange?: (value: TValue[]) => void;
|
|
326
|
+
disabled?: boolean;
|
|
327
|
+
size?: ComponentSize;
|
|
328
|
+
inline?: boolean;
|
|
329
|
+
inset?: boolean;
|
|
330
|
+
required?: boolean;
|
|
331
|
+
validate?: (value: TValue[]) => string | undefined;
|
|
332
|
+
lazyValidation?: boolean;
|
|
333
|
+
class?: string;
|
|
334
|
+
style?: JSX.CSSProperties;
|
|
335
|
+
children?: JSX.Element;
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Sub-components
|
|
340
|
+
|
|
341
|
+
- **`CheckboxGroup.Item<TValue>`** -- Props: `value: TValue`, `disabled?: boolean`, `children?: JSX.Element`.
|
|
342
|
+
|
|
343
|
+
## RadioGroup
|
|
344
|
+
|
|
345
|
+
Single-select group of radio buttons.
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
interface RadioGroupProps<TValue> {
|
|
349
|
+
value?: TValue;
|
|
350
|
+
onValueChange?: (value: TValue) => void;
|
|
351
|
+
disabled?: boolean;
|
|
352
|
+
size?: ComponentSize;
|
|
353
|
+
inline?: boolean;
|
|
354
|
+
inset?: boolean;
|
|
355
|
+
required?: boolean;
|
|
356
|
+
validate?: (value: TValue | undefined) => string | undefined;
|
|
357
|
+
lazyValidation?: boolean;
|
|
358
|
+
class?: string;
|
|
359
|
+
style?: JSX.CSSProperties;
|
|
360
|
+
children?: JSX.Element;
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Sub-components
|
|
365
|
+
|
|
366
|
+
- **`RadioGroup.Item<TValue>`** -- Props: `value: TValue`, `disabled?: boolean`, `children?: JSX.Element`.
|
|
367
|
+
|
|
368
|
+
## ColorPicker
|
|
369
|
+
|
|
370
|
+
Native HTML color picker input.
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
interface ColorPickerProps {
|
|
374
|
+
value?: string; // #RRGGBB format
|
|
375
|
+
onValueChange?: (value: string | undefined) => void;
|
|
376
|
+
title?: string;
|
|
377
|
+
disabled?: boolean;
|
|
378
|
+
size?: ComponentSize;
|
|
379
|
+
inset?: boolean;
|
|
380
|
+
required?: boolean;
|
|
381
|
+
validate?: (value: string | undefined) => string | undefined;
|
|
382
|
+
lazyValidation?: boolean;
|
|
383
|
+
class?: string;
|
|
384
|
+
style?: JSX.CSSProperties;
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## DateRangePicker
|
|
389
|
+
|
|
390
|
+
Date range input with period type selector (day/month/range).
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
type DateRangePeriodType = "day" | "month" | "range";
|
|
394
|
+
|
|
395
|
+
interface DateRangePickerProps {
|
|
396
|
+
periodType?: DateRangePeriodType;
|
|
397
|
+
onPeriodTypeChange?: (value: DateRangePeriodType) => void;
|
|
398
|
+
from?: DateOnly;
|
|
399
|
+
onFromChange?: (value: DateOnly | undefined) => void;
|
|
400
|
+
to?: DateOnly;
|
|
401
|
+
onToChange?: (value: DateOnly | undefined) => void;
|
|
402
|
+
required?: boolean;
|
|
403
|
+
disabled?: boolean;
|
|
404
|
+
size?: ComponentSize;
|
|
405
|
+
class?: string;
|
|
406
|
+
style?: JSX.CSSProperties;
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## RichTextEditor
|
|
411
|
+
|
|
412
|
+
Tiptap-based rich text editor with toolbar (text formatting, alignment, colors, tables, images).
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
interface RichTextEditorProps {
|
|
416
|
+
value?: string; // HTML string
|
|
417
|
+
onValueChange?: (value: string) => void;
|
|
418
|
+
disabled?: boolean;
|
|
419
|
+
size?: ComponentSize;
|
|
420
|
+
class?: string;
|
|
421
|
+
style?: JSX.CSSProperties;
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Numpad
|
|
426
|
+
|
|
427
|
+
Numeric keypad for touch-friendly number input.
|
|
428
|
+
|
|
429
|
+
```ts
|
|
430
|
+
interface NumpadProps {
|
|
431
|
+
value?: number;
|
|
432
|
+
onValueChange?: (value: number | undefined) => void;
|
|
433
|
+
placeholder?: string;
|
|
434
|
+
required?: boolean;
|
|
435
|
+
inputDisabled?: boolean; // disable direct text field input
|
|
436
|
+
withEnterButton?: boolean;
|
|
437
|
+
withMinusButton?: boolean;
|
|
438
|
+
onEnterButtonClick?: () => void;
|
|
439
|
+
size?: ComponentSize;
|
|
440
|
+
class?: string;
|
|
441
|
+
style?: JSX.CSSProperties;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## StatePreset
|
|
446
|
+
|
|
447
|
+
Save and restore named state presets to synced storage.
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
interface StatePresetProps<TValue> {
|
|
451
|
+
storageKey: string;
|
|
452
|
+
value: TValue;
|
|
453
|
+
onValueChange: (value: TValue) => void;
|
|
454
|
+
size?: ComponentSize;
|
|
455
|
+
class?: string;
|
|
456
|
+
style?: JSX.CSSProperties;
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## ThemeToggle
|
|
461
|
+
|
|
462
|
+
Theme cycle button (light -> system -> dark -> light). Must be used inside `ThemeProvider`.
|
|
463
|
+
|
|
464
|
+
```ts
|
|
465
|
+
interface ThemeToggleProps extends Omit<JSX.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
|
|
466
|
+
size?: ComponentSize;
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Invalid
|
|
471
|
+
|
|
472
|
+
Validation indicator wrapper. Wraps a child element and shows a validation error via dot or border.
|
|
473
|
+
|
|
474
|
+
```ts
|
|
475
|
+
interface InvalidProps {
|
|
476
|
+
/** Validation error message. Non-empty = invalid. */
|
|
477
|
+
message?: string;
|
|
478
|
+
/** Visual indicator variant */
|
|
479
|
+
variant?: "border" | "dot";
|
|
480
|
+
/** When true, visual display only appears after target loses focus */
|
|
481
|
+
lazyValidation?: boolean;
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Field Style Exports
|
|
486
|
+
|
|
487
|
+
Exported from `src/components/form-control/field/Field.styles.ts`:
|
|
488
|
+
|
|
489
|
+
```ts
|
|
490
|
+
const fieldSurface: string; // bg + text + border + focus-within
|
|
491
|
+
const fieldBaseClass: string; // inline-flex + fieldSurface
|
|
492
|
+
const fieldSizeClasses: Record<ComponentSize, string>;
|
|
493
|
+
const fieldInputClass: string; // input element styles
|
|
494
|
+
function getFieldWrapperClass(options: {
|
|
495
|
+
size?: ComponentSize;
|
|
496
|
+
disabled?: boolean;
|
|
497
|
+
inset?: boolean;
|
|
498
|
+
includeCustomClass?: string | false;
|
|
499
|
+
extra?: string | false;
|
|
500
|
+
}): string;
|
|
501
|
+
function getTextareaWrapperClass(options: {
|
|
502
|
+
size?: ComponentSize;
|
|
503
|
+
disabled?: boolean;
|
|
504
|
+
inset?: boolean;
|
|
505
|
+
includeCustomClass?: string | false;
|
|
506
|
+
}): string;
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Checkbox Style Exports
|
|
510
|
+
|
|
511
|
+
Exported from `src/components/form-control/checkbox/Checkbox.styles.ts`:
|
|
512
|
+
|
|
513
|
+
```ts
|
|
514
|
+
type CheckboxSize = ComponentSize;
|
|
515
|
+
const checkboxBaseClass: string;
|
|
516
|
+
const indicatorBaseClass: string;
|
|
517
|
+
const checkedClass: string;
|
|
518
|
+
const checkboxSizeClasses: Record<CheckboxSize, string>;
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## DropdownTrigger Style Exports
|
|
522
|
+
|
|
523
|
+
Exported from `src/components/form-control/DropdownTrigger.styles.ts`:
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
const triggerBaseClass: string;
|
|
527
|
+
const triggerDisabledClass: string;
|
|
528
|
+
const triggerInsetClass: string;
|
|
529
|
+
const triggerSizeClasses: Record<ComponentSize, string>;
|
|
530
|
+
const chevronWrapperClass: string;
|
|
531
|
+
function getTriggerClass(options: {
|
|
532
|
+
size?: ComponentSize;
|
|
533
|
+
disabled?: boolean;
|
|
534
|
+
inset?: boolean;
|
|
535
|
+
class?: string;
|
|
536
|
+
}): string;
|
|
537
|
+
```
|
package/docs/helpers.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Helpers
|
|
2
|
+
|
|
3
|
+
Source: `src/helpers/*.ts`
|
|
4
|
+
|
|
5
|
+
## mergeStyles
|
|
6
|
+
|
|
7
|
+
Utility function that merges CSS styles from multiple sources (objects and strings).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
function mergeStyles(
|
|
11
|
+
...styles: (JSX.CSSProperties | string | undefined)[]
|
|
12
|
+
): JSX.CSSProperties;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Object styles are merged with later values taking precedence.
|
|
16
|
+
- String styles are parsed (semicolon-delimited, kebab-case converted to camelCase).
|
|
17
|
+
- `undefined` values are ignored.
|
|
18
|
+
|
|
19
|
+
## createAppStructure
|
|
20
|
+
|
|
21
|
+
Builds app menus, routes, permissions, and flat menu lists from a declarative structure definition. Supports module-based filtering and permission inference.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
function createAppStructure<TModule, const TItems extends AppStructureItem<TModule>[]>(
|
|
25
|
+
items: TItems,
|
|
26
|
+
options: {
|
|
27
|
+
basePath: string;
|
|
28
|
+
enabledModules?: TModule[];
|
|
29
|
+
enabledPerms?: string[];
|
|
30
|
+
homeCode?: string;
|
|
31
|
+
},
|
|
32
|
+
): AppStructure<TModule>;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Input Types
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
interface AppStructureGroupItem<TModule> {
|
|
39
|
+
code: string;
|
|
40
|
+
title: string;
|
|
41
|
+
icon?: Component<IconProps>;
|
|
42
|
+
modules?: TModule[];
|
|
43
|
+
requiredModules?: TModule[];
|
|
44
|
+
children: AppStructureItem<TModule>[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface AppStructureLeafItem<TModule> {
|
|
48
|
+
code: string;
|
|
49
|
+
title: string;
|
|
50
|
+
icon?: Component<IconProps>;
|
|
51
|
+
modules?: TModule[];
|
|
52
|
+
requiredModules?: TModule[];
|
|
53
|
+
component?: Component;
|
|
54
|
+
perms?: ("use" | "edit")[];
|
|
55
|
+
subPerms?: AppStructureSubPerm<TModule>[];
|
|
56
|
+
isNotMenu?: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type AppStructureItem<TModule> =
|
|
60
|
+
| AppStructureGroupItem<TModule>
|
|
61
|
+
| AppStructureLeafItem<TModule>;
|
|
62
|
+
|
|
63
|
+
interface AppStructureSubPerm<TModule> {
|
|
64
|
+
code: string;
|
|
65
|
+
title: string;
|
|
66
|
+
modules?: TModule[];
|
|
67
|
+
requiredModules?: TModule[];
|
|
68
|
+
perms: ("use" | "edit")[];
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Output Types
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
interface AppStructure<TModule> {
|
|
76
|
+
items: AppStructureItem<TModule>[];
|
|
77
|
+
usableRoutes: Accessor<AppRoute[]>;
|
|
78
|
+
usableMenus: Accessor<AppMenu[]>;
|
|
79
|
+
usableFlatMenus: Accessor<AppFlatMenu[]>;
|
|
80
|
+
usablePerms: Accessor<AppPerm<TModule>[]>;
|
|
81
|
+
allFlatPerms: AppFlatPerm<TModule>[];
|
|
82
|
+
getTitleChainByHref(href: string): string[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface AppMenu {
|
|
86
|
+
title: string;
|
|
87
|
+
href?: string;
|
|
88
|
+
icon?: Component<IconProps>;
|
|
89
|
+
children?: AppMenu[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface AppPerm<TModule = string> {
|
|
93
|
+
title: string;
|
|
94
|
+
href?: string;
|
|
95
|
+
modules?: TModule[];
|
|
96
|
+
perms?: string[];
|
|
97
|
+
children?: AppPerm<TModule>[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface AppRoute {
|
|
101
|
+
path: string;
|
|
102
|
+
component: Component;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface AppFlatMenu {
|
|
106
|
+
titleChain: string[];
|
|
107
|
+
href: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface AppFlatPerm<TModule = string> {
|
|
111
|
+
titleChain: string[];
|
|
112
|
+
code: string;
|
|
113
|
+
modulesChain: TModule[][];
|
|
114
|
+
requiredModulesChain: TModule[][];
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## createSlot
|
|
119
|
+
|
|
120
|
+
Single-item slot pattern for parent-child communication. Used for patterns like `Dialog.Header`, `Select.Header`.
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
function createSlot<TItem>(): [
|
|
124
|
+
SlotComponent: (props: TItem) => null,
|
|
125
|
+
createSlotAccessor: () => [Accessor<TItem | undefined>, ParentComponent],
|
|
126
|
+
];
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Usage pattern:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
// 1. Create slot at module level
|
|
133
|
+
const [HeaderSlot, createHeaderAccessor] = createSlot<{ children: JSX.Element }>();
|
|
134
|
+
|
|
135
|
+
// 2. In parent component
|
|
136
|
+
const [header, HeaderProvider] = createHeaderAccessor();
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<HeaderProvider>
|
|
140
|
+
{props.children}
|
|
141
|
+
<Show when={header()}>{header()!.children}</Show>
|
|
142
|
+
</HeaderProvider>
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// 3. In child usage
|
|
146
|
+
<Parent>
|
|
147
|
+
<HeaderSlot>My Header Content</HeaderSlot>
|
|
148
|
+
{/* other content */}
|
|
149
|
+
</Parent>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## createSlots
|
|
153
|
+
|
|
154
|
+
Multi-item slot pattern. Like `createSlot` but collects an array of items.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
interface SlotRegistrar<TItem> {
|
|
158
|
+
add: (item: TItem) => void;
|
|
159
|
+
remove: (item: TItem) => void;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function createSlots<TItem>(): [
|
|
163
|
+
SlotComponent: (props: TItem) => null,
|
|
164
|
+
createSlotsAccessor: () => [Accessor<TItem[]>, ParentComponent],
|
|
165
|
+
];
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Items are collected in order of registration and removed on cleanup.
|