@simplysm/solid 13.0.69 → 13.0.71
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 +168 -195
- package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
- package/dist/components/data/calendar/Calendar.js +15 -2
- package/dist/components/data/calendar/Calendar.js.map +2 -2
- package/dist/components/data/kanban/KanbanContext.js +2 -2
- package/dist/components/data/kanban/KanbanContext.js.map +1 -1
- package/dist/components/data/list/List.d.ts +8 -8
- package/dist/components/data/list/ListContext.d.ts +1 -1
- package/dist/components/data/list/ListItem.d.ts +15 -15
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +6 -4
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- package/dist/components/data/sheet/DataSheetConfigDialog.js +8 -8
- package/dist/components/data/sheet/DataSheetConfigDialog.js.map +1 -1
- package/dist/components/data/sheet/types.d.ts +4 -4
- package/dist/components/data/sheet/types.d.ts.map +1 -1
- package/dist/components/disclosure/Collapse.d.ts +4 -4
- package/dist/components/disclosure/Dialog.d.ts +24 -24
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +7 -2
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/DialogContext.d.ts +25 -25
- package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
- package/dist/components/disclosure/DialogContext.js +1 -1
- package/dist/components/disclosure/DialogContext.js.map +1 -1
- package/dist/components/disclosure/DialogInstanceContext.d.ts +7 -7
- package/dist/components/disclosure/DialogInstanceContext.d.ts.map +1 -1
- package/dist/components/disclosure/DialogProvider.d.ts +3 -3
- package/dist/components/disclosure/Dropdown.d.ts +26 -24
- package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
- package/dist/components/disclosure/Dropdown.js +24 -8
- package/dist/components/disclosure/Dropdown.js.map +2 -2
- package/dist/components/disclosure/Tabs.js +1 -1
- package/dist/components/disclosure/Tabs.js.map +1 -1
- package/dist/components/disclosure/dialogZIndex.d.ts +9 -7
- package/dist/components/disclosure/dialogZIndex.d.ts.map +1 -1
- package/dist/components/disclosure/dialogZIndex.js +4 -0
- package/dist/components/disclosure/dialogZIndex.js.map +1 -1
- package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
- package/dist/components/features/crud-detail/CrudDetail.js +34 -22
- 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 +48 -33
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/crudRegistry.d.ts +16 -0
- package/dist/components/features/crudRegistry.d.ts.map +1 -0
- package/dist/components/features/crudRegistry.js +37 -0
- package/dist/components/features/crudRegistry.js.map +6 -0
- package/dist/components/features/data-select-button/DataSelectButton.d.ts +14 -14
- package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.js +27 -9
- package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
- package/dist/components/features/permission-table/PermissionTable.d.ts +3 -3
- package/dist/components/features/permission-table/PermissionTable.d.ts.map +1 -1
- package/dist/components/features/permission-table/PermissionTable.js +74 -85
- package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelect.d.ts +12 -12
- package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelect.js +10 -6
- package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +10 -10
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts +23 -15
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.js +191 -65
- package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectListContext.d.ts +15 -0
- package/dist/components/features/shared-data/SharedDataSelectListContext.d.ts.map +1 -0
- package/dist/components/features/shared-data/SharedDataSelectListContext.js +27 -0
- package/dist/components/features/shared-data/SharedDataSelectListContext.js.map +6 -0
- package/dist/components/feedback/Progress.d.ts +1 -1
- package/dist/components/feedback/Progress.d.ts.map +1 -1
- package/dist/components/feedback/busy/BusyContainer.d.ts +2 -2
- package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -1
- package/dist/components/feedback/busy/BusyContext.d.ts +11 -11
- package/dist/components/feedback/busy/BusyContext.d.ts.map +1 -1
- package/dist/components/feedback/busy/BusyContext.js +1 -1
- package/dist/components/feedback/busy/BusyContext.js.map +1 -1
- package/dist/components/feedback/busy/BusyProvider.d.ts +6 -6
- package/dist/components/feedback/busy/BusyProvider.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBanner.js +7 -3
- package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBell.js +2 -2
- package/dist/components/feedback/notification/NotificationBell.js.map +1 -1
- package/dist/components/feedback/notification/NotificationContext.d.ts +22 -22
- package/dist/components/feedback/notification/NotificationContext.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationContext.js +1 -1
- package/dist/components/feedback/notification/NotificationContext.js.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.d.ts +5 -5
- package/dist/components/feedback/notification/NotificationProvider.js +1 -1
- package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
- package/dist/components/feedback/print/PrintContext.js +1 -1
- package/dist/components/feedback/print/PrintContext.js.map +1 -1
- package/dist/components/form-control/DropdownTrigger.styles.d.ts +1 -1
- package/dist/components/form-control/DropdownTrigger.styles.d.ts.map +1 -1
- package/dist/components/form-control/ThemeToggle.d.ts +7 -7
- package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
- package/dist/components/form-control/ThemeToggle.js +3 -3
- package/dist/components/form-control/checkbox/Checkbox.js +1 -1
- package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
- package/dist/components/form-control/checkbox/Radio.js +1 -1
- package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.d.ts +12 -12
- package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.js +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts +22 -22
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +2 -2
- package/dist/components/form-control/combobox/ComboboxContext.d.ts +4 -4
- package/dist/components/form-control/combobox/ComboboxContext.d.ts.map +1 -1
- package/dist/components/form-control/combobox/ComboboxContext.js +1 -1
- package/dist/components/form-control/combobox/ComboboxContext.js.map +1 -1
- package/dist/components/form-control/combobox/ComboboxItem.d.ts +3 -3
- package/dist/components/form-control/combobox/ComboboxItem.d.ts.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +14 -14
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +20 -9
- package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
- package/dist/components/form-control/editor/EditorToolbar.d.ts.map +1 -1
- package/dist/components/form-control/editor/EditorToolbar.js +65 -20
- package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
- package/dist/components/form-control/editor/RichTextEditor.d.ts +6 -6
- package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/components/form-control/editor/RichTextEditor.js +1 -1
- package/dist/components/form-control/editor/editor.css +5 -5
- package/dist/components/form-control/field/DatePicker.d.ts +22 -22
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js +4 -4
- package/dist/components/form-control/field/DatePicker.js.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.d.ts +21 -21
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js +4 -4
- package/dist/components/form-control/field/DateTimePicker.js.map +1 -1
- package/dist/components/form-control/field/FieldPlaceholder.d.ts +1 -1
- package/dist/components/form-control/field/FieldPlaceholder.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.d.ts +23 -23
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +4 -4
- package/dist/components/form-control/field/NumberInput.js.map +1 -1
- package/dist/components/form-control/field/TextInput.d.ts +25 -25
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +5 -5
- package/dist/components/form-control/field/TextInput.js.map +1 -1
- package/dist/components/form-control/field/Textarea.d.ts +19 -19
- package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
- package/dist/components/form-control/field/Textarea.js +4 -4
- package/dist/components/form-control/field/Textarea.js.map +1 -1
- package/dist/components/form-control/field/TimePicker.d.ts +20 -20
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js +4 -4
- package/dist/components/form-control/field/TimePicker.js.map +1 -1
- package/dist/components/form-control/numpad/Numpad.d.ts +11 -11
- package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.d.ts +26 -26
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js +34 -23
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/select/SelectContext.d.ts +7 -7
- package/dist/components/form-control/select/SelectContext.d.ts.map +1 -1
- package/dist/components/form-control/select/SelectContext.js +1 -1
- package/dist/components/form-control/select/SelectContext.js.map +1 -1
- package/dist/components/form-control/select/SelectItem.d.ts +4 -4
- package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.js +8 -8
- package/dist/components/form-control/state-preset/StatePreset.js.map +1 -1
- package/dist/components/layout/FormTable.js +4 -4
- package/dist/components/layout/sidebar/Sidebar.d.ts +5 -5
- package/dist/components/layout/sidebar/SidebarContainer.d.ts +11 -11
- package/dist/components/layout/sidebar/SidebarContainer.d.ts.map +1 -1
- package/dist/components/layout/sidebar/SidebarContainer.js +6 -1
- package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
- package/dist/components/layout/sidebar/SidebarContext.d.ts +7 -7
- package/dist/components/layout/sidebar/SidebarContext.js +1 -1
- package/dist/components/layout/sidebar/SidebarContext.js.map +1 -1
- package/dist/components/layout/sidebar/SidebarMenu.d.ts +11 -11
- package/dist/components/layout/sidebar/SidebarUser.d.ts +14 -14
- package/dist/components/layout/topbar/Topbar.d.ts +6 -6
- package/dist/components/layout/topbar/Topbar.d.ts.map +1 -1
- package/dist/components/layout/topbar/Topbar.js +11 -6
- package/dist/components/layout/topbar/Topbar.js.map +2 -2
- package/dist/components/layout/topbar/TopbarContainer.d.ts +6 -6
- package/dist/components/layout/topbar/TopbarContext.js +2 -2
- package/dist/components/layout/topbar/TopbarContext.js.map +1 -1
- package/dist/components/layout/topbar/TopbarMenu.d.ts +11 -11
- package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
- package/dist/components/layout/topbar/TopbarMenu.js +5 -1
- package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
- package/dist/components/layout/topbar/TopbarUser.d.ts +9 -9
- package/dist/directives/ripple.d.ts +5 -5
- package/dist/helpers/createAppStructure.d.ts.map +1 -1
- package/dist/helpers/createAppStructure.js +7 -3
- package/dist/helpers/createAppStructure.js.map +1 -1
- package/dist/helpers/createHmrSafeContext.d.ts +3 -0
- package/dist/helpers/createHmrSafeContext.d.ts.map +1 -0
- package/dist/helpers/createHmrSafeContext.js +10 -0
- package/dist/helpers/createHmrSafeContext.js.map +6 -0
- package/dist/helpers/createSlotComponent.d.ts +3 -3
- package/dist/helpers/mergeStyles.d.ts +8 -8
- package/dist/hooks/createControllableSignal.d.ts +10 -10
- package/dist/hooks/createControllableStore.d.ts +6 -6
- package/dist/hooks/createIMEHandler.d.ts +7 -7
- package/dist/hooks/createMountTransition.d.ts +4 -4
- package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
- package/dist/hooks/createSelectionGroup.js +4 -3
- package/dist/hooks/createSelectionGroup.js.map +2 -2
- package/dist/hooks/createSlotSignal.d.ts +2 -2
- package/dist/hooks/useLocalStorage.d.ts +11 -11
- package/dist/hooks/useLogger.d.ts +1 -1
- package/dist/hooks/useLogger.d.ts.map +1 -1
- package/dist/hooks/useLogger.js +1 -1
- package/dist/hooks/useLogger.js.map +1 -1
- package/dist/hooks/useRouterLink.d.ts +10 -10
- package/dist/hooks/useRouterLink.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/ClipboardProvider.d.ts +5 -5
- package/dist/providers/ConfigContext.d.ts +6 -6
- package/dist/providers/ConfigContext.js +2 -2
- package/dist/providers/ConfigContext.js.map +1 -1
- package/dist/providers/ErrorLoggerProvider.d.ts +3 -3
- package/dist/providers/LoggerContext.d.ts +13 -13
- package/dist/providers/PwaUpdateProvider.d.ts +4 -4
- package/dist/providers/PwaUpdateProvider.js +2 -2
- package/dist/providers/PwaUpdateProvider.js.map +1 -1
- package/dist/providers/ServiceClientContext.d.ts +8 -8
- package/dist/providers/ServiceClientContext.d.ts.map +1 -1
- package/dist/providers/ServiceClientContext.js +1 -1
- package/dist/providers/ServiceClientContext.js.map +1 -1
- package/dist/providers/ServiceClientProvider.d.ts +6 -6
- package/dist/providers/ServiceClientProvider.js +7 -7
- package/dist/providers/ServiceClientProvider.js.map +1 -1
- package/dist/providers/SyncStorageContext.d.ts +14 -14
- package/dist/providers/SystemProvider.d.ts.map +1 -1
- package/dist/providers/SystemProvider.js +21 -16
- package/dist/providers/SystemProvider.js.map +2 -2
- package/dist/providers/ThemeContext.d.ts +20 -20
- package/dist/providers/ThemeContext.d.ts.map +1 -1
- package/dist/providers/ThemeContext.js +1 -1
- package/dist/providers/ThemeContext.js.map +1 -1
- package/dist/providers/i18n/I18nContext.d.ts +44 -0
- package/dist/providers/i18n/I18nContext.d.ts.map +1 -0
- package/dist/providers/i18n/I18nContext.js +73 -0
- package/dist/providers/i18n/I18nContext.js.map +6 -0
- package/dist/providers/i18n/I18nContext.types.d.ts +28 -0
- package/dist/providers/i18n/I18nContext.types.d.ts.map +1 -0
- package/dist/providers/i18n/I18nContext.types.js +1 -0
- package/dist/providers/i18n/I18nContext.types.js.map +6 -0
- package/dist/providers/i18n/i18nUtils.d.ts +18 -0
- package/dist/providers/i18n/i18nUtils.d.ts.map +1 -0
- package/dist/providers/i18n/i18nUtils.js +25 -0
- package/dist/providers/i18n/i18nUtils.js.map +6 -0
- package/dist/providers/i18n/locales/en.d.ts +163 -0
- package/dist/providers/i18n/locales/en.d.ts.map +1 -0
- package/dist/providers/i18n/locales/en.js +165 -0
- package/dist/providers/i18n/locales/en.js.map +6 -0
- package/dist/providers/i18n/locales/ko.d.ts +163 -0
- package/dist/providers/i18n/locales/ko.d.ts.map +1 -0
- package/dist/providers/i18n/locales/ko.js +165 -0
- package/dist/providers/i18n/locales/ko.js.map +6 -0
- package/dist/providers/shared-data/SharedDataChangeEvent.d.ts +4 -4
- package/dist/providers/shared-data/SharedDataContext.d.ts +28 -28
- package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataContext.js +1 -1
- package/dist/providers/shared-data/SharedDataContext.js.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.d.ts +9 -9
- package/dist/providers/shared-data/SharedDataProvider.js +4 -4
- package/dist/providers/shared-data/SharedDataProvider.js.map +1 -1
- package/package.json +9 -8
- package/src/components/data/calendar/Calendar.tsx +10 -4
- package/src/components/data/kanban/Kanban.tsx +14 -14
- package/src/components/data/kanban/KanbanContext.ts +3 -3
- package/src/components/data/list/List.tsx +10 -10
- package/src/components/data/list/ListContext.ts +1 -1
- package/src/components/data/list/ListItem.styles.ts +8 -8
- package/src/components/data/list/ListItem.tsx +15 -15
- package/src/components/data/sheet/DataSheet.styles.ts +22 -22
- package/src/components/data/sheet/DataSheet.tsx +52 -48
- package/src/components/data/sheet/DataSheetColumn.tsx +1 -1
- package/src/components/data/sheet/DataSheetConfigDialog.tsx +9 -9
- package/src/components/data/sheet/sheetUtils.ts +7 -7
- package/src/components/data/sheet/types.ts +16 -16
- package/src/components/disclosure/Collapse.tsx +11 -11
- package/src/components/disclosure/Dialog.tsx +60 -57
- package/src/components/disclosure/DialogContext.ts +26 -26
- package/src/components/disclosure/DialogInstanceContext.ts +7 -7
- package/src/components/disclosure/DialogProvider.tsx +5 -5
- package/src/components/disclosure/Dropdown.tsx +89 -75
- package/src/components/disclosure/Tabs.tsx +1 -1
- package/src/components/disclosure/dialogZIndex.ts +16 -11
- package/src/components/display/Echarts.tsx +4 -4
- package/src/components/features/address/AddressSearch.tsx +2 -2
- package/src/components/features/crud-detail/CrudDetail.tsx +34 -21
- package/src/components/features/crud-detail/CrudDetailAfter.tsx +1 -1
- package/src/components/features/crud-detail/CrudDetailBefore.tsx +1 -1
- package/src/components/features/crud-detail/CrudDetailTools.tsx +1 -1
- package/src/components/features/crud-sheet/CrudSheet.tsx +52 -40
- package/src/components/features/crud-sheet/CrudSheetColumn.tsx +1 -1
- package/src/components/features/crud-sheet/CrudSheetFilter.tsx +1 -1
- package/src/components/features/crud-sheet/CrudSheetHeader.tsx +1 -1
- package/src/components/features/crud-sheet/CrudSheetTools.tsx +1 -1
- package/src/components/features/crudRegistry.ts +60 -0
- package/src/components/features/data-select-button/DataSelectButton.tsx +34 -32
- package/src/components/features/permission-table/PermissionTable.tsx +70 -64
- package/src/components/features/shared-data/SharedDataSelect.tsx +24 -22
- package/src/components/features/shared-data/SharedDataSelectButton.tsx +10 -10
- package/src/components/features/shared-data/SharedDataSelectList.tsx +231 -59
- package/src/components/features/shared-data/SharedDataSelectListContext.ts +39 -0
- package/src/components/feedback/Progress.tsx +1 -1
- package/src/components/feedback/busy/BusyContainer.tsx +6 -6
- package/src/components/feedback/busy/BusyContext.ts +12 -12
- package/src/components/feedback/busy/BusyProvider.tsx +6 -6
- package/src/components/feedback/notification/NotificationBanner.tsx +3 -1
- package/src/components/feedback/notification/NotificationBell.tsx +4 -4
- package/src/components/feedback/notification/NotificationContext.ts +28 -28
- package/src/components/feedback/notification/NotificationProvider.tsx +9 -9
- package/src/components/feedback/print/PrintContext.ts +1 -1
- package/src/components/form-control/Button.tsx +1 -1
- package/src/components/form-control/DropdownTrigger.styles.ts +1 -1
- package/src/components/form-control/Invalid.tsx +5 -5
- package/src/components/form-control/ThemeToggle.tsx +10 -10
- package/src/components/form-control/checkbox/Checkbox.styles.ts +8 -8
- package/src/components/form-control/checkbox/Checkbox.tsx +2 -2
- package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/form-control/checkbox/Radio.tsx +2 -2
- package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
- package/src/components/form-control/color-picker/ColorPicker.tsx +17 -17
- package/src/components/form-control/combobox/Combobox.tsx +55 -55
- package/src/components/form-control/combobox/ComboboxContext.ts +5 -5
- package/src/components/form-control/combobox/ComboboxItem.tsx +3 -3
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +40 -26
- package/src/components/form-control/editor/EditorToolbar.tsx +52 -50
- package/src/components/form-control/editor/RichTextEditor.tsx +16 -16
- package/src/components/form-control/editor/editor.css +5 -5
- package/src/components/form-control/field/DatePicker.tsx +39 -39
- package/src/components/form-control/field/DateTimePicker.tsx +38 -38
- package/src/components/form-control/field/Field.styles.ts +11 -11
- package/src/components/form-control/field/FieldPlaceholder.tsx +1 -1
- package/src/components/form-control/field/NumberInput.tsx +63 -63
- package/src/components/form-control/field/TextInput.tsx +48 -48
- package/src/components/form-control/field/Textarea.tsx +32 -32
- package/src/components/form-control/field/TimePicker.tsx +37 -37
- package/src/components/form-control/numpad/Numpad.tsx +26 -26
- package/src/components/form-control/select/Select.tsx +82 -86
- package/src/components/form-control/select/SelectContext.ts +8 -8
- package/src/components/form-control/select/SelectItem.tsx +5 -5
- package/src/components/form-control/state-preset/StatePreset.tsx +13 -13
- package/src/components/layout/FormTable.tsx +4 -4
- package/src/components/layout/sidebar/Sidebar.tsx +8 -8
- package/src/components/layout/sidebar/SidebarContainer.tsx +19 -17
- package/src/components/layout/sidebar/SidebarContext.ts +8 -8
- package/src/components/layout/sidebar/SidebarMenu.tsx +19 -19
- package/src/components/layout/sidebar/SidebarUser.tsx +14 -14
- package/src/components/layout/topbar/Topbar.tsx +15 -13
- package/src/components/layout/topbar/TopbarContainer.tsx +6 -6
- package/src/components/layout/topbar/TopbarContext.ts +2 -2
- package/src/components/layout/topbar/TopbarMenu.tsx +18 -16
- package/src/components/layout/topbar/TopbarUser.tsx +9 -9
- package/src/directives/ripple.ts +8 -8
- package/src/helpers/createAppStructure.ts +15 -8
- package/src/helpers/createHmrSafeContext.ts +8 -0
- package/src/helpers/createSlotComponent.ts +4 -4
- package/src/helpers/mergeStyles.ts +11 -11
- package/src/hooks/createControllableSignal.ts +11 -11
- package/src/hooks/createControllableStore.ts +8 -8
- package/src/hooks/createIMEHandler.ts +7 -7
- package/src/hooks/createMountTransition.ts +4 -4
- package/src/hooks/createSelectionGroup.tsx +5 -3
- package/src/hooks/createSlotSignal.ts +2 -2
- package/src/hooks/useLocalStorage.ts +13 -13
- package/src/hooks/useLogger.ts +2 -2
- package/src/hooks/useRouterLink.ts +15 -15
- package/src/index.ts +4 -3
- package/src/providers/ClipboardProvider.tsx +19 -19
- package/src/providers/ConfigContext.tsx +8 -8
- package/src/providers/ErrorLoggerProvider.tsx +3 -3
- package/src/providers/LoggerContext.tsx +13 -13
- package/src/providers/PwaUpdateProvider.tsx +6 -6
- package/src/providers/ServiceClientContext.ts +9 -9
- package/src/providers/ServiceClientProvider.tsx +15 -15
- package/src/providers/SyncStorageContext.tsx +15 -15
- package/src/providers/SystemProvider.tsx +15 -12
- package/src/providers/ThemeContext.tsx +26 -26
- package/src/providers/i18n/I18nContext.tsx +129 -0
- package/src/providers/i18n/I18nContext.types.ts +30 -0
- package/src/providers/i18n/i18nUtils.ts +38 -0
- package/src/providers/i18n/locales/en.ts +161 -0
- package/src/providers/i18n/locales/ko.ts +161 -0
- package/src/providers/shared-data/SharedDataChangeEvent.ts +4 -4
- package/src/providers/shared-data/SharedDataContext.ts +29 -29
- package/src/providers/shared-data/SharedDataProvider.tsx +21 -21
- package/src/styles/patterns.styles.ts +6 -6
- package/src/styles/tokens.styles.ts +5 -5
- package/tailwind.config.ts +1 -1
- package/tailwind.css +4 -4
- package/tests/components/data/List.spec.tsx +689 -0
- package/tests/components/data/Pagination.spec.tsx +336 -0
- package/tests/components/data/Table.spec.tsx +55 -0
- package/tests/components/data/kanban/Kanban.selection.spec.tsx +213 -0
- package/tests/components/data/sheet/DataSheet.spec.tsx +645 -0
- package/tests/components/disclosure/Collapse.spec.tsx +173 -0
- package/tests/components/disclosure/Dialog.spec.tsx +438 -0
- package/tests/components/disclosure/DialogProvider.spec.tsx +142 -0
- package/tests/components/disclosure/Dropdown.spec.tsx +333 -0
- package/tests/components/disclosure/Tabs.spec.tsx +220 -0
- package/tests/components/disclosure/dialogZIndex.spec.ts +45 -0
- package/tests/components/display/Alert.spec.tsx +47 -0
- package/tests/components/display/Barcode.spec.tsx +61 -0
- package/tests/components/display/Card.spec.tsx +41 -0
- package/tests/components/display/Link.spec.tsx +62 -0
- package/tests/components/display/Tag.spec.tsx +47 -0
- package/tests/components/features/address/AddressSearch.spec.tsx +45 -0
- package/tests/components/features/crud-detail/CrudDetail.spec.tsx +537 -0
- package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +491 -0
- package/tests/components/features/crudRegistry.spec.ts +119 -0
- package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +482 -0
- package/tests/components/features/permission-table/PermissionTable.spec.tsx +288 -0
- package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +448 -0
- package/tests/components/feedback/busy/BusyContainer.spec.tsx +80 -0
- package/tests/components/feedback/notification/LiveRegion.spec.tsx +52 -0
- package/tests/components/feedback/notification/NotificationBanner.spec.tsx +187 -0
- package/tests/components/feedback/notification/NotificationBell.spec.tsx +226 -0
- package/tests/components/feedback/notification/NotificationContext.spec.tsx +362 -0
- package/tests/components/feedback/print/Print.spec.tsx +45 -0
- package/tests/components/form-control/Button.spec.tsx +119 -0
- package/tests/components/form-control/Invalid.spec.tsx +131 -0
- package/tests/components/form-control/checkbox/Checkbox.spec.tsx +137 -0
- package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +108 -0
- package/tests/components/form-control/checkbox/Radio.spec.tsx +138 -0
- package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +108 -0
- package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +94 -0
- package/tests/components/form-control/combobox/Combobox.spec.tsx +253 -0
- package/tests/components/form-control/combobox/ComboboxItem.spec.tsx +88 -0
- package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +208 -0
- package/tests/components/form-control/field/DatePicker.spec.tsx +381 -0
- package/tests/components/form-control/field/DateTimePicker.spec.tsx +383 -0
- package/tests/components/form-control/field/NumberInput.spec.tsx +371 -0
- package/tests/components/form-control/field/TextInput.spec.tsx +341 -0
- package/tests/components/form-control/field/Textarea.spec.tsx +224 -0
- package/tests/components/form-control/field/TimePicker.spec.tsx +315 -0
- package/tests/components/form-control/numpad/Numpad.spec.tsx +248 -0
- package/tests/components/form-control/select/Select.spec.tsx +676 -0
- package/tests/components/form-control/select/SelectItem.spec.tsx +174 -0
- package/tests/components/layout/FormGroup.spec.tsx +104 -0
- package/tests/components/layout/FormTable.spec.tsx +43 -0
- package/tests/components/layout/sidebar/Sidebar.spec.tsx +192 -0
- package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +261 -0
- package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +219 -0
- package/tests/components/layout/sidebar/SidebarUser.spec.tsx +133 -0
- package/tests/components/layout/topbar/TopbarActions.spec.tsx +77 -0
- package/tests/components/layout/topbar/TopbarContainer.spec.tsx +38 -0
- package/tests/components/layout/topbar/createTopbarActions.spec.tsx +66 -0
- package/tests/directives/ripple.spec.tsx +130 -0
- package/tests/helpers/createAppStructure.spec.tsx +843 -0
- package/tests/helpers/mergeStyles.spec.ts +172 -0
- package/tests/hooks/createControllableSignal.spec.ts +194 -0
- package/tests/hooks/createIMEHandler.spec.ts +80 -0
- package/tests/hooks/createMountTransition.spec.ts +86 -0
- package/tests/hooks/useLocalStorage.spec.tsx +223 -0
- package/tests/hooks/useLogger.spec.tsx +116 -0
- package/tests/hooks/usePrint.spec.tsx +134 -0
- package/tests/hooks/useRouterLink.spec.tsx +183 -0
- package/tests/hooks/useSyncConfig.spec.tsx +304 -0
- package/tests/providers/ClipboardProvider.spec.tsx +20 -0
- package/tests/providers/ConfigContext.spec.tsx +42 -0
- package/tests/providers/ErrorLoggerProvider.spec.tsx +73 -0
- package/tests/providers/LoggerContext.spec.tsx +76 -0
- package/tests/providers/PwaUpdateProvider.spec.tsx +22 -0
- package/tests/providers/ServiceClientContext.spec.tsx +88 -0
- package/tests/providers/SyncStorageContext.spec.tsx +77 -0
- package/tests/providers/i18n/I18nContext.spec.tsx +110 -0
- package/tests/providers/shared-data/SharedDataProvider.spec.tsx +401 -0
- package/tests/vitest-env.d.ts +1 -0
- package/dist/components/form-control/select-list/SelectList.d.ts +0 -54
- package/dist/components/form-control/select-list/SelectList.d.ts.map +0 -1
- package/dist/components/form-control/select-list/SelectList.js +0 -280
- package/dist/components/form-control/select-list/SelectList.js.map +0 -6
- package/dist/components/form-control/select-list/SelectListContext.d.ts +0 -13
- package/dist/components/form-control/select-list/SelectListContext.d.ts.map +0 -1
- package/dist/components/form-control/select-list/SelectListContext.js +0 -14
- package/dist/components/form-control/select-list/SelectListContext.js.map +0 -6
- package/docs/data-components.md +0 -782
- package/docs/disclosure.md +0 -254
- package/docs/display.md +0 -153
- package/docs/feedback.md +0 -238
- package/docs/form-controls.md +0 -1068
- package/docs/helpers.md +0 -54
- package/docs/hooks.md +0 -588
- package/docs/layout.md +0 -384
- package/docs/providers.md +0 -211
- package/docs/styling.md +0 -184
- package/src/components/form-control/select-list/SelectList.tsx +0 -385
- package/src/components/form-control/select-list/SelectListContext.ts +0 -23
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { render, fireEvent } from "@solidjs/testing-library";
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
|
+
import { createSignal } from "solid-js";
|
|
4
|
+
import { TextInput } from "../../../../src/components/form-control/field/TextInput";
|
|
5
|
+
|
|
6
|
+
describe("TextInput component", () => {
|
|
7
|
+
describe("basic rendering", () => {
|
|
8
|
+
it("renders input element", () => {
|
|
9
|
+
const { container } = render(() => <TextInput />);
|
|
10
|
+
const input = container.querySelector("input");
|
|
11
|
+
expect(input).toBeTruthy();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("defaults type to text", () => {
|
|
15
|
+
const { container } = render(() => <TextInput />);
|
|
16
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
17
|
+
expect(input.type).toBe("text");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("renders password input when type=password", () => {
|
|
21
|
+
const { container } = render(() => <TextInput type="password" />);
|
|
22
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
23
|
+
expect(input.type).toBe("password");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("renders email input when type=email", () => {
|
|
27
|
+
const { container } = render(() => <TextInput type="email" />);
|
|
28
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
29
|
+
expect(input.type).toBe("email");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("applies placeholder to input", () => {
|
|
33
|
+
const { container } = render(() => <TextInput placeholder="Enter text" />);
|
|
34
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
35
|
+
expect(input.placeholder).toBe("Enter text");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("applies title to input", () => {
|
|
39
|
+
const { container } = render(() => <TextInput title="Input title" />);
|
|
40
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
41
|
+
expect(input.title).toBe("Input title");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("defaults autocomplete to one-time-code", () => {
|
|
45
|
+
const { container } = render(() => <TextInput />);
|
|
46
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
47
|
+
expect(input.autocomplete).toBe("one-time-code");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("applies explicitly specified autocomplete value", () => {
|
|
51
|
+
const { container } = render(() => <TextInput autocomplete="email" />);
|
|
52
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
53
|
+
expect(input.autocomplete).toBe("email");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("controlled pattern", () => {
|
|
58
|
+
it("displays value prop in input", () => {
|
|
59
|
+
const { container } = render(() => <TextInput value="Hello" />);
|
|
60
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
61
|
+
expect(input.value).toBe("Hello");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("calls onValueChange on input", () => {
|
|
65
|
+
const handleChange = vi.fn();
|
|
66
|
+
const { container } = render(() => <TextInput value="" onValueChange={handleChange} />);
|
|
67
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
68
|
+
|
|
69
|
+
fireEvent.input(input, { target: { value: "Test" } });
|
|
70
|
+
|
|
71
|
+
expect(handleChange).toHaveBeenCalledWith("Test");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("updates input value when external state changes", () => {
|
|
75
|
+
const [value, setValue] = createSignal("Initial");
|
|
76
|
+
const { container } = render(() => <TextInput value={value()} onValueChange={setValue} />);
|
|
77
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
78
|
+
|
|
79
|
+
expect(input.value).toBe("Initial");
|
|
80
|
+
|
|
81
|
+
setValue("Updated");
|
|
82
|
+
expect(input.value).toBe("Updated");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("uncontrolled pattern", () => {
|
|
87
|
+
it("manages value internally without onValueChange", () => {
|
|
88
|
+
const { container } = render(() => <TextInput value="Initial" />);
|
|
89
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
90
|
+
|
|
91
|
+
expect(input.value).toBe("Initial");
|
|
92
|
+
|
|
93
|
+
fireEvent.input(input, { target: { value: "Changed" } });
|
|
94
|
+
expect(input.value).toBe("Changed");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("disabled state", () => {
|
|
99
|
+
it("renders as div when disabled=true", () => {
|
|
100
|
+
const { container } = render(() => <TextInput disabled value="Disabled text" />);
|
|
101
|
+
const input = container.querySelector("input:not([aria-hidden])");
|
|
102
|
+
const div = container.querySelector("div.sd-text-field");
|
|
103
|
+
|
|
104
|
+
expect(input).toBeFalsy();
|
|
105
|
+
expect(div).toBeTruthy();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("displays value when disabled", () => {
|
|
109
|
+
const { getByText } = render(() => <TextInput disabled value="Disabled text" />);
|
|
110
|
+
expect(getByText("Disabled text")).toBeTruthy();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("applies disabled style", () => {
|
|
114
|
+
const { container } = render(() => <TextInput disabled value="Text" />);
|
|
115
|
+
const div = container.querySelector("div.sd-text-field") as HTMLElement;
|
|
116
|
+
expect(div.classList.contains("bg-base-100")).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("readonly state", () => {
|
|
121
|
+
it("renders as div when readonly=true", () => {
|
|
122
|
+
const { container } = render(() => <TextInput readonly value="Readonly text" />);
|
|
123
|
+
const input = container.querySelector("input:not([aria-hidden])");
|
|
124
|
+
const div = container.querySelector("div.sd-text-field");
|
|
125
|
+
|
|
126
|
+
expect(input).toBeFalsy();
|
|
127
|
+
expect(div).toBeTruthy();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("displays value when readonly", () => {
|
|
131
|
+
const { getByText } = render(() => <TextInput readonly value="Readonly text" />);
|
|
132
|
+
expect(getByText("Readonly text")).toBeTruthy();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe("format option", () => {
|
|
137
|
+
it("displays value with format applied", () => {
|
|
138
|
+
const { container } = render(() => <TextInput format="XXX-XXXX-XXXX" value="01012345678" />);
|
|
139
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
140
|
+
expect(input.value).toBe("010-1234-5678");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("passes raw value to onValueChange when format is applied", () => {
|
|
144
|
+
const handleChange = vi.fn();
|
|
145
|
+
const { container } = render(() => (
|
|
146
|
+
<TextInput format="XXX-XXXX-XXXX" value="" onValueChange={handleChange} />
|
|
147
|
+
));
|
|
148
|
+
const input = container.querySelector("input") as HTMLInputElement;
|
|
149
|
+
|
|
150
|
+
fireEvent.input(input, { target: { value: "010-1234-5678" } });
|
|
151
|
+
|
|
152
|
+
// raw value with format characters ('-') stripped is passed
|
|
153
|
+
expect(handleChange).toHaveBeenCalledWith("01012345678");
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("size option", () => {
|
|
158
|
+
it("applies small padding when size=sm", () => {
|
|
159
|
+
const { container } = render(() => <TextInput size="sm" />);
|
|
160
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
161
|
+
expect(wrapper.classList.contains("py-0.5")).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("applies large padding when size=lg", () => {
|
|
165
|
+
const { container } = render(() => <TextInput size="lg" />);
|
|
166
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
167
|
+
expect(wrapper.classList.contains("py-2")).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("inset style", () => {
|
|
172
|
+
it("removes border and applies inset background when inset=true", () => {
|
|
173
|
+
const { container } = render(() => <TextInput inset />);
|
|
174
|
+
const outer = container.firstChild as HTMLElement;
|
|
175
|
+
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
176
|
+
expect(contentDiv.classList.contains("border-none")).toBe(true);
|
|
177
|
+
expect(contentDiv.classList.contains("bg-primary-50")).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("shows content div and no input when inset + readonly", () => {
|
|
181
|
+
const { container } = render(() => <TextInput inset readonly value="Hello" />);
|
|
182
|
+
const outer = container.firstChild as HTMLElement;
|
|
183
|
+
expect(outer.classList.contains("relative")).toBe(true);
|
|
184
|
+
|
|
185
|
+
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
186
|
+
expect(contentDiv).toBeTruthy();
|
|
187
|
+
expect(contentDiv.textContent).toBe("Hello");
|
|
188
|
+
|
|
189
|
+
const input = outer.querySelector("input:not([aria-hidden])");
|
|
190
|
+
expect(input).toBeFalsy();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("shows hidden content div and input when inset + editable", () => {
|
|
194
|
+
const { container } = render(() => <TextInput inset value="Hello" />);
|
|
195
|
+
const outer = container.firstChild as HTMLElement;
|
|
196
|
+
|
|
197
|
+
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
198
|
+
expect(contentDiv).toBeTruthy();
|
|
199
|
+
expect(contentDiv.style.visibility).toBe("hidden");
|
|
200
|
+
|
|
201
|
+
const input = outer.querySelector("input") as HTMLInputElement;
|
|
202
|
+
expect(input).toBeTruthy();
|
|
203
|
+
expect(input.value).toBe("Hello");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("shows NBSP in content div when inset + empty value", () => {
|
|
207
|
+
const { container } = render(() => <TextInput inset readonly />);
|
|
208
|
+
const outer = container.firstChild as HTMLElement;
|
|
209
|
+
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
210
|
+
expect(contentDiv.textContent).toBe("\u00A0");
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("content div is always in DOM when toggling inset + readonly/editable", () => {
|
|
214
|
+
const [readonly, setReadonly] = createSignal(true);
|
|
215
|
+
const { container } = render(() => <TextInput inset readonly={readonly()} value="Test" />);
|
|
216
|
+
const outer = container.firstChild as HTMLElement;
|
|
217
|
+
|
|
218
|
+
let contentDiv = outer.querySelector("[data-text-field-content]");
|
|
219
|
+
expect(contentDiv).toBeTruthy();
|
|
220
|
+
expect(outer.querySelector("input:not([aria-hidden])")).toBeFalsy();
|
|
221
|
+
|
|
222
|
+
setReadonly(false);
|
|
223
|
+
contentDiv = outer.querySelector("[data-text-field-content]");
|
|
224
|
+
expect(contentDiv).toBeTruthy();
|
|
225
|
+
expect(outer.querySelector("input")).toBeTruthy();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe("class merging", () => {
|
|
230
|
+
it("merges custom class with existing styles", () => {
|
|
231
|
+
// eslint-disable-next-line tailwindcss/no-custom-classname
|
|
232
|
+
const { container } = render(() => <TextInput class="my-custom-class" />);
|
|
233
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
234
|
+
expect(wrapper.classList.contains("my-custom-class")).toBe(true);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe("default style", () => {
|
|
239
|
+
it("applies default border style", () => {
|
|
240
|
+
const { container } = render(() => <TextInput />);
|
|
241
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
242
|
+
expect(wrapper.classList.contains("border")).toBe(true);
|
|
243
|
+
expect(wrapper.classList.contains("border-base-200")).toBe(true);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("changes border color on focus", () => {
|
|
247
|
+
const { container } = render(() => <TextInput />);
|
|
248
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
249
|
+
expect(wrapper.classList.contains("focus-within:border-primary-500")).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("applies dark mode style", () => {
|
|
253
|
+
const { container } = render(() => <TextInput />);
|
|
254
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
255
|
+
expect(wrapper.classList.contains("dark:border-base-700")).toBe(true);
|
|
256
|
+
expect(wrapper.classList.contains("dark:bg-primary-950/30")).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe("validation", () => {
|
|
261
|
+
it("sets error message in hidden input when required and empty", () => {
|
|
262
|
+
const { container } = render(() => <TextInput required value="" />);
|
|
263
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
264
|
+
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("is valid when required and value exists", () => {
|
|
268
|
+
const { container } = render(() => <TextInput required value="hello" />);
|
|
269
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
270
|
+
expect(hiddenInput.validity.valid).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("sets error message when minLength is violated", () => {
|
|
274
|
+
const { container } = render(() => <TextInput minLength={3} value="ab" />);
|
|
275
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
276
|
+
expect(hiddenInput.validationMessage).toBe("Enter at least 3 characters");
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it("sets error message when maxLength is violated", () => {
|
|
280
|
+
const { container } = render(() => <TextInput maxLength={5} value="abcdef" />);
|
|
281
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
282
|
+
expect(hiddenInput.validationMessage).toBe("Enter up to 5 characters");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("sets error message when pattern is violated", () => {
|
|
286
|
+
const { container } = render(() => <TextInput pattern="^[0-9]+$" value="abc" />);
|
|
287
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
288
|
+
expect(hiddenInput.validationMessage).toBe("The input format is invalid");
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("sets error message returned by validate function", () => {
|
|
292
|
+
const { container } = render(() => (
|
|
293
|
+
<TextInput
|
|
294
|
+
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
295
|
+
value="hello"
|
|
296
|
+
/>
|
|
297
|
+
));
|
|
298
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
299
|
+
expect(hiddenInput.validationMessage).toBe("이메일 형식이 아닙니다");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("runs validate function after base validators pass", () => {
|
|
303
|
+
const { container } = render(() => (
|
|
304
|
+
<TextInput
|
|
305
|
+
required
|
|
306
|
+
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
307
|
+
value=""
|
|
308
|
+
/>
|
|
309
|
+
));
|
|
310
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
311
|
+
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
describe("Prefix slot", () => {
|
|
316
|
+
it("renders TextInput.Prefix slot", () => {
|
|
317
|
+
render(() => (
|
|
318
|
+
<TextInput>
|
|
319
|
+
<TextInput.Prefix>
|
|
320
|
+
<span data-testid="prefix">P</span>
|
|
321
|
+
</TextInput.Prefix>
|
|
322
|
+
</TextInput>
|
|
323
|
+
));
|
|
324
|
+
|
|
325
|
+
expect(document.querySelector('[data-testid="prefix"]')).not.toBeNull();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it("applies gap class when Prefix slot is used", () => {
|
|
329
|
+
const { container } = render(() => (
|
|
330
|
+
<TextInput>
|
|
331
|
+
<TextInput.Prefix>
|
|
332
|
+
<span>P</span>
|
|
333
|
+
</TextInput.Prefix>
|
|
334
|
+
</TextInput>
|
|
335
|
+
));
|
|
336
|
+
|
|
337
|
+
const wrapper = container.querySelector("[data-text-field]") as HTMLElement;
|
|
338
|
+
expect(wrapper.className).toContain("gap-");
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { render, fireEvent } from "@solidjs/testing-library";
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
|
+
import { createSignal } from "solid-js";
|
|
4
|
+
import { Textarea } from "../../../../src/components/form-control/field/Textarea";
|
|
5
|
+
|
|
6
|
+
describe("Textarea component", () => {
|
|
7
|
+
describe("basic rendering", () => {
|
|
8
|
+
it("renders textarea element", () => {
|
|
9
|
+
const { container } = render(() => <Textarea />);
|
|
10
|
+
const textarea = container.querySelector("textarea");
|
|
11
|
+
expect(textarea).toBeTruthy();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("applies placeholder to textarea", () => {
|
|
15
|
+
const { container } = render(() => <Textarea placeholder="내용을 입력하세요" />);
|
|
16
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
17
|
+
expect(textarea.placeholder).toBe("내용을 입력하세요");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("applies title to textarea", () => {
|
|
21
|
+
const { container } = render(() => <Textarea title="Textarea title" />);
|
|
22
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
23
|
+
expect(textarea.title).toBe("Textarea title");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("controlled pattern", () => {
|
|
28
|
+
it("displays value prop in textarea", () => {
|
|
29
|
+
const { container } = render(() => <Textarea value="Hello" />);
|
|
30
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
31
|
+
expect(textarea.value).toBe("Hello");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("calls onValueChange on input", () => {
|
|
35
|
+
const handleChange = vi.fn();
|
|
36
|
+
const { container } = render(() => <Textarea value="" onValueChange={handleChange} />);
|
|
37
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
38
|
+
|
|
39
|
+
fireEvent.input(textarea, { target: { value: "Test" } });
|
|
40
|
+
|
|
41
|
+
expect(handleChange).toHaveBeenCalledWith("Test");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("updates textarea value when external state changes", () => {
|
|
45
|
+
const [value, setValue] = createSignal("Initial");
|
|
46
|
+
const { container } = render(() => <Textarea value={value()} onValueChange={setValue} />);
|
|
47
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
48
|
+
|
|
49
|
+
expect(textarea.value).toBe("Initial");
|
|
50
|
+
|
|
51
|
+
setValue("Updated");
|
|
52
|
+
expect(textarea.value).toBe("Updated");
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("uncontrolled pattern", () => {
|
|
57
|
+
it("manages value internally without onValueChange", () => {
|
|
58
|
+
const { container } = render(() => <Textarea value="Initial" />);
|
|
59
|
+
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
60
|
+
|
|
61
|
+
expect(textarea.value).toBe("Initial");
|
|
62
|
+
|
|
63
|
+
fireEvent.input(textarea, { target: { value: "Changed" } });
|
|
64
|
+
expect(textarea.value).toBe("Changed");
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe("disabled state", () => {
|
|
69
|
+
it("does not render textarea when disabled=true", () => {
|
|
70
|
+
const { container } = render(() => <Textarea disabled value="Disabled text" />);
|
|
71
|
+
const textarea = container.querySelector("textarea");
|
|
72
|
+
expect(textarea).toBeFalsy();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("displays value when disabled", () => {
|
|
76
|
+
const { getByText } = render(() => <Textarea disabled value="Disabled text" />);
|
|
77
|
+
expect(getByText("Disabled text")).toBeTruthy();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("applies disabled style", () => {
|
|
81
|
+
const { container } = render(() => <Textarea disabled value="Text" />);
|
|
82
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
83
|
+
expect(wrapper.classList.contains("bg-base-100")).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("readonly state", () => {
|
|
88
|
+
it("does not render textarea when readonly=true", () => {
|
|
89
|
+
const { container } = render(() => <Textarea readonly value="Readonly text" />);
|
|
90
|
+
const textarea = container.querySelector("textarea");
|
|
91
|
+
expect(textarea).toBeFalsy();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("displays value when readonly", () => {
|
|
95
|
+
const { getByText } = render(() => <Textarea readonly value="Readonly text" />);
|
|
96
|
+
expect(getByText("Readonly text")).toBeTruthy();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("size option", () => {
|
|
101
|
+
it("applies small padding when size=sm", () => {
|
|
102
|
+
const { container } = render(() => <Textarea size="sm" />);
|
|
103
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
104
|
+
expect(wrapper.classList.contains("py-0.5")).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("applies large padding when size=lg", () => {
|
|
108
|
+
const { container } = render(() => <Textarea size="lg" />);
|
|
109
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
110
|
+
expect(wrapper.classList.contains("py-2")).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("inset style", () => {
|
|
115
|
+
it("removes border and applies inset background when inset=true", () => {
|
|
116
|
+
const { container } = render(() => <Textarea inset />);
|
|
117
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
118
|
+
expect(wrapper.classList.contains("relative")).toBe(true);
|
|
119
|
+
const content = wrapper.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
120
|
+
expect(content.classList.contains("border-none")).toBe(true);
|
|
121
|
+
expect(content.classList.contains("bg-primary-50")).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("shows content div and no textarea when inset + readonly", () => {
|
|
125
|
+
const { container } = render(() => <Textarea inset readonly value="Hello" />);
|
|
126
|
+
const outer = container.firstChild as HTMLElement;
|
|
127
|
+
expect(outer.classList.contains("relative")).toBe(true);
|
|
128
|
+
|
|
129
|
+
const contentDiv = outer.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
130
|
+
expect(contentDiv).toBeTruthy();
|
|
131
|
+
expect(contentDiv.textContent).toContain("Hello");
|
|
132
|
+
|
|
133
|
+
expect(outer.querySelector("textarea")).toBeFalsy();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("shows hidden content div and textarea when inset + editable", () => {
|
|
137
|
+
const { container } = render(() => <Textarea inset value="Hello" />);
|
|
138
|
+
const outer = container.firstChild as HTMLElement;
|
|
139
|
+
|
|
140
|
+
const contentDiv = outer.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
141
|
+
expect(contentDiv).toBeTruthy();
|
|
142
|
+
expect(contentDiv.style.visibility).toBe("hidden");
|
|
143
|
+
|
|
144
|
+
const textarea = outer.querySelector("textarea") as HTMLTextAreaElement;
|
|
145
|
+
expect(textarea).toBeTruthy();
|
|
146
|
+
expect(textarea.value).toBe("Hello");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("shows NBSP in content div when inset + empty value", () => {
|
|
150
|
+
const { container } = render(() => <Textarea inset readonly />);
|
|
151
|
+
const outer = container.firstChild as HTMLElement;
|
|
152
|
+
const contentDiv = outer.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
153
|
+
expect(contentDiv.textContent).toContain("\u00A0");
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("class merging", () => {
|
|
158
|
+
it("merges custom class with existing styles", () => {
|
|
159
|
+
// eslint-disable-next-line tailwindcss/no-custom-classname
|
|
160
|
+
const { container } = render(() => <Textarea class="my-custom-class" />);
|
|
161
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
162
|
+
expect(wrapper.classList.contains("my-custom-class")).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe("auto height adjustment", () => {
|
|
167
|
+
it("renders hidden div for height measurement", () => {
|
|
168
|
+
const { container } = render(() => <Textarea value="Test" />);
|
|
169
|
+
const wrapper = container.firstChild as HTMLElement;
|
|
170
|
+
const hiddenDiv = wrapper.querySelector("[data-hidden-content]") as HTMLElement;
|
|
171
|
+
expect(hiddenDiv).toBeTruthy();
|
|
172
|
+
expect(hiddenDiv.style.visibility).toBe("hidden");
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe("validation", () => {
|
|
177
|
+
it("sets error message in hidden input when required and empty", () => {
|
|
178
|
+
const { container } = render(() => <Textarea required value="" />);
|
|
179
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
180
|
+
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("is valid when required and value exists", () => {
|
|
184
|
+
const { container } = render(() => <Textarea required value="hello" />);
|
|
185
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
186
|
+
expect(hiddenInput.validity.valid).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("sets error message when minLength is violated", () => {
|
|
190
|
+
const { container } = render(() => <Textarea minLength={3} value="ab" />);
|
|
191
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
192
|
+
expect(hiddenInput.validationMessage).toBe("Enter at least 3 characters");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("sets error message when maxLength is violated", () => {
|
|
196
|
+
const { container } = render(() => <Textarea maxLength={5} value="abcdef" />);
|
|
197
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
198
|
+
expect(hiddenInput.validationMessage).toBe("Enter up to 5 characters");
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("sets error message returned by validate function", () => {
|
|
202
|
+
const { container } = render(() => (
|
|
203
|
+
<Textarea
|
|
204
|
+
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
205
|
+
value="hello"
|
|
206
|
+
/>
|
|
207
|
+
));
|
|
208
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
209
|
+
expect(hiddenInput.validationMessage).toBe("이메일 형식이 아닙니다");
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("runs validate function after base validators pass", () => {
|
|
213
|
+
const { container } = render(() => (
|
|
214
|
+
<Textarea
|
|
215
|
+
required
|
|
216
|
+
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
217
|
+
value=""
|
|
218
|
+
/>
|
|
219
|
+
));
|
|
220
|
+
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
221
|
+
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|