@wipco/sdui 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.
@@ -0,0 +1,1012 @@
1
+ import * as React from 'react';
2
+ import React__default, { ComponentType } from 'react';
3
+ import { D as DatePicker, a as DateRangePicker } from './DatePicker-CTDcFR7V.js';
4
+ export { b as DatePickerProps, c as DateRangePickerProps, d as DateRangeValue } from './DatePicker-CTDcFR7V.js';
5
+ import { S as SduiAction, a as SduiPropValue, b as SduiRule, c as SduiPage } from './types-D5Tkrynd.js';
6
+ export { d as SduiCalcRef, e as SduiChild, f as SduiIndexRef, g as SduiItemRef, h as SduiNode, i as SduiScalar, j as SduiStateRef } from './types-D5Tkrynd.js';
7
+
8
+ /**
9
+ * 호스트 앱 연결점 — ERP에서는 라우터·erpFetch·SSE가 하던 일을
10
+ * 어댑터로 주입받는다. 전부 선택 사항이며, 기본 구현은 브라우저
11
+ * 표준 API(fetch, location)로 동작한다.
12
+ */
13
+ interface SduiAdapter {
14
+ /** navigate 액션 처리. 기본: window.location.assign */
15
+ navigate?: (to: string) => void;
16
+ /**
17
+ * submitForm 등 JSON API 호출. 성공 시 응답 JSON을, 실패 시
18
+ * Error(사용자에게 보여줄 메시지)를 던진다.
19
+ */
20
+ fetch?: (path: string, init: {
21
+ method: string;
22
+ body?: unknown;
23
+ }) => Promise<unknown>;
24
+ /** download 액션용 원시 fetch. 기본: fetch(path, { credentials: 'include' }) */
25
+ rawFetch?: (path: string) => Promise<Response>;
26
+ /** invalidate 액션 — 클라이언트 조회 캐시 무효화 (TanStack Query 등) */
27
+ invalidate?: (prefix: string, exact: boolean) => void;
28
+ /** refresh 액션 — 페이지 스펙 재조회 */
29
+ refresh?: () => void;
30
+ /**
31
+ * 페이지 스펙의 subscribe 채널 구독(SSE 등).
32
+ * onEvent 호출 시 렌더러가 조용한 재조회(invalidate+refresh)를 수행한다.
33
+ * 반환값은 구독 해제 함수.
34
+ */
35
+ subscribe?: (channels: string[], onEvent: () => void) => () => void;
36
+ /**
37
+ * urlState 반영 시 URL 쿼리 교체를 위임한다 — react-router 호스트라면
38
+ * setSearchParams(params, { replace: true })를 연결해 라우터 구독자와
39
+ * 어긋나지 않게 한다. 기본: window.history.replaceState.
40
+ */
41
+ replaceQuery?: (params: URLSearchParams) => void;
42
+ }
43
+ declare const defaultAdapter: Required<Pick<SduiAdapter, 'navigate' | 'fetch' | 'rawFetch'>> & SduiAdapter;
44
+
45
+ /**
46
+ * 권한 게이트 — 통과하면 children, 실패하면 fallback 슬롯(없으면 아무 것도)을 렌더한다.
47
+ * 판정 자체는 하지 않는다. 호스트가 주입한 콜백(permission.tsx)에 질의만 위임한다.
48
+ *
49
+ * 스펙 예 (ERP 85개 페이지 중 56개가 쓰는 형태 그대로):
50
+ * { "component": "Can",
51
+ * "props": { "entity": "asset", "action": "create" },
52
+ * "children": [ { "component": "Button", ... } ] }
53
+ */
54
+
55
+ interface CanProps {
56
+ /** 대상 엔티티 식별자 */
57
+ entity: string;
58
+ /** 수행 동작 — 생략 시 'read'(ERP Can과 같은 기본값) */
59
+ action?: string;
60
+ /** 최소 적용 범위 — 생략 시 호스트 판정기의 기본값을 따른다 */
61
+ scope?: string;
62
+ /** 차단 시 대신 보여줄 내용 (JSON에서는 slots.fallback) */
63
+ fallback?: React__default.ReactNode;
64
+ children?: React__default.ReactNode;
65
+ }
66
+ declare function Can({ entity, action, scope, fallback, children }: CanProps): React__default.JSX.Element;
67
+
68
+ /**
69
+ * 내장 기본 컴포넌트 세트 — WIPCO 디자인 시스템(wp-* 토큰)을 따르는
70
+ * 독립 구현. ERP 디자인 시스템과 같은 프롭 규약을 쓰므로 스펙이 호환된다.
71
+ * 스타일은 styles.css 한 파일이 담당한다.
72
+ */
73
+
74
+ interface IconProps extends React__default.SVGAttributes<SVGSVGElement> {
75
+ name: string;
76
+ size?: number;
77
+ strokeWidth?: number;
78
+ }
79
+ /** 스트로크 아이콘. 등록되지 않은 이름은 점으로 대체된다. */
80
+ declare function Icon({ name, size, strokeWidth, ...rest }: IconProps): React__default.JSX.Element;
81
+ interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
82
+ /** primary = WIPCO Blue, secondary = 외곽선(기본), ghost = 투명, danger = WIPCO Red, link = 인라인 */
83
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
84
+ /** xs 24 · sm 28 · md 32(기본) · lg 40 · xl 48 px */
85
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
86
+ /** 선행 아이콘 이름 */
87
+ icon?: string;
88
+ /** 후행 아이콘 이름 */
89
+ iconEnd?: string;
90
+ /** 라벨을 스피너로 바꾸고 입력을 막는다 */
91
+ loading?: boolean;
92
+ block?: boolean;
93
+ disabled?: boolean;
94
+ children?: React__default.ReactNode;
95
+ }
96
+ declare function Button({ variant, size, icon, iconEnd, loading, block, disabled, children, className, type, ...rest }: ButtonProps): React__default.JSX.Element;
97
+ interface IconButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
98
+ icon: string;
99
+ /** 접근성 라벨(필수 권장) */
100
+ label?: string;
101
+ size?: 'xs' | 'sm' | 'md';
102
+ /**
103
+ * 예전 이름. `variant`를 주지 않았을 때만 쓰인다 — `variant` 주석 참고.
104
+ * @deprecated `variant`로 옮겨라. `tone="danger"`는 `variant="danger"`와 같다.
105
+ */
106
+ tone?: 'default' | 'danger';
107
+ /**
108
+ * 디자인 시스템 어휘. ghost = 투명(기본) · outlined = 하드라인 테두리 · danger = 빨강.
109
+ *
110
+ * 같은 자리를 가리키는 프롭이 `tone`과 둘로 갈라져 있는데 **variant가 이긴다** —
111
+ * 스펙과 디자인 시스템 문서가 쓰는 이름이 이쪽이고, 값 어휘도 넓다(outlined는 tone에 없다).
112
+ * variant를 주지 않으면 tone이 그대로 먹으므로 tone만 쓰던 코드는 그대로 돈다.
113
+ */
114
+ variant?: 'ghost' | 'outlined' | 'danger';
115
+ }
116
+ declare function IconButton({ icon, label, size, tone, variant, className, type, ...rest }: IconButtonProps): React__default.JSX.Element;
117
+ interface InputProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, 'size'> {
118
+ /** sm 28 · md 32(기본) · lg 40 px */
119
+ size?: 'sm' | 'md' | 'lg';
120
+ /** 선행 아이콘 이름 (예: "search") */
121
+ icon?: string;
122
+ /** 빨간 테두리 — Field error와 함께 사용 */
123
+ invalid?: boolean;
124
+ /** 고정폭 글꼴 — ID, 좌표, 해시 */
125
+ mono?: boolean;
126
+ /**
127
+ * 입력 오른쪽 끝에 겹쳐 그리는 후행 표시 — "원", "위", "mm" 같은 단위가 대부분이다.
128
+ *
129
+ * 단위를 값 안에 섞어 넣지 않는다는 규칙을 지키려면 값이 아니라 입력 위에 얹어야 해서,
130
+ * 선행 `icon`과 같은 래퍼를 쓴다.
131
+ *
132
+ * 문자열은 **ICON_PATHS에 있는 이름이면 아이콘, 아니면 그대로 단위 글자**로 그린다.
133
+ * 디자인 시스템 쪽 용례는 `trailing="eye"`(비밀번호 보기)처럼 아이콘 이름인데
134
+ * 실제 스펙 9곳은 전부 "원"·"위" 같은 단위 글자라, 둘 중 하나만 고르면 나머지가 깨진다.
135
+ * 단위가 아이콘 이름과 겹치는 일은 없으므로 이름으로 갈라도 안전하다.
136
+ */
137
+ trailing?: React__default.ReactNode;
138
+ }
139
+ declare function Input({ size, icon, invalid, mono, trailing, className, style, ...rest }: InputProps): React__default.JSX.Element;
140
+ interface TextareaProps extends React__default.TextareaHTMLAttributes<HTMLTextAreaElement> {
141
+ invalid?: boolean;
142
+ rows?: number;
143
+ }
144
+ declare function Textarea({ invalid, rows, className, ...rest }: TextareaProps): React__default.JSX.Element;
145
+ interface SelectOption {
146
+ value: string;
147
+ label: string;
148
+ disabled?: boolean;
149
+ }
150
+ interface SelectProps extends Omit<React__default.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
151
+ options: SelectOption[];
152
+ size?: 'sm' | 'md' | 'lg';
153
+ invalid?: boolean;
154
+ /** 비어 있는 첫 옵션 */
155
+ placeholder?: string;
156
+ }
157
+ declare function Select({ options, size, invalid, placeholder, className, ...rest }: SelectProps): React__default.JSX.Element;
158
+ interface CheckboxProps extends React__default.InputHTMLAttributes<HTMLInputElement> {
159
+ label?: React__default.ReactNode;
160
+ description?: React__default.ReactNode;
161
+ disabled?: boolean;
162
+ }
163
+ declare function Checkbox({ label, description, disabled, className, ...rest }: CheckboxProps): React__default.JSX.Element;
164
+ interface SwitchProps extends Omit<React__default.InputHTMLAttributes<HTMLInputElement>, 'size'> {
165
+ label?: React__default.ReactNode;
166
+ size?: 'sm' | 'md';
167
+ disabled?: boolean;
168
+ }
169
+ declare function Switch({ label, size, disabled, className, ...rest }: SwitchProps): React__default.JSX.Element;
170
+ interface FieldProps extends React__default.HTMLAttributes<HTMLDivElement> {
171
+ label?: React__default.ReactNode;
172
+ /** 에러가 없을 때 보여줄 안내 한 줄 */
173
+ hint?: React__default.ReactNode;
174
+ /** hint를 대체하고 빨간색으로 표시 */
175
+ error?: React__default.ReactNode;
176
+ required?: boolean;
177
+ htmlFor?: string;
178
+ /** stacked(기본) 또는 horizontal(132px 라벨 컬럼) */
179
+ layout?: 'stacked' | 'horizontal';
180
+ children?: React__default.ReactNode;
181
+ }
182
+ declare function Field({ label, hint, error, required, htmlFor, layout, children, className, ...rest }: FieldProps): React__default.JSX.Element;
183
+ interface CardProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'title'> {
184
+ title?: React__default.ReactNode;
185
+ subtitle?: React__default.ReactNode;
186
+ /** 헤더 우측 — 버튼, Select 등 */
187
+ actions?: React__default.ReactNode;
188
+ /** 우측 정렬 푸터 행 */
189
+ footer?: React__default.ReactNode;
190
+ variant?: 'default' | 'raised' | 'flat' | 'sunken';
191
+ selected?: boolean;
192
+ interactive?: boolean;
193
+ /** default 20px · tight 14px · none(테이블, 리스트) */
194
+ padding?: 'default' | 'tight' | 'none';
195
+ children?: React__default.ReactNode;
196
+ }
197
+ declare function Card({ title, subtitle, actions, footer, variant, selected, interactive, padding, children, className, ...rest }: CardProps): React__default.JSX.Element;
198
+ interface BadgeProps extends React__default.HTMLAttributes<HTMLSpanElement> {
199
+ tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'brand';
200
+ /** 선행 5px 점 — 라이브/진행 상태 */
201
+ dot?: boolean;
202
+ size?: 'md' | 'lg';
203
+ children?: React__default.ReactNode;
204
+ }
205
+ declare function Badge({ tone, dot, size, children, className, ...rest }: BadgeProps): React__default.JSX.Element;
206
+ interface TagProps extends React__default.HTMLAttributes<HTMLSpanElement> {
207
+ /** 선행 점의 CSS 색상 */
208
+ color?: string;
209
+ filled?: boolean;
210
+ onRemove?: (e: React__default.MouseEvent) => void;
211
+ children?: React__default.ReactNode;
212
+ }
213
+ declare function Tag({ color, filled, onRemove, children, className, ...rest }: TagProps): React__default.JSX.Element;
214
+ interface AlertProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'title'> {
215
+ tone?: 'info' | 'success' | 'warning' | 'danger' | 'neutral';
216
+ title?: React__default.ReactNode;
217
+ children?: React__default.ReactNode;
218
+ actions?: React__default.ReactNode;
219
+ onClose?: () => void;
220
+ /**
221
+ * 테두리를 왼쪽 색 막대 하나로 바꾼다(모서리도 각지게 편다).
222
+ *
223
+ * 화면 맨 위에 놓여 먼저 읽혀야 하는 공지 — 개인정보 보호 안내, 업로드 절차 안내처럼
224
+ * 카드 안의 알림이 아니라 화면 폭을 가르는 배너로 보여야 하는 자리에 쓴다.
225
+ */
226
+ bar?: boolean;
227
+ }
228
+ declare function Alert({ tone, title, children, actions, onClose, bar, className, ...rest }: AlertProps): React__default.JSX.Element;
229
+ interface ToastProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'title'> {
230
+ tone?: 'info' | 'success' | 'warning' | 'danger';
231
+ title?: React__default.ReactNode;
232
+ children?: React__default.ReactNode;
233
+ onClose?: () => void;
234
+ }
235
+ /** 우하단 일시 알림. .wp-toast-region 안에 렌더링된다. */
236
+ declare function Toast({ tone, title, children, onClose, className, ...rest }: ToastProps): React__default.JSX.Element;
237
+ interface TabItem {
238
+ value: string;
239
+ label: React__default.ReactNode;
240
+ icon?: string;
241
+ count?: number;
242
+ }
243
+ interface TabsProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'onChange'> {
244
+ items: TabItem[];
245
+ value: string;
246
+ onChange?: (value: string) => void;
247
+ size?: 'md' | 'lg';
248
+ }
249
+ declare function Tabs({ items, value, onChange, size, className, ...rest }: TabsProps): React__default.JSX.Element;
250
+ interface TableColumn {
251
+ key: string;
252
+ header: React__default.ReactNode;
253
+ /** CSS 폭 — "180px", "22%" */
254
+ width?: string;
255
+ align?: 'left' | 'right';
256
+ mono?: boolean;
257
+ strong?: boolean;
258
+ /**
259
+ * 셀 값을 Badge로 렌더링 — JSON 스펙에서 쓸 수 있는 선언적 지정.
260
+ * toneMap: 값 → tone, labelMap: 값 → 표시 텍스트(생략 시 값 그대로)
261
+ */
262
+ badge?: {
263
+ toneMap?: Record<string, string>;
264
+ labelMap?: Record<string, string>;
265
+ };
266
+ /** 프로그래매틱 사용 전용 — JSON 스펙에서는 쓸 수 없다 */
267
+ render?: (row: any, index: number) => React__default.ReactNode;
268
+ }
269
+ interface TableProps extends React__default.TableHTMLAttributes<HTMLTableElement> {
270
+ columns: TableColumn[];
271
+ rows: any[];
272
+ /** 40px 대신 32px 행 */
273
+ dense?: boolean;
274
+ hover?: boolean;
275
+ /** 행 key와 선택에 쓸 필드. 기본 "id" */
276
+ rowKey?: string;
277
+ onRowClick?: (row: any) => void;
278
+ /** rows가 비었을 때 대신 렌더링 — EmptyState 권장 */
279
+ empty?: React__default.ReactNode;
280
+ }
281
+ declare function Table({ columns, rows, dense, hover, rowKey, onRowClick, empty, className, ...rest }: TableProps): React__default.JSX.Element;
282
+ interface StatCardProps extends React__default.HTMLAttributes<HTMLDivElement> {
283
+ label: React__default.ReactNode;
284
+ value: React__default.ReactNode;
285
+ /** 단위 접미사 — "GB", "건", "%" */
286
+ unit?: string;
287
+ /** 비교 텍스트 — "+12.4%" */
288
+ delta?: React__default.ReactNode;
289
+ trend?: 'up' | 'down' | 'flat';
290
+ icon?: string;
291
+ footer?: React__default.ReactNode;
292
+ size?: 'md' | 'sm';
293
+ }
294
+ declare function StatCard({ label, value, unit, delta, trend, icon, footer, size, className, ...rest }: StatCardProps): React__default.JSX.Element;
295
+ interface EmptyStateProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'title'> {
296
+ icon?: string;
297
+ title?: React__default.ReactNode;
298
+ children?: React__default.ReactNode;
299
+ actions?: React__default.ReactNode;
300
+ tight?: boolean;
301
+ }
302
+ declare function EmptyState({ icon, title, children, actions, tight, className, ...rest }: EmptyStateProps): React__default.JSX.Element;
303
+ interface SpinnerProps extends React__default.HTMLAttributes<HTMLSpanElement> {
304
+ size?: 'sm' | 'md' | 'lg';
305
+ label?: string;
306
+ }
307
+ declare function Spinner({ size, label, className, ...rest }: SpinnerProps): React__default.JSX.Element;
308
+ interface ProgressBarProps extends React__default.HTMLAttributes<HTMLDivElement> {
309
+ /** 0~100 */
310
+ value: number;
311
+ /** danger 임계 강조 등 */
312
+ tone?: 'brand' | 'success' | 'warning' | 'danger' | 'info';
313
+ label?: React__default.ReactNode;
314
+ /**
315
+ * 라벨 줄 오른쪽 끝에 현재 값을 퍼센트로 적는다.
316
+ *
317
+ * 막대만으로는 82%와 91%를 구분할 수 없어서, 여러 개를 세로로 쌓아 비교하는
318
+ * 자리(공정별 진척 목록 등)에서 필요하다. 라벨 없이 켜도 값은 오른쪽에 붙는다.
319
+ */
320
+ showValue?: boolean;
321
+ }
322
+ declare function ProgressBar({ value, tone, label, showValue, className, ...rest }: ProgressBarProps): React__default.JSX.Element;
323
+ interface PaginationProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'onChange'> {
324
+ page: number;
325
+ pageCount: number;
326
+ total?: number;
327
+ pageSize?: number;
328
+ onChange?: (page: number) => void;
329
+ }
330
+ declare function Pagination({ page, pageCount, total, pageSize, onChange, className, ...rest }: PaginationProps): React__default.JSX.Element;
331
+ interface DialogProps extends Omit<React__default.HTMLAttributes<HTMLDivElement>, 'title'> {
332
+ title?: React__default.ReactNode;
333
+ subtitle?: React__default.ReactNode;
334
+ /** 타이틀 좌측 마크 안의 아이콘 이름 */
335
+ icon?: string;
336
+ tone?: 'brand' | 'danger';
337
+ /** sm 380 · md 480(기본) · lg 680 · xl 880 px */
338
+ size?: 'sm' | 'md' | 'lg' | 'xl';
339
+ /** 우측 정렬 액션 행 — 보조 버튼 다음 주 버튼 */
340
+ footer?: React__default.ReactNode;
341
+ onClose?: () => void;
342
+ children?: React__default.ReactNode;
343
+ }
344
+ /** 모달 본체. 오버레이가 가장 가까운 포지셔닝 조상을 채운다 — SDUI에서는 SduiDialog 래퍼가 뷰포트에 고정한다. */
345
+ declare function Dialog({ title, subtitle, icon, tone, size, footer, onClose, children, className, ...rest }: DialogProps): React__default.JSX.Element;
346
+
347
+ interface GridProps {
348
+ /** wp-grid--N 프리셋 */
349
+ columns?: 2 | 3 | 4;
350
+ /** 커스텀 트랙 — grid-template-columns 값. columns보다 우선 */
351
+ template?: string;
352
+ className?: string;
353
+ style?: React__default.CSSProperties;
354
+ children?: React__default.ReactNode;
355
+ }
356
+ declare function Grid({ columns, template, className, style, children }: GridProps): React__default.JSX.Element;
357
+ type Justify = 'start' | 'center' | 'end' | 'between';
358
+ interface RowProps {
359
+ /** 가로 정렬 (기본 start) */
360
+ justify?: Justify;
361
+ className?: string;
362
+ style?: React__default.CSSProperties;
363
+ children?: React__default.ReactNode;
364
+ }
365
+ declare function Row({ justify, className, style, children }: RowProps): React__default.JSX.Element;
366
+ interface ActionsProps {
367
+ /** 가로 정렬 — 기본 end(우측) */
368
+ justify?: Justify;
369
+ className?: string;
370
+ style?: React__default.CSSProperties;
371
+ children?: React__default.ReactNode;
372
+ }
373
+ /** 액션 버튼 묶음 — 슬롯 안에서 정렬을 제어한다(flex:1로 슬롯 폭 차지). */
374
+ declare function Actions({ justify, className, style, children }: ActionsProps): React__default.JSX.Element;
375
+ declare function Col({ className, style, children }: {
376
+ className?: string;
377
+ style?: React__default.CSSProperties;
378
+ children?: React__default.ReactNode;
379
+ }): React__default.JSX.Element;
380
+ interface SpacerProps {
381
+ /**
382
+ * 간격 토큰 단계(`--wp-space-N`). 주면 "남는 공간 밀어내기"가 아니라
383
+ * 그만큼의 **고정 간격**이 된다 — Card 본문처럼 gap이 이미 걸린 세로 묶음 안에서
384
+ * 한 덩어리를 다음 덩어리와 더 떼어 놓을 때 쓴다.
385
+ * 토큰에 없는 단계를 주면 무시하고 기존 flex 채움으로 돌아간다.
386
+ */
387
+ size?: 1 | 2 | 3 | 4 | 5 | 6 | 8;
388
+ }
389
+ declare function Spacer({ size }: SpacerProps): React__default.JSX.Element;
390
+ interface SectionProps {
391
+ title?: React__default.ReactNode;
392
+ className?: string;
393
+ style?: React__default.CSSProperties;
394
+ children?: React__default.ReactNode;
395
+ }
396
+ declare function Section({ title, className, style, children }: SectionProps): React__default.JSX.Element;
397
+ type TextPreset = 'display-1' | 'display-2' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body-lg' | 'body' | 'body-sm' | 'caption' | 'label' | 'overline' | 'micro' | 'metric' | 'metric-sm' | 'mono' | 'mono-xs';
398
+ interface TextProps {
399
+ /** styles.css의 .wp-* 타입 프리셋 이름 */
400
+ preset?: TextPreset;
401
+ as?: 'p' | 'span' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
402
+ className?: string;
403
+ style?: React__default.CSSProperties;
404
+ /** children 대신 쓸 수 있는 내용 — 상태 바인딩({ "$state": ... })에 유용 */
405
+ value?: React__default.ReactNode;
406
+ children?: React__default.ReactNode;
407
+ }
408
+ declare function Text({ preset, as: Tag, className, style, value, children }: TextProps): React__default.JSX.Element;
409
+ interface KeyValueItem {
410
+ label: React__default.ReactNode;
411
+ /** source에서 꺼낼 필드 키. 생략하면 value를 그대로 출력 */
412
+ key?: string;
413
+ value?: React__default.ReactNode;
414
+ mono?: boolean;
415
+ }
416
+ interface KeyValueListProps {
417
+ /** 값의 원천 객체 — 보통 상태 바인딩({ "$state": "selectedOrder" })을 넣는다 */
418
+ source?: Record<string, unknown> | null;
419
+ items: KeyValueItem[];
420
+ className?: string;
421
+ style?: React__default.CSSProperties;
422
+ }
423
+ /** 키-값 요약 목록 (.wp-kv) — 상세 다이얼로그·패널의 표준 표현. */
424
+ declare function KeyValueList({ source, items, className, style }: KeyValueListProps): React__default.JSX.Element;
425
+ interface PageHeadProps {
426
+ title?: React__default.ReactNode;
427
+ subtitle?: React__default.ReactNode;
428
+ /** 우측 액션 영역 (JSON에서는 slots.actions로 전달) */
429
+ actions?: React__default.ReactNode;
430
+ }
431
+ declare function PageHead({ title, subtitle, actions }: PageHeadProps): React__default.JSX.Element;
432
+ interface ShowProps {
433
+ /** 보통 상태 참조({ "$state": ... })를 바인딩한다. truthy면 children을 렌더링. */
434
+ when?: unknown;
435
+ children?: React__default.ReactNode;
436
+ }
437
+ /** 조건부 렌더링 — Dialog 등을 상태로 열고 닫을 때 사용. */
438
+ declare function Show({ when, children }: ShowProps): React__default.JSX.Element | null;
439
+ /** 가로 구분선 */
440
+ declare function Divider({ style }: {
441
+ style?: React__default.CSSProperties;
442
+ }): React__default.JSX.Element;
443
+
444
+ /**
445
+ * 목록 원격 조회 어댑터.
446
+ *
447
+ * core는 특정 HTTP 클라이언트에 묶이지 않는다 — ERP는 SWR(useErpQuery)로 조회했지만
448
+ * 라이브러리는 "endpoint + 파라미터 → { data, total }" 한 줄짜리 계약만 요구하고,
449
+ * 호스트가 자기 클라이언트(TanStack Query, SWR, 사내 fetch 래퍼…)를 끼워 넣는다.
450
+ * 주입이 없으면 브라우저 fetch로 동작한다(어댑터를 안 준 SduiRenderer와 같은 정책).
451
+ */
452
+
453
+ interface SearchRow {
454
+ id: string;
455
+ [key: string]: unknown;
456
+ }
457
+ interface SearchPage {
458
+ data: SearchRow[];
459
+ total: number;
460
+ }
461
+ /**
462
+ * 목록 한 페이지를 가져온다. 실패하면 Error(사용자에게 보여줄 메시지)를 던진다.
463
+ * signal은 파라미터가 바뀌거나 언마운트될 때 중단 신호로 넘어온다.
464
+ */
465
+ type SearchFetcher = (endpoint: string, params: URLSearchParams, signal: AbortSignal) => Promise<SearchPage>;
466
+ declare function SduiSearchDataProvider({ fetcher, children, }: {
467
+ fetcher: SearchFetcher;
468
+ children?: React__default.ReactNode;
469
+ }): React__default.JSX.Element;
470
+ declare function useSearchFetcher(): SearchFetcher;
471
+ interface RemotePageState {
472
+ page: SearchPage;
473
+ isLoading: boolean;
474
+ error: Error | null;
475
+ reload: () => void;
476
+ }
477
+ /**
478
+ * endpoint+params 조회 훅. 라이브러리 안에 캐시를 두지 않는다(호스트 클라이언트의 몫) —
479
+ * 대신 직전 페이지를 유지해(keepPreviousData 상당) 페이지 이동 중 목록이 깜빡이지 않게 한다.
480
+ */
481
+ declare function useRemoteSearchPage(endpoint: string, params: URLSearchParams): RemotePageState;
482
+
483
+ /**
484
+ * 검색 툴바 — ERP `app/components/search/SearchToolbar.tsx`의 계약(타입·헬퍼·동작)을
485
+ * 그대로 옮긴 것. 스펙 호환이 목적이므로 값 규칙(쉼표 다중값, 느슨한 검색, 범위 키 이름)은
486
+ * 한 글자도 바꾸지 않았다.
487
+ *
488
+ * - 검색 버튼은 두지 않는다(Enter로 검색) — 시안 규칙 유지
489
+ * - 상세검색은 아이콘 버튼 → 드롭다운 패널(초기화/적용)
490
+ * - 적용된 조건은 칩(Tag)으로 나열되고, 다중 선택 칩은 값 하나씩 제거된다
491
+ */
492
+
493
+ interface SearchOption {
494
+ label: string;
495
+ value: string;
496
+ }
497
+ interface CascadingSearchOption extends SearchOption {
498
+ children?: CascadingSearchOption[];
499
+ }
500
+ type SearchField = {
501
+ type?: 'text';
502
+ key: string;
503
+ label: string;
504
+ placeholder?: string;
505
+ } | {
506
+ /** 다중 선택 — 값은 쉼표로 합쳐 저장한다 */
507
+ type: 'select';
508
+ key: string;
509
+ label: string;
510
+ options: SearchOption[];
511
+ allLabel?: string;
512
+ } | {
513
+ type: 'dateRange';
514
+ key: string;
515
+ label: string;
516
+ fromKey?: string;
517
+ toKey?: string;
518
+ } | {
519
+ type: 'numberRange';
520
+ key: string;
521
+ label: string;
522
+ fromKey?: string;
523
+ toKey?: string;
524
+ minPlaceholder?: string;
525
+ maxPlaceholder?: string;
526
+ } | {
527
+ /**
528
+ * 계층 다중 선택 — 단계별 체크박스 목록 체인. 선택된 값들을 쉼표로 합쳐 저장하며,
529
+ * 부모를 선택하면 그 자손 선택은 제거되고 자손을 선택하면 그 조상 선택이 제거된다.
530
+ */
531
+ type: 'cascading';
532
+ key: string;
533
+ label: string;
534
+ options: CascadingSearchOption[];
535
+ allLabel?: string;
536
+ };
537
+ type SearchValues = Record<string, string>;
538
+ declare function splitMultiValue(value: string): string[];
539
+ declare function joinMultiValue(values: string[]): string;
540
+ declare function normalizeSearchText(value: string): string;
541
+ declare function includesLooseSearch(text: string, keyword: string): boolean;
542
+ /** 필드가 점유하는 파라미터 키 전체 — 범위 필드는 From/To(Min/Max) 두 개다 */
543
+ declare function searchFieldKeys(fields: SearchField[]): string[];
544
+ declare function searchValuesFromParams(fields: SearchField[], params: URLSearchParams): SearchValues;
545
+ declare function cleanSearchValues(fields: SearchField[], values: SearchValues): SearchValues;
546
+ /**
547
+ * 값 → 자기 자신을 포함한 조상 값 목록(루트→자신 순).
548
+ * SearchResults의 클라이언트 필터링에서 "부모 선택 = 자손 값 매칭"을 구현할 때 쓴다.
549
+ */
550
+ declare function cascadingValuePaths(options: CascadingSearchOption[]): Map<string, string[]>;
551
+ interface SearchToolbarProps {
552
+ search: string;
553
+ onSearchChange: (value: string) => void;
554
+ onSearch: (search: string, advancedValues: SearchValues) => void;
555
+ advancedFields?: SearchField[];
556
+ advancedValues?: SearchValues;
557
+ placeholder?: string;
558
+ className?: string;
559
+ /** 필터 전용 모드: 검색 입력창 없이 상세검색 버튼+칩만 보여준다 */
560
+ hideSearchInput?: boolean;
561
+ }
562
+ declare function SearchToolbar({ search, onSearchChange, onSearch, advancedFields, advancedValues, placeholder, className, hideSearchInput, }: SearchToolbarProps): React__default.JSX.Element;
563
+
564
+ /**
565
+ * 검색 결과 목록 — ERP `app/components/search/SearchResults.tsx`의 계약을 그대로 가져온 포팅.
566
+ * - 목록(Table)/카드 그리드(Card) 전환, 정렬, 좌/우 필터, 선택 후 일괄 액션, 페이지네이션
567
+ * - 데이터 가공(검색·필터·정렬·페이지 슬라이스)은 로컬 데이터 기준 클라이언트에서 수행하며,
568
+ * 서버 페이징으로 넘어가면 params를 그대로 백엔드 질의로 옮기면 된다
569
+ *
570
+ * ERP와 다른 점은 하나뿐이다: 검색/필터/페이지 파라미터를 URL에 직접 쓰지 않고
571
+ * `searchParams` + `onParamsChange`로만 다룬다(controlled). core는 라우터를 알지 않으며,
572
+ * 한 페이지에 목록이 여러 개 있어도 서로의 URL을 오염시키지 않는다.
573
+ */
574
+
575
+ /** DS Badge 톤 */
576
+ type BadgeTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'brand';
577
+ interface SearchAction<T> {
578
+ label: string;
579
+ onClick: (selectedItems: T[]) => void | Promise<void>;
580
+ icon?: string;
581
+ variant?: 'default' | 'destructive' | 'outline';
582
+ }
583
+ interface SearchColumn<T> {
584
+ key: string;
585
+ title: string;
586
+ sortable?: boolean;
587
+ /** DS Table은 left/right만 지원한다 */
588
+ textAlign?: 'left' | 'right';
589
+ /** 상대 폭 — 전체 ratio 합 대비 % 폭으로 환산된다 */
590
+ ratio?: number;
591
+ mono?: boolean;
592
+ strong?: boolean;
593
+ accessor?: (item: T) => string | number | Date | null | undefined;
594
+ render?: (item: T) => React__default.ReactNode;
595
+ }
596
+ interface SearchFilter {
597
+ key: string;
598
+ label: string;
599
+ options: {
600
+ key: string;
601
+ label: string;
602
+ value: string;
603
+ }[];
604
+ }
605
+ interface GridCardRow<T> {
606
+ icon?: React__default.ReactNode | ((item: T) => React__default.ReactNode);
607
+ label?: React__default.ReactNode | ((item: T) => React__default.ReactNode);
608
+ value?: React__default.ReactNode | ((item: T) => React__default.ReactNode);
609
+ show?: (item: T) => boolean;
610
+ }
611
+ interface GridCardConfig<T> {
612
+ title: (item: T) => React__default.ReactNode;
613
+ subtitle?: (item: T) => React__default.ReactNode;
614
+ badge?: (item: T) => {
615
+ text: React__default.ReactNode;
616
+ variant?: BadgeTone;
617
+ } | null;
618
+ actions?: (item: T) => React__default.ReactNode;
619
+ rows?: GridCardRow<T>[];
620
+ leftRows?: GridCardRow<T>[];
621
+ rightRows?: GridCardRow<T>[];
622
+ note?: (item: T) => React__default.ReactNode | null;
623
+ }
624
+ interface SearchResultsProps<T> {
625
+ item: {
626
+ data: T[];
627
+ total: number;
628
+ };
629
+ columns: SearchColumn<T>[];
630
+ gridConfig?: GridCardConfig<T>;
631
+ leftFilters?: SearchFilter[];
632
+ rightFilters?: SearchFilter[];
633
+ initialView?: 'grid' | 'list';
634
+ className?: string;
635
+ /** 검색/필터/페이지 파라미터 (controlled) */
636
+ searchParams: URLSearchParams;
637
+ onParamsChange: (next: URLSearchParams) => void;
638
+ /** 선택 액션 — 있으면 체크박스 선택이 활성화된다 */
639
+ actions?: SearchAction<T>[];
640
+ disableGrid?: boolean;
641
+ disableList?: boolean;
642
+ onRowClick?: (item: T) => void;
643
+ /** 화면에는 카운트만 표시 — 접근성 레이블·빈 상태 문구에 사용 */
644
+ title: string;
645
+ headerActions?: React__default.ReactNode;
646
+ isLoading?: boolean;
647
+ hideHeader?: boolean;
648
+ advancedSearchFields?: SearchField[];
649
+ searchPlaceholder?: string;
650
+ /**
651
+ * 가상 스크롤(대용량 목록) — true면 기본 임계값 150행, 숫자면 그 값이 임계값.
652
+ * 목록 뷰에서 행 수가 임계값을 넘으면 페이지 슬라이스 대신 전체 목록을 창 렌더한다
653
+ * (서버 페이징 모드에서는 현재 응답 분량만 가상화).
654
+ */
655
+ virtual?: boolean | number;
656
+ }
657
+ declare function SearchResults<T extends {
658
+ id: string;
659
+ }>({ item, columns, gridConfig, leftFilters, rightFilters, initialView, className, searchParams, onParamsChange, actions, disableGrid, disableList, onRowClick, title, headerActions, isLoading, hideHeader, advancedSearchFields, searchPlaceholder, virtual, }: SearchResultsProps<T>): React__default.JSX.Element;
660
+
661
+ /**
662
+ * SearchResults의 SDUI 어댑터 — 함수 프롭 없이 JSON만으로 검색+목록 화면을 구성한다.
663
+ * 백엔드는 이 프롭 형태(전부 직렬화 가능)를 그대로 내려주면 된다.
664
+ * 레지스트리에는 "SearchResults" / "RemoteSearchResults"로 등록된다.
665
+ *
666
+ * 선언적 스펙 → 함수 프롭 변환(cell.badge → render, run → onClick)은 전부 여기서 일어난다.
667
+ * 액션 실행은 useSduiDispatch로 렌더러에 되돌려 준다.
668
+ */
669
+
670
+ /** JSON 컬럼 정의 — render 함수 대신 선언적 cell 스펙을 쓴다 */
671
+ interface SduiSearchColumn {
672
+ key: string;
673
+ title: string;
674
+ sortable?: boolean;
675
+ /** DS Table은 left/right만 지원 */
676
+ textAlign?: 'left' | 'right';
677
+ ratio?: number;
678
+ mono?: boolean;
679
+ strong?: boolean;
680
+ /** 셀 표현. 생략하면 row[key]를 그대로 출력한다 */
681
+ cell?: {
682
+ type: 'badge';
683
+ /** 값 → Badge 톤 매핑 (없는 값은 neutral) */
684
+ toneMap?: Record<string, BadgeTone>;
685
+ };
686
+ }
687
+ interface SduiGridCard {
688
+ titleKey: string;
689
+ subtitleKey?: string;
690
+ badge?: {
691
+ key: string;
692
+ toneMap?: Record<string, BadgeTone>;
693
+ };
694
+ rows?: Array<{
695
+ label?: string;
696
+ valueKey: string;
697
+ }>;
698
+ }
699
+ interface SduiSearchAction {
700
+ label: string;
701
+ icon?: string;
702
+ variant?: 'default' | 'destructive' | 'outline';
703
+ /** 실행할 선언적 액션 — 이벤트 값으로 선택된 행 id 배열이 전달된다 */
704
+ run: SduiAction | SduiAction[];
705
+ }
706
+ /** 두 어댑터가 공유하는 선언적 프롭 */
707
+ interface SduiSearchCommonProps {
708
+ title: string;
709
+ columns: SduiSearchColumn[];
710
+ fields?: SearchField[];
711
+ leftFilters?: SearchFilter[];
712
+ rightFilters?: SearchFilter[];
713
+ gridCard?: SduiGridCard;
714
+ actions?: SduiSearchAction[];
715
+ initialView?: 'grid' | 'list';
716
+ disableGrid?: boolean;
717
+ disableList?: boolean;
718
+ searchPlaceholder?: string;
719
+ /** 행 클릭 시 실행할 액션 — 이벤트 값으로 행 객체 전체가 전달된다 */
720
+ rowClick?: SduiAction | SduiAction[];
721
+ /** 렌더러의 slots.headerActions가 이 프롭으로 들어온다 */
722
+ headerActions?: React__default.ReactNode;
723
+ /** 가상 스크롤 — true면 기본 임계값 150행, 숫자면 그 값이 임계값 (JSON 직렬화 가능) */
724
+ virtual?: boolean | number;
725
+ }
726
+ interface SduiSearchResultsProps extends SduiSearchCommonProps {
727
+ data: SearchRow[];
728
+ }
729
+ declare function SduiSearchResults({ title, data, columns, fields, leftFilters, rightFilters, gridCard, actions, initialView, disableGrid, disableList, searchPlaceholder, rowClick, headerActions, virtual, }: SduiSearchResultsProps): React__default.JSX.Element;
730
+ interface RemoteSearchResultsProps extends SduiSearchCommonProps {
731
+ /**
732
+ * 목록 endpoint — page/limit/search/필드키 쿼리를 붙여 조회하고
733
+ * `{ data: Row[]; total: number }`를 기대한다. 조회 자체는 어댑터(SearchFetcher)가 한다.
734
+ */
735
+ endpoint: string;
736
+ /** 페이지당 행 수 (기본 10) — limit 파라미터의 초기값 */
737
+ pageSize?: number;
738
+ }
739
+ declare function RemoteSearchResults({ title, endpoint, columns, fields, leftFilters, rightFilters, gridCard, actions, initialView, disableGrid, disableList, searchPlaceholder, rowClick, headerActions, virtual, pageSize, }: RemoteSearchResultsProps): React__default.JSX.Element;
740
+
741
+ /**
742
+ * 목록 표 — SearchResults 전용. 내장 `Table`은 정렬 헤더·선택 표시·가상 스크롤을
743
+ * 다루지 않으므로, 같은 wp-table 마크업/클래스를 유지한 채 그 세 가지를 더한 변형이다.
744
+ *
745
+ * 가상 스크롤은 **의존성 없이** 직접 구현한다(core는 무거운 외부 의존성을 갖지 않는다).
746
+ * ERP는 @tanstack/react-virtual을 썼지만, 여기서 필요한 건 "고정 행 높이 목록의 창"뿐이라
747
+ * scrollTop → 인덱스 범위 계산으로 충분하다. 렌더 범위 밖은 상/하단 스페이서 행으로 대체한다
748
+ * (<table> 마크업에서 transform 대신 안전하게 동작하는 방식).
749
+ */
750
+
751
+ interface ResultTableColumn<T> {
752
+ key: string;
753
+ header: React__default.ReactNode;
754
+ sortable?: boolean;
755
+ /** right → 우측 정렬 + tabular numerals (wp-table__num) */
756
+ align?: 'left' | 'right';
757
+ /** 고정폭 글꼴 셀 (wp-table__mono) */
758
+ mono?: boolean;
759
+ /** 강조 셀 (wp-table__strong) */
760
+ strong?: boolean;
761
+ /** CSS width — "180px", "22%" */
762
+ width?: string;
763
+ render?: (row: T, index: number) => React__default.ReactNode;
764
+ }
765
+ type SortDir = 'asc' | 'desc';
766
+ interface ResultTableProps<T extends {
767
+ id: string;
768
+ }> {
769
+ columns: ResultTableColumn<T>[];
770
+ rows: T[];
771
+ sort?: {
772
+ key: string;
773
+ dir: SortDir;
774
+ };
775
+ onSort?: (key: string) => void;
776
+ onRowClick?: (row: T) => void;
777
+ selectedIds?: string[];
778
+ /** rows가 비었을 때 표 대신 렌더 */
779
+ empty?: React__default.ReactNode;
780
+ /** true면 스크롤 창 안에서 보이는 행만 렌더한다 */
781
+ virtual?: boolean;
782
+ /** 가상 스크롤 컨테이너 높이(px). 기본 560 */
783
+ height?: number;
784
+ /** 가상 스크롤 행 높이(px) 초기 추정치. 첫 렌더 후 실측값으로 대체된다 — 기본 41(wp-table 기본 행) */
785
+ rowHeight?: number;
786
+ }
787
+ declare function ResultTable<T extends {
788
+ id: string;
789
+ }>({ columns, rows, sort, onSort, onRowClick, selectedIds, empty, virtual, height, rowHeight, }: ResultTableProps<T>): React__default.JSX.Element;
790
+
791
+ /**
792
+ * Dialog + 표준 닫기 UX(Escape·배경 클릭). 레지스트리의 "Dialog"는 이 래퍼다.
793
+ */
794
+ declare function SduiDialog(props: DialogProps): React.JSX.Element;
795
+
796
+ /**
797
+ * SDUI 폼 컨테이너. 필드 값은 페이지 상태의 `{id}.{field}` 키에 산다:
798
+ * value: { "$state": "orderForm.partner", "default": "" }
799
+ * onChange: { "action": "setState", "key": "orderForm.partner", "fromEvent": true }
800
+ * 제출은 onSubmit에 submitForm 액션을 배선한다(Enter 제출 포함). 렌더러가 규칙 검증 후
801
+ * `{id}.$errors`(필드별 메시지) · `{id}.$submitting` · `{id}.$dirty`를 관리한다.
802
+ */
803
+ interface SduiFormProps {
804
+ id: string;
805
+ /** 최초 마운트 시 시드할 필드 기본값 */
806
+ initial?: Record<string, SduiPropValue>;
807
+ /**
808
+ * URL 쿼리에서 프리필할 필드 — { 필드명: 쿼리파라미터명 }.
809
+ * initial보다 우선하며, 파라미터가 없거나 이미 값이 있으면 건드리지 않는다.
810
+ */
811
+ initialFromUrl?: Record<string, string>;
812
+ /** 필드별 검증 규칙 */
813
+ rules?: Record<string, SduiRule[]>;
814
+ /** 에러 메시지용 필드 라벨 */
815
+ labels?: Record<string, string>;
816
+ /** true면 작성 중(dirty) 창 닫기/새로고침 시 확인을 띄운다 */
817
+ guard?: boolean;
818
+ onSubmit?: (event: React__default.FormEvent) => void;
819
+ className?: string;
820
+ style?: React__default.CSSProperties;
821
+ children?: React__default.ReactNode;
822
+ }
823
+ declare function SduiForm({ id, initial, initialFromUrl, rules, labels, guard, onSubmit, className, style, children, }: SduiFormProps): React__default.JSX.Element;
824
+
825
+ /**
826
+ * JSON 스펙의 `component` 이름 → 실제 컴포넌트.
827
+ * 이 키 목록이 곧 스펙에서 사용할 수 있는 컴포넌트 어휘 전체다.
828
+ * (ForEach는 렌더러 내장이라 등록하지 않는다.)
829
+ *
830
+ * 스펙의 props는 런타임에 오는 JSON이라 정적으로 검증할 수 없으므로 any를 쓴다.
831
+ */
832
+ type SduiRegistry = Record<string, ComponentType<any>>;
833
+ /**
834
+ * 기본 어휘.
835
+ *
836
+ * **여기 들어오는 조건은 "외부 의존성이 없을 것" 하나다.** 기본 레지스트리는 모듈
837
+ * 최상단에서 정적으로 import하므로, 여기 이름을 하나 올리면 그 컴포넌트가 끌고 오는
838
+ * 의존성이 core 번들에 그대로 붙는다 — 그 컴포넌트를 안 쓰는 스펙만 렌더하는
839
+ * 소비자도 예외 없이 내려받게 되고 트리셰이킹으로도 떼어낼 수 없다.
840
+ * 그래서 recharts가 필요한 `Chart`와 ol이 필요한 `MapPreview`는 여기 없다.
841
+ * `@wipco/sdui/rich`의 `richComponents`로 나가 있고, 필요한 소비자가
842
+ * `createRegistry(richComponents)`로 직접 얹는다(사용법은 그 파일 주석 참고).
843
+ */
844
+ declare const defaultRegistry: {
845
+ Alert: typeof Alert;
846
+ Badge: typeof Badge;
847
+ Button: typeof Button;
848
+ Card: typeof Card;
849
+ Checkbox: typeof Checkbox;
850
+ DatePicker: typeof DatePicker;
851
+ DateRangePicker: typeof DateRangePicker;
852
+ Dialog: typeof SduiDialog;
853
+ EmptyState: typeof EmptyState;
854
+ Field: typeof Field;
855
+ Icon: typeof Icon;
856
+ IconButton: typeof IconButton;
857
+ Input: typeof Input;
858
+ Pagination: typeof Pagination;
859
+ ProgressBar: typeof ProgressBar;
860
+ Select: typeof Select;
861
+ Spinner: typeof Spinner;
862
+ StatCard: typeof StatCard;
863
+ Switch: typeof Switch;
864
+ Table: typeof Table;
865
+ Tabs: typeof Tabs;
866
+ Tag: typeof Tag;
867
+ Textarea: typeof Textarea;
868
+ Toast: typeof Toast;
869
+ Actions: typeof Actions;
870
+ Col: typeof Col;
871
+ Divider: typeof Divider;
872
+ Grid: typeof Grid;
873
+ KeyValueList: typeof KeyValueList;
874
+ PageHead: typeof PageHead;
875
+ Row: typeof Row;
876
+ Section: typeof Section;
877
+ Show: typeof Show;
878
+ Spacer: typeof Spacer;
879
+ Text: typeof Text;
880
+ Form: typeof SduiForm;
881
+ Can: typeof Can;
882
+ SearchResults: typeof SduiSearchResults;
883
+ RemoteSearchResults: typeof RemoteSearchResults;
884
+ };
885
+ /**
886
+ * 기본 어휘에 앱 고유 컴포넌트를 더한 레지스트리를 만든다.
887
+ * 같은 이름을 주면 기본 컴포넌트를 덮어쓴다.
888
+ *
889
+ * `@wipco/sdui/rich`의 무거운 위젯도 이 함수로 얹는다 —
890
+ * `createRegistry(richComponents)`가 곧 Chart/MapPreview를 켜는 스위치다.
891
+ */
892
+ declare function createRegistry(extensions: SduiRegistry): SduiRegistry;
893
+
894
+ /** custom 액션을 앱 코드로 위임하는 확장 지점. */
895
+ type CustomActionHandler = (name: string, payload?: SduiPropValue, value?: unknown) => void;
896
+ /** custom 검증 규칙 구현 — 에러 메시지 또는 null 반환 */
897
+ type CustomValidator = (fieldValue: SduiPropValue | undefined, values: Record<string, SduiPropValue>) => string | null;
898
+ interface SduiRendererProps {
899
+ page: SduiPage;
900
+ /** 컴포넌트 어휘 — 생략 시 내장 기본 레지스트리 */
901
+ registry?: SduiRegistry;
902
+ /** 내비게이션·API·실시간 연결점 — 생략 시 브라우저 기본 구현 */
903
+ adapter?: SduiAdapter;
904
+ /**
905
+ * page.urlState ↔ URL 쿼리 동기화 여부 (기본 true).
906
+ * 편집기 미리보기처럼 실제 페이지 라우트가 아닌 곳에 마운트할 때 false로 끈다 —
907
+ * 안 그러면 미리보기의 상태가 호스트 앱 URL을 오염시킨다.
908
+ */
909
+ syncUrlState?: boolean;
910
+ onCustomAction?: CustomActionHandler;
911
+ customValidators?: Record<string, CustomValidator>;
912
+ }
913
+ /**
914
+ * 서버(JSON 스펙) 주도 페이지 렌더러.
915
+ * 스펙은 직렬화 가능한 데이터만 담고, 상태·이벤트·폼·내비게이션은 여기서 해석한다.
916
+ */
917
+ declare function SduiRenderer({ page, registry, adapter, syncUrlState, onCustomAction, customValidators, }: SduiRendererProps): React__default.JSX.Element;
918
+
919
+ /**
920
+ * 스펙 구조 검증기 — 서버(또는 편집기)가 만든 스펙의 형태 오류를 렌더 전에 찾아낸다.
921
+ * 렌더러는 개발 모드에서 이 결과를 콘솔에 경고하고, 관리자 편집기는
922
+ * 저장 전에 같은 검사를 돌려 문제 목록을 보여준다.
923
+ */
924
+ interface SpecIssue {
925
+ path: string;
926
+ message: string;
927
+ }
928
+ declare function validateSpec(page: unknown, knownComponents?: Set<string>): SpecIssue[];
929
+
930
+ /**
931
+ * 권한 판정 주입 지점.
932
+ *
933
+ * 라이브러리는 **특정 권한 모델을 알지 않는다**. ERP는 권한을
934
+ * `{ entity, actions: CRUD[], scope }`로 두고 scope 서열(team<group<division<all)로
935
+ * 판정하지만, SDUI는 다른 프로젝트에도 쓰이므로 그 규칙을 core에 박아 넣을 수 없다.
936
+ * 그래서 "질의 형태"만 계약으로 정하고 판정은 호스트 앱이 주입한다.
937
+ */
938
+
939
+ /** `Can`이 호스트에 던지는 질의. entity/action은 문자열이면 무엇이든 된다(도메인 어휘는 호스트 소유). */
940
+ interface SduiCanQuery {
941
+ /** 대상 엔티티 식별자 (예: "asset", "contract") */
942
+ entity: string;
943
+ /** 수행 동작 (ERP 기준 create/read/update/delete) */
944
+ action: string;
945
+ /** 최소 적용 범위 — 생략 시 호스트가 자기 기본값(ERP라면 'team')으로 판단한다 */
946
+ scope?: string;
947
+ }
948
+ type SduiCanFn = (query: SduiCanQuery) => boolean;
949
+ /**
950
+ * 권한 판정 설정.
951
+ * - 함수: 호스트 앱의 실제 판정
952
+ * - `'allow-all'`/`'deny-all'`: 판정 없이 전부 통과/차단하겠다는 **명시적** 선언
953
+ * (편집기 미리보기·스토리북·테스트처럼 세션이 없는 자리에서 쓴다)
954
+ */
955
+ type SduiCanSetting = SduiCanFn | 'allow-all' | 'deny-all';
956
+ interface SduiPermissionProviderProps {
957
+ can?: SduiCanSetting;
958
+ children?: React__default.ReactNode;
959
+ }
960
+ /**
961
+ * 권한 판정을 하위 트리에 공급한다. SduiRenderer가 자기 `can` 프롭을 이 provider로 흘려보낸다.
962
+ * 렌더러 밖에서 직접 감싸도 동작한다(테스트·스토리북).
963
+ */
964
+ declare function SduiPermissionProvider({ can, children }: SduiPermissionProviderProps): React__default.JSX.Element;
965
+ /**
966
+ * 권한 판정기. 주입되지 않았으면 {@link MISSING}(경고 후 통과)을 돌려준다 —
967
+ * useSduiDispatch처럼 던지지 않는다. 권한 게이트 하나 때문에 페이지가 죽으면 안 된다.
968
+ */
969
+ declare function useSduiCan(): SduiCanFn;
970
+
971
+ /** SduiRenderer가 제공하는 액션 디스패처. 레지스트리의 복합 컴포넌트가 선언적 액션을 실행할 때 쓴다. */
972
+ type SduiDispatch = (action: SduiAction, eventValue?: unknown) => void;
973
+ declare function useSduiDispatch(): SduiDispatch;
974
+
975
+ /** Form이 렌더러에 등록하는 검증 설정 */
976
+ interface SduiFormConfig {
977
+ rules: Record<string, SduiRule[]>;
978
+ /** 에러 메시지에 쓸 필드 라벨 (없으면 필드 키) */
979
+ labels: Record<string, string>;
980
+ }
981
+ /**
982
+ * 렌더러 런타임 — 페이지 상태와 폼 레지스트리에 대한 접근.
983
+ * SduiForm 등 상태와 직접 상호작용해야 하는 스마트 컴포넌트가 쓴다.
984
+ */
985
+ interface SduiRuntime {
986
+ state: Record<string, SduiPropValue | undefined>;
987
+ setEntries: (entries: Record<string, SduiPropValue | undefined>) => void;
988
+ registerForm: (id: string, config: SduiFormConfig) => void;
989
+ unregisterForm: (id: string) => void;
990
+ }
991
+ declare function useSduiRuntime(): SduiRuntime;
992
+
993
+ interface Props {
994
+ name: string;
995
+ children: React__default.ReactNode;
996
+ }
997
+ interface State {
998
+ error: Error | null;
999
+ }
1000
+ /**
1001
+ * 노드 단위 에러 바운더리 — 스펙의 한 노드가 렌더 중 던져도
1002
+ * 그 노드 자리에만 오류 카드를 남기고 페이지 나머지는 살린다.
1003
+ */
1004
+ declare class NodeErrorBoundary extends React__default.Component<Props, State> {
1005
+ state: State;
1006
+ static getDerivedStateFromError(error: Error): State;
1007
+ componentDidCatch(error: Error): void;
1008
+ componentDidUpdate(prevProps: Props): void;
1009
+ render(): string | number | bigint | boolean | React__default.JSX.Element | Iterable<React__default.ReactNode> | Promise<string | number | bigint | boolean | React__default.ReactPortal | React__default.ReactElement<unknown, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined> | null | undefined;
1010
+ }
1011
+
1012
+ export { Actions, type ActionsProps, Alert, type AlertProps, Badge, type BadgeProps, type BadgeTone, Button, type ButtonProps, Can, type CanProps, Card, type CardProps, type CascadingSearchOption, Checkbox, type CheckboxProps, Col, type CustomActionHandler, type CustomValidator, DatePicker, DateRangePicker, Dialog, type DialogProps, Divider, EmptyState, type EmptyStateProps, Field, type FieldProps, Grid, type GridCardConfig, type GridCardRow, type GridProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, type Justify, type KeyValueItem, KeyValueList, type KeyValueListProps, NodeErrorBoundary, PageHead, type PageHeadProps, Pagination, type PaginationProps, ProgressBar, type ProgressBarProps, RemoteSearchResults, type RemoteSearchResultsProps, ResultTable, type ResultTableColumn, type ResultTableProps, Row, type RowProps, SduiAction, type SduiAdapter, type SduiCanFn, type SduiCanQuery, type SduiCanSetting, SduiDialog, type SduiDispatch, SduiForm, type SduiFormConfig, type SduiFormProps, type SduiGridCard, SduiPage, SduiPermissionProvider, SduiPropValue, type SduiRegistry, SduiRenderer, type SduiRendererProps, SduiRule, type SduiRuntime, type SduiSearchAction, type SduiSearchColumn, SduiSearchDataProvider, SduiSearchResults, type SduiSearchResultsProps, type SearchAction, type SearchColumn, type SearchFetcher, type SearchField, type SearchFilter, type SearchOption, type SearchPage, SearchResults, type SearchResultsProps, type SearchRow, SearchToolbar, type SearchValues, Section, type SectionProps, Select, type SelectOption, type SelectProps, Show, type ShowProps, type SortDir, Spacer, type SpacerProps, type SpecIssue, Spinner, type SpinnerProps, StatCard, type StatCardProps, Switch, type SwitchProps, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextPreset, type TextProps, Textarea, type TextareaProps, Toast, type ToastProps, cascadingValuePaths, cleanSearchValues, createRegistry, defaultAdapter, defaultRegistry, includesLooseSearch, joinMultiValue, normalizeSearchText, searchFieldKeys, searchValuesFromParams, splitMultiValue, useRemoteSearchPage, useSduiCan, useSduiDispatch, useSduiRuntime, useSearchFetcher, validateSpec };