@simplysm/solid 13.0.76 → 13.0.77
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 +9 -10
- package/dist/components/data/kanban/Kanban.d.ts +31 -38
- package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
- package/dist/components/data/kanban/Kanban.js.map +1 -1
- package/dist/components/data/list/List.d.ts +7 -28
- package/dist/components/data/list/List.d.ts.map +1 -1
- package/dist/components/data/list/List.js +3 -2
- package/dist/components/data/list/List.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.d.ts +3 -8
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +305 -418
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- package/dist/components/data/sheet/{types.d.ts → DataSheet.types.d.ts} +9 -3
- package/dist/components/data/sheet/DataSheet.types.d.ts.map +1 -0
- package/dist/components/data/sheet/DataSheet.types.js +1 -0
- package/dist/components/data/sheet/{sheetUtils.d.ts → DataSheet.utils.d.ts} +2 -2
- package/dist/components/data/sheet/DataSheet.utils.d.ts.map +1 -0
- package/dist/components/data/sheet/{sheetUtils.js → DataSheet.utils.js} +3 -3
- package/dist/components/data/sheet/DataSheet.utils.js.map +6 -0
- package/dist/components/data/sheet/DataSheetColumn.d.ts +1 -1
- package/dist/components/data/sheet/DataSheetColumn.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.d.ts +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetExpansion.d.ts +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetExpansion.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetExpansion.js +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetFixedColumns.d.ts +2 -2
- package/dist/components/data/sheet/hooks/useDataSheetFixedColumns.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetHeaderCell.d.ts +27 -0
- package/dist/components/data/sheet/hooks/useDataSheetHeaderCell.d.ts.map +1 -0
- package/dist/components/data/sheet/hooks/useDataSheetHeaderCell.js +173 -0
- package/dist/components/data/sheet/hooks/useDataSheetHeaderCell.js.map +6 -0
- package/dist/components/data/sheet/hooks/useDataSheetReorder.d.ts +1 -2
- package/dist/components/data/sheet/hooks/useDataSheetReorder.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetReorder.js.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetSelection.d.ts +2 -2
- package/dist/components/data/sheet/hooks/useDataSheetSelection.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetSelection.js +2 -2
- package/dist/components/data/sheet/hooks/useDataSheetSelection.js.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetSorting.d.ts +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetSorting.d.ts.map +1 -1
- package/dist/components/data/sheet/hooks/useDataSheetSorting.js +1 -1
- package/dist/components/disclosure/Dialog.d.ts +6 -10
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +11 -14
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/Dropdown.d.ts +8 -12
- package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
- package/dist/components/disclosure/Dropdown.js.map +1 -1
- package/dist/components/disclosure/Tabs.d.ts +3 -5
- package/dist/components/disclosure/Tabs.d.ts.map +1 -1
- package/dist/components/disclosure/Tabs.js.map +1 -1
- package/dist/components/display/Barcode.d.ts +1 -1
- package/dist/components/display/Barcode.d.ts.map +1 -1
- package/dist/components/display/Barcode.js +2 -1
- package/dist/components/display/Barcode.js.map +2 -2
- package/dist/components/display/Barcode.types.d.ts +2 -0
- package/dist/components/display/Barcode.types.d.ts.map +1 -0
- package/dist/components/display/Barcode.types.js +1 -0
- package/dist/components/display/Echarts.d.ts +2 -2
- package/dist/components/display/Echarts.d.ts.map +1 -1
- package/dist/components/display/Echarts.js +7 -8
- package/dist/components/display/Echarts.js.map +2 -2
- package/dist/components/features/address/AddressSearch.d.ts.map +1 -1
- package/dist/components/features/address/AddressSearch.js +4 -1
- package/dist/components/features/address/AddressSearch.js.map +2 -2
- package/dist/components/features/crud-detail/CrudDetail.d.ts +12 -13
- package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
- package/dist/components/features/crud-detail/CrudDetail.js +18 -15
- package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
- package/dist/components/features/crud-detail/{types.d.ts → CrudDetail.types.d.ts} +1 -1
- package/dist/components/features/crud-detail/CrudDetail.types.d.ts.map +1 -0
- package/dist/components/features/crud-detail/CrudDetail.types.js +1 -0
- package/dist/components/features/crud-sheet/CrudSheet.d.ts +3 -13
- package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
- package/dist/components/features/crud-sheet/CrudSheet.js +62 -73
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/crud-sheet/{types.d.ts → CrudSheet.types.d.ts} +10 -10
- package/dist/components/features/crud-sheet/CrudSheet.types.d.ts.map +1 -0
- package/dist/components/features/crud-sheet/CrudSheet.types.js +1 -0
- package/dist/components/features/crud-sheet/CrudSheet.types.js.map +6 -0
- package/dist/components/features/crud-sheet/CrudSheetColumn.d.ts +1 -1
- package/dist/components/features/crud-sheet/CrudSheetColumn.d.ts.map +1 -1
- package/dist/components/features/crud-sheet/CrudSheetTools.d.ts +1 -1
- package/dist/components/features/crud-sheet/CrudSheetTools.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.d.ts +2 -2
- package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.js +3 -3
- package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelect.d.ts +7 -11
- package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelect.js +5 -4
- package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectButton.js.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts +8 -15
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.js +5 -3
- package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
- package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.js +9 -1
- package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
- package/dist/components/feedback/print/Print.d.ts +4 -6
- package/dist/components/feedback/print/Print.d.ts.map +1 -1
- package/dist/components/feedback/print/Print.js +3 -2
- package/dist/components/feedback/print/Print.js.map +2 -2
- package/dist/components/feedback/print/PrintProvider.d.ts.map +1 -1
- package/dist/components/feedback/print/PrintProvider.js +1 -0
- package/dist/components/feedback/print/PrintProvider.js.map +1 -1
- package/dist/components/form-control/Invalid.d.ts +1 -1
- package/dist/components/form-control/Invalid.d.ts.map +1 -1
- package/dist/components/form-control/Invalid.js +27 -26
- package/dist/components/form-control/Invalid.js.map +2 -2
- package/dist/components/form-control/checkbox/Checkbox.d.ts +1 -1
- package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/CheckboxGroup.d.ts +10 -10
- package/dist/components/form-control/checkbox/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/CheckboxGroup.js +2 -2
- package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
- package/dist/components/form-control/checkbox/Radio.d.ts +1 -1
- package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/RadioGroup.d.ts +10 -10
- package/dist/components/form-control/checkbox/RadioGroup.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/RadioGroup.js +2 -2
- package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
- package/dist/components/form-control/checkbox/SelectableBase.d.ts +1 -1
- package/dist/components/form-control/checkbox/SelectableBase.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/SelectableBase.js +3 -3
- package/dist/components/form-control/checkbox/SelectableBase.js.map +2 -2
- package/dist/components/form-control/checkbox/SelectionGroupBase.d.ts +1 -1
- package/dist/components/form-control/checkbox/SelectionGroupBase.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/SelectionGroupBase.js +3 -3
- package/dist/components/form-control/checkbox/SelectionGroupBase.js.map +2 -2
- package/dist/components/form-control/color-picker/ColorPicker.d.ts +2 -2
- package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.js +3 -3
- package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts +3 -3
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +10 -5
- package/dist/components/form-control/combobox/Combobox.js.map +2 -2
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +4 -4
- 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 +176 -312
- package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js +3 -3
- package/dist/components/form-control/field/DatePicker.js.map +2 -2
- package/dist/components/form-control/field/DateTimePicker.d.ts +2 -2
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js +3 -3
- package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
- package/dist/components/form-control/field/FieldShell.d.ts +1 -1
- package/dist/components/form-control/field/FieldShell.d.ts.map +1 -1
- package/dist/components/form-control/field/FieldShell.js +2 -2
- package/dist/components/form-control/field/FieldShell.js.map +2 -2
- package/dist/components/form-control/field/NumberInput.d.ts +7 -28
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +7 -5
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts +7 -23
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +6 -5
- package/dist/components/form-control/field/TextInput.js.map +2 -2
- package/dist/components/form-control/field/Textarea.d.ts +2 -2
- package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
- package/dist/components/form-control/field/Textarea.js +3 -3
- package/dist/components/form-control/field/Textarea.js.map +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js +3 -3
- package/dist/components/form-control/field/TimePicker.js.map +2 -2
- package/dist/components/form-control/select/Select.d.ts +22 -44
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js +8 -6
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/state-preset/StatePreset.js +5 -5
- package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
- package/dist/components/layout/sidebar/Sidebar.d.ts +5 -102
- package/dist/components/layout/sidebar/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/sidebar/Sidebar.js.map +1 -1
- package/dist/components/layout/topbar/Topbar.d.ts +1 -1
- package/dist/components/layout/topbar/Topbar.d.ts.map +1 -1
- package/dist/components/layout/topbar/Topbar.js +3 -3
- package/dist/components/layout/topbar/Topbar.js.map +2 -2
- package/dist/helpers/createAppStructure.d.ts.map +1 -1
- package/dist/helpers/createAppStructure.js.map +1 -1
- package/dist/hooks/createControllableStore.js +5 -5
- package/dist/hooks/createControllableStore.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/providers/ServiceClientProvider.d.ts +2 -2
- package/dist/providers/ServiceClientProvider.d.ts.map +1 -1
- package/dist/providers/ServiceClientProvider.js.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.d.ts +1 -1
- package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.js +98 -86
- package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
- package/package.json +5 -5
- package/src/components/data/kanban/Kanban.tsx +37 -32
- package/src/components/data/list/List.tsx +3 -6
- package/src/components/data/sheet/DataSheet.tsx +224 -334
- package/src/components/data/sheet/{types.ts → DataSheet.types.ts} +8 -2
- package/src/components/data/sheet/{sheetUtils.ts → DataSheet.utils.ts} +3 -3
- package/src/components/data/sheet/DataSheetColumn.tsx +1 -1
- package/src/components/data/sheet/DataSheetConfigDialog.tsx +1 -1
- package/src/components/data/sheet/hooks/useDataSheetExpansion.ts +2 -2
- package/src/components/data/sheet/hooks/useDataSheetFixedColumns.ts +2 -2
- package/src/components/data/sheet/hooks/useDataSheetHeaderCell.tsx +168 -0
- package/src/components/data/sheet/hooks/useDataSheetReorder.ts +1 -2
- package/src/components/data/sheet/hooks/useDataSheetSelection.ts +4 -4
- package/src/components/data/sheet/hooks/useDataSheetSorting.ts +2 -2
- package/src/components/disclosure/Dialog.tsx +21 -27
- package/src/components/disclosure/Dropdown.tsx +1 -6
- package/src/components/disclosure/Tabs.tsx +1 -6
- package/src/components/display/Barcode.tsx +4 -113
- package/src/components/display/Barcode.types.ts +111 -0
- package/src/components/display/Echarts.tsx +10 -11
- package/src/components/features/address/AddressSearch.tsx +21 -3
- package/src/components/features/crud-detail/CrudDetail.tsx +21 -38
- package/src/components/features/crud-sheet/CrudSheet.tsx +77 -93
- package/src/components/features/crud-sheet/{types.ts → CrudSheet.types.ts} +9 -9
- package/src/components/features/crud-sheet/CrudSheetColumn.tsx +1 -1
- package/src/components/features/crud-sheet/CrudSheetTools.tsx +1 -1
- package/src/components/features/data-select-button/DataSelectButton.tsx +8 -8
- package/src/components/features/shared-data/SharedDataSelect.tsx +23 -34
- package/src/components/features/shared-data/SharedDataSelectButton.tsx +1 -4
- package/src/components/features/shared-data/SharedDataSelectList.tsx +6 -10
- package/src/components/feedback/notification/NotificationProvider.tsx +9 -1
- package/src/components/feedback/print/Print.tsx +4 -8
- package/src/components/feedback/print/PrintProvider.tsx +2 -1
- package/src/components/form-control/Invalid.tsx +33 -29
- package/src/components/form-control/checkbox/Checkbox.tsx +1 -1
- package/src/components/form-control/checkbox/CheckboxGroup.tsx +3 -12
- package/src/components/form-control/checkbox/Radio.tsx +1 -1
- package/src/components/form-control/checkbox/RadioGroup.tsx +3 -12
- package/src/components/form-control/checkbox/SelectableBase.tsx +3 -3
- package/src/components/form-control/checkbox/SelectionGroupBase.tsx +3 -3
- package/src/components/form-control/color-picker/ColorPicker.tsx +4 -4
- package/src/components/form-control/combobox/Combobox.tsx +23 -18
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +5 -5
- package/src/components/form-control/editor/EditorToolbar.tsx +82 -202
- package/src/components/form-control/field/DatePicker.tsx +4 -4
- package/src/components/form-control/field/DateTimePicker.tsx +4 -4
- package/src/components/form-control/field/FieldShell.tsx +2 -2
- package/src/components/form-control/field/NumberInput.tsx +8 -11
- package/src/components/form-control/field/TextInput.tsx +7 -11
- package/src/components/form-control/field/Textarea.tsx +4 -4
- package/src/components/form-control/field/TimePicker.tsx +4 -4
- package/src/components/form-control/select/Select.tsx +33 -42
- package/src/components/form-control/state-preset/StatePreset.tsx +5 -5
- package/src/components/layout/sidebar/Sidebar.tsx +1 -7
- package/src/components/layout/topbar/Topbar.tsx +3 -3
- package/src/helpers/createAppStructure.ts +16 -0
- package/src/hooks/createControllableStore.ts +5 -5
- package/src/index.ts +4 -3
- package/src/providers/ServiceClientProvider.tsx +4 -4
- package/src/providers/shared-data/SharedDataProvider.tsx +136 -113
- package/tests/components/data/sheet/DataSheet.spec.tsx +2 -2
- package/tests/components/data/sheet/hooks/useDataSheetFixedColumns.spec.ts +1 -1
- package/tests/components/data/sheet/hooks/useDataSheetSelection.spec.ts +34 -17
- package/tests/components/data/sheet/hooks/useDataSheetSorting.spec.ts +1 -1
- package/tests/components/disclosure/Dialog.spec.tsx +7 -7
- package/tests/components/display/Barcode.spec.tsx +15 -1
- package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +6 -6
- package/tests/components/form-control/Invalid.spec.tsx +5 -5
- package/tests/components/form-control/combobox/Combobox.spec.tsx +24 -1
- package/tests/components/layout/topbar/TopbarActions.spec.tsx +4 -4
- package/tests/components/layout/topbar/{createTopbarActions.spec.tsx → useTopbarActions.spec.tsx} +4 -4
- package/tests/providers/shared-data/SharedDataProvider.spec.tsx +130 -8
- package/dist/components/data/sheet/sheetUtils.d.ts.map +0 -1
- package/dist/components/data/sheet/sheetUtils.js.map +0 -6
- package/dist/components/data/sheet/types.d.ts.map +0 -1
- package/dist/components/data/sheet/types.js +0 -1
- package/dist/components/features/crud-detail/types.d.ts.map +0 -1
- package/dist/components/features/crud-detail/types.js +0 -1
- package/dist/components/features/crud-sheet/types.d.ts.map +0 -1
- package/dist/components/features/crud-sheet/types.js +0 -1
- package/dist/components/feedback/notification/index.d.ts +0 -4
- package/dist/components/feedback/notification/index.d.ts.map +0 -1
- package/dist/components/feedback/notification/index.js +0 -4
- package/dist/components/feedback/notification/index.js.map +0 -6
- package/src/components/feedback/notification/index.ts +0 -3
- /package/dist/components/data/sheet/{types.js.map → DataSheet.types.js.map} +0 -0
- /package/dist/components/{features/crud-detail/types.js.map → display/Barcode.types.js.map} +0 -0
- /package/dist/components/features/{crud-sheet/types.js.map → crud-detail/CrudDetail.types.js.map} +0 -0
- /package/src/components/features/crud-detail/{types.ts → CrudDetail.types.ts} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type Accessor, type JSX, createContext, createMemo, createSignal, onCleanup, useContext } from "solid-js";
|
|
2
|
-
import {
|
|
2
|
+
import { obj, wait as waitU } from "@simplysm/core-common";
|
|
3
3
|
import { SharedDataChangeEvent } from "./SharedDataChangeEvent";
|
|
4
4
|
import { useServiceClient } from "../ServiceClientProvider";
|
|
5
5
|
import { useNotification } from "../../components/feedback/notification/NotificationProvider";
|
|
6
6
|
import { useLogger } from "../../hooks/useLogger";
|
|
7
|
+
import type { ServiceClient } from "@simplysm/service-client";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Shared data definition.
|
|
@@ -92,9 +93,11 @@ export function useSharedData<
|
|
|
92
93
|
if (!context) {
|
|
93
94
|
throw new Error("useSharedData can only be used inside SharedDataProvider");
|
|
94
95
|
}
|
|
95
|
-
return context as
|
|
96
|
+
return context as SharedDataValue<TSharedData>;
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
type EntryState = "idle" | "initializing" | "ready" | "error";
|
|
100
|
+
|
|
98
101
|
/**
|
|
99
102
|
* Shared data Provider.
|
|
100
103
|
*
|
|
@@ -102,7 +105,7 @@ export function useSharedData<
|
|
|
102
105
|
* - Must be used inside ServiceClientProvider and NotificationProvider
|
|
103
106
|
* - Logs fetch failures to logger if LoggerProvider is present
|
|
104
107
|
* - Before configure(): only wait, busy, configure are accessible. Data access throws
|
|
105
|
-
* - After configure(): registers definitions
|
|
108
|
+
* - After configure(): registers definitions and immediately starts fetching data for all entries
|
|
106
109
|
* - Prevents data inversion on concurrent fetch calls via version counter
|
|
107
110
|
* - Displays danger notification to the user on fetch failure
|
|
108
111
|
* - Automatically releases all event listeners on cleanup
|
|
@@ -132,17 +135,14 @@ export function SharedDataProvider(props: { children: JSX.Element }): JSX.Elemen
|
|
|
132
135
|
const [busyCount, setBusyCount] = createSignal(0);
|
|
133
136
|
const busy: Accessor<boolean> = () => busyCount() > 0;
|
|
134
137
|
|
|
135
|
-
const signalMap = new Map<string, ReturnType<typeof createSignal<unknown[]>>>();
|
|
136
|
-
const memoMap = new Map<string, Accessor<Map<string | number, unknown>>>();
|
|
137
|
-
const listenerKeyMap = new Map<string, string>();
|
|
138
|
-
const versionMap = new Map<string, number>();
|
|
139
138
|
const accessors: Record<string, SharedDataAccessor<unknown>> = {};
|
|
140
|
-
let currentDefinitions: Record<string, SharedDataDefinition<unknown>> | undefined;
|
|
141
139
|
|
|
142
|
-
|
|
140
|
+
let disposed = false;
|
|
141
|
+
|
|
142
|
+
function ordering<TItem>(data: TItem[], orderByList: [(item: TItem) => unknown, "asc" | "desc"][]): TItem[] {
|
|
143
143
|
let result = [...data];
|
|
144
144
|
for (const orderBy of [...orderByList].reverse()) {
|
|
145
|
-
const selector = (item:
|
|
145
|
+
const selector = (item: TItem) => orderBy[0](item) as string | number | undefined;
|
|
146
146
|
if (orderBy[1] === "desc") {
|
|
147
147
|
result = result.orderByDesc(selector);
|
|
148
148
|
} else {
|
|
@@ -152,49 +152,137 @@ export function SharedDataProvider(props: { children: JSX.Element }): JSX.Elemen
|
|
|
152
152
|
return result;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
function createSharedDataEntry(
|
|
156
156
|
name: string,
|
|
157
157
|
def: SharedDataDefinition<unknown>,
|
|
158
|
-
|
|
159
|
-
): Promise<void> {
|
|
160
|
-
|
|
161
|
-
const currentVersion = (versionMap.get(name) ?? 0) + 1;
|
|
162
|
-
versionMap.set(name, currentVersion);
|
|
158
|
+
client: ServiceClient,
|
|
159
|
+
): SharedDataAccessor<unknown> & { cleanup: () => void; initialize: () => Promise<void> } {
|
|
160
|
+
const [items, setItems] = createSignal<unknown[]>([]);
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
162
|
+
const itemMap = createMemo(() => {
|
|
163
|
+
const map = new Map<string | number, unknown>();
|
|
164
|
+
for (const item of items()) {
|
|
165
|
+
map.set(def.getKey(item as never), item);
|
|
166
|
+
}
|
|
167
|
+
return map;
|
|
168
|
+
});
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
let state: EntryState = "idle";
|
|
171
|
+
let listenerKey: string | undefined;
|
|
172
|
+
let version = 0;
|
|
171
173
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
async function loadData(changeKeys?: Array<string | number>): Promise<void> {
|
|
175
|
+
// Prevent data inversion on concurrent calls via version counter
|
|
176
|
+
const currentVersion = ++version;
|
|
174
177
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
setBusyCount((c) => c + 1);
|
|
179
|
+
try {
|
|
180
|
+
const resData = await def.fetch(changeKeys);
|
|
181
|
+
|
|
182
|
+
// Ignore stale responses
|
|
183
|
+
if (version !== currentVersion) return;
|
|
184
|
+
|
|
185
|
+
if (!changeKeys) {
|
|
186
|
+
setItems(ordering(resData, def.orderBy));
|
|
187
|
+
} else {
|
|
188
|
+
setItems((prev) => {
|
|
189
|
+
const filtered = prev.filter((item) => !changeKeys.includes(def.getKey(item as never)));
|
|
190
|
+
filtered.push(...resData);
|
|
191
|
+
return ordering(filtered, def.orderBy);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
} catch (err) {
|
|
195
|
+
logger.error(`SharedData '${name}' fetch failed:`, err);
|
|
196
|
+
notification.danger(
|
|
197
|
+
"Shared data load failed",
|
|
198
|
+
err instanceof Error ? err.message : `Error occurred while loading '${name}' data.`,
|
|
199
|
+
);
|
|
200
|
+
throw err;
|
|
201
|
+
} finally {
|
|
202
|
+
setBusyCount((c) => c - 1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function initialize(): Promise<void> {
|
|
207
|
+
if (state !== "idle" && state !== "error") return;
|
|
208
|
+
|
|
209
|
+
// Clean up leaked listener from previous failed attempt
|
|
210
|
+
if (listenerKey != null) {
|
|
211
|
+
void client.removeListener(listenerKey);
|
|
212
|
+
listenerKey = undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
state = "initializing";
|
|
216
|
+
|
|
217
|
+
// Increment busyCount synchronously so wait() sees busy state immediately
|
|
218
|
+
setBusyCount((c) => c + 1);
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const key = await client.addListener(
|
|
222
|
+
SharedDataChangeEvent,
|
|
223
|
+
{ name, filter: def.filter },
|
|
224
|
+
async (changeKeys) => {
|
|
225
|
+
try {
|
|
226
|
+
await loadData(changeKeys);
|
|
227
|
+
} catch {
|
|
228
|
+
// Error already logged and notified in loadData
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (disposed) {
|
|
234
|
+
void client.removeListener(key);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
listenerKey = key;
|
|
239
|
+
|
|
240
|
+
await loadData();
|
|
241
|
+
|
|
242
|
+
state = "ready";
|
|
243
|
+
} catch {
|
|
244
|
+
state = "error";
|
|
245
|
+
} finally {
|
|
246
|
+
setBusyCount((c) => c - 1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function cleanup(): void {
|
|
251
|
+
if (listenerKey != null) {
|
|
252
|
+
void client.removeListener(listenerKey);
|
|
183
253
|
}
|
|
184
|
-
} catch (err) {
|
|
185
|
-
// CR-2: Notify user on fetch failure
|
|
186
|
-
logger.error(`SharedData '${name}' fetch failed:`, err);
|
|
187
|
-
notification.danger(
|
|
188
|
-
"Shared data load failed",
|
|
189
|
-
err instanceof Error ? err.message : `Error occurred while loading '${name}' data.`,
|
|
190
|
-
);
|
|
191
|
-
} finally {
|
|
192
|
-
setBusyCount((c) => c - 1);
|
|
193
254
|
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
items: () => {
|
|
258
|
+
void initialize();
|
|
259
|
+
return items();
|
|
260
|
+
},
|
|
261
|
+
get: (key: string | number | undefined) => {
|
|
262
|
+
void initialize();
|
|
263
|
+
if (key === undefined) return undefined;
|
|
264
|
+
return itemMap().get(key);
|
|
265
|
+
},
|
|
266
|
+
emit: async (changeKeys?: Array<string | number>) => {
|
|
267
|
+
await client.emitEvent(
|
|
268
|
+
SharedDataChangeEvent,
|
|
269
|
+
(info) => info.name === name && obj.equal(info.filter, def.filter),
|
|
270
|
+
changeKeys,
|
|
271
|
+
);
|
|
272
|
+
},
|
|
273
|
+
getKey: def.getKey,
|
|
274
|
+
itemSearchText: def.itemSearchText,
|
|
275
|
+
isItemHidden: def.isItemHidden,
|
|
276
|
+
getParentKey: def.getParentKey,
|
|
277
|
+
cleanup,
|
|
278
|
+
initialize,
|
|
279
|
+
};
|
|
194
280
|
}
|
|
195
281
|
|
|
282
|
+
const entries = new Map<string, ReturnType<typeof createSharedDataEntry>>();
|
|
283
|
+
|
|
196
284
|
async function wait(): Promise<void> {
|
|
197
|
-
await
|
|
285
|
+
await waitU.until(() => busyCount() <= 0);
|
|
198
286
|
}
|
|
199
287
|
|
|
200
288
|
function configure(
|
|
@@ -208,85 +296,20 @@ export function SharedDataProvider(props: { children: JSX.Element }): JSX.Elemen
|
|
|
208
296
|
configured = true;
|
|
209
297
|
|
|
210
298
|
const definitions = fn({});
|
|
211
|
-
currentDefinitions = definitions;
|
|
212
299
|
|
|
213
300
|
for (const [name, def] of Object.entries(definitions)) {
|
|
214
|
-
const [items, setItems] = createSignal<unknown[]>([]);
|
|
215
|
-
signalMap.set(name, [items, setItems]);
|
|
216
|
-
|
|
217
|
-
const itemMap = createMemo(() => {
|
|
218
|
-
const map = new Map<string | number, unknown>();
|
|
219
|
-
for (const item of items()) {
|
|
220
|
-
map.set(def.getKey(item as never), item);
|
|
221
|
-
}
|
|
222
|
-
return map;
|
|
223
|
-
});
|
|
224
|
-
memoMap.set(name, itemMap);
|
|
225
|
-
|
|
226
301
|
const client = serviceClient.get(def.serviceKey ?? "default");
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (initialized) return;
|
|
232
|
-
initialized = true;
|
|
233
|
-
|
|
234
|
-
void client
|
|
235
|
-
.addEventListener(
|
|
236
|
-
SharedDataChangeEvent,
|
|
237
|
-
{ name, filter: def.filter },
|
|
238
|
-
async (changeKeys) => {
|
|
239
|
-
await loadData(name, def, changeKeys);
|
|
240
|
-
},
|
|
241
|
-
)
|
|
242
|
-
.then((key) => {
|
|
243
|
-
if (disposed) {
|
|
244
|
-
void client.removeEventListener(key);
|
|
245
|
-
} else {
|
|
246
|
-
listenerKeyMap.set(name, key);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
void loadData(name, def);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
accessors[name] = {
|
|
254
|
-
items: () => {
|
|
255
|
-
ensureInitialized();
|
|
256
|
-
return items();
|
|
257
|
-
},
|
|
258
|
-
get: (key: string | number | undefined) => {
|
|
259
|
-
ensureInitialized();
|
|
260
|
-
if (key === undefined) return undefined;
|
|
261
|
-
return itemMap().get(key);
|
|
262
|
-
},
|
|
263
|
-
emit: async (changeKeys?: Array<string | number>) => {
|
|
264
|
-
await client.emitToServer(
|
|
265
|
-
SharedDataChangeEvent,
|
|
266
|
-
(info) => info.name === name && objEqual(info.filter, def.filter),
|
|
267
|
-
changeKeys,
|
|
268
|
-
);
|
|
269
|
-
},
|
|
270
|
-
getKey: def.getKey,
|
|
271
|
-
itemSearchText: def.itemSearchText,
|
|
272
|
-
isItemHidden: def.isItemHidden,
|
|
273
|
-
getParentKey: def.getParentKey,
|
|
274
|
-
};
|
|
302
|
+
const entry = createSharedDataEntry(name, def, client);
|
|
303
|
+
entries.set(name, entry);
|
|
304
|
+
accessors[name] = entry;
|
|
305
|
+
void entry.initialize();
|
|
275
306
|
}
|
|
276
307
|
}
|
|
277
308
|
|
|
278
|
-
let disposed = false;
|
|
279
|
-
|
|
280
309
|
onCleanup(() => {
|
|
281
310
|
disposed = true;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const listenerKey = listenerKeyMap.get(name);
|
|
285
|
-
if (listenerKey != null) {
|
|
286
|
-
const def = currentDefinitions[name];
|
|
287
|
-
const client = serviceClient.get(def.serviceKey ?? "default");
|
|
288
|
-
void client.removeEventListener(listenerKey);
|
|
289
|
-
}
|
|
311
|
+
for (const entry of entries.values()) {
|
|
312
|
+
entry.cleanup();
|
|
290
313
|
}
|
|
291
314
|
});
|
|
292
315
|
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
applySorting,
|
|
6
6
|
collectAllExpandable,
|
|
7
7
|
flattenTree,
|
|
8
|
-
} from "../../../../src/components/data/sheet/
|
|
9
|
-
import type { SortingDef } from "../../../../src/components/data/sheet/types";
|
|
8
|
+
} from "../../../../src/components/data/sheet/DataSheet.utils";
|
|
9
|
+
import type { SortingDef } from "../../../../src/components/data/sheet/DataSheet.types";
|
|
10
10
|
import { ConfigContext, ConfigProvider } from "../../../../src/providers/ConfigContext";
|
|
11
11
|
import type { JSX } from "solid-js";
|
|
12
12
|
import { I18nProvider } from "../../../../src/providers/i18n/I18nProvider";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { createRoot } from "solid-js";
|
|
3
3
|
import { useDataSheetFixedColumns } from "../../../../../src/components/data/sheet/hooks/useDataSheetFixedColumns";
|
|
4
|
-
import type { DataSheetColumnDef } from "../../../../../src/components/data/sheet/types";
|
|
4
|
+
import type { DataSheetColumnDef } from "../../../../../src/components/data/sheet/DataSheet.types";
|
|
5
5
|
|
|
6
6
|
interface TestItem {
|
|
7
7
|
id: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { createRoot } from "solid-js";
|
|
3
3
|
import { useDataSheetSelection } from "../../../../../src/components/data/sheet/hooks/useDataSheetSelection";
|
|
4
|
-
import type { FlatItem } from "../../../../../src/components/data/sheet/types";
|
|
4
|
+
import type { FlatItem } from "../../../../../src/components/data/sheet/DataSheet.types";
|
|
5
5
|
|
|
6
6
|
interface TestItem {
|
|
7
7
|
id: string;
|
|
@@ -56,23 +56,23 @@ describe("useDataSheetSelection", () => {
|
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
it("getItemSelectable should return
|
|
59
|
+
it("getItemSelectable should return disabled string when item is not selectable", () => {
|
|
60
60
|
createRoot(() => {
|
|
61
|
-
const
|
|
61
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
62
62
|
const result = useDataSheetSelection(
|
|
63
|
-
{
|
|
63
|
+
{ isItemSelectable },
|
|
64
64
|
() => createTestFlatItems(testItems),
|
|
65
65
|
);
|
|
66
66
|
|
|
67
|
-
expect(result.getItemSelectable(testItems[2])).toBe(
|
|
67
|
+
expect(result.getItemSelectable(testItems[2])).toBe("disabled");
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it("getItemSelectable should return reason string when item is disabled", () => {
|
|
72
72
|
createRoot(() => {
|
|
73
|
-
const
|
|
73
|
+
const isItemSelectable = (item: TestItem) => item.disabledReason != null && item.disabledReason !== "" ? item.disabledReason : true;
|
|
74
74
|
const result = useDataSheetSelection(
|
|
75
|
-
{
|
|
75
|
+
{ isItemSelectable },
|
|
76
76
|
() => createTestFlatItems(testItems),
|
|
77
77
|
);
|
|
78
78
|
|
|
@@ -134,9 +134,9 @@ describe("useDataSheetSelection", () => {
|
|
|
134
134
|
|
|
135
135
|
it("toggleSelect should not select non-selectable items", () => {
|
|
136
136
|
createRoot(() => {
|
|
137
|
-
const
|
|
137
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
138
138
|
const result = useDataSheetSelection(
|
|
139
|
-
{
|
|
139
|
+
{ isItemSelectable },
|
|
140
140
|
() => createTestFlatItems(testItems),
|
|
141
141
|
);
|
|
142
142
|
|
|
@@ -174,9 +174,9 @@ describe("useDataSheetSelection", () => {
|
|
|
174
174
|
|
|
175
175
|
it("toggleSelectAll should select all selectable items", () => {
|
|
176
176
|
createRoot(() => {
|
|
177
|
-
const
|
|
177
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
178
178
|
const result = useDataSheetSelection(
|
|
179
|
-
{
|
|
179
|
+
{ isItemSelectable },
|
|
180
180
|
() => createTestFlatItems(testItems),
|
|
181
181
|
);
|
|
182
182
|
|
|
@@ -189,10 +189,10 @@ describe("useDataSheetSelection", () => {
|
|
|
189
189
|
|
|
190
190
|
it("toggleSelectAll should deselect all items when all are selected", () => {
|
|
191
191
|
createRoot(() => {
|
|
192
|
-
const
|
|
192
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
193
193
|
const selectableItems = testItems.filter((i) => i.selectable !== false);
|
|
194
194
|
const result = useDataSheetSelection(
|
|
195
|
-
{
|
|
195
|
+
{ isItemSelectable, selection: selectableItems },
|
|
196
196
|
() => createTestFlatItems(testItems),
|
|
197
197
|
);
|
|
198
198
|
|
|
@@ -204,9 +204,9 @@ describe("useDataSheetSelection", () => {
|
|
|
204
204
|
|
|
205
205
|
it("toggleSelectAll should only select selectable items", () => {
|
|
206
206
|
createRoot(() => {
|
|
207
|
-
const
|
|
207
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
208
208
|
const result = useDataSheetSelection(
|
|
209
|
-
{
|
|
209
|
+
{ isItemSelectable },
|
|
210
210
|
() => createTestFlatItems(testItems),
|
|
211
211
|
);
|
|
212
212
|
|
|
@@ -284,9 +284,9 @@ describe("useDataSheetSelection", () => {
|
|
|
284
284
|
|
|
285
285
|
it("rangeSelect should only select selectable items in range", () => {
|
|
286
286
|
createRoot(() => {
|
|
287
|
-
const
|
|
287
|
+
const isItemSelectable = (item: TestItem): true | string => item.selectable !== false ? true : "disabled";
|
|
288
288
|
const result = useDataSheetSelection(
|
|
289
|
-
{ selectionMode: "multiple",
|
|
289
|
+
{ selectionMode: "multiple", isItemSelectable },
|
|
290
290
|
() => createTestFlatItems(testItems),
|
|
291
291
|
);
|
|
292
292
|
|
|
@@ -342,4 +342,21 @@ describe("useDataSheetSelection", () => {
|
|
|
342
342
|
expect(result.lastClickAction()).toBe("select");
|
|
343
343
|
});
|
|
344
344
|
});
|
|
345
|
+
|
|
346
|
+
it("treats false return from isItemSelectable as not selectable", () => {
|
|
347
|
+
createRoot((dispose) => {
|
|
348
|
+
const flatItems = () => createTestFlatItems(testItems);
|
|
349
|
+
const sel = useDataSheetSelection<TestItem>(
|
|
350
|
+
{
|
|
351
|
+
selectionMode: "multiple",
|
|
352
|
+
isItemSelectable: (item) => (item.selectable === false ? false : true),
|
|
353
|
+
},
|
|
354
|
+
flatItems,
|
|
355
|
+
);
|
|
356
|
+
expect(sel.getItemSelectable(testItems[2])).toBe(false);
|
|
357
|
+
sel.toggleSelect(testItems[2]);
|
|
358
|
+
expect(sel.selection()).toEqual([]);
|
|
359
|
+
dispose();
|
|
360
|
+
});
|
|
361
|
+
});
|
|
345
362
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { createRoot, createSignal } from "solid-js";
|
|
3
3
|
import { useDataSheetSorting } from "../../../../../src/components/data/sheet/hooks/useDataSheetSorting";
|
|
4
|
-
import type { SortingDef } from "../../../../../src/components/data/sheet/types";
|
|
4
|
+
import type { SortingDef } from "../../../../../src/components/data/sheet/DataSheet.types";
|
|
5
5
|
|
|
6
6
|
interface TestItem {
|
|
7
7
|
id: number;
|
|
@@ -207,11 +207,11 @@ describe("Dialog", () => {
|
|
|
207
207
|
expect(handleOpenChange).not.toHaveBeenCalled();
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
it("does not close when
|
|
210
|
+
it("does not close when beforeClose returns false", async () => {
|
|
211
211
|
const handleOpenChange = vi.fn();
|
|
212
212
|
render(() => (
|
|
213
213
|
<ConfigProvider clientName="test"><I18nProvider>
|
|
214
|
-
<Dialog open={true} onOpenChange={handleOpenChange}
|
|
214
|
+
<Dialog open={true} onOpenChange={handleOpenChange} beforeClose={() => false}>
|
|
215
215
|
<Dialog.Header>테스트</Dialog.Header>
|
|
216
216
|
<div>내용</div>
|
|
217
217
|
</Dialog>
|
|
@@ -264,7 +264,7 @@ describe("Dialog", () => {
|
|
|
264
264
|
it("does not set aria-modal in float mode", async () => {
|
|
265
265
|
render(() => (
|
|
266
266
|
<ConfigProvider clientName="test"><I18nProvider>
|
|
267
|
-
<Dialog open={true} float>
|
|
267
|
+
<Dialog open={true} mode="float">
|
|
268
268
|
<Dialog.Header>플로팅 다이얼로그</Dialog.Header>
|
|
269
269
|
<div>내용</div>
|
|
270
270
|
</Dialog>
|
|
@@ -280,10 +280,10 @@ describe("Dialog", () => {
|
|
|
280
280
|
});
|
|
281
281
|
|
|
282
282
|
describe("float mode", () => {
|
|
283
|
-
it("has no backdrop when float
|
|
283
|
+
it("has no backdrop when mode='float'", async () => {
|
|
284
284
|
render(() => (
|
|
285
285
|
<ConfigProvider clientName="test"><I18nProvider>
|
|
286
|
-
<Dialog open={true} float>
|
|
286
|
+
<Dialog open={true} mode="float">
|
|
287
287
|
<Dialog.Header>테스트</Dialog.Header>
|
|
288
288
|
<div data-testid="content">내용</div>
|
|
289
289
|
</Dialog>
|
|
@@ -298,10 +298,10 @@ describe("Dialog", () => {
|
|
|
298
298
|
});
|
|
299
299
|
|
|
300
300
|
describe("fill mode", () => {
|
|
301
|
-
it("applies fill style to dialog when fill
|
|
301
|
+
it("applies fill style to dialog when mode='fill'", async () => {
|
|
302
302
|
render(() => (
|
|
303
303
|
<ConfigProvider clientName="test"><I18nProvider>
|
|
304
|
-
<Dialog open={true} fill>
|
|
304
|
+
<Dialog open={true} mode="fill">
|
|
305
305
|
<Dialog.Header>테스트</Dialog.Header>
|
|
306
306
|
<div>내용</div>
|
|
307
307
|
</Dialog>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { render } from "@solidjs/testing-library";
|
|
2
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { Barcode } from "../../../src/components/display/Barcode";
|
|
5
5
|
|
|
@@ -18,6 +18,20 @@ describe("Barcode", () => {
|
|
|
18
18
|
});
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
it("logs warning on render failure", () => {
|
|
22
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
23
|
+
|
|
24
|
+
// "code128" requires specific format; passing invalid chars triggers bwip-js error
|
|
25
|
+
render(() => <Barcode type={"invalid-type" as any} value="test" />);
|
|
26
|
+
|
|
27
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
28
|
+
"Barcode render failed:",
|
|
29
|
+
expect.any(Error),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
warnSpy.mockRestore();
|
|
33
|
+
});
|
|
34
|
+
|
|
21
35
|
describe("reactivity", () => {
|
|
22
36
|
it("updates SVG when value changes", () => {
|
|
23
37
|
const [value, setValue] = createSignal("first");
|
|
@@ -25,7 +25,7 @@ function DialogWrapper(props: { children: JSX.Element }) {
|
|
|
25
25
|
return (
|
|
26
26
|
<ConfigContext.Provider value={{ clientName: "test" }}>
|
|
27
27
|
<NotificationProvider>
|
|
28
|
-
<Dialog open fill>
|
|
28
|
+
<Dialog open mode="fill">
|
|
29
29
|
<Dialog.Header>Test Dialog</Dialog.Header>
|
|
30
30
|
{props.children}
|
|
31
31
|
</Dialog>
|
|
@@ -174,7 +174,7 @@ describe("CrudSheet inline edit", () => {
|
|
|
174
174
|
<CrudSheet<TestItem, Record<string, never>>
|
|
175
175
|
search={searchFn}
|
|
176
176
|
getItemKey={(item) => item.id}
|
|
177
|
-
|
|
177
|
+
isItemDeleted={(item) => item.isDeleted}
|
|
178
178
|
inlineEdit={{
|
|
179
179
|
submit: () => Promise.resolve(),
|
|
180
180
|
newItem: () => ({ name: "", isDeleted: false }),
|
|
@@ -196,7 +196,7 @@ describe("CrudSheet inline edit", () => {
|
|
|
196
196
|
});
|
|
197
197
|
});
|
|
198
198
|
|
|
199
|
-
describe("CrudSheet
|
|
199
|
+
describe("CrudSheet isItemDeletable", () => {
|
|
200
200
|
beforeEach(() => {
|
|
201
201
|
localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
|
|
202
202
|
});
|
|
@@ -205,7 +205,7 @@ describe("CrudSheet itemDeletable", () => {
|
|
|
205
205
|
localStorage.removeItem("test.i18n-locale");
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
it("inline delete button is disabled for items where
|
|
208
|
+
it("inline delete button is disabled for items where isItemDeletable=false", async () => {
|
|
209
209
|
const searchFn = () =>
|
|
210
210
|
Promise.resolve({
|
|
211
211
|
items: [
|
|
@@ -221,8 +221,8 @@ describe("CrudSheet itemDeletable", () => {
|
|
|
221
221
|
<CrudSheet<TestItem, Record<string, never>>
|
|
222
222
|
search={searchFn}
|
|
223
223
|
getItemKey={(item) => item.id}
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
isItemDeletable={(item) => item.id !== 1}
|
|
225
|
+
isItemDeleted={(item) => item.isDeleted}
|
|
226
226
|
inlineEdit={{
|
|
227
227
|
submit: () => Promise.resolve(),
|
|
228
228
|
newItem: () => ({ name: "", isDeleted: false }),
|
|
@@ -90,10 +90,10 @@ describe("Invalid component", () => {
|
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
describe("
|
|
94
|
-
it("has no visual indication initially in
|
|
93
|
+
describe("lazyValidation", () => {
|
|
94
|
+
it("has no visual indication initially in lazyValidation", () => {
|
|
95
95
|
const { container } = render(() => (
|
|
96
|
-
<Invalid variant="border" message="error"
|
|
96
|
+
<Invalid variant="border" message="error" lazyValidation>
|
|
97
97
|
<div data-testid="target" class="border">
|
|
98
98
|
Content
|
|
99
99
|
</div>
|
|
@@ -103,9 +103,9 @@ describe("Invalid component", () => {
|
|
|
103
103
|
expect(target.classList.contains("border-danger-500")).toBe(false);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
it("setCustomValidity is always set in
|
|
106
|
+
it("setCustomValidity is always set in lazyValidation", () => {
|
|
107
107
|
const { container } = render(() => (
|
|
108
|
-
<Invalid variant="border" message="error"
|
|
108
|
+
<Invalid variant="border" message="error" lazyValidation>
|
|
109
109
|
<div>Content</div>
|
|
110
110
|
</Invalid>
|
|
111
111
|
));
|
|
@@ -132,7 +132,7 @@ describe("Combobox component", () => {
|
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
describe("allowsCustomValue", () => {
|
|
135
|
-
it("allows entering custom value with Enter when allowsCustomValue
|
|
135
|
+
it("allows entering custom value with Enter when allowsCustomValue and parseCustomValue are provided", () => {
|
|
136
136
|
const handleChange = vi.fn();
|
|
137
137
|
const loadItems = vi.fn(() => Promise.resolve([]));
|
|
138
138
|
|
|
@@ -142,6 +142,7 @@ describe("Combobox component", () => {
|
|
|
142
142
|
loadItems={loadItems}
|
|
143
143
|
onValueChange={handleChange}
|
|
144
144
|
allowsCustomValue
|
|
145
|
+
parseCustomValue={(text) => text}
|
|
145
146
|
renderValue={(v) => <>{v}</>}
|
|
146
147
|
/>
|
|
147
148
|
</I18nProvider></ConfigProvider>
|
|
@@ -176,6 +177,28 @@ describe("Combobox component", () => {
|
|
|
176
177
|
|
|
177
178
|
expect(handleChange).toHaveBeenCalledWith({ name: "테스트", custom: true });
|
|
178
179
|
});
|
|
180
|
+
|
|
181
|
+
it("sets undefined when allowsCustomValue is true without parseCustomValue", async () => {
|
|
182
|
+
const onValueChange = vi.fn();
|
|
183
|
+
const { container, getByRole } = render(() => (
|
|
184
|
+
<ConfigProvider clientName="test"><I18nProvider>
|
|
185
|
+
<Combobox
|
|
186
|
+
loadItems={() => []}
|
|
187
|
+
renderValue={(v: string) => <>{v}</>}
|
|
188
|
+
allowsCustomValue
|
|
189
|
+
onValueChange={onValueChange}
|
|
190
|
+
/>
|
|
191
|
+
</I18nProvider></ConfigProvider>
|
|
192
|
+
));
|
|
193
|
+
|
|
194
|
+
const input = container.querySelector("input")!;
|
|
195
|
+
fireEvent.input(input, { target: { value: "custom text" } });
|
|
196
|
+
fireEvent.keyDown(getByRole("combobox"), { key: "Enter" });
|
|
197
|
+
|
|
198
|
+
await waitFor(() => {
|
|
199
|
+
expect(onValueChange).toHaveBeenCalledWith(undefined);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
179
202
|
});
|
|
180
203
|
|
|
181
204
|
describe("validation", () => {
|