@simplysm/solid 13.0.67 → 13.0.68

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.
Files changed (94) hide show
  1. package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
  2. package/dist/components/data/kanban/Kanban.js +4 -13
  3. package/dist/components/data/kanban/Kanban.js.map +2 -2
  4. package/dist/components/data/list/ListItem.d.ts +0 -18
  5. package/dist/components/data/list/ListItem.d.ts.map +1 -1
  6. package/dist/components/data/list/ListItem.js +3 -7
  7. package/dist/components/data/list/ListItem.js.map +2 -2
  8. package/dist/components/data/sheet/DataSheet.js +3 -3
  9. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  10. package/dist/components/disclosure/Dialog.d.ts +0 -6
  11. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  12. package/dist/components/disclosure/Dialog.js +12 -18
  13. package/dist/components/disclosure/Dialog.js.map +2 -2
  14. package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
  15. package/dist/components/disclosure/Dropdown.js +4 -13
  16. package/dist/components/disclosure/Dropdown.js.map +2 -2
  17. package/dist/components/disclosure/dialogZIndex.d.ts +2 -0
  18. package/dist/components/disclosure/dialogZIndex.d.ts.map +1 -1
  19. package/dist/components/disclosure/dialogZIndex.js +4 -0
  20. package/dist/components/disclosure/dialogZIndex.js.map +1 -1
  21. package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
  22. package/dist/components/features/crud-detail/CrudDetail.js +3 -2
  23. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  24. package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
  25. package/dist/components/features/crud-sheet/CrudSheet.js +4 -3
  26. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  27. package/dist/components/feedback/busy/BusyContainer.d.ts +2 -0
  28. package/dist/components/feedback/busy/BusyContainer.d.ts.map +1 -1
  29. package/dist/components/feedback/busy/BusyContainer.js.map +1 -1
  30. package/dist/components/feedback/print/PrintContext.js +1 -1
  31. package/dist/components/feedback/print/PrintContext.js.map +1 -1
  32. package/dist/components/form-control/field/NumberInput.d.ts +2 -2
  33. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  34. package/dist/components/form-control/field/NumberInput.js +3 -7
  35. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  36. package/dist/components/form-control/field/TextInput.d.ts +2 -2
  37. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  38. package/dist/components/form-control/field/TextInput.js +3 -7
  39. package/dist/components/form-control/field/TextInput.js.map +2 -2
  40. package/dist/components/form-control/select/SelectItem.d.ts +0 -3
  41. package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
  42. package/dist/components/form-control/select/SelectItem.js +3 -7
  43. package/dist/components/form-control/select/SelectItem.js.map +2 -2
  44. package/dist/helpers/createSlotComponent.d.ts +12 -0
  45. package/dist/helpers/createSlotComponent.d.ts.map +1 -0
  46. package/dist/helpers/createSlotComponent.js +13 -0
  47. package/dist/helpers/createSlotComponent.js.map +6 -0
  48. package/dist/{hooks/createPointerDrag.d.ts → helpers/startPointerDrag.d.ts} +2 -2
  49. package/dist/helpers/startPointerDrag.d.ts.map +1 -0
  50. package/dist/{hooks/createPointerDrag.js → helpers/startPointerDrag.js} +3 -3
  51. package/dist/{hooks/createPointerDrag.js.map → helpers/startPointerDrag.js.map} +2 -2
  52. package/dist/hooks/createControllableStore.d.ts.map +1 -1
  53. package/dist/hooks/createControllableStore.js +5 -1
  54. package/dist/hooks/createControllableStore.js.map +1 -1
  55. package/dist/hooks/useLogger.d.ts.map +1 -1
  56. package/dist/hooks/useLogger.js +3 -2
  57. package/dist/hooks/useLogger.js.map +1 -1
  58. package/dist/hooks/useSyncConfig.d.ts.map +1 -1
  59. package/dist/hooks/useSyncConfig.js +10 -4
  60. package/dist/hooks/useSyncConfig.js.map +1 -1
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +1 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/providers/LoggerContext.d.ts +0 -6
  66. package/dist/providers/LoggerContext.d.ts.map +1 -1
  67. package/dist/providers/LoggerContext.js +2 -6
  68. package/dist/providers/LoggerContext.js.map +2 -2
  69. package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
  70. package/dist/providers/shared-data/SharedDataProvider.js +7 -1
  71. package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
  72. package/package.json +9 -9
  73. package/src/components/data/kanban/Kanban.tsx +3 -15
  74. package/src/components/data/list/ListItem.tsx +2 -27
  75. package/src/components/data/sheet/DataSheet.tsx +3 -3
  76. package/src/components/disclosure/Dialog.tsx +14 -27
  77. package/src/components/disclosure/Dropdown.tsx +3 -15
  78. package/src/components/disclosure/dialogZIndex.ts +5 -0
  79. package/src/components/features/crud-detail/CrudDetail.tsx +3 -2
  80. package/src/components/features/crud-sheet/CrudSheet.tsx +4 -3
  81. package/src/components/feedback/busy/BusyContainer.tsx +2 -0
  82. package/src/components/feedback/print/PrintContext.ts +1 -1
  83. package/src/components/form-control/field/NumberInput.tsx +2 -10
  84. package/src/components/form-control/field/TextInput.tsx +3 -18
  85. package/src/components/form-control/select/SelectItem.tsx +3 -19
  86. package/src/helpers/createSlotComponent.ts +23 -0
  87. package/src/{hooks/createPointerDrag.ts → helpers/startPointerDrag.ts} +1 -1
  88. package/src/hooks/createControllableStore.ts +5 -1
  89. package/src/hooks/useLogger.ts +3 -3
  90. package/src/hooks/useSyncConfig.ts +12 -4
  91. package/src/index.ts +1 -0
  92. package/src/providers/LoggerContext.tsx +1 -16
  93. package/src/providers/shared-data/SharedDataProvider.tsx +8 -2
  94. package/dist/hooks/createPointerDrag.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/providers/LoggerContext.tsx"],
4
- "mappings": ";AAAA,SAEEA,eACAC,cACAC,kBAEK;AACP,SAASC,eAAe;AAaxB,MAAMC,oBAAgC;EACpCC,OAAOA,CAACC,aAAaC,SAAUJ,QAAgBG,QAAQ,EAAE,GAAGC,IAAI;AAClE;AAoBO,MAAMC,gBAAgBR,cAAkC;AAOxD,SAASS,gBAAgD;AAC9D,SAAOP,WAAWM,aAAa;AACjC;AAyBO,MAAME,iBAAmCC,WAAU;AACxD,QAAM,CAACC,SAASC,UAAU,IAAIZ,aAAyBG,iBAAiB;AAExE,QAAMU,QAA4B;IAChCF;IACAG,WAAYC,QAA2CH,WAAYI,UAASD,GAAGC,IAAI,CAAC;EACtF;AAEA,SAAAC,kBAAQV,cAAcW,UAAQ;IAACL;IAAY,IAAAM,WAAA;AAAA,aAAGT,MAAMS;IAAQ;EAAA,CAAA;AAC9D;",
5
- "names": ["createContext", "createSignal", "useContext", "consola", "defaultLogAdapter", "write", "severity", "data", "LoggerContext", "useLogAdapter", "LoggerProvider", "props", "adapter", "setAdapter", "value", "configure", "fn", "prev", "_$createComponent", "Provider", "children"]
4
+ "mappings": ";AAAA,SAAwBA,eAAeC,oBAA0C;AACjF,SAASC,eAAe;AAaxB,MAAMC,oBAAgC;EACpCC,OAAOA,CAACC,aAAaC,SAAUJ,QAAgBG,QAAQ,EAAE,GAAGC,IAAI;AAClE;AAoBO,MAAMC,gBAAgBP,cAAkC;AAyBxD,MAAMQ,iBAAmCC,WAAU;AACxD,QAAM,CAACC,SAASC,UAAU,IAAIV,aAAyBE,iBAAiB;AAExE,QAAMS,QAA4B;IAChCF;IACAG,WAAYC,QAA2CH,WAAYI,UAASD,GAAGC,IAAI,CAAC;EACtF;AAEA,SAAAC,kBAAQT,cAAcU,UAAQ;IAACL;IAAY,IAAAM,WAAA;AAAA,aAAGT,MAAMS;IAAQ;EAAA,CAAA;AAC9D;",
5
+ "names": ["createContext", "createSignal", "consola", "defaultLogAdapter", "write", "severity", "data", "LoggerContext", "LoggerProvider", "props", "adapter", "setAdapter", "value", "configure", "fn", "prev", "_$createComponent", "Provider", "children"]
6
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["..\\..\\..\\src\\providers\\shared-data\\SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAaxF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAyLhF"}
1
+ {"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["..\\..\\..\\src\\providers\\shared-data\\SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAaxF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CA+LhF"}
@@ -77,7 +77,11 @@ function SharedDataProvider(props) {
77
77
  }, async (changeKeys) => {
78
78
  await loadData(name, def, changeKeys);
79
79
  }).then((key) => {
80
- listenerKeyMap.set(name, key);
80
+ if (disposed) {
81
+ void client.removeEventListener(key);
82
+ } else {
83
+ listenerKeyMap.set(name, key);
84
+ }
81
85
  });
82
86
  void loadData(name, def);
83
87
  };
@@ -114,7 +118,9 @@ function SharedDataProvider(props) {
114
118
  };
115
119
  }
116
120
  }
121
+ let disposed = false;
117
122
  onCleanup(() => {
123
+ disposed = true;
118
124
  if (!currentDefinitions) return;
119
125
  for (const [name] of Object.entries(currentDefinitions)) {
120
126
  const listenerKey = listenerKeyMap.get(name);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/providers/shared-data/SharedDataProvider.tsx"],
4
- "mappings": "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",
5
- "names": ["createMemo", "createSignal", "onCleanup", "objEqual", "waitUntil", "SharedDataContext", "SharedDataChangeEvent", "useServiceClient", "useNotification", "useLogger", "SharedDataProvider", "props", "serviceClient", "notification", "logger", "configured", "busyCount", "setBusyCount", "busy", "signalMap", "Map", "memoMap", "listenerKeyMap", "versionMap", "accessors", "currentDefinitions", "ordering", "data", "orderByList", "result", "orderBy", "reverse", "selector", "item", "orderByDesc", "loadData", "name", "def", "changeKeys", "currentVersion", "get", "set", "c", "signal", "Error", "setItems", "resData", "fetch", "prev", "filtered", "filter", "includes", "getKey", "push", "err", "error", "danger", "message", "wait", "configure", "fn", "definitions", "Object", "entries", "ensureInitialized", "initialized", "client", "addEventListener", "then", "key", "items", "itemMap", "map", "serviceKey", "undefined", "emit", "emitToServer", "info", "getSearchText", "getIsHidden", "getParentKey", "listenerKey", "removeEventListener", "KNOWN_KEYS", "Set", "contextValue", "Proxy", "target", "prop", "has", "_$createComponent", "Provider", "value", "children"]
4
+ "mappings": "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",
5
+ "names": ["createMemo", "createSignal", "onCleanup", "objEqual", "waitUntil", "SharedDataContext", "SharedDataChangeEvent", "useServiceClient", "useNotification", "useLogger", "SharedDataProvider", "props", "serviceClient", "notification", "logger", "configured", "busyCount", "setBusyCount", "busy", "signalMap", "Map", "memoMap", "listenerKeyMap", "versionMap", "accessors", "currentDefinitions", "ordering", "data", "orderByList", "result", "orderBy", "reverse", "selector", "item", "orderByDesc", "loadData", "name", "def", "changeKeys", "currentVersion", "get", "set", "c", "signal", "Error", "setItems", "resData", "fetch", "prev", "filtered", "filter", "includes", "getKey", "push", "err", "error", "danger", "message", "wait", "configure", "fn", "definitions", "Object", "entries", "ensureInitialized", "initialized", "client", "addEventListener", "then", "key", "disposed", "removeEventListener", "items", "itemMap", "map", "serviceKey", "undefined", "emit", "emitToServer", "info", "getSearchText", "getIsHidden", "getParentKey", "listenerKey", "KNOWN_KEYS", "Set", "contextValue", "Proxy", "target", "prop", "has", "_$createComponent", "Provider", "value", "children"]
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/solid",
3
- "version": "13.0.67",
3
+ "version": "13.0.68",
4
4
  "description": "심플리즘 패키지 - SolidJS 라이브러리",
5
5
  "author": "김석래",
6
6
  "license": "Apache-2.0",
@@ -23,10 +23,10 @@
23
23
  "*.css"
24
24
  ],
25
25
  "dependencies": {
26
- "@solid-primitives/event-listener": "^2.4.4",
27
- "@solid-primitives/media": "^2.3.4",
28
- "@solid-primitives/resize-observer": "^2.1.4",
29
- "@solid-primitives/storage": "^4.3.3",
26
+ "@solid-primitives/event-listener": "^2.4.5",
27
+ "@solid-primitives/media": "^2.3.5",
28
+ "@solid-primitives/resize-observer": "^2.1.5",
29
+ "@solid-primitives/storage": "^4.3.4",
30
30
  "@solidjs/router": "^0.15.4",
31
31
  "@tabler/icons-solidjs": "^3.37.1",
32
32
  "@tiptap/core": "^3.20.0",
@@ -50,10 +50,10 @@
50
50
  "solid-tiptap": "^0.8.0",
51
51
  "tailwind-merge": "^3.5.0",
52
52
  "tailwindcss": "^3.4.19",
53
- "@simplysm/core-browser": "13.0.67",
54
- "@simplysm/service-client": "13.0.67",
55
- "@simplysm/core-common": "13.0.67",
56
- "@simplysm/service-common": "13.0.67"
53
+ "@simplysm/core-common": "13.0.68",
54
+ "@simplysm/core-browser": "13.0.68",
55
+ "@simplysm/service-common": "13.0.68",
56
+ "@simplysm/service-client": "13.0.68"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@solidjs/testing-library": "^0.8.10"
@@ -8,7 +8,6 @@ import {
8
8
  type ParentComponent,
9
9
  Show,
10
10
  splitProps,
11
- useContext,
12
11
  } from "solid-js";
13
12
  import clsx from "clsx";
14
13
  import { twMerge } from "tailwind-merge";
@@ -18,6 +17,7 @@ import { Checkbox } from "../../form-control/checkbox/Checkbox";
18
17
  import { Icon } from "../../display/Icon";
19
18
  import { BusyContainer } from "../../feedback/busy/BusyContainer";
20
19
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
20
+ import { createSlotComponent } from "../../../helpers/createSlotComponent";
21
21
  import { createSlotSignal } from "../../../hooks/createSlotSignal";
22
22
  import "./Kanban.css";
23
23
  import { iconButtonBase } from "../../../styles/patterns.styles";
@@ -35,23 +35,11 @@ import {
35
35
 
36
36
  // ─── KanbanLaneTitle ─────────────────────────────────────────────
37
37
 
38
- const KanbanLaneTitle: ParentComponent = (props) => {
39
- const ctx = useContext(KanbanLaneContext)!;
40
- // eslint-disable-next-line solid/reactivity -- 슬롯 accessor로 저장, JSX tracked scope에서 호출됨
41
- ctx.setTitle(() => props.children);
42
- onCleanup(() => ctx.setTitle(undefined));
43
- return null;
44
- };
38
+ const KanbanLaneTitle = createSlotComponent(KanbanLaneContext, (ctx) => ctx.setTitle);
45
39
 
46
40
  // ─── KanbanLaneTools ─────────────────────────────────────────────
47
41
 
48
- const KanbanLaneTools: ParentComponent = (props) => {
49
- const ctx = useContext(KanbanLaneContext)!;
50
- // eslint-disable-next-line solid/reactivity -- 슬롯 accessor로 저장, JSX tracked scope에서 호출됨
51
- ctx.setTools(() => props.children);
52
- onCleanup(() => ctx.setTools(undefined));
53
- return null;
54
- };
42
+ const KanbanLaneTools = createSlotComponent(KanbanLaneContext, (ctx) => ctx.setTools);
55
43
 
56
44
  // ─── KanbanCard ──────────────────────────────────────────────────
57
45
 
@@ -2,11 +2,9 @@ import {
2
2
  type Component,
3
3
  createContext,
4
4
  type JSX,
5
- onCleanup,
6
5
  type ParentComponent,
7
6
  Show,
8
7
  splitProps,
9
- useContext,
10
8
  } from "solid-js";
11
9
  import { IconChevronDown, type IconProps } from "@tabler/icons-solidjs";
12
10
  import { Icon } from "../../display/Icon";
@@ -15,6 +13,7 @@ import { twMerge } from "tailwind-merge";
15
13
  import { ripple } from "../../../directives/ripple";
16
14
  import { Collapse } from "../../disclosure/Collapse";
17
15
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
16
+ import { createSlotComponent } from "../../../helpers/createSlotComponent";
18
17
  import { createSlotSignal, type SlotAccessor } from "../../../hooks/createSlotSignal";
19
18
  import { useListContext } from "./ListContext";
20
19
  import { List } from "./List";
@@ -40,31 +39,7 @@ const ListItemSlotsContext = createContext<ListItemSlotsContextValue>();
40
39
 
41
40
  const chevronClass = clsx("transition-transform duration-200 motion-reduce:transition-none");
42
41
 
43
- /**
44
- * 중첩 리스트를 담는 서브 컴포넌트
45
- *
46
- * ListItem의 하위 아이템을 정의할 때 사용한다.
47
- * 내부적으로 `<List inset>`으로 감싸서 Context와 키보드 네비게이션이 동작한다.
48
- * 세로선 가이드가 자동으로 표시된다.
49
- *
50
- * @example
51
- * ```tsx
52
- * <List.Item>
53
- * Folder
54
- * <List.Item.Children>
55
- * <List.Item>File 1</List.Item>
56
- * <List.Item>File 2</List.Item>
57
- * </List.Item.Children>
58
- * </List.Item>
59
- * ```
60
- */
61
- const ListItemChildren: ParentComponent = (props) => {
62
- const ctx = useContext(ListItemSlotsContext)!;
63
- // eslint-disable-next-line solid/reactivity -- 슬롯 accessor로 저장, JSX tracked scope에서 호출됨
64
- ctx.setChildren(() => props.children);
65
- onCleanup(() => ctx.setChildren(undefined));
66
- return null;
67
- };
42
+ const ListItemChildren = createSlotComponent(ListItemSlotsContext, (ctx) => ctx.setChildren);
68
43
 
69
44
  export interface ListItemProps extends Omit<
70
45
  JSX.ButtonHTMLAttributes<HTMLButtonElement>,
@@ -33,7 +33,7 @@ import type {
33
33
  import { isDataSheetColumnDef, DataSheetColumn } from "./DataSheetColumn";
34
34
  import { applySorting, buildHeaderTable, collectAllExpandable, flattenTree } from "./sheetUtils";
35
35
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
36
- import { createPointerDrag } from "../../../hooks/createPointerDrag";
36
+ import { startPointerDrag } from "../../../helpers/startPointerDrag";
37
37
  import { Icon } from "../../display/Icon";
38
38
  import { Checkbox } from "../../form-control/checkbox/Checkbox";
39
39
  import { Pagination } from "../Pagination";
@@ -390,7 +390,7 @@ export const DataSheet: DataSheetComponent = <T,>(props: DataSheetProps<T>) => {
390
390
  height: `${container.scrollHeight}px`,
391
391
  });
392
392
 
393
- createPointerDrag(target, event.pointerId, {
393
+ startPointerDrag(target, event.pointerId, {
394
394
  onMove(e) {
395
395
  const delta = e.clientX - startX;
396
396
  const newWidth = Math.max(30, startWidth + delta);
@@ -586,7 +586,7 @@ export const DataSheet: DataSheetComponent = <T,>(props: DataSheetProps<T>) => {
586
586
 
587
587
  setDragState({ draggingItem: item, targetItem: null, position: null });
588
588
 
589
- createPointerDrag(target, e.pointerId, {
589
+ startPointerDrag(target, e.pointerId, {
590
590
  onMove(ev) {
591
591
  let foundTarget: T | null = null;
592
592
  let foundPosition: "before" | "after" | "inside" | null = null;
@@ -18,12 +18,13 @@ import { IconX } from "@tabler/icons-solidjs";
18
18
  import { createControllableSignal } from "../../hooks/createControllableSignal";
19
19
  import { createSlotSignal, type SlotAccessor } from "../../hooks/createSlotSignal";
20
20
  import { createMountTransition } from "../../hooks/createMountTransition";
21
- import { createPointerDrag } from "../../hooks/createPointerDrag";
21
+ import { startPointerDrag } from "../../helpers/startPointerDrag";
22
+ import { createSlotComponent } from "../../helpers/createSlotComponent";
22
23
  import { mergeStyles } from "../../helpers/mergeStyles";
23
24
  import { Icon } from "../display/Icon";
24
25
  import { borderSubtle } from "../../styles/tokens.styles";
25
26
  import { DialogDefaultsContext } from "./DialogContext";
26
- import { bringToFront, registerDialog, unregisterDialog } from "./dialogZIndex";
27
+ import { bringToFront, registerDialog, unregisterDialog, isTopmost } from "./dialogZIndex";
27
28
  import { Button } from "../form-control/Button";
28
29
 
29
30
  interface DialogSlotsContextValue {
@@ -33,27 +34,8 @@ interface DialogSlotsContextValue {
33
34
 
34
35
  const DialogSlotsContext = createContext<DialogSlotsContextValue>();
35
36
 
36
- /**
37
- * 다이얼로그 헤더 서브 컴포넌트
38
- */
39
- const DialogHeader: ParentComponent = (props) => {
40
- const ctx = useContext(DialogSlotsContext)!;
41
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
42
- ctx.setHeader(() => props.children);
43
- onCleanup(() => ctx.setHeader(undefined));
44
- return null;
45
- };
46
-
47
- /**
48
- * 다이얼로그 액션 서브 컴포넌트
49
- */
50
- const DialogAction: ParentComponent = (props) => {
51
- const ctx = useContext(DialogSlotsContext)!;
52
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
53
- ctx.setAction(() => props.children);
54
- onCleanup(() => ctx.setAction(undefined));
55
- return null;
56
- };
37
+ const DialogHeader = createSlotComponent(DialogSlotsContext, (ctx) => ctx.setHeader);
38
+ const DialogAction = createSlotComponent(DialogSlotsContext, (ctx) => ctx.setAction);
57
39
 
58
40
  export interface DialogProps {
59
41
  /** 모달 열림 상태 */
@@ -238,10 +220,15 @@ export const Dialog: DialogComponent = (props) => {
238
220
  // Escape 키 감지
239
221
  createEffect(() => {
240
222
  if (!open()) return;
241
- if (!closeOnEscape()) return;
242
223
 
243
224
  const handleKeyDown = (e: KeyboardEvent) => {
244
- if (e.key === "Escape") {
225
+ if (e.key !== "Escape") return;
226
+
227
+ const el = wrapperRef();
228
+ if (!el || !isTopmost(el)) return;
229
+
230
+ if (closeOnEscape()) {
231
+ e.stopImmediatePropagation();
245
232
  tryClose();
246
233
  }
247
234
  };
@@ -308,7 +295,7 @@ export const Dialog: DialogComponent = (props) => {
308
295
  const startTop = dialogEl.offsetTop;
309
296
  const startLeft = dialogEl.offsetLeft;
310
297
 
311
- createPointerDrag(target, event.pointerId, {
298
+ startPointerDrag(target, event.pointerId, {
312
299
  onMove(e) {
313
300
  e.stopPropagation();
314
301
  e.preventDefault();
@@ -356,7 +343,7 @@ export const Dialog: DialogComponent = (props) => {
356
343
  const startTop = dialogEl.offsetTop;
357
344
  const startLeft = dialogEl.offsetLeft;
358
345
 
359
- createPointerDrag(target, event.pointerId, {
346
+ startPointerDrag(target, event.pointerId, {
360
347
  onMove(e) {
361
348
  e.stopPropagation();
362
349
  e.preventDefault();
@@ -4,7 +4,6 @@ import {
4
4
  createSignal,
5
5
  createEffect,
6
6
  createContext,
7
- useContext,
8
7
  onCleanup,
9
8
  Show,
10
9
  splitProps,
@@ -17,6 +16,7 @@ import { Portal } from "solid-js/web";
17
16
  import clsx from "clsx";
18
17
  import { twMerge } from "tailwind-merge";
19
18
  import { mergeStyles } from "../../helpers/mergeStyles";
19
+ import { createSlotComponent } from "../../helpers/createSlotComponent";
20
20
  import { borderSubtle } from "../../styles/tokens.styles";
21
21
 
22
22
  // --- DropdownContext (internal) ---
@@ -31,23 +31,11 @@ const DropdownContext = createContext<DropdownContextValue>();
31
31
 
32
32
  // --- DropdownTrigger ---
33
33
 
34
- const DropdownTrigger: ParentComponent = (props) => {
35
- const ctx = useContext(DropdownContext)!;
36
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
37
- ctx.setTrigger(() => props.children);
38
- onCleanup(() => ctx.setTrigger(undefined));
39
- return null;
40
- };
34
+ const DropdownTrigger = createSlotComponent(DropdownContext, (ctx) => ctx.setTrigger);
41
35
 
42
36
  // --- DropdownContent ---
43
37
 
44
- const DropdownContent: ParentComponent = (props) => {
45
- const ctx = useContext(DropdownContext)!;
46
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
47
- ctx.setContent(() => props.children);
48
- onCleanup(() => ctx.setContent(undefined));
49
- return null;
50
- };
38
+ const DropdownContent = createSlotComponent(DropdownContext, (ctx) => ctx.setContent);
51
39
 
52
40
  // --- Dropdown ---
53
41
 
@@ -41,3 +41,8 @@ function reindex(): void {
41
41
  stack[i].style.zIndex = (BASE_Z + i).toString();
42
42
  }
43
43
  }
44
+
45
+ /** 해당 Dialog가 스택 최상위인지 확인 */
46
+ export function isTopmost(el: HTMLElement): boolean {
47
+ return stack.length > 0 && stack[stack.length - 1] === el;
48
+ }
@@ -47,7 +47,7 @@ interface CrudDetailComponent {
47
47
  }
48
48
 
49
49
  const CrudDetailBase = <TData extends object>(props: CrudDetailProps<TData>) => {
50
- const [local, _rest] = splitProps(props, [
50
+ const [local] = splitProps(props, [
51
51
  "load",
52
52
  "children",
53
53
  "submit",
@@ -175,9 +175,10 @@ const CrudDetailBase = <TData extends object>(props: CrudDetailProps<TData>) =>
175
175
 
176
176
  // -- Keyboard Shortcuts --
177
177
  createEventListener(document, "keydown", (e: KeyboardEvent) => {
178
+ if (!formRef?.contains(document.activeElement)) return;
178
179
  if (e.ctrlKey && e.key === "s") {
179
180
  e.preventDefault();
180
- formRef?.requestSubmit();
181
+ formRef.requestSubmit();
181
182
  }
182
183
  if (e.ctrlKey && e.altKey && e.key === "l") {
183
184
  e.preventDefault();
@@ -65,7 +65,7 @@ interface CrudSheetComponent {
65
65
  const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
66
66
  props: CrudSheetProps<TItem, TFilter>,
67
67
  ) => {
68
- const [local, _rest] = splitProps(props, [
68
+ const [local] = splitProps(props, [
69
69
  "search",
70
70
  "getItemKey",
71
71
  "persistKey",
@@ -387,9 +387,10 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
387
387
 
388
388
  // -- Keyboard Shortcuts --
389
389
  createEventListener(document, "keydown", async (e: KeyboardEvent) => {
390
+ if (!formRef?.contains(document.activeElement)) return;
390
391
  if (e.ctrlKey && e.key === "s" && !isSelectMode()) {
391
392
  e.preventDefault();
392
- formRef?.requestSubmit();
393
+ formRef.requestSubmit();
393
394
  }
394
395
  if (e.ctrlKey && e.altKey && e.key === "l") {
395
396
  e.preventDefault();
@@ -622,7 +623,7 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
622
623
  autoSelect={isSelectMode() && local.selectMode === "single" ? "click" : undefined}
623
624
  cellClass={(item) => {
624
625
  if (isItemDeleted(item)) {
625
- return clsx("line-through");
626
+ return "line-through";
626
627
  }
627
628
  return undefined;
628
629
  }}
@@ -14,7 +14,9 @@ import { createMountTransition } from "../../../hooks/createMountTransition";
14
14
  import "./BusyContainer.css";
15
15
 
16
16
  export interface BusyContainerProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "children"> {
17
+ /** 로딩 오버레이 표시 (children은 유지됨) */
17
18
  busy?: boolean;
19
+ /** false이면 children을 숨기고 로딩 오버레이 표시. 초기 데이터 로드 시 사용 */
18
20
  ready?: boolean;
19
21
  variant?: BusyVariant;
20
22
  message?: string;
@@ -15,6 +15,6 @@ export const PrintContext = createContext<PrintContextValue>();
15
15
 
16
16
  export function usePrint(): PrintContextValue {
17
17
  const ctx = useContext(PrintContext);
18
- if (!ctx) throw new Error("usePrint must be used inside <PrintProvider>");
18
+ if (!ctx) throw new Error("usePrint PrintProvider 내부에서만 사용할 있습니다");
19
19
  return ctx;
20
20
  }
@@ -4,15 +4,13 @@ import {
4
4
  createMemo,
5
5
  createSignal,
6
6
  type JSX,
7
- onCleanup,
8
- type ParentComponent,
9
7
  Show,
10
8
  splitProps,
11
- useContext,
12
9
  } from "solid-js";
13
10
  import clsx from "clsx";
14
11
  import { twMerge } from "tailwind-merge";
15
12
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
13
+ import { createSlotComponent } from "../../../helpers/createSlotComponent";
16
14
  import { createSlotSignal, type SlotAccessor } from "../../../hooks/createSlotSignal";
17
15
  import {
18
16
  type FieldSize,
@@ -37,13 +35,7 @@ interface NumberInputSlotsContextValue {
37
35
 
38
36
  const NumberInputSlotsContext = createContext<NumberInputSlotsContextValue>();
39
37
 
40
- const NumberInputPrefix: ParentComponent = (props) => {
41
- const ctx = useContext(NumberInputSlotsContext)!;
42
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
43
- ctx.setPrefix(() => props.children);
44
- onCleanup(() => ctx.setPrefix(undefined));
45
- return null;
46
- };
38
+ const NumberInputPrefix = createSlotComponent(NumberInputSlotsContext, (ctx) => ctx.setPrefix);
47
39
 
48
40
  export interface NumberInputProps {
49
41
  /** 입력 값 */
@@ -1,17 +1,8 @@
1
1
  import clsx from "clsx";
2
- import {
3
- createContext,
4
- createEffect,
5
- createMemo,
6
- type JSX,
7
- onCleanup,
8
- type ParentComponent,
9
- Show,
10
- splitProps,
11
- useContext,
12
- } from "solid-js";
2
+ import { createContext, createEffect, createMemo, type JSX, Show, splitProps } from "solid-js";
13
3
  import { twMerge } from "tailwind-merge";
14
4
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
5
+ import { createSlotComponent } from "../../../helpers/createSlotComponent";
15
6
  import { createSlotSignal, type SlotAccessor } from "../../../hooks/createSlotSignal";
16
7
  import { createIMEHandler } from "../../../hooks/createIMEHandler";
17
8
  import {
@@ -31,13 +22,7 @@ const TextInputSlotsContext = createContext<TextInputSlotsContextValue>();
31
22
 
32
23
  type TextInputType = "text" | "password" | "email";
33
24
 
34
- const TextInputPrefix: ParentComponent = (props) => {
35
- const ctx = useContext(TextInputSlotsContext)!;
36
- // eslint-disable-next-line solid/reactivity -- slot accessor: children은 렌더 시점에 lazy 평가됨
37
- ctx.setPrefix(() => props.children);
38
- onCleanup(() => ctx.setPrefix(undefined));
39
- return null;
40
- };
25
+ const TextInputPrefix = createSlotComponent(TextInputSlotsContext, (ctx) => ctx.setPrefix);
41
26
 
42
27
  export interface TextInputProps {
43
28
  /** 입력 값 */
@@ -1,18 +1,11 @@
1
- import {
2
- createContext,
3
- type JSX,
4
- onCleanup,
5
- type ParentComponent,
6
- Show,
7
- splitProps,
8
- useContext,
9
- } from "solid-js";
1
+ import { createContext, type JSX, type ParentComponent, Show, splitProps } from "solid-js";
10
2
  import { twMerge } from "tailwind-merge";
11
3
  import { IconCheck } from "@tabler/icons-solidjs";
12
4
  import { Icon } from "../../display/Icon";
13
5
  import { useSelectContext } from "./SelectContext";
14
6
  import { ripple } from "../../../directives/ripple";
15
7
  import { createSlotSignal, type SlotAccessor } from "../../../hooks/createSlotSignal";
8
+ import { createSlotComponent } from "../../../helpers/createSlotComponent";
16
9
  import { List } from "../../data/list/List";
17
10
  import { Collapse } from "../../disclosure/Collapse";
18
11
  import {
@@ -32,16 +25,7 @@ interface SelectItemSlotsContextValue {
32
25
 
33
26
  const SelectItemSlotsContext = createContext<SelectItemSlotsContextValue>();
34
27
 
35
- /**
36
- * 중첩 아이템을 담는 서브 컴포넌트
37
- */
38
- const SelectItemChildren: ParentComponent = (props) => {
39
- const ctx = useContext(SelectItemSlotsContext)!;
40
- // eslint-disable-next-line solid/reactivity -- slot accessor: children is lazily read at render time
41
- ctx.setChildren(() => props.children);
42
- onCleanup(() => ctx.setChildren(undefined));
43
- return null;
44
- };
28
+ const SelectItemChildren = createSlotComponent(SelectItemSlotsContext, (ctx) => ctx.setChildren);
45
29
 
46
30
  export interface SelectItemProps<TValue = unknown> extends Omit<
47
31
  JSX.ButtonHTMLAttributes<HTMLButtonElement>,
@@ -0,0 +1,23 @@
1
+ import { type Context, type ParentComponent, onCleanup, useContext } from "solid-js";
2
+ import type { JSX } from "solid-js";
3
+
4
+ type SlotSetter = (value: (() => JSX.Element) | undefined) => void;
5
+
6
+ /**
7
+ * Slot 등록 컴포넌트를 생성하는 팩토리 함수
8
+ *
9
+ * @param context - slot을 등록할 Context
10
+ * @param getSetter - context value에서 setter를 추출하는 함수
11
+ */
12
+ export function createSlotComponent<TCtx>(
13
+ context: Context<TCtx | undefined>,
14
+ getSetter: (ctx: TCtx) => SlotSetter,
15
+ ): ParentComponent {
16
+ return (props) => {
17
+ const ctx = useContext(context)!;
18
+ // eslint-disable-next-line solid/reactivity -- slot 등록은 초기 마운트 시 한 번만 수행
19
+ getSetter(ctx)(() => props.children);
20
+ onCleanup(() => getSetter(ctx)(undefined));
21
+ return null;
22
+ };
23
+ }
@@ -6,7 +6,7 @@
6
6
  * @param options.onMove - Called on each pointermove
7
7
  * @param options.onEnd - Called on pointerup or pointercancel (after listener cleanup)
8
8
  */
9
- export function createPointerDrag(
9
+ export function startPointerDrag(
10
10
  target: HTMLElement,
11
11
  pointerId: number,
12
12
  options: {
@@ -39,8 +39,12 @@ export function createControllableStore<TValue extends object>(options: {
39
39
 
40
40
  // 함수 래퍼로 setter 감싸서 onChange 알림 추가
41
41
  const wrappedSet = ((...args: any[]) => {
42
+ const before = JSON.stringify(unwrap(store));
42
43
  (rawSet as any)(...args);
43
- options.onChange()?.(objClone(unwrap(store)));
44
+ const after = JSON.stringify(unwrap(store));
45
+ if (before !== after) {
46
+ options.onChange()?.(objClone(unwrap(store)));
47
+ }
44
48
  }) as SetStoreFunction<TValue>;
45
49
 
46
50
  return [store, wrappedSet];
@@ -1,5 +1,6 @@
1
+ import { useContext } from "solid-js";
1
2
  import { consola } from "consola";
2
- import { useLogAdapter, type LogAdapter } from "../providers/LoggerContext";
3
+ import { LoggerContext, type LogAdapter } from "../providers/LoggerContext";
3
4
 
4
5
  type LogLevel = Parameters<LogAdapter["write"]>[0];
5
6
 
@@ -13,11 +14,10 @@ export interface Logger {
13
14
  }
14
15
 
15
16
  export function useLogger(): Logger {
16
- const loggerCtx = useLogAdapter();
17
+ const loggerCtx = useContext(LoggerContext);
17
18
 
18
19
  const createLogFunction = (level: LogLevel) => {
19
20
  return (...args: unknown[]) => {
20
- // Lazy read: 매 호출마다 현재 adapter를 확인
21
21
  const adapter = loggerCtx?.adapter();
22
22
  if (adapter) {
23
23
  void adapter.write(level, ...args);