@thewrong/ui 0.1.0
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 +65 -0
- package/dist/index.cjs.js +40 -0
- package/dist/index.es.js +8066 -0
- package/dist/src/components/_shared/form-size-tokens.d.ts +16 -0
- package/dist/src/components/action-toast/ActionToast.d.ts +56 -0
- package/dist/src/components/action-toast/index.d.ts +2 -0
- package/dist/src/components/animated-height/AnimatedHeight.d.ts +30 -0
- package/dist/src/components/animated-height/index.d.ts +2 -0
- package/dist/src/components/badge/Badge.d.ts +2 -0
- package/dist/src/components/badge/index.d.ts +2 -0
- package/dist/src/components/badge/types.d.ts +56 -0
- package/dist/src/components/badge/utils.d.ts +13 -0
- package/dist/src/components/button/Button.d.ts +2 -0
- package/dist/src/components/button/index.d.ts +2 -0
- package/dist/src/components/button/types.d.ts +22 -0
- package/dist/src/components/button/utils.d.ts +6 -0
- package/dist/src/components/checkbox/Checkbox.d.ts +33 -0
- package/dist/src/components/checkbox/index.d.ts +2 -0
- package/dist/src/components/checkbox/types.d.ts +33 -0
- package/dist/src/components/checkbox/utils.d.ts +33 -0
- package/dist/src/components/collapsible/Collapsible.d.ts +36 -0
- package/dist/src/components/collapsible/index.d.ts +2 -0
- package/dist/src/components/date-input/DateInput.d.ts +27 -0
- package/dist/src/components/date-input/index.d.ts +1 -0
- package/dist/src/components/date-picker/date-picker.d.ts +34 -0
- package/dist/src/components/date-picker/date-range-picker.d.ts +21 -0
- package/dist/src/components/date-picker/index.d.ts +5 -0
- package/dist/src/components/date-picker/month-picker.d.ts +25 -0
- package/dist/src/components/drawer/Drawer.d.ts +18 -0
- package/dist/src/components/drawer/index.d.ts +2 -0
- package/dist/src/components/info-tooltip/InfoTooltip.d.ts +11 -0
- package/dist/src/components/info-tooltip/index.d.ts +2 -0
- package/dist/src/components/input/Input.d.ts +10 -0
- package/dist/src/components/input/PasswordInput.d.ts +8 -0
- package/dist/src/components/input/format.d.ts +38 -0
- package/dist/src/components/input/index.d.ts +4 -0
- package/dist/src/components/input/types.d.ts +131 -0
- package/dist/src/components/input/utils.d.ts +17 -0
- package/dist/src/components/loading-spinner/LoadingSpinner.d.ts +16 -0
- package/dist/src/components/loading-spinner/index.d.ts +2 -0
- package/dist/src/components/modal/Modal.d.ts +51 -0
- package/dist/src/components/modal/ModalSubView.d.ts +61 -0
- package/dist/src/components/modal/StandardModal.d.ts +59 -0
- package/dist/src/components/modal/index.d.ts +6 -0
- package/dist/src/components/page-title/PageTitle.d.ts +17 -0
- package/dist/src/components/page-title/index.d.ts +1 -0
- package/dist/src/components/popover/Popover.d.ts +28 -0
- package/dist/src/components/popover/index.d.ts +2 -0
- package/dist/src/components/search-box/ExactMatchToggle.d.ts +14 -0
- package/dist/src/components/search-box/SearchBox.d.ts +35 -0
- package/dist/src/components/search-box/SearchBoxChips.d.ts +12 -0
- package/dist/src/components/search-box/SearchBoxDateRange.d.ts +20 -0
- package/dist/src/components/search-box/SearchBoxDateSingle.d.ts +17 -0
- package/dist/src/components/search-box/SearchBoxField.d.ts +11 -0
- package/dist/src/components/search-box/SearchBoxFloatingInput.d.ts +24 -0
- package/dist/src/components/search-box/SearchBoxFloatingSelect.d.ts +19 -0
- package/dist/src/components/search-box/SearchBoxMonth.d.ts +14 -0
- package/dist/src/components/search-box/SearchBoxMultiSelect.d.ts +25 -0
- package/dist/src/components/search-box/SearchBoxSheetContext.d.ts +8 -0
- package/dist/src/components/search-box/dateRangePresets.d.ts +10 -0
- package/dist/src/components/search-box/index.d.ts +5 -0
- package/dist/src/components/search-box/parseDateRange.d.ts +15 -0
- package/dist/src/components/search-box/parseSearchValues.d.ts +38 -0
- package/dist/src/components/search-box/types.d.ts +67 -0
- package/dist/src/components/search-box/useSearchBoxState.d.ts +30 -0
- package/dist/src/components/select/MultiSelect.d.ts +69 -0
- package/dist/src/components/select/Select.d.ts +81 -0
- package/dist/src/components/select/index.d.ts +4 -0
- package/dist/src/components/select/loading-dots.d.ts +9 -0
- package/dist/src/components/select/types.d.ts +141 -0
- package/dist/src/components/select/utils.d.ts +16 -0
- package/dist/src/components/switch/Switch.d.ts +17 -0
- package/dist/src/components/switch/index.d.ts +2 -0
- package/dist/src/components/switch/types.d.ts +10 -0
- package/dist/src/components/switch/utils.d.ts +14 -0
- package/dist/src/components/table/accordion-table.d.ts +31 -0
- package/dist/src/components/table/column-group-utils.d.ts +49 -0
- package/dist/src/components/table/components/ColumnPresetSelector.d.ts +36 -0
- package/dist/src/components/table/components/ColumnSettingsTable.d.ts +25 -0
- package/dist/src/components/table/components/KeyboardNavButton.d.ts +12 -0
- package/dist/src/components/table/components/PageJumpInput.d.ts +16 -0
- package/dist/src/components/table/components/Pagination.d.ts +38 -0
- package/dist/src/components/table/components/PaginationFooter.d.ts +28 -0
- package/dist/src/components/table/components/SortableHeaderCell.d.ts +27 -0
- package/dist/src/components/table/hooks/useColumnPresets.d.ts +48 -0
- package/dist/src/components/table/hooks/useColumnResize.d.ts +99 -0
- package/dist/src/components/table/hooks/useFillEmptyRows.d.ts +51 -0
- package/dist/src/components/table/hooks/useInfiniteScroll.d.ts +58 -0
- package/dist/src/components/table/hooks/useTableColumnState.d.ts +30 -0
- package/dist/src/components/table/hooks/useTableDragSelection.d.ts +35 -0
- package/dist/src/components/table/hooks/useTableSort.d.ts +47 -0
- package/dist/src/components/table/hooks/useVirtualTable.d.ts +49 -0
- package/dist/src/components/table/index.d.ts +27 -0
- package/dist/src/components/table/mini-table.d.ts +44 -0
- package/dist/src/components/table/paginated-mini-table.d.ts +28 -0
- package/dist/src/components/table/paginated-table.d.ts +8 -0
- package/dist/src/components/table/table.d.ts +10 -0
- package/dist/src/components/table/types.d.ts +409 -0
- package/dist/src/components/table/utils.d.ts +47 -0
- package/dist/src/components/table-checkbox/TableCheckbox.d.ts +16 -0
- package/dist/src/components/table-checkbox/index.d.ts +1 -0
- package/dist/src/components/table-page-layout/TablePageLayout.d.ts +22 -0
- package/dist/src/components/table-page-layout/index.d.ts +1 -0
- package/dist/src/components/textarea/Textarea.d.ts +10 -0
- package/dist/src/components/textarea/index.d.ts +2 -0
- package/dist/src/components/textarea/types.d.ts +38 -0
- package/dist/src/components/toast/ToastProvider.d.ts +26 -0
- package/dist/src/components/toast/index.d.ts +3 -0
- package/dist/src/components/toolbar/Toolbar.d.ts +114 -0
- package/dist/src/components/toolbar/index.d.ts +2 -0
- package/dist/src/components/tooltip/Tooltip.d.ts +18 -0
- package/dist/src/components/tooltip/index.d.ts +2 -0
- package/dist/src/hooks/index.d.ts +4 -0
- package/dist/src/hooks/useBottomSheetDrag.d.ts +41 -0
- package/dist/src/hooks/useClickOutside.d.ts +16 -0
- package/dist/src/hooks/useMediaQuery.d.ts +15 -0
- package/dist/src/hooks/useScrollLock.d.ts +8 -0
- package/dist/src/index.d.ts +27 -0
- package/dist/src/lib/Portal.d.ts +12 -0
- package/dist/src/lib/column-preset-storage.d.ts +54 -0
- package/dist/src/lib/index.d.ts +6 -0
- package/dist/src/lib/overlay-stack.d.ts +13 -0
- package/dist/src/lib/utils.d.ts +11 -0
- package/dist/ui.css +3 -0
- package/package.json +128 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dateRange 필드 직렬화 헬퍼.
|
|
3
|
+
*
|
|
4
|
+
* SearchValues는 평면 `Record<string, string>`이라 from/to 두 값을 단일 키에 묶어야 한다.
|
|
5
|
+
* 형식: `"from~to"`. 한쪽만 있어도 OK (`"~2026-05-06"`, `"2026-05-01~"`).
|
|
6
|
+
* 빈 문자열은 미입력.
|
|
7
|
+
*/
|
|
8
|
+
export interface DateRangeValue {
|
|
9
|
+
from: string;
|
|
10
|
+
to: string;
|
|
11
|
+
}
|
|
12
|
+
/** SearchValues 문자열 → { from, to } */
|
|
13
|
+
export declare function parseDateRangeValue(raw: string | undefined): DateRangeValue;
|
|
14
|
+
/** 양쪽 모두 빈 값이면 빈 문자열 (URL에서 자동 제거되도록). */
|
|
15
|
+
export declare function serializeDateRangeValue(from: string, to: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { DateRangeValue } from './parseDateRange';
|
|
2
|
+
import { SearchField, SearchValues } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* SearchValues를 type-aware하게 파싱한 결과.
|
|
5
|
+
* - text/select 필드: `string` 그대로 (빈 값이면 `""`)
|
|
6
|
+
* - multiSelect 필드: `string[]` 으로 split (CSV → array)
|
|
7
|
+
* - dateRange 필드: `{ from, to }` 객체 (한쪽만 있어도 OK, 둘 다 비면 빈 문자열)
|
|
8
|
+
*
|
|
9
|
+
* 호출부가 SearchBox의 직렬화 형식을 알 필요 없이 바로 API 파라미터로 사용 가능.
|
|
10
|
+
*/
|
|
11
|
+
export type ParsedSearchValues<TFields extends readonly SearchField[]> = {
|
|
12
|
+
[K in TFields[number] as K["key"]]: K["type"] extends "multiSelect" ? string[] : K["type"] extends "dateRange" ? DateRangeValue : string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* multiSelect의 CSV 값을 array로 변환. 빈 값이면 `[]`.
|
|
16
|
+
*
|
|
17
|
+
* SearchBox의 CSV 직렬화는 `Record<string, string>` 시그니처/URL 호환을 위한 내부 표현이고,
|
|
18
|
+
* 호출부는 array가 필요. 이 헬퍼로 매번 split 보일러플레이트를 줄인다.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseMultiSelectValue(value: string | undefined): string[];
|
|
21
|
+
/**
|
|
22
|
+
* SearchValues 전체를 fields 정의 기준으로 파싱.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const SEARCH_FIELDS = [
|
|
27
|
+
* { type: "text", key: "name", label: "이름" },
|
|
28
|
+
* { type: "multiSelect", key: "type", label: "유형", options: [...] },
|
|
29
|
+
* ] as const satisfies readonly SearchField[];
|
|
30
|
+
*
|
|
31
|
+
* const parsed = parseSearchValues(SEARCH_FIELDS, search);
|
|
32
|
+
* // ^? { name: string; type: string[] }
|
|
33
|
+
*
|
|
34
|
+
* // 그대로 axios에 전달 — split 보일러플레이트 없음.
|
|
35
|
+
* useApiQuery({ params: { name: parsed.name || undefined, type: parsed.type } });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseSearchValues<const TFields extends readonly SearchField[]>(fields: TFields, values: SearchValues): ParsedSearchValues<TFields>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SelectOption } from '../../../components/select';
|
|
2
|
+
/** 검색 필드 정의 — discriminated union. 새 타입은 여기에 추가. */
|
|
3
|
+
export type SearchField = SearchFieldText | SearchFieldSelect | SearchFieldMultiSelect | SearchFieldDateRange | SearchFieldDateSingle | SearchFieldMonth;
|
|
4
|
+
/**
|
|
5
|
+
* 검색 값 형태. key → 값(빈 문자열 = 미입력).
|
|
6
|
+
* - text/select: "값"
|
|
7
|
+
* - multiSelect: "값1,값2" (CSV 직렬화. URL/zod schema와의 호환을 위해 string 일관성 유지)
|
|
8
|
+
* - dateRange: "from~to" (둘 다 yyyy-MM-dd, 한쪽만 있어도 OK. 예: "2026-05-01~2026-05-06")
|
|
9
|
+
* - dateSingle: "yyyy-MM-dd" 단일 값
|
|
10
|
+
* - month: "yyyy-MM" 단일 값
|
|
11
|
+
*/
|
|
12
|
+
export type SearchValues = Record<string, string>;
|
|
13
|
+
interface SearchFieldCommon {
|
|
14
|
+
/** 결과 객체의 키. */
|
|
15
|
+
key: string;
|
|
16
|
+
/** 라벨 — 칩에서 prefix로 사용 가능. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** 폼 영역에서의 폭. 미지정 시 자동(grid) 분배. 단위는 tailwind w-* 또는 임의 className. */
|
|
19
|
+
className?: string;
|
|
20
|
+
/** true면 입력 UI/칩/parse/state 모든 곳에서 제외 — 권한 기반 가시성 분기에 사용. */
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface SearchFieldText extends SearchFieldCommon {
|
|
24
|
+
type: "text";
|
|
25
|
+
/** placeholder. 미지정 시 label. */
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
inputMode?: "text" | "numeric";
|
|
28
|
+
}
|
|
29
|
+
export interface SearchFieldSelect extends SearchFieldCommon {
|
|
30
|
+
type: "select";
|
|
31
|
+
options: SelectOption[];
|
|
32
|
+
/** placeholder(첫 옵션 자동 생성용). 미지정 시 "{label} 전체". */
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface SearchFieldMultiSelect extends SearchFieldCommon {
|
|
36
|
+
type: "multiSelect";
|
|
37
|
+
options: SelectOption[];
|
|
38
|
+
/** placeholder. 미지정 시 "{label} 선택". */
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
}
|
|
41
|
+
/** 날짜 범위 프리셋. label은 버튼 표기, range()는 호출 시점의 from/to(yyyy-MM-dd) 반환. */
|
|
42
|
+
export interface DateRangePreset {
|
|
43
|
+
label: string;
|
|
44
|
+
range: () => {
|
|
45
|
+
from: string;
|
|
46
|
+
to: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface SearchFieldDateRange extends SearchFieldCommon {
|
|
50
|
+
type: "dateRange";
|
|
51
|
+
/** 단일 key에 "from~to" CSV로 직렬화. parseSearchValues가 { from, to }로 풀어준다. */
|
|
52
|
+
presets?: DateRangePreset[];
|
|
53
|
+
}
|
|
54
|
+
/** 단일 날짜 프리셋. label은 버튼 표기, date()는 호출 시점의 yyyy-MM-dd 반환. */
|
|
55
|
+
export interface DateSinglePreset {
|
|
56
|
+
label: string;
|
|
57
|
+
date: () => string;
|
|
58
|
+
}
|
|
59
|
+
export interface SearchFieldDateSingle extends SearchFieldCommon {
|
|
60
|
+
type: "dateSingle";
|
|
61
|
+
/** yyyy-MM-dd 단일 값. parseSearchValues가 그대로 string으로 반환. */
|
|
62
|
+
presets?: DateSinglePreset[];
|
|
63
|
+
}
|
|
64
|
+
export interface SearchFieldMonth extends SearchFieldCommon {
|
|
65
|
+
type: "month";
|
|
66
|
+
}
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SearchField, SearchValues } from './types';
|
|
2
|
+
interface UseSearchBoxStateArgs {
|
|
3
|
+
fields: readonly SearchField[];
|
|
4
|
+
/** 외부에서 적용된 값. 외부가 commit한 값이라 내부 draft와 별개. */
|
|
5
|
+
values: SearchValues;
|
|
6
|
+
/** 사용자가 [검색]/Enter로 commit할 때 호출. */
|
|
7
|
+
onSearch: (next: SearchValues) => void;
|
|
8
|
+
/** [초기화] 호출. 미지정 시 빈 객체로 onSearch 호출. */
|
|
9
|
+
onClear?: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* SearchBox의 입력/적용 상태 관리.
|
|
13
|
+
* - draft: 사용자가 입력 중인 값 (외부에 노출 X)
|
|
14
|
+
* - values: 외부가 commit한 적용 값 (칩 표시·재적용 시 draft 동기화 기준)
|
|
15
|
+
*
|
|
16
|
+
* 핵심: **입력 즉시 onSearch 호출하지 않는다.** [검색] 버튼/Enter 시점에만 commit.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useSearchBoxState({ fields, values, onSearch, onClear, }: UseSearchBoxStateArgs): {
|
|
19
|
+
draft: SearchValues;
|
|
20
|
+
setFieldValue: (key: string, value: string) => void;
|
|
21
|
+
submit: () => boolean;
|
|
22
|
+
clear: () => void;
|
|
23
|
+
chips: {
|
|
24
|
+
key: string;
|
|
25
|
+
label: string;
|
|
26
|
+
valueLabel: string;
|
|
27
|
+
}[];
|
|
28
|
+
removeChip: (key: string) => void;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SelectCommonProps, SelectOption } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* MultiSelect의 search 관련 props discriminated union.
|
|
4
|
+
* `searchable=true`일 때만 검색 prop이 의미가 있다 — Select와 동일 패턴.
|
|
5
|
+
*/
|
|
6
|
+
type MultiSelectSearchProps = {
|
|
7
|
+
searchable?: false;
|
|
8
|
+
searchPlaceholder?: never;
|
|
9
|
+
onSearchChange?: never;
|
|
10
|
+
isSearchLoading?: never;
|
|
11
|
+
} | {
|
|
12
|
+
searchable: true;
|
|
13
|
+
/** 패널 검색 input placeholder. */
|
|
14
|
+
searchPlaceholder?: string;
|
|
15
|
+
/** 외부 검색(서버) 콜백. 제공 시 클라이언트 필터를 끄고 입력만 외부에 전달. */
|
|
16
|
+
onSearchChange?: (query: string) => void;
|
|
17
|
+
/** 외부 검색 로딩 상태. 패널 검색 input 옆 LoadingDots. */
|
|
18
|
+
isSearchLoading?: boolean;
|
|
19
|
+
};
|
|
20
|
+
type MultiSelectBaseProps = Omit<SelectCommonProps, "searchable" | "searchPlaceholder" | "onSearchChange" | "isSearchLoading"> & {
|
|
21
|
+
/** 선택 옵션 목록. */
|
|
22
|
+
options: SelectOption[];
|
|
23
|
+
/** 선택된 값들. 빈 배열이면 placeholder 노출. */
|
|
24
|
+
value: string[];
|
|
25
|
+
/** 값 변경 콜백. options 순서를 보존한 배열로 전달. */
|
|
26
|
+
onChange: (values: string[]) => void;
|
|
27
|
+
/** 트리거 추가 className. */
|
|
28
|
+
className?: string;
|
|
29
|
+
/** 드롭다운 패널 추가 className. */
|
|
30
|
+
panelClassName?: string;
|
|
31
|
+
/**
|
|
32
|
+
* 트리거에 보여줄 풀 텍스트 포맷터. 기본은 라벨을 콤마로 연결.
|
|
33
|
+
* 폭이 부족하면 자동으로 `formatCollapsed`로 폴백 (`disableAutoCollapse`로 끄기 가능).
|
|
34
|
+
*/
|
|
35
|
+
formatTrigger?: (selectedOptions: SelectOption[]) => string;
|
|
36
|
+
/**
|
|
37
|
+
* 폭 부족 시 폴백 텍스트 포맷터. 기본은 `${count}개 선택`.
|
|
38
|
+
* 호출부 사용 예: `(sel) => sel.length > 0 ? `${sel.length}건 선택` : ""`
|
|
39
|
+
*/
|
|
40
|
+
formatCollapsed?: (selectedOptions: SelectOption[]) => string;
|
|
41
|
+
/**
|
|
42
|
+
* 트리거 폭에 풀 텍스트가 안 들어갈 때 자동으로 `formatCollapsed`로 전환하는 동작 비활성화.
|
|
43
|
+
* 항상 풀 텍스트 + truncate ellipsis로 보고 싶을 때.
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
disableAutoCollapse?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 패널 상단에 "전체 선택/해제" 토글 버튼 노출.
|
|
49
|
+
* searchable 모드에서는 검색 결과(`filteredOptions`) 기준으로 동작.
|
|
50
|
+
* disabled 옵션은 자동 제외.
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
showSelectAll?: boolean;
|
|
54
|
+
/** id (label htmlFor 연결용). */
|
|
55
|
+
id?: string;
|
|
56
|
+
/** name (form 제출용 hidden input. CSV 직렬화). */
|
|
57
|
+
name?: string;
|
|
58
|
+
};
|
|
59
|
+
type MultiSelectProps = MultiSelectBaseProps & MultiSelectSearchProps;
|
|
60
|
+
/**
|
|
61
|
+
* 다중 선택 Select. 옵션 리스트에 체크박스를 표시하고 토글 방식으로 동작.
|
|
62
|
+
* 트리거/패널/슬롯/사이즈 정합은 단일 `Select`와 동일 (`shared/ui/input/utils` 공유).
|
|
63
|
+
*
|
|
64
|
+
* - searchable: 옵션 안 검색. `onSearchChange` 제공 시 외부 검색.
|
|
65
|
+
* - value는 string[]. options 순서를 보존해 emit.
|
|
66
|
+
* - 트리거에는 라벨을 콤마로 연결 — 길어지면 `formatTrigger`로 커스텀.
|
|
67
|
+
*/
|
|
68
|
+
export declare const MultiSelect: import('react').ForwardRefExoticComponent<MultiSelectProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { SelectCommonProps, SelectOption } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Select의 search 관련 props discriminated union.
|
|
4
|
+
* `searchable=true`일 때만 onSearchChange/isSearchLoading/onLoadMore/hasMore/searchDebounceMs/searchPlaceholder가 의미가 있다.
|
|
5
|
+
* 호출부가 `searchable=false`인데 검색 관련 prop을 넘기면 컴파일 에러로 차단.
|
|
6
|
+
*/
|
|
7
|
+
type SelectSearchProps = {
|
|
8
|
+
searchable?: false;
|
|
9
|
+
searchPlaceholder?: never;
|
|
10
|
+
onSearchChange?: never;
|
|
11
|
+
isSearchLoading?: never;
|
|
12
|
+
onLoadMore?: never;
|
|
13
|
+
hasMore?: never;
|
|
14
|
+
searchDebounceMs?: never;
|
|
15
|
+
} | {
|
|
16
|
+
searchable: true;
|
|
17
|
+
/** 트리거 input의 검색 placeholder. selected 있을 때 fallback으로 노출. */
|
|
18
|
+
searchPlaceholder?: string;
|
|
19
|
+
/** 외부 검색(서버) 콜백. 제공 시 클라이언트 필터를 끄고 입력만 외부에 전달. */
|
|
20
|
+
onSearchChange?: (query: string) => void;
|
|
21
|
+
/** 외부 검색 로딩 상태. true면 트리거 우측에 스피너 + 무한스크롤 sentinel 동작 가드. */
|
|
22
|
+
isSearchLoading?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 무한스크롤: 옵션 패널 끝에 도달하면 호출. 호출부가 다음 페이지 fetch + options append.
|
|
25
|
+
* `hasMore=true`일 때만 sentinel이 활성화되며, `isSearchLoading` 상태에서는 중복 호출 안 함.
|
|
26
|
+
*/
|
|
27
|
+
onLoadMore?: () => void;
|
|
28
|
+
/** 무한스크롤: 더 가져올 페이지가 있는지. true일 때만 sentinel 노출. */
|
|
29
|
+
hasMore?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* `onSearchChange` 호출 디바운스 (ms). 0 또는 false면 즉시 호출.
|
|
32
|
+
* 클라이언트 필터(`onSearchChange` 미제공)에는 영향 없음.
|
|
33
|
+
* @default 300
|
|
34
|
+
*/
|
|
35
|
+
searchDebounceMs?: number | false;
|
|
36
|
+
};
|
|
37
|
+
/** Select의 search 외 base props (SelectCommonProps에서 search 관련 제외). */
|
|
38
|
+
type SelectBaseProps = Omit<SelectCommonProps, "searchable" | "searchPlaceholder" | "onSearchChange" | "isSearchLoading"> & {
|
|
39
|
+
/** 선택 옵션 목록. */
|
|
40
|
+
options: SelectOption[];
|
|
41
|
+
/** 선택된 값. 제어 컴포넌트로 사용. 빈 문자열이면 placeholder 노출. */
|
|
42
|
+
value: string;
|
|
43
|
+
/** 값 변경 콜백. clearable로 비울 때도 빈 문자열로 호출. */
|
|
44
|
+
onChange: (value: string) => void;
|
|
45
|
+
/** 드롭다운 패널 추가 className. */
|
|
46
|
+
panelClassName?: string;
|
|
47
|
+
/** 트리거 추가 className. */
|
|
48
|
+
className?: string;
|
|
49
|
+
/** id (label htmlFor 연결용). */
|
|
50
|
+
id?: string;
|
|
51
|
+
/** name (form 제출용 hidden input). */
|
|
52
|
+
name?: string;
|
|
53
|
+
};
|
|
54
|
+
type SelectProps = SelectBaseProps & SelectSearchProps;
|
|
55
|
+
/**
|
|
56
|
+
* 단일 선택 Select. floating-ui 기반으로 트리거 폭과 패널 폭이 정합되며 a11y 표준 키보드 동작을 갖춘다.
|
|
57
|
+
*
|
|
58
|
+
* - 트리거 외관(슬롯/사이즈/variant)은 Input과 동일 토큰을 공유 (`shared/ui/input/utils`).
|
|
59
|
+
* - searchable: 옵션 안 검색 input. `onSearchChange` 제공 시 외부 검색(서버), 미제공 시 클라이언트 필터.
|
|
60
|
+
* - description/trailing은 옵션 리스트에서만 노출 — 트리거에는 label만.
|
|
61
|
+
*
|
|
62
|
+
* 자유 입력(옵션 외 값 허용)은 후속 `Autocomplete`로 분리.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```tsx
|
|
66
|
+
* <Select
|
|
67
|
+
* variant="box"
|
|
68
|
+
* options={[{ value: "kr", label: "한국" }]}
|
|
69
|
+
* value={value}
|
|
70
|
+
* onChange={setValue}
|
|
71
|
+
* placeholder="국가 선택"
|
|
72
|
+
* />
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* ref 타입은 trigger element를 가리킨다. searchable=false면 button, searchable=true면 input.
|
|
77
|
+
* 외부에서 보통 `.focus()` 정도만 사용하므로 union으로 정직하게 노출.
|
|
78
|
+
*/
|
|
79
|
+
export type SelectTriggerRef = HTMLButtonElement | HTMLInputElement;
|
|
80
|
+
export declare const Select: import('react').ForwardRefExoticComponent<SelectProps & import('react').RefAttributes<SelectTriggerRef>>;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 점 3개 점진적 페이드 로딩 인디케이터.
|
|
3
|
+
* 검색/페이지 fetch 중 부담 없는 시각 신호로 Select/MultiSelect 양쪽에서 공용.
|
|
4
|
+
*
|
|
5
|
+
* @keyframes는 tailwind animate-pulse를 stagger로 사용 — animationDelay만 inline.
|
|
6
|
+
*/
|
|
7
|
+
export declare const LoadingDots: ({ className }: {
|
|
8
|
+
className?: string;
|
|
9
|
+
}) => import("react").JSX.Element;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode, Ref } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Select 컴포넌트의 Variant 타입
|
|
4
|
+
*/
|
|
5
|
+
export type SelectVariant = "box" | "line" | "big" | "hero";
|
|
6
|
+
/**
|
|
7
|
+
* Select 컴포넌트의 사이즈. Button/Input/Textarea와 동일 토큰. box variant에서만 적용.
|
|
8
|
+
* - mini: 모바일/매우 좁은 영역의 다건 입력
|
|
9
|
+
* - small: 다건 입력/표 형식 기본
|
|
10
|
+
* - medium: 폼 단독 입력 기본
|
|
11
|
+
* - large: 메인 페이지의 강조 선택
|
|
12
|
+
*/
|
|
13
|
+
export type SelectSize = "mini" | "small" | "medium" | "large";
|
|
14
|
+
/**
|
|
15
|
+
* Select 컴포넌트의 Label 표시 방식 타입
|
|
16
|
+
*/
|
|
17
|
+
export type SelectLabelOption = "appear" | "sustain";
|
|
18
|
+
/**
|
|
19
|
+
* Select 컴포넌트의 공통 Props
|
|
20
|
+
*/
|
|
21
|
+
export interface SelectCommonProps {
|
|
22
|
+
/**
|
|
23
|
+
* Select 필드의 모양
|
|
24
|
+
*/
|
|
25
|
+
variant: SelectVariant;
|
|
26
|
+
/**
|
|
27
|
+
* Select 필드의 크기
|
|
28
|
+
* @default 'medium'
|
|
29
|
+
*/
|
|
30
|
+
selectSize?: SelectSize;
|
|
31
|
+
/**
|
|
32
|
+
* Select 필드의 상단의 라벨
|
|
33
|
+
*/
|
|
34
|
+
label?: string;
|
|
35
|
+
/**
|
|
36
|
+
* label 표시 방식
|
|
37
|
+
* 'appear': value가 있을 때만 label이 보여요
|
|
38
|
+
* 'sustain': 항상 label이 보여요
|
|
39
|
+
* @default 'sustain'
|
|
40
|
+
*/
|
|
41
|
+
labelOption?: SelectLabelOption;
|
|
42
|
+
/**
|
|
43
|
+
* Select 필드의 하단의 도움말
|
|
44
|
+
*/
|
|
45
|
+
help?: ReactNode;
|
|
46
|
+
/**
|
|
47
|
+
* placeholder 텍스트 (첫 번째 옵션의 라벨로 표시)
|
|
48
|
+
*/
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Select 필드의 에러 여부
|
|
52
|
+
* @default false
|
|
53
|
+
*/
|
|
54
|
+
hasError?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Select 필드의 비활성화 여부
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 트리거 텍스트 뒤에 붙는 단위 텍스트 (예: "원"). chevron 앞쪽 슬롯의 가장 좌측.
|
|
62
|
+
*/
|
|
63
|
+
suffix?: string;
|
|
64
|
+
/**
|
|
65
|
+
* 우측 트레일링 아이콘 (lucide-react 등). suffix 다음, clearable 앞.
|
|
66
|
+
*/
|
|
67
|
+
trailingIcon?: ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* 값이 있을 때 우측에 X 버튼(CircleX)을 노출. 클릭 시 onChange로 빈 값을 emit.
|
|
70
|
+
* disabled에서는 노출하지 않는다. trailingIcon 다음, badge 앞.
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
clearable?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* chevron 바로 앞에 표시할 뱃지/라벨 ReactNode.
|
|
76
|
+
*/
|
|
77
|
+
badge?: ReactNode;
|
|
78
|
+
/**
|
|
79
|
+
* 검색 기능 활성화 여부
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
searchable?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 검색 입력 필드 placeholder
|
|
85
|
+
* @default "검색..."
|
|
86
|
+
*/
|
|
87
|
+
searchPlaceholder?: string;
|
|
88
|
+
/**
|
|
89
|
+
* 검색어 변경 시 호출되는 콜백 (서버 필터링용)
|
|
90
|
+
* 이 콜백이 제공되면 클라이언트 필터링을 비활성화하고 외부에서 options를 업데이트해야 함
|
|
91
|
+
*/
|
|
92
|
+
onSearchChange?: (query: string) => void;
|
|
93
|
+
/**
|
|
94
|
+
* 서버 검색 중 로딩 상태
|
|
95
|
+
* @default false
|
|
96
|
+
*/
|
|
97
|
+
isSearchLoading?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* 컨테이너의 추가 props
|
|
100
|
+
*/
|
|
101
|
+
containerProps?: ComponentPropsWithoutRef<"div">;
|
|
102
|
+
/**
|
|
103
|
+
* 컨테이너의 ref
|
|
104
|
+
*/
|
|
105
|
+
containerRef?: Ref<HTMLDivElement>;
|
|
106
|
+
/**
|
|
107
|
+
* 테스트 ID (data-testid)
|
|
108
|
+
*/
|
|
109
|
+
"data-testid"?: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Select Option 타입
|
|
113
|
+
*/
|
|
114
|
+
export interface SelectOption {
|
|
115
|
+
value: string | number;
|
|
116
|
+
label: string;
|
|
117
|
+
/**
|
|
118
|
+
* 라벨 아래에 작게 표시되는 보조 설명. 두 줄 옵션이 필요할 때 사용.
|
|
119
|
+
* 트리거(닫힌 상태)에는 노출되지 않고 드롭다운 옵션 리스트에서만 보인다.
|
|
120
|
+
*/
|
|
121
|
+
description?: string;
|
|
122
|
+
/**
|
|
123
|
+
* 라벨 우측에 작게 표시되는 보조 정보. 잔고/금액 등 정렬해서 보여주고 싶을 때.
|
|
124
|
+
* 트리거에는 노출되지 않고 드롭다운 옵션 리스트에서만 보인다.
|
|
125
|
+
*/
|
|
126
|
+
trailing?: string;
|
|
127
|
+
disabled?: boolean;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Select 컴포넌트의 Props
|
|
131
|
+
*/
|
|
132
|
+
export interface SelectProps extends Omit<ComponentPropsWithoutRef<"select">, "color">, SelectCommonProps {
|
|
133
|
+
/**
|
|
134
|
+
* Select 옵션 목록
|
|
135
|
+
*/
|
|
136
|
+
options?: SelectOption[];
|
|
137
|
+
/**
|
|
138
|
+
* children으로 option을 직접 전달할 수도 있어요
|
|
139
|
+
*/
|
|
140
|
+
children?: ReactNode;
|
|
141
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SelectSize, SelectVariant } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Select Variant에 따른 컨테이너 클래스. 2026 리디자인 box variant는 Button/Input과 동일 토큰.
|
|
4
|
+
* line/big/hero는 레거시 — Input과 동일하게 추후 정리.
|
|
5
|
+
*/
|
|
6
|
+
export declare const getSelectVariantClasses: (variant: SelectVariant, hasError?: boolean, disabled?: boolean, size?: SelectSize) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Select의 텍스트 토큰 — Input과 동일한 색 위계.
|
|
9
|
+
* disabled / error / filled / placeholder 4단계.
|
|
10
|
+
*/
|
|
11
|
+
export declare const getSelectBaseClasses: (variant?: SelectVariant, hasError?: boolean, disabled?: boolean, filled?: boolean, size?: SelectSize) => string;
|
|
12
|
+
/** trailing chevron 색 — Input의 trailing icon과 동일 위계. */
|
|
13
|
+
export declare const getSelectTrailingIconColor: (hasError: boolean, disabled: boolean, filledOrFocused: boolean) => string;
|
|
14
|
+
export declare const getSelectContainerClasses: () => string;
|
|
15
|
+
export declare const getSelectLabelClasses: (_variant: SelectVariant, hasError: boolean) => string;
|
|
16
|
+
export declare const getSelectHelpClasses: (hasError: boolean) => string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SwitchProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* On/Off 토글 스위치.
|
|
4
|
+
*
|
|
5
|
+
* `<input type="checkbox">`를 시각적으로 가리고(`sr-only peer`) 트랙·노브를 그린다.
|
|
6
|
+
* 키보드(스페이스), 클릭, label 클릭 모두 native 동작 그대로 작동.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* <Switch
|
|
11
|
+
* checked={enabled}
|
|
12
|
+
* onCheckedChange={setEnabled}
|
|
13
|
+
* label="잔여한도 지급 기능 사용"
|
|
14
|
+
* />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const Switch: import('react').ForwardRefExoticComponent<SwitchProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InputHTMLAttributes } from 'react';
|
|
2
|
+
export type SwitchSize = "small" | "medium";
|
|
3
|
+
export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
|
|
4
|
+
/** 트랙·노브 사이즈. 기본 medium. */
|
|
5
|
+
size?: SwitchSize;
|
|
6
|
+
/** 우측 라벨. 지정하면 클릭 가능한 label로 감싸진다. */
|
|
7
|
+
label?: string;
|
|
8
|
+
/** 체크 상태 변경 콜백. onChange와 함께 호출된다. */
|
|
9
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SwitchSize } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 트랙(외곽) 사이즈 매핑.
|
|
4
|
+
* 노브는 트랙 안에서 padding 2px만큼 들어가 있고, ON 시 (트랙 width − 노브 width − padding × 2)만큼 우측 이동.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SWITCH_SIZE_MAP: Record<SwitchSize, {
|
|
7
|
+
track: string;
|
|
8
|
+
thumb: string;
|
|
9
|
+
translate: string;
|
|
10
|
+
}>;
|
|
11
|
+
/** 트랙(외곽 박스) 클래스. peer-checked로 ON/OFF 색 전환. */
|
|
12
|
+
export declare function getSwitchTrackClasses(size: SwitchSize, disabled: boolean): string;
|
|
13
|
+
/** 노브(원형) 클래스. translateX로 좌→우 이동. wrapper 기준 absolute로 트랙 위에 뜬다. */
|
|
14
|
+
export declare function getSwitchThumbClasses(size: SwitchSize): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { PaginatedTableProps } from './types';
|
|
3
|
+
export type ExpandedRowId = string | number;
|
|
4
|
+
export interface AccordionExpandable<T> {
|
|
5
|
+
/** 펼친 행 안에 그릴 콘텐츠 */
|
|
6
|
+
renderRow: (row: T) => ReactNode;
|
|
7
|
+
/** 현재 펼쳐진 행 id 집합 */
|
|
8
|
+
expandedIds: Set<ExpandedRowId>;
|
|
9
|
+
/**
|
|
10
|
+
* 토글 콜백. single/multiple 동작은 호출부에서 결정 — 컴포넌트는 단순히 행 토글 의도만 전달한다.
|
|
11
|
+
* - multiple: `setExpanded(prev => prev.has(id) ? new Set([...prev].filter(x => x !== id)) : new Set([...prev, id]))`
|
|
12
|
+
* - single: `setExpanded(prev => prev.has(id) ? new Set() : new Set([id]))`
|
|
13
|
+
*/
|
|
14
|
+
onToggle: (id: ExpandedRowId) => void;
|
|
15
|
+
/** 행 → 안정 식별자 */
|
|
16
|
+
getRowId: (row: T) => ExpandedRowId;
|
|
17
|
+
/**
|
|
18
|
+
* 펼침 콘텐츠가 가로스크롤에 따라 좌측에 sticky 하게 따라오게 할지 여부.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
stickyDetail?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface AccordionTableProps<T> extends PaginatedTableProps<T> {
|
|
24
|
+
/**
|
|
25
|
+
* 행 펼침 설정. 미지정 시 PaginatedTable과 동일하게 동작 (토글 컬럼/펼침 행 없음).
|
|
26
|
+
*/
|
|
27
|
+
expandable?: AccordionExpandable<T>;
|
|
28
|
+
}
|
|
29
|
+
export declare const AccordionTable: <T>(props: AccordionTableProps<T> & {
|
|
30
|
+
ref?: React.ForwardedRef<HTMLDivElement>;
|
|
31
|
+
}) => React.ReactElement;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TableColumn, TableColumnGroupMeta } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 슬롯(그룹 또는 단일 컬럼) 단위 표현.
|
|
4
|
+
*
|
|
5
|
+
* 옵션 2 정책의 핵심 — columnOrder/hiddenColumns가 다루는 단위는 슬롯이지 평면 컬럼이 아니다.
|
|
6
|
+
* - 그룹: 묶음 고정. 하위 컬럼 키들은 슬롯에 속하지만 columnOrder에는 들어가지 않는다.
|
|
7
|
+
* - 단일 컬럼: 슬롯과 컬럼이 1:1.
|
|
8
|
+
*/
|
|
9
|
+
export interface ColumnSlot<T> {
|
|
10
|
+
kind: "group" | "column";
|
|
11
|
+
/** 슬롯 키. 그룹키 또는 컬럼키. */
|
|
12
|
+
key: string;
|
|
13
|
+
header: TableColumn<T>["header"];
|
|
14
|
+
/** 그룹이면 하위 컬럼 배열, 단일 컬럼이면 자기 자신 한 개. */
|
|
15
|
+
leafColumns: TableColumn<T>[];
|
|
16
|
+
/** hideOnMobile: 그룹 메타의 옵션 또는 단일 컬럼의 hideOnMobile. */
|
|
17
|
+
hideOnMobile?: boolean;
|
|
18
|
+
/** 그룹 메타 원본 (그룹일 때만). */
|
|
19
|
+
group?: TableColumnGroupMeta;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 평면 컬럼 배열 + 그룹 메타를 받아 슬롯 단위로 묶는다.
|
|
23
|
+
*
|
|
24
|
+
* 그룹에 속한 컬럼들은 그룹 슬롯 1개로 합쳐지고, 속하지 않은 컬럼은 각자 슬롯이 된다.
|
|
25
|
+
* 그룹 내부 컬럼 순서는 `group.columnKeys` 순서대로 강제 — `columns` 배열 내 등장 순서와 다를 수 있다.
|
|
26
|
+
*
|
|
27
|
+
* 그룹 메타에 정의된 columnKey가 columns에 없으면 무시(방어).
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildColumnSlots<T>(columns: TableColumn<T>[], groups?: TableColumnGroupMeta[]): ColumnSlot<T>[];
|
|
30
|
+
/**
|
|
31
|
+
* 슬롯 키 배열을 columnState.columnOrder의 기본값으로 변환. (그룹키 또는 컬럼키)
|
|
32
|
+
*/
|
|
33
|
+
export declare function getDefaultSlotOrder<T>(slots: ColumnSlot<T>[]): string[];
|
|
34
|
+
/**
|
|
35
|
+
* columnOrder(슬롯 키 배열) + hiddenSlots를 적용해 가시 슬롯만 추려낸다.
|
|
36
|
+
* 정의에 `hidden: true`로 박힌 단일 컬럼도 함께 제거.
|
|
37
|
+
*
|
|
38
|
+
* columnOrder에 없는 신규 슬롯(저장된 프리셋 이후 추가된 컬럼/그룹)은 끝에 자동 append —
|
|
39
|
+
* useColumnPresets의 mergeColumnOrders가 effect로 합쳐주기 전 첫 렌더에서 빠지는 깜빡임을 막는다.
|
|
40
|
+
*/
|
|
41
|
+
export declare function applyColumnState<T>(slots: ColumnSlot<T>[], columnOrder: string[], hiddenSlotKeys: Set<string>): ColumnSlot<T>[];
|
|
42
|
+
/**
|
|
43
|
+
* 가시 슬롯 → 평면 leaf 컬럼 시퀀스 (tbody td 매핑/colgroup/너비계산에 사용).
|
|
44
|
+
*/
|
|
45
|
+
export declare function flattenLeafColumns<T>(visibleSlots: ColumnSlot<T>[]): TableColumn<T>[];
|
|
46
|
+
/**
|
|
47
|
+
* 가시 슬롯 중 하나라도 그룹이 있는지 — thead 2-row 분기 신호.
|
|
48
|
+
*/
|
|
49
|
+
export declare function hasGroupSlot<T>(visibleSlots: ColumnSlot<T>[]): boolean;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PresetNumber } from '../../../../lib/column-preset-storage';
|
|
2
|
+
import { TableColumn, TableColumnGroupMeta } from '../types';
|
|
3
|
+
interface ColumnPresetSelectorProps<T> {
|
|
4
|
+
columns: TableColumn<T>[];
|
|
5
|
+
columnGroups?: TableColumnGroupMeta[];
|
|
6
|
+
activePreset: PresetNumber;
|
|
7
|
+
columnOrder: string[];
|
|
8
|
+
hiddenColumns: string[];
|
|
9
|
+
columnWidths: Record<string, number>;
|
|
10
|
+
isDirty: boolean;
|
|
11
|
+
hasPreset: (num: PresetNumber) => boolean;
|
|
12
|
+
onApplyPreset: (num: PresetNumber) => void;
|
|
13
|
+
/** 현재 편집 중 상태를 활성 프리셋에 저장(commit). 저장 불가하면 false. */
|
|
14
|
+
onSaveActivePreset: () => boolean;
|
|
15
|
+
/** 활성 프리셋을 기본값으로 되돌리기. */
|
|
16
|
+
onResetActivePreset: () => void;
|
|
17
|
+
/** 편집 중 컬럼 순서 갱신. */
|
|
18
|
+
onColumnOrderChange: (next: string[]) => void;
|
|
19
|
+
/** 편집 중 숨김 컬럼 갱신. */
|
|
20
|
+
onHiddenColumnsChange: (next: string[]) => void;
|
|
21
|
+
/** 단일 컬럼 너비 갱신. 0 이하면 키 제거(기본값 복원). */
|
|
22
|
+
onSetColumnWidth: (key: string, width: number) => void;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 컬럼 프리셋 셀렉터 + 설정 드롭다운
|
|
27
|
+
*
|
|
28
|
+
* pill 형태 세그먼트 컨트롤. 톱니(설정) + 세로 디바이더 + 프리셋 1·2·3.
|
|
29
|
+
* 활성 프리셋은 흰 배경이 layoutId로 슬라이드되며 이동.
|
|
30
|
+
* 위치 계산은 floating-ui 위임 — flip으로 공간 부족 시 위로 뒤집고, shift로 viewport 안에 클램프.
|
|
31
|
+
*
|
|
32
|
+
* 편집 중 변경은 외부(useColumnPresets)에 즉시 반영되고, 명시 저장 시에만 영구화.
|
|
33
|
+
* isDirty가 true면 톱니 옆에 점을 표시한다.
|
|
34
|
+
*/
|
|
35
|
+
export declare function ColumnPresetSelector<T>({ columns, columnGroups, activePreset, columnOrder, hiddenColumns, columnWidths, isDirty, hasPreset, onApplyPreset, onSaveActivePreset, onResetActivePreset, onColumnOrderChange, onHiddenColumnsChange, onSetColumnWidth, className, }: ColumnPresetSelectorProps<T>): import("react").JSX.Element;
|
|
36
|
+
export {};
|