@wipco/sdui 0.32.0 → 0.34.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/chunk-D4AILKSJ.js +159 -0
- package/dist/chunk-PCMJE2GO.js +109 -0
- package/dist/{chunk-LDJ2CFFH.js → chunk-XAYXHY7R.js} +9 -2
- package/dist/meta.d.ts +5 -1
- package/dist/meta.js +103 -2
- package/dist/widgets/DiffView.d.ts +11 -0
- package/dist/widgets/DiffView.js +1 -1
- package/dist/widgets/PositionSelect.d.ts +44 -0
- package/dist/widgets/PositionSelect.js +4 -0
- package/dist/widgets/QRDisplay.d.ts +45 -0
- package/dist/widgets/QRDisplay.js +4 -0
- package/dist/widgets/index.d.ts +7 -1
- package/dist/widgets/index.js +12 -6
- package/package.json +9 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { useSduiAdapter, hostFetchOf, defaultAdapter } from './chunk-DKPNFEVU.js';
|
|
2
|
+
import { Select, Button } from './chunk-WIDDHR7L.js';
|
|
3
|
+
import { boxed } from './chunk-SAN4IX6N.js';
|
|
4
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var EMPTY_VALUE = "__wipco_position_none__";
|
|
8
|
+
var LOADING_VALUE = "__wipco_position_loading__";
|
|
9
|
+
var toNumber = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
10
|
+
function parseRow(raw) {
|
|
11
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
12
|
+
const row = raw;
|
|
13
|
+
if (typeof row.name !== "string") return null;
|
|
14
|
+
return {
|
|
15
|
+
name: row.name,
|
|
16
|
+
rankOrder: toNumber(row.rank_order),
|
|
17
|
+
sortOrder: toNumber(row.sort_order),
|
|
18
|
+
// is_active 결측은 true 폴백 — 파서 사정으로 목록이 전부 사라지는 사고 방지(v2와 동일).
|
|
19
|
+
isActive: row.is_active === void 0 || row.is_active === null ? true : row.is_active === true
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function fetchAllPositions(api, endpoint) {
|
|
23
|
+
const LIMIT = 500;
|
|
24
|
+
const MAX_PAGES = 10;
|
|
25
|
+
const rows = [];
|
|
26
|
+
let offset = 0;
|
|
27
|
+
for (let page = 0; page < MAX_PAGES; page += 1) {
|
|
28
|
+
const sep = endpoint.includes("?") ? "&" : "?";
|
|
29
|
+
const res = await api(`${endpoint}${sep}limit=${LIMIT}&offset=${offset}`, {
|
|
30
|
+
method: "GET"
|
|
31
|
+
});
|
|
32
|
+
const data = Array.isArray(res?.data) ? res.data : [];
|
|
33
|
+
for (const raw of data) {
|
|
34
|
+
const parsed = parseRow(raw);
|
|
35
|
+
if (parsed) rows.push(parsed);
|
|
36
|
+
}
|
|
37
|
+
const total = typeof res?.total === "number" ? res.total : rows.length;
|
|
38
|
+
offset += LIMIT;
|
|
39
|
+
if (data.length === 0 || rows.length >= total) break;
|
|
40
|
+
}
|
|
41
|
+
return rows;
|
|
42
|
+
}
|
|
43
|
+
var inflight = /* @__PURE__ */ new Map();
|
|
44
|
+
function loadPositions(api, endpoint) {
|
|
45
|
+
const pending = inflight.get(endpoint);
|
|
46
|
+
if (pending) return pending;
|
|
47
|
+
const next = fetchAllPositions(api, endpoint).finally(() => {
|
|
48
|
+
inflight.delete(endpoint);
|
|
49
|
+
});
|
|
50
|
+
inflight.set(endpoint, next);
|
|
51
|
+
return next;
|
|
52
|
+
}
|
|
53
|
+
function PositionSelectImpl({
|
|
54
|
+
endpoint = "/job-positions",
|
|
55
|
+
value,
|
|
56
|
+
onChange,
|
|
57
|
+
allowEmpty = false,
|
|
58
|
+
disabled = false,
|
|
59
|
+
size,
|
|
60
|
+
invalid,
|
|
61
|
+
placeholder = "\uC9C1\uC704\uB97C \uC120\uD0DD\uD558\uC138\uC694",
|
|
62
|
+
id
|
|
63
|
+
}) {
|
|
64
|
+
const adapter = useSduiAdapter();
|
|
65
|
+
const api = hostFetchOf(adapter) ?? defaultAdapter.fetch;
|
|
66
|
+
const [positions, setPositions] = useState(null);
|
|
67
|
+
const [failed, setFailed] = useState(false);
|
|
68
|
+
const [attempt, setAttempt] = useState(0);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
let alive = true;
|
|
71
|
+
loadPositions(api, endpoint).then((rows2) => {
|
|
72
|
+
if (!alive) return;
|
|
73
|
+
setPositions(rows2);
|
|
74
|
+
setFailed(false);
|
|
75
|
+
}).catch(() => {
|
|
76
|
+
if (!alive) return;
|
|
77
|
+
setPositions([]);
|
|
78
|
+
setFailed(true);
|
|
79
|
+
});
|
|
80
|
+
return () => {
|
|
81
|
+
alive = false;
|
|
82
|
+
};
|
|
83
|
+
}, [attempt]);
|
|
84
|
+
const isLoading = positions === null && !failed;
|
|
85
|
+
const rows = useMemo(() => positions ?? [], [positions]);
|
|
86
|
+
const activeByName = useMemo(() => {
|
|
87
|
+
const map = /* @__PURE__ */ new Map();
|
|
88
|
+
for (const position of rows) {
|
|
89
|
+
if (position.name.trim() === "") continue;
|
|
90
|
+
map.set(position.name, (map.get(position.name) ?? false) || position.isActive);
|
|
91
|
+
}
|
|
92
|
+
return map;
|
|
93
|
+
}, [rows]);
|
|
94
|
+
const activeNames = useMemo(() => {
|
|
95
|
+
const sorted = [...rows].sort(
|
|
96
|
+
(a, b) => a.rankOrder - b.rankOrder || a.sortOrder - b.sortOrder || a.name.localeCompare(b.name, "ko")
|
|
97
|
+
);
|
|
98
|
+
const seen = /* @__PURE__ */ new Set();
|
|
99
|
+
const names = [];
|
|
100
|
+
for (const position of sorted) {
|
|
101
|
+
if (!position.isActive) continue;
|
|
102
|
+
if (position.name.trim() === "" || seen.has(position.name)) continue;
|
|
103
|
+
seen.add(position.name);
|
|
104
|
+
names.push(position.name);
|
|
105
|
+
}
|
|
106
|
+
return names;
|
|
107
|
+
}, [rows]);
|
|
108
|
+
const current = typeof value === "string" ? value : "";
|
|
109
|
+
const isOffList = current !== "" && !activeNames.includes(current);
|
|
110
|
+
const suffix = isLoading || failed ? "" : activeByName.has(current) ? " (\uBBF8\uC0AC\uC6A9)" : " (\uBBF8\uB4F1\uB85D \uC9C1\uC704)";
|
|
111
|
+
const options = useMemo(() => {
|
|
112
|
+
const list = [];
|
|
113
|
+
if (allowEmpty) list.push({ value: EMPTY_VALUE, label: "\uC120\uD0DD \uC548 \uD568" });
|
|
114
|
+
if (isOffList) list.push({ value: current, label: `${current}${suffix}` });
|
|
115
|
+
if (isLoading) list.push({ value: LOADING_VALUE, label: "\uBD88\uB7EC\uC624\uB294 \uC911\u2026", disabled: true });
|
|
116
|
+
for (const name of activeNames) list.push({ value: name, label: name });
|
|
117
|
+
return list;
|
|
118
|
+
}, [allowEmpty, isOffList, current, suffix, isLoading, activeNames]);
|
|
119
|
+
return /* @__PURE__ */ jsxs("div", { className: "wp-col", style: { gap: "var(--wp-space-1)" }, children: [
|
|
120
|
+
/* @__PURE__ */ jsx(
|
|
121
|
+
Select,
|
|
122
|
+
{
|
|
123
|
+
id,
|
|
124
|
+
size,
|
|
125
|
+
invalid,
|
|
126
|
+
disabled,
|
|
127
|
+
value: current,
|
|
128
|
+
options,
|
|
129
|
+
placeholder,
|
|
130
|
+
onChange: (event) => {
|
|
131
|
+
const next = event.target.value;
|
|
132
|
+
if (next === LOADING_VALUE) return;
|
|
133
|
+
onChange?.(next === EMPTY_VALUE ? "" : next);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
!isLoading && failed && /* @__PURE__ */ jsxs("div", { className: "wp-row", style: { alignItems: "center", gap: "var(--wp-space-2)" }, children: [
|
|
138
|
+
/* @__PURE__ */ jsx("span", { className: "wp-caption", style: { color: "var(--wp-text-muted)" }, children: "\uC9C1\uC704 \uBAA9\uB85D\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4" }),
|
|
139
|
+
/* @__PURE__ */ jsx(
|
|
140
|
+
Button,
|
|
141
|
+
{
|
|
142
|
+
type: "button",
|
|
143
|
+
size: "sm",
|
|
144
|
+
variant: "secondary",
|
|
145
|
+
onClick: () => {
|
|
146
|
+
setPositions(null);
|
|
147
|
+
setFailed(false);
|
|
148
|
+
setAttempt((n) => n + 1);
|
|
149
|
+
},
|
|
150
|
+
children: "\uB2E4\uC2DC \uC2DC\uB3C4"
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
] }),
|
|
154
|
+
!isLoading && !failed && activeNames.length === 0 && !isOffList && /* @__PURE__ */ jsx("span", { className: "wp-caption", style: { color: "var(--wp-text-muted)" }, children: "\uB4F1\uB85D\uB41C \uC9C1\uC704\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC778\uC0AC > \uC9C1\uC704 \uAD00\uB9AC\uC5D0\uC11C \uB4F1\uB85D\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4." })
|
|
155
|
+
] });
|
|
156
|
+
}
|
|
157
|
+
var PositionSelect = boxed(PositionSelectImpl, "PositionSelect");
|
|
158
|
+
|
|
159
|
+
export { PositionSelect };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useSduiAssetResolver } from './chunk-DKPNFEVU.js';
|
|
2
|
+
import { Spinner, Icon } from './chunk-WIDDHR7L.js';
|
|
3
|
+
import { boxed } from './chunk-SAN4IX6N.js';
|
|
4
|
+
import { useState, useEffect } from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var FALLBACK_NOTE = "QR \uC774\uBBF8\uC9C0\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC11C\uBC84 \uC5F0\uACB0\uC744 \uD655\uC778\uD558\uC138\uC694";
|
|
8
|
+
var boxStyle = (size) => ({
|
|
9
|
+
width: size,
|
|
10
|
+
height: size,
|
|
11
|
+
display: "flex",
|
|
12
|
+
flexDirection: "column",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
justifyContent: "center",
|
|
15
|
+
gap: "var(--wp-space-2)"
|
|
16
|
+
});
|
|
17
|
+
function QRDisplayImpl({
|
|
18
|
+
path,
|
|
19
|
+
url,
|
|
20
|
+
size = 128,
|
|
21
|
+
endpoint = "/qr",
|
|
22
|
+
caption
|
|
23
|
+
}) {
|
|
24
|
+
const [absoluteUrl, setAbsoluteUrl] = useState(null);
|
|
25
|
+
const [failed, setFailed] = useState(false);
|
|
26
|
+
const resolveAsset = useSduiAssetResolver();
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setFailed(false);
|
|
29
|
+
try {
|
|
30
|
+
const base = window.location.origin;
|
|
31
|
+
const target = url ?? path ?? window.location.href;
|
|
32
|
+
setAbsoluteUrl(new URL(target, base).toString());
|
|
33
|
+
} catch {
|
|
34
|
+
setAbsoluteUrl(null);
|
|
35
|
+
setFailed(true);
|
|
36
|
+
}
|
|
37
|
+
}, [path, url]);
|
|
38
|
+
const raw = absoluteUrl !== null ? `${endpoint}${endpoint.includes("?") ? "&" : "?"}data=${encodeURIComponent(absoluteUrl)}&size=${size}` : null;
|
|
39
|
+
const src = raw === null ? null : resolveAsset(raw, { component: "QRDisplay", prop: "src", kind: "attribute" });
|
|
40
|
+
const pending = absoluteUrl === null && !failed;
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"figure",
|
|
43
|
+
{
|
|
44
|
+
style: {
|
|
45
|
+
display: "inline-flex",
|
|
46
|
+
flexDirection: "column",
|
|
47
|
+
alignItems: "center",
|
|
48
|
+
gap: "var(--wp-space-3)",
|
|
49
|
+
margin: 0,
|
|
50
|
+
padding: "var(--wp-space-4)",
|
|
51
|
+
background: "var(--wp-surface-card)",
|
|
52
|
+
border: "1px solid var(--wp-border-subtle)",
|
|
53
|
+
borderRadius: "var(--wp-radius-md)",
|
|
54
|
+
boxShadow: "var(--wp-shadow-xs)"
|
|
55
|
+
},
|
|
56
|
+
children: [
|
|
57
|
+
failed || src === null ? /* @__PURE__ */ jsx(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
role: "img",
|
|
61
|
+
"aria-label": FALLBACK_NOTE,
|
|
62
|
+
style: {
|
|
63
|
+
...boxStyle(size),
|
|
64
|
+
border: "1px dashed var(--wp-border-strong)",
|
|
65
|
+
borderRadius: "var(--wp-radius-md)",
|
|
66
|
+
background: "var(--wp-surface-sunken)",
|
|
67
|
+
color: "var(--wp-text-subtle)"
|
|
68
|
+
},
|
|
69
|
+
children: pending ? /* @__PURE__ */ jsx(Spinner, { label: "QR \uC900\uBE44 \uC911" }) : /* @__PURE__ */ jsx(Icon, { name: "scan", size: 24 })
|
|
70
|
+
}
|
|
71
|
+
) : /* @__PURE__ */ jsx(
|
|
72
|
+
"img",
|
|
73
|
+
{
|
|
74
|
+
src,
|
|
75
|
+
width: size,
|
|
76
|
+
height: size,
|
|
77
|
+
alt: caption ? `QR \uCF54\uB4DC \u2014 ${caption}` : "QR \uCF54\uB4DC",
|
|
78
|
+
onError: () => setFailed(true),
|
|
79
|
+
style: {
|
|
80
|
+
display: "block",
|
|
81
|
+
borderRadius: "var(--wp-radius-xs)",
|
|
82
|
+
maxWidth: "100%"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
/* @__PURE__ */ jsxs(
|
|
87
|
+
"figcaption",
|
|
88
|
+
{
|
|
89
|
+
style: {
|
|
90
|
+
display: "flex",
|
|
91
|
+
flexDirection: "column",
|
|
92
|
+
alignItems: "center",
|
|
93
|
+
gap: "var(--wp-space-1)",
|
|
94
|
+
maxWidth: Math.max(size, 160),
|
|
95
|
+
textAlign: "center"
|
|
96
|
+
},
|
|
97
|
+
children: [
|
|
98
|
+
caption && /* @__PURE__ */ jsx("span", { className: "wp-caption", style: { color: "var(--wp-text-muted)" }, children: caption }),
|
|
99
|
+
failed && /* @__PURE__ */ jsx("span", { className: "wp-caption", style: { color: "var(--wp-text-subtle)" }, children: FALLBACK_NOTE })
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
var QRDisplay = boxed(QRDisplayImpl, "QRDisplay");
|
|
108
|
+
|
|
109
|
+
export { QRDisplay };
|
|
@@ -51,10 +51,17 @@ function DiffViewImpl({ fields, lists }) {
|
|
|
51
51
|
const added = list.added ?? [];
|
|
52
52
|
const removed = list.removed ?? [];
|
|
53
53
|
const kept = list.kept ?? [];
|
|
54
|
-
const
|
|
54
|
+
const isReplace = list.before !== void 0 || list.after !== void 0;
|
|
55
|
+
const before = list.before ?? [];
|
|
56
|
+
const after = list.after ?? [];
|
|
57
|
+
const isEmpty = isReplace ? before.length === 0 && after.length === 0 : added.length === 0 && removed.length === 0 && kept.length === 0;
|
|
55
58
|
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
56
59
|
/* @__PURE__ */ jsx("span", { className: "erp-diff__label", children: list.label }),
|
|
57
|
-
/* @__PURE__ */ jsx("span", { className: "erp-diff__badges", children: isEmpty ? /* @__PURE__ */ jsx("span", { className: "wp-caption", children: "\uBCC0\uACBD \uC5C6\uC74C" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: "erp-diff__badges", children: isEmpty ? /* @__PURE__ */ jsx("span", { className: "wp-caption", children: "\uBCC0\uACBD \uC5C6\uC74C" }) : isReplace ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
|
+
before.map((value, i) => /* @__PURE__ */ jsx(Badge, { tone: "neutral", children: value }, `b-${value}-${i}`)),
|
|
62
|
+
/* @__PURE__ */ jsx("span", { className: "erp-diff__arrow", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { name: "arrow-right", size: 14 }) }),
|
|
63
|
+
after.length === 0 ? /* @__PURE__ */ jsx("span", { className: "wp-caption", children: "\uBE44\uC6C0" }) : after.map((value, i) => /* @__PURE__ */ jsx(Badge, { tone: "success", children: value }, `f-${value}-${i}`))
|
|
64
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
58
65
|
added.map((value, i) => /* @__PURE__ */ jsxs(Badge, { tone: "success", children: [
|
|
59
66
|
"+ ",
|
|
60
67
|
value
|
package/dist/meta.d.ts
CHANGED
|
@@ -435,6 +435,8 @@ declare const ExcelUploadCardMeta: SduiComponentMeta;
|
|
|
435
435
|
declare const OptionSchemaEditorMeta: SduiComponentMeta;
|
|
436
436
|
declare const OptionValueFieldsMeta: SduiComponentMeta;
|
|
437
437
|
declare const StagePeriodEditorMeta: SduiComponentMeta;
|
|
438
|
+
declare const QRDisplayMeta: SduiComponentMeta;
|
|
439
|
+
declare const PositionSelectMeta: SduiComponentMeta;
|
|
438
440
|
declare const AutocompleteFieldMeta: SduiComponentMeta;
|
|
439
441
|
declare const InlineEditMeta: SduiComponentMeta;
|
|
440
442
|
declare const JsonFieldMeta: SduiComponentMeta;
|
|
@@ -471,6 +473,8 @@ declare const widgetComponentMeta: {
|
|
|
471
473
|
ApprovalLineEditor: SduiComponentMeta;
|
|
472
474
|
ApprovalOverridesEditor: SduiComponentMeta;
|
|
473
475
|
ApprovalStepper: SduiComponentMeta;
|
|
476
|
+
PositionSelect: SduiComponentMeta;
|
|
477
|
+
QRDisplay: SduiComponentMeta;
|
|
474
478
|
OptionSchemaEditor: SduiComponentMeta;
|
|
475
479
|
OptionValueFields: SduiComponentMeta;
|
|
476
480
|
StagePeriodEditor: SduiComponentMeta;
|
|
@@ -612,4 +616,4 @@ declare function paletteGroups(catalog?: Record<string, SduiComponentMeta>): Arr
|
|
|
612
616
|
items: SduiComponentMeta[];
|
|
613
617
|
}>;
|
|
614
618
|
|
|
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 };
|
|
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 };
|
package/dist/meta.js
CHANGED
|
@@ -4177,6 +4177,96 @@ var StagePeriodEditorMeta = {
|
|
|
4177
4177
|
},
|
|
4178
4178
|
resize: { kind: "none" }
|
|
4179
4179
|
};
|
|
4180
|
+
var QRDisplayMeta = {
|
|
4181
|
+
name: "QRDisplay",
|
|
4182
|
+
label: "QR \uCF54\uB4DC",
|
|
4183
|
+
category: "display",
|
|
4184
|
+
icon: "scan",
|
|
4185
|
+
description: "\uBC31\uC5D4\uB4DC QR \uB80C\uB354\uB7EC(GET /qr)\uB85C \uB9CC\uB4E0 QR \uC774\uBBF8\uC9C0\uB97C \uCEA1\uC158\uACFC \uD568\uAED8 \uBCF4\uC5EC\uC900\uB2E4. \uB85C\uB4DC\uC5D0 \uC2E4\uD328\uD558\uBA74 \uC810\uC120 \uD50C\uB808\uC774\uC2A4\uD640\uB354\uB85C \uB300\uCCB4\uB41C\uB2E4.",
|
|
4186
|
+
props: [
|
|
4187
|
+
{
|
|
4188
|
+
name: "path",
|
|
4189
|
+
kind: "string",
|
|
4190
|
+
label: "\uC571 \uB0B4\uBD80 \uACBD\uB85C",
|
|
4191
|
+
bindable: true,
|
|
4192
|
+
description: '\uC608: "/public/asset/unit/WP-0001". \uB9C8\uC6B4\uD2B8 \uD6C4 \uC808\uB300 URL\uB85C \uBCC0\uD658\uD574 \uC778\uCF54\uB529\uD55C\uB2E4.',
|
|
4193
|
+
group: "content"
|
|
4194
|
+
},
|
|
4195
|
+
// 실측 2/2
|
|
4196
|
+
{
|
|
4197
|
+
name: "url",
|
|
4198
|
+
kind: "string",
|
|
4199
|
+
label: "URL \uC9C1\uC811 \uC9C0\uC815",
|
|
4200
|
+
bindable: true,
|
|
4201
|
+
description: "path\uBCF4\uB2E4 \uC6B0\uC120\uD55C\uB2E4.",
|
|
4202
|
+
group: "content",
|
|
4203
|
+
advanced: true
|
|
4204
|
+
},
|
|
4205
|
+
// 실측 0/2 — 구현에는 있다
|
|
4206
|
+
{
|
|
4207
|
+
name: "size",
|
|
4208
|
+
kind: "number",
|
|
4209
|
+
label: "\uD06C\uAE30(px)",
|
|
4210
|
+
default: 128,
|
|
4211
|
+
description: "QR \uD55C \uBCC0. \uAC00\uB85C\xB7\uC138\uB85C\uAC00 \uAC19\uC774 \uC6C0\uC9C1\uC778\uB2E4.",
|
|
4212
|
+
group: "appearance"
|
|
4213
|
+
},
|
|
4214
|
+
// 실측 2/2 (148, 112)
|
|
4215
|
+
{ name: "caption", kind: "string", label: "\uCEA1\uC158", group: "content" }
|
|
4216
|
+
// 실측 2/2
|
|
4217
|
+
],
|
|
4218
|
+
children: { accepts: false },
|
|
4219
|
+
dom: { element: "figure" },
|
|
4220
|
+
// 실측: 루트가 <figure>
|
|
4221
|
+
preset: {
|
|
4222
|
+
component: "QRDisplay",
|
|
4223
|
+
props: { path: "/", size: 128, caption: "QR \uCF54\uB4DC" }
|
|
4224
|
+
},
|
|
4225
|
+
// size 하나가 한 변이라 가로 손잡이든 세로 손잡이든 같은 프롭을 움직인다.
|
|
4226
|
+
// 실측(resizePatch 직접 호출): dx=+40 dy=0 → {size:168} · dx=0 dy=+40 → {size:168} ·
|
|
4227
|
+
// dx=+40 dy=+10 → {size:168}. 대각선은 더 많이 끈 축을 따른다(합산이 아니다).
|
|
4228
|
+
// 처음 적을 때는 이 문장을 재보지 않고 썼고 실제로는 거짓이었다 — 가로 손잡이가
|
|
4229
|
+
// 죽어 있었다. resize.ts의 "같은 프롭이면 축을 합친다" 분기를 그때 넣어 참으로 만들었다.
|
|
4230
|
+
resize: { kind: "numeric", widthProp: "size", heightProp: "size", unit: "px", axis: "both" }
|
|
4231
|
+
};
|
|
4232
|
+
var PositionSelectMeta = {
|
|
4233
|
+
name: "PositionSelect",
|
|
4234
|
+
label: "\uC9C1\uC704 \uC120\uD0DD",
|
|
4235
|
+
category: "input",
|
|
4236
|
+
icon: "circle-user",
|
|
4237
|
+
description: '\uC9C1\uC704 \uB9C8\uC2A4\uD130(/job-positions) \uC140\uB809\uD2B8. \uD65C\uC131 \uC9C1\uC704\uB97C \uC11C\uC5F4(rank_order\u2192sort_order) \uC21C\uC73C\uB85C \uBCF4\uC5EC\uC8FC\uACE0, \uBAA9\uB85D \uBC16 \uD604\uC7AC \uAC12\uC740 " (\uBBF8\uC0AC\uC6A9)"/" (\uBBF8\uB4F1\uB85D \uC9C1\uC704)" \uC811\uBBF8\uC0AC\uB85C \uC5B9\uC5B4 \uBCF4\uC874\uD55C\uB2E4. \uAC12\uC740 employees.grade \uBB38\uC790\uC5F4 \uC0AC\uBCF8 \uADF8\uB300\uB85C\uB2E4.',
|
|
4238
|
+
props: [
|
|
4239
|
+
{ name: "value", kind: "string", label: "\uD604\uC7AC \uC9C1\uC704", required: true, bindable: true, description: "\uC9C1\uC704 \uC774\uB984 \uBB38\uC790\uC5F4(employees.grade).", group: "data" },
|
|
4240
|
+
{ name: "onChange", kind: "action", label: "\uC9C1\uC704 \uBCC0\uACBD", required: true, eventArg: '\uBC14\uB010 \uC9C1\uC704 \uC774\uB984 \uBB38\uC790\uC5F4 \u2014 "\uC120\uD0DD \uC548 \uD568"\uC740 \uBE48 \uBB38\uC790\uC5F4', group: "behavior" },
|
|
4241
|
+
{ name: "allowEmpty", kind: "boolean", label: "\uC120\uD0DD \uC548 \uD568 \uB178\uCD9C", default: false, description: '\uB9E8 \uC704\uC5D0 "\uC120\uD0DD \uC548 \uD568" \uD56D\uBAA9\uC744 \uB178\uCD9C\uD55C\uB2E4. \uC120\uD0DD \uC2DC \uBE48 \uBB38\uC790\uC5F4\uC744 \uD758\uB9B0\uB2E4.', group: "behavior" },
|
|
4242
|
+
{ name: "placeholder", kind: "string", label: "\uD50C\uB808\uC774\uC2A4\uD640\uB354", default: "\uC9C1\uC704\uB97C \uC120\uD0DD\uD558\uC138\uC694", group: "content" },
|
|
4243
|
+
{ name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
|
|
4244
|
+
{ name: "invalid", kind: "boolean", label: "\uC624\uB958 \uD45C\uC2DC", bindable: true, group: "appearance", advanced: true },
|
|
4245
|
+
{ name: "size", kind: "enum", label: "\uD06C\uAE30", options: [{ value: "sm", label: "\uC791\uAC8C" }, { value: "md", label: "\uBCF4\uD1B5" }, { value: "lg", label: "\uD06C\uAC8C" }], group: "appearance", advanced: true },
|
|
4246
|
+
{ name: "id", kind: "string", label: "\uC694\uC18C id", group: "behavior", advanced: true },
|
|
4247
|
+
{
|
|
4248
|
+
name: "endpoint",
|
|
4249
|
+
kind: "string",
|
|
4250
|
+
label: "\uC9C1\uC704 \uBAA9\uB85D \uACBD\uB85C",
|
|
4251
|
+
description: "\uC751\uB2F5 {data:[\u2026], total} \uC744 500\uAC74\uC529 \uC218\uC9D1\uD55C\uB2E4. \uAE30\uBCF8 '/job-positions'.",
|
|
4252
|
+
group: "data",
|
|
4253
|
+
advanced: true
|
|
4254
|
+
}
|
|
4255
|
+
],
|
|
4256
|
+
children: { accepts: false },
|
|
4257
|
+
dom: { element: "div" },
|
|
4258
|
+
// 루트 <div class="wp-col"> (Select + 안내문)
|
|
4259
|
+
// 마운트 즉시 GET /job-positions 1회가 나간다 — RoleTagPicker.sourceEndpoint와 같은 결(캔버스에서는 조용히 실패).
|
|
4260
|
+
preset: {
|
|
4261
|
+
component: "PositionSelect",
|
|
4262
|
+
props: {
|
|
4263
|
+
value: { $state: "empForm.grade", default: "" },
|
|
4264
|
+
onChange: { action: "setState", key: "empForm.grade", fromEvent: true },
|
|
4265
|
+
allowEmpty: true
|
|
4266
|
+
}
|
|
4267
|
+
},
|
|
4268
|
+
resize: { kind: "none" }
|
|
4269
|
+
};
|
|
4180
4270
|
var AutocompleteFieldMeta = {
|
|
4181
4271
|
name: "AutocompleteField",
|
|
4182
4272
|
label: "\uC790\uB3D9\uC644\uC131",
|
|
@@ -4989,7 +5079,16 @@ var DiffViewMeta = {
|
|
|
4989
5079
|
{ name: "label", kind: "string", label: "\uD56D\uBAA9\uBA85", required: true },
|
|
4990
5080
|
{ name: "added", kind: "array", label: "\uCD94\uAC00\uB428", item: [], itemKind: "string" },
|
|
4991
5081
|
{ name: "removed", kind: "array", label: "\uC0AD\uC81C\uB428", item: [], itemKind: "string" },
|
|
4992
|
-
{ name: "kept", kind: "array", label: "\uC720\uC9C0\uB428", item: [], itemKind: "string" }
|
|
5082
|
+
{ name: "kept", kind: "array", label: "\uC720\uC9C0\uB428", item: [], itemKind: "string" },
|
|
5083
|
+
{
|
|
5084
|
+
name: "before",
|
|
5085
|
+
kind: "array",
|
|
5086
|
+
label: "\uBCC0\uACBD \uC804(\uC804\uCCB4 \uAD50\uCCB4)",
|
|
5087
|
+
item: [],
|
|
5088
|
+
itemKind: "string",
|
|
5089
|
+
description: '\uC774 \uCD95\uC744 \uC8FC\uBA74 added/removed/kept \uB300\uC2E0 "before \u2192 after" \uB85C \uADF8\uB9B0\uB2E4 \u2014 \uC885\uB958 \uB2E8\uC704 \uC804\uCCB4 \uAD50\uCCB4.'
|
|
5090
|
+
},
|
|
5091
|
+
{ name: "after", kind: "array", label: "\uBCC0\uACBD \uD6C4(\uC804\uCCB4 \uAD50\uCCB4)", item: [], itemKind: "string" }
|
|
4993
5092
|
]
|
|
4994
5093
|
}
|
|
4995
5094
|
],
|
|
@@ -5597,6 +5696,8 @@ var widgetComponentMeta = {
|
|
|
5597
5696
|
ApprovalLineEditor: ApprovalLineEditorMeta,
|
|
5598
5697
|
ApprovalOverridesEditor: ApprovalOverridesEditorMeta,
|
|
5599
5698
|
ApprovalStepper: ApprovalStepperMeta,
|
|
5699
|
+
PositionSelect: PositionSelectMeta,
|
|
5700
|
+
QRDisplay: QRDisplayMeta,
|
|
5600
5701
|
OptionSchemaEditor: OptionSchemaEditorMeta,
|
|
5601
5702
|
OptionValueFields: OptionValueFieldsMeta,
|
|
5602
5703
|
StagePeriodEditor: StagePeriodEditorMeta,
|
|
@@ -5663,4 +5764,4 @@ function paletteGroups(catalog = allComponentMeta) {
|
|
|
5663
5764
|
})).filter((group) => group.items.length > 0);
|
|
5664
5765
|
}
|
|
5665
5766
|
|
|
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 };
|
|
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 };
|
|
@@ -11,6 +11,17 @@ interface DiffList {
|
|
|
11
11
|
added?: string[];
|
|
12
12
|
removed?: string[];
|
|
13
13
|
kept?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* **종류 단위 전체 교체**를 그린다 — `before`/`after` 중 하나라도 있으면
|
|
16
|
+
* added/removed/kept 대신 이쪽으로 그린다.
|
|
17
|
+
*
|
|
18
|
+
* 항목별 추가·삭제가 아니라 "이 종류가 통째로 이 목록으로 바뀐다"가 참인 자리가
|
|
19
|
+
* 있다(학력·자격처럼 서버가 종류째 갈아 끼우는 관계). 그걸 added/removed 로 그리면
|
|
20
|
+
* **의미가 달라진다** — 같은 값이 양쪽에 있어도 "유지"가 아니라 "지웠다 다시 넣음"이
|
|
21
|
+
* 서버에서 실제로 일어나기 때문이다.
|
|
22
|
+
*/
|
|
23
|
+
before?: string[];
|
|
24
|
+
after?: string[];
|
|
14
25
|
}
|
|
15
26
|
interface DiffViewProps {
|
|
16
27
|
fields?: DiffField[];
|
package/dist/widgets/DiffView.js
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { S as SduiBoxProps } from '../layout-B1QrIBm6.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PositionSelect — 직위 마스터(/job-positions) 셀렉트. v2 position-select.tsx 이식.
|
|
6
|
+
*
|
|
7
|
+
* 옵션은 **활성 직위만**, 마스터 서열(rank_order → sort_order → 이름 ko) 순서 그대로다 —
|
|
8
|
+
* 서열이 곧 표시 순서라 가나다 재정렬로 덮으면 안 된다. 같은 이름이 중복되면
|
|
9
|
+
* 첫 등장(서열 높은 쪽)만 남긴다(같은 value 옵션이 둘 생기는 사고 방지).
|
|
10
|
+
*
|
|
11
|
+
* **off-list 값 처리**: 현재 값이 활성 목록에 없으면(미사용 전환·예전 자유 입력) 그 값을
|
|
12
|
+
* 항목으로 얹어 표시를 유지한다 — 안 얹으면 셀렉트가 비어 보이고 저장 시 기존 값이
|
|
13
|
+
* 날아간 것처럼 오해된다(v2가 고친 문제). 접미사: 마스터에 있으나 미사용이면 " (미사용)",
|
|
14
|
+
* 마스터에 아예 없으면 " (미등록 직위)". 로딩/에러 중에는 접미사를 생략한다 —
|
|
15
|
+
* 조회 한 번 실패했다고 멀쩡한 값이 "미등록"으로 낙인찍히면 안 된다.
|
|
16
|
+
*
|
|
17
|
+
* **조회는 매 마운트 1회**(limit 500씩 total까지 페이지 수집) — v2의 60초 모듈 캐시 +
|
|
18
|
+
* 세대 카운터 대신 단순화했다. 직위 관리 화면 변경 뒤 폼 다이얼로그가 다시 열리면
|
|
19
|
+
* (Show 언마운트→재마운트) 새로 읽으므로 invalidate 별도 배선이 필요 없다.
|
|
20
|
+
* 한 화면 다중 인스턴스(등록 폼+필터)의 중복 조회만 모듈 인플라이트 공유로 억제한다.
|
|
21
|
+
*
|
|
22
|
+
* **onChange는 문자열**을 흘린다 — "선택 안 함"은 ''(빈 문자열). v2 계약은 null이었지만
|
|
23
|
+
* 호출부가 전부 null→''로 접어 저장했고, SDUI setState(fromEvent)에는 값 변환 어휘가
|
|
24
|
+
* 없어 그 접기를 위젯이 대신한다. employees.grade는 문자열 사본 컬럼이라 ''가 "미지정"이다.
|
|
25
|
+
*/
|
|
26
|
+
interface PositionSelectProps {
|
|
27
|
+
/** 직위 목록 경로. 응답 `{data:[…], total}` 을 500건씩 수집한다. 기본 '/job-positions'. */
|
|
28
|
+
endpoint?: string;
|
|
29
|
+
/** 현재 직위 이름(employees.grade 문자열 사본). */
|
|
30
|
+
value?: string | null;
|
|
31
|
+
/** 바뀐 직위 이름. "선택 안 함"은 ''(빈 문자열). */
|
|
32
|
+
onChange?: (value: string) => void;
|
|
33
|
+
/** "선택 안 함" 항목을 맨 위에 노출한다. 선택 시 onChange(''). */
|
|
34
|
+
allowEmpty?: boolean;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
size?: 'sm' | 'md' | 'lg';
|
|
37
|
+
invalid?: boolean;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
id?: string;
|
|
40
|
+
}
|
|
41
|
+
/** 바깥 style·className을 뿌리에 얹는다 — 자기 축(폭·여백) 통로. */
|
|
42
|
+
declare const PositionSelect: React.FC<PositionSelectProps & SduiBoxProps>;
|
|
43
|
+
|
|
44
|
+
export { PositionSelect, type PositionSelectProps };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { S as SduiBoxProps } from '../layout-B1QrIBm6.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* QRDisplay — 백엔드 QR 렌더러(GET {API_BASE}/qr)로 만든 QR 이미지를 카드로 표시.
|
|
6
|
+
*
|
|
7
|
+
* path(앱 내부 경로) 또는 url을 받아 마운트 후 절대 URL로 변환해
|
|
8
|
+
* 인코딩한다(SSR 안전). 백엔드가 없어 이미지 로드가 실패하면 점선
|
|
9
|
+
* 플레이스홀더 + 안내 문구로 대체한다.
|
|
10
|
+
*
|
|
11
|
+
* ## 자산 관문을 스스로 통과시킨다 (useSduiAssetResolver)
|
|
12
|
+
*
|
|
13
|
+
* 렌더러의 자산 순회는 **스펙이 준 URL**만 본다. 이 컴포넌트는 그 검사에 걸릴 문자열이
|
|
14
|
+
* 애초에 없다 — `src`를 프롭으로 받지 않고 `apiUrl('/qr?data=…')`로 **안에서 만들어**
|
|
15
|
+
* 붙이기 때문이다. 그래서 편집기 캔버스가 클릭·fetch·navigate를 다 막아 둔 상태에서도
|
|
16
|
+
* 이 `<img>` 하나는 잠금 밖이었다. 목적지가 동일 오리진이라 **세션 쿠키까지 실린다.**
|
|
17
|
+
*
|
|
18
|
+
* 더 나쁜 경우가 둘 더 있다.
|
|
19
|
+
* - 프롭을 아예 안 주면 `window.location.href`로 채우는데(아래 effect), 캔버스에서 그건
|
|
20
|
+
* **편집기 자신의 URL**이다. 남의 스펙을 여는 것만으로 편집 중인 화면 주소가 QR 인코딩
|
|
21
|
+
* 요청에 실려 나간다.
|
|
22
|
+
* - Tauri 데스크톱에서 `apiUrl`의 기준은 **사용자가 설정한 임의 호스트**다. 웹처럼
|
|
23
|
+
* 동일 오리진으로 끝나지 않는다.
|
|
24
|
+
*
|
|
25
|
+
* 그래서 URL을 만든 쪽이 직접 관문에 태운다. 진짜 앱에서는 항등함수라
|
|
26
|
+
* (`defaultAdapter.resolveAsset`) 바이트 단위로 같은 요청이 나간다.
|
|
27
|
+
*/
|
|
28
|
+
interface QRDisplayProps {
|
|
29
|
+
/** QR에 담을 앱 내부 경로(예: "/hr/employees/1"). 마운트 후 절대 URL로 변환. */
|
|
30
|
+
path?: string;
|
|
31
|
+
/** 절대/상대 URL을 직접 지정. path보다 우선한다. */
|
|
32
|
+
url?: string;
|
|
33
|
+
/** QR 한 변(px). 기본 128. */
|
|
34
|
+
size?: number;
|
|
35
|
+
/**
|
|
36
|
+
* QR 이미지를 내주는 서버 경로. `?data=<인코딩된 URL>&size=<px>` 가 붙는다.
|
|
37
|
+
* 기본 '/qr'. API 가 다른 오리진이면 그 절대 주소를 넘긴다.
|
|
38
|
+
*/
|
|
39
|
+
endpoint?: string;
|
|
40
|
+
caption?: string;
|
|
41
|
+
}
|
|
42
|
+
/** 바깥에서 온 `style`·`className`을 뿌리에 얹어 내보낸다 — 자기 축(폭·여백)이 닿게 하는 통로. */
|
|
43
|
+
declare const QRDisplay: React.FC<QRDisplayProps & SduiBoxProps>;
|
|
44
|
+
|
|
45
|
+
export { QRDisplay, type QRDisplayProps };
|
package/dist/widgets/index.d.ts
CHANGED
|
@@ -24,8 +24,12 @@ import { RecordSheetProps } from './RecordSheet.js';
|
|
|
24
24
|
export { RecordSheet, RecordSheetCell, RecordSheetCellKind, RecordSheetRow } from './RecordSheet.js';
|
|
25
25
|
import { RankBoardProps } from './RankBoard.js';
|
|
26
26
|
export { RankBoard } from './RankBoard.js';
|
|
27
|
+
import { QRDisplayProps } from './QRDisplay.js';
|
|
28
|
+
export { QRDisplay } from './QRDisplay.js';
|
|
27
29
|
import { PrintSheetProps } from './PrintSheet.js';
|
|
28
30
|
export { PrintSheet } from './PrintSheet.js';
|
|
31
|
+
import { PositionSelectProps } from './PositionSelect.js';
|
|
32
|
+
export { PositionSelect } from './PositionSelect.js';
|
|
29
33
|
import { PeriodFilterProps } from './PeriodFilter.js';
|
|
30
34
|
export { Period, PeriodFilter, PeriodMode, PeriodModeItem } from './PeriodFilter.js';
|
|
31
35
|
import { PermissionMatrixEditorProps } from './PermissionMatrixEditor.js';
|
|
@@ -90,7 +94,9 @@ declare const widgetComponents: {
|
|
|
90
94
|
OrgChartBoard: React.FC<OrgChartBoardProps & SduiBoxProps>;
|
|
91
95
|
PermissionMatrixEditor: React.FC<PermissionMatrixEditorProps & SduiBoxProps>;
|
|
92
96
|
PeriodFilter: React.FC<PeriodFilterProps & SduiBoxProps>;
|
|
97
|
+
PositionSelect: React.FC<PositionSelectProps & SduiBoxProps>;
|
|
93
98
|
PrintSheet: React.FC<PrintSheetProps & SduiBoxProps>;
|
|
99
|
+
QRDisplay: React.FC<QRDisplayProps & SduiBoxProps>;
|
|
94
100
|
RankBoard: React.FC<RankBoardProps & SduiBoxProps>;
|
|
95
101
|
RecordSheet: React.FC<RecordSheetProps & SduiBoxProps>;
|
|
96
102
|
RoleMemberPicker: React.FC<RoleMemberPickerProps & SduiBoxProps>;
|
|
@@ -108,4 +114,4 @@ declare const widgetComponents: {
|
|
|
108
114
|
/** 위젯 어휘의 컴포넌트 이름 union — 메타데이터 대조에 쓴다(`@wipco/sdui/meta`). */
|
|
109
115
|
type SduiWidgetComponentName = keyof typeof widgetComponents;
|
|
110
116
|
|
|
111
|
-
export { ApprovalLineEditorProps, ApprovalOverridesEditorProps, ApprovalStepperProps, ColumnBoardProps, DiffViewProps, DisclosureProps, EventCalendarProps, ImageLightboxProps, InlineEditProps, JsonFieldProps, LiveClockProps, OptionSchemaEditorProps, OptionValueFieldsProps, OrgChartBoardProps, OrgChartProps, PeriodFilterProps, PermissionMatrixEditorProps, PrintSheetProps, RankBoardProps, RecordSheetProps, RoleMemberPickerProps, type SduiWidgetComponentName, SearchableMultiPickerProps, SecureScreenProps, StackedMeterProps, StagePeriodEditorProps, StripProps, SummaryTableProps, TagMultiSelectProps, TimelineProps, TreePickerProps, TreeViewProps, widgetComponents };
|
|
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 };
|
package/dist/widgets/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { StackedMeter } from '../chunk-BMZKZGJF.js';
|
|
2
|
+
export { StackedMeter } from '../chunk-BMZKZGJF.js';
|
|
3
|
+
import { StagePeriodEditor } from '../chunk-KVFHPBAY.js';
|
|
4
|
+
export { StagePeriodEditor } from '../chunk-KVFHPBAY.js';
|
|
1
5
|
import { Strip } from '../chunk-ZH5MLOZS.js';
|
|
2
6
|
export { Strip } from '../chunk-ZH5MLOZS.js';
|
|
3
7
|
import { SummaryTable } from '../chunk-O4U7Y3XL.js';
|
|
@@ -8,8 +12,12 @@ import { TreePicker } from '../chunk-U3HYQCFA.js';
|
|
|
8
12
|
export { TreePicker } from '../chunk-U3HYQCFA.js';
|
|
9
13
|
import { TreeView } from '../chunk-X5R2HHEN.js';
|
|
10
14
|
export { TreeView, buildTreeNodes } from '../chunk-X5R2HHEN.js';
|
|
15
|
+
import { PositionSelect } from '../chunk-D4AILKSJ.js';
|
|
16
|
+
export { PositionSelect } from '../chunk-D4AILKSJ.js';
|
|
11
17
|
import { PrintSheet } from '../chunk-MYJ2KEIP.js';
|
|
12
18
|
export { PrintSheet } from '../chunk-MYJ2KEIP.js';
|
|
19
|
+
import { QRDisplay } from '../chunk-PCMJE2GO.js';
|
|
20
|
+
export { QRDisplay } from '../chunk-PCMJE2GO.js';
|
|
13
21
|
import { RankBoard } from '../chunk-U6H7YN4I.js';
|
|
14
22
|
export { RankBoard } from '../chunk-U6H7YN4I.js';
|
|
15
23
|
import { RecordSheet } from '../chunk-K3JBSWFI.js';
|
|
@@ -20,10 +28,6 @@ import { SearchableMultiPicker } from '../chunk-C53NGSA3.js';
|
|
|
20
28
|
export { SearchableMultiPicker } from '../chunk-C53NGSA3.js';
|
|
21
29
|
import { SecureScreen } from '../chunk-IIRENCDS.js';
|
|
22
30
|
export { SecureScreen } from '../chunk-IIRENCDS.js';
|
|
23
|
-
import { StackedMeter } from '../chunk-BMZKZGJF.js';
|
|
24
|
-
export { StackedMeter } from '../chunk-BMZKZGJF.js';
|
|
25
|
-
import { StagePeriodEditor } from '../chunk-KVFHPBAY.js';
|
|
26
|
-
export { StagePeriodEditor } from '../chunk-KVFHPBAY.js';
|
|
27
31
|
import { JsonField } from '../chunk-JVBZRDC2.js';
|
|
28
32
|
export { JsonField } from '../chunk-JVBZRDC2.js';
|
|
29
33
|
import { LiveClock } from '../chunk-Z3WGIFJP.js';
|
|
@@ -43,8 +47,8 @@ export { PeriodFilter } from '../chunk-INWASR2G.js';
|
|
|
43
47
|
export { AutocompleteField, toAutocompleteOptions } from '../chunk-CVCP52OD.js';
|
|
44
48
|
import { ColumnBoard } from '../chunk-C4JRSZGS.js';
|
|
45
49
|
export { ColumnBoard } from '../chunk-C4JRSZGS.js';
|
|
46
|
-
import { DiffView } from '../chunk-
|
|
47
|
-
export { DiffView } from '../chunk-
|
|
50
|
+
import { DiffView } from '../chunk-XAYXHY7R.js';
|
|
51
|
+
export { DiffView } from '../chunk-XAYXHY7R.js';
|
|
48
52
|
import { Disclosure } from '../chunk-HIZ2OVJA.js';
|
|
49
53
|
export { Disclosure } from '../chunk-HIZ2OVJA.js';
|
|
50
54
|
import { EventCalendar } from '../chunk-C3JY6GA3.js';
|
|
@@ -92,7 +96,9 @@ var widgetComponents = {
|
|
|
92
96
|
OrgChartBoard,
|
|
93
97
|
PermissionMatrixEditor,
|
|
94
98
|
PeriodFilter,
|
|
99
|
+
PositionSelect,
|
|
95
100
|
PrintSheet,
|
|
101
|
+
QRDisplay,
|
|
96
102
|
RankBoard,
|
|
97
103
|
RecordSheet,
|
|
98
104
|
RoleMemberPicker,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wipco/sdui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "WIPCO 서버 주도 UI(SDUI) 렌더러 — JSON 페이지 스펙을 React 컴포넌트로 렌더링",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sdui",
|
|
@@ -116,10 +116,18 @@
|
|
|
116
116
|
"types": "./dist/widgets/PeriodFilter.d.ts",
|
|
117
117
|
"default": "./dist/widgets/PeriodFilter.js"
|
|
118
118
|
},
|
|
119
|
+
"./widgets/PositionSelect": {
|
|
120
|
+
"types": "./dist/widgets/PositionSelect.d.ts",
|
|
121
|
+
"default": "./dist/widgets/PositionSelect.js"
|
|
122
|
+
},
|
|
119
123
|
"./widgets/PrintSheet": {
|
|
120
124
|
"types": "./dist/widgets/PrintSheet.d.ts",
|
|
121
125
|
"default": "./dist/widgets/PrintSheet.js"
|
|
122
126
|
},
|
|
127
|
+
"./widgets/QRDisplay": {
|
|
128
|
+
"types": "./dist/widgets/QRDisplay.d.ts",
|
|
129
|
+
"default": "./dist/widgets/QRDisplay.js"
|
|
130
|
+
},
|
|
123
131
|
"./widgets/RankBoard": {
|
|
124
132
|
"types": "./dist/widgets/RankBoard.d.ts",
|
|
125
133
|
"default": "./dist/widgets/RankBoard.js"
|