@simplysm/solid 13.0.53 → 13.0.56

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 (222) hide show
  1. package/README.md +6 -2
  2. package/dist/components/data/crud-detail/CrudDetail.d.ts +14 -0
  3. package/dist/components/data/crud-detail/CrudDetail.d.ts.map +1 -0
  4. package/dist/components/data/crud-detail/CrudDetail.js +348 -0
  5. package/dist/components/data/crud-detail/CrudDetail.js.map +6 -0
  6. package/dist/components/data/crud-detail/CrudDetailAfter.d.ts +7 -0
  7. package/dist/components/data/crud-detail/CrudDetailAfter.d.ts.map +1 -0
  8. package/dist/components/data/crud-detail/CrudDetailAfter.js +14 -0
  9. package/dist/components/data/crud-detail/CrudDetailAfter.js.map +6 -0
  10. package/dist/components/data/crud-detail/CrudDetailBefore.d.ts +7 -0
  11. package/dist/components/data/crud-detail/CrudDetailBefore.d.ts.map +1 -0
  12. package/dist/components/data/crud-detail/CrudDetailBefore.js +14 -0
  13. package/dist/components/data/crud-detail/CrudDetailBefore.js.map +6 -0
  14. package/dist/components/data/crud-detail/CrudDetailTools.d.ts +7 -0
  15. package/dist/components/data/crud-detail/CrudDetailTools.d.ts.map +1 -0
  16. package/dist/components/data/crud-detail/CrudDetailTools.js +14 -0
  17. package/dist/components/data/crud-detail/CrudDetailTools.js.map +6 -0
  18. package/dist/components/data/crud-detail/types.d.ts +45 -0
  19. package/dist/components/data/crud-detail/types.d.ts.map +1 -0
  20. package/dist/components/data/crud-detail/types.js +1 -0
  21. package/dist/components/data/crud-detail/types.js.map +6 -0
  22. package/dist/components/data/crud-sheet/CrudSheet.d.ts +17 -0
  23. package/dist/components/data/crud-sheet/CrudSheet.d.ts.map +1 -0
  24. package/dist/components/data/crud-sheet/CrudSheet.js +679 -0
  25. package/dist/components/data/crud-sheet/CrudSheet.js.map +6 -0
  26. package/dist/components/data/crud-sheet/CrudSheetColumn.d.ts +5 -0
  27. package/dist/components/data/crud-sheet/CrudSheetColumn.d.ts.map +1 -0
  28. package/dist/components/data/crud-sheet/CrudSheetColumn.js +29 -0
  29. package/dist/components/data/crud-sheet/CrudSheetColumn.js.map +6 -0
  30. package/dist/components/data/crud-sheet/CrudSheetFilter.d.ts +7 -0
  31. package/dist/components/data/crud-sheet/CrudSheetFilter.d.ts.map +1 -0
  32. package/dist/components/data/crud-sheet/CrudSheetFilter.js +14 -0
  33. package/dist/components/data/crud-sheet/CrudSheetFilter.js.map +6 -0
  34. package/dist/components/data/crud-sheet/CrudSheetHeader.d.ts +7 -0
  35. package/dist/components/data/crud-sheet/CrudSheetHeader.d.ts.map +1 -0
  36. package/dist/components/data/crud-sheet/CrudSheetHeader.js +14 -0
  37. package/dist/components/data/crud-sheet/CrudSheetHeader.js.map +6 -0
  38. package/dist/components/data/crud-sheet/CrudSheetTools.d.ts +7 -0
  39. package/dist/components/data/crud-sheet/CrudSheetTools.d.ts.map +1 -0
  40. package/dist/components/data/crud-sheet/CrudSheetTools.js +14 -0
  41. package/dist/components/data/crud-sheet/CrudSheetTools.js.map +6 -0
  42. package/dist/components/data/crud-sheet/types.d.ts +109 -0
  43. package/dist/components/data/crud-sheet/types.d.ts.map +1 -0
  44. package/dist/components/data/crud-sheet/types.js +1 -0
  45. package/dist/components/data/crud-sheet/types.js.map +6 -0
  46. package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
  47. package/dist/components/data/kanban/Kanban.js +137 -138
  48. package/dist/components/data/kanban/Kanban.js.map +2 -2
  49. package/dist/components/data/kanban/KanbanContext.d.ts +5 -1
  50. package/dist/components/data/kanban/KanbanContext.d.ts.map +1 -1
  51. package/dist/components/data/kanban/KanbanContext.js.map +1 -1
  52. package/dist/components/data/list/ListItem.d.ts.map +1 -1
  53. package/dist/components/data/list/ListItem.js +109 -99
  54. package/dist/components/data/list/ListItem.js.map +2 -2
  55. package/dist/components/data/sheet/DataSheet.css +28 -10
  56. package/dist/components/data/sheet/DataSheet.js +1 -1
  57. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  58. package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
  59. package/dist/components/data/sheet/DataSheet.styles.js +1 -1
  60. package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
  61. package/dist/components/disclosure/Dialog.d.ts +16 -10
  62. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  63. package/dist/components/disclosure/Dialog.js +126 -91
  64. package/dist/components/disclosure/Dialog.js.map +2 -2
  65. package/dist/components/disclosure/DialogContext.d.ts +2 -4
  66. package/dist/components/disclosure/DialogContext.d.ts.map +1 -1
  67. package/dist/components/disclosure/DialogContext.js.map +1 -1
  68. package/dist/components/disclosure/DialogProvider.d.ts.map +1 -1
  69. package/dist/components/disclosure/DialogProvider.js +14 -9
  70. package/dist/components/disclosure/DialogProvider.js.map +2 -2
  71. package/dist/components/disclosure/Dropdown.d.ts +46 -22
  72. package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
  73. package/dist/components/disclosure/Dropdown.js +100 -65
  74. package/dist/components/disclosure/Dropdown.js.map +2 -2
  75. package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
  76. package/dist/components/feedback/notification/NotificationBanner.js +3 -3
  77. package/dist/components/feedback/notification/NotificationBanner.js.map +1 -1
  78. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  79. package/dist/components/feedback/notification/NotificationBell.js +84 -84
  80. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  81. package/dist/components/form-control/Invalid.js +1 -1
  82. package/dist/components/form-control/combobox/Combobox.d.ts +6 -3
  83. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  84. package/dist/components/form-control/combobox/Combobox.js +150 -168
  85. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  86. package/dist/components/form-control/combobox/ComboboxContext.d.ts +3 -0
  87. package/dist/components/form-control/combobox/ComboboxContext.d.ts.map +1 -1
  88. package/dist/components/form-control/combobox/ComboboxContext.js.map +1 -1
  89. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +0 -2
  90. package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
  91. package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -17
  92. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  93. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  94. package/dist/components/form-control/field/DatePicker.js +3 -2
  95. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  96. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  97. package/dist/components/form-control/field/DateTimePicker.js +3 -2
  98. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  99. package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
  100. package/dist/components/form-control/field/Field.styles.js +2 -1
  101. package/dist/components/form-control/field/Field.styles.js.map +1 -1
  102. package/dist/components/form-control/field/NumberInput.d.ts +15 -5
  103. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  104. package/dist/components/form-control/field/NumberInput.js +181 -141
  105. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  106. package/dist/components/form-control/field/TextInput.d.ts +9 -5
  107. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  108. package/dist/components/form-control/field/TextInput.js +199 -154
  109. package/dist/components/form-control/field/TextInput.js.map +2 -2
  110. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  111. package/dist/components/form-control/field/TimePicker.js +3 -2
  112. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  113. package/dist/components/form-control/select/Select.d.ts +3 -3
  114. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  115. package/dist/components/form-control/select/Select.js +116 -100
  116. package/dist/components/form-control/select/Select.js.map +2 -2
  117. package/dist/components/form-control/select/SelectContext.d.ts +9 -1
  118. package/dist/components/form-control/select/SelectContext.d.ts.map +1 -1
  119. package/dist/components/form-control/select/SelectContext.js.map +1 -1
  120. package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
  121. package/dist/components/form-control/select/SelectItem.js +77 -67
  122. package/dist/components/form-control/select/SelectItem.js.map +2 -2
  123. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  124. package/dist/components/form-control/state-preset/StatePreset.js +1 -1
  125. package/dist/components/form-control/state-preset/StatePreset.js.map +1 -1
  126. package/dist/components/layout/topbar/Topbar.d.ts +2 -0
  127. package/dist/components/layout/topbar/Topbar.d.ts.map +1 -1
  128. package/dist/components/layout/topbar/Topbar.js +2 -0
  129. package/dist/components/layout/topbar/Topbar.js.map +2 -2
  130. package/dist/components/layout/topbar/TopbarActions.d.ts +3 -0
  131. package/dist/components/layout/topbar/TopbarActions.d.ts.map +1 -0
  132. package/dist/components/layout/topbar/TopbarActions.js +17 -0
  133. package/dist/components/layout/topbar/TopbarActions.js.map +6 -0
  134. package/dist/components/layout/topbar/TopbarContainer.d.ts +1 -1
  135. package/dist/components/layout/topbar/TopbarContainer.d.ts.map +1 -1
  136. package/dist/components/layout/topbar/TopbarContainer.js +21 -12
  137. package/dist/components/layout/topbar/TopbarContainer.js.map +2 -2
  138. package/dist/components/layout/topbar/TopbarContext.d.ts +9 -0
  139. package/dist/components/layout/topbar/TopbarContext.d.ts.map +1 -0
  140. package/dist/components/layout/topbar/TopbarContext.js +29 -0
  141. package/dist/components/layout/topbar/TopbarContext.js.map +6 -0
  142. package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
  143. package/dist/components/layout/topbar/TopbarMenu.js +63 -57
  144. package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
  145. package/dist/components/layout/topbar/TopbarUser.d.ts.map +1 -1
  146. package/dist/components/layout/topbar/TopbarUser.js +53 -54
  147. package/dist/components/layout/topbar/TopbarUser.js.map +2 -2
  148. package/dist/hooks/createControllableStore.d.ts +29 -0
  149. package/dist/hooks/createControllableStore.d.ts.map +1 -0
  150. package/dist/hooks/createControllableStore.js +19 -0
  151. package/dist/hooks/createControllableStore.js.map +6 -0
  152. package/dist/index.d.ts +6 -1
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.js +7 -2
  155. package/dist/index.js.map +1 -1
  156. package/dist/styles/patterns.styles.d.ts.map +1 -1
  157. package/dist/styles/patterns.styles.js +7 -1
  158. package/dist/styles/patterns.styles.js.map +1 -1
  159. package/docs/data-components.md +428 -0
  160. package/docs/disclosure.md +65 -35
  161. package/docs/form-controls.md +18 -3
  162. package/docs/helpers.md +0 -39
  163. package/docs/hooks.md +39 -0
  164. package/docs/layout.md +70 -1
  165. package/package.json +4 -3
  166. package/src/components/data/crud-detail/CrudDetail.tsx +346 -0
  167. package/src/components/data/crud-detail/CrudDetailAfter.tsx +19 -0
  168. package/src/components/data/crud-detail/CrudDetailBefore.tsx +19 -0
  169. package/src/components/data/crud-detail/CrudDetailTools.tsx +19 -0
  170. package/src/components/data/crud-detail/types.ts +58 -0
  171. package/src/components/data/crud-sheet/CrudSheet.tsx +628 -0
  172. package/src/components/data/crud-sheet/CrudSheetColumn.tsx +34 -0
  173. package/src/components/data/crud-sheet/CrudSheetFilter.tsx +21 -0
  174. package/src/components/data/crud-sheet/CrudSheetHeader.tsx +19 -0
  175. package/src/components/data/crud-sheet/CrudSheetTools.tsx +21 -0
  176. package/src/components/data/crud-sheet/types.ts +133 -0
  177. package/src/components/data/kanban/Kanban.tsx +72 -65
  178. package/src/components/data/kanban/KanbanContext.ts +7 -1
  179. package/src/components/data/list/ListItem.tsx +31 -18
  180. package/src/components/data/sheet/DataSheet.css +28 -10
  181. package/src/components/data/sheet/DataSheet.styles.ts +1 -1
  182. package/src/components/data/sheet/DataSheet.tsx +1 -1
  183. package/src/components/disclosure/Dialog.tsx +143 -105
  184. package/src/components/disclosure/DialogContext.ts +2 -4
  185. package/src/components/disclosure/DialogProvider.tsx +4 -2
  186. package/src/components/disclosure/Dropdown.tsx +174 -86
  187. package/src/components/feedback/notification/NotificationBanner.tsx +3 -9
  188. package/src/components/feedback/notification/NotificationBell.tsx +51 -57
  189. package/src/components/form-control/Invalid.tsx +1 -1
  190. package/src/components/form-control/combobox/Combobox.tsx +109 -133
  191. package/src/components/form-control/combobox/ComboboxContext.ts +4 -1
  192. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +6 -16
  193. package/src/components/form-control/field/DatePicker.tsx +4 -1
  194. package/src/components/form-control/field/DateTimePicker.tsx +3 -0
  195. package/src/components/form-control/field/Field.styles.ts +1 -0
  196. package/src/components/form-control/field/NumberInput.tsx +131 -86
  197. package/src/components/form-control/field/TextInput.tsx +139 -88
  198. package/src/components/form-control/field/TimePicker.tsx +3 -0
  199. package/src/components/form-control/select/Select.tsx +85 -67
  200. package/src/components/form-control/select/SelectContext.ts +12 -1
  201. package/src/components/form-control/select/SelectItem.tsx +39 -18
  202. package/src/components/form-control/state-preset/StatePreset.tsx +1 -0
  203. package/src/components/layout/topbar/Topbar.tsx +3 -0
  204. package/src/components/layout/topbar/TopbarActions.tsx +8 -0
  205. package/src/components/layout/topbar/TopbarContainer.tsx +9 -5
  206. package/src/components/layout/topbar/TopbarContext.ts +36 -0
  207. package/src/components/layout/topbar/TopbarMenu.tsx +52 -55
  208. package/src/components/layout/topbar/TopbarUser.tsx +28 -31
  209. package/src/hooks/createControllableStore.ts +47 -0
  210. package/src/index.ts +6 -1
  211. package/src/styles/patterns.styles.ts +7 -1
  212. package/tailwind.css +4 -0
  213. package/dist/helpers/splitSlots.d.ts +0 -25
  214. package/dist/helpers/splitSlots.d.ts.map +0 -1
  215. package/dist/helpers/splitSlots.js +0 -25
  216. package/dist/helpers/splitSlots.js.map +0 -6
  217. package/dist/hooks/createItemTemplate.d.ts +0 -17
  218. package/dist/hooks/createItemTemplate.d.ts.map +0 -1
  219. package/dist/hooks/createItemTemplate.js +0 -40
  220. package/dist/hooks/createItemTemplate.js.map +0 -6
  221. package/src/helpers/splitSlots.ts +0 -51
  222. package/src/hooks/createItemTemplate.tsx +0 -42
@@ -50,16 +50,9 @@ export const TopbarUser: ParentComponent<TopbarUserProps> = (props) => {
50
50
  const [local, rest] = splitProps(props, ["children", "class", "menus"]);
51
51
 
52
52
  const [open, setOpen] = createSignal(false);
53
- let buttonRef: HTMLButtonElement | undefined;
54
53
 
55
54
  const hasMenus = () => local.menus !== undefined && local.menus.length > 0;
56
55
 
57
- const handleClick = () => {
58
- if (hasMenus()) {
59
- setOpen((v) => !v);
60
- }
61
- };
62
-
63
56
  const handleMenuClick = (menu: TopbarUserMenu) => {
64
57
  setOpen(false);
65
58
  menu.onClick();
@@ -67,32 +60,36 @@ export const TopbarUser: ParentComponent<TopbarUserProps> = (props) => {
67
60
 
68
61
  const getClassName = () => twMerge(wrapperBaseClass, local.class);
69
62
 
63
+ const buttonContent = () => (
64
+ <Button
65
+ variant="ghost"
66
+ class={buttonContentClass}
67
+ aria-haspopup={hasMenus() ? "menu" : undefined}
68
+ aria-expanded={hasMenus() ? open() : undefined}
69
+ >
70
+ {local.children}
71
+ <Show when={hasMenus()}>
72
+ <Icon
73
+ icon={IconChevronDown}
74
+ size="1em"
75
+ class={clsx("transition-transform", open() && "rotate-180")}
76
+ />
77
+ </Show>
78
+ </Button>
79
+ );
80
+
70
81
  return (
71
82
  <div {...rest} data-topbar-user class={getClassName()}>
72
- <Button
73
- ref={buttonRef}
74
- variant="ghost"
75
- onClick={handleClick}
76
- class={buttonContentClass}
77
- aria-haspopup={hasMenus() ? "menu" : undefined}
78
- aria-expanded={hasMenus() ? open() : undefined}
79
- >
80
- {local.children}
81
- <Show when={hasMenus()}>
82
- <Icon
83
- icon={IconChevronDown}
84
- size="1em"
85
- class={clsx("transition-transform", open() && "rotate-180")}
86
- />
87
- </Show>
88
- </Button>
89
- <Show when={hasMenus()}>
90
- <Dropdown triggerRef={() => buttonRef} open={open()} onOpenChange={setOpen}>
91
- <List inset>
92
- <For each={local.menus}>
93
- {(menu) => <ListItem onClick={() => handleMenuClick(menu)}>{menu.title}</ListItem>}
94
- </For>
95
- </List>
83
+ <Show when={hasMenus()} fallback={buttonContent()}>
84
+ <Dropdown open={open()} onOpenChange={setOpen}>
85
+ <Dropdown.Trigger>{buttonContent()}</Dropdown.Trigger>
86
+ <Dropdown.Content>
87
+ <List inset>
88
+ <For each={local.menus}>
89
+ {(menu) => <ListItem onClick={() => handleMenuClick(menu)}>{menu.title}</ListItem>}
90
+ </For>
91
+ </List>
92
+ </Dropdown.Content>
96
93
  </Dropdown>
97
94
  </Show>
98
95
  </div>
@@ -0,0 +1,47 @@
1
+ import { createEffect } from "solid-js";
2
+ import { createStore, reconcile, unwrap } from "solid-js/store";
3
+ import type { SetStoreFunction } from "solid-js/store";
4
+ import { objClone } from "@simplysm/core-common";
5
+
6
+ /**
7
+ * Controlled/Uncontrolled 패턴을 지원하는 store hook
8
+ *
9
+ * @remarks
10
+ * - `onChange`가 제공되면 controlled 모드: setter 호출 시 onChange로 변경 알림
11
+ * - `onChange`가 없으면 uncontrolled 모드: 내부 store만 사용
12
+ * - SetStoreFunction의 모든 overload 지원 (path 기반, produce, reconcile 등)
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // Controlled 모드 (onItemsChange 제공)
17
+ * const [items, setItems] = createControllableStore<Item[]>({
18
+ * value: () => props.items ?? [],
19
+ * onChange: () => props.onItemsChange,
20
+ * });
21
+ *
22
+ * // Uncontrolled 모드 (onItemsChange 미제공)
23
+ * const [items, setItems] = createControllableStore<Item[]>({
24
+ * value: () => [],
25
+ * onChange: () => undefined,
26
+ * });
27
+ * ```
28
+ */
29
+ export function createControllableStore<TValue extends object>(options: {
30
+ value: () => TValue;
31
+ onChange: () => ((value: TValue) => void) | undefined;
32
+ }): [TValue, SetStoreFunction<TValue>] {
33
+ const [store, rawSet] = createStore<TValue>(objClone(options.value()));
34
+
35
+ // 외부 value 변경 → 내부 store 동기화
36
+ createEffect(() => {
37
+ rawSet(reconcile(options.value()) as any);
38
+ });
39
+
40
+ // 함수 래퍼로 setter 감싸서 onChange 알림 추가
41
+ const wrappedSet = ((...args: any[]) => {
42
+ (rawSet as any)(...args);
43
+ options.onChange()?.(objClone(unwrap(store)));
44
+ }) as SetStoreFunction<TValue>;
45
+
46
+ return [store, wrappedSet];
47
+ }
package/src/index.ts CHANGED
@@ -43,6 +43,7 @@ export * from "./components/layout/FormTable";
43
43
  export * from "./components/layout/sidebar/Sidebar";
44
44
  export * from "./components/layout/sidebar/SidebarContext";
45
45
  export * from "./components/layout/topbar/Topbar";
46
+ export * from "./components/layout/topbar/TopbarContext";
46
47
 
47
48
  //#endregion
48
49
 
@@ -56,6 +57,10 @@ export * from "./components/data/Pagination";
56
57
  export * from "./components/data/sheet/DataSheet";
57
58
  export * from "./components/data/sheet/DataSheet.styles";
58
59
  export * from "./components/data/sheet/types";
60
+ export * from "./components/data/crud-sheet/CrudSheet";
61
+ export * from "./components/data/crud-sheet/types";
62
+ export * from "./components/data/crud-detail/CrudDetail";
63
+ export * from "./components/data/crud-detail/types";
59
64
  export * from "./components/data/calendar/Calendar";
60
65
  export * from "./components/data/permission-table/PermissionTable";
61
66
  export * from "./components/data/kanban/Kanban";
@@ -154,6 +159,7 @@ export * from "./hooks/useLocalStorage";
154
159
  export * from "./hooks/useSyncConfig";
155
160
  export * from "./hooks/useLogger";
156
161
  export { createControllableSignal } from "./hooks/createControllableSignal";
162
+ export { createControllableStore } from "./hooks/createControllableStore";
157
163
  export { createIMEHandler } from "./hooks/createIMEHandler";
158
164
  export { createMountTransition } from "./hooks/createMountTransition";
159
165
  export { useRouterLink } from "./hooks/useRouterLink";
@@ -176,7 +182,6 @@ export { ripple } from "./directives/ripple";
176
182
  //#region ========== Helpers ==========
177
183
 
178
184
  export { mergeStyles } from "./helpers/mergeStyles";
179
- export { splitSlots } from "./helpers/splitSlots";
180
185
  export { createAppStructure } from "./helpers/createAppStructure";
181
186
  export type {
182
187
  AppStructureItem,
@@ -41,4 +41,10 @@ export const fieldSurface = clsx(
41
41
  );
42
42
 
43
43
  // ── 입력 요소 공통 ──
44
- export const inputBase = clsx("min-w-0 flex-1", "bg-transparent", "outline-none", textPlaceholder);
44
+ export const inputBase = clsx(
45
+ "min-w-0 flex-1",
46
+ "bg-transparent",
47
+ "outline-none",
48
+ "[text-decoration:inherit]",
49
+ textPlaceholder,
50
+ );
package/tailwind.css CHANGED
@@ -18,6 +18,10 @@
18
18
  height: 100%;
19
19
  }
20
20
 
21
+ pre {
22
+ font-family: sans-serif;
23
+ }
24
+
21
25
  *:focus {
22
26
  outline: none;
23
27
  }
@@ -1,25 +0,0 @@
1
- import "@simplysm/core-common";
2
- import { type Accessor } from "solid-js";
3
- import type { JSX } from "solid-js/jsx-runtime";
4
- /**
5
- * children을 slot 키 기준으로 분리하여 반환합니다.
6
- * SolidJS의 splitProps와 유사한 패턴으로 동작합니다.
7
- *
8
- * @param resolved - children(() => props.children)으로 생성된 resolved children
9
- * @param keys - 분리할 slot 키 배열 (camelCase, data 속성과 매칭)
10
- * @returns [slots, content] - slots는 각 키별 HTMLElement[], content는 나머지 JSX.Element[]
11
- *
12
- * @example
13
- * ```tsx
14
- * const resolved = children(() => props.children);
15
- * const [slots, content] = splitSlots(resolved, ["selectHeader", "selectAction"] as const);
16
- *
17
- * // JSX에서 사용
18
- * <div>{slots().selectHeader.single()}</div>
19
- * <div>{content()}</div>
20
- * ```
21
- */
22
- export declare function splitSlots<K extends string>(resolved: {
23
- toArray: () => unknown[];
24
- }, keys: readonly K[]): [Accessor<Record<K, HTMLElement[]>>, Accessor<JSX.Element[]>];
25
- //# sourceMappingURL=splitSlots.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"splitSlots.d.ts","sourceRoot":"","sources":["..\\..\\src\\helpers\\splitSlots.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,QAAQ,EAAc,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,OAAO,EAAE,CAAA;CAAE,EACtC,IAAI,EAAE,SAAS,CAAC,EAAE,GACjB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAyB/D"}
@@ -1,25 +0,0 @@
1
- import "@simplysm/core-common";
2
- import { createMemo } from "solid-js";
3
- function splitSlots(resolved, keys) {
4
- const memo = createMemo(() => {
5
- const arr = resolved.toArray();
6
- const result = Object.fromEntries(keys.map((k) => [k, []]));
7
- const content = [];
8
- for (const c of arr) {
9
- if (c instanceof HTMLElement) {
10
- const matchedKey = keys.find((k) => k in c.dataset);
11
- if (matchedKey !== void 0) {
12
- result[matchedKey].push(c);
13
- continue;
14
- }
15
- }
16
- content.push(c);
17
- }
18
- return { result, content };
19
- });
20
- return [() => memo().result, () => memo().content];
21
- }
22
- export {
23
- splitSlots
24
- };
25
- //# sourceMappingURL=splitSlots.js.map
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/helpers/splitSlots.ts"],
4
- "mappings": "AAAA,OAAO;AACP,SAAwB,kBAAkB;AAqBnC,SAAS,WACd,UACA,MAC+D;AAC/D,QAAM,OAAO,WAAW,MAAM;AAC5B,UAAM,MAAM,SAAS,QAAQ;AAC7B,UAAM,SAAS,OAAO,YAAY,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAI1D,UAAM,UAAyB,CAAC;AAEhC,eAAW,KAAK,KAAK;AACnB,UAAI,aAAa,aAAa;AAC5B,cAAM,aAAa,KAAK,KAAK,CAAC,MAAM,KAAK,EAAE,OAAO;AAClD,YAAI,eAAe,QAAW;AAC5B,iBAAO,UAAU,EAAE,KAAK,CAAC;AACzB;AAAA,QACF;AAAA,MACF;AACA,cAAQ,KAAK,CAAgB;AAAA,IAC/B;AAEA,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B,CAAC;AAGD,SAAO,CAAC,MAAM,KAAK,EAAE,QAAQ,MAAM,KAAK,EAAE,OAAO;AACnD;",
5
- "names": []
6
- }
@@ -1,17 +0,0 @@
1
- import type { JSX } from "solid-js";
2
- /**
3
- * WeakMap 기반 템플릿 슬롯 패턴을 생성합니다. SolidJS children을 통해 렌더 함수를 전달할 때 사용합니다.
4
- *
5
- * Select와 Combobox의 ItemTemplate 서브 컴포넌트 패턴에서 사용됩니다.
6
- * TemplateSlot은 WeakMap에 렌더 함수를 ref로 저장하는 숨겨진 span을 렌더링합니다.
7
- * getTemplate은 resolved 슬롯 엘리먼트에서 렌더 함수를 가져옵니다.
8
- *
9
- * @param dataAttr - 숨겨진 span에 사용할 HTML 속성 이름 (예: "data-select-item-template")
10
- */
11
- export declare function createItemTemplate<TArgs extends unknown[]>(dataAttr: string): {
12
- TemplateSlot: (props: {
13
- children(...args: TArgs): JSX.Element;
14
- }) => JSX.Element;
15
- getTemplate: (slotElements: Element[]) => ((...args: TArgs) => JSX.Element) | undefined;
16
- };
17
- //# sourceMappingURL=createItemTemplate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createItemTemplate.d.ts","sourceRoot":"","sources":["..\\..\\src\\hooks\\createItemTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,OAAO,EAAE,EACxD,QAAQ,EAAE,MAAM,GACf;IACD,YAAY,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,GAAG,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAAA;KAAE,KAAK,GAAG,CAAC,OAAO,CAAC;IAChF,WAAW,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;CACzF,CAyBA"}
@@ -1,40 +0,0 @@
1
- import { template as _$template } from "solid-js/web";
2
- import { use as _$use } from "solid-js/web";
3
- import { spread as _$spread } from "solid-js/web";
4
- import { mergeProps as _$mergeProps } from "solid-js/web";
5
- var _tmpl$ = /* @__PURE__ */ _$template(`<span>`);
6
- function createItemTemplate(dataAttr) {
7
- const templateFnMap = /* @__PURE__ */ new WeakMap();
8
- function TemplateSlot(props) {
9
- return (() => {
10
- var _el$ = _tmpl$();
11
- _$use((el) => {
12
- templateFnMap.set(el, props.children);
13
- }, _el$);
14
- _$spread(_el$, _$mergeProps({
15
- [dataAttr]: true
16
- }, {
17
- "style": {
18
- display: "none"
19
- }
20
- }), false, false);
21
- return _el$;
22
- })();
23
- }
24
- function getTemplate(slotElements) {
25
- if (slotElements.length === 0) return void 0;
26
- const el = slotElements[0];
27
- if (el instanceof HTMLElement) {
28
- return templateFnMap.get(el);
29
- }
30
- return void 0;
31
- }
32
- return {
33
- TemplateSlot,
34
- getTemplate
35
- };
36
- }
37
- export {
38
- createItemTemplate
39
- };
40
- //# sourceMappingURL=createItemTemplate.js.map
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/hooks/createItemTemplate.tsx"],
4
- "mappings": ";;;;;AAWO,SAASA,mBACdC,UAIA;AACA,QAAMC,gBAAgB,oBAAIC,QAAsD;AAEhF,WAASC,aAAaC,OAA+D;AACnF,YAAA,MAAA;AAAA,UAAAC,OAAAC,OAAA;AAAAC,YAEUC,QAAO;AACXP,sBAAcQ,IAAID,IAAIJ,MAAMM,QAAQ;MACtC,GAACL,IAAA;AAAAM,eAAAN,MAAAO,aACG;QAAE,CAACZ,QAAQ,GAAG;MAAK,GAAC;QAAA,SACjB;UAAEa,SAAS;QAAO;MAAC,CAAA,GAAA,OAAA,KAAA;AAAA,aAAAR;IAAA,GAAA;EAGhC;AAEA,WAASS,YAAYC,cAAwE;AAC3F,QAAIA,aAAaC,WAAW,EAAG,QAAOC;AACtC,UAAMT,KAAKO,aAAa,CAAC;AACzB,QAAIP,cAAcU,aAAa;AAC7B,aAAOjB,cAAckB,IAAIX,EAAE;IAC7B;AACA,WAAOS;EACT;AAEA,SAAO;IAAEd;IAAcW;EAAY;AACrC;",
5
- "names": ["createItemTemplate", "dataAttr", "templateFnMap", "WeakMap", "TemplateSlot", "props", "_el$", "_tmpl$", "_$use", "el", "set", "children", "_$spread", "_$mergeProps", "display", "getTemplate", "slotElements", "length", "undefined", "HTMLElement", "get"]
6
- }
@@ -1,51 +0,0 @@
1
- import "@simplysm/core-common";
2
- import { type Accessor, createMemo } from "solid-js";
3
- import type { JSX } from "solid-js/jsx-runtime";
4
-
5
- /**
6
- * children을 slot 키 기준으로 분리하여 반환합니다.
7
- * SolidJS의 splitProps와 유사한 패턴으로 동작합니다.
8
- *
9
- * @param resolved - children(() => props.children)으로 생성된 resolved children
10
- * @param keys - 분리할 slot 키 배열 (camelCase, data 속성과 매칭)
11
- * @returns [slots, content] - slots는 각 키별 HTMLElement[], content는 나머지 JSX.Element[]
12
- *
13
- * @example
14
- * ```tsx
15
- * const resolved = children(() => props.children);
16
- * const [slots, content] = splitSlots(resolved, ["selectHeader", "selectAction"] as const);
17
- *
18
- * // JSX에서 사용
19
- * <div>{slots().selectHeader.single()}</div>
20
- * <div>{content()}</div>
21
- * ```
22
- */
23
- export function splitSlots<K extends string>(
24
- resolved: { toArray: () => unknown[] },
25
- keys: readonly K[],
26
- ): [Accessor<Record<K, HTMLElement[]>>, Accessor<JSX.Element[]>] {
27
- const memo = createMemo(() => {
28
- const arr = resolved.toArray();
29
- const result = Object.fromEntries(keys.map((k) => [k, []])) as unknown as Record<
30
- K,
31
- HTMLElement[]
32
- >;
33
- const content: JSX.Element[] = [];
34
-
35
- for (const c of arr) {
36
- if (c instanceof HTMLElement) {
37
- const matchedKey = keys.find((k) => k in c.dataset);
38
- if (matchedKey !== undefined) {
39
- result[matchedKey].push(c);
40
- continue;
41
- }
42
- }
43
- content.push(c as JSX.Element);
44
- }
45
-
46
- return { result, content };
47
- });
48
-
49
- // eslint-disable-next-line solid/reactivity -- 반환된 accessor는 JSX나 tracked scope에서 호출됨
50
- return [() => memo().result, () => memo().content];
51
- }
@@ -1,42 +0,0 @@
1
- import type { JSX } from "solid-js";
2
-
3
- /**
4
- * WeakMap 기반 템플릿 슬롯 패턴을 생성합니다. SolidJS children을 통해 렌더 함수를 전달할 때 사용합니다.
5
- *
6
- * Select와 Combobox의 ItemTemplate 서브 컴포넌트 패턴에서 사용됩니다.
7
- * TemplateSlot은 WeakMap에 렌더 함수를 ref로 저장하는 숨겨진 span을 렌더링합니다.
8
- * getTemplate은 resolved 슬롯 엘리먼트에서 렌더 함수를 가져옵니다.
9
- *
10
- * @param dataAttr - 숨겨진 span에 사용할 HTML 속성 이름 (예: "data-select-item-template")
11
- */
12
- export function createItemTemplate<TArgs extends unknown[]>(
13
- dataAttr: string,
14
- ): {
15
- TemplateSlot: (props: { children(...args: TArgs): JSX.Element }) => JSX.Element;
16
- getTemplate: (slotElements: Element[]) => ((...args: TArgs) => JSX.Element) | undefined;
17
- } {
18
- const templateFnMap = new WeakMap<HTMLElement, (...args: TArgs) => JSX.Element>();
19
-
20
- function TemplateSlot(props: { children(...args: TArgs): JSX.Element }): JSX.Element {
21
- return (
22
- <span
23
- ref={(el) => {
24
- templateFnMap.set(el, props.children);
25
- }}
26
- {...{ [dataAttr]: true }}
27
- style={{ display: "none" }}
28
- />
29
- );
30
- }
31
-
32
- function getTemplate(slotElements: Element[]): ((...args: TArgs) => JSX.Element) | undefined {
33
- if (slotElements.length === 0) return undefined;
34
- const el = slotElements[0];
35
- if (el instanceof HTMLElement) {
36
- return templateFnMap.get(el);
37
- }
38
- return undefined;
39
- }
40
-
41
- return { TemplateSlot, getTemplate };
42
- }