@wipco/sdui 0.34.0 → 0.35.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.
@@ -1,8 +1,25 @@
1
+ import { useSduiAdapter, hostFetchOf } from './chunk-DKPNFEVU.js';
1
2
  import { Badge, Tag } from './chunk-WIDDHR7L.js';
2
3
  import { boxed } from './chunk-SAN4IX6N.js';
3
- import { useMemo, useState } from 'react';
4
+ import { useRef, useEffect, useMemo, useState } from 'react';
4
5
  import { jsx } from 'react/jsx-runtime';
5
6
 
7
+ function pickSeedValues(payload, valueKey) {
8
+ let rows = [];
9
+ if (Array.isArray(payload)) {
10
+ rows = payload;
11
+ } else if (payload !== null && typeof payload === "object") {
12
+ const body = payload;
13
+ const arrayKeys = Object.keys(body).filter((key) => Array.isArray(body[key]));
14
+ if (arrayKeys.length === 1) rows = body[arrayKeys[0]];
15
+ }
16
+ return rows.flatMap((row) => {
17
+ if (typeof row === "string") return row ? [row] : [];
18
+ if (row === null || typeof row !== "object") return [];
19
+ const value = row[valueKey];
20
+ return typeof value === "string" && value ? [value] : [];
21
+ });
22
+ }
6
23
  function foldOptions(options, valueKey, labelKey) {
7
24
  if (!Array.isArray(options)) return [];
8
25
  return options.flatMap((raw) => {
@@ -15,6 +32,8 @@ function foldOptions(options, valueKey, labelKey) {
15
32
  });
16
33
  }
17
34
  function TagMultiSelectImpl({
35
+ sourceEndpoint,
36
+ keepUnknownValues = true,
18
37
  options,
19
38
  valueKey,
20
39
  labelKey,
@@ -23,10 +42,35 @@ function TagMultiSelectImpl({
23
42
  disabled = false,
24
43
  emptyText = "\uC120\uD0DD\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
25
44
  }) {
26
- const safeOptions = useMemo(() => foldOptions(options, valueKey, labelKey), [options, valueKey, labelKey]);
45
+ const adapter = useSduiAdapter();
46
+ const onChangeRef = useRef(onChange);
47
+ onChangeRef.current = onChange;
48
+ const seededFor = useRef(null);
49
+ useEffect(() => {
50
+ if (!sourceEndpoint || seededFor.current === sourceEndpoint) return;
51
+ seededFor.current = sourceEndpoint;
52
+ const hostFetch = hostFetchOf(adapter);
53
+ if (!hostFetch) return;
54
+ let alive = true;
55
+ hostFetch(sourceEndpoint, { method: "GET" }).then((payload) => {
56
+ if (!alive) return;
57
+ onChangeRef.current?.(pickSeedValues(payload, valueKey ?? "value"));
58
+ }).catch(() => {
59
+ });
60
+ return () => {
61
+ alive = false;
62
+ };
63
+ }, [sourceEndpoint, adapter, valueKey]);
64
+ const folded = useMemo(() => foldOptions(options, valueKey, labelKey), [options, valueKey, labelKey]);
27
65
  const isControlled = values !== void 0 && typeof onChange === "function";
28
66
  const [internalValues, setInternalValues] = useState(values ?? []);
29
67
  const current = isControlled ? values : internalValues;
68
+ const safeOptions = useMemo(() => {
69
+ if (!keepUnknownValues) return folded;
70
+ const known = new Set(folded.map((option) => option.value));
71
+ const unknown = (current ?? []).filter((value) => value && !known.has(value)).map((value) => ({ value, label: value }));
72
+ return unknown.length > 0 ? [...folded, ...unknown] : folded;
73
+ }, [folded, current, keepUnknownValues]);
30
74
  const currentSet = useMemo(() => new Set(current), [current]);
31
75
  const toggle = (value) => {
32
76
  const set = new Set(currentSet);
@@ -71,4 +115,4 @@ function TagMultiSelectImpl({
71
115
  }
72
116
  var TagMultiSelect = boxed(TagMultiSelectImpl, "TagMultiSelect");
73
117
 
74
- export { TagMultiSelect };
118
+ export { TagMultiSelect, pickSeedValues };
@@ -0,0 +1,167 @@
1
+ import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-DKPNFEVU.js';
2
+ import { Spinner, Badge, Icon } from './chunk-WIDDHR7L.js';
3
+ import { boxed } from './chunk-SAN4IX6N.js';
4
+ import { useState, useEffect } from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ var text = (value) => {
8
+ if (value === null || value === void 0) return "";
9
+ if (typeof value === "string") return value.trim();
10
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
11
+ return "";
12
+ };
13
+ var period = (item, fromKey, toKey) => {
14
+ const from = text(item[fromKey]);
15
+ const to = text(item[toKey]);
16
+ if (!from && !to) return "";
17
+ return `${from || "?"} ~ ${to || "\uD604\uC7AC"}`;
18
+ };
19
+ function summarizeItem(kind, raw) {
20
+ if (typeof raw !== "object" || raw === null) return "";
21
+ const item = raw;
22
+ const parts = [];
23
+ switch (kind) {
24
+ case "degrees":
25
+ parts.push(text(item.institution), text(item.degree), text(item.field_of_study), period(item, "start_date", "end_date"));
26
+ break;
27
+ case "certifications":
28
+ parts.push(text(item.name), text(item.authority), text(item.certification_date));
29
+ break;
30
+ case "careers":
31
+ parts.push(text(item.company), text(item.title) || text(item.duty), period(item, "start_date", "end_date"));
32
+ break;
33
+ case "awards":
34
+ parts.push(text(item.title), text(item.authority), text(item.award_date));
35
+ break;
36
+ case "dispatches":
37
+ parts.push(text(item.destination), text(item.purpose), period(item, "start_date", "end_date"));
38
+ break;
39
+ case "licenses":
40
+ parts.push(text(item.license), text(item.qualification), text(item.grade), text(item.association));
41
+ break;
42
+ default: {
43
+ for (const [key, value] of Object.entries(item)) {
44
+ if (["id", "employee_id", "created_at", "updated_at", "deleted_at"].includes(key)) continue;
45
+ const v = text(value);
46
+ if (v) parts.push(v);
47
+ if (parts.length >= 3) break;
48
+ }
49
+ }
50
+ }
51
+ return parts.filter(Boolean).join(" \xB7 ");
52
+ }
53
+ var noticeStyle = {
54
+ border: "var(--wp-border-w) dashed var(--wp-border-default)",
55
+ borderRadius: "var(--wp-radius-lg)",
56
+ padding: "var(--wp-space-4)",
57
+ textAlign: "center",
58
+ color: "var(--wp-text-muted)"
59
+ };
60
+ var cellStyle = {
61
+ flex: 1,
62
+ minWidth: 0,
63
+ padding: "var(--wp-space-2)",
64
+ borderRadius: "var(--wp-radius-md)",
65
+ background: "var(--wp-surface-sunken)",
66
+ whiteSpace: "pre-wrap",
67
+ overflowWrap: "anywhere"
68
+ };
69
+ function ListCell({ kind, value }) {
70
+ const items = Array.isArray(value) ? value : [];
71
+ return /* @__PURE__ */ jsxs("div", { style: cellStyle, className: "wp-body-sm", children: [
72
+ /* @__PURE__ */ jsxs("span", { className: "wp-caption", style: { color: "var(--wp-text-muted)" }, children: [
73
+ items.length,
74
+ "\uAC74"
75
+ ] }),
76
+ items.map((item, index) => /* @__PURE__ */ jsx("div", { style: { marginTop: "var(--wp-space-1)" }, children: summarizeItem(kind, item) || "(\uB0B4\uC6A9 \uC5C6\uC74C)" }, index))
77
+ ] });
78
+ }
79
+ function ProfileEditDiffCardImpl({
80
+ scalarLabels = {},
81
+ relationLabels = {},
82
+ sourceEndpoint
83
+ }) {
84
+ const adapter = useSduiAdapter();
85
+ const api = hostFetchOf(adapter) ?? defaultAdapter.fetch;
86
+ const [detail, setDetail] = useState(null);
87
+ const [loading, setLoading] = useState(false);
88
+ const [failed, setFailed] = useState(false);
89
+ useEffect(() => {
90
+ if (!sourceEndpoint) return;
91
+ let alive = true;
92
+ setLoading(true);
93
+ setFailed(false);
94
+ api(sourceEndpoint, { method: "GET" }).then((response) => {
95
+ if (!alive) return;
96
+ setDetail(response ?? null);
97
+ setLoading(false);
98
+ }).catch(() => {
99
+ if (!alive) return;
100
+ setDetail(null);
101
+ setFailed(true);
102
+ setLoading(false);
103
+ });
104
+ return () => {
105
+ alive = false;
106
+ };
107
+ }, [sourceEndpoint]);
108
+ if (!sourceEndpoint) {
109
+ return /* @__PURE__ */ jsx("div", { className: "wp-body-sm", style: noticeStyle, children: "sourceEndpoint \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." });
110
+ }
111
+ if (loading) return /* @__PURE__ */ jsx(Spinner, { size: "sm", label: "\uBCC0\uACBD \uB0B4\uC6A9\uC744 \uBD88\uB7EC\uC624\uB294 \uC911" });
112
+ if (failed || !detail) {
113
+ return /* @__PURE__ */ jsx("div", { className: "wp-body-sm", style: noticeStyle, children: "\uBCC0\uACBD \uB0B4\uC6A9\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC774\uB825\uCE74\uB4DC \uC218\uC815 \uACB0\uC7AC\uC5D0\uC11C\uB9CC \uD45C\uC2DC\uB429\uB2C8\uB2E4." });
114
+ }
115
+ const payload = detail.request && typeof detail.request.payload === "object" && detail.request.payload !== null ? detail.request.payload : {};
116
+ const current = typeof detail.current === "object" && detail.current !== null ? detail.current : {};
117
+ const keys = Object.keys(payload);
118
+ const applied = Boolean(detail.request?.applied_at);
119
+ if (keys.length === 0) {
120
+ return /* @__PURE__ */ jsx("div", { className: "wp-body-sm", style: noticeStyle, children: "\uC2E0\uCCAD\uB41C \uBCC0\uACBD \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." });
121
+ }
122
+ return /* @__PURE__ */ jsxs("div", { className: "wp-col", style: { gap: "var(--wp-space-3)" }, children: [
123
+ /* @__PURE__ */ jsxs("div", { className: "wp-row", style: { alignItems: "center", gap: "var(--wp-space-2)" }, children: [
124
+ /* @__PURE__ */ jsxs("span", { className: "wp-caption", style: { color: "var(--wp-text-muted)" }, children: [
125
+ "\uBCC0\uACBD \uD56D\uBAA9 ",
126
+ keys.length,
127
+ "\uAC1C \xB7 \uBAA9\uB85D \uD56D\uBAA9(\uD559\uB825\xB7\uC790\uACA9\uC99D \uB4F1)\uC740 \uBAA9\uB85D \uC804\uCCB4\uAC00 \uAD50\uCCB4\uB429\uB2C8\uB2E4"
128
+ ] }),
129
+ applied ? /* @__PURE__ */ jsx(Badge, { tone: "success", children: "\uBC18\uC601 \uC644\uB8CC \u2014 \uBCC0\uACBD \uC804\uC740 \uBC18\uC601 \uC9C1\uC804 \uAC12" }) : null
130
+ ] }),
131
+ /* @__PURE__ */ jsxs("div", { className: "wp-row wp-caption", style: { alignItems: "center", color: "var(--wp-text-muted)" }, children: [
132
+ /* @__PURE__ */ jsx("span", { style: { flex: "none", width: 120 }, children: "\uD56D\uBAA9" }),
133
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: "\uBCC0\uACBD \uC804" }),
134
+ /* @__PURE__ */ jsx("span", { style: { flex: "none", width: 22 } }),
135
+ /* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: "\uBCC0\uACBD \uD6C4" })
136
+ ] }),
137
+ keys.map((key) => {
138
+ const isList = key in relationLabels || Array.isArray(payload[key]);
139
+ const label = scalarLabels[key] ?? relationLabels[key] ?? key;
140
+ return /* @__PURE__ */ jsxs("div", { className: "wp-row", style: { alignItems: "flex-start", gap: "var(--wp-space-2)" }, children: [
141
+ /* @__PURE__ */ jsx("span", { className: "wp-label", style: { flex: "none", width: 120, paddingTop: "var(--wp-space-2)" }, children: label }),
142
+ isList ? /* @__PURE__ */ jsx(ListCell, { kind: key, value: current[key] }) : /* @__PURE__ */ jsx("span", { className: "wp-body-sm", style: cellStyle, children: text(current[key]) || "-" }),
143
+ /* @__PURE__ */ jsx(
144
+ "span",
145
+ {
146
+ style: {
147
+ flex: "none",
148
+ width: 22,
149
+ display: "inline-flex",
150
+ justifyContent: "center",
151
+ paddingTop: "var(--wp-space-2)",
152
+ color: "var(--wp-text-muted)"
153
+ },
154
+ children: /* @__PURE__ */ jsx(Icon, { name: "arrow-right", size: 14 })
155
+ }
156
+ ),
157
+ isList ? /* @__PURE__ */ jsx(ListCell, { kind: key, value: payload[key] }) : /* @__PURE__ */ jsx("span", { className: "wp-body-sm", style: { ...cellStyle, background: "var(--wp-surface-brand-tint)" }, children: text(payload[key]) || "-" })
158
+ ] }, key);
159
+ })
160
+ ] });
161
+ }
162
+ var ProfileEditDiffCard = boxed(
163
+ ProfileEditDiffCardImpl,
164
+ "ProfileEditDiffCard"
165
+ );
166
+
167
+ export { ProfileEditDiffCard };
@@ -1,4 +1,4 @@
1
- import { TagMultiSelect } from './chunk-QDEZXA34.js';
1
+ import { TagMultiSelect } from './chunk-C7VAWTEP.js';
2
2
  import { ApprovalLineEditor, stepTypeIcon, stepLabel } from './chunk-S4LOH2TU.js';
3
3
  import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-DKPNFEVU.js';
4
4
  import { Card, Icon, Input, IconButton, Field, Button, Badge } from './chunk-WIDDHR7L.js';
package/dist/meta.d.ts CHANGED
@@ -437,6 +437,7 @@ declare const OptionValueFieldsMeta: SduiComponentMeta;
437
437
  declare const StagePeriodEditorMeta: SduiComponentMeta;
438
438
  declare const QRDisplayMeta: SduiComponentMeta;
439
439
  declare const PositionSelectMeta: SduiComponentMeta;
440
+ declare const ProfileEditDiffCardMeta: SduiComponentMeta;
440
441
  declare const AutocompleteFieldMeta: SduiComponentMeta;
441
442
  declare const InlineEditMeta: SduiComponentMeta;
442
443
  declare const JsonFieldMeta: SduiComponentMeta;
@@ -473,6 +474,7 @@ declare const widgetComponentMeta: {
473
474
  ApprovalLineEditor: SduiComponentMeta;
474
475
  ApprovalOverridesEditor: SduiComponentMeta;
475
476
  ApprovalStepper: SduiComponentMeta;
477
+ ProfileEditDiffCard: SduiComponentMeta;
476
478
  PositionSelect: SduiComponentMeta;
477
479
  QRDisplay: SduiComponentMeta;
478
480
  OptionSchemaEditor: SduiComponentMeta;
@@ -616,4 +618,4 @@ declare function paletteGroups(catalog?: Record<string, SduiComponentMeta>): Arr
616
618
  items: SduiComponentMeta[];
617
619
  }>;
618
620
 
619
- 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, PositionSelectMeta, PrintSheetMeta, ProgressBarMeta, QRDisplayMeta, 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 };
621
+ 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, PositionSelectMeta, PrintSheetMeta, ProfileEditDiffCardMeta, ProgressBarMeta, QRDisplayMeta, 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
@@ -4267,6 +4267,44 @@ var PositionSelectMeta = {
4267
4267
  },
4268
4268
  resize: { kind: "none" }
4269
4269
  };
4270
+ var ProfileEditDiffCardMeta = {
4271
+ name: "ProfileEditDiffCard",
4272
+ label: "\uC774\uB825\uCE74\uB4DC \uBCC0\uACBD \uBE44\uAD50",
4273
+ category: "display",
4274
+ icon: "files",
4275
+ description: "\uC774\uB825\uCE74\uB4DC \uC218\uC815 \uC2E0\uCCAD\uC758 \uBCC0\uACBD \uC804/\uD6C4 \uBE44\uAD50 \uCE74\uB4DC(\uD45C\uC2DC \uC804\uC6A9). sourceEndpoint(/employee-profile-edit-requests/{approvalId} \u2014 \uC2E0\uCCAD id \uB610\uB294 \uACB0\uC7AC id)\uB97C \uC2A4\uC2A4\uB85C \uC870\uD68C\uD574 payload\uC640 current\uB97C \uC9DD\uC9C0\uC5B4 \uADF8\uB9B0\uB2E4. \uBAA9\uB85D \uD56D\uBAA9(\uD559\uB825\xB7\uC790\uACA9\uC99D \uB4F1)\uC740 \uC885\uB958 \uB2E8\uC704 \uC804\uCCB4 \uAD50\uCCB4\uB85C \uD45C\uC2DC\uD55C\uB2E4.",
4276
+ props: [
4277
+ { name: "sourceEndpoint", kind: "string", label: "\uC2E0\uCCAD \uC0C1\uC138 \uACBD\uB85C", description: "/employee-profile-edit-requests/{approvalId} \u2014 \uACBD\uB85C\uAC00 \uBC14\uB014 \uB54C\uB9C8\uB2E4 \uC7AC\uC870\uD68C\uD55C\uB2E4(\uC0C1\uD0DC\uB97C \uCFFC\uB9AC\uB85C \uBD99\uC774\uBA74 \uCC98\uB9AC \uC9C1\uD6C4 \uC7AC\uC870\uD68C\uB97C \uC720\uB3C4\uD560 \uC218 \uC788\uB2E4).", group: "data" },
4278
+ {
4279
+ name: "scalarLabels",
4280
+ kind: "object",
4281
+ label: "\uD56D\uBAA9 \uD45C\uC2DC\uBA85",
4282
+ bindable: true,
4283
+ description: "{\uD0A4: \uB77C\uBCA8}. \uC548 \uC8FC\uBA74 \uC11C\uBC84\uAC00 \uC900 \uD0A4\uB97C \uADF8\uB300\uB85C \uBCF4\uC5EC\uC900\uB2E4.",
4284
+ group: "content",
4285
+ advanced: true
4286
+ },
4287
+ {
4288
+ name: "relationLabels",
4289
+ kind: "object",
4290
+ label: "\uBAA9\uB85D \uD56D\uBAA9 \uD45C\uC2DC\uBA85",
4291
+ bindable: true,
4292
+ description: "\uC5EC\uAE30 \uB4F1\uC7A5\uD558\uB294 \uD0A4\uB294 \uC885\uB958 \uB2E8\uC704 \uC804\uCCB4 \uAD50\uCCB4\uB85C \uADF8\uB9B0\uB2E4.",
4293
+ group: "content",
4294
+ advanced: true
4295
+ }
4296
+ ],
4297
+ children: { accepts: false },
4298
+ dom: { element: "div" },
4299
+ // 루트 <div class="wp-col"> (비교 행 목록) 또는 안내문 <div>
4300
+ // 마운트 즉시 GET sourceEndpoint 1회 — 캔버스 샌드박스에서는 조용히 실패하고 안내문만 남는다(RoleTagPicker와 같은 결).
4301
+ preset: {
4302
+ component: "ProfileEditDiffCard",
4303
+ // 빈 props 는 저장 왕복에서 사라진다(편집기 계약) — 프리셋은 실제로 채운다.
4304
+ props: { sourceEndpoint: "" }
4305
+ },
4306
+ resize: { kind: "none" }
4307
+ };
4270
4308
  var AutocompleteFieldMeta = {
4271
4309
  name: "AutocompleteField",
4272
4310
  label: "\uC790\uB3D9\uC644\uC131",
@@ -4638,7 +4676,25 @@ var TagMultiSelectMeta = {
4638
4676
  },
4639
4677
  { name: "onChange", kind: "action", label: "\uBCC0\uACBD", eventArg: "\uC120\uD0DD\uB41C \uAC12 \uBC30\uC5F4", group: "behavior" },
4640
4678
  { name: "emptyText", kind: "string", label: "\uC635\uC158 \uC5C6\uC74C \uBB38\uAD6C", default: "\uC120\uD0DD\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4", group: "content" },
4641
- { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" }
4679
+ { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
4680
+ {
4681
+ name: "sourceEndpoint",
4682
+ kind: "string",
4683
+ label: "\uD604\uC7AC \uAC12 \uC2DC\uB529 \uACBD\uB85C",
4684
+ bindable: true,
4685
+ description: "\uC8FC\uBA74 \uADF8 \uACBD\uB85C\uB97C \uC77D\uC5B4 \uD604\uC7AC \uAC12\uC744 onChange \uB85C \uD55C \uBC88 \uD758\uB9B0\uB2E4. \uACBD\uB85C\uAC00 \uBC14\uB014 \uB54C\uB9C8\uB2E4 \uB2E4\uC2DC \uC2DC\uB529\uD558\uBBC0\uB85C, \uC5EC\uB294 \uCABD\uC774 \uC5EC\uB294 \uD69F\uC218\uB97C \uBD99\uC774\uBA74 \uC7AC\uC5F4\uB9BC\uC5D0\uB3C4 \uCD08\uAE30\uD654\uB41C\uB2E4.",
4686
+ group: "data",
4687
+ advanced: true
4688
+ },
4689
+ {
4690
+ name: "keepUnknownValues",
4691
+ kind: "boolean",
4692
+ label: "\uBAA9\uB85D \uBC16 \uAC12 \uC720\uC9C0",
4693
+ default: true,
4694
+ description: "\uC800\uC7A5\uB3FC \uC788\uB294\uB370 \uC635\uC158\uC5D0 \uC5C6\uB294 \uAC12\uB3C4 \uD0DC\uADF8\uB85C \uB0A8\uAE34\uB2E4 \u2014 \uB044\uBA74 \uC800\uC7A5 \uC2DC \uC870\uC6A9\uD788 \uC0AC\uB77C\uC9C4\uB2E4.",
4695
+ group: "behavior",
4696
+ advanced: true
4697
+ }
4642
4698
  ],
4643
4699
  children: { accepts: false },
4644
4700
  dom: { element: "div" },
@@ -5696,6 +5752,7 @@ var widgetComponentMeta = {
5696
5752
  ApprovalLineEditor: ApprovalLineEditorMeta,
5697
5753
  ApprovalOverridesEditor: ApprovalOverridesEditorMeta,
5698
5754
  ApprovalStepper: ApprovalStepperMeta,
5755
+ ProfileEditDiffCard: ProfileEditDiffCardMeta,
5699
5756
  PositionSelect: PositionSelectMeta,
5700
5757
  QRDisplay: QRDisplayMeta,
5701
5758
  OptionSchemaEditor: OptionSchemaEditorMeta,
@@ -5764,4 +5821,4 @@ function paletteGroups(catalog = allComponentMeta) {
5764
5821
  })).filter((group) => group.items.length > 0);
5765
5822
  }
5766
5823
 
5767
- 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, PositionSelectMeta, PrintSheetMeta, ProgressBarMeta, QRDisplayMeta, 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 };
5824
+ 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, PositionSelectMeta, PrintSheetMeta, ProfileEditDiffCardMeta, ProgressBarMeta, QRDisplayMeta, 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 };
@@ -1,5 +1,5 @@
1
- export { ApprovalOverridesEditor } from '../chunk-OR27SRKL.js';
2
- import '../chunk-QDEZXA34.js';
1
+ export { ApprovalOverridesEditor } from '../chunk-G7JKDAS5.js';
2
+ import '../chunk-C7VAWTEP.js';
3
3
  import '../chunk-S4LOH2TU.js';
4
4
  import '../chunk-BD75U73S.js';
5
5
  import '../chunk-EFMKWPZ3.js';
@@ -0,0 +1,24 @@
1
+ import { S as SduiBoxProps } from '../layout-B1QrIBm6.js';
2
+ import React__default from 'react';
3
+
4
+ interface ProfileEditDiffCardProps {
5
+ /**
6
+ * 신청 상세 경로 — `/employee-profile-edit-requests/{approvalId}`.
7
+ * 경로가 바뀔 때마다 다시 조회한다.
8
+ */
9
+ sourceEndpoint?: string;
10
+ /**
11
+ * 스칼라 항목의 표시명(`{키: 라벨}`). 안 주면 **키를 그대로 보여준다** —
12
+ * 어떤 키가 오는지는 서버가 정하므로 라이브러리가 미리 알 수 없다.
13
+ */
14
+ scalarLabels?: Record<string, string>;
15
+ /**
16
+ * 목록 항목의 표시명. 여기 등장하는 키는 **종류 단위 전체 교체**로 그린다
17
+ * (`DiffView.lists` 의 before/after 축). 안 주면 값이 배열인 키를 목록으로 본다.
18
+ */
19
+ relationLabels?: Record<string, string>;
20
+ }
21
+ /** 바깥 style·className 을 뿌리에 얹는다 — 자기 축(폭·여백) 통로. */
22
+ declare const ProfileEditDiffCard: React__default.FC<ProfileEditDiffCardProps & SduiBoxProps>;
23
+
24
+ export { ProfileEditDiffCard, type ProfileEditDiffCardProps };
@@ -0,0 +1,4 @@
1
+ export { ProfileEditDiffCard } from '../chunk-FS65US2B.js';
2
+ import '../chunk-DKPNFEVU.js';
3
+ import '../chunk-WIDDHR7L.js';
4
+ import '../chunk-SAN4IX6N.js';
@@ -28,11 +28,39 @@ interface TagMultiSelectProps {
28
28
  disabled?: boolean;
29
29
  /** 옵션이 하나도 없을 때 보여줄 안내 문구. */
30
30
  emptyText?: string;
31
+ /**
32
+ * 현재 값을 읽어 와 `onChange` 로 **한 번** 흘리는 시딩 경로.
33
+ *
34
+ * 다이얼로그가 열릴 때 "지금 배정된 것"을 폼 상태로 채우는 자리다 — 선언으로는
35
+ * 표현할 수 없어(폼의 initial 은 마운트 1회라 늦게 온 값을 못 받는다) 여기서 받는다.
36
+ * 경로가 **바뀔 때마다** 다시 시딩하므로, 여는 쪽이 경로에 여는 횟수를 붙이면
37
+ * 재열림에도 초기화된다.
38
+ *
39
+ * 응답은 배열이거나 `{data|items|results|rows: 배열}` 봉투다. 원소가 객체면
40
+ * `valueKey`(기본 'value')로 값을 뽑는다 — 문자열 배열이면 그대로 쓴다.
41
+ */
42
+ sourceEndpoint?: string;
43
+ /**
44
+ * 옵션 목록에 없는 값도 태그로 남긴다(해제할 수 있게). 기본 켜짐 —
45
+ * 저장돼 있는데 목록에서 사라진 값이 조용히 지워지면 저장 시 유실된다.
46
+ */
47
+ keepUnknownValues?: boolean;
31
48
  }
49
+ /** valueKey/labelKey 계약으로 임의 행을 {value,label}로 접는다 — `normalizeSearchOptions`와 같은 규칙. */
50
+ /**
51
+ * 시딩 응답에서 값 배열을 뽑는다.
52
+ *
53
+ * 봉투는 **이름이 아니라 모양으로** 벗긴다 — 배열 값을 가진 키가 정확히 하나면 그것이
54
+ * 목록이다. 이름 허용목록(`data`·`items`…)을 두면 `{roles:[…]}`·`{members:[…]}` 처럼
55
+ * 자원 이름을 쓰는 서버가 전부 빈 목록이 되고, 결국 소비 앱이 위젯을 하나 더 만들게
56
+ * 된다(FileDropzone 의 업로드 봉투와 같은 판단).
57
+ * 키가 둘 이상이면 벗기지 않는다 — 엉뚱한 배열을 집는 것보다 비는 편이 낫다.
58
+ */
59
+ declare function pickSeedValues(payload: unknown, valueKey: string): string[];
32
60
  /**
33
61
  * 바깥에서 온 `style`·`className`을 뿌리에 얹어 내보낸다 — 자식 축(`grow`·`width` …)이
34
62
  * 이 컴포넌트에서도 동작하게 하는 유일한 통로다. 까닭은 {@link ../boxed.tsx}에 있다.
35
63
  */
36
64
  declare const TagMultiSelect: React.FC<TagMultiSelectProps & SduiBoxProps>;
37
65
 
38
- export { TagMultiSelect, type TagMultiSelectOption, type TagMultiSelectProps };
66
+ export { TagMultiSelect, type TagMultiSelectOption, type TagMultiSelectProps, pickSeedValues };
@@ -1,3 +1,4 @@
1
- export { TagMultiSelect } from '../chunk-QDEZXA34.js';
1
+ export { TagMultiSelect, pickSeedValues } from '../chunk-C7VAWTEP.js';
2
+ import '../chunk-DKPNFEVU.js';
2
3
  import '../chunk-WIDDHR7L.js';
3
4
  import '../chunk-SAN4IX6N.js';
@@ -5,7 +5,7 @@ export { TreePicker } from './TreePicker.js';
5
5
  import { TimelineProps } from './Timeline.js';
6
6
  export { Timeline, TimelineItem } from './Timeline.js';
7
7
  import { TagMultiSelectProps } from './TagMultiSelect.js';
8
- export { TagMultiSelect, TagMultiSelectOption } from './TagMultiSelect.js';
8
+ export { TagMultiSelect, TagMultiSelectOption, pickSeedValues } from './TagMultiSelect.js';
9
9
  import { SummaryTableProps } from './SummaryTable.js';
10
10
  export { SummaryTable, SummaryTableColumn } from './SummaryTable.js';
11
11
  import { StripProps } from './Strip.js';
@@ -26,6 +26,8 @@ import { RankBoardProps } from './RankBoard.js';
26
26
  export { RankBoard } from './RankBoard.js';
27
27
  import { QRDisplayProps } from './QRDisplay.js';
28
28
  export { QRDisplay } from './QRDisplay.js';
29
+ import { ProfileEditDiffCardProps } from './ProfileEditDiffCard.js';
30
+ export { ProfileEditDiffCard } from './ProfileEditDiffCard.js';
29
31
  import { PrintSheetProps } from './PrintSheet.js';
30
32
  export { PrintSheet } from './PrintSheet.js';
31
33
  import { PositionSelectProps } from './PositionSelect.js';
@@ -96,6 +98,7 @@ declare const widgetComponents: {
96
98
  PeriodFilter: React.FC<PeriodFilterProps & SduiBoxProps>;
97
99
  PositionSelect: React.FC<PositionSelectProps & SduiBoxProps>;
98
100
  PrintSheet: React.FC<PrintSheetProps & SduiBoxProps>;
101
+ ProfileEditDiffCard: React.FC<ProfileEditDiffCardProps & SduiBoxProps>;
99
102
  QRDisplay: React.FC<QRDisplayProps & SduiBoxProps>;
100
103
  RankBoard: React.FC<RankBoardProps & SduiBoxProps>;
101
104
  RecordSheet: React.FC<RecordSheetProps & SduiBoxProps>;
@@ -114,4 +117,4 @@ declare const widgetComponents: {
114
117
  /** 위젯 어휘의 컴포넌트 이름 union — 메타데이터 대조에 쓴다(`@wipco/sdui/meta`). */
115
118
  type SduiWidgetComponentName = keyof typeof widgetComponents;
116
119
 
117
- export { ApprovalLineEditorProps, ApprovalOverridesEditorProps, ApprovalStepperProps, ColumnBoardProps, DiffViewProps, DisclosureProps, EventCalendarProps, ImageLightboxProps, InlineEditProps, JsonFieldProps, LiveClockProps, OptionSchemaEditorProps, OptionValueFieldsProps, OrgChartBoardProps, OrgChartProps, PeriodFilterProps, PermissionMatrixEditorProps, PositionSelectProps, PrintSheetProps, QRDisplayProps, RankBoardProps, RecordSheetProps, RoleMemberPickerProps, type SduiWidgetComponentName, SearchableMultiPickerProps, SecureScreenProps, StackedMeterProps, StagePeriodEditorProps, StripProps, SummaryTableProps, TagMultiSelectProps, TimelineProps, TreePickerProps, TreeViewProps, widgetComponents };
120
+ export { ApprovalLineEditorProps, ApprovalOverridesEditorProps, ApprovalStepperProps, ColumnBoardProps, DiffViewProps, DisclosureProps, EventCalendarProps, ImageLightboxProps, InlineEditProps, JsonFieldProps, LiveClockProps, OptionSchemaEditorProps, OptionValueFieldsProps, OrgChartBoardProps, OrgChartProps, PeriodFilterProps, PermissionMatrixEditorProps, PositionSelectProps, PrintSheetProps, ProfileEditDiffCardProps, QRDisplayProps, RankBoardProps, RecordSheetProps, RoleMemberPickerProps, type SduiWidgetComponentName, SearchableMultiPickerProps, SecureScreenProps, StackedMeterProps, StagePeriodEditorProps, StripProps, SummaryTableProps, TagMultiSelectProps, TimelineProps, TreePickerProps, TreeViewProps, widgetComponents };
@@ -1,3 +1,5 @@
1
+ import { SecureScreen } from '../chunk-IIRENCDS.js';
2
+ export { SecureScreen } from '../chunk-IIRENCDS.js';
1
3
  import { StackedMeter } from '../chunk-BMZKZGJF.js';
2
4
  export { StackedMeter } from '../chunk-BMZKZGJF.js';
3
5
  import { StagePeriodEditor } from '../chunk-KVFHPBAY.js';
@@ -18,6 +20,8 @@ import { PrintSheet } from '../chunk-MYJ2KEIP.js';
18
20
  export { PrintSheet } from '../chunk-MYJ2KEIP.js';
19
21
  import { QRDisplay } from '../chunk-PCMJE2GO.js';
20
22
  export { QRDisplay } from '../chunk-PCMJE2GO.js';
23
+ import { ProfileEditDiffCard } from '../chunk-FS65US2B.js';
24
+ export { ProfileEditDiffCard } from '../chunk-FS65US2B.js';
21
25
  import { RankBoard } from '../chunk-U6H7YN4I.js';
22
26
  export { RankBoard } from '../chunk-U6H7YN4I.js';
23
27
  import { RecordSheet } from '../chunk-K3JBSWFI.js';
@@ -26,8 +30,6 @@ import { RoleMemberPicker } from '../chunk-WXZDYDXG.js';
26
30
  export { RoleMemberPicker } from '../chunk-WXZDYDXG.js';
27
31
  import { SearchableMultiPicker } from '../chunk-C53NGSA3.js';
28
32
  export { SearchableMultiPicker } from '../chunk-C53NGSA3.js';
29
- import { SecureScreen } from '../chunk-IIRENCDS.js';
30
- export { SecureScreen } from '../chunk-IIRENCDS.js';
31
33
  import { JsonField } from '../chunk-JVBZRDC2.js';
32
34
  export { JsonField } from '../chunk-JVBZRDC2.js';
33
35
  import { LiveClock } from '../chunk-Z3WGIFJP.js';
@@ -62,10 +64,10 @@ import '../chunk-QU7YVMFA.js';
62
64
  import '../chunk-QO6UJAQN.js';
63
65
  import '../chunk-THEP3VWY.js';
64
66
  import '../chunk-SNRKPEWT.js';
65
- import { ApprovalOverridesEditor } from '../chunk-OR27SRKL.js';
66
- export { ApprovalOverridesEditor } from '../chunk-OR27SRKL.js';
67
- import { TagMultiSelect } from '../chunk-QDEZXA34.js';
68
- export { TagMultiSelect } from '../chunk-QDEZXA34.js';
67
+ import { ApprovalOverridesEditor } from '../chunk-G7JKDAS5.js';
68
+ export { ApprovalOverridesEditor } from '../chunk-G7JKDAS5.js';
69
+ import { TagMultiSelect } from '../chunk-C7VAWTEP.js';
70
+ export { TagMultiSelect, pickSeedValues } from '../chunk-C7VAWTEP.js';
69
71
  import { ApprovalLineEditor } from '../chunk-S4LOH2TU.js';
70
72
  export { ApprovalLineEditor } from '../chunk-S4LOH2TU.js';
71
73
  import '../chunk-BD75U73S.js';
@@ -98,6 +100,7 @@ var widgetComponents = {
98
100
  PeriodFilter,
99
101
  PositionSelect,
100
102
  PrintSheet,
103
+ ProfileEditDiffCard,
101
104
  QRDisplay,
102
105
  RankBoard,
103
106
  RecordSheet,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipco/sdui",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "WIPCO 서버 주도 UI(SDUI) 렌더러 — JSON 페이지 스펙을 React 컴포넌트로 렌더링",
5
5
  "keywords": [
6
6
  "sdui",
@@ -128,6 +128,10 @@
128
128
  "types": "./dist/widgets/QRDisplay.d.ts",
129
129
  "default": "./dist/widgets/QRDisplay.js"
130
130
  },
131
+ "./widgets/ProfileEditDiffCard": {
132
+ "types": "./dist/widgets/ProfileEditDiffCard.d.ts",
133
+ "default": "./dist/widgets/ProfileEditDiffCard.js"
134
+ },
131
135
  "./widgets/RankBoard": {
132
136
  "types": "./dist/widgets/RankBoard.d.ts",
133
137
  "default": "./dist/widgets/RankBoard.js"