@simplysm/solid 13.0.28 → 13.0.29
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 +6 -5
- package/dist/components/data/Pagination.d.ts.map +1 -1
- package/dist/components/data/Pagination.js.map +1 -1
- package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
- package/dist/components/data/calendar/Calendar.js.map +1 -1
- package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
- package/dist/components/data/kanban/Kanban.js +2 -2
- package/dist/components/data/kanban/Kanban.js.map +2 -2
- package/dist/components/data/list/List.d.ts.map +1 -1
- package/dist/components/data/list/List.js.map +1 -1
- package/dist/components/data/list/ListItem.d.ts.map +1 -1
- package/dist/components/data/list/ListItem.js.map +1 -1
- package/dist/components/data/permission-table/PermissionTable.d.ts.map +1 -1
- package/dist/components/data/permission-table/PermissionTable.js.map +1 -1
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js +23 -5
- package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
- package/dist/components/data/sheet/DataSheetColumn.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheetColumn.js.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.js.map +1 -1
- package/dist/components/data/sheet/sheetUtils.d.ts.map +1 -1
- package/dist/components/data/sheet/sheetUtils.js.map +1 -1
- package/dist/components/disclosure/Collapse.d.ts.map +1 -1
- package/dist/components/disclosure/Collapse.js +0 -3
- package/dist/components/disclosure/Collapse.js.map +1 -1
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js.map +1 -1
- package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
- package/dist/components/disclosure/DialogContext.js.map +1 -1
- package/dist/components/disclosure/DialogProvider.d.ts.map +1 -1
- package/dist/components/disclosure/DialogProvider.js.map +1 -1
- 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.map +1 -1
- package/dist/components/disclosure/Tabs.js.map +1 -1
- package/dist/components/display/Alert.d.ts.map +1 -1
- package/dist/components/display/Alert.js.map +1 -1
- package/dist/components/display/Card.d.ts +0 -1
- package/dist/components/display/Card.d.ts.map +1 -1
- package/dist/components/display/Card.js +1 -2
- package/dist/components/display/Card.js.map +1 -1
- package/dist/components/display/Echarts.d.ts +1 -1
- package/dist/components/display/Echarts.d.ts.map +1 -1
- package/dist/components/display/Echarts.js +2 -2
- package/dist/components/display/Echarts.js.map +2 -2
- package/dist/components/display/Link.d.ts +5 -0
- package/dist/components/display/Link.d.ts.map +1 -0
- package/dist/components/display/Link.js +26 -0
- package/dist/components/display/Link.js.map +6 -0
- package/dist/components/feedback/busy/BusyContainer.d.ts +12 -0
- package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -0
- package/dist/components/feedback/{loading/LoadingContainer.js → busy/BusyContainer.js} +7 -7
- package/dist/components/feedback/busy/BusyContainer.js.map +6 -0
- package/dist/components/feedback/busy/BusyContext.d.ts +11 -0
- package/dist/components/feedback/busy/BusyContext.d.ts.map +1 -0
- package/dist/components/feedback/busy/BusyContext.js +14 -0
- package/dist/components/feedback/busy/BusyContext.js.map +6 -0
- package/dist/components/feedback/busy/BusyProvider.d.ts +7 -0
- package/dist/components/feedback/busy/BusyProvider.d.ts.map +1 -0
- package/dist/components/feedback/{loading/LoadingProvider.js → busy/BusyProvider.js} +7 -7
- package/dist/components/feedback/busy/BusyProvider.js.map +6 -0
- package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBanner.js.map +1 -1
- package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBell.js.map +1 -1
- package/dist/components/feedback/notification/NotificationContext.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationContext.js.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.js.map +1 -1
- package/dist/components/form-control/Button.d.ts.map +1 -1
- package/dist/components/form-control/Button.js +2 -2
- package/dist/components/form-control/Button.js.map +1 -1
- package/dist/components/form-control/DropdownTrigger.styles.d.ts.map +1 -1
- package/dist/components/form-control/DropdownTrigger.styles.js +6 -1
- package/dist/components/form-control/DropdownTrigger.styles.js.map +1 -1
- package/dist/components/form-control/Invalid.d.ts.map +1 -1
- package/dist/components/form-control/Invalid.js +1 -1
- package/dist/components/form-control/Invalid.js.map +1 -1
- package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
- package/dist/components/form-control/ThemeToggle.js.map +1 -1
- package/dist/components/form-control/checkbox/Checkbox.styles.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/Checkbox.styles.js +5 -1
- package/dist/components/form-control/checkbox/Checkbox.styles.js.map +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.js.map +1 -1
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +5 -5
- package/dist/components/form-control/combobox/Combobox.js.map +2 -2
- package/dist/components/form-control/editor/EditorToolbar.d.ts.map +1 -1
- package/dist/components/form-control/editor/EditorToolbar.js.map +1 -1
- package/dist/components/form-control/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/components/form-control/editor/RichTextEditor.js.map +1 -1
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js.map +1 -1
- package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
- package/dist/components/form-control/field/Field.styles.js +17 -3
- package/dist/components/form-control/field/Field.styles.js.map +1 -1
- package/dist/components/form-control/field/NumberInput.d.ts +3 -0
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +23 -5
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts +4 -1
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +23 -6
- 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.map +1 -1
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js.map +1 -1
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js.map +1 -1
- package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
- package/dist/components/form-control/select/SelectItem.js.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.js.map +1 -1
- package/dist/components/layout/FormGroup.d.ts.map +1 -1
- package/dist/components/layout/FormGroup.js.map +1 -1
- package/dist/components/layout/sidebar/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/sidebar/Sidebar.js +1 -1
- package/dist/components/layout/sidebar/Sidebar.js.map +1 -1
- package/dist/components/layout/sidebar/SidebarContainer.d.ts.map +1 -1
- package/dist/components/layout/sidebar/SidebarContainer.js.map +1 -1
- package/dist/components/layout/sidebar/SidebarMenu.js.map +1 -1
- package/dist/components/layout/sidebar/SidebarUser.d.ts.map +1 -1
- package/dist/components/layout/sidebar/SidebarUser.js +2 -2
- package/dist/components/layout/sidebar/SidebarUser.js.map +1 -1
- package/dist/components/layout/topbar/Topbar.js +1 -1
- package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
- package/dist/components/layout/topbar/TopbarMenu.js.map +1 -1
- package/dist/components/layout/topbar/TopbarUser.d.ts.map +1 -1
- package/dist/components/layout/topbar/TopbarUser.js.map +1 -1
- package/dist/helpers/createAppStructure.d.ts.map +1 -1
- package/dist/helpers/createAppStructure.js +17 -12
- package/dist/helpers/createAppStructure.js.map +1 -1
- package/dist/helpers/mergeStyles.d.ts.map +1 -1
- package/dist/helpers/mergeStyles.js +4 -1
- package/dist/helpers/mergeStyles.js.map +1 -1
- package/dist/helpers/splitSlots.d.ts.map +1 -1
- package/dist/helpers/splitSlots.js.map +1 -1
- package/dist/hooks/createControllableSignal.d.ts.map +1 -1
- package/dist/hooks/createControllableSignal.js.map +1 -1
- package/dist/hooks/useClipboardValueCopy.js +3 -1
- package/dist/hooks/useClipboardValueCopy.js.map +1 -1
- package/dist/hooks/useLocalStorage.d.ts.map +1 -1
- package/dist/hooks/useLocalStorage.js.map +1 -1
- package/dist/hooks/usePrint.d.ts.map +1 -1
- package/dist/hooks/usePrint.js +5 -3
- package/dist/hooks/usePrint.js.map +1 -1
- package/dist/hooks/useRouterLink.d.ts.map +1 -1
- package/dist/hooks/useRouterLink.js.map +1 -1
- package/dist/hooks/useSyncConfig.d.ts +3 -3
- package/dist/hooks/useSyncConfig.js +4 -4
- package/dist/hooks/useSyncConfig.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/ConfigContext.d.ts +2 -2
- package/dist/providers/ConfigContext.d.ts.map +1 -1
- package/dist/providers/InitializeProvider.js +3 -3
- package/dist/providers/InitializeProvider.js.map +2 -2
- package/dist/providers/ServiceClientProvider.d.ts.map +1 -1
- package/dist/providers/ServiceClientProvider.js.map +1 -1
- package/dist/providers/ThemeContext.d.ts.map +1 -1
- package/dist/providers/ThemeContext.js.map +1 -1
- package/dist/providers/shared-data/SharedDataChangeEvent.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataChangeEvent.js +1 -3
- package/dist/providers/shared-data/SharedDataChangeEvent.js.map +1 -1
- package/dist/providers/shared-data/SharedDataContext.d.ts +1 -1
- package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.js +6 -6
- package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
- package/dist/styles/patterns.styles.js +1 -1
- package/dist/styles/tokens.styles.d.ts +1 -1
- package/dist/styles/tokens.styles.js +1 -1
- package/docs/display.md +19 -2
- package/docs/feedback.md +10 -10
- package/docs/hooks.md +6 -6
- package/docs/layout.md +3 -3
- package/docs/providers.md +1 -1
- package/package.json +3 -3
- package/src/components/data/Pagination.tsx +6 -1
- package/src/components/data/calendar/Calendar.tsx +18 -4
- package/src/components/data/kanban/Kanban.tsx +62 -18
- package/src/components/data/list/List.tsx +11 -4
- package/src/components/data/list/ListItem.tsx +12 -2
- package/src/components/data/permission-table/PermissionTable.tsx +32 -5
- package/src/components/data/sheet/DataSheet.styles.ts +23 -5
- package/src/components/data/sheet/DataSheet.tsx +100 -25
- package/src/components/data/sheet/DataSheetColumn.tsx +5 -1
- package/src/components/data/sheet/DataSheetConfigDialog.tsx +27 -5
- package/src/components/data/sheet/sheetUtils.ts +12 -3
- package/src/components/disclosure/Collapse.tsx +14 -3
- package/src/components/disclosure/Dialog.tsx +35 -6
- package/src/components/disclosure/DialogContext.ts +4 -1
- package/src/components/disclosure/DialogProvider.tsx +15 -3
- package/src/components/disclosure/Dropdown.tsx +12 -2
- package/src/components/disclosure/Tabs.tsx +29 -5
- package/src/components/display/Alert.tsx +3 -4
- package/src/components/display/Card.tsx +1 -2
- package/src/components/display/Echarts.tsx +12 -5
- package/src/components/display/Link.tsx +22 -0
- package/src/components/feedback/{loading/LoadingContainer.tsx → busy/BusyContainer.tsx} +43 -14
- package/src/components/feedback/busy/BusyContext.ts +20 -0
- package/src/components/feedback/{loading/LoadingProvider.tsx → busy/BusyProvider.tsx} +10 -10
- package/src/components/feedback/notification/NotificationBanner.tsx +13 -2
- package/src/components/feedback/notification/NotificationBell.tsx +17 -3
- package/src/components/feedback/notification/NotificationContext.ts +4 -1
- package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
- package/src/components/form-control/Button.tsx +8 -3
- package/src/components/form-control/DropdownTrigger.styles.ts +7 -1
- package/src/components/form-control/Invalid.tsx +5 -1
- package/src/components/form-control/ThemeToggle.tsx +6 -2
- package/src/components/form-control/checkbox/Checkbox.styles.ts +5 -1
- package/src/components/form-control/color-picker/ColorPicker.tsx +15 -2
- package/src/components/form-control/combobox/Combobox.tsx +16 -8
- package/src/components/form-control/editor/EditorToolbar.tsx +16 -5
- package/src/components/form-control/editor/RichTextEditor.tsx +22 -4
- package/src/components/form-control/field/DatePicker.tsx +5 -1
- package/src/components/form-control/field/DateTimePicker.tsx +8 -1
- package/src/components/form-control/field/Field.styles.ts +17 -3
- package/src/components/form-control/field/NumberInput.tsx +24 -0
- package/src/components/form-control/field/TextInput.tsx +28 -5
- package/src/components/form-control/field/Textarea.tsx +2 -1
- package/src/components/form-control/field/TimePicker.tsx +5 -1
- package/src/components/form-control/select/Select.tsx +32 -7
- package/src/components/form-control/select/SelectItem.tsx +3 -1
- package/src/components/form-control/state-preset/StatePreset.tsx +39 -14
- package/src/components/layout/FormGroup.tsx +11 -2
- package/src/components/layout/sidebar/Sidebar.tsx +3 -2
- package/src/components/layout/sidebar/SidebarContainer.tsx +8 -1
- package/src/components/layout/sidebar/SidebarMenu.tsx +7 -1
- package/src/components/layout/sidebar/SidebarUser.tsx +9 -4
- package/src/components/layout/topbar/Topbar.tsx +1 -1
- package/src/components/layout/topbar/TopbarMenu.tsx +27 -5
- package/src/components/layout/topbar/TopbarUser.tsx +5 -1
- package/src/helpers/createAppStructure.ts +29 -15
- package/src/helpers/mergeStyles.ts +6 -2
- package/src/helpers/splitSlots.ts +4 -1
- package/src/hooks/createControllableSignal.ts +2 -1
- package/src/hooks/useClipboardValueCopy.ts +5 -2
- package/src/hooks/useLocalStorage.ts +3 -1
- package/src/hooks/usePrint.ts +9 -4
- package/src/hooks/useRouterLink.ts +3 -1
- package/src/hooks/useSyncConfig.ts +7 -7
- package/src/index.ts +5 -4
- package/src/providers/ConfigContext.ts +2 -2
- package/src/providers/InitializeProvider.tsx +2 -2
- package/src/providers/ServiceClientProvider.tsx +14 -3
- package/src/providers/ThemeContext.tsx +10 -2
- package/src/providers/shared-data/SharedDataChangeEvent.ts +4 -3
- package/src/providers/shared-data/SharedDataContext.ts +1 -1
- package/src/providers/shared-data/SharedDataProvider.tsx +13 -8
- package/src/styles/patterns.styles.ts +1 -1
- package/src/styles/tokens.styles.ts +1 -1
- package/tailwind.config.ts +9 -0
- package/tailwind.css +1 -1
- package/dist/components/display/Card.css +0 -15
- package/dist/components/feedback/loading/LoadingContainer.d.ts +0 -12
- package/dist/components/feedback/loading/LoadingContainer.d.ts.map +0 -1
- package/dist/components/feedback/loading/LoadingContainer.js.map +0 -6
- package/dist/components/feedback/loading/LoadingContext.d.ts +0 -11
- package/dist/components/feedback/loading/LoadingContext.d.ts.map +0 -1
- package/dist/components/feedback/loading/LoadingContext.js +0 -14
- package/dist/components/feedback/loading/LoadingContext.js.map +0 -6
- package/dist/components/feedback/loading/LoadingProvider.d.ts +0 -7
- package/dist/components/feedback/loading/LoadingProvider.d.ts.map +0 -1
- package/dist/components/feedback/loading/LoadingProvider.js.map +0 -6
- package/src/components/display/Card.css +0 -15
- package/src/components/feedback/loading/LoadingContext.ts +0 -20
- /package/dist/components/feedback/{loading/LoadingContainer.css → busy/BusyContainer.css} +0 -0
- /package/src/components/feedback/{loading/LoadingContainer.css → busy/BusyContainer.css} +0 -0
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type Component,
|
|
3
|
+
createEffect,
|
|
4
|
+
createSignal,
|
|
5
|
+
onCleanup,
|
|
6
|
+
splitProps,
|
|
7
|
+
type JSX,
|
|
8
|
+
} from "solid-js";
|
|
2
9
|
import { createResizeObserver } from "@solid-primitives/resize-observer";
|
|
3
10
|
import type * as echartsType from "echarts";
|
|
4
11
|
import clsx from "clsx";
|
|
@@ -6,13 +13,13 @@ import { twMerge } from "tailwind-merge";
|
|
|
6
13
|
|
|
7
14
|
export interface EchartsProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
8
15
|
option: echartsType.EChartsOption;
|
|
9
|
-
|
|
16
|
+
busy?: boolean;
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
const baseClass = clsx("block", "size-full");
|
|
13
20
|
|
|
14
21
|
export const Echarts: Component<EchartsProps> = (props) => {
|
|
15
|
-
const [local, rest] = splitProps(props, ["option", "
|
|
22
|
+
const [local, rest] = splitProps(props, ["option", "busy", "class"]);
|
|
16
23
|
let containerRef!: HTMLDivElement;
|
|
17
24
|
let chart: echartsType.EChartsType | undefined;
|
|
18
25
|
const [ready, setReady] = createSignal(false);
|
|
@@ -33,10 +40,10 @@ export const Echarts: Component<EchartsProps> = (props) => {
|
|
|
33
40
|
chart!.setOption(local.option);
|
|
34
41
|
});
|
|
35
42
|
|
|
36
|
-
//
|
|
43
|
+
// busy 상태 변경 감지
|
|
37
44
|
createEffect(() => {
|
|
38
45
|
if (!ready()) return;
|
|
39
|
-
if (local.
|
|
46
|
+
if (local.busy) {
|
|
40
47
|
chart!.showLoading();
|
|
41
48
|
} else {
|
|
42
49
|
chart!.hideLoading();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type JSX, type ParentComponent, splitProps } from "solid-js";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
|
|
5
|
+
export interface LinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {}
|
|
6
|
+
|
|
7
|
+
const baseClass = clsx(
|
|
8
|
+
"text-primary-600",
|
|
9
|
+
"dark:text-primary-400",
|
|
10
|
+
"hover:underline",
|
|
11
|
+
"cursor-pointer",
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const Link: ParentComponent<LinkProps> = (props) => {
|
|
15
|
+
const [local, rest] = splitProps(props, ["children", "class"]);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<a class={twMerge(baseClass, local.class)} {...rest}>
|
|
19
|
+
{local.children}
|
|
20
|
+
</a>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ParentComponent,
|
|
3
|
+
type JSX,
|
|
4
|
+
splitProps,
|
|
5
|
+
createEffect,
|
|
6
|
+
onCleanup,
|
|
7
|
+
Show,
|
|
8
|
+
useContext,
|
|
9
|
+
} from "solid-js";
|
|
2
10
|
import clsx from "clsx";
|
|
3
11
|
import { twMerge } from "tailwind-merge";
|
|
4
|
-
import {
|
|
12
|
+
import { BusyContext, type BusyVariant } from "./BusyContext";
|
|
5
13
|
import { createMountTransition } from "../../../hooks/createMountTransition";
|
|
6
|
-
import "./
|
|
14
|
+
import "./BusyContainer.css";
|
|
7
15
|
|
|
8
|
-
export interface
|
|
16
|
+
export interface BusyContainerProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
9
17
|
busy?: boolean;
|
|
10
|
-
variant?:
|
|
18
|
+
variant?: BusyVariant;
|
|
11
19
|
message?: string;
|
|
12
20
|
progressPercent?: number;
|
|
13
21
|
children?: JSX.Element;
|
|
@@ -46,11 +54,18 @@ const progressBarClass = clsx(
|
|
|
46
54
|
|
|
47
55
|
const barIndicatorClass = clsx("absolute left-0 top-0", "h-1 w-full", "bg-white dark:bg-base-800");
|
|
48
56
|
|
|
49
|
-
export const
|
|
50
|
-
const [local, rest] = splitProps(props, [
|
|
57
|
+
export const BusyContainer: ParentComponent<BusyContainerProps> = (props) => {
|
|
58
|
+
const [local, rest] = splitProps(props, [
|
|
59
|
+
"busy",
|
|
60
|
+
"variant",
|
|
61
|
+
"message",
|
|
62
|
+
"progressPercent",
|
|
63
|
+
"class",
|
|
64
|
+
"children",
|
|
65
|
+
]);
|
|
51
66
|
|
|
52
|
-
const
|
|
53
|
-
const currVariant = ():
|
|
67
|
+
const busyCtx = useContext(BusyContext);
|
|
68
|
+
const currVariant = (): BusyVariant => local.variant ?? busyCtx?.variant() ?? "spinner";
|
|
54
69
|
|
|
55
70
|
// 애니메이션 상태 (mount transition)
|
|
56
71
|
const { mounted, animating, unmount } = createMountTransition(() => !!local.busy);
|
|
@@ -74,11 +89,16 @@ export const LoadingContainer: ParentComponent<LoadingContainerProps> = (props)
|
|
|
74
89
|
};
|
|
75
90
|
|
|
76
91
|
containerRef.addEventListener("keydown", handleKeyDownCapture, { capture: true });
|
|
77
|
-
onCleanup(() =>
|
|
92
|
+
onCleanup(() =>
|
|
93
|
+
containerRef.removeEventListener("keydown", handleKeyDownCapture, { capture: true }),
|
|
94
|
+
);
|
|
78
95
|
});
|
|
79
96
|
|
|
80
97
|
const screenClass = () =>
|
|
81
|
-
clsx(
|
|
98
|
+
clsx(
|
|
99
|
+
screenBaseClass,
|
|
100
|
+
animating() ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0",
|
|
101
|
+
);
|
|
82
102
|
|
|
83
103
|
// spinner: 슬라이드 다운 애니메이션
|
|
84
104
|
const rectClass = () => {
|
|
@@ -100,13 +120,19 @@ export const LoadingContainer: ParentComponent<LoadingContainerProps> = (props)
|
|
|
100
120
|
<Show when={currVariant() === "bar" && local.busy}>
|
|
101
121
|
<div class={barIndicatorClass}>
|
|
102
122
|
<div
|
|
103
|
-
class={clsx(
|
|
123
|
+
class={clsx(
|
|
124
|
+
"absolute left-0 top-0 h-1 w-full origin-left",
|
|
125
|
+
"bg-primary-500 dark:bg-primary-400",
|
|
126
|
+
)}
|
|
104
127
|
style={{
|
|
105
128
|
animation: "sd-busy-bar-before 2s infinite ease-in",
|
|
106
129
|
}}
|
|
107
130
|
/>
|
|
108
131
|
<div
|
|
109
|
-
class={clsx(
|
|
132
|
+
class={clsx(
|
|
133
|
+
"absolute left-0 top-0 h-1 w-full origin-left",
|
|
134
|
+
"bg-white dark:bg-base-800",
|
|
135
|
+
)}
|
|
110
136
|
style={{
|
|
111
137
|
animation: "sd-busy-bar-after 2s infinite ease-out",
|
|
112
138
|
}}
|
|
@@ -121,7 +147,10 @@ export const LoadingContainer: ParentComponent<LoadingContainerProps> = (props)
|
|
|
121
147
|
</div>
|
|
122
148
|
<Show when={local.progressPercent != null}>
|
|
123
149
|
<div class={progressTrackClass}>
|
|
124
|
-
<div
|
|
150
|
+
<div
|
|
151
|
+
class={progressBarClass}
|
|
152
|
+
style={{ transform: `scaleX(${(local.progressPercent ?? 0) / 100})` }}
|
|
153
|
+
/>
|
|
125
154
|
</div>
|
|
126
155
|
</Show>
|
|
127
156
|
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createContext, useContext, type Accessor } from "solid-js";
|
|
2
|
+
|
|
3
|
+
export type BusyVariant = "spinner" | "bar";
|
|
4
|
+
|
|
5
|
+
export interface BusyContextValue {
|
|
6
|
+
variant: Accessor<BusyVariant>;
|
|
7
|
+
show: (message?: string) => void;
|
|
8
|
+
hide: () => void;
|
|
9
|
+
setProgress: (percent: number | undefined) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const BusyContext = createContext<BusyContextValue>();
|
|
13
|
+
|
|
14
|
+
export function useBusy(): BusyContextValue {
|
|
15
|
+
const context = useContext(BusyContext);
|
|
16
|
+
if (!context) {
|
|
17
|
+
throw new Error("useBusy는 BusyProvider 내부에서만 사용할 수 있습니다");
|
|
18
|
+
}
|
|
19
|
+
return context;
|
|
20
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { type ParentComponent, createSignal } from "solid-js";
|
|
2
2
|
import { Portal } from "solid-js/web";
|
|
3
3
|
import clsx from "clsx";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { BusyContext, type BusyContextValue, type BusyVariant } from "./BusyContext";
|
|
5
|
+
import { BusyContainer } from "./BusyContainer";
|
|
6
6
|
|
|
7
7
|
const overlayClass = clsx("fixed left-0 top-0", "h-screen w-screen", "overflow-hidden");
|
|
8
8
|
|
|
9
|
-
export interface
|
|
10
|
-
variant?:
|
|
9
|
+
export interface BusyProviderProps {
|
|
10
|
+
variant?: BusyVariant;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const BusyProvider: ParentComponent<BusyProviderProps> = (props) => {
|
|
14
14
|
const [busyCount, setBusyCount] = createSignal(0);
|
|
15
15
|
const [message, setMessage] = createSignal<string | undefined>();
|
|
16
16
|
const [progress, setProgress] = createSignal<number | undefined>();
|
|
17
17
|
|
|
18
|
-
const variant = ():
|
|
18
|
+
const variant = (): BusyVariant => props.variant ?? "spinner";
|
|
19
19
|
|
|
20
20
|
const show = (msg?: string): void => {
|
|
21
21
|
setBusyCount((c) => c + 1);
|
|
@@ -33,7 +33,7 @@ export const LoadingProvider: ParentComponent<LoadingProviderProps> = (props) =>
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const contextValue:
|
|
36
|
+
const contextValue: BusyContextValue = {
|
|
37
37
|
variant,
|
|
38
38
|
show,
|
|
39
39
|
hide,
|
|
@@ -41,10 +41,10 @@ export const LoadingProvider: ParentComponent<LoadingProviderProps> = (props) =>
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
|
-
<
|
|
44
|
+
<BusyContext.Provider value={contextValue}>
|
|
45
45
|
{props.children}
|
|
46
46
|
<Portal>
|
|
47
|
-
<
|
|
47
|
+
<BusyContainer
|
|
48
48
|
busy={busyCount() > 0}
|
|
49
49
|
variant={variant()}
|
|
50
50
|
message={message()}
|
|
@@ -53,6 +53,6 @@ export const LoadingProvider: ParentComponent<LoadingProviderProps> = (props) =>
|
|
|
53
53
|
style={{ "pointer-events": busyCount() > 0 ? "auto" : "none" }}
|
|
54
54
|
/>
|
|
55
55
|
</Portal>
|
|
56
|
-
</
|
|
56
|
+
</BusyContext.Provider>
|
|
57
57
|
);
|
|
58
58
|
};
|
|
@@ -33,7 +33,13 @@ const themeClasses: Record<string, string> = {
|
|
|
33
33
|
const contentClass = clsx("flex flex-col", "gap-0.5", "min-w-0");
|
|
34
34
|
const messageClass = clsx("text-sm", "opacity-90", "overflow-auto");
|
|
35
35
|
const actionsClass = clsx("flex items-center", "gap-2", "shrink-0");
|
|
36
|
-
const actionButtonClass = clsx(
|
|
36
|
+
const actionButtonClass = clsx(
|
|
37
|
+
"rounded",
|
|
38
|
+
"bg-white/20",
|
|
39
|
+
"px-3 py-1",
|
|
40
|
+
"text-sm",
|
|
41
|
+
"hover:bg-white/30",
|
|
42
|
+
);
|
|
37
43
|
const dismissButtonClass = clsx("rounded", "p-1", "hover:bg-white/20");
|
|
38
44
|
|
|
39
45
|
export const NotificationBanner: Component = () => {
|
|
@@ -70,7 +76,12 @@ export const NotificationBanner: Component = () => {
|
|
|
70
76
|
{item().action!.label}
|
|
71
77
|
</button>
|
|
72
78
|
</Show>
|
|
73
|
-
<button
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
aria-label="알림 닫기"
|
|
82
|
+
class={dismissButtonClass}
|
|
83
|
+
onClick={handleDismiss}
|
|
84
|
+
>
|
|
74
85
|
<Icon icon={IconX} size="1.25em" />
|
|
75
86
|
</button>
|
|
76
87
|
</div>
|
|
@@ -99,18 +99,32 @@ export const NotificationBell: Component<NotificationBellProps> = (props) => {
|
|
|
99
99
|
</Show>
|
|
100
100
|
</button>
|
|
101
101
|
|
|
102
|
-
<Dropdown
|
|
102
|
+
<Dropdown
|
|
103
|
+
triggerRef={() => buttonRef}
|
|
104
|
+
open={open()}
|
|
105
|
+
onOpenChange={handleOpenChange}
|
|
106
|
+
maxHeight={400}
|
|
107
|
+
class="w-80"
|
|
108
|
+
>
|
|
103
109
|
<div class="p-2">
|
|
104
110
|
<div class={dropdownHeaderClass}>
|
|
105
111
|
<span class="font-semibold">알림</span>
|
|
106
112
|
<Show when={notification.items().length > 0}>
|
|
107
|
-
<button
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
data-notification-clear
|
|
116
|
+
class={clearButtonClass}
|
|
117
|
+
onClick={handleClear}
|
|
118
|
+
>
|
|
108
119
|
전체 삭제
|
|
109
120
|
</button>
|
|
110
121
|
</Show>
|
|
111
122
|
</div>
|
|
112
123
|
|
|
113
|
-
<Show
|
|
124
|
+
<Show
|
|
125
|
+
when={notification.items().length > 0}
|
|
126
|
+
fallback={<div class={emptyClass}>알림이 없습니다</div>}
|
|
127
|
+
>
|
|
114
128
|
<div class={listClass}>
|
|
115
129
|
<For each={[...notification.items()].reverse()}>
|
|
116
130
|
{(item) => (
|
|
@@ -38,7 +38,10 @@ export interface NotificationContextValue {
|
|
|
38
38
|
danger: (title: string, message?: string, options?: NotificationOptions) => string;
|
|
39
39
|
|
|
40
40
|
// 에러 처리 (danger 알림 + 로깅)
|
|
41
|
-
try: <TResult>(
|
|
41
|
+
try: <TResult>(
|
|
42
|
+
fn: () => Promise<TResult> | TResult,
|
|
43
|
+
header?: string,
|
|
44
|
+
) => Promise<TResult | undefined>;
|
|
42
45
|
|
|
43
46
|
// 알림 수정
|
|
44
47
|
update: (
|
|
@@ -154,7 +154,9 @@ export const NotificationProvider: ParentComponent = (props) => {
|
|
|
154
154
|
<NotificationContext.Provider value={contextValue}>
|
|
155
155
|
{/* 스크린 리더용 Live Region */}
|
|
156
156
|
<div role="status" aria-live="polite" aria-atomic="true" class="sr-only">
|
|
157
|
-
<Show when={latestUnread()}>
|
|
157
|
+
<Show when={latestUnread()}>
|
|
158
|
+
{(item) => `알림: ${item().title} ${item().message ?? ""}`}
|
|
159
|
+
</Show>
|
|
158
160
|
</div>
|
|
159
161
|
{props.children}
|
|
160
162
|
</NotificationContext.Provider>
|
|
@@ -2,7 +2,12 @@ import { type JSX, type ParentComponent, splitProps } from "solid-js";
|
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { twMerge } from "tailwind-merge";
|
|
4
4
|
import { ripple } from "../../directives/ripple";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
themeTokens,
|
|
7
|
+
type SemanticTheme,
|
|
8
|
+
type ComponentSize,
|
|
9
|
+
disabledOpacity,
|
|
10
|
+
} from "../../styles/tokens.styles";
|
|
6
11
|
|
|
7
12
|
// Directive 사용 선언 (TypeScript용)
|
|
8
13
|
void ripple;
|
|
@@ -18,7 +23,7 @@ const baseClass = clsx(
|
|
|
18
23
|
"justify-center",
|
|
19
24
|
"text-center",
|
|
20
25
|
"cursor-pointer",
|
|
21
|
-
"transition
|
|
26
|
+
"transition",
|
|
22
27
|
"rounded",
|
|
23
28
|
"focus:outline-none",
|
|
24
29
|
"focus-visible:ring-2",
|
|
@@ -30,7 +35,7 @@ const themeClasses = Object.fromEntries(
|
|
|
30
35
|
Object.entries(themeTokens).map(([theme, t]) => [
|
|
31
36
|
theme,
|
|
32
37
|
{
|
|
33
|
-
solid: clsx(t.solid, t.solidHover),
|
|
38
|
+
solid: clsx(t.solid, t.solidHover, "shadow-md hover:shadow-lg"),
|
|
34
39
|
outline: clsx("bg-transparent", t.hoverBg, t.text, t.border),
|
|
35
40
|
ghost: clsx("bg-transparent", t.hoverBg, t.text),
|
|
36
41
|
},
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { twMerge } from "tailwind-merge";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
borderDefault,
|
|
5
|
+
type ComponentSize,
|
|
6
|
+
paddingLg,
|
|
7
|
+
paddingSm,
|
|
8
|
+
paddingXl,
|
|
9
|
+
} from "../../styles/tokens.styles";
|
|
4
10
|
import { insetBase, insetFocusOutlineSelf } from "../../styles/patterns.styles";
|
|
5
11
|
|
|
6
12
|
export const triggerBaseClass = clsx(
|
|
@@ -49,13 +49,17 @@ export const Invalid: ParentComponent<InvalidProps> = (props) => {
|
|
|
49
49
|
return (
|
|
50
50
|
<div {...rest} class={twMerge("inline", local.class)}>
|
|
51
51
|
<span class={anchorClass}>
|
|
52
|
-
<span
|
|
52
|
+
<span
|
|
53
|
+
class={indicatorClass}
|
|
54
|
+
style={{ display: (local.message ?? "") !== "" ? "block" : "none" }}
|
|
55
|
+
/>
|
|
53
56
|
</span>
|
|
54
57
|
{local.children}
|
|
55
58
|
<input
|
|
56
59
|
ref={hiddenInputEl}
|
|
57
60
|
type="text"
|
|
58
61
|
class={hiddenInputClass}
|
|
62
|
+
autocomplete="off"
|
|
59
63
|
tabIndex={-1}
|
|
60
64
|
aria-hidden="true"
|
|
61
65
|
onFocus={handleHiddenInputFocus}
|
|
@@ -37,7 +37,10 @@ const modeLabels: Record<ThemeMode, string> = {
|
|
|
37
37
|
dark: "다크 모드",
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export interface ThemeToggleProps extends Omit<
|
|
40
|
+
export interface ThemeToggleProps extends Omit<
|
|
41
|
+
JSX.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
42
|
+
"children"
|
|
43
|
+
> {
|
|
41
44
|
/** 버튼 크기 */
|
|
42
45
|
size?: "sm" | "lg";
|
|
43
46
|
}
|
|
@@ -65,7 +68,8 @@ export const ThemeToggle: Component<ThemeToggleProps> = (props) => {
|
|
|
65
68
|
|
|
66
69
|
const { mode, cycleMode } = useTheme();
|
|
67
70
|
|
|
68
|
-
const getClassName = () =>
|
|
71
|
+
const getClassName = () =>
|
|
72
|
+
twMerge(baseClass, "p-1.5", local.size && sizeClasses[local.size], local.class);
|
|
69
73
|
|
|
70
74
|
const iconSize = () => (local.size ? iconSizes[local.size] : "1.25em");
|
|
71
75
|
|
|
@@ -53,7 +53,11 @@ export const checkboxSizeClasses: Record<CheckboxSize, string> = {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
// inset 스타일
|
|
56
|
-
export const checkboxInsetClass = clsx(
|
|
56
|
+
export const checkboxInsetClass = clsx(
|
|
57
|
+
"h-field-inset justify-center bg-transparent",
|
|
58
|
+
insetBase,
|
|
59
|
+
insetFocusOutlineSelf,
|
|
60
|
+
);
|
|
57
61
|
|
|
58
62
|
// inset 사이즈별 높이 (border 2px 제외)
|
|
59
63
|
export const checkboxInsetSizeHeightClasses: Record<CheckboxSize, string> = {
|
|
@@ -66,7 +66,15 @@ export interface ColorPickerProps {
|
|
|
66
66
|
* ```
|
|
67
67
|
*/
|
|
68
68
|
export const ColorPicker: Component<ColorPickerProps> = (props) => {
|
|
69
|
-
const [local, rest] = splitProps(props, [
|
|
69
|
+
const [local, rest] = splitProps(props, [
|
|
70
|
+
"value",
|
|
71
|
+
"onValueChange",
|
|
72
|
+
"title",
|
|
73
|
+
"disabled",
|
|
74
|
+
"size",
|
|
75
|
+
"class",
|
|
76
|
+
"style",
|
|
77
|
+
]);
|
|
70
78
|
|
|
71
79
|
const [value, setValue] = createControllableSignal({
|
|
72
80
|
value: () => local.value ?? "#000000",
|
|
@@ -78,7 +86,12 @@ export const ColorPicker: Component<ColorPickerProps> = (props) => {
|
|
|
78
86
|
};
|
|
79
87
|
|
|
80
88
|
const getClassName = () =>
|
|
81
|
-
twMerge(
|
|
89
|
+
twMerge(
|
|
90
|
+
baseClass,
|
|
91
|
+
local.size && sizeClasses[local.size],
|
|
92
|
+
local.disabled && disabledClass,
|
|
93
|
+
local.class,
|
|
94
|
+
);
|
|
82
95
|
|
|
83
96
|
return (
|
|
84
97
|
<input
|
|
@@ -154,7 +154,7 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
154
154
|
const [open, setOpen] = createSignal(false);
|
|
155
155
|
const [query, setQuery] = createSignal("");
|
|
156
156
|
const [items, setItems] = createSignal<T[]>([]);
|
|
157
|
-
const [
|
|
157
|
+
const [busy, setBusy] = createSignal(false);
|
|
158
158
|
|
|
159
159
|
// 선택된 값 관리 (controlled/uncontrolled 패턴)
|
|
160
160
|
const [getValue, setInternalValue] = createControllableSignal<T | undefined>({
|
|
@@ -200,12 +200,12 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
200
200
|
// loadItems 함수 참조를 캡처하여 사용
|
|
201
201
|
const loadItemsFn = local.loadItems;
|
|
202
202
|
debounceQueue.run(async () => {
|
|
203
|
-
|
|
203
|
+
setBusy(true);
|
|
204
204
|
try {
|
|
205
205
|
const result = await loadItemsFn(searchQuery);
|
|
206
206
|
setItems(result);
|
|
207
207
|
} finally {
|
|
208
|
-
|
|
208
|
+
setBusy(false);
|
|
209
209
|
}
|
|
210
210
|
});
|
|
211
211
|
};
|
|
@@ -282,7 +282,9 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
282
282
|
const getItemTemplate = (): ((item: T, index: number) => JSX.Element) | undefined => {
|
|
283
283
|
const templateSlots = slots().comboboxItemTemplate;
|
|
284
284
|
if (templateSlots.length === 0) return undefined;
|
|
285
|
-
return templateFnMap.get(templateSlots[0]) as
|
|
285
|
+
return templateFnMap.get(templateSlots[0]) as
|
|
286
|
+
| ((item: T, index: number) => JSX.Element)
|
|
287
|
+
| undefined;
|
|
286
288
|
};
|
|
287
289
|
|
|
288
290
|
// 선택된 값 또는 입력 표시
|
|
@@ -318,7 +320,7 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
318
320
|
const itemTemplate = getItemTemplate();
|
|
319
321
|
|
|
320
322
|
// 로딩 중
|
|
321
|
-
if (
|
|
323
|
+
if (busy()) {
|
|
322
324
|
return <div class={noResultsClass}>검색 중...</div>;
|
|
323
325
|
}
|
|
324
326
|
|
|
@@ -337,13 +339,19 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
337
339
|
if (itemTemplate) {
|
|
338
340
|
return (
|
|
339
341
|
<For each={items()}>
|
|
340
|
-
{(item, index) =>
|
|
342
|
+
{(item, index) => (
|
|
343
|
+
<ComboboxItem value={item}>{itemTemplate(item, index())}</ComboboxItem>
|
|
344
|
+
)}
|
|
341
345
|
</For>
|
|
342
346
|
);
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
// 기본 렌더링
|
|
346
|
-
return
|
|
350
|
+
return (
|
|
351
|
+
<For each={items()}>
|
|
352
|
+
{(item) => <ComboboxItem value={item}>{String(item)}</ComboboxItem>}
|
|
353
|
+
</For>
|
|
354
|
+
);
|
|
347
355
|
};
|
|
348
356
|
|
|
349
357
|
return (
|
|
@@ -364,7 +372,7 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
364
372
|
>
|
|
365
373
|
<div class={selectedValueClass}>{renderDisplayContent()}</div>
|
|
366
374
|
<div class={chevronWrapperClass}>
|
|
367
|
-
<Show when={
|
|
375
|
+
<Show when={busy()} fallback={<Icon icon={IconChevronDown} size="1em" />}>
|
|
368
376
|
<Icon icon={IconLoader2} size="1em" class="animate-spin" />
|
|
369
377
|
</Show>
|
|
370
378
|
</div>
|
|
@@ -48,7 +48,10 @@ const toolbarBtnClass = clsx(
|
|
|
48
48
|
);
|
|
49
49
|
|
|
50
50
|
// 툴바 버튼 활성 스타일
|
|
51
|
-
const toolbarBtnActiveClass = clsx(
|
|
51
|
+
const toolbarBtnActiveClass = clsx(
|
|
52
|
+
"bg-primary-100 text-primary-700",
|
|
53
|
+
"dark:bg-primary-900/40 dark:text-primary-300",
|
|
54
|
+
);
|
|
52
55
|
|
|
53
56
|
// 구분선 스타일
|
|
54
57
|
const separatorClass = clsx("mx-1 h-5 w-px", "bg-base-300 dark:bg-base-700");
|
|
@@ -107,7 +110,8 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
|
|
|
107
110
|
(editor) => (editor.getAttributes("highlight")["color"] as string | undefined) ?? "#ffff00",
|
|
108
111
|
);
|
|
109
112
|
|
|
110
|
-
const btnClass = (active: () => boolean) =>
|
|
113
|
+
const btnClass = (active: () => boolean) =>
|
|
114
|
+
twMerge(toolbarBtnClass, active() && toolbarBtnActiveClass);
|
|
111
115
|
|
|
112
116
|
// 이미지 삽입 핸들러
|
|
113
117
|
const handleImageInsert = () => {
|
|
@@ -202,14 +206,19 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
|
|
|
202
206
|
/>
|
|
203
207
|
</label>
|
|
204
208
|
<label class={colorLabelClass} title="배경색">
|
|
205
|
-
<span
|
|
209
|
+
<span
|
|
210
|
+
class={clsx("rounded px-0.5 text-sm font-bold")}
|
|
211
|
+
style={{ "background-color": currentHighlight() }}
|
|
212
|
+
>
|
|
206
213
|
A
|
|
207
214
|
</span>
|
|
208
215
|
<input
|
|
209
216
|
type="color"
|
|
210
217
|
class={colorInputClass}
|
|
211
218
|
value={currentHighlight()}
|
|
212
|
-
onInput={(ev) =>
|
|
219
|
+
onInput={(ev) =>
|
|
220
|
+
props.editor.chain().focus().toggleHighlight({ color: ev.currentTarget.value }).run()
|
|
221
|
+
}
|
|
213
222
|
/>
|
|
214
223
|
</label>
|
|
215
224
|
|
|
@@ -321,7 +330,9 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
|
|
|
321
330
|
type="button"
|
|
322
331
|
class={toolbarBtnClass}
|
|
323
332
|
title="테이블 삽입"
|
|
324
|
-
onClick={() =>
|
|
333
|
+
onClick={() =>
|
|
334
|
+
props.editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
|
|
335
|
+
}
|
|
325
336
|
>
|
|
326
337
|
<Icon icon={IconTablePlus} size="1em" />
|
|
327
338
|
</button>
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type Component,
|
|
3
|
+
type JSX,
|
|
4
|
+
Show,
|
|
5
|
+
createEffect,
|
|
6
|
+
on,
|
|
7
|
+
onCleanup,
|
|
8
|
+
splitProps,
|
|
9
|
+
untrack,
|
|
10
|
+
} from "solid-js";
|
|
2
11
|
import clsx from "clsx";
|
|
3
12
|
import "./editor.css";
|
|
4
13
|
import { twMerge } from "tailwind-merge";
|
|
@@ -67,7 +76,14 @@ const editorContentSizeClasses: Record<FieldSize, string> = {
|
|
|
67
76
|
};
|
|
68
77
|
|
|
69
78
|
export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
|
|
70
|
-
const [local, rest] = splitProps(props, [
|
|
79
|
+
const [local, rest] = splitProps(props, [
|
|
80
|
+
"value",
|
|
81
|
+
"onValueChange",
|
|
82
|
+
"disabled",
|
|
83
|
+
"size",
|
|
84
|
+
"class",
|
|
85
|
+
"style",
|
|
86
|
+
]);
|
|
71
87
|
|
|
72
88
|
const [value, setValue] = createControllableSignal({
|
|
73
89
|
value: () => local.value ?? "",
|
|
@@ -148,9 +164,11 @@ export const RichTextEditor: Component<RichTextEditorProps> = (props) => {
|
|
|
148
164
|
editor()?.destroy();
|
|
149
165
|
});
|
|
150
166
|
|
|
151
|
-
const getWrapperClass = () =>
|
|
167
|
+
const getWrapperClass = () =>
|
|
168
|
+
twMerge(editorWrapperClass, local.disabled && editorDisabledClass, local.class);
|
|
152
169
|
|
|
153
|
-
const getContentClass = () =>
|
|
170
|
+
const getContentClass = () =>
|
|
171
|
+
twMerge(editorContentClass, local.size && editorContentSizeClasses[local.size]);
|
|
154
172
|
|
|
155
173
|
return (
|
|
156
174
|
<div {...rest} data-rich-text-editor class={getWrapperClass()} style={local.style}>
|
|
@@ -241,7 +241,11 @@ export const DatePicker: Component<DatePickerProps> = (props) => {
|
|
|
241
241
|
class={twMerge(getWrapperClass(false), "relative", local.class)}
|
|
242
242
|
style={local.style}
|
|
243
243
|
>
|
|
244
|
-
<div
|
|
244
|
+
<div
|
|
245
|
+
data-date-field-content
|
|
246
|
+
style={{ visibility: isEditable() ? "hidden" : undefined }}
|
|
247
|
+
title={local.title}
|
|
248
|
+
>
|
|
245
249
|
{displayValue() || "\u00A0"}
|
|
246
250
|
</div>
|
|
247
251
|
|