@simplysm/solid 13.0.55 → 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.
- package/README.md +3 -1
- package/dist/components/data/crud-detail/CrudDetail.d.ts +14 -0
- package/dist/components/data/crud-detail/CrudDetail.d.ts.map +1 -0
- package/dist/components/data/crud-detail/CrudDetail.js +348 -0
- package/dist/components/data/crud-detail/CrudDetail.js.map +6 -0
- package/dist/components/data/crud-detail/CrudDetailAfter.d.ts +7 -0
- package/dist/components/data/crud-detail/CrudDetailAfter.d.ts.map +1 -0
- package/dist/components/data/crud-detail/CrudDetailAfter.js +14 -0
- package/dist/components/data/crud-detail/CrudDetailAfter.js.map +6 -0
- package/dist/components/data/crud-detail/CrudDetailBefore.d.ts +7 -0
- package/dist/components/data/crud-detail/CrudDetailBefore.d.ts.map +1 -0
- package/dist/components/data/crud-detail/CrudDetailBefore.js +14 -0
- package/dist/components/data/crud-detail/CrudDetailBefore.js.map +6 -0
- package/dist/components/data/crud-detail/CrudDetailTools.d.ts +7 -0
- package/dist/components/data/crud-detail/CrudDetailTools.d.ts.map +1 -0
- package/dist/components/data/crud-detail/CrudDetailTools.js +14 -0
- package/dist/components/data/crud-detail/CrudDetailTools.js.map +6 -0
- package/dist/components/data/crud-detail/types.d.ts +45 -0
- package/dist/components/data/crud-detail/types.d.ts.map +1 -0
- package/dist/components/data/crud-detail/types.js +1 -0
- package/dist/components/data/crud-detail/types.js.map +6 -0
- package/dist/components/data/crud-sheet/CrudSheet.d.ts +17 -0
- package/dist/components/data/crud-sheet/CrudSheet.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/CrudSheet.js +679 -0
- package/dist/components/data/crud-sheet/CrudSheet.js.map +6 -0
- package/dist/components/data/crud-sheet/CrudSheetColumn.d.ts +5 -0
- package/dist/components/data/crud-sheet/CrudSheetColumn.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/CrudSheetColumn.js +29 -0
- package/dist/components/data/crud-sheet/CrudSheetColumn.js.map +6 -0
- package/dist/components/data/crud-sheet/CrudSheetFilter.d.ts +7 -0
- package/dist/components/data/crud-sheet/CrudSheetFilter.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/CrudSheetFilter.js +14 -0
- package/dist/components/data/crud-sheet/CrudSheetFilter.js.map +6 -0
- package/dist/components/data/crud-sheet/CrudSheetHeader.d.ts +7 -0
- package/dist/components/data/crud-sheet/CrudSheetHeader.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/CrudSheetHeader.js +14 -0
- package/dist/components/data/crud-sheet/CrudSheetHeader.js.map +6 -0
- package/dist/components/data/crud-sheet/CrudSheetTools.d.ts +7 -0
- package/dist/components/data/crud-sheet/CrudSheetTools.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/CrudSheetTools.js +14 -0
- package/dist/components/data/crud-sheet/CrudSheetTools.js.map +6 -0
- package/dist/components/data/crud-sheet/types.d.ts +109 -0
- package/dist/components/data/crud-sheet/types.d.ts.map +1 -0
- package/dist/components/data/crud-sheet/types.js +1 -0
- package/dist/components/data/crud-sheet/types.js.map +6 -0
- package/dist/components/data/kanban/Kanban.d.ts.map +1 -1
- package/dist/components/data/kanban/Kanban.js +137 -138
- package/dist/components/data/kanban/Kanban.js.map +2 -2
- package/dist/components/data/kanban/KanbanContext.d.ts +5 -1
- package/dist/components/data/kanban/KanbanContext.d.ts.map +1 -1
- package/dist/components/data/kanban/KanbanContext.js.map +1 -1
- package/dist/components/data/list/ListItem.d.ts.map +1 -1
- package/dist/components/data/list/ListItem.js +109 -99
- package/dist/components/data/list/ListItem.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.js +1 -1
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
- package/dist/components/disclosure/Dialog.d.ts +16 -10
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +126 -91
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/DialogContext.d.ts +2 -4
- 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 +14 -9
- package/dist/components/disclosure/DialogProvider.js.map +2 -2
- package/dist/components/disclosure/Dropdown.d.ts +46 -22
- package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
- package/dist/components/disclosure/Dropdown.js +100 -65
- package/dist/components/disclosure/Dropdown.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBanner.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBanner.js +3 -3
- 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 +84 -84
- package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts +6 -3
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +150 -168
- package/dist/components/form-control/combobox/Combobox.js.map +2 -2
- package/dist/components/form-control/combobox/ComboboxContext.d.ts +3 -0
- package/dist/components/form-control/combobox/ComboboxContext.d.ts.map +1 -1
- package/dist/components/form-control/combobox/ComboboxContext.js.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts +0 -2
- package/dist/components/form-control/date-range-picker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -17
- package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
- package/dist/components/form-control/field/Field.styles.d.ts.map +1 -1
- package/dist/components/form-control/field/Field.styles.js +2 -1
- package/dist/components/form-control/field/Field.styles.js.map +1 -1
- package/dist/components/form-control/field/NumberInput.d.ts +15 -5
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +181 -141
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts +9 -5
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +199 -154
- package/dist/components/form-control/field/TextInput.js.map +2 -2
- package/dist/components/form-control/select/Select.d.ts +3 -3
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js +116 -100
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/select/SelectContext.d.ts +9 -1
- package/dist/components/form-control/select/SelectContext.d.ts.map +1 -1
- package/dist/components/form-control/select/SelectContext.js.map +1 -1
- package/dist/components/form-control/select/SelectItem.d.ts.map +1 -1
- package/dist/components/form-control/select/SelectItem.js +77 -67
- package/dist/components/form-control/select/SelectItem.js.map +2 -2
- package/dist/components/layout/topbar/TopbarMenu.d.ts.map +1 -1
- package/dist/components/layout/topbar/TopbarMenu.js +63 -57
- package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
- package/dist/components/layout/topbar/TopbarUser.d.ts.map +1 -1
- package/dist/components/layout/topbar/TopbarUser.js +53 -54
- package/dist/components/layout/topbar/TopbarUser.js.map +2 -2
- package/dist/hooks/createControllableStore.d.ts +29 -0
- package/dist/hooks/createControllableStore.d.ts.map +1 -0
- package/dist/hooks/createControllableStore.js +19 -0
- package/dist/hooks/createControllableStore.js.map +6 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/styles/patterns.styles.d.ts.map +1 -1
- package/dist/styles/patterns.styles.js +7 -1
- package/dist/styles/patterns.styles.js.map +1 -1
- package/docs/data-components.md +428 -0
- package/docs/disclosure.md +65 -35
- package/docs/form-controls.md +18 -3
- package/docs/helpers.md +0 -39
- package/docs/hooks.md +39 -0
- package/package.json +4 -3
- package/src/components/data/crud-detail/CrudDetail.tsx +346 -0
- package/src/components/data/crud-detail/CrudDetailAfter.tsx +19 -0
- package/src/components/data/crud-detail/CrudDetailBefore.tsx +19 -0
- package/src/components/data/crud-detail/CrudDetailTools.tsx +19 -0
- package/src/components/data/crud-detail/types.ts +58 -0
- package/src/components/data/crud-sheet/CrudSheet.tsx +628 -0
- package/src/components/data/crud-sheet/CrudSheetColumn.tsx +34 -0
- package/src/components/data/crud-sheet/CrudSheetFilter.tsx +21 -0
- package/src/components/data/crud-sheet/CrudSheetHeader.tsx +19 -0
- package/src/components/data/crud-sheet/CrudSheetTools.tsx +21 -0
- package/src/components/data/crud-sheet/types.ts +133 -0
- package/src/components/data/kanban/Kanban.tsx +72 -65
- package/src/components/data/kanban/KanbanContext.ts +7 -1
- package/src/components/data/list/ListItem.tsx +31 -18
- package/src/components/data/sheet/DataSheet.styles.ts +1 -1
- package/src/components/data/sheet/DataSheet.tsx +1 -1
- package/src/components/disclosure/Dialog.tsx +143 -105
- package/src/components/disclosure/DialogContext.ts +2 -4
- package/src/components/disclosure/DialogProvider.tsx +4 -2
- package/src/components/disclosure/Dropdown.tsx +174 -86
- package/src/components/feedback/notification/NotificationBanner.tsx +3 -9
- package/src/components/feedback/notification/NotificationBell.tsx +51 -57
- package/src/components/form-control/combobox/Combobox.tsx +109 -134
- package/src/components/form-control/combobox/ComboboxContext.ts +4 -1
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +6 -16
- package/src/components/form-control/field/Field.styles.ts +1 -0
- package/src/components/form-control/field/NumberInput.tsx +131 -88
- package/src/components/form-control/field/TextInput.tsx +139 -88
- package/src/components/form-control/select/Select.tsx +85 -67
- package/src/components/form-control/select/SelectContext.ts +12 -1
- package/src/components/form-control/select/SelectItem.tsx +39 -18
- package/src/components/layout/topbar/TopbarMenu.tsx +52 -55
- package/src/components/layout/topbar/TopbarUser.tsx +28 -31
- package/src/hooks/createControllableStore.ts +47 -0
- package/src/index.ts +5 -1
- package/src/styles/patterns.styles.ts +7 -1
- package/tailwind.css +4 -0
- package/dist/helpers/splitSlots.d.ts +0 -25
- package/dist/helpers/splitSlots.d.ts.map +0 -1
- package/dist/helpers/splitSlots.js +0 -25
- package/dist/helpers/splitSlots.js.map +0 -6
- package/dist/hooks/createItemTemplate.d.ts +0 -17
- package/dist/hooks/createItemTemplate.d.ts.map +0 -1
- package/dist/hooks/createItemTemplate.js +0 -40
- package/dist/hooks/createItemTemplate.js.map +0 -6
- package/src/helpers/splitSlots.ts +0 -51
- package/src/hooks/createItemTemplate.tsx +0 -42
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
children,
|
|
3
|
-
createMemo,
|
|
4
|
-
createSignal,
|
|
5
|
-
For,
|
|
6
|
-
type JSX,
|
|
7
|
-
onCleanup,
|
|
8
|
-
Show,
|
|
9
|
-
splitProps,
|
|
10
|
-
} from "solid-js";
|
|
1
|
+
import { createMemo, createSignal, For, type JSX, onCleanup, Show, splitProps } from "solid-js";
|
|
11
2
|
import clsx from "clsx";
|
|
12
3
|
import { IconChevronDown, IconLoader2 } from "@tabler/icons-solidjs";
|
|
13
4
|
import { DebounceQueue } from "@simplysm/core-common";
|
|
14
5
|
import { Icon } from "../../display/Icon";
|
|
15
6
|
import { Dropdown } from "../../disclosure/Dropdown";
|
|
16
7
|
import { List } from "../../data/list/List";
|
|
17
|
-
import { ComboboxContext, type ComboboxContextValue } from "./ComboboxContext";
|
|
8
|
+
import { ComboboxContext, type ComboboxContextValue, useComboboxContext } from "./ComboboxContext";
|
|
18
9
|
import { ComboboxItem } from "./ComboboxItem";
|
|
19
10
|
import { ripple } from "../../../directives/ripple";
|
|
20
11
|
import { createControllableSignal } from "../../../hooks/createControllableSignal";
|
|
21
|
-
import { createItemTemplate } from "../../../hooks/createItemTemplate";
|
|
22
|
-
import { splitSlots } from "../../../helpers/splitSlots";
|
|
23
12
|
import { type ComponentSize, textMuted } from "../../../styles/tokens.styles";
|
|
24
13
|
import { chevronWrapperClass, getTriggerClass } from "../DropdownTrigger.styles";
|
|
25
14
|
import { Invalid } from "../Invalid";
|
|
@@ -36,8 +25,18 @@ const inputClass = clsx(
|
|
|
36
25
|
|
|
37
26
|
const noResultsClass = clsx("px-3 py-2", textMuted);
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
/**
|
|
29
|
+
* 아이템 템플릿 서브 컴포넌트
|
|
30
|
+
*/
|
|
31
|
+
const ComboboxItemTemplate = <TArgs extends unknown[]>(props: {
|
|
32
|
+
children: (...args: TArgs) => JSX.Element;
|
|
33
|
+
}) => {
|
|
34
|
+
const ctx = useComboboxContext();
|
|
35
|
+
// eslint-disable-next-line solid/reactivity -- 렌더 함수를 signal에 저장, JSX tracked scope에서 호출됨
|
|
36
|
+
ctx.setItemTemplate(props.children as (...args: unknown[]) => JSX.Element);
|
|
37
|
+
onCleanup(() => ctx.setItemTemplate(undefined));
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
41
40
|
|
|
42
41
|
// Props 정의
|
|
43
42
|
export interface ComboboxProps<TValue = unknown> {
|
|
@@ -150,8 +149,6 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
150
149
|
"touchMode",
|
|
151
150
|
]);
|
|
152
151
|
|
|
153
|
-
let triggerRef!: HTMLDivElement;
|
|
154
|
-
|
|
155
152
|
// 상태
|
|
156
153
|
const [open, setOpen] = createSignal(false);
|
|
157
154
|
const [query, setQuery] = createSignal("");
|
|
@@ -190,11 +187,19 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
190
187
|
setOpen(false);
|
|
191
188
|
};
|
|
192
189
|
|
|
190
|
+
// 아이템 템플릿 signal
|
|
191
|
+
const [itemTemplate, _setItemTemplate] = createSignal<
|
|
192
|
+
((...args: unknown[]) => JSX.Element) | undefined
|
|
193
|
+
>();
|
|
194
|
+
const setItemTemplate = (fn: ((...args: unknown[]) => JSX.Element) | undefined) =>
|
|
195
|
+
_setItemTemplate(() => fn);
|
|
196
|
+
|
|
193
197
|
// Context 값
|
|
194
198
|
const contextValue: ComboboxContextValue<T> = {
|
|
195
199
|
isSelected,
|
|
196
200
|
selectValue,
|
|
197
201
|
closeDropdown,
|
|
202
|
+
setItemTemplate,
|
|
198
203
|
};
|
|
199
204
|
|
|
200
205
|
// 검색 실행
|
|
@@ -224,24 +229,11 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
224
229
|
}
|
|
225
230
|
};
|
|
226
231
|
|
|
227
|
-
//
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const target = e.target as HTMLElement;
|
|
233
|
-
if (target.tagName === "INPUT") {
|
|
234
|
-
if (!open()) {
|
|
235
|
-
setOpen(true);
|
|
236
|
-
performSearch(query());
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
// 다른 영역 클릭 시 토글
|
|
240
|
-
const wasOpen = open();
|
|
241
|
-
setOpen(!wasOpen);
|
|
242
|
-
if (!wasOpen) {
|
|
243
|
-
performSearch(query());
|
|
244
|
-
}
|
|
232
|
+
// Dropdown 열림/닫힘 변경 핸들러
|
|
233
|
+
const handleOpenChange = (isOpen: boolean) => {
|
|
234
|
+
setOpen(isOpen);
|
|
235
|
+
if (isOpen) {
|
|
236
|
+
performSearch(query());
|
|
245
237
|
}
|
|
246
238
|
};
|
|
247
239
|
|
|
@@ -283,123 +275,106 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
|
|
|
283
275
|
// 참고: 초기 검색은 handleTriggerClick에서 수행됨
|
|
284
276
|
// 입력 시에는 handleInput에서 performSearch가 호출됨
|
|
285
277
|
|
|
286
|
-
//
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
const [slots, childItems] = splitSlots(resolved, ["comboboxItemTemplate"] as const);
|
|
290
|
-
|
|
291
|
-
// itemTemplate 함수 추출
|
|
292
|
-
const getItemTemplate = (): ((item: T, index: number) => JSX.Element) | undefined => {
|
|
293
|
-
return getComboboxItemTemplate(slots().comboboxItemTemplate) as
|
|
294
|
-
| ((item: T, index: number) => JSX.Element)
|
|
295
|
-
| undefined;
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
// 선택된 값 또는 입력 표시
|
|
299
|
-
const renderDisplayContent = (): JSX.Element => {
|
|
300
|
-
const currentValue = getValue();
|
|
301
|
-
|
|
302
|
-
// 드롭다운이 열려있거나 값이 없으면 입력 필드 표시
|
|
303
|
-
if (open() || currentValue === undefined) {
|
|
304
|
-
return (
|
|
305
|
-
<input
|
|
306
|
-
ref={(el) => {
|
|
307
|
-
// 드롭다운이 열릴 때 input에 포커스
|
|
308
|
-
if (open()) {
|
|
309
|
-
requestAnimationFrame(() => el.focus());
|
|
310
|
-
}
|
|
311
|
-
}}
|
|
312
|
-
type="text"
|
|
313
|
-
class={inputClass}
|
|
314
|
-
value={query()}
|
|
315
|
-
placeholder={currentValue === undefined ? local.placeholder : undefined}
|
|
316
|
-
disabled={local.disabled}
|
|
317
|
-
autocomplete="one-time-code"
|
|
318
|
-
onInput={handleInput}
|
|
319
|
-
/>
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// 값이 있고 드롭다운이 닫혀있으면 값 표시
|
|
324
|
-
return <div class="truncate">{local.renderValue(currentValue)}</div>;
|
|
325
|
-
};
|
|
278
|
+
// 선택된 값 또는 입력 표시
|
|
279
|
+
const renderDisplayContent = (): JSX.Element => {
|
|
280
|
+
const currentValue = getValue();
|
|
326
281
|
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
|
|
282
|
+
// 드롭다운이 열려있거나 값이 없으면 입력 필드 표시
|
|
283
|
+
if (open() || currentValue === undefined) {
|
|
284
|
+
return (
|
|
285
|
+
<input
|
|
286
|
+
ref={(el) => {
|
|
287
|
+
// 드롭다운이 열릴 때 input에 포커스
|
|
288
|
+
if (open()) {
|
|
289
|
+
requestAnimationFrame(() => el.focus());
|
|
290
|
+
}
|
|
291
|
+
}}
|
|
292
|
+
type="text"
|
|
293
|
+
class={inputClass}
|
|
294
|
+
value={query()}
|
|
295
|
+
placeholder={currentValue === undefined ? local.placeholder : undefined}
|
|
296
|
+
disabled={local.disabled}
|
|
297
|
+
autocomplete="one-time-code"
|
|
298
|
+
onInput={handleInput}
|
|
299
|
+
/>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
330
302
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
303
|
+
// 값이 있고 드롭다운이 닫혀있으면 값 표시
|
|
304
|
+
return <div class="truncate">{local.renderValue(currentValue)}</div>;
|
|
305
|
+
};
|
|
335
306
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
return <>{resolvedChildren}</>;
|
|
340
|
-
}
|
|
307
|
+
// 아이템 렌더링
|
|
308
|
+
const renderItems = (): JSX.Element => {
|
|
309
|
+
const template = itemTemplate() as ((item: T, index: number) => JSX.Element) | undefined;
|
|
341
310
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
311
|
+
// 로딩 중
|
|
312
|
+
if (busyCount() > 0) {
|
|
313
|
+
return <div class={noResultsClass}>검색 중...</div>;
|
|
314
|
+
}
|
|
346
315
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
{(item, index) => (
|
|
352
|
-
<ComboboxItem value={item}>{itemTemplate(item, index())}</ComboboxItem>
|
|
353
|
-
)}
|
|
354
|
-
</For>
|
|
355
|
-
);
|
|
356
|
-
}
|
|
316
|
+
// items가 비어있는 경우
|
|
317
|
+
if (items().length === 0) {
|
|
318
|
+
return <div class={noResultsClass}>검색 결과가 없습니다</div>;
|
|
319
|
+
}
|
|
357
320
|
|
|
358
|
-
|
|
321
|
+
// ItemTemplate 방식
|
|
322
|
+
if (template) {
|
|
359
323
|
return (
|
|
360
324
|
<For each={items()}>
|
|
361
|
-
{(item) => <ComboboxItem value={item}>{
|
|
325
|
+
{(item, index) => <ComboboxItem value={item}>{template(item, index())}</ComboboxItem>}
|
|
362
326
|
</For>
|
|
363
327
|
);
|
|
364
|
-
}
|
|
328
|
+
}
|
|
365
329
|
|
|
330
|
+
// 기본 렌더링
|
|
366
331
|
return (
|
|
367
|
-
<
|
|
368
|
-
<div
|
|
369
|
-
ref={triggerRef}
|
|
370
|
-
use:ripple={!local.disabled}
|
|
371
|
-
role="combobox"
|
|
372
|
-
aria-haspopup="listbox"
|
|
373
|
-
aria-expanded={open()}
|
|
374
|
-
aria-disabled={local.disabled || undefined}
|
|
375
|
-
aria-required={local.required || undefined}
|
|
376
|
-
tabIndex={local.disabled ? -1 : 0}
|
|
377
|
-
class={getTriggerClassName()}
|
|
378
|
-
style={local.style}
|
|
379
|
-
onClick={handleTriggerClick}
|
|
380
|
-
onKeyDown={handleTriggerKeyDown}
|
|
381
|
-
>
|
|
382
|
-
<div class={selectedValueClass}>{renderDisplayContent()}</div>
|
|
383
|
-
<div class={chevronWrapperClass}>
|
|
384
|
-
<Show when={busyCount() > 0} fallback={<Icon icon={IconChevronDown} size="1em" />}>
|
|
385
|
-
<Icon icon={IconLoader2} size="1em" class="animate-spin" />
|
|
386
|
-
</Show>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
389
|
-
|
|
390
|
-
<Dropdown triggerRef={() => triggerRef} open={open()} onOpenChange={setOpen} keyboardNav>
|
|
391
|
-
<List inset role="listbox">
|
|
392
|
-
{renderItems()}
|
|
393
|
-
</List>
|
|
394
|
-
</Dropdown>
|
|
395
|
-
</div>
|
|
332
|
+
<For each={items()}>{(item) => <ComboboxItem value={item}>{String(item)}</ComboboxItem>}</For>
|
|
396
333
|
);
|
|
397
334
|
};
|
|
398
335
|
|
|
399
336
|
return (
|
|
400
337
|
<Invalid message={errorMsg()} variant="border" touchMode={local.touchMode}>
|
|
401
338
|
<ComboboxContext.Provider value={contextValue as ComboboxContextValue}>
|
|
402
|
-
<
|
|
339
|
+
<div {...rest} data-combobox class={local.inset ? "flex" : "inline-flex"}>
|
|
340
|
+
<Dropdown
|
|
341
|
+
disabled={local.disabled}
|
|
342
|
+
open={open()}
|
|
343
|
+
onOpenChange={handleOpenChange}
|
|
344
|
+
keyboardNav
|
|
345
|
+
>
|
|
346
|
+
<Dropdown.Trigger>
|
|
347
|
+
<div
|
|
348
|
+
use:ripple={!local.disabled}
|
|
349
|
+
role="combobox"
|
|
350
|
+
aria-haspopup="listbox"
|
|
351
|
+
aria-expanded={open()}
|
|
352
|
+
aria-disabled={local.disabled || undefined}
|
|
353
|
+
aria-required={local.required || undefined}
|
|
354
|
+
tabIndex={local.disabled ? -1 : 0}
|
|
355
|
+
class={getTriggerClassName()}
|
|
356
|
+
style={local.style}
|
|
357
|
+
onKeyDown={handleTriggerKeyDown}
|
|
358
|
+
>
|
|
359
|
+
<div class={selectedValueClass}>{renderDisplayContent()}</div>
|
|
360
|
+
<div class={chevronWrapperClass}>
|
|
361
|
+
<Show
|
|
362
|
+
when={busyCount() > 0}
|
|
363
|
+
fallback={<Icon icon={IconChevronDown} size="1em" />}
|
|
364
|
+
>
|
|
365
|
+
<Icon icon={IconLoader2} size="1em" class="animate-spin" />
|
|
366
|
+
</Show>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
</Dropdown.Trigger>
|
|
370
|
+
<Dropdown.Content>
|
|
371
|
+
<List inset role="listbox">
|
|
372
|
+
{local.children}
|
|
373
|
+
{renderItems()}
|
|
374
|
+
</List>
|
|
375
|
+
</Dropdown.Content>
|
|
376
|
+
</Dropdown>
|
|
377
|
+
</div>
|
|
403
378
|
</ComboboxContext.Provider>
|
|
404
379
|
</Invalid>
|
|
405
380
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext } from "solid-js";
|
|
1
|
+
import { type JSX, createContext, useContext } from "solid-js";
|
|
2
2
|
|
|
3
3
|
export interface ComboboxContextValue<TValue = unknown> {
|
|
4
4
|
/** 값이 선택되어 있는지 확인 */
|
|
@@ -9,6 +9,9 @@ export interface ComboboxContextValue<TValue = unknown> {
|
|
|
9
9
|
|
|
10
10
|
/** 드롭다운 닫기 */
|
|
11
11
|
closeDropdown: () => void;
|
|
12
|
+
|
|
13
|
+
/** 아이템 템플릿 등록 */
|
|
14
|
+
setItemTemplate: (fn: ((...args: unknown[]) => JSX.Element) | undefined) => void;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export const ComboboxContext = createContext<ComboboxContextValue>();
|
|
@@ -39,9 +39,6 @@ export interface DateRangePickerProps {
|
|
|
39
39
|
/** 사이즈 */
|
|
40
40
|
size?: FieldSize;
|
|
41
41
|
|
|
42
|
-
/** 기간 타입 라벨 (기본값: { day: "일", month: "월", range: "범위" }) */
|
|
43
|
-
periodLabels?: Partial<Record<DateRangePeriodType, string>>;
|
|
44
|
-
|
|
45
42
|
/** 커스텀 class */
|
|
46
43
|
class?: string;
|
|
47
44
|
|
|
@@ -90,19 +87,10 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
90
87
|
"required",
|
|
91
88
|
"disabled",
|
|
92
89
|
"size",
|
|
93
|
-
"periodLabels",
|
|
94
90
|
"class",
|
|
95
91
|
"style",
|
|
96
92
|
]);
|
|
97
93
|
|
|
98
|
-
// 기간 타입 라벨
|
|
99
|
-
const labels = (): Record<DateRangePeriodType, string> => ({
|
|
100
|
-
day: "일",
|
|
101
|
-
month: "월",
|
|
102
|
-
range: "범위",
|
|
103
|
-
...local.periodLabels,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
94
|
// controlled/uncontrolled 패턴
|
|
107
95
|
const [periodType, setPeriodType] = createControllableSignal({
|
|
108
96
|
value: () => local.periodType ?? ("range" as DateRangePeriodType),
|
|
@@ -170,15 +158,17 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
|
|
|
170
158
|
<Select
|
|
171
159
|
value={periodType()}
|
|
172
160
|
onValueChange={handlePeriodTypeChange}
|
|
173
|
-
renderValue={(v: DateRangePeriodType) =>
|
|
161
|
+
renderValue={(v: DateRangePeriodType) => (
|
|
162
|
+
<>{{ day: "일", month: "월", range: "범위" }[v]}</>
|
|
163
|
+
)}
|
|
174
164
|
required
|
|
175
165
|
disabled={local.disabled}
|
|
176
166
|
size={local.size}
|
|
177
167
|
inset
|
|
178
168
|
>
|
|
179
|
-
<Select.Item value={"day" as DateRangePeriodType}
|
|
180
|
-
<Select.Item value={"month" as DateRangePeriodType}
|
|
181
|
-
<Select.Item value={"range" as DateRangePeriodType}
|
|
169
|
+
<Select.Item value={"day" as DateRangePeriodType}>일</Select.Item>
|
|
170
|
+
<Select.Item value={"month" as DateRangePeriodType}>월</Select.Item>
|
|
171
|
+
<Select.Item value={"range" as DateRangePeriodType}>범위</Select.Item>
|
|
182
172
|
</Select>
|
|
183
173
|
|
|
184
174
|
<Show
|