@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,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crud activation registry
|
|
3
|
+
*
|
|
4
|
+
* Tracks mounted CrudDetail/CrudSheet instances and determines which one
|
|
5
|
+
* should respond to keyboard shortcuts (Ctrl+S, Ctrl+Alt+L).
|
|
6
|
+
*
|
|
7
|
+
* Priority rules:
|
|
8
|
+
* 1. If a Dialog is open, only cruds inside the topmost Dialog are candidates.
|
|
9
|
+
* 2. Among candidates, the most recently activated (interacted) crud wins.
|
|
10
|
+
* 3. On mount, cruds are auto-activated (last mounted = active).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { getTopmostDialog } from "../disclosure/dialogZIndex";
|
|
14
|
+
|
|
15
|
+
interface CrudEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
formEl: HTMLFormElement;
|
|
18
|
+
lastActivatedAt: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const entries: CrudEntry[] = [];
|
|
22
|
+
let _counter = 0;
|
|
23
|
+
|
|
24
|
+
export function registerCrud(id: string, formEl: HTMLFormElement): void {
|
|
25
|
+
const existing = entries.find((e) => e.id === id);
|
|
26
|
+
if (existing) return;
|
|
27
|
+
entries.push({ id, formEl, lastActivatedAt: ++_counter });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function unregisterCrud(id: string): void {
|
|
31
|
+
const idx = entries.findIndex((e) => e.id === id);
|
|
32
|
+
if (idx >= 0) entries.splice(idx, 1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function activateCrud(id: string): void {
|
|
36
|
+
const entry = entries.find((e) => e.id === id);
|
|
37
|
+
if (entry) entry.lastActivatedAt = ++_counter;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isActiveCrud(id: string): boolean {
|
|
41
|
+
const entry = entries.find((e) => e.id === id);
|
|
42
|
+
if (!entry) return false;
|
|
43
|
+
|
|
44
|
+
const topDialog = getTopmostDialog();
|
|
45
|
+
|
|
46
|
+
const candidates = topDialog
|
|
47
|
+
? entries.filter((e) => topDialog.contains(e.formEl))
|
|
48
|
+
: entries;
|
|
49
|
+
|
|
50
|
+
if (candidates.length === 0) return false;
|
|
51
|
+
|
|
52
|
+
let best = candidates[0];
|
|
53
|
+
for (let i = 1; i < candidates.length; i++) {
|
|
54
|
+
if (candidates[i].lastActivatedAt > best.lastActivatedAt) {
|
|
55
|
+
best = candidates[i];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return best.id === id;
|
|
60
|
+
}
|
|
@@ -15,6 +15,7 @@ import { IconSearch, IconX } from "@tabler/icons-solidjs";
|
|
|
15
15
|
import { Icon } from "../../display/Icon";
|
|
16
16
|
import { Invalid } from "../../form-control/Invalid";
|
|
17
17
|
import { useDialog, type DialogShowOptions } from "../../disclosure/DialogContext";
|
|
18
|
+
import { useI18nOptional } from "../../../providers/i18n/I18nContext";
|
|
18
19
|
import { createControllableSignal } from "../../../hooks/createControllableSignal";
|
|
19
20
|
import { type ComponentSize, textMuted } from "../../../styles/tokens.styles";
|
|
20
21
|
import {
|
|
@@ -24,46 +25,46 @@ import {
|
|
|
24
25
|
triggerSizeClasses,
|
|
25
26
|
} from "../../form-control/DropdownTrigger.styles";
|
|
26
27
|
|
|
27
|
-
/**
|
|
28
|
+
/** Result interface returned from modal */
|
|
28
29
|
export interface DataSelectModalResult<TKey> {
|
|
29
30
|
selectedKeys: TKey[];
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
/** DataSelectButton Props */
|
|
33
34
|
export interface DataSelectButtonProps<TItem, TKey = string | number> {
|
|
34
|
-
/**
|
|
35
|
+
/** Currently selected key(s) (single or multiple) */
|
|
35
36
|
value?: TKey | TKey[];
|
|
36
|
-
/**
|
|
37
|
+
/** Value change callback */
|
|
37
38
|
onValueChange?: (value: TKey | TKey[] | undefined) => void;
|
|
38
39
|
|
|
39
|
-
/**
|
|
40
|
+
/** Function to load items by key */
|
|
40
41
|
load: (keys: TKey[]) => TItem[] | Promise<TItem[]>;
|
|
41
|
-
/**
|
|
42
|
+
/** Selection modal component factory */
|
|
42
43
|
modal: () => JSX.Element;
|
|
43
|
-
/**
|
|
44
|
+
/** Item rendering function */
|
|
44
45
|
renderItem: (item: TItem) => JSX.Element;
|
|
45
46
|
|
|
46
|
-
/**
|
|
47
|
+
/** Multiple selection mode */
|
|
47
48
|
multiple?: boolean;
|
|
48
|
-
/**
|
|
49
|
+
/** Required input */
|
|
49
50
|
required?: boolean;
|
|
50
|
-
/**
|
|
51
|
+
/** Disabled */
|
|
51
52
|
disabled?: boolean;
|
|
52
|
-
/**
|
|
53
|
+
/** Trigger size */
|
|
53
54
|
size?: ComponentSize;
|
|
54
|
-
/**
|
|
55
|
+
/** Borderless style */
|
|
55
56
|
inset?: boolean;
|
|
56
57
|
|
|
57
|
-
/**
|
|
58
|
+
/** Custom validation function */
|
|
58
59
|
validate?: (value: unknown) => string | undefined;
|
|
59
|
-
/** touchMode:
|
|
60
|
+
/** touchMode: show error only after focus is lost */
|
|
60
61
|
touchMode?: boolean;
|
|
61
62
|
|
|
62
|
-
/**
|
|
63
|
+
/** Dialog options */
|
|
63
64
|
dialogOptions?: DialogShowOptions;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
//
|
|
67
|
+
// Styles
|
|
67
68
|
const containerClass = clsx("inline-flex items-center", "group");
|
|
68
69
|
const selectedValueClass = clsx("flex-1", "whitespace-nowrap", "overflow-hidden", "text-ellipsis");
|
|
69
70
|
const actionButtonClass = clsx(
|
|
@@ -111,27 +112,28 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
111
112
|
"dialogOptions",
|
|
112
113
|
]);
|
|
113
114
|
|
|
115
|
+
const i18n = useI18nOptional();
|
|
114
116
|
const dialog = useDialog();
|
|
115
117
|
|
|
116
|
-
// value
|
|
118
|
+
// Always normalize value to array
|
|
117
119
|
const normalizeKeys = (value: TKey | TKey[] | undefined): TKey[] => {
|
|
118
120
|
if (value === undefined || value === null) return [];
|
|
119
121
|
if (Array.isArray(value)) return value;
|
|
120
122
|
return [value];
|
|
121
123
|
};
|
|
122
124
|
|
|
123
|
-
//
|
|
125
|
+
// Controlled/uncontrolled pattern
|
|
124
126
|
type ValueType = TKey | TKey[] | undefined;
|
|
125
127
|
const [getValue, setValue] = createControllableSignal<ValueType>({
|
|
126
128
|
value: () => local.value,
|
|
127
129
|
onChange: () => local.onValueChange as ((v: ValueType) => void) | undefined,
|
|
128
130
|
} as Parameters<typeof createControllableSignal<ValueType>>[0]);
|
|
129
131
|
|
|
130
|
-
//
|
|
131
|
-
// eslint-disable-next-line solid/reactivity --
|
|
132
|
+
// Track keys for loading
|
|
133
|
+
// eslint-disable-next-line solid/reactivity -- initial value read once at mount time
|
|
132
134
|
const [loadKeys, setLoadKeys] = createSignal<TKey[]>(normalizeKeys(local.value));
|
|
133
135
|
|
|
134
|
-
//
|
|
136
|
+
// Update loadKeys when value changes
|
|
135
137
|
createEffect(
|
|
136
138
|
on(
|
|
137
139
|
() => getValue(),
|
|
@@ -141,33 +143,33 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
141
143
|
),
|
|
142
144
|
);
|
|
143
145
|
|
|
144
|
-
//
|
|
145
|
-
// eslint-disable-next-line solid/reactivity -- createResource
|
|
146
|
+
// Call load via createResource
|
|
147
|
+
// eslint-disable-next-line solid/reactivity -- createResource fetcher is called when source changes
|
|
146
148
|
const [selectedItems] = createResource(loadKeys, async (keys) => {
|
|
147
149
|
if (keys.length === 0) return [];
|
|
148
150
|
return Promise.resolve(local.load(keys));
|
|
149
151
|
});
|
|
150
152
|
|
|
151
|
-
//
|
|
153
|
+
// Check if has value
|
|
152
154
|
const hasValue = createMemo(() => {
|
|
153
155
|
const keys = normalizeKeys(getValue());
|
|
154
156
|
return keys.length > 0;
|
|
155
157
|
});
|
|
156
158
|
|
|
157
|
-
//
|
|
159
|
+
// Check if clearable
|
|
158
160
|
const clearable = createMemo(() => !local.required && hasValue() && !local.disabled);
|
|
159
161
|
|
|
160
|
-
//
|
|
162
|
+
// Validation
|
|
161
163
|
const errorMsg = createMemo(() => {
|
|
162
164
|
const v = getValue();
|
|
163
165
|
if (local.required) {
|
|
164
166
|
const keys = normalizeKeys(v);
|
|
165
|
-
if (keys.length === 0) return "
|
|
167
|
+
if (keys.length === 0) return "Required field";
|
|
166
168
|
}
|
|
167
169
|
return local.validate?.(v);
|
|
168
170
|
});
|
|
169
171
|
|
|
170
|
-
//
|
|
172
|
+
// Open modal
|
|
171
173
|
const handleOpenModal = async () => {
|
|
172
174
|
if (local.disabled) return;
|
|
173
175
|
|
|
@@ -186,7 +188,7 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
186
188
|
}
|
|
187
189
|
};
|
|
188
190
|
|
|
189
|
-
//
|
|
191
|
+
// Clear selection
|
|
190
192
|
const handleClear = (e: MouseEvent) => {
|
|
191
193
|
e.stopPropagation();
|
|
192
194
|
if (local.multiple) {
|
|
@@ -196,7 +198,7 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
196
198
|
}
|
|
197
199
|
};
|
|
198
200
|
|
|
199
|
-
//
|
|
201
|
+
// Render selected value display
|
|
200
202
|
const renderSelectedDisplay = (): JSX.Element => {
|
|
201
203
|
const items = selectedItems();
|
|
202
204
|
if (!items || items.length === 0) {
|
|
@@ -218,7 +220,7 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
218
220
|
);
|
|
219
221
|
};
|
|
220
222
|
|
|
221
|
-
//
|
|
223
|
+
// Calculate trigger class
|
|
222
224
|
const triggerClassName = () =>
|
|
223
225
|
getTriggerContainerClass({
|
|
224
226
|
size: local.size,
|
|
@@ -254,7 +256,7 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
254
256
|
class={twMerge(actionButtonClass, "text-base-400 hover:text-danger-500")}
|
|
255
257
|
onClick={handleClear}
|
|
256
258
|
tabIndex={-1}
|
|
257
|
-
aria-label="
|
|
259
|
+
aria-label={i18n?.t("dataSelectButton.deselect") ?? "Deselect"}
|
|
258
260
|
>
|
|
259
261
|
<Icon icon={IconX} size="0.875em" />
|
|
260
262
|
</button>
|
|
@@ -266,7 +268,7 @@ export function DataSelectButton<TItem, TKey = string | number>(
|
|
|
266
268
|
class={twMerge(actionButtonClass, "text-base-400 hover:text-primary-500")}
|
|
267
269
|
onClick={() => void handleOpenModal()}
|
|
268
270
|
tabIndex={-1}
|
|
269
|
-
aria-label="
|
|
271
|
+
aria-label={i18n?.t("dataSelectButton.search") ?? "Search"}
|
|
270
272
|
>
|
|
271
273
|
<Icon icon={IconSearch} size="0.875em" />
|
|
272
274
|
</button>
|
|
@@ -10,17 +10,17 @@ import {
|
|
|
10
10
|
splitProps,
|
|
11
11
|
} from "solid-js";
|
|
12
12
|
import clsx from "clsx";
|
|
13
|
-
import { twMerge } from "tailwind-merge";
|
|
14
13
|
import { DataSheet } from "../../data/sheet/DataSheet";
|
|
15
14
|
import { Checkbox } from "../../form-control/checkbox/Checkbox";
|
|
16
15
|
import { borderDefault } from "../../../styles/tokens.styles";
|
|
17
16
|
import type { AppPerm } from "../../../helpers/createAppStructure";
|
|
17
|
+
import { useI18nOptional } from "../../../providers/i18n/I18nContext";
|
|
18
18
|
|
|
19
19
|
const titleCellClass = clsx("flex items-stretch", "px-2");
|
|
20
20
|
const indentGuideWrapperClass = clsx("mr-1 flex w-3", "justify-center");
|
|
21
21
|
const indentGuideLineClass = clsx("w-0 self-stretch", "border-r", borderDefault);
|
|
22
22
|
|
|
23
|
-
// ---
|
|
23
|
+
// --- Types ---
|
|
24
24
|
|
|
25
25
|
export interface PermissionTableProps<TModule = string> {
|
|
26
26
|
items?: AppPerm<TModule>[];
|
|
@@ -32,9 +32,9 @@ export interface PermissionTableProps<TModule = string> {
|
|
|
32
32
|
style?: JSX.CSSProperties;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// ---
|
|
35
|
+
// --- Utilities (also used in tests) ---
|
|
36
36
|
|
|
37
|
-
/**
|
|
37
|
+
/** Collect all unique perm types from the tree */
|
|
38
38
|
export function collectAllPerms<TModule>(items: AppPerm<TModule>[]): string[] {
|
|
39
39
|
const set = new Set<string>();
|
|
40
40
|
const walk = (list: AppPerm<TModule>[]) => {
|
|
@@ -49,7 +49,7 @@ export function collectAllPerms<TModule>(items: AppPerm<TModule>[]): string[] {
|
|
|
49
49
|
return [...set];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/** modules
|
|
52
|
+
/** Filter by modules: keep only items that have intersection with active modules */
|
|
53
53
|
export function filterByModules<TModule>(
|
|
54
54
|
items: AppPerm<TModule>[],
|
|
55
55
|
modules: TModule[] | undefined,
|
|
@@ -72,7 +72,7 @@ export function filterByModules<TModule>(
|
|
|
72
72
|
return result;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/**
|
|
75
|
+
/** Handle cascading when checkbox changes */
|
|
76
76
|
export function changePermCheck<TModule>(
|
|
77
77
|
value: Record<string, boolean>,
|
|
78
78
|
item: AppPerm<TModule>,
|
|
@@ -112,9 +112,9 @@ export function changePermCheck<TModule>(
|
|
|
112
112
|
return result;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// ---
|
|
115
|
+
// --- Internal Helpers ---
|
|
116
116
|
|
|
117
|
-
/**
|
|
117
|
+
/** Check if item is visible by module filter (preserve object reference) */
|
|
118
118
|
function isItemVisible<TModule>(item: AppPerm<TModule>, modules: TModule[] | undefined): boolean {
|
|
119
119
|
if (!modules || modules.length === 0) return true;
|
|
120
120
|
if (item.modules && !item.modules.some((m) => modules.includes(m))) return false;
|
|
@@ -124,7 +124,7 @@ function isItemVisible<TModule>(item: AppPerm<TModule>, modules: TModule[] | und
|
|
|
124
124
|
return true;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
/**
|
|
127
|
+
/** Collect unique perm types from visible items only */
|
|
128
128
|
function collectVisiblePerms<TModule>(
|
|
129
129
|
items: AppPerm<TModule>[],
|
|
130
130
|
modules: TModule[] | undefined,
|
|
@@ -145,7 +145,7 @@ function collectVisiblePerms<TModule>(
|
|
|
145
145
|
return [...set];
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
/**
|
|
148
|
+
/** Get check state of group node: true if any child is checked */
|
|
149
149
|
function isGroupPermChecked<TModule>(
|
|
150
150
|
item: AppPerm<TModule>,
|
|
151
151
|
perm: string,
|
|
@@ -160,7 +160,7 @@ function isGroupPermChecked<TModule>(
|
|
|
160
160
|
return false;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
/**
|
|
163
|
+
/** Check if specific perm exists in subtree */
|
|
164
164
|
function hasPermInTree<TModule>(item: AppPerm<TModule>, perm: string): boolean {
|
|
165
165
|
if (item.perms?.includes(perm)) return true;
|
|
166
166
|
if (item.children) {
|
|
@@ -169,7 +169,7 @@ function hasPermInTree<TModule>(item: AppPerm<TModule>, perm: string): boolean {
|
|
|
169
169
|
return false;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
/**
|
|
172
|
+
/** Check if perm should be disabled (base perm is off) */
|
|
173
173
|
function isPermDisabled<TModule>(
|
|
174
174
|
item: AppPerm<TModule>,
|
|
175
175
|
perm: string,
|
|
@@ -181,7 +181,7 @@ function isPermDisabled<TModule>(
|
|
|
181
181
|
return !(value[item.href + "/" + basePerm] ?? false);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/** Collect all expandable items (preserve object reference) */
|
|
185
185
|
function collectExpandable<TModule>(
|
|
186
186
|
items: AppPerm<TModule>[],
|
|
187
187
|
getChildren: (item: AppPerm<TModule>) => AppPerm<TModule>[] | undefined,
|
|
@@ -202,7 +202,7 @@ function collectExpandable<TModule>(
|
|
|
202
202
|
return result;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
// ---
|
|
205
|
+
// --- Component ---
|
|
206
206
|
|
|
207
207
|
export const PermissionTable: Component<PermissionTableProps> = (props) => {
|
|
208
208
|
const [local] = splitProps(props, [
|
|
@@ -215,14 +215,16 @@ export const PermissionTable: Component<PermissionTableProps> = (props) => {
|
|
|
215
215
|
"style",
|
|
216
216
|
]);
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
const i18n = useI18nOptional();
|
|
219
|
+
|
|
220
|
+
// Visible top-level items (preserve object reference)
|
|
219
221
|
const visibleItems = createMemo(() => {
|
|
220
222
|
const items = local.items ?? [];
|
|
221
223
|
if (!local.modules || local.modules.length === 0) return items;
|
|
222
224
|
return items.filter((item) => isItemVisible(item, local.modules));
|
|
223
225
|
});
|
|
224
226
|
|
|
225
|
-
// Sheet
|
|
227
|
+
// Sheet's getChildren — apply module filter, preserve object reference
|
|
226
228
|
const getChildren = (item: AppPerm): AppPerm[] | undefined => {
|
|
227
229
|
if (!item.children || item.children.length === 0) return undefined;
|
|
228
230
|
const modules = local.modules;
|
|
@@ -231,17 +233,17 @@ export const PermissionTable: Component<PermissionTableProps> = (props) => {
|
|
|
231
233
|
return filtered.length > 0 ? filtered : undefined;
|
|
232
234
|
};
|
|
233
235
|
|
|
234
|
-
//
|
|
236
|
+
// All unique perm types from visible items
|
|
235
237
|
const allPerms = createMemo(() => collectVisiblePerms(local.items ?? [], local.modules));
|
|
236
238
|
|
|
237
239
|
const currentValue = createMemo(() => local.value ?? {});
|
|
238
240
|
|
|
239
|
-
//
|
|
241
|
+
// Expanded state — all expanded by default
|
|
240
242
|
const getAllExpandable = () => collectExpandable(visibleItems(), getChildren);
|
|
241
243
|
|
|
242
244
|
const [expandedItems, setExpandedItems] = createSignal<AppPerm[]>(getAllExpandable());
|
|
243
245
|
|
|
244
|
-
//
|
|
246
|
+
// Re-expand all when tree structure changes (e.g., module filter changed)
|
|
245
247
|
createEffect(
|
|
246
248
|
on(
|
|
247
249
|
visibleItems,
|
|
@@ -258,51 +260,55 @@ export const PermissionTable: Component<PermissionTableProps> = (props) => {
|
|
|
258
260
|
};
|
|
259
261
|
|
|
260
262
|
return (
|
|
261
|
-
<
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
263
|
+
<DataSheet
|
|
264
|
+
data-permission-table
|
|
265
|
+
items={visibleItems()}
|
|
266
|
+
getChildren={getChildren}
|
|
267
|
+
expandedItems={expandedItems()}
|
|
268
|
+
onExpandedItemsChange={setExpandedItems}
|
|
269
|
+
hideConfigBar
|
|
270
|
+
>
|
|
271
|
+
<DataSheet.Column
|
|
272
|
+
key="title"
|
|
273
|
+
header={i18n?.t("permissionTable.permissionItem") ?? "Permission Item"}
|
|
274
|
+
sortable={false}
|
|
275
|
+
resizable={false}
|
|
268
276
|
>
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
<
|
|
274
|
-
|
|
275
|
-
{
|
|
276
|
-
<div class={
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
{
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
<
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
</DataSheet>
|
|
306
|
-
</div>
|
|
277
|
+
{(ctx) => {
|
|
278
|
+
const item = ctx.item as AppPerm;
|
|
279
|
+
return (
|
|
280
|
+
<div class={titleCellClass}>
|
|
281
|
+
<For each={Array.from({ length: ctx.depth })}>
|
|
282
|
+
{() => (
|
|
283
|
+
<div class={indentGuideWrapperClass}>
|
|
284
|
+
<div class={indentGuideLineClass} />
|
|
285
|
+
</div>
|
|
286
|
+
)}
|
|
287
|
+
</For>
|
|
288
|
+
<span class="py-1">{item.title}</span>
|
|
289
|
+
</div>
|
|
290
|
+
);
|
|
291
|
+
}}
|
|
292
|
+
</DataSheet.Column>
|
|
293
|
+
<For each={allPerms()}>
|
|
294
|
+
{(perm) => (
|
|
295
|
+
<DataSheet.Column key={`perm-${perm}`} header={perm} sortable={false} resizable={false}>
|
|
296
|
+
{(ctx) => {
|
|
297
|
+
const item = ctx.item as AppPerm;
|
|
298
|
+
return (
|
|
299
|
+
<Show when={hasPermInTree(item, perm)}>
|
|
300
|
+
<Checkbox
|
|
301
|
+
value={isGroupPermChecked(item, perm, currentValue())}
|
|
302
|
+
onValueChange={(checked) => handlePermChange(item, perm, checked)}
|
|
303
|
+
disabled={local.disabled || isPermDisabled(item, perm, currentValue())}
|
|
304
|
+
inset
|
|
305
|
+
/>
|
|
306
|
+
</Show>
|
|
307
|
+
);
|
|
308
|
+
}}
|
|
309
|
+
</DataSheet.Column>
|
|
310
|
+
)}
|
|
311
|
+
</For>
|
|
312
|
+
</DataSheet>
|
|
307
313
|
);
|
|
308
314
|
};
|
|
@@ -4,72 +4,74 @@ import { type SharedDataAccessor } from "../../../providers/shared-data/SharedDa
|
|
|
4
4
|
import { Select, type SelectProps } from "../../form-control/select/Select";
|
|
5
5
|
import { Icon } from "../../display/Icon";
|
|
6
6
|
import { useDialog } from "../../disclosure/DialogContext";
|
|
7
|
+
import { useI18nOptional } from "../../../providers/i18n/I18nContext";
|
|
7
8
|
import { type ComponentSize } from "../../../styles/tokens.styles";
|
|
8
9
|
|
|
9
10
|
/** SharedDataSelect Props */
|
|
10
11
|
export interface SharedDataSelectProps<TItem> {
|
|
11
|
-
/**
|
|
12
|
+
/** Shared data accessor */
|
|
12
13
|
data: SharedDataAccessor<TItem>;
|
|
13
14
|
|
|
14
|
-
/**
|
|
15
|
+
/** Currently selected value */
|
|
15
16
|
value?: unknown;
|
|
16
|
-
/**
|
|
17
|
+
/** Value change callback */
|
|
17
18
|
onValueChange?: (value: unknown) => void;
|
|
18
|
-
/**
|
|
19
|
+
/** Multiple selection mode */
|
|
19
20
|
multiple?: boolean;
|
|
20
|
-
/**
|
|
21
|
+
/** Required input */
|
|
21
22
|
required?: boolean;
|
|
22
|
-
/**
|
|
23
|
+
/** Disabled */
|
|
23
24
|
disabled?: boolean;
|
|
24
|
-
/**
|
|
25
|
+
/** Trigger size */
|
|
25
26
|
size?: ComponentSize;
|
|
26
|
-
/**
|
|
27
|
+
/** Borderless style */
|
|
27
28
|
inset?: boolean;
|
|
28
29
|
|
|
29
|
-
/**
|
|
30
|
+
/** Item filter function */
|
|
30
31
|
filterFn?: (item: TItem, index: number) => boolean;
|
|
31
|
-
/**
|
|
32
|
+
/** Selection modal component factory */
|
|
32
33
|
modal?: () => JSX.Element;
|
|
33
|
-
/**
|
|
34
|
+
/** Edit modal component factory */
|
|
34
35
|
editModal?: () => JSX.Element;
|
|
35
36
|
|
|
36
|
-
/**
|
|
37
|
+
/** Item rendering function */
|
|
37
38
|
children: (item: TItem, index: number, depth: number) => JSX.Element;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export function SharedDataSelect<TItem>(props: SharedDataSelectProps<TItem>): JSX.Element {
|
|
41
42
|
const [local, rest] = splitProps(props, ["data", "filterFn", "modal", "editModal", "children"]);
|
|
42
43
|
|
|
44
|
+
const i18n = useI18nOptional();
|
|
43
45
|
const dialog = useDialog();
|
|
44
46
|
|
|
45
|
-
// filterFn
|
|
47
|
+
// Items with filterFn applied
|
|
46
48
|
const items = createMemo(() => {
|
|
47
49
|
const allItems = local.data.items();
|
|
48
50
|
if (!local.filterFn) return allItems;
|
|
49
51
|
return allItems.filter(local.filterFn);
|
|
50
52
|
});
|
|
51
53
|
|
|
52
|
-
// modal
|
|
54
|
+
// Open modal
|
|
53
55
|
const handleOpenModal = async () => {
|
|
54
56
|
if (!local.modal) return;
|
|
55
57
|
await dialog.show(local.modal, {});
|
|
56
58
|
};
|
|
57
59
|
|
|
58
|
-
//
|
|
60
|
+
// Open edit modal
|
|
59
61
|
const handleOpenEditModal = async () => {
|
|
60
62
|
if (!local.editModal) return;
|
|
61
63
|
await dialog.show(local.editModal, {});
|
|
62
64
|
};
|
|
63
65
|
|
|
64
|
-
// Select
|
|
65
|
-
// getter
|
|
66
|
+
// Use mergeProps + as for Select's discriminated union (multiple: true | false?) and TItem → unknown conversion
|
|
67
|
+
// Wrap with getter to satisfy SolidJS reactivity lint rules
|
|
66
68
|
const selectProps = mergeProps(rest, {
|
|
67
69
|
get items() {
|
|
68
70
|
return items();
|
|
69
71
|
},
|
|
70
72
|
get getChildren() {
|
|
71
73
|
if (!local.data.getParentKey) return undefined;
|
|
72
|
-
// eslint-disable-next-line solid/reactivity --
|
|
74
|
+
// eslint-disable-next-line solid/reactivity -- return function is called within Select's internal JSX tracked scope
|
|
73
75
|
return (item: TItem) => {
|
|
74
76
|
const key = local.data.getKey(item);
|
|
75
77
|
return items().filter((child) => local.data.getParentKey!(child) === key);
|
|
@@ -87,13 +89,13 @@ export function SharedDataSelect<TItem>(props: SharedDataSelectProps<TItem>): JS
|
|
|
87
89
|
<Select {...selectProps}>
|
|
88
90
|
<Select.ItemTemplate>{local.children}</Select.ItemTemplate>
|
|
89
91
|
{local.modal && (
|
|
90
|
-
<Select.Action onClick={() => void handleOpenModal()} aria-label="
|
|
91
|
-
<Icon icon={IconSearch}
|
|
92
|
+
<Select.Action onClick={() => void handleOpenModal()} aria-label={i18n?.t("sharedDataSelect.search") ?? "Search"}>
|
|
93
|
+
<Icon icon={IconSearch} />
|
|
92
94
|
</Select.Action>
|
|
93
95
|
)}
|
|
94
96
|
{local.editModal && (
|
|
95
|
-
<Select.Action onClick={() => void handleOpenEditModal()} aria-label="
|
|
96
|
-
<Icon icon={IconEdit}
|
|
97
|
+
<Select.Action onClick={() => void handleOpenEditModal()} aria-label={i18n?.t("sharedDataSelect.edit") ?? "Edit"}>
|
|
98
|
+
<Icon icon={IconEdit} />
|
|
97
99
|
</Select.Action>
|
|
98
100
|
)}
|
|
99
101
|
</Select>
|
|
@@ -8,27 +8,27 @@ import { type ComponentSize } from "../../../styles/tokens.styles";
|
|
|
8
8
|
|
|
9
9
|
/** SharedDataSelectButton Props */
|
|
10
10
|
export interface SharedDataSelectButtonProps<TItem> {
|
|
11
|
-
/**
|
|
11
|
+
/** Shared data accessor */
|
|
12
12
|
data: SharedDataAccessor<TItem>;
|
|
13
13
|
|
|
14
|
-
/**
|
|
14
|
+
/** Currently selected key(s) (single or multiple) */
|
|
15
15
|
value?: DataSelectButtonProps<TItem>["value"];
|
|
16
|
-
/**
|
|
16
|
+
/** Value change callback */
|
|
17
17
|
onValueChange?: DataSelectButtonProps<TItem>["onValueChange"];
|
|
18
|
-
/**
|
|
18
|
+
/** Multiple selection mode */
|
|
19
19
|
multiple?: boolean;
|
|
20
|
-
/**
|
|
20
|
+
/** Required input */
|
|
21
21
|
required?: boolean;
|
|
22
|
-
/**
|
|
22
|
+
/** Disabled */
|
|
23
23
|
disabled?: boolean;
|
|
24
|
-
/**
|
|
24
|
+
/** Trigger size */
|
|
25
25
|
size?: ComponentSize;
|
|
26
|
-
/**
|
|
26
|
+
/** Borderless style */
|
|
27
27
|
inset?: boolean;
|
|
28
28
|
|
|
29
|
-
/**
|
|
29
|
+
/** Selection modal component factory */
|
|
30
30
|
modal: () => JSX.Element;
|
|
31
|
-
/**
|
|
31
|
+
/** Item rendering function */
|
|
32
32
|
children: (item: TItem) => JSX.Element;
|
|
33
33
|
}
|
|
34
34
|
|