@wipco/sdui 0.30.0 → 0.32.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/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
- import { TimePicker } from './chunk-WXOU7QTN.js';
2
- export { TimePicker, loadOptionalModule } from './chunk-WXOU7QTN.js';
1
+ export { loadOptionalModule } from './chunk-RRMKCZYQ.js';
3
2
  import { useSduiDispatch, SduiDialog, useSduiCan, SduiDispatchContext, SduiPermissionProvider } from './chunk-QU7YVMFA.js';
4
3
  export { SduiDialog, SduiPermissionProvider, useSduiCan, useSduiDispatch } from './chunk-QU7YVMFA.js';
4
+ import { Text, Spacer, Show, Section, Row, PageHead, KeyValueList, Grid, Divider, Col, Actions } from './chunk-QO6UJAQN.js';
5
+ export { Actions, Col, Divider, Grid, KeyValueList, PageHead, Row, Section, Show, Spacer, Text } from './chunk-QO6UJAQN.js';
5
6
  import { ImageViewer } from './chunk-THEP3VWY.js';
6
7
  export { ImageViewer } from './chunk-THEP3VWY.js';
8
+ import { TimePicker } from './chunk-SNRKPEWT.js';
9
+ export { TimePicker } from './chunk-SNRKPEWT.js';
7
10
  import { normalizeSearchFields, searchValuesFromParams, splitMultiValue, includesLooseSearch, cascadingValuePaths, SearchToolbar, searchFieldKeys, Popover } from './chunk-BD75U73S.js';
8
11
  export { SearchToolbar, cascadingValuePaths, cleanSearchValues, includesLooseSearch, joinMultiValue, normalizeSearchText, searchFieldKeys, searchValuesFromParams, splitMultiValue } from './chunk-BD75U73S.js';
9
12
  import { HoistedStyle, DateRangePicker, DatePicker } from './chunk-EFMKWPZ3.js';
@@ -13,9 +16,9 @@ import { DEV, isSafeNavigationTarget, useSduiAdapter, hostFetchOf, useSduiSandbo
13
16
  export { defaultAdapter, useSduiAssetResolver, useSduiSandbox } from './chunk-DKPNFEVU.js';
14
17
  import { EmptyState, Button, Checkbox, SegmentedControl, Spinner, Select, Pagination, Icon, Card, Badge, ProgressBar, Tag, Toast, Textarea, Tabs, Table, Switch, StatCard, Input, IconButton, Field, Alert, warnOnce } from './chunk-WIDDHR7L.js';
15
18
  export { Alert, Avatar, Badge, Breadcrumb, Button, Card, Checkbox, Dialog, EmptyState, Field, Icon, IconButton, Input, Pagination, ProgressBar, Radio, SegmentedControl, Select, SidebarNav, Spinner, StatCard, Switch, Table, Tabs, Tag, Textarea, Toast, Tooltip } from './chunk-WIDDHR7L.js';
16
- import { boxed, mergeStyle, containerLayoutStyle, joinClass, columnsClass, typographyStyle, LAYOUT_CSS, childLayoutFrom, CHILD_LAYOUT_PROPS } from './chunk-SAN4IX6N.js';
19
+ import { boxed, LAYOUT_CSS, childLayoutFrom, CHILD_LAYOUT_PROPS } from './chunk-SAN4IX6N.js';
17
20
  export { CHILD_LAYOUT_PROPS, LAYOUT_CSS, boxed, childLayoutFrom, columnsClass, containerLayoutStyle, joinClass, mergeStyle, typographyStyle } from './chunk-SAN4IX6N.js';
18
- import React10, { createContext, useState, useMemo, useRef, useEffect, useCallback, useContext } from 'react';
21
+ import React9, { createContext, useState, useMemo, useRef, useEffect, useCallback, useContext } from 'react';
19
22
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
20
23
 
21
24
  // src/asset-url.ts
@@ -112,7 +115,7 @@ function resolveAssetsIn(propName, value, resolve, component) {
112
115
  return out ?? record;
113
116
  }
114
117
  }
115
- var NodeErrorBoundary = class extends React10.Component {
118
+ var NodeErrorBoundary = class extends React9.Component {
116
119
  state = { error: null };
117
120
  static getDerivedStateFromError(error) {
118
121
  return { error };
@@ -160,145 +163,6 @@ function Can({ entity, action = "read", scope, fallback = null, children }) {
160
163
  }
161
164
  return can({ entity, action: typeof action === "string" ? action : "read", scope }) ? /* @__PURE__ */ jsx(Fragment, { children }) : /* @__PURE__ */ jsx(Fragment, { children: fallback });
162
165
  }
163
- function paddingStyle(padding) {
164
- const value = padding === void 0 ? void 0 : PADDING_CSS[padding];
165
- return value === void 0 ? {} : { padding: value };
166
- }
167
- var PADDING_CSS = {
168
- "2": "2px",
169
- "4": "4px",
170
- "8": "8px",
171
- "12": "12px",
172
- "16": "16px",
173
- "20": "20px",
174
- "24": "24px",
175
- "32": "32px"
176
- };
177
- function Grid({
178
- columns = 3,
179
- template,
180
- gap,
181
- align,
182
- justify,
183
- wrap,
184
- padding,
185
- className,
186
- style,
187
- children
188
- }) {
189
- return /* @__PURE__ */ jsx(
190
- "div",
191
- {
192
- className: joinClass("wp-grid", !template && columnsClass(columns), className),
193
- style: mergeStyle(
194
- {
195
- ...template ? { gridTemplateColumns: template } : null,
196
- ...containerLayoutStyle({ gap, align, justify, wrap }),
197
- ...paddingStyle(padding)
198
- },
199
- style
200
- ),
201
- children
202
- }
203
- );
204
- }
205
- function Row({ justify, gap, align, wrap, className, style, children }) {
206
- return /* @__PURE__ */ jsx(
207
- "div",
208
- {
209
- className: joinClass("wp-row", justify === "between" && "wp-row--between", className),
210
- style: mergeStyle(containerLayoutStyle({ gap, align, justify, wrap }), style),
211
- children
212
- }
213
- );
214
- }
215
- function Actions({ justify = "end", gap, align, wrap, className, style, children }) {
216
- return /* @__PURE__ */ jsx(
217
- "div",
218
- {
219
- className: joinClass("wp-row", className),
220
- style: mergeStyle({ flex: 1, ...containerLayoutStyle({ gap, align, justify, wrap }) }, style),
221
- children
222
- }
223
- );
224
- }
225
- function Col({ gap, align, justify, wrap, className, style, children }) {
226
- return /* @__PURE__ */ jsx("div", { className: joinClass("wp-col", className), style: mergeStyle(containerLayoutStyle({ gap, align, justify, wrap }), style), children });
227
- }
228
- var SPACER_STEPS = /* @__PURE__ */ new Set([1, 2, 3, 4, 5, 6, 8]);
229
- function Spacer({ size, className, style }) {
230
- const step = size !== void 0 && SPACER_STEPS.has(Number(size)) ? Number(size) : void 0;
231
- return /* @__PURE__ */ jsx(
232
- "div",
233
- {
234
- className: joinClass("wp-spacer", step !== void 0 && `wp-spacer--${step}`, className),
235
- style
236
- }
237
- );
238
- }
239
- function Section({ title, gap, align, justify, wrap, className, style, children }) {
240
- return /* @__PURE__ */ jsxs(
241
- "section",
242
- {
243
- className: joinClass("wp-col", className),
244
- style: mergeStyle(containerLayoutStyle({ gap, align, justify, wrap }), style),
245
- children: [
246
- title ? /* @__PURE__ */ jsx("h2", { className: "wp-h4", children: title }) : null,
247
- children
248
- ]
249
- }
250
- );
251
- }
252
- var TEXT_WRAP_CSS = {
253
- normal: {},
254
- preserve: { whiteSpace: "pre-wrap" },
255
- anywhere: { whiteSpace: "pre-wrap", wordBreak: "break-all" }
256
- };
257
- function Text({
258
- preset = "body",
259
- as: Tag2 = "p",
260
- weight,
261
- textAlign,
262
- wrap,
263
- className,
264
- style,
265
- value,
266
- children
267
- }) {
268
- return /* @__PURE__ */ jsx(
269
- Tag2,
270
- {
271
- className: joinClass(`wp-${preset}`, className),
272
- style: mergeStyle({ ...typographyStyle({ weight, textAlign }), ...TEXT_WRAP_CSS[wrap ?? "normal"] }, style),
273
- children: value ?? children
274
- }
275
- );
276
- }
277
- function KeyValueList({ source, items, className, style }) {
278
- return /* @__PURE__ */ jsx("div", { className: joinClass("wp-kv", className), style, children: (items ?? []).map((item, index) => {
279
- const raw = item.key ? source?.[item.key] : item.value;
280
- const content = raw === null || raw === void 0 || raw === "" ? "\u2014" : raw;
281
- return /* @__PURE__ */ jsxs(React10.Fragment, { children: [
282
- /* @__PURE__ */ jsx("span", { className: "wp-kv__k", children: item.label }),
283
- /* @__PURE__ */ jsx("span", { className: joinClass("wp-kv__v", item.mono && "wp-mono"), children: content })
284
- ] }, index);
285
- }) });
286
- }
287
- function PageHead({ title, subtitle, actions, className, style }) {
288
- return /* @__PURE__ */ jsxs("div", { className: joinClass("wp-page-head", className), style, children: [
289
- /* @__PURE__ */ jsxs("div", { className: "wp-page-head__text", children: [
290
- title ? /* @__PURE__ */ jsx("h1", { className: "wp-page-head__title", children: title }) : null,
291
- subtitle ? /* @__PURE__ */ jsx("div", { className: "wp-page-head__sub", children: subtitle }) : null
292
- ] }),
293
- actions ? /* @__PURE__ */ jsx("div", { className: "wp-page-head__actions", children: actions }) : null
294
- ] });
295
- }
296
- function Show({ when, children }) {
297
- return when ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
298
- }
299
- function Divider({ style, className }) {
300
- return /* @__PURE__ */ jsx("hr", { className: joinClass("wp-divider", className), style });
301
- }
302
166
  function imageRenderer(cell, key, width = cell.width ?? 72) {
303
167
  const height = cell.height ?? 52;
304
168
  return (row) => /* @__PURE__ */ jsx(
@@ -2639,7 +2503,7 @@ function SduiNodeRenderer({
2639
2503
  return /* @__PURE__ */ jsx(Fragment, { children: rows.map((item, rowIndex) => {
2640
2504
  const rowScope = [...scope, { item, index: rowIndex }];
2641
2505
  const rowKey = isPlainObject4(item) && typeof item.id === "string" ? item.id : rowIndex;
2642
- return /* @__PURE__ */ jsx(React10.Fragment, { children: childList?.map((child, i) => renderChild(child, i, rowScope, engine)) }, rowKey);
2506
+ return /* @__PURE__ */ jsx(React9.Fragment, { children: childList?.map((child, i) => renderChild(child, i, rowScope, engine)) }, rowKey);
2643
2507
  }) });
2644
2508
  }
2645
2509
  if (node.component === "Fragment") {
@@ -2715,11 +2579,11 @@ function SduiNodeRenderer({
2715
2579
  const children = childList?.map((child, i) => renderChild(child, i, scope, engine));
2716
2580
  return /* @__PURE__ */ jsx(Component, { ...props, children });
2717
2581
  }
2718
- var SduiFragmentChainContext = React10.createContext([]);
2582
+ var SduiFragmentChainContext = React9.createContext([]);
2719
2583
  var FRAGMENT_MAX_DEPTH = 4;
2720
2584
  function SduiFragment({ node, scope, engine }) {
2721
2585
  const adapter = useSduiAdapter();
2722
- const chain = React10.useContext(SduiFragmentChainContext);
2586
+ const chain = React9.useContext(SduiFragmentChainContext);
2723
2587
  const raw = isPlainObject4(node.props) ? node.props.id : void 0;
2724
2588
  const id = engine.resolveValue(raw, scope);
2725
2589
  if (typeof id !== "string" || id === "") {
@@ -2774,9 +2638,9 @@ function SduiFragmentBody({
2774
2638
  engine
2775
2639
  }) {
2776
2640
  const spec = useSpec(id);
2777
- const nextChain = React10.useMemo(() => [...chain, id], [chain, id]);
2778
- const bodyScope = React10.useMemo(() => [...scope, { args, callSiteScope: scope }], [scope, args]);
2779
- React10.useEffect(() => {
2641
+ const nextChain = React9.useMemo(() => [...chain, id], [chain, id]);
2642
+ const bodyScope = React9.useMemo(() => [...scope, { args, callSiteScope: scope }], [scope, args]);
2643
+ React9.useEffect(() => {
2780
2644
  if (!DEV || !isPlainObject4(spec) || !Array.isArray(spec.body)) return;
2781
2645
  validateSpec(spec, new Set(Object.keys(engine.registry))).forEach(
2782
2646
  (issue) => console.warn(`[sdui:spec:${id}] ${issue.path} \u2014 ${issue.message}`)
@@ -3267,4 +3131,4 @@ function SduiRenderer({
3267
3131
  );
3268
3132
  }
3269
3133
 
3270
- export { Actions, CALC_OPS, Can, Col, Divider, Grid, KeyValueList, NodeErrorBoundary, PageHead, RemoteSearchResults, ResultTable, Row, SduiForm, SduiRenderer, SduiSearchDataProvider, SduiSearchResults, SearchResults, Section, Show, SortHandle, SortableList, Spacer, Text, cellRenderer, createRegistry, defaultRegistry, imageRenderer, normalizePageSizes, sortableDropIndex, sortableMove, useRemoteSearchPage, useSduiRuntime, useSearchFetcher, validateSpec };
3134
+ export { CALC_OPS, Can, NodeErrorBoundary, RemoteSearchResults, ResultTable, SduiForm, SduiRenderer, SduiSearchDataProvider, SduiSearchResults, SearchResults, SortHandle, SortableList, cellRenderer, createRegistry, defaultRegistry, imageRenderer, normalizePageSizes, sortableDropIndex, sortableMove, useRemoteSearchPage, useSduiRuntime, useSearchFetcher, validateSpec };
package/dist/meta.d.ts CHANGED
@@ -431,6 +431,10 @@ declare const OrgChartBoardMeta: SduiComponentMeta;
431
431
  declare const PermissionMatrixEditorMeta: SduiComponentMeta;
432
432
  declare const RoleMemberPickerMeta: SduiComponentMeta;
433
433
  declare const FileDropzoneMeta: SduiComponentMeta;
434
+ declare const ExcelUploadCardMeta: SduiComponentMeta;
435
+ declare const OptionSchemaEditorMeta: SduiComponentMeta;
436
+ declare const OptionValueFieldsMeta: SduiComponentMeta;
437
+ declare const StagePeriodEditorMeta: SduiComponentMeta;
434
438
  declare const AutocompleteFieldMeta: SduiComponentMeta;
435
439
  declare const InlineEditMeta: SduiComponentMeta;
436
440
  declare const JsonFieldMeta: SduiComponentMeta;
@@ -456,7 +460,7 @@ declare const StripMeta: SduiComponentMeta;
456
460
  /**
457
461
  * 위젯 어휘의 메타데이터.
458
462
  *
459
- * 키 타입이 `SduiWidgetComponentName | 'AutocompleteField' | 'FileDropzone'`인 이유:
463
+ * 키 타입이 `SduiWidgetComponentName | 'AutocompleteField' | 'FileDropzone' | 'ExcelUploadCard'`인 이유:
460
464
  * 앞의 20종은 `widgetComponents`와 키가 어긋나면 컴파일 에러가 나야 하고(core·rich와 같다),
461
465
  * `AutocompleteField`는 그 묶음에 **일부러 빠져 있는** 이름이라 union에 직접 적어야 한다.
462
466
  * 표시 계층만 라이브러리에 있고 조회는 앱 어댑터가 얹는 구조인데(widgets/index.ts 참고),
@@ -467,6 +471,10 @@ declare const widgetComponentMeta: {
467
471
  ApprovalLineEditor: SduiComponentMeta;
468
472
  ApprovalOverridesEditor: SduiComponentMeta;
469
473
  ApprovalStepper: SduiComponentMeta;
474
+ OptionSchemaEditor: SduiComponentMeta;
475
+ OptionValueFields: SduiComponentMeta;
476
+ StagePeriodEditor: SduiComponentMeta;
477
+ ExcelUploadCard: SduiComponentMeta;
470
478
  FileDropzone: SduiComponentMeta;
471
479
  PermissionMatrixEditor: SduiComponentMeta;
472
480
  RoleMemberPicker: SduiComponentMeta;
@@ -604,4 +612,4 @@ declare function paletteGroups(catalog?: Record<string, SduiComponentMeta>): Arr
604
612
  items: SduiComponentMeta[];
605
613
  }>;
606
614
 
607
- export { ActionsMeta, AlertMeta, ApprovalLineEditorMeta, ApprovalOverridesEditorMeta, ApprovalStepperMeta, AutocompleteFieldMeta, AvatarMeta, BadgeMeta, BreadcrumbMeta, ButtonMeta, CanMeta, CardMeta, ChartMeta, CheckboxMeta, ColMeta, ColumnBoardMeta, DatePickerMeta, DateRangePickerMeta, DialogMeta, DiffViewMeta, DisclosureMeta, DividerMeta, EmptyStateMeta, EventCalendarMeta, FieldMeta, FileDropzoneMeta, ForEachMeta, FormMeta, FragmentMeta, GridMeta, IconButtonMeta, IconMeta, ImageLightboxMeta, InlineEditMeta, InputMeta, JsonFieldMeta, KeyValueListMeta, LiveClockMeta, MapPreviewMeta, OrgChartBoardMeta, OrgChartMeta, PageHeadMeta, PaginationMeta, PeriodFilterMeta, PermissionMatrixEditorMeta, PrintSheetMeta, ProgressBarMeta, RadioMeta, RankBoardMeta, RecordSheetMeta, RemoteSearchResultsMeta, RoleMemberPickerMeta, RowMeta, SDUI_CATEGORIES, SELF_AXIS_PROPS, type SduiCategory, type SduiChildrenMeta, type SduiComponentMeta, type SduiDomMeta, type SduiEnumOption, type SduiPropGroup, type SduiPropKind, type SduiPropMeta, type SduiResizeMeta, type SduiSlotMeta, SearchResultsMeta, SearchableMultiPickerMeta, SectionMeta, SecureScreenMeta, SegmentedControlMeta, SelectMeta, ShowMeta, SidebarNavMeta, SortHandleMeta, SortableListMeta, SpacerMeta, SpinnerMeta, StackedMeterMeta, StatCardMeta, StripMeta, SummaryTableMeta, SwitchMeta, TableMeta, TabsMeta, TagMeta, TagMultiSelectMeta, TextMeta, TextareaMeta, TimePickerMeta, TimelineMeta, ToastMeta, TooltipMeta, TreePickerMeta, TreeViewMeta, allComponentMeta, builtinComponentMeta, coreComponentMeta, dsComponentMeta, getComponentMeta, paletteGroups, richComponentMeta, slotNamesOf, widgetComponentMeta, withSelfAxis, withSelfAxisAll };
615
+ export { ActionsMeta, AlertMeta, ApprovalLineEditorMeta, ApprovalOverridesEditorMeta, ApprovalStepperMeta, AutocompleteFieldMeta, AvatarMeta, BadgeMeta, BreadcrumbMeta, ButtonMeta, CanMeta, CardMeta, ChartMeta, CheckboxMeta, ColMeta, ColumnBoardMeta, DatePickerMeta, DateRangePickerMeta, DialogMeta, DiffViewMeta, DisclosureMeta, DividerMeta, EmptyStateMeta, EventCalendarMeta, ExcelUploadCardMeta, FieldMeta, FileDropzoneMeta, ForEachMeta, FormMeta, FragmentMeta, GridMeta, IconButtonMeta, IconMeta, ImageLightboxMeta, InlineEditMeta, InputMeta, JsonFieldMeta, KeyValueListMeta, LiveClockMeta, MapPreviewMeta, OptionSchemaEditorMeta, OptionValueFieldsMeta, OrgChartBoardMeta, OrgChartMeta, PageHeadMeta, PaginationMeta, PeriodFilterMeta, PermissionMatrixEditorMeta, PrintSheetMeta, ProgressBarMeta, RadioMeta, RankBoardMeta, RecordSheetMeta, RemoteSearchResultsMeta, RoleMemberPickerMeta, RowMeta, SDUI_CATEGORIES, SELF_AXIS_PROPS, type SduiCategory, type SduiChildrenMeta, type SduiComponentMeta, type SduiDomMeta, type SduiEnumOption, type SduiPropGroup, type SduiPropKind, type SduiPropMeta, type SduiResizeMeta, type SduiSlotMeta, SearchResultsMeta, SearchableMultiPickerMeta, SectionMeta, SecureScreenMeta, SegmentedControlMeta, SelectMeta, ShowMeta, SidebarNavMeta, SortHandleMeta, SortableListMeta, SpacerMeta, SpinnerMeta, StackedMeterMeta, StagePeriodEditorMeta, StatCardMeta, StripMeta, SummaryTableMeta, SwitchMeta, TableMeta, TabsMeta, TagMeta, TagMultiSelectMeta, TextMeta, TextareaMeta, TimePickerMeta, TimelineMeta, ToastMeta, TooltipMeta, TreePickerMeta, TreeViewMeta, allComponentMeta, builtinComponentMeta, coreComponentMeta, dsComponentMeta, getComponentMeta, paletteGroups, richComponentMeta, slotNamesOf, widgetComponentMeta, withSelfAxis, withSelfAxisAll };
package/dist/meta.js CHANGED
@@ -3949,6 +3949,234 @@ var FileDropzoneMeta = {
3949
3949
  },
3950
3950
  resize: { kind: "none" }
3951
3951
  };
3952
+ var ExcelUploadCardMeta = {
3953
+ name: "ExcelUploadCard",
3954
+ label: "\uC5D1\uC140 \uC77C\uAD04 \uC5C5\uB85C\uB4DC",
3955
+ category: "data",
3956
+ icon: "cloud-upload",
3957
+ description: "\uC5D1\uC140 \uC77C\uAD04 \uC5C5\uB85C\uB4DC \uCE74\uB4DC. server\uB294 \uD30C\uC77C\uC744 \uADF8\uB300\uB85C \uC62C\uB824 \uCC98\uB9AC \uC694\uC57D\uC744 \uBC1B\uACE0, preview\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD30C\uC2F1\xB7\uAC80\uC99D\uD558\uACE0 \uC624\uB958 \uC140\uC744 \uACE0\uCE5C \uB4A4 \uC720\uD6A8 \uD589\uB9CC \uBCF4\uB0B8\uB2E4.",
3958
+ props: [
3959
+ {
3960
+ name: "mode",
3961
+ kind: "enum",
3962
+ label: "\uB3D9\uC791 \uBC29\uC2DD",
3963
+ default: "server",
3964
+ options: [
3965
+ { value: "server", label: "\uC11C\uBC84 \uC5C5\uB85C\uB4DC", description: "\uD30C\uC77C\uC744 multipart\uB85C \uC62C\uB9AC\uACE0 \uCC98\uB9AC \uC694\uC57D\xB7\uD589 \uC624\uB958\uB97C \uBC1B\uB294\uB2E4" },
3966
+ { value: "preview", label: "\uBBF8\uB9AC\uBCF4\uAE30 \uAC80\uC99D", description: "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD30C\uC2F1\xB7\uAC80\uC99D\uD558\uACE0 \uC624\uB958 \uC140\uC744 \uC778\uB77C\uC778 \uC218\uC815\uD55C \uB4A4 \uC720\uD6A8 \uD589\uB9CC \uBCF4\uB0B8\uB2E4" }
3967
+ ],
3968
+ group: "behavior"
3969
+ },
3970
+ // 실측 8/8 (preview×5, server×3)
3971
+ {
3972
+ name: "endpoint",
3973
+ kind: "string",
3974
+ label: "\uC5C5\uB85C\uB4DC \uACBD\uB85C",
3975
+ description: "server\uBA74 \uD30C\uC77C multipart POST \uB300\uC0C1, preview\uBA74 \uAC80\uC99D\uB41C { rows } JSON POST \uB300\uC0C1.",
3976
+ group: "data"
3977
+ },
3978
+ // 실측 7/8
3979
+ {
3980
+ name: "templateColumns",
3981
+ kind: "array",
3982
+ label: "\uD15C\uD50C\uB9BF \uCEEC\uB7FC",
3983
+ description: "\uC788\uC73C\uBA74 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD15C\uD50C\uB9BF xlsx\uB97C \uB9CC\uB4E0\uB2E4(\uBC31\uC5D4\uB4DC \uBD88\uD544\uC694). 2\uD589\uC5D0 \uC608\uC2DC\uAC12\uC774 \uB4E4\uC5B4\uAC04\uB2E4.",
3984
+ group: "data",
3985
+ // 실측 8/8, 원소 54개 — key·header·example 세 키가 모두 54/54로 항상 채워져 있다.
3986
+ item: [
3987
+ { name: "key", kind: "string", label: "\uD0A4", required: true },
3988
+ { name: "header", kind: "string", label: "\uD5E4\uB354", required: true },
3989
+ { name: "example", kind: "string", label: "\uC608\uC2DC\uAC12", description: "\uD15C\uD50C\uB9BF 2\uD589\uC5D0 \uB4E4\uC5B4\uAC04\uB2E4." }
3990
+ ]
3991
+ },
3992
+ {
3993
+ name: "columns",
3994
+ kind: "array",
3995
+ label: "\uAC80\uC99D \uC2A4\uD0A4\uB9C8",
3996
+ description: "preview \uBAA8\uB4DC\uC758 \uD30C\uC2F1\xB7\uAC80\uC99D \uAE30\uC900. \uC2E4\uCE21\uC0C1 preview \uC778\uC2A4\uD134\uC2A4 5\uAC1C\uC640 \uC815\uD655\uD788 \uC77C\uCE58\uD55C\uB2E4.",
3997
+ group: "data",
3998
+ // 실측 5/8, 원소 34개 — key·header 34/34, required 17/34(값은 전부 true), options 9/34.
3999
+ item: [
4000
+ { name: "key", kind: "string", label: "\uD0A4", required: true },
4001
+ { name: "header", kind: "string", label: "\uC5D1\uC140 \uD5E4\uB354", required: true, description: "\uD55C\uAD6D\uC5B4 \uBCC4\uCE6D. key\uC640\uB3C4 \uB9E4\uCE6D\uB41C\uB2E4." },
4002
+ { name: "required", kind: "boolean", label: "\uD544\uC218", default: false },
4003
+ {
4004
+ name: "options",
4005
+ kind: "array",
4006
+ label: "\uD5C8\uC6A9\uAC12",
4007
+ description: "\uC788\uC73C\uBA74 \uC624\uB958 \uC140\uC744 Select\uB85C, \uC5C6\uC73C\uBA74 Input\uC73C\uB85C \uACE0\uCE5C\uB2E4.",
4008
+ item: [],
4009
+ itemKind: "string"
4010
+ }
4011
+ ]
4012
+ },
4013
+ {
4014
+ name: "summaryLabels",
4015
+ kind: "object",
4016
+ label: "\uC694\uC57D \uD0C0\uC77C \uB77C\uBCA8",
4017
+ // fields를 적지 않아 자유 JSON으로 둔다 — 키가 백엔드 응답의 숫자 필드 이름이라
4018
+ // 엔드포인트마다 다르다. 실측에서도 rows(3)·createdUnits(2) 외에 skippedRows·
4019
+ // createdAssets·skippedUnits·createdBorrows·skippedBorrows가 각 1회씩으로 전부 달랐다.
4020
+ description: "\uC11C\uBC84 \uC751\uB2F5\uC758 \uC22B\uC790 \uD544\uB4DC \uC774\uB984 \u2192 \uC694\uC57D \uD0C0\uC77C\uC5D0 \uC4F8 \uB77C\uBCA8. server \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC4F0\uC778\uB2E4.",
4021
+ group: "content"
4022
+ },
4023
+ // 실측 3/8 — server 인스턴스 3개와 일치
4024
+ {
4025
+ name: "templateEndpoint",
4026
+ kind: "string",
4027
+ label: "\uD15C\uD50C\uB9BF \uB2E4\uC6B4\uB85C\uB4DC \uACBD\uB85C",
4028
+ description: "templateColumns\uAC00 \uC5C6\uC744 \uB54C\uB9CC \uC4F0\uC778\uB2E4(blob \uB2E4\uC6B4\uB85C\uB4DC).",
4029
+ group: "data",
4030
+ advanced: true
4031
+ },
4032
+ // 실측 0/8 — 구현에는 있다
4033
+ {
4034
+ name: "onComplete",
4035
+ kind: "action",
4036
+ label: "\uC644\uB8CC",
4037
+ eventArg: "server\uBA74 \uC751\uB2F5 JSON, preview\uBA74 \uC11C\uBC84 \uC751\uB2F5 \uB610\uB294 \uAC80\uC99D\uB41C \uC720\uD6A8 \uD589 \uBC30\uC5F4",
4038
+ group: "behavior"
4039
+ }
4040
+ // 실측 5/8 — 단일 toast×3, 액션 배열×2(close→toast)
4041
+ ],
4042
+ children: { accepts: false },
4043
+ dom: { element: "div" },
4044
+ // 실측: 루트가 라이브러리 Card → <div class="wp-card">
4045
+ // 프리셋에 endpoint·templateEndpoint를 넣지 않는다. 이 조합이면 템플릿은 브라우저에서
4046
+ // xlsx로 만들고, 가져오기도 onComplete만 부른다 → 바깥으로 나가는 요청이 0건이다.
4047
+ preset: {
4048
+ component: "ExcelUploadCard",
4049
+ props: {
4050
+ mode: "preview",
4051
+ templateColumns: [
4052
+ { key: "name", header: "\uD488\uBAA9\uBA85", example: "\uB178\uD2B8\uBD81" },
4053
+ { key: "qty", header: "\uC218\uB7C9", example: "3" }
4054
+ ],
4055
+ columns: [
4056
+ { key: "name", header: "\uD488\uBAA9\uBA85", required: true },
4057
+ { key: "qty", header: "\uC218\uB7C9", required: true }
4058
+ ]
4059
+ }
4060
+ },
4061
+ resize: { kind: "none" }
4062
+ };
4063
+ var OptionSchemaEditorMeta = {
4064
+ name: "OptionSchemaEditor",
4065
+ label: "\uC635\uC158 \uC11C\uC2DD \uD3B8\uC9D1",
4066
+ category: "input",
4067
+ icon: "sliders-horizontal",
4068
+ description: "\uC7A5\uBE44\uAC00 \uC790\uAE30 \uC720\uB2DB\uC5D0\uAC8C \uBC1B\uC744 \uC635\uC158\uC758 \uC11C\uC2DD(\uC774\uB984\xB7\uD615\uC2DD\xB7\uC120\uD0DD\uC9C0)\uC744 \uC815\uD55C\uB2E4. \uAC12\uC774 \uC544\uB2C8\uB77C \uC11C\uC2DD\uC774\uB2E4 \u2014 \uC720\uB2DB \uC218\uC815\uC740 \uC774 \uC11C\uC2DD\uB300\uB85C \uCE78\uC744 \uADF8\uB9B0\uB2E4(OptionValueFields).",
4069
+ props: [
4070
+ {
4071
+ name: "value",
4072
+ kind: "object",
4073
+ label: "\uC7A5\uBE44 config",
4074
+ bindable: true,
4075
+ description: "\uC11C\uC2DD\uC740 \uC774 \uAC1D\uCCB4\uC758 options\uC5D0 \uB2F4\uAE34\uB2E4 \u2014 { options: [{ key, label?, type, options?, unit? }] }. \uBC30\uC5F4\uC774 \uC544\uB2C8\uB77C config \uD1B5\uC9F8\uB85C \uC8FC\uACE0\uBC1B\uB294 \uC774\uC720\uB294 setState\uAC00 \uC810 \uACBD\uB85C\uB97C \uD3C9\uBA74 \uD0A4\uB85C \uC800\uC7A5\uD558\uAE30 \uB54C\uBB38\uC774\uB2E4.",
4076
+ group: "data"
4077
+ },
4078
+ {
4079
+ name: "onChange",
4080
+ kind: "action",
4081
+ label: "\uBCC0\uACBD",
4082
+ eventArg: "options\uAC00 \uAC31\uC2E0\uB41C config \uAC1D\uCCB4",
4083
+ description: '{ "action": "setState", "key": "assetEditForm.config", "fromEvent": true }',
4084
+ group: "behavior"
4085
+ },
4086
+ { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" }
4087
+ ],
4088
+ children: { accepts: false },
4089
+ dom: { element: "div" },
4090
+ preset: {
4091
+ component: "OptionSchemaEditor",
4092
+ props: {
4093
+ value: { $state: "form.config", default: {} },
4094
+ onChange: { action: "setState", key: "form.config", fromEvent: true }
4095
+ }
4096
+ },
4097
+ resize: { kind: "none" }
4098
+ };
4099
+ var OptionValueFieldsMeta = {
4100
+ name: "OptionValueFields",
4101
+ label: "\uC635\uC158 \uAC12 \uC785\uB825",
4102
+ category: "input",
4103
+ icon: "list-filter",
4104
+ description: "\uC7A5\uBE44\uAC00 \uC815\uD574 \uB454 \uC635\uC158 \uC11C\uC2DD\uB300\uB85C \uC720\uB2DB\uC758 \uAC12 \uCE78\uC744 \uADF8\uB9B0\uB2E4. \uC11C\uC2DD\uC5D0 \uC5C6\uB294 \uD0A4\uB294 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uBCF4\uAD00\uD55C\uB2E4.",
4105
+ props: [
4106
+ {
4107
+ name: "schema",
4108
+ kind: "array",
4109
+ label: "\uC635\uC158 \uC11C\uC2DD",
4110
+ bindable: true,
4111
+ description: "\uC7A5\uBE44\uC758 assets.config.options \u2014 OptionSchemaEditor\uAC00 \uB9CC\uB4E0 \uBC30\uC5F4 \uADF8\uB300\uB85C.",
4112
+ group: "data",
4113
+ item: [
4114
+ { name: "key", kind: "string", label: "\uC774\uB984(\uD0A4)", required: true },
4115
+ { name: "label", kind: "string", label: "\uD45C\uC2DC \uC774\uB984" },
4116
+ { name: "type", kind: "string", label: "\uD615\uC2DD", required: true },
4117
+ { name: "options", kind: "array", label: "\uC120\uD0DD\uC9C0", itemKind: "string", item: [] },
4118
+ { name: "unit", kind: "string", label: "\uB2E8\uC704" }
4119
+ ]
4120
+ },
4121
+ {
4122
+ name: "value",
4123
+ kind: "object",
4124
+ label: "\uC635\uC158 \uAC12",
4125
+ bindable: true,
4126
+ description: "{ \uD0A4: \uAC12 } \uD3C9\uBA74 \uAC1D\uCCB4 \u2014 asset_units.config.",
4127
+ group: "data"
4128
+ },
4129
+ {
4130
+ name: "onChange",
4131
+ kind: "action",
4132
+ label: "\uBCC0\uACBD",
4133
+ eventArg: "\uC635\uC158 \uAC12 \uAC1D\uCCB4",
4134
+ description: '{ "action": "setState", "key": "unitForm.config", "fromEvent": true }',
4135
+ group: "behavior"
4136
+ },
4137
+ { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
4138
+ {
4139
+ name: "readOnly",
4140
+ kind: "boolean",
4141
+ label: "\uC77D\uAE30 \uD45C\uC2DC",
4142
+ default: false,
4143
+ description: "\uC0C1\uC138 \uD654\uBA74\uC6A9 \u2014 \uC785\uB825\uCE78 \uB300\uC2E0 \uAC12\uC774 \uC788\uB294 \uCE78\uB9CC \uB77C\uBCA8\xB7\uAC12 \uC904\uB85C \uC138\uC6B4\uB2E4.",
4144
+ group: "appearance"
4145
+ }
4146
+ ],
4147
+ children: { accepts: false },
4148
+ dom: { element: "div" },
4149
+ preset: {
4150
+ component: "OptionValueFields",
4151
+ props: {
4152
+ schema: { $state: "rt.assetOptions.config.options", default: [] },
4153
+ value: { $state: "unitForm.config", default: {} },
4154
+ onChange: { action: "setState", key: "unitForm.config", fromEvent: true }
4155
+ }
4156
+ },
4157
+ resize: { kind: "none" }
4158
+ };
4159
+ var StagePeriodEditorMeta = {
4160
+ name: "StagePeriodEditor",
4161
+ label: "\uB2E8\uACC4 \uAE30\uAC04 \uC785\uB825\uAE30",
4162
+ category: "input",
4163
+ icon: "calendar",
4164
+ description: "\uD3C9\uAC00 \uB2E8\uACC4\uC758 \uAE30\uAC04 4\uD544\uB4DC(startDate/endDate/startTime/endTime)\uB97C \uD3B8\uC9D1\uD55C\uB2E4. \uBE48\uAC12\u2192null \uC815\uADDC\uD654\uC640 \uC11C\uBC84 validate_period \uBBF8\uB7EC(\uC885\uB8CC\uC77C<\uC2DC\uC791\uC77C, \uAC19\uC740 \uB0A0 \uC2DC\uAC04 \uC21C\uC11C)\uAC00 \uC874\uC7AC \uC774\uC720 \u2014 onChange \uBD09\uD22C\uC758 error\uAC00 \uC788\uC73C\uBA74 \uC800\uC7A5\uC744 \uC7A0\uADFC\uB2E4. \uC800\uC7A5\uC740 \uC2A4\uD399\uC774 PATCH \uCCB4\uC778\uC73C\uB85C \uD55C\uB2E4.",
4165
+ props: [
4166
+ { name: "value", kind: "object", label: "\uC800\uC7A5\uB41C \uAE30\uAC04", bindable: true, description: "\uB2E8\uACC4 \uD589(stages[]) \uADF8\uB300\uB85C \u2014 \uC2DC\uAC01 HH:MM:SS \uD5C8\uC6A9, HH:MM\uB85C \uC815\uADDC\uD654\uD574 \uC77D\uB294\uB2E4. \uC2DC\uB529 \uC804\uC6A9.", group: "data" },
4167
+ { name: "onChange", kind: "action", label: "\uBCC0\uACBD", description: "{startDate,endDate,startTime,endTime(null|\uC720\uD6A8\uAC12), error} \uBD09\uD22C. \uB9C8\uC6B4\uD2B8 \uC9C1\uD6C4\uC5D0\uB3C4 1\uD68C \uD758\uB9B0\uB2E4.", group: "behavior" },
4168
+ { name: "resetKey", kind: "string", label: "\uC7AC\uC2DC\uB529 \uD0A4", bindable: true, group: "data", advanced: true },
4169
+ { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" }
4170
+ ],
4171
+ children: { accepts: false },
4172
+ dom: { element: "div" },
4173
+ preset: {
4174
+ component: "StagePeriodEditor",
4175
+ // 빈 props 는 저장 왕복에서 사라진다(편집기 계약) — 프리셋은 실제로 채운다.
4176
+ props: { value: { startDate: "", endDate: "", startTime: "09:00", endTime: "18:00" } }
4177
+ },
4178
+ resize: { kind: "none" }
4179
+ };
3952
4180
  var AutocompleteFieldMeta = {
3953
4181
  name: "AutocompleteField",
3954
4182
  label: "\uC790\uB3D9\uC644\uC131",
@@ -5369,6 +5597,10 @@ var widgetComponentMeta = {
5369
5597
  ApprovalLineEditor: ApprovalLineEditorMeta,
5370
5598
  ApprovalOverridesEditor: ApprovalOverridesEditorMeta,
5371
5599
  ApprovalStepper: ApprovalStepperMeta,
5600
+ OptionSchemaEditor: OptionSchemaEditorMeta,
5601
+ OptionValueFields: OptionValueFieldsMeta,
5602
+ StagePeriodEditor: StagePeriodEditorMeta,
5603
+ ExcelUploadCard: ExcelUploadCardMeta,
5372
5604
  FileDropzone: FileDropzoneMeta,
5373
5605
  PermissionMatrixEditor: PermissionMatrixEditorMeta,
5374
5606
  RoleMemberPicker: RoleMemberPickerMeta,
@@ -5431,4 +5663,4 @@ function paletteGroups(catalog = allComponentMeta) {
5431
5663
  })).filter((group) => group.items.length > 0);
5432
5664
  }
5433
5665
 
5434
- export { ActionsMeta, AlertMeta, ApprovalLineEditorMeta, ApprovalOverridesEditorMeta, ApprovalStepperMeta, AutocompleteFieldMeta, AvatarMeta, BadgeMeta, BreadcrumbMeta, ButtonMeta, CanMeta, CardMeta, ChartMeta, CheckboxMeta, ColMeta, ColumnBoardMeta, DatePickerMeta, DateRangePickerMeta, DialogMeta, DiffViewMeta, DisclosureMeta, DividerMeta, EmptyStateMeta, EventCalendarMeta, FieldMeta, FileDropzoneMeta, ForEachMeta, FormMeta, FragmentMeta, GridMeta, IconButtonMeta, IconMeta, ImageLightboxMeta, InlineEditMeta, InputMeta, JsonFieldMeta, KeyValueListMeta, LiveClockMeta, MapPreviewMeta, OrgChartBoardMeta, OrgChartMeta, PageHeadMeta, PaginationMeta, PeriodFilterMeta, PermissionMatrixEditorMeta, PrintSheetMeta, ProgressBarMeta, RadioMeta, RankBoardMeta, RecordSheetMeta, RemoteSearchResultsMeta, RoleMemberPickerMeta, RowMeta, SDUI_CATEGORIES, SELF_AXIS_PROPS, SearchResultsMeta, SearchableMultiPickerMeta, SectionMeta, SecureScreenMeta, SegmentedControlMeta, SelectMeta, ShowMeta, SidebarNavMeta, SortHandleMeta, SortableListMeta, SpacerMeta, SpinnerMeta, StackedMeterMeta, StatCardMeta, StripMeta, SummaryTableMeta, SwitchMeta, TableMeta, TabsMeta, TagMeta, TagMultiSelectMeta, TextMeta, TextareaMeta, TimePickerMeta, TimelineMeta, ToastMeta, TooltipMeta, TreePickerMeta, TreeViewMeta, allComponentMeta, builtinComponentMeta, coreComponentMeta, dsComponentMeta, getComponentMeta, paletteGroups, richComponentMeta, slotNamesOf, widgetComponentMeta, withSelfAxis, withSelfAxisAll };
5666
+ export { ActionsMeta, AlertMeta, ApprovalLineEditorMeta, ApprovalOverridesEditorMeta, ApprovalStepperMeta, AutocompleteFieldMeta, AvatarMeta, BadgeMeta, BreadcrumbMeta, ButtonMeta, CanMeta, CardMeta, ChartMeta, CheckboxMeta, ColMeta, ColumnBoardMeta, DatePickerMeta, DateRangePickerMeta, DialogMeta, DiffViewMeta, DisclosureMeta, DividerMeta, EmptyStateMeta, EventCalendarMeta, ExcelUploadCardMeta, FieldMeta, FileDropzoneMeta, ForEachMeta, FormMeta, FragmentMeta, GridMeta, IconButtonMeta, IconMeta, ImageLightboxMeta, InlineEditMeta, InputMeta, JsonFieldMeta, KeyValueListMeta, LiveClockMeta, MapPreviewMeta, OptionSchemaEditorMeta, OptionValueFieldsMeta, OrgChartBoardMeta, OrgChartMeta, PageHeadMeta, PaginationMeta, PeriodFilterMeta, PermissionMatrixEditorMeta, PrintSheetMeta, ProgressBarMeta, RadioMeta, RankBoardMeta, RecordSheetMeta, RemoteSearchResultsMeta, RoleMemberPickerMeta, RowMeta, SDUI_CATEGORIES, SELF_AXIS_PROPS, SearchResultsMeta, SearchableMultiPickerMeta, SectionMeta, SecureScreenMeta, SegmentedControlMeta, SelectMeta, ShowMeta, SidebarNavMeta, SortHandleMeta, SortableListMeta, SpacerMeta, SpinnerMeta, StackedMeterMeta, StagePeriodEditorMeta, StatCardMeta, StripMeta, SummaryTableMeta, SwitchMeta, TableMeta, TabsMeta, TagMeta, TagMultiSelectMeta, TextMeta, TextareaMeta, TimePickerMeta, TimelineMeta, ToastMeta, TooltipMeta, TreePickerMeta, TreeViewMeta, allComponentMeta, builtinComponentMeta, coreComponentMeta, dsComponentMeta, getComponentMeta, paletteGroups, richComponentMeta, slotNamesOf, widgetComponentMeta, withSelfAxis, withSelfAxisAll };
@@ -0,0 +1,37 @@
1
+ import { S as SduiBoxProps } from '../layout-B1QrIBm6.js';
2
+ import React__default from 'react';
3
+
4
+ interface ExcelTemplateColumn {
5
+ key: string;
6
+ header: string;
7
+ /** 템플릿 2행에 들어갈 예시값 */
8
+ example?: string;
9
+ }
10
+ interface ExcelPreviewColumn {
11
+ key: string;
12
+ /** 엑셀 헤더(한국어 별칭). key와도 매칭된다. */
13
+ header: string;
14
+ required?: boolean;
15
+ /** 허용값 목록 — 있으면 오류 셀을 Select로 수정 */
16
+ options?: string[];
17
+ }
18
+ interface ExcelUploadCardProps {
19
+ /** server = 파일을 서버로 바로 업로드, preview = 클라이언트 파싱·검증 후 가져오기 */
20
+ mode?: 'server' | 'preview';
21
+ /** server: multipart POST 대상 / preview: 검증된 rows JSON POST 대상 */
22
+ endpoint?: string;
23
+ /** 템플릿 다운로드 GET 경로 (templateColumns 없을 때 사용) */
24
+ templateEndpoint?: string;
25
+ /** 있으면 클라이언트에서 템플릿 xlsx 생성 — 백엔드 없이 동작 */
26
+ templateColumns?: ExcelTemplateColumn[];
27
+ /** preview 모드 파싱·검증 스키마 */
28
+ columns?: ExcelPreviewColumn[];
29
+ /** server 응답 요약 타일 라벨 매핑 (응답 키 → 라벨) */
30
+ summaryLabels?: Record<string, string>;
31
+ /** server: 응답 JSON / preview: 서버 응답(없으면 유효 행 배열) */
32
+ onComplete?: (result: unknown) => void;
33
+ }
34
+ /** 바깥에서 온 `style`·`className`을 뿌리에 얹어 내보낸다 — 자기 축(폭·여백)이 닿게 하는 통로. */
35
+ declare const ExcelUploadCard: React__default.FC<ExcelUploadCardProps & SduiBoxProps>;
36
+
37
+ export { type ExcelPreviewColumn, type ExcelTemplateColumn, ExcelUploadCard, type ExcelUploadCardProps };