@simplysm/solid 13.0.85 → 13.0.88

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 (116) hide show
  1. package/README.md +143 -28
  2. package/dist/components/data/list/ListItem.d.ts.map +1 -1
  3. package/dist/components/data/list/ListItem.js +11 -4
  4. package/dist/components/data/list/ListItem.js.map +2 -2
  5. package/dist/components/data/list/ListItem.styles.d.ts +2 -0
  6. package/dist/components/data/list/ListItem.styles.d.ts.map +1 -1
  7. package/dist/components/data/list/ListItem.styles.js +11 -1
  8. package/dist/components/data/list/ListItem.styles.js.map +1 -1
  9. package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
  10. package/dist/components/features/crud-sheet/CrudSheet.js +7 -0
  11. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  12. package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
  13. package/dist/components/features/data-select-button/DataSelectButton.js +30 -26
  14. package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
  15. package/dist/components/features/permission-table/PermissionTable.js +5 -1
  16. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  17. package/dist/components/form-control/DropdownTrigger.styles.js +1 -1
  18. package/dist/components/form-control/combobox/Combobox.d.ts +19 -5
  19. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  20. package/dist/components/form-control/combobox/Combobox.js +2 -4
  21. package/dist/components/form-control/combobox/Combobox.js.map +1 -1
  22. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +2 -2
  23. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
  24. package/dist/components/form-control/date-range-picker/DateRangePicker.js +10 -1
  25. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  26. package/dist/components/form-control/editor/RichTextEditor.d.ts +2 -2
  27. package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
  28. package/dist/components/form-control/editor/RichTextEditor.js +2 -2
  29. package/dist/components/form-control/editor/RichTextEditor.js.map +1 -1
  30. package/dist/components/form-control/field/DatePicker.d.ts +2 -2
  31. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  32. package/dist/components/form-control/field/DatePicker.js.map +1 -1
  33. package/dist/components/form-control/field/DateTimePicker.d.ts +2 -2
  34. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  35. package/dist/components/form-control/field/DateTimePicker.js.map +1 -1
  36. package/dist/components/form-control/field/Field.styles.d.ts +6 -7
  37. package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
  38. package/dist/components/form-control/field/Field.styles.js.map +1 -1
  39. package/dist/components/form-control/field/NumberInput.d.ts +2 -2
  40. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  41. package/dist/components/form-control/field/NumberInput.js.map +1 -1
  42. package/dist/components/form-control/field/TextInput.d.ts +2 -2
  43. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  44. package/dist/components/form-control/field/TextInput.js.map +1 -1
  45. package/dist/components/form-control/field/Textarea.d.ts +2 -2
  46. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  47. package/dist/components/form-control/field/Textarea.js.map +1 -1
  48. package/dist/components/form-control/field/TimePicker.d.ts +2 -2
  49. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  50. package/dist/components/form-control/field/TimePicker.js.map +1 -1
  51. package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
  52. package/dist/components/form-control/numpad/Numpad.js +4 -17
  53. package/dist/components/form-control/numpad/Numpad.js.map +2 -2
  54. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  55. package/dist/components/form-control/select/Select.js +19 -6
  56. package/dist/components/form-control/select/Select.js.map +2 -2
  57. package/dist/components/form-control/state-preset/StatePreset.d.ts +1 -3
  58. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  59. package/dist/components/form-control/state-preset/StatePreset.js +69 -91
  60. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  61. package/dist/components/layout/FormGroup.js +1 -1
  62. package/dist/components/layout/FormGroup.js.map +1 -1
  63. package/dist/components/layout/FormTable.js +3 -3
  64. package/dist/components/layout/FormTable.js.map +1 -1
  65. package/dist/components/layout/sidebar/Sidebar.d.ts.map +1 -1
  66. package/dist/components/layout/sidebar/Sidebar.js +3 -6
  67. package/dist/components/layout/sidebar/Sidebar.js.map +2 -2
  68. package/dist/providers/i18n/locales/en.d.ts +2 -3
  69. package/dist/providers/i18n/locales/en.d.ts.map +1 -1
  70. package/dist/providers/i18n/locales/en.js +3 -4
  71. package/dist/providers/i18n/locales/en.js.map +1 -1
  72. package/dist/providers/i18n/locales/ko.d.ts +2 -3
  73. package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
  74. package/dist/providers/i18n/locales/ko.js +3 -4
  75. package/dist/providers/i18n/locales/ko.js.map +1 -1
  76. package/docs/display-feedback.md +279 -0
  77. package/docs/features.md +357 -213
  78. package/docs/form-controls.md +261 -403
  79. package/docs/layout-data.md +386 -0
  80. package/docs/providers-hooks.md +411 -0
  81. package/package.json +5 -5
  82. package/src/components/data/list/ListItem.styles.ts +14 -2
  83. package/src/components/data/list/ListItem.tsx +13 -4
  84. package/src/components/features/crud-sheet/CrudSheet.tsx +8 -0
  85. package/src/components/features/data-select-button/DataSelectButton.tsx +39 -32
  86. package/src/components/features/permission-table/PermissionTable.tsx +1 -1
  87. package/src/components/form-control/DropdownTrigger.styles.ts +1 -1
  88. package/src/components/form-control/combobox/Combobox.tsx +42 -16
  89. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +6 -4
  90. package/src/components/form-control/editor/RichTextEditor.tsx +5 -6
  91. package/src/components/form-control/field/DatePicker.tsx +3 -2
  92. package/src/components/form-control/field/DateTimePicker.tsx +3 -2
  93. package/src/components/form-control/field/Field.styles.ts +6 -8
  94. package/src/components/form-control/field/NumberInput.tsx +3 -2
  95. package/src/components/form-control/field/TextInput.tsx +3 -2
  96. package/src/components/form-control/field/Textarea.tsx +3 -2
  97. package/src/components/form-control/field/TimePicker.tsx +3 -2
  98. package/src/components/form-control/numpad/Numpad.tsx +16 -18
  99. package/src/components/form-control/select/Select.tsx +19 -5
  100. package/src/components/form-control/state-preset/StatePreset.tsx +32 -57
  101. package/src/components/layout/FormGroup.tsx +1 -1
  102. package/src/components/layout/FormTable.tsx +3 -3
  103. package/src/components/layout/sidebar/Sidebar.tsx +2 -3
  104. package/src/providers/i18n/locales/en.ts +2 -3
  105. package/src/providers/i18n/locales/ko.ts +2 -3
  106. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +62 -7
  107. package/tests/components/form-control/combobox/Combobox.spec.tsx +3 -3
  108. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +56 -0
  109. package/docs/data.md +0 -204
  110. package/docs/disclosure.md +0 -146
  111. package/docs/display.md +0 -125
  112. package/docs/feedback.md +0 -156
  113. package/docs/helpers.md +0 -173
  114. package/docs/hooks.md +0 -146
  115. package/docs/layout.md +0 -94
  116. package/docs/providers.md +0 -180
@@ -137,7 +137,9 @@ const ComboboxItem: ParentComponent<ComboboxItemProps> = <TValue,>(
137
137
  //#endregion
138
138
 
139
139
  // Props definition
140
- export interface ComboboxProps<TValue = unknown> {
140
+
141
+ /** Base props shared by all Combobox variants */
142
+ interface ComboboxBaseProps<TValue> {
141
143
  /** Currently selected value */
142
144
  value?: TValue;
143
145
 
@@ -150,12 +152,6 @@ export interface ComboboxProps<TValue = unknown> {
150
152
  /** Debounce delay (default: 300ms) */
151
153
  debounceMs?: number;
152
154
 
153
- /** Allow custom values */
154
- allowsCustomValue?: boolean;
155
-
156
- /** Custom value parsing function */
157
- parseCustomValue?: (text: string) => TValue;
158
-
159
155
  /** Function to render selected value (required) */
160
156
  renderValue: (value: TValue) => JSX.Element;
161
157
 
@@ -190,6 +186,29 @@ export interface ComboboxProps<TValue = unknown> {
190
186
  children?: JSX.Element;
191
187
  }
192
188
 
189
+ /** Custom value with parser: TValue can be anything */
190
+ interface ComboboxCustomParserProps<TValue> extends ComboboxBaseProps<TValue> {
191
+ allowsCustomValue: true;
192
+ parseCustomValue: (text: string) => TValue;
193
+ }
194
+
195
+ /** Custom value without parser: TValue MUST be string */
196
+ interface ComboboxCustomStringProps extends ComboboxBaseProps<string> {
197
+ allowsCustomValue: true;
198
+ parseCustomValue?: undefined;
199
+ }
200
+
201
+ /** No custom value (default) */
202
+ interface ComboboxDefaultProps<TValue> extends ComboboxBaseProps<TValue> {
203
+ allowsCustomValue?: false;
204
+ parseCustomValue?: undefined;
205
+ }
206
+
207
+ export type ComboboxProps<TValue = unknown> =
208
+ | ComboboxCustomParserProps<TValue>
209
+ | ComboboxCustomStringProps
210
+ | ComboboxDefaultProps<TValue>;
211
+
193
212
  /**
194
213
  * Combobox component
195
214
  *
@@ -220,8 +239,15 @@ export interface ComboboxProps<TValue = unknown> {
220
239
  * </Combobox>
221
240
  * ```
222
241
  */
242
+ /** Internal props used after splitProps — collapses the discriminated union for runtime use */
243
+ interface ComboboxInternalProps<TValue> extends ComboboxBaseProps<TValue> {
244
+ allowsCustomValue?: boolean;
245
+ parseCustomValue?: (text: string) => TValue;
246
+ children?: JSX.Element;
247
+ }
248
+
223
249
  const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
224
- const [local, rest] = splitProps(props as ComboboxProps<TValue> & { children?: JSX.Element }, [
250
+ const [local, rest] = splitProps(props as ComboboxInternalProps<TValue>, [
225
251
  "children",
226
252
  "class",
227
253
  "style",
@@ -252,8 +278,8 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
252
278
  // Selected value management (controlled/uncontrolled pattern)
253
279
  const [getValue, setInternalValue] = createControllableSignal<TValue | undefined>({
254
280
  value: () => local.value,
255
- onChange: () => local.onValueChange,
256
- } as Parameters<typeof createControllableSignal<TValue | undefined>>[0]);
281
+ onChange: () => local.onValueChange as ((value: TValue | undefined) => void) | undefined,
282
+ });
257
283
 
258
284
  // Debounce queue (created once on mount, debounceMs only used as initial value)
259
285
  const debounceQueue = new DebounceQueue(local.debounceMs ?? 300);
@@ -270,7 +296,7 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
270
296
 
271
297
  // Select value
272
298
  const selectValue = (value: TValue) => {
273
- setInternalValue(value as any);
299
+ setInternalValue(value);
274
300
  setQuery("");
275
301
  setOpen(false);
276
302
  };
@@ -346,9 +372,8 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
346
372
  if (local.parseCustomValue) {
347
373
  selectValue(local.parseCustomValue(query()));
348
374
  } else {
349
- setInternalValue(undefined as any);
350
- setQuery("");
351
- setOpen(false);
375
+ // TValue is string when parseCustomValue is not provided (enforced by type system)
376
+ selectValue(query() as TValue);
352
377
  }
353
378
  }
354
379
  };
@@ -391,6 +416,7 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
391
416
  class={clsx("min-w-0 flex-1 bg-transparent outline-none", text.placeholder)}
392
417
  value={query()}
393
418
  placeholder={currentValue === undefined ? local.placeholder : undefined}
419
+
394
420
  disabled={local.disabled}
395
421
  autocomplete="one-time-code"
396
422
  onInput={handleInput}
@@ -399,7 +425,7 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
399
425
  }
400
426
 
401
427
  // Show value if selected and dropdown is closed
402
- return <div class="truncate">{local.renderValue(currentValue)}</div>;
428
+ return <div class="whitespace-nowrap">{local.renderValue(currentValue)}</div>;
403
429
  };
404
430
 
405
431
  // Render items
@@ -454,7 +480,7 @@ const ComboboxInner = <TValue,>(props: ComboboxProps<TValue>) => {
454
480
  style={local.style}
455
481
  onKeyDown={handleTriggerKeyDown}
456
482
  >
457
- <div class="flex-1 overflow-hidden whitespace-nowrap">{renderDisplayContent()}</div>
483
+ <div class="flex-1 whitespace-nowrap">{renderDisplayContent()}</div>
458
484
  <div class={chevronWrapperClass}>
459
485
  <Show
460
486
  when={busyCount() > 0}
@@ -3,9 +3,8 @@ import clsx from "clsx";
3
3
  import { twMerge } from "tailwind-merge";
4
4
  import { DateOnly } from "@simplysm/core-common";
5
5
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
6
- import { type FieldSize } from "../field/Field.styles";
7
6
  import { text } from "../../../styles/base.styles";
8
- import { gap } from "../../../styles/control.styles";
7
+ import { type ComponentSize, gap } from "../../../styles/control.styles";
9
8
  import { DatePicker } from "../field/DatePicker";
10
9
  import { Select } from "../select/Select";
11
10
  import { useI18n } from "../../../providers/i18n/I18nProvider";
@@ -38,7 +37,7 @@ export interface DateRangePickerProps {
38
37
  disabled?: boolean;
39
38
 
40
39
  /** Size */
41
- size?: FieldSize;
40
+ size?: ComponentSize;
42
41
 
43
42
  /** Custom class */
44
43
  class?: string;
@@ -169,7 +168,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
169
168
  required
170
169
  disabled={local.disabled}
171
170
  size={local.size}
172
- inset
171
+ class="min-w-0"
173
172
  >
174
173
  <Select.Item value={"day" as DateRangePeriodType}>
175
174
  {i18n.t("dateRangePicker.day")}
@@ -189,6 +188,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
189
188
  unit={periodType() === "month" ? "month" : "date"}
190
189
  value={from()}
191
190
  onValueChange={handleFromChange}
191
+ required={local.required}
192
192
  disabled={local.disabled}
193
193
  size={local.size}
194
194
  />
@@ -198,6 +198,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
198
198
  unit="date"
199
199
  value={from()}
200
200
  onValueChange={handleFromChange}
201
+ required={local.required}
201
202
  disabled={local.disabled}
202
203
  size={local.size}
203
204
  />
@@ -207,6 +208,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
207
208
  value={to()}
208
209
  onValueChange={handleToChange}
209
210
  min={from()}
211
+ required={local.required}
210
212
  disabled={local.disabled}
211
213
  size={local.size}
212
214
  />
@@ -23,9 +23,8 @@ import TableHeader from "@tiptap/extension-table-header";
23
23
  import TableCell from "@tiptap/extension-table-cell";
24
24
  import Image from "@tiptap/extension-image";
25
25
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
26
- import type { FieldSize } from "../field/Field.styles";
27
26
  import { bg, border, text } from "../../../styles/base.styles";
28
- import { pad } from "../../../styles/control.styles";
27
+ import { type ComponentSize, pad } from "../../../styles/control.styles";
29
28
  import { EditorToolbar } from "./EditorToolbar";
30
29
 
31
30
  export interface RichTextEditorProps {
@@ -39,7 +38,7 @@ export interface RichTextEditorProps {
39
38
  disabled?: boolean;
40
39
 
41
40
  /** Size */
42
- size?: FieldSize;
41
+ size?: ComponentSize;
43
42
 
44
43
  /** Custom class */
45
44
  class?: string;
@@ -49,7 +48,7 @@ export interface RichTextEditorProps {
49
48
  }
50
49
 
51
50
  // Editor content size-based style
52
- const editorContentSizeClasses: Record<FieldSize, string> = {
51
+ const editorContentSizeClasses: Record<ComponentSize, string> = {
53
52
  md: clsx(pad.xl, "min-h-32"),
54
53
  xs: clsx(pad.xs, "min-h-12"),
55
54
  sm: clsx(pad.sm, "min-h-24"),
@@ -151,7 +150,7 @@ export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
151
150
  {...rest}
152
151
  data-rich-text-editor
153
152
  class={twMerge(
154
- clsx("flex flex-col bg-primary-50 dark:bg-primary-950/30", text.default, "border", border.default, "rounded focus-within:border-primary-500"),
153
+ clsx("flex flex-col", text.default, "border", border.default, "rounded focus-within:border-primary-500"),
155
154
  local.disabled && clsx(bg.muted, text.muted),
156
155
  local.class,
157
156
  )}
@@ -164,7 +163,7 @@ export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
164
163
  </Show>
165
164
  )}
166
165
  </Show>
167
- <div ref={editorRef} class={twMerge("outline-none prose prose-sm max-w-none dark:prose-invert", editorContentSizeClasses[local.size ?? "md"])} />
166
+ <div ref={editorRef} class={twMerge("outline-none prose prose-sm max-w-none dark:prose-invert bg-primary-50 dark:bg-primary-950/30", editorContentSizeClasses[local.size ?? "md"])} />
168
167
  </div>
169
168
  );
170
169
  };
@@ -1,7 +1,8 @@
1
1
  import { type Component, createMemo, type JSX, splitProps } from "solid-js";
2
2
  import { DateOnly } from "@simplysm/core-common";
3
3
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
4
- import { fieldInputClass, type FieldSize, getFieldWrapperClass } from "./Field.styles";
4
+ import { fieldInputClass, getFieldWrapperClass } from "./Field.styles";
5
+ import type { ComponentSize } from "../../../styles/control.styles";
5
6
  import { useI18n } from "../../../providers/i18n/I18nProvider";
6
7
  import { FieldShell } from "./FieldShell";
7
8
 
@@ -33,7 +34,7 @@ export interface DatePickerProps {
33
34
  readOnly?: boolean;
34
35
 
35
36
  /** Size */
36
- size?: FieldSize;
37
+ size?: ComponentSize;
37
38
 
38
39
  /** Borderless style */
39
40
  inset?: boolean;
@@ -1,7 +1,8 @@
1
1
  import { type Component, createMemo, type JSX, splitProps } from "solid-js";
2
2
  import { DateTime } from "@simplysm/core-common";
3
3
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
4
- import { type FieldSize, fieldInputClass, getFieldWrapperClass } from "./Field.styles";
4
+ import { fieldInputClass, getFieldWrapperClass } from "./Field.styles";
5
+ import type { ComponentSize } from "../../../styles/control.styles";
5
6
  import { useI18n } from "../../../providers/i18n/I18nProvider";
6
7
  import { FieldShell } from "./FieldShell";
7
8
 
@@ -33,7 +34,7 @@ export interface DateTimePickerProps {
33
34
  readOnly?: boolean;
34
35
 
35
36
  /** Size */
36
- size?: FieldSize;
37
+ size?: ComponentSize;
37
38
 
38
39
  /** Borderless style */
39
40
  inset?: boolean;
@@ -3,8 +3,6 @@ import { twMerge } from "tailwind-merge";
3
3
  import { type ComponentSize, gap, pad } from "../../../styles/control.styles";
4
4
  import { border, text } from "../../../styles/base.styles";
5
5
 
6
- export type FieldSize = ComponentSize;
7
-
8
6
  // ── Form Field Common Surface (background + text + border + focus) ──
9
7
  export const fieldSurface = clsx(
10
8
  "bg-primary-50 dark:bg-primary-950/30",
@@ -23,7 +21,7 @@ export const fieldBaseClass = clsx(
23
21
  );
24
22
 
25
23
  // Size-specific styles
26
- export const fieldSizeClasses: Record<FieldSize, string> = {
24
+ export const fieldSizeClasses: Record<ComponentSize, string> = {
27
25
  md: clsx("h-field", pad.md),
28
26
  xs: clsx("h-field-xs", pad.xs),
29
27
  sm: clsx("h-field-sm", pad.sm),
@@ -41,7 +39,7 @@ export const fieldInsetClass = clsx(
41
39
  );
42
40
 
43
41
  // Inset heights (excluding 2px border)
44
- export const fieldInsetSizeHeightClasses: Record<FieldSize, string> = {
42
+ export const fieldInsetSizeHeightClasses: Record<ComponentSize, string> = {
45
43
  md: clsx`h-field-inset`,
46
44
  xs: clsx`h-field-inset-xs`,
47
45
  sm: clsx`h-field-inset-sm`,
@@ -56,7 +54,7 @@ export const fieldDisabledClass = clsx("bg-base-100 text-base-500 dark:bg-base-8
56
54
  export const textAreaBaseClass = clsx("inline-block w-48", fieldSurface);
57
55
 
58
56
  // Textarea size-specific styles (h-field-* removed)
59
- export const textAreaSizeClasses: Record<FieldSize, string> = {
57
+ export const textAreaSizeClasses: Record<ComponentSize, string> = {
60
58
  md: pad.md,
61
59
  xs: pad.xs,
62
60
  sm: pad.sm,
@@ -74,7 +72,7 @@ export const fieldInputClass = clsx(
74
72
  );
75
73
 
76
74
  // Prefix icon gap classes (replaces nested ternary)
77
- export const fieldGapClasses: Record<FieldSize, string> = {
75
+ export const fieldGapClasses: Record<ComponentSize, string> = {
78
76
  md: gap.md,
79
77
  xs: gap.xs,
80
78
  sm: gap.sm,
@@ -84,7 +82,7 @@ export const fieldGapClasses: Record<FieldSize, string> = {
84
82
 
85
83
  // Shared wrapper class generation function
86
84
  export function getFieldWrapperClass(options: {
87
- size?: FieldSize;
85
+ size?: ComponentSize;
88
86
  disabled?: boolean;
89
87
  inset?: boolean;
90
88
  includeCustomClass?: string | false;
@@ -103,7 +101,7 @@ export function getFieldWrapperClass(options: {
103
101
 
104
102
  // Textarea-specific wrapper class generation function
105
103
  export function getTextareaWrapperClass(options: {
106
- size?: FieldSize;
104
+ size?: ComponentSize;
107
105
  disabled?: boolean;
108
106
  inset?: boolean;
109
107
  includeCustomClass?: string | false;
@@ -9,11 +9,11 @@ import {
9
9
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
10
10
  import { createSlot } from "../../../helpers/createSlot";
11
11
  import {
12
- type FieldSize,
13
12
  fieldInputClass,
14
13
  fieldGapClasses,
15
14
  getFieldWrapperClass,
16
15
  } from "./Field.styles";
16
+ import type { ComponentSize } from "../../../styles/control.styles";
17
17
  import { PlaceholderFallback } from "./FieldPlaceholder";
18
18
  import { useI18n } from "../../../providers/i18n/I18nProvider";
19
19
  import { FieldShell } from "./FieldShell";
@@ -49,7 +49,7 @@ export interface NumberInputProps {
49
49
  readOnly?: boolean;
50
50
 
51
51
  /** Size */
52
- size?: FieldSize;
52
+ size?: ComponentSize;
53
53
 
54
54
  /** Borderless style */
55
55
  inset?: boolean;
@@ -332,6 +332,7 @@ const NumberInputInner = (props: NumberInputProps): JSX.Element => {
332
332
  )}
333
333
  value={displayValue()}
334
334
  placeholder={local.placeholder}
335
+
335
336
  title={local.title}
336
337
  autocomplete="one-time-code"
337
338
  onInput={handleInput}
@@ -5,9 +5,9 @@ import { createIMEHandler } from "../../../hooks/createIMEHandler";
5
5
  import {
6
6
  fieldGapClasses,
7
7
  fieldInputClass,
8
- type FieldSize,
9
8
  getFieldWrapperClass,
10
9
  } from "./Field.styles";
10
+ import type { ComponentSize } from "../../../styles/control.styles";
11
11
  import { PlaceholderFallback } from "./FieldPlaceholder";
12
12
  import { FieldShell } from "./FieldShell";
13
13
  import { useI18n } from "../../../providers/i18n/I18nProvider";
@@ -41,7 +41,7 @@ export interface TextInputProps {
41
41
  readOnly?: boolean;
42
42
 
43
43
  /** Size */
44
- size?: FieldSize;
44
+ size?: ComponentSize;
45
45
 
46
46
  /** Borderless style */
47
47
  inset?: boolean;
@@ -286,6 +286,7 @@ const TextInputInner = (props: TextInputProps) => {
286
286
  class={fieldInputClass}
287
287
  value={inputValue()}
288
288
  placeholder={local.placeholder}
289
+
289
290
  title={local.title}
290
291
  autocomplete={local.autocomplete ?? "one-time-code"}
291
292
  onInput={handleInput}
@@ -4,7 +4,8 @@ import { twMerge } from "tailwind-merge";
4
4
  import { text } from "../../../styles/base.styles";
5
5
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
6
6
  import { createIMEHandler } from "../../../hooks/createIMEHandler";
7
- import { type FieldSize, textAreaSizeClasses, getTextareaWrapperClass } from "./Field.styles";
7
+ import { textAreaSizeClasses, getTextareaWrapperClass } from "./Field.styles";
8
+ import type { ComponentSize } from "../../../styles/control.styles";
8
9
  import { PlaceholderFallback } from "./FieldPlaceholder";
9
10
  import { FieldShell } from "./FieldShell";
10
11
  import { useI18n } from "../../../providers/i18n/I18nProvider";
@@ -29,7 +30,7 @@ export interface TextareaProps {
29
30
  readOnly?: boolean;
30
31
 
31
32
  /** Size */
32
- size?: FieldSize;
33
+ size?: ComponentSize;
33
34
 
34
35
  /** Borderless style */
35
36
  inset?: boolean;
@@ -1,7 +1,8 @@
1
1
  import { type Component, createMemo, type JSX, splitProps } from "solid-js";
2
2
  import { Time } from "@simplysm/core-common";
3
3
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
4
- import { type FieldSize, fieldInputClass, getFieldWrapperClass } from "./Field.styles";
4
+ import { fieldInputClass, getFieldWrapperClass } from "./Field.styles";
5
+ import type { ComponentSize } from "../../../styles/control.styles";
5
6
  import { useI18n } from "../../../providers/i18n/I18nProvider";
6
7
  import { FieldShell } from "./FieldShell";
7
8
 
@@ -27,7 +28,7 @@ export interface TimePickerProps {
27
28
  readOnly?: boolean;
28
29
 
29
30
  /** Size */
30
- size?: FieldSize;
31
+ size?: ComponentSize;
31
32
 
32
33
  /** Borderless style */
33
34
  inset?: boolean;
@@ -127,7 +127,7 @@ export const Numpad: Component<NumpadProps> = (props) => {
127
127
  setInputStr(valueToInputStr(val));
128
128
  };
129
129
 
130
- const buttonSize = () => props.size ?? "lg";
130
+ const buttonSize = () => props.size ?? "md";
131
131
 
132
132
  return (
133
133
  <div data-numpad class={twMerge(clsx("grid grid-cols-3", gap.sm, "w-auto"), props.class)} style={props.style}>
@@ -138,7 +138,7 @@ export const Numpad: Component<NumpadProps> = (props) => {
138
138
  onValueChange={handleFieldValueChange}
139
139
  placeholder={props.placeholder}
140
140
  readOnly={props.inputDisabled}
141
- inset
141
+ size={buttonSize()}
142
142
  class="w-full"
143
143
  useGrouping={false}
144
144
  />
@@ -148,7 +148,6 @@ export const Numpad: Component<NumpadProps> = (props) => {
148
148
  theme="primary"
149
149
  variant="solid"
150
150
  size={buttonSize()}
151
- inset
152
151
  disabled={props.required && value() == null}
153
152
  onClick={handleEnter}
154
153
  >
@@ -158,60 +157,59 @@ export const Numpad: Component<NumpadProps> = (props) => {
158
157
 
159
158
  {/* Row 2: optional Minus + C + BS */}
160
159
  <Show when={props.withMinusButton}>
161
- <Button size={buttonSize()} inset onClick={handleMinus}>
160
+ <Button size={buttonSize()} onClick={handleMinus}>
162
161
  -
163
162
  </Button>
164
163
  </Show>
165
164
  <Button
166
165
  size={buttonSize()}
167
- inset
168
- onClick={handleClear}
166
+ onClick={handleClear}
169
167
  class={clsx(props.withMinusButton ? "col-span-1" : "col-span-2", "text-danger-500")}
170
168
  >
171
169
  <Icon icon={IconEraser} />
172
170
  </Button>
173
- <Button size={buttonSize()} inset onClick={handleBackspace} class="text-warning-500">
171
+ <Button size={buttonSize()} onClick={handleBackspace} class="text-warning-500">
174
172
  <Icon icon={IconArrowLeft} />
175
173
  </Button>
176
174
 
177
175
  {/* Row 3: 7 8 9 */}
178
- <Button size={buttonSize()} inset onClick={() => handleDigit("7")}>
176
+ <Button size={buttonSize()} onClick={() => handleDigit("7")}>
179
177
  7
180
178
  </Button>
181
- <Button size={buttonSize()} inset onClick={() => handleDigit("8")}>
179
+ <Button size={buttonSize()} onClick={() => handleDigit("8")}>
182
180
  8
183
181
  </Button>
184
- <Button size={buttonSize()} inset onClick={() => handleDigit("9")}>
182
+ <Button size={buttonSize()} onClick={() => handleDigit("9")}>
185
183
  9
186
184
  </Button>
187
185
 
188
186
  {/* Row 4: 4 5 6 */}
189
- <Button size={buttonSize()} inset onClick={() => handleDigit("4")}>
187
+ <Button size={buttonSize()} onClick={() => handleDigit("4")}>
190
188
  4
191
189
  </Button>
192
- <Button size={buttonSize()} inset onClick={() => handleDigit("5")}>
190
+ <Button size={buttonSize()} onClick={() => handleDigit("5")}>
193
191
  5
194
192
  </Button>
195
- <Button size={buttonSize()} inset onClick={() => handleDigit("6")}>
193
+ <Button size={buttonSize()} onClick={() => handleDigit("6")}>
196
194
  6
197
195
  </Button>
198
196
 
199
197
  {/* Row 5: 1 2 3 */}
200
- <Button size={buttonSize()} inset onClick={() => handleDigit("1")}>
198
+ <Button size={buttonSize()} onClick={() => handleDigit("1")}>
201
199
  1
202
200
  </Button>
203
- <Button size={buttonSize()} inset onClick={() => handleDigit("2")}>
201
+ <Button size={buttonSize()} onClick={() => handleDigit("2")}>
204
202
  2
205
203
  </Button>
206
- <Button size={buttonSize()} inset onClick={() => handleDigit("3")}>
204
+ <Button size={buttonSize()} onClick={() => handleDigit("3")}>
207
205
  3
208
206
  </Button>
209
207
 
210
208
  {/* Row 6: 0 (colspan 2) + . */}
211
- <Button size={buttonSize()} inset class="col-span-2" onClick={() => handleDigit("0")}>
209
+ <Button size={buttonSize()} class="col-span-2" onClick={() => handleDigit("0")}>
212
210
  0
213
211
  </Button>
214
- <Button size={buttonSize()} inset onClick={handleDot}>
212
+ <Button size={buttonSize()} onClick={handleDot}>
215
213
  .
216
214
  </Button>
217
215
  </div>
@@ -38,7 +38,10 @@ import {
38
38
  listItemIndentGuideClass,
39
39
  listItemContentClass,
40
40
  getListItemSelectedIconClass,
41
+ listItemBasePadLeft,
42
+ LIST_ITEM_INDENT_SIZE,
41
43
  } from "../../data/list/ListItem.styles";
44
+ import { useListContext } from "../../data/list/ListContext";
42
45
 
43
46
  void ripple;
44
47
 
@@ -108,6 +111,7 @@ const SelectAction = (props: SelectActionProps) => {
108
111
  <button
109
112
  {...rest}
110
113
  type="button"
114
+ use:ripple={!rest.disabled}
111
115
  onClick={handleClick}
112
116
  class={twMerge(
113
117
  "inline-flex items-center",
@@ -177,9 +181,11 @@ export interface SelectItemProps<TValue = unknown> extends Omit<
177
181
  const SelectItemInner = <TValue,>(
178
182
  props: SelectItemProps<TValue> & { children?: JSX.Element },
179
183
  ) => {
180
- const [local, rest] = splitProps(props, ["children", "class", "value", "disabled"]);
184
+ const [local, rest] = splitProps(props, ["children", "class", "style", "value", "disabled"]);
181
185
 
182
186
  const context = useSelectContext<TValue>();
187
+ const listContext = useListContext();
188
+ const level = listContext.level;
183
189
 
184
190
  const [childrenSlot, ItemChildrenProvider] = createItemChildrenSlotAccessor();
185
191
  const hasChildren = () => childrenSlot() !== undefined;
@@ -206,6 +212,13 @@ const SelectItemInner = <TValue,>(
206
212
  local.class,
207
213
  );
208
214
 
215
+ const indentPaddingLeft = level >= 1
216
+ ? `${listItemBasePadLeft[context.size()] + level * LIST_ITEM_INDENT_SIZE}rem`
217
+ : undefined;
218
+
219
+ const getGuideLeft = () =>
220
+ `${listItemBasePadLeft[context.size()] + level * LIST_ITEM_INDENT_SIZE + LIST_ITEM_INDENT_SIZE * 0.5}rem`;
221
+
209
222
  return (
210
223
  <ItemChildrenProvider>
211
224
  <button
@@ -213,6 +226,7 @@ const SelectItemInner = <TValue,>(
213
226
  type="button"
214
227
  use:ripple={useRipple()}
215
228
  class={getClassName()}
229
+ style={{ ...(local.style as JSX.CSSProperties), "padding-left": indentPaddingLeft }}
216
230
  data-select-item
217
231
  data-list-item
218
232
  role="option"
@@ -228,9 +242,9 @@ const SelectItemInner = <TValue,>(
228
242
  </button>
229
243
  <Show when={hasChildren()}>
230
244
  <Collapse open={true}>
231
- <div class="flex">
232
- <div class={listItemIndentGuideClass} />
233
- <List inset class="flex-1">
245
+ <div class="relative">
246
+ <div class={listItemIndentGuideClass} style={{ left: getGuideLeft() }} />
247
+ <List inset>
234
248
  {childrenSlot()!.children}
235
249
  </List>
236
250
  </div>
@@ -622,7 +636,7 @@ const SelectInnerComponent = <TValue,>(props: SelectProps<TValue>) => {
622
636
  local.multiple === true && !local.hideSelectAll && local.items !== undefined;
623
637
 
624
638
  return (
625
- <div {...rest} data-select class={clsx("group", local.inset ? "flex" : "inline-flex")}>
639
+ <div {...rest} data-select class={clsx("group", local.inset ? "flex" : "inline-flex", "[&>[data-dropdown-trigger]]:flex")}>
626
640
  <Dropdown disabled={local.disabled} open={open()} onOpenChange={setOpen} keyboardNav>
627
641
  <Dropdown.Trigger>
628
642
  <div