@simplysm/solid 13.0.84 → 13.0.86
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 +143 -28
- package/dist/components/data/list/ListItem.d.ts.map +1 -1
- package/dist/components/data/list/ListItem.js +11 -4
- package/dist/components/data/list/ListItem.js.map +2 -2
- package/dist/components/data/list/ListItem.styles.d.ts +2 -0
- package/dist/components/data/list/ListItem.styles.d.ts.map +1 -1
- package/dist/components/data/list/ListItem.styles.js +11 -1
- package/dist/components/data/list/ListItem.styles.js.map +1 -1
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +6 -9
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- package/dist/components/data/sheet/hooks/createDataSheetExpansion.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/createDataSheetExpansion.js +15 -17
- package/dist/components/data/sheet/hooks/createDataSheetExpansion.js.map +1 -1
- package/dist/components/data/sheet/hooks/createDataSheetReorder.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/createDataSheetReorder.js +12 -12
- package/dist/components/data/sheet/hooks/createDataSheetReorder.js.map +1 -1
- package/dist/components/data/sheet/hooks/createDataSheetSelection.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/createDataSheetSelection.js +9 -3
- package/dist/components/data/sheet/hooks/createDataSheetSelection.js.map +1 -1
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +3 -21
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
- package/dist/components/disclosure/Dropdown.js +1 -11
- package/dist/components/disclosure/Dropdown.js.map +2 -2
- package/dist/components/disclosure/Tabs.d.ts.map +1 -1
- package/dist/components/disclosure/Tabs.js +1 -3
- package/dist/components/disclosure/Tabs.js.map +2 -2
- package/dist/components/features/crud-detail/CrudDetail.js +103 -102
- package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
- package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
- package/dist/components/features/crud-sheet/CrudSheet.js +10 -5
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.js +30 -26
- package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
- package/dist/components/features/permission-table/PermissionTable.js +5 -1
- package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
- package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -1
- package/dist/components/feedback/busy/BusyContainer.js +1 -6
- package/dist/components/feedback/busy/BusyContainer.js.map +2 -2
- package/dist/components/form-control/DropdownTrigger.styles.js +1 -1
- package/dist/components/form-control/checkbox/SelectableBase.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/SelectableBase.js +2 -4
- package/dist/components/form-control/checkbox/SelectableBase.js.map +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts +19 -5
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +2 -4
- package/dist/components/form-control/combobox/Combobox.js.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +2 -2
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +11 -3
- package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
- package/dist/components/form-control/editor/RichTextEditor.d.ts +2 -2
- package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/components/form-control/editor/RichTextEditor.js +2 -4
- package/dist/components/form-control/editor/RichTextEditor.js.map +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.d.ts +2 -2
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js.map +1 -1
- package/dist/components/form-control/field/Field.styles.d.ts +6 -7
- package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
- package/dist/components/form-control/field/Field.styles.js.map +1 -1
- package/dist/components/form-control/field/NumberInput.d.ts +2 -2
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +7 -7
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts +2 -2
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js.map +1 -1
- package/dist/components/form-control/field/Textarea.d.ts +2 -2
- package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
- package/dist/components/form-control/field/Textarea.js +1 -3
- package/dist/components/form-control/field/Textarea.js.map +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js.map +1 -1
- package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
- package/dist/components/form-control/numpad/Numpad.js +4 -17
- package/dist/components/form-control/numpad/Numpad.js.map +2 -2
- package/dist/components/form-control/select/Select.d.ts +2 -0
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js +29 -15
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/state-preset/StatePreset.d.ts +1 -3
- package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.js +69 -95
- package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
- package/dist/components/layout/FormGroup.js +1 -1
- package/dist/components/layout/FormGroup.js.map +1 -1
- package/dist/components/layout/FormTable.js +3 -3
- package/dist/components/layout/FormTable.js.map +1 -1
- package/dist/components/layout/sidebar/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/sidebar/Sidebar.js +3 -6
- package/dist/components/layout/sidebar/Sidebar.js.map +2 -2
- package/dist/components/layout/topbar/Topbar.js +1 -3
- package/dist/components/layout/topbar/Topbar.js.map +2 -2
- package/dist/hooks/createControllableStore.d.ts.map +1 -1
- package/dist/hooks/createControllableStore.js +8 -5
- package/dist/hooks/createControllableStore.js.map +1 -1
- package/dist/hooks/useLocalStorage.d.ts.map +1 -1
- package/dist/hooks/useLocalStorage.js +3 -2
- package/dist/hooks/useLocalStorage.js.map +1 -1
- package/dist/hooks/useSyncConfig.d.ts.map +1 -1
- package/dist/hooks/useSyncConfig.js +5 -4
- package/dist/hooks/useSyncConfig.js.map +1 -1
- package/dist/providers/i18n/locales/en.d.ts +2 -3
- package/dist/providers/i18n/locales/en.d.ts.map +1 -1
- package/dist/providers/i18n/locales/en.js +3 -4
- package/dist/providers/i18n/locales/en.js.map +1 -1
- package/dist/providers/i18n/locales/ko.d.ts +2 -3
- package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
- package/dist/providers/i18n/locales/ko.js +3 -4
- package/dist/providers/i18n/locales/ko.js.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.js +0 -1
- package/dist/providers/shared-data/SharedDataProvider.js.map +1 -1
- package/docs/display-feedback.md +279 -0
- package/docs/features.md +357 -213
- package/docs/form-controls.md +261 -403
- package/docs/layout-data.md +386 -0
- package/docs/providers-hooks.md +411 -0
- package/package.json +5 -5
- package/src/components/data/list/ListItem.styles.ts +14 -2
- package/src/components/data/list/ListItem.tsx +13 -4
- package/src/components/data/sheet/DataSheet.tsx +6 -10
- package/src/components/data/sheet/hooks/createDataSheetExpansion.ts +17 -18
- package/src/components/data/sheet/hooks/createDataSheetReorder.ts +12 -13
- package/src/components/data/sheet/hooks/createDataSheetSelection.ts +9 -3
- package/src/components/disclosure/Dialog.tsx +45 -59
- package/src/components/disclosure/Dropdown.tsx +4 -14
- package/src/components/disclosure/Tabs.tsx +12 -17
- package/src/components/features/crud-detail/CrudDetail.tsx +4 -4
- package/src/components/features/crud-sheet/CrudSheet.tsx +12 -5
- package/src/components/features/data-select-button/DataSelectButton.tsx +39 -32
- package/src/components/features/permission-table/PermissionTable.tsx +1 -1
- package/src/components/feedback/busy/BusyContainer.tsx +12 -18
- package/src/components/form-control/DropdownTrigger.styles.ts +1 -1
- package/src/components/form-control/checkbox/SelectableBase.tsx +10 -16
- package/src/components/form-control/combobox/Combobox.tsx +42 -16
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +7 -8
- package/src/components/form-control/editor/RichTextEditor.tsx +14 -16
- package/src/components/form-control/field/DatePicker.tsx +3 -2
- package/src/components/form-control/field/DateTimePicker.tsx +3 -2
- package/src/components/form-control/field/Field.styles.ts +6 -8
- package/src/components/form-control/field/NumberInput.tsx +9 -10
- package/src/components/form-control/field/TextInput.tsx +3 -2
- package/src/components/form-control/field/Textarea.tsx +14 -12
- package/src/components/form-control/field/TimePicker.tsx +3 -2
- package/src/components/form-control/numpad/Numpad.tsx +16 -18
- package/src/components/form-control/select/Select.tsx +41 -13
- package/src/components/form-control/state-preset/StatePreset.tsx +39 -71
- package/src/components/layout/FormGroup.tsx +1 -1
- package/src/components/layout/FormTable.tsx +3 -3
- package/src/components/layout/sidebar/Sidebar.tsx +2 -3
- package/src/components/layout/topbar/Topbar.tsx +2 -2
- package/src/hooks/createControllableStore.ts +8 -4
- package/src/hooks/useLocalStorage.ts +3 -2
- package/src/hooks/useSyncConfig.ts +5 -4
- package/src/providers/i18n/locales/en.ts +2 -3
- package/src/providers/i18n/locales/ko.ts +2 -3
- package/src/providers/shared-data/SharedDataProvider.tsx +0 -1
- package/tests/components/features/crud-detail/CrudDetail.spec.tsx +49 -0
- package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +62 -7
- package/tests/components/form-control/combobox/Combobox.spec.tsx +3 -3
- package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +56 -0
- package/tests/components/form-control/select/SelectItem.spec.tsx +5 -0
- package/tests/providers/shared-data/SharedDataProvider.spec.tsx +0 -104
- package/docs/data.md +0 -204
- package/docs/disclosure.md +0 -146
- package/docs/display.md +0 -125
- package/docs/feedback.md +0 -156
- package/docs/helpers.md +0 -173
- package/docs/hooks.md +0 -146
- package/docs/layout.md +0 -94
- 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
|
-
|
|
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
|
|
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
|
-
}
|
|
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
|
|
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
|
-
|
|
350
|
-
|
|
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="
|
|
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
|
|
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?:
|
|
40
|
+
size?: ComponentSize;
|
|
42
41
|
|
|
43
42
|
/** Custom class */
|
|
44
43
|
class?: string;
|
|
@@ -153,11 +152,8 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
153
152
|
setTo(newTo);
|
|
154
153
|
};
|
|
155
154
|
|
|
156
|
-
// Wrapper CSS class
|
|
157
|
-
const getWrapperClass = () => twMerge(clsx("inline-flex items-center", gap.md), local.class);
|
|
158
|
-
|
|
159
155
|
return (
|
|
160
|
-
<div {...rest} data-date-range-picker class={
|
|
156
|
+
<div {...rest} data-date-range-picker class={twMerge(clsx("inline-flex items-center", gap.md), local.class)} style={local.style}>
|
|
161
157
|
<Select
|
|
162
158
|
value={periodType()}
|
|
163
159
|
onValueChange={handlePeriodTypeChange}
|
|
@@ -172,7 +168,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
172
168
|
required
|
|
173
169
|
disabled={local.disabled}
|
|
174
170
|
size={local.size}
|
|
175
|
-
|
|
171
|
+
class="min-w-0"
|
|
176
172
|
>
|
|
177
173
|
<Select.Item value={"day" as DateRangePeriodType}>
|
|
178
174
|
{i18n.t("dateRangePicker.day")}
|
|
@@ -192,6 +188,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
192
188
|
unit={periodType() === "month" ? "month" : "date"}
|
|
193
189
|
value={from()}
|
|
194
190
|
onValueChange={handleFromChange}
|
|
191
|
+
required={local.required}
|
|
195
192
|
disabled={local.disabled}
|
|
196
193
|
size={local.size}
|
|
197
194
|
/>
|
|
@@ -201,6 +198,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
201
198
|
unit="date"
|
|
202
199
|
value={from()}
|
|
203
200
|
onValueChange={handleFromChange}
|
|
201
|
+
required={local.required}
|
|
204
202
|
disabled={local.disabled}
|
|
205
203
|
size={local.size}
|
|
206
204
|
/>
|
|
@@ -210,6 +208,7 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
210
208
|
value={to()}
|
|
211
209
|
onValueChange={handleToChange}
|
|
212
210
|
min={from()}
|
|
211
|
+
required={local.required}
|
|
213
212
|
disabled={local.disabled}
|
|
214
213
|
size={local.size}
|
|
215
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?:
|
|
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<
|
|
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"),
|
|
@@ -146,18 +145,17 @@ export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
|
|
|
146
145
|
editor()?.destroy();
|
|
147
146
|
});
|
|
148
147
|
|
|
149
|
-
const getWrapperClass = () =>
|
|
150
|
-
twMerge(
|
|
151
|
-
clsx("flex flex-col bg-primary-50 dark:bg-primary-950/30", text.default, "border", border.default, "rounded focus-within:border-primary-500"),
|
|
152
|
-
local.disabled && clsx(bg.muted, text.muted),
|
|
153
|
-
local.class,
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const getContentClass = () =>
|
|
157
|
-
twMerge("outline-none prose prose-sm max-w-none dark:prose-invert", editorContentSizeClasses[local.size ?? "md"]);
|
|
158
|
-
|
|
159
148
|
return (
|
|
160
|
-
<div
|
|
149
|
+
<div
|
|
150
|
+
{...rest}
|
|
151
|
+
data-rich-text-editor
|
|
152
|
+
class={twMerge(
|
|
153
|
+
clsx("flex flex-col", text.default, "border", border.default, "rounded focus-within:border-primary-500"),
|
|
154
|
+
local.disabled && clsx(bg.muted, text.muted),
|
|
155
|
+
local.class,
|
|
156
|
+
)}
|
|
157
|
+
style={local.style}
|
|
158
|
+
>
|
|
161
159
|
<Show when={editor()}>
|
|
162
160
|
{(instance) => (
|
|
163
161
|
<Show when={!local.disabled}>
|
|
@@ -165,7 +163,7 @@ export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
|
|
|
165
163
|
</Show>
|
|
166
164
|
)}
|
|
167
165
|
</Show>
|
|
168
|
-
<div ref={editorRef} class={
|
|
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"])} />
|
|
169
167
|
</div>
|
|
170
168
|
);
|
|
171
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,
|
|
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?:
|
|
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 {
|
|
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?:
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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?:
|
|
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?:
|
|
104
|
+
size?: ComponentSize;
|
|
107
105
|
disabled?: boolean;
|
|
108
106
|
inset?: boolean;
|
|
109
107
|
includeCustomClass?: string | false;
|
|
@@ -9,23 +9,16 @@ 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";
|
|
20
20
|
import clsx from "clsx";
|
|
21
21
|
|
|
22
|
-
// NumberInput-specific input style (right-aligned + spinner hidden)
|
|
23
|
-
const numberInputClass = clsx(
|
|
24
|
-
fieldInputClass,
|
|
25
|
-
"text-right",
|
|
26
|
-
"[&::-webkit-outer-spin-button]:appearance-none",
|
|
27
|
-
"[&::-webkit-inner-spin-button]:appearance-none",
|
|
28
|
-
);
|
|
29
22
|
|
|
30
23
|
const [NumberInputPrefixSlot, createNumberInputPrefixAccessor] = createSlot<{ children: JSX.Element }>();
|
|
31
24
|
export const NumberInputPrefix = NumberInputPrefixSlot;
|
|
@@ -56,7 +49,7 @@ export interface NumberInputProps {
|
|
|
56
49
|
readOnly?: boolean;
|
|
57
50
|
|
|
58
51
|
/** Size */
|
|
59
|
-
size?:
|
|
52
|
+
size?: ComponentSize;
|
|
60
53
|
|
|
61
54
|
/** Borderless style */
|
|
62
55
|
inset?: boolean;
|
|
@@ -331,9 +324,15 @@ const NumberInputInner = (props: NumberInputProps): JSX.Element => {
|
|
|
331
324
|
<input
|
|
332
325
|
type="text"
|
|
333
326
|
inputmode="numeric"
|
|
334
|
-
class={
|
|
327
|
+
class={clsx(
|
|
328
|
+
fieldInputClass,
|
|
329
|
+
"text-right",
|
|
330
|
+
"[&::-webkit-outer-spin-button]:appearance-none",
|
|
331
|
+
"[&::-webkit-inner-spin-button]:appearance-none",
|
|
332
|
+
)}
|
|
335
333
|
value={displayValue()}
|
|
336
334
|
placeholder={local.placeholder}
|
|
335
|
+
|
|
337
336
|
title={local.title}
|
|
338
337
|
autocomplete="one-time-code"
|
|
339
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?:
|
|
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 {
|
|
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?:
|
|
33
|
+
size?: ComponentSize;
|
|
33
34
|
|
|
34
35
|
/** Borderless style */
|
|
35
36
|
inset?: boolean;
|
|
@@ -59,13 +60,6 @@ export interface TextareaProps {
|
|
|
59
60
|
style?: JSX.CSSProperties;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
const textareaBaseClass = clsx(
|
|
63
|
-
"absolute left-0 top-0",
|
|
64
|
-
"size-full",
|
|
65
|
-
"resize-none overflow-hidden",
|
|
66
|
-
"bg-transparent",
|
|
67
|
-
text.placeholder,
|
|
68
|
-
);
|
|
69
63
|
|
|
70
64
|
/**
|
|
71
65
|
* Textarea component
|
|
@@ -164,8 +158,6 @@ export const Textarea: Component<TextareaProps> = (props) => {
|
|
|
164
158
|
"whitespace-pre-wrap break-all",
|
|
165
159
|
);
|
|
166
160
|
|
|
167
|
-
const getTextareaClass = () =>
|
|
168
|
-
twMerge(textareaBaseClass, textAreaSizeClasses[local.size ?? "md"], local.inset && "p-0");
|
|
169
161
|
|
|
170
162
|
// Whether editable
|
|
171
163
|
const isEditable = () => !local.disabled && !local.readOnly;
|
|
@@ -228,7 +220,17 @@ export const Textarea: Component<TextareaProps> = (props) => {
|
|
|
228
220
|
{contentForHeight()}
|
|
229
221
|
</div>
|
|
230
222
|
<textarea
|
|
231
|
-
class={
|
|
223
|
+
class={twMerge(
|
|
224
|
+
clsx(
|
|
225
|
+
"absolute left-0 top-0",
|
|
226
|
+
"size-full",
|
|
227
|
+
"resize-none overflow-hidden",
|
|
228
|
+
"bg-transparent",
|
|
229
|
+
text.placeholder,
|
|
230
|
+
),
|
|
231
|
+
textAreaSizeClasses[local.size ?? "md"],
|
|
232
|
+
local.inset && "p-0",
|
|
233
|
+
)}
|
|
232
234
|
value={value()}
|
|
233
235
|
placeholder={local.placeholder}
|
|
234
236
|
title={local.title}
|
|
@@ -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 {
|
|
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?:
|
|
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 ?? "
|
|
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
|
-
|
|
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()}
|
|
160
|
+
<Button size={buttonSize()} onClick={handleMinus}>
|
|
162
161
|
-
|
|
163
162
|
</Button>
|
|
164
163
|
</Show>
|
|
165
164
|
<Button
|
|
166
165
|
size={buttonSize()}
|
|
167
|
-
|
|
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()}
|
|
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()}
|
|
176
|
+
<Button size={buttonSize()} onClick={() => handleDigit("7")}>
|
|
179
177
|
7
|
|
180
178
|
</Button>
|
|
181
|
-
<Button size={buttonSize()}
|
|
179
|
+
<Button size={buttonSize()} onClick={() => handleDigit("8")}>
|
|
182
180
|
8
|
|
183
181
|
</Button>
|
|
184
|
-
<Button size={buttonSize()}
|
|
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()}
|
|
187
|
+
<Button size={buttonSize()} onClick={() => handleDigit("4")}>
|
|
190
188
|
4
|
|
191
189
|
</Button>
|
|
192
|
-
<Button size={buttonSize()}
|
|
190
|
+
<Button size={buttonSize()} onClick={() => handleDigit("5")}>
|
|
193
191
|
5
|
|
194
192
|
</Button>
|
|
195
|
-
<Button size={buttonSize()}
|
|
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()}
|
|
198
|
+
<Button size={buttonSize()} onClick={() => handleDigit("1")}>
|
|
201
199
|
1
|
|
202
200
|
</Button>
|
|
203
|
-
<Button size={buttonSize()}
|
|
201
|
+
<Button size={buttonSize()} onClick={() => handleDigit("2")}>
|
|
204
202
|
2
|
|
205
203
|
</Button>
|
|
206
|
-
<Button size={buttonSize()}
|
|
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()}
|
|
209
|
+
<Button size={buttonSize()} class="col-span-2" onClick={() => handleDigit("0")}>
|
|
212
210
|
0
|
|
213
211
|
</Button>
|
|
214
|
-
<Button size={buttonSize()}
|
|
212
|
+
<Button size={buttonSize()} onClick={handleDot}>
|
|
215
213
|
.
|
|
216
214
|
</Button>
|
|
217
215
|
</div>
|