@simplysm/solid 13.0.71 → 13.0.74
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 +209 -202
- package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
- package/dist/components/data/calendar/Calendar.js +3 -11
- package/dist/components/data/calendar/Calendar.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +13 -16
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.js +27 -9
- package/dist/components/data/sheet/DataSheetConfigDialog.js.map +2 -2
- package/dist/components/disclosure/Dialog.d.ts +1 -1
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +5 -5
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/dialogZIndex.d.ts +1 -1
- package/dist/components/features/crud-detail/CrudDetail.js +23 -23
- package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
- package/dist/components/features/crud-sheet/CrudSheet.js +49 -49
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/crud-sheet/types.d.ts +4 -4
- package/dist/components/features/crud-sheet/types.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.d.ts +25 -7
- package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.js +27 -12
- package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
- package/dist/components/features/permission-table/PermissionTable.js +4 -4
- package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelect.d.ts +22 -10
- package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelect.js +113 -29
- package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +3 -3
- 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.js +5 -4
- package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBanner.js +3 -3
- package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBell.js +12 -5
- package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
- package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.js +3 -1
- package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
- package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
- package/dist/components/form-control/ThemeToggle.js +9 -6
- package/dist/components/form-control/ThemeToggle.js.map +2 -2
- package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/Checkbox.js +3 -1
- package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
- package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
- package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
- package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/Radio.js +3 -1
- package/dist/components/form-control/checkbox/Radio.js.map +2 -2
- package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
- package/dist/components/form-control/checkbox/RadioGroup.js.map +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 -1
- package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +9 -5
- package/dist/components/form-control/combobox/Combobox.js.map +2 -2
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -9
- package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
- package/dist/components/form-control/editor/EditorToolbar.js +3 -3
- package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js +9 -3
- package/dist/components/form-control/field/DatePicker.js.map +2 -2
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js +9 -3
- package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +9 -3
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +10 -4
- package/dist/components/form-control/field/TextInput.js.map +2 -2
- package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
- package/dist/components/form-control/field/Textarea.js +9 -3
- package/dist/components/form-control/field/Textarea.js.map +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js +9 -3
- package/dist/components/form-control/field/TimePicker.js.map +2 -2
- package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
- package/dist/components/form-control/numpad/Numpad.js +5 -1
- package/dist/components/form-control/numpad/Numpad.js.map +2 -2
- package/dist/components/form-control/select/Select.js +7 -7
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.js +42 -20
- package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
- package/dist/components/layout/sidebar/SidebarContainer.js +3 -3
- package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
- package/dist/components/layout/sidebar/SidebarMenu.d.ts.map +1 -1
- package/dist/components/layout/sidebar/SidebarMenu.js +5 -2
- package/dist/components/layout/sidebar/SidebarMenu.js.map +2 -2
- package/dist/components/layout/topbar/Topbar.js +3 -4
- package/dist/components/layout/topbar/Topbar.js.map +2 -2
- package/dist/components/layout/topbar/TopbarMenu.js +3 -3
- package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
- package/dist/hooks/createSelectionGroup.d.ts +2 -2
- package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
- package/dist/hooks/createSelectionGroup.js +5 -2
- package/dist/hooks/createSelectionGroup.js.map +2 -2
- package/dist/providers/i18n/I18nContext.d.ts +0 -4
- package/dist/providers/i18n/I18nContext.d.ts.map +1 -1
- package/dist/providers/i18n/I18nContext.js +1 -5
- package/dist/providers/i18n/I18nContext.js.map +2 -2
- package/dist/providers/i18n/locales/en.d.ts +38 -0
- package/dist/providers/i18n/locales/en.d.ts.map +1 -1
- package/dist/providers/i18n/locales/en.js +39 -1
- package/dist/providers/i18n/locales/en.js.map +1 -1
- package/dist/providers/i18n/locales/ko.d.ts +38 -0
- package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
- package/dist/providers/i18n/locales/ko.js +39 -1
- package/dist/providers/i18n/locales/ko.js.map +1 -1
- package/package.json +6 -6
- package/src/components/data/calendar/Calendar.tsx +3 -4
- package/src/components/data/sheet/DataSheet.styles.ts +1 -1
- package/src/components/data/sheet/DataSheet.tsx +14 -15
- package/src/components/data/sheet/DataSheetConfigDialog.tsx +12 -10
- package/src/components/data/sheet/types.ts +1 -1
- package/src/components/disclosure/Dialog.tsx +10 -10
- package/src/components/disclosure/dialogZIndex.ts +1 -1
- package/src/components/features/crud-detail/CrudDetail.tsx +25 -25
- package/src/components/features/crud-sheet/CrudSheet.tsx +53 -53
- package/src/components/features/crud-sheet/types.ts +4 -4
- package/src/components/features/data-select-button/DataSelectButton.tsx +51 -21
- package/src/components/features/permission-table/PermissionTable.tsx +3 -3
- package/src/components/features/shared-data/SharedDataSelect.tsx +172 -33
- package/src/components/features/shared-data/SharedDataSelectButton.tsx +3 -2
- package/src/components/features/shared-data/SharedDataSelectList.tsx +4 -4
- package/src/components/feedback/notification/NotificationBanner.tsx +3 -3
- package/src/components/feedback/notification/NotificationBell.tsx +6 -4
- package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
- package/src/components/form-control/ThemeToggle.tsx +10 -6
- package/src/components/form-control/checkbox/Checkbox.tsx +4 -1
- package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/form-control/checkbox/Radio.tsx +4 -1
- package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
- package/src/components/form-control/color-picker/ColorPicker.tsx +4 -1
- package/src/components/form-control/combobox/Combobox.tsx +6 -3
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +8 -8
- package/src/components/form-control/editor/EditorToolbar.tsx +23 -23
- package/src/components/form-control/field/DatePicker.tsx +6 -3
- package/src/components/form-control/field/DateTimePicker.tsx +6 -3
- package/src/components/form-control/field/NumberInput.tsx +6 -3
- package/src/components/form-control/field/TextInput.tsx +7 -4
- package/src/components/form-control/field/Textarea.tsx +6 -3
- package/src/components/form-control/field/TimePicker.tsx +6 -3
- package/src/components/form-control/numpad/Numpad.tsx +3 -1
- package/src/components/form-control/select/Select.tsx +7 -7
- package/src/components/form-control/state-preset/StatePreset.tsx +14 -12
- package/src/components/layout/sidebar/SidebarContainer.tsx +3 -3
- package/src/components/layout/sidebar/SidebarMenu.tsx +3 -1
- package/src/components/layout/topbar/Topbar.tsx +3 -3
- package/src/components/layout/topbar/TopbarMenu.tsx +3 -3
- package/src/hooks/createSelectionGroup.tsx +8 -4
- package/src/providers/i18n/I18nContext.tsx +0 -7
- package/src/providers/i18n/locales/en.ts +38 -0
- package/src/providers/i18n/locales/ko.ts +38 -0
- package/tailwind.config.ts +2 -2
- package/tests/components/data/kanban/Kanban.selection.spec.tsx +34 -24
- package/tests/components/disclosure/Dialog.spec.tsx +28 -28
- package/tests/components/disclosure/DialogProvider.spec.tsx +51 -25
- package/tests/components/features/address/AddressSearch.spec.tsx +12 -4
- package/tests/components/features/crud-detail/CrudDetail.spec.tsx +1 -0
- package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +30 -6
- package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +77 -56
- package/tests/components/features/permission-table/PermissionTable.spec.tsx +12 -8
- package/tests/components/features/shared-data/SharedDataSelect.spec.tsx +172 -0
- package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +14 -2
- package/tests/components/feedback/notification/LiveRegion.spec.tsx +20 -9
- package/tests/components/feedback/notification/NotificationBanner.spec.tsx +64 -46
- package/tests/components/feedback/notification/NotificationBell.spec.tsx +70 -51
- package/tests/components/feedback/notification/NotificationContext.spec.tsx +105 -78
- package/tests/components/form-control/checkbox/Checkbox.spec.tsx +25 -20
- package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +53 -30
- package/tests/components/form-control/checkbox/Radio.spec.tsx +25 -20
- package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +53 -30
- package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +24 -15
- package/tests/components/form-control/combobox/Combobox.spec.tsx +92 -59
- package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +2 -2
- package/tests/components/form-control/field/DatePicker.spec.tsx +50 -44
- package/tests/components/form-control/field/DateTimePicker.spec.tsx +51 -45
- package/tests/components/form-control/field/NumberInput.spec.tsx +53 -47
- package/tests/components/form-control/field/TextInput.spec.tsx +50 -44
- package/tests/components/form-control/field/Textarea.spec.tsx +35 -29
- package/tests/components/form-control/field/TimePicker.spec.tsx +43 -37
- package/tests/components/form-control/numpad/Numpad.spec.tsx +175 -25
- package/tests/components/form-control/select/Select.spec.tsx +5 -0
- package/tests/components/form-control/select/SelectItem.spec.tsx +1 -0
- package/tests/components/layout/sidebar/Sidebar.spec.tsx +79 -35
- package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +1 -0
- package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +28 -17
- package/tests/components/layout/topbar/TopbarActions.spec.tsx +41 -23
- package/tests/components/layout/topbar/createTopbarActions.spec.tsx +1 -0
- package/tests/hooks/usePrint.spec.tsx +1 -1
- package/tests/hooks/useRouterLink.spec.tsx +2 -0
- package/tests/hooks/useSyncConfig.spec.tsx +1 -0
- package/tests/providers/ErrorLoggerProvider.spec.tsx +1 -0
- package/tests/providers/PwaUpdateProvider.spec.tsx +16 -6
- package/tests/providers/ServiceClientContext.spec.tsx +40 -25
- package/tests/providers/i18n/I18nContext.spec.tsx +3 -4
- package/tests/providers/shared-data/SharedDataProvider.spec.tsx +2 -0
- package/dist/hooks/usePrint.d.ts +0 -3
- package/dist/hooks/usePrint.d.ts.map +0 -1
- package/dist/hooks/usePrint.js +0 -5
- package/dist/hooks/usePrint.js.map +0 -6
- package/src/hooks/usePrint.ts +0 -2
|
@@ -8,6 +8,7 @@ import { useSyncConfig } from "../../../hooks/useSyncConfig";
|
|
|
8
8
|
import { useNotification } from "../../feedback/notification/NotificationContext";
|
|
9
9
|
import { Icon } from "../../display/Icon";
|
|
10
10
|
import { textPlaceholder } from "../../../styles/tokens.styles";
|
|
11
|
+
import { useI18n } from "../../../providers/i18n/I18nContext";
|
|
11
12
|
import type { ComponentSize } from "../../../styles/tokens.styles";
|
|
12
13
|
import { iconButtonBase } from "../../../styles/patterns.styles";
|
|
13
14
|
|
|
@@ -116,6 +117,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
116
117
|
]);
|
|
117
118
|
|
|
118
119
|
const notification = useNotification();
|
|
120
|
+
const i18n = useI18n();
|
|
119
121
|
|
|
120
122
|
// presetKey is an identifier set only once at mount, evaluate immediately to capture
|
|
121
123
|
/* eslint-disable solid/reactivity */
|
|
@@ -147,7 +149,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
if (presets().some((p) => p.name === name)) {
|
|
150
|
-
notification.warning("
|
|
152
|
+
notification.warning(i18n.t("statePreset.duplicateName"), i18n.t("statePreset.duplicateMessage"));
|
|
151
153
|
return;
|
|
152
154
|
}
|
|
153
155
|
|
|
@@ -156,7 +158,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
156
158
|
state: objClone(local.value),
|
|
157
159
|
};
|
|
158
160
|
setPresets([...presets(), newPreset]);
|
|
159
|
-
notification.info("
|
|
161
|
+
notification.info(i18n.t("statePreset.saved"), i18n.t("statePreset.savedMessage", { name }));
|
|
160
162
|
setAdding(false);
|
|
161
163
|
setInputValue("");
|
|
162
164
|
}
|
|
@@ -177,11 +179,11 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
177
179
|
setPresets(updated);
|
|
178
180
|
|
|
179
181
|
const notiId = notification.info(
|
|
180
|
-
"
|
|
181
|
-
|
|
182
|
+
i18n.t("statePreset.overwritten"),
|
|
183
|
+
i18n.t("statePreset.overwrittenMessage", { name: presetName }),
|
|
182
184
|
{
|
|
183
185
|
action: {
|
|
184
|
-
label: "
|
|
186
|
+
label: i18n.t("statePreset.undo"),
|
|
185
187
|
onClick: () => {
|
|
186
188
|
setPresets(snapshot);
|
|
187
189
|
notification.remove(notiId);
|
|
@@ -198,9 +200,9 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
198
200
|
const updated = snapshot.filter((_, i) => i !== index);
|
|
199
201
|
setPresets(updated);
|
|
200
202
|
|
|
201
|
-
const notiId = notification.info("
|
|
203
|
+
const notiId = notification.info(i18n.t("statePreset.deleted"), i18n.t("statePreset.deletedMessage", { name: presetName }), {
|
|
202
204
|
action: {
|
|
203
|
-
label: "
|
|
205
|
+
label: i18n.t("statePreset.undo"),
|
|
204
206
|
onClick: () => {
|
|
205
207
|
setPresets(snapshot);
|
|
206
208
|
notification.remove(notiId);
|
|
@@ -242,7 +244,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
242
244
|
type="button"
|
|
243
245
|
class={resolvedStarBtnClass()}
|
|
244
246
|
onClick={handleStartAdd}
|
|
245
|
-
title="
|
|
247
|
+
title={i18n.t("statePreset.addPreset")}
|
|
246
248
|
>
|
|
247
249
|
<Icon icon={IconStar} size={iconSize} />
|
|
248
250
|
</button>
|
|
@@ -255,7 +257,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
255
257
|
type="button"
|
|
256
258
|
class={chipNameBtnClass}
|
|
257
259
|
onClick={() => handleRestore(preset)}
|
|
258
|
-
title={
|
|
260
|
+
title={preset.name}
|
|
259
261
|
>
|
|
260
262
|
{preset.name}
|
|
261
263
|
</button>
|
|
@@ -263,7 +265,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
263
265
|
type="button"
|
|
264
266
|
class={resolvedIconBtnClass()}
|
|
265
267
|
onClick={() => handleOverwrite(index())}
|
|
266
|
-
title="
|
|
268
|
+
title={i18n.t("statePreset.overwrite")}
|
|
267
269
|
>
|
|
268
270
|
<Icon icon={IconDeviceFloppy} size={iconSize} />
|
|
269
271
|
</button>
|
|
@@ -271,7 +273,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
271
273
|
type="button"
|
|
272
274
|
class={resolvedIconBtnClass()}
|
|
273
275
|
onClick={() => handleDelete(index())}
|
|
274
|
-
title="
|
|
276
|
+
title={i18n.t("statePreset.deletePreset")}
|
|
275
277
|
>
|
|
276
278
|
<Icon icon={IconX} size={iconSize} />
|
|
277
279
|
</button>
|
|
@@ -288,7 +290,7 @@ function StatePresetInner<TValue>(props: StatePresetProps<TValue>): JSX.Element
|
|
|
288
290
|
}}
|
|
289
291
|
type="text"
|
|
290
292
|
class={resolvedInputClass()}
|
|
291
|
-
placeholder="
|
|
293
|
+
placeholder={i18n.t("statePreset.namePlaceholder")}
|
|
292
294
|
autocomplete="one-time-code"
|
|
293
295
|
value={inputValue()}
|
|
294
296
|
onInput={(e) => setInputValue(e.currentTarget.value)}
|
|
@@ -12,7 +12,7 @@ import clsx from "clsx";
|
|
|
12
12
|
import { twMerge } from "tailwind-merge";
|
|
13
13
|
import { SidebarContext, SM_MEDIA_QUERY } from "./SidebarContext";
|
|
14
14
|
import { mergeStyles } from "../../../helpers/mergeStyles";
|
|
15
|
-
import {
|
|
15
|
+
import { useI18n } from "../../../providers/i18n/I18nContext";
|
|
16
16
|
|
|
17
17
|
const backdropClass = clsx(
|
|
18
18
|
"absolute",
|
|
@@ -62,7 +62,7 @@ export interface SidebarContainerProps extends JSX.HTMLAttributes<HTMLDivElement
|
|
|
62
62
|
export const SidebarContainer: ParentComponent<SidebarContainerProps> = (props) => {
|
|
63
63
|
const [local, rest] = splitProps(props, ["children", "class", "style"]);
|
|
64
64
|
|
|
65
|
-
const i18n =
|
|
65
|
+
const i18n = useI18n();
|
|
66
66
|
const [toggle, setToggle] = createSignal(false);
|
|
67
67
|
|
|
68
68
|
// Detect Tailwind sm: breakpoint
|
|
@@ -113,7 +113,7 @@ export const SidebarContainer: ParentComponent<SidebarContainerProps> = (props)
|
|
|
113
113
|
onClick={handleBackdropClick}
|
|
114
114
|
onKeyDown={(e) => e.key === "Escape" && handleBackdropClick()}
|
|
115
115
|
role="button"
|
|
116
|
-
aria-label={i18n
|
|
116
|
+
aria-label={i18n.t("sidebar.closeSidebar")}
|
|
117
117
|
tabIndex={0}
|
|
118
118
|
/>
|
|
119
119
|
</Show>
|
|
@@ -19,6 +19,7 @@ import type { AppMenu } from "../../../helpers/createAppStructure";
|
|
|
19
19
|
import { Icon } from "../../display/Icon";
|
|
20
20
|
import { List } from "../../data/list/List";
|
|
21
21
|
import { ListItem } from "../../data/list/ListItem";
|
|
22
|
+
import { useI18n } from "../../../providers/i18n/I18nContext";
|
|
22
23
|
|
|
23
24
|
const headerClass = clsx(
|
|
24
25
|
"px-4",
|
|
@@ -72,6 +73,7 @@ const MenuContext = createContext<MenuContextValue>();
|
|
|
72
73
|
*/
|
|
73
74
|
export const SidebarMenu: Component<SidebarMenuProps> = (props) => {
|
|
74
75
|
const [local, rest] = splitProps(props, ["menus", "class"]);
|
|
76
|
+
const i18n = useI18n();
|
|
75
77
|
|
|
76
78
|
const location = useLocation();
|
|
77
79
|
|
|
@@ -107,7 +109,7 @@ export const SidebarMenu: Component<SidebarMenuProps> = (props) => {
|
|
|
107
109
|
return (
|
|
108
110
|
<MenuContext.Provider value={{ initialOpenItems }}>
|
|
109
111
|
<div {...rest} data-sidebar-menu class={getClassName()}>
|
|
110
|
-
<div class={headerClass}>
|
|
112
|
+
<div class={headerClass}>{i18n.t("sidebarMenu.menu")}</div>
|
|
111
113
|
<List inset>
|
|
112
114
|
<For each={local.menus}>{(menu) => <MenuItem menu={menu} size="lg" />}</For>
|
|
113
115
|
</List>
|
|
@@ -5,7 +5,7 @@ import { Icon } from "../../display/Icon";
|
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
6
|
import { Button } from "../../form-control/Button";
|
|
7
7
|
import { useSidebarContextOptional } from "../sidebar/SidebarContext";
|
|
8
|
-
import {
|
|
8
|
+
import { useI18n } from "../../../providers/i18n/I18nContext";
|
|
9
9
|
import { TopbarActions } from "./TopbarActions";
|
|
10
10
|
import { TopbarContainer } from "./TopbarContainer";
|
|
11
11
|
import { TopbarMenu } from "./TopbarMenu";
|
|
@@ -71,7 +71,7 @@ const TopbarBase: ParentComponent<TopbarProps> = (props) => {
|
|
|
71
71
|
|
|
72
72
|
// Optional use of SidebarContext (toggle button not shown if Context doesn't exist)
|
|
73
73
|
const sidebarContext = useSidebarContextOptional();
|
|
74
|
-
const i18n =
|
|
74
|
+
const i18n = useI18n();
|
|
75
75
|
|
|
76
76
|
const handleToggle = () => {
|
|
77
77
|
sidebarContext?.setToggle((v) => !v);
|
|
@@ -82,7 +82,7 @@ const TopbarBase: ParentComponent<TopbarProps> = (props) => {
|
|
|
82
82
|
return (
|
|
83
83
|
<header {...rest} data-topbar class={getClassName()}>
|
|
84
84
|
<Show when={sidebarContext}>
|
|
85
|
-
<Button variant="ghost" onClick={handleToggle} class="p-2" aria-label={i18n
|
|
85
|
+
<Button variant="ghost" onClick={handleToggle} class="p-2" aria-label={i18n.t("topbar.toggleSidebar")}>
|
|
86
86
|
<Icon icon={IconMenu2} size="1.5em" />
|
|
87
87
|
</Button>
|
|
88
88
|
</Show>
|
|
@@ -16,7 +16,7 @@ import { Button } from "../../form-control/Button";
|
|
|
16
16
|
import { Dropdown } from "../../disclosure/Dropdown";
|
|
17
17
|
import { List } from "../../data/list/List";
|
|
18
18
|
import { ListItem } from "../../data/list/ListItem";
|
|
19
|
-
import {
|
|
19
|
+
import { useI18n } from "../../../providers/i18n/I18nContext";
|
|
20
20
|
|
|
21
21
|
const desktopNavBaseClass = clsx("hidden sm:flex", "flex-row gap-1", "items-center");
|
|
22
22
|
const mobileWrapperClass = clsx("flex sm:hidden");
|
|
@@ -64,7 +64,7 @@ export interface TopbarMenuProps extends Omit<JSX.HTMLAttributes<HTMLElement>, "
|
|
|
64
64
|
export const TopbarMenu: Component<TopbarMenuProps> = (props) => {
|
|
65
65
|
const [local, rest] = splitProps(props, ["menus", "class"]);
|
|
66
66
|
const [mobileMenuOpen, setMobileMenuOpen] = createSignal(false);
|
|
67
|
-
const i18n =
|
|
67
|
+
const i18n = useI18n();
|
|
68
68
|
|
|
69
69
|
return (
|
|
70
70
|
<>
|
|
@@ -79,7 +79,7 @@ export const TopbarMenu: Component<TopbarMenuProps> = (props) => {
|
|
|
79
79
|
<Dropdown.Trigger>
|
|
80
80
|
<Button
|
|
81
81
|
variant="ghost"
|
|
82
|
-
aria-label={i18n
|
|
82
|
+
aria-label={i18n.t("topbarMenu.menu")}
|
|
83
83
|
aria-haspopup="menu"
|
|
84
84
|
aria-expanded={mobileMenuOpen()}
|
|
85
85
|
>
|
|
@@ -10,6 +10,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
10
10
|
import { createControllableSignal } from "./createControllableSignal";
|
|
11
11
|
import { Invalid } from "../components/form-control/Invalid";
|
|
12
12
|
import type { CheckboxSize } from "../components/form-control/checkbox/Checkbox.styles";
|
|
13
|
+
import { useI18n } from "../providers/i18n/I18nContext";
|
|
13
14
|
|
|
14
15
|
interface SelectionItemComponentProps {
|
|
15
16
|
value: boolean;
|
|
@@ -42,14 +43,14 @@ interface MultiGroupConfig {
|
|
|
42
43
|
mode: "multiple";
|
|
43
44
|
contextName: string;
|
|
44
45
|
ItemComponent: (props: SelectionItemComponentProps) => JSX.Element;
|
|
45
|
-
|
|
46
|
+
emptyErrorMsgKey: string;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
interface SingleGroupConfig {
|
|
49
50
|
mode: "single";
|
|
50
51
|
contextName: string;
|
|
51
52
|
ItemComponent: (props: SelectionItemComponentProps) => JSX.Element;
|
|
52
|
-
|
|
53
|
+
emptyErrorMsgKey: string;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
interface SelectionGroupItemProps<TValue> {
|
|
@@ -148,6 +149,9 @@ export function createSelectionGroup(config: MultiGroupConfig | SingleGroupConfi
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
const GroupInner: ParentComponent<MultiGroupProps<unknown>> = (props) => {
|
|
152
|
+
const i18n = useI18n();
|
|
153
|
+
const resolvedErrorMsg = () => i18n.t(config.emptyErrorMsgKey);
|
|
154
|
+
|
|
151
155
|
const [local, rest] = splitProps(props, [
|
|
152
156
|
"value",
|
|
153
157
|
"onValueChange",
|
|
@@ -205,11 +209,11 @@ export function createSelectionGroup(config: MultiGroupConfig | SingleGroupConfi
|
|
|
205
209
|
const errorMsg = createMemo(() => {
|
|
206
210
|
if (config.mode === "multiple") {
|
|
207
211
|
const v = local.value ?? [];
|
|
208
|
-
if (local.required && v.length === 0) return
|
|
212
|
+
if (local.required && v.length === 0) return resolvedErrorMsg();
|
|
209
213
|
return (local.validate as ((v: unknown[]) => string | undefined) | undefined)?.(v);
|
|
210
214
|
} else {
|
|
211
215
|
const v = local.value as unknown | undefined;
|
|
212
|
-
if (local.required && (v === undefined || v === null)) return
|
|
216
|
+
if (local.required && (v === undefined || v === null)) return resolvedErrorMsg();
|
|
213
217
|
return (local.validate as ((v: unknown | undefined) => string | undefined) | undefined)?.(
|
|
214
218
|
v,
|
|
215
219
|
);
|
|
@@ -38,13 +38,6 @@ export function useI18n(): I18nContextValue {
|
|
|
38
38
|
return context;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/**
|
|
42
|
-
* Get i18n context value (optional, returns undefined if not in provider)
|
|
43
|
-
*/
|
|
44
|
-
export function useI18nOptional(): I18nContextValue | undefined {
|
|
45
|
-
return useContext(I18nContext);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
41
|
/**
|
|
49
42
|
* I18n Provider component
|
|
50
43
|
*
|
|
@@ -144,6 +144,7 @@ export default {
|
|
|
144
144
|
},
|
|
145
145
|
sharedDataSelectList: {
|
|
146
146
|
searchPlaceholder: "Search...",
|
|
147
|
+
unspecified: "Unspecified",
|
|
147
148
|
},
|
|
148
149
|
dataSelectButton: {
|
|
149
150
|
deselect: "Deselect",
|
|
@@ -158,4 +159,41 @@ export default {
|
|
|
158
159
|
topbarMenu: {
|
|
159
160
|
menu: "Menu",
|
|
160
161
|
},
|
|
162
|
+
notificationBell: {
|
|
163
|
+
notifications: "Notifications",
|
|
164
|
+
clearAll: "Clear All",
|
|
165
|
+
noNotifications: "No notifications",
|
|
166
|
+
unreadCount: "{{count}} notifications",
|
|
167
|
+
},
|
|
168
|
+
notificationProvider: {
|
|
169
|
+
prefix: "Notification:",
|
|
170
|
+
},
|
|
171
|
+
themeToggle: {
|
|
172
|
+
light: "Light mode",
|
|
173
|
+
system: "System settings",
|
|
174
|
+
dark: "Dark mode",
|
|
175
|
+
},
|
|
176
|
+
combobox: {
|
|
177
|
+
searching: "Searching...",
|
|
178
|
+
noResults: "No results found",
|
|
179
|
+
},
|
|
180
|
+
numpad: {
|
|
181
|
+
enter: "ENT",
|
|
182
|
+
},
|
|
183
|
+
sidebarMenu: {
|
|
184
|
+
menu: "MENU",
|
|
185
|
+
},
|
|
186
|
+
validation: {
|
|
187
|
+
required: "This is a required field",
|
|
188
|
+
requiredField: "Required field",
|
|
189
|
+
requiredSelection: "This is a required selection",
|
|
190
|
+
selectItem: "Please select an item",
|
|
191
|
+
minLength: "Enter at least {{min}} characters",
|
|
192
|
+
maxLength: "Enter up to {{max}} characters",
|
|
193
|
+
invalidFormat: "The input format is invalid",
|
|
194
|
+
minValue: "Minimum value is {{min}}",
|
|
195
|
+
maxValue: "Maximum value is {{max}}",
|
|
196
|
+
minDate: "Must be greater than or equal to {{min}}",
|
|
197
|
+
maxDate: "Must be less than or equal to {{max}}",
|
|
198
|
+
},
|
|
161
199
|
};
|
|
@@ -144,6 +144,7 @@ export default {
|
|
|
144
144
|
},
|
|
145
145
|
sharedDataSelectList: {
|
|
146
146
|
searchPlaceholder: "검색...",
|
|
147
|
+
unspecified: "미지정",
|
|
147
148
|
},
|
|
148
149
|
dataSelectButton: {
|
|
149
150
|
deselect: "선택 해제",
|
|
@@ -158,4 +159,41 @@ export default {
|
|
|
158
159
|
topbarMenu: {
|
|
159
160
|
menu: "메뉴",
|
|
160
161
|
},
|
|
162
|
+
notificationBell: {
|
|
163
|
+
notifications: "알림",
|
|
164
|
+
clearAll: "모두 지우기",
|
|
165
|
+
noNotifications: "알림 없음",
|
|
166
|
+
unreadCount: "{{count}}개의 알림",
|
|
167
|
+
},
|
|
168
|
+
notificationProvider: {
|
|
169
|
+
prefix: "알림:",
|
|
170
|
+
},
|
|
171
|
+
themeToggle: {
|
|
172
|
+
light: "라이트 모드",
|
|
173
|
+
system: "시스템 설정",
|
|
174
|
+
dark: "다크 모드",
|
|
175
|
+
},
|
|
176
|
+
combobox: {
|
|
177
|
+
searching: "검색 중...",
|
|
178
|
+
noResults: "결과 없음",
|
|
179
|
+
},
|
|
180
|
+
numpad: {
|
|
181
|
+
enter: "입력",
|
|
182
|
+
},
|
|
183
|
+
sidebarMenu: {
|
|
184
|
+
menu: "메뉴",
|
|
185
|
+
},
|
|
186
|
+
validation: {
|
|
187
|
+
required: "필수 입력 항목입니다",
|
|
188
|
+
requiredField: "필수 항목",
|
|
189
|
+
requiredSelection: "필수 선택 항목입니다",
|
|
190
|
+
selectItem: "항목을 선택해 주세요",
|
|
191
|
+
minLength: "{{min}}자 이상 입력해 주세요",
|
|
192
|
+
maxLength: "{{max}}자 이하로 입력해 주세요",
|
|
193
|
+
invalidFormat: "입력 형식이 올바르지 않습니다",
|
|
194
|
+
minValue: "최솟값은 {{min}}입니다",
|
|
195
|
+
maxValue: "최댓값은 {{max}}입니다",
|
|
196
|
+
minDate: "{{min}} 이상이어야 합니다",
|
|
197
|
+
maxDate: "{{max}} 이하이어야 합니다",
|
|
198
|
+
},
|
|
161
199
|
};
|
package/tailwind.config.ts
CHANGED
|
@@ -1,38 +1,48 @@
|
|
|
1
1
|
import { render, fireEvent } from "@solidjs/testing-library";
|
|
2
2
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
3
3
|
import { Kanban } from "../../../../src/components/data/kanban/Kanban";
|
|
4
|
+
import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
|
|
5
|
+
import { ConfigProvider } from "../../../../src/providers/ConfigContext";
|
|
4
6
|
|
|
5
7
|
describe("Kanban selection system", () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
|
|
10
|
+
});
|
|
11
|
+
|
|
6
12
|
function renderKanban(options?: {
|
|
7
13
|
selectedValues?: unknown[];
|
|
8
14
|
onSelectedValuesChange?: (v: unknown[]) => void;
|
|
9
15
|
selectable?: boolean;
|
|
10
16
|
}) {
|
|
11
17
|
return render(() => (
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
<ConfigProvider clientName="test">
|
|
19
|
+
<I18nProvider>
|
|
20
|
+
<Kanban
|
|
21
|
+
selectedValues={options?.selectedValues}
|
|
22
|
+
onSelectedValuesChange={options?.onSelectedValuesChange}
|
|
23
|
+
class="h-[400px]"
|
|
24
|
+
>
|
|
25
|
+
<Kanban.Lane value="lane-1">
|
|
26
|
+
<Kanban.LaneTitle>Lane 1</Kanban.LaneTitle>
|
|
27
|
+
<Kanban.Card value={1} selectable={options?.selectable ?? true} contentClass="p-2">
|
|
28
|
+
Card 1
|
|
29
|
+
</Kanban.Card>
|
|
30
|
+
<Kanban.Card value={2} selectable={options?.selectable ?? true} contentClass="p-2">
|
|
31
|
+
Card 2
|
|
32
|
+
</Kanban.Card>
|
|
33
|
+
<Kanban.Card value={3} selectable={false} contentClass="p-2">
|
|
34
|
+
Card 3 (not selectable)
|
|
35
|
+
</Kanban.Card>
|
|
36
|
+
</Kanban.Lane>
|
|
37
|
+
<Kanban.Lane value="lane-2">
|
|
38
|
+
<Kanban.LaneTitle>Lane 2</Kanban.LaneTitle>
|
|
39
|
+
<Kanban.Card value={4} selectable contentClass="p-2">
|
|
40
|
+
Card 4
|
|
41
|
+
</Kanban.Card>
|
|
42
|
+
</Kanban.Lane>
|
|
43
|
+
</Kanban>
|
|
44
|
+
</I18nProvider>
|
|
45
|
+
</ConfigProvider>
|
|
36
46
|
));
|
|
37
47
|
}
|
|
38
48
|
|