@wipco/sdui 1.6.0 → 1.7.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/{DatePicker-DX9juElE.d.ts → DatePicker-BOOKdd5x.d.ts} +6 -6
- package/dist/calendar-nav-BSGsgJc4.d.ts +54 -0
- package/dist/{chunk-53KS4E5N.js → chunk-27ILQUWE.js} +121 -28
- package/dist/{chunk-AY4GM6KQ.js → chunk-466W3XNK.js} +1 -1
- package/dist/{chunk-X2NIRVLN.js → chunk-4VQIKSDS.js} +157 -190
- package/dist/{chunk-LIZTK3HO.js → chunk-5FZBH3T5.js} +1 -1
- package/dist/{chunk-NA232CBX.js → chunk-5LIFU57A.js} +2 -2
- package/dist/{chunk-LKQJJSVJ.js → chunk-63GM4S25.js} +1 -1
- package/dist/{chunk-CSE3PZOZ.js → chunk-7EDFYBUA.js} +4 -4
- package/dist/{chunk-MN4RZ2WP.js → chunk-7YTZB5LQ.js} +3 -3
- package/dist/{chunk-WEG3V7ZB.js → chunk-7ZCM6XEM.js} +2 -2
- package/dist/{chunk-6XI2VF2O.js → chunk-A22QR6PM.js} +2 -2
- package/dist/{chunk-CEVZAFPO.js → chunk-A3SO6H47.js} +2 -2
- package/dist/{chunk-2KQL6DYG.js → chunk-AP33B24H.js} +65 -9
- package/dist/{chunk-FEKKOBPX.js → chunk-B5MB64YQ.js} +209 -25
- package/dist/{chunk-IQXLNICY.js → chunk-DCSUBFFG.js} +4 -4
- package/dist/{chunk-OUEJWC2Z.js → chunk-DILQ2DJV.js} +5 -5
- package/dist/{chunk-NAIWQQPW.js → chunk-ENZBX4AR.js} +1 -1
- package/dist/{chunk-WTIYILY3.js → chunk-FGKBXUUA.js} +1 -1
- package/dist/{chunk-CI5OZ2QT.js → chunk-FUNCQCKN.js} +2 -2
- package/dist/{chunk-XG22XKKD.js → chunk-GWT5UF5B.js} +2 -2
- package/dist/{chunk-K6RE23XX.js → chunk-H5QRRPBJ.js} +3 -3
- package/dist/{chunk-AZSLSAJB.js → chunk-JCG4575S.js} +2 -2
- package/dist/{chunk-YZTTFEL4.js → chunk-JMNUFA5M.js} +1 -1
- package/dist/{chunk-KZ6U6FKB.js → chunk-L6ODTHTX.js} +1 -1
- package/dist/{chunk-W4VA76QO.js → chunk-LKA43GYA.js} +1 -1
- package/dist/{chunk-6TI4WF5Y.js → chunk-LKL3SCBJ.js} +2 -2
- package/dist/{chunk-4OABUPIU.js → chunk-LN4KPZIX.js} +3 -3
- package/dist/chunk-MUXGTVEA.js +421 -0
- package/dist/{chunk-7C54CKFZ.js → chunk-MWBCQHKQ.js} +3 -3
- package/dist/{chunk-7JP52QQO.js → chunk-NI3LMETK.js} +2 -2
- package/dist/{chunk-HXLQSO66.js → chunk-NJTIJAFU.js} +2 -2
- package/dist/{chunk-YN7X7BEO.js → chunk-NQDHGK7C.js} +3 -3
- package/dist/{chunk-BLFJMMBW.js → chunk-OWM7E55U.js} +25 -2
- package/dist/{chunk-VPOOIEKT.js → chunk-P62INTQ5.js} +1 -1
- package/dist/{chunk-QVS6K4FP.js → chunk-Q56LZJFX.js} +1 -1
- package/dist/{chunk-BITS7UJY.js → chunk-R2ORCOTG.js} +2 -2
- package/dist/{chunk-2QXA52DG.js → chunk-RA74PUMP.js} +3 -3
- package/dist/{chunk-GSM664TX.js → chunk-TAVKGYH5.js} +24 -1
- package/dist/{chunk-OYDJHQNZ.js → chunk-UBVYPV7H.js} +2 -2
- package/dist/chunk-VR4DQTWR.js +391 -0
- package/dist/{chunk-M6H3SHIS.js → chunk-WPAZBAUW.js} +1 -1
- package/dist/{chunk-NWYYNE3Q.js → chunk-WTQH2NI2.js} +1 -1
- package/dist/{chunk-HRHKQOOF.js → chunk-X7RSKFWF.js} +1 -1
- package/dist/{chunk-CSZCWBOE.js → chunk-XDR6HC4U.js} +14 -7
- package/dist/{chunk-RU5U2YMT.js → chunk-Z4JZUIKE.js} +3 -3
- package/dist/{chunk-V7BWMOHO.js → chunk-Z4LFZWHH.js} +2 -2
- package/dist/{chunk-YNEEJCSZ.js → chunk-ZBX2CAOO.js} +2 -2
- package/dist/index.d.ts +57 -7
- package/dist/index.js +93 -37
- package/dist/meta.d.ts +1 -1
- package/dist/meta.js +129 -4
- package/dist/rich/ExcelUploadCard.js +4 -4
- package/dist/rich.d.ts +4 -2
- package/dist/rich.js +36 -8
- package/dist/styles.css +27 -0
- package/dist/{types-CYfIthux.d.ts → types-CMikpoN5.d.ts} +8 -1
- package/dist/widgets/ApprovalLineEditor.js +9 -8
- package/dist/widgets/ApprovalOverridesEditor.js +11 -10
- package/dist/widgets/ApprovalStepper.js +2 -2
- package/dist/widgets/AutocompleteField.js +9 -8
- package/dist/widgets/ColumnBoard.js +2 -2
- package/dist/widgets/DiffView.js +2 -2
- package/dist/widgets/Disclosure.js +2 -2
- package/dist/widgets/EventCalendar.d.ts +14 -10
- package/dist/widgets/EventCalendar.js +5 -3
- package/dist/widgets/FileDropzone.js +7 -7
- package/dist/widgets/ImageLightbox.js +5 -5
- package/dist/widgets/InlineEdit.js +2 -2
- package/dist/widgets/JsonField.js +2 -2
- package/dist/widgets/OptionSchemaEditor.js +3 -3
- package/dist/widgets/OptionValueFields.js +3 -3
- package/dist/widgets/OrgChart.js +3 -3
- package/dist/widgets/OrgChartBoard.d.ts +57 -4
- package/dist/widgets/OrgChartBoard.js +8 -8
- package/dist/widgets/PeriodFilter.js +6 -5
- package/dist/widgets/PermissionMatrixEditor.js +4 -4
- package/dist/widgets/PositionSelect.js +4 -4
- package/dist/widgets/PrintSheet.js +2 -2
- package/dist/widgets/ProfileEditDiffCard.js +4 -4
- package/dist/widgets/QRDisplay.js +4 -4
- package/dist/widgets/RankBoard.js +6 -6
- package/dist/widgets/RecordSheet.d.ts +48 -1
- package/dist/widgets/RecordSheet.js +2 -1
- package/dist/widgets/RoleMemberPicker.js +5 -5
- package/dist/widgets/SearchableMultiPicker.js +7 -6
- package/dist/widgets/SecureScreen.js +2 -2
- package/dist/widgets/StagePeriodEditor.js +6 -5
- package/dist/widgets/TagInput.js +2 -2
- package/dist/widgets/TagMultiSelect.js +4 -4
- package/dist/widgets/Timeline.js +3 -3
- package/dist/widgets/TreePicker.js +8 -7
- package/dist/widgets/TreeView.d.ts +16 -2
- package/dist/widgets/TreeView.js +7 -6
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.js +76 -75
- package/package.json +1 -1
- package/dist/chunk-IB2ZPUTF.js +0 -172
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { useIsMobile } from './chunk-TAVKGYH5.js';
|
|
2
|
+
import { boxed } from './chunk-3JTBOABA.js';
|
|
3
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var RECORD_SHEET_CSS = `
|
|
7
|
+
.erp-recsheet__scroll{overflow-x:auto;min-width:0}
|
|
8
|
+
.erp-recsheet{width:100%;min-width:clamp(40rem,100%,44rem);border-collapse:collapse;table-layout:fixed;font-size:var(--wp-size-sm)}
|
|
9
|
+
.erp-recsheet td{height:var(--wp-row-h-dense);border:var(--wp-border-w) solid var(--wp-border-default);padding:var(--wp-space-1) var(--wp-space-2);color:var(--wp-text-default);vertical-align:middle;line-height:var(--wp-leading-snug);overflow-wrap:anywhere}
|
|
10
|
+
.erp-recsheet td.erp-recsheet__title{background:var(--wp-surface-inverse);color:var(--wp-text-inverse);text-align:center;font-size:var(--wp-size-lg);font-weight:var(--wp-weight-semibold);letter-spacing:var(--wp-tracking-heading);padding:var(--wp-space-3) var(--wp-space-2)}
|
|
11
|
+
.erp-recsheet td.erp-recsheet__label{background:var(--wp-surface-sunken);color:var(--wp-text-subtle);font-size:var(--wp-size-xs);font-weight:var(--wp-weight-semibold);text-align:center;white-space:nowrap}
|
|
12
|
+
.erp-recsheet td.erp-recsheet__section{background:var(--wp-surface-brand-tint);border-top:var(--wp-border-w-strong) solid var(--wp-border-brand);color:var(--wp-text-brand);font-size:var(--wp-size-xs);font-weight:var(--wp-weight-semibold);letter-spacing:var(--wp-tracking-heading)}
|
|
13
|
+
.erp-recsheet tr.erp-recsheet__gap td{border:0;padding:0;height:var(--wp-space-3)}
|
|
14
|
+
.erp-recsheet td.erp-recsheet__mono{font-family:var(--wp-font-mono);font-size:var(--wp-size-xs)}
|
|
15
|
+
.erp-recsheet td.erp-recsheet__photo{background:var(--wp-surface-sunken);padding:var(--wp-space-2);text-align:center}
|
|
16
|
+
.erp-recsheet__img{display:block;width:100%;height:11rem;object-fit:cover;border-radius:var(--wp-radius-sm)}
|
|
17
|
+
.erp-recsheet__noimg{display:flex;align-items:center;justify-content:center;width:100%;height:11rem;border:var(--wp-border-w) dashed var(--wp-border-default);border-radius:var(--wp-radius-sm);color:var(--wp-text-disabled);font-size:var(--wp-size-xs)}
|
|
18
|
+
.erp-recsheet__note{margin:var(--wp-space-2) 0 0;text-align:right;color:var(--wp-text-subtle);font-size:var(--wp-size-xs)}
|
|
19
|
+
.erp-recsheet__frame{position:relative;min-width:0}
|
|
20
|
+
.erp-recsheet__frame::before,.erp-recsheet__frame::after{content:"";position:absolute;top:0;bottom:0;z-index:1;width:var(--wp-space-4);pointer-events:none;opacity:0;transition:opacity var(--wp-duration-fast)}
|
|
21
|
+
.erp-recsheet__frame::before{left:0;background:linear-gradient(to right,color-mix(in srgb,var(--wp-text-strong) 16%,transparent),transparent)}
|
|
22
|
+
.erp-recsheet__frame::after{right:0;background:linear-gradient(to left,color-mix(in srgb,var(--wp-text-strong) 16%,transparent),transparent)}
|
|
23
|
+
.erp-recsheet__frame[data-more-left]::before,.erp-recsheet__frame[data-more-right]::after{opacity:1}
|
|
24
|
+
.erp-recsheet-stack{display:flex;flex-direction:column;gap:var(--wp-space-3);min-width:0;font-size:var(--wp-size-sm);color:var(--wp-text-default)}
|
|
25
|
+
.erp-recsheet-stack__title{padding:var(--wp-space-2) var(--wp-space-3);background:var(--wp-surface-inverse);color:var(--wp-text-inverse);font-size:var(--wp-size-lg);font-weight:var(--wp-weight-semibold);letter-spacing:var(--wp-tracking-heading);line-height:var(--wp-leading-snug);text-align:left}
|
|
26
|
+
.erp-recsheet-stack__block{display:flex;flex-direction:column;min-width:0}
|
|
27
|
+
.erp-recsheet-stack__head{padding:var(--wp-space-2);background:var(--wp-surface-brand-tint);border-top:var(--wp-border-w-strong) solid var(--wp-border-brand);color:var(--wp-text-brand);font-size:var(--wp-size-xs);font-weight:var(--wp-weight-semibold);letter-spacing:var(--wp-tracking-heading)}
|
|
28
|
+
.erp-recsheet-stack__pairs{width:100%;border-collapse:collapse;table-layout:fixed}
|
|
29
|
+
.erp-recsheet-stack__pairs :is(th,td){height:var(--wp-row-h-dense);border:var(--wp-border-w) solid var(--wp-border-default);padding:var(--wp-space-1) var(--wp-space-2);vertical-align:middle;line-height:var(--wp-leading-snug);text-align:left;overflow-wrap:anywhere}
|
|
30
|
+
.erp-recsheet-stack__pairs th{width:6.5rem;background:var(--wp-surface-sunken);color:var(--wp-text-subtle);font-size:var(--wp-size-xs);font-weight:var(--wp-weight-semibold);word-break:keep-all;overflow-wrap:break-word}
|
|
31
|
+
.erp-recsheet-stack__pairs td.erp-recsheet__mono{font-family:var(--wp-font-mono);font-size:var(--wp-size-xs)}
|
|
32
|
+
.erp-recsheet-stack__scroll{overflow-x:auto;min-width:0;overscroll-behavior-x:contain}
|
|
33
|
+
.erp-recsheet.erp-recsheet-stack__grid{min-width:0;width:100%;table-layout:auto}
|
|
34
|
+
.erp-recsheet.erp-recsheet-stack__grid td{word-break:keep-all;overflow-wrap:break-word}
|
|
35
|
+
.erp-recsheet.erp-recsheet-stack__grid td.erp-recsheet__label{white-space:normal;min-width:3.5rem}
|
|
36
|
+
.erp-recsheet.erp-recsheet-stack__grid td.erp-recsheet__mono{white-space:nowrap}
|
|
37
|
+
.erp-recsheet-stack__photo{align-self:center;width:6.5rem}
|
|
38
|
+
.erp-recsheet-stack__photo :is(.erp-recsheet__img,.erp-recsheet__noimg){height:8.5rem}
|
|
39
|
+
.erp-recsheet-stack .erp-recsheet__note{margin:0}
|
|
40
|
+
@media print{
|
|
41
|
+
.erp-recsheet__frame::before,.erp-recsheet__frame::after{display:none}
|
|
42
|
+
.erp-recsheet__scroll{overflow-x:visible}
|
|
43
|
+
.erp-recsheet{min-width:0}
|
|
44
|
+
.erp-recsheet tr{break-inside:avoid}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
function RecordSheetStyles() {
|
|
48
|
+
return /* @__PURE__ */ jsx("style", { href: "erp-recsheet", precedence: "medium", children: RECORD_SHEET_CSS });
|
|
49
|
+
}
|
|
50
|
+
function gridColumns(columns) {
|
|
51
|
+
if (typeof columns !== "number" || !Number.isFinite(columns)) return 24;
|
|
52
|
+
return Math.min(60, Math.max(1, Math.floor(columns)));
|
|
53
|
+
}
|
|
54
|
+
function cellClass(cell) {
|
|
55
|
+
const classes = [];
|
|
56
|
+
if (cell.kind === "label") classes.push("erp-recsheet__label");
|
|
57
|
+
else if (cell.kind === "section") classes.push("erp-recsheet__section");
|
|
58
|
+
else if (cell.kind === "photo") classes.push("erp-recsheet__photo");
|
|
59
|
+
if (cell.mono) classes.push("erp-recsheet__mono");
|
|
60
|
+
return classes.length > 0 ? classes.join(" ") : void 0;
|
|
61
|
+
}
|
|
62
|
+
function isBlank(value) {
|
|
63
|
+
return value === null || value === void 0 || value === "";
|
|
64
|
+
}
|
|
65
|
+
function pickValue(cell, item) {
|
|
66
|
+
if (!item || typeof item !== "object") return void 0;
|
|
67
|
+
const row = item;
|
|
68
|
+
if (cell.fields && cell.fields.length > 0) {
|
|
69
|
+
const parts = cell.fields.map((name) => isBlank(row[name]) ? "" : String(row[name]));
|
|
70
|
+
if (parts.every((part) => part === "")) return void 0;
|
|
71
|
+
return parts.join(cell.separator ?? " ~ ");
|
|
72
|
+
}
|
|
73
|
+
if (cell.field) return row[cell.field];
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
function PhotoCell({ src, alt }) {
|
|
77
|
+
const [failed, setFailed] = useState(false);
|
|
78
|
+
const label = alt ?? "\uC0AC\uC9C4";
|
|
79
|
+
if (!src || failed) return /* @__PURE__ */ jsx("span", { className: "erp-recsheet__noimg", children: label });
|
|
80
|
+
return /* @__PURE__ */ jsx("img", { className: "erp-recsheet__img", src, alt: label, onError: () => setFailed(true) });
|
|
81
|
+
}
|
|
82
|
+
function cellContent(cell, item, repeated) {
|
|
83
|
+
if (cell.kind === "photo") return /* @__PURE__ */ jsx(PhotoCell, { src: cell.src, alt: cell.alt });
|
|
84
|
+
if (!repeated) {
|
|
85
|
+
if (!isBlank(cell.text)) return cell.text;
|
|
86
|
+
if (cell.kind === "label" || cell.kind === "section") return null;
|
|
87
|
+
return cell.placeholder ?? "-";
|
|
88
|
+
}
|
|
89
|
+
const value = pickValue(cell, item);
|
|
90
|
+
if (!isBlank(value)) return value;
|
|
91
|
+
return item ? cell.placeholder ?? "-" : null;
|
|
92
|
+
}
|
|
93
|
+
function renderCells(cells, items, keyPrefix) {
|
|
94
|
+
return cells.map((cell, index) => {
|
|
95
|
+
const item = items ? items[cell.source ?? 0] ?? null : null;
|
|
96
|
+
return /* @__PURE__ */ jsx(
|
|
97
|
+
"td",
|
|
98
|
+
{
|
|
99
|
+
className: cellClass(cell),
|
|
100
|
+
colSpan: cell.span && cell.span > 1 ? cell.span : void 0,
|
|
101
|
+
rowSpan: cell.rowSpan && cell.rowSpan > 1 ? cell.rowSpan : void 0,
|
|
102
|
+
style: cell.align && cell.align !== "left" ? { textAlign: cell.align } : void 0,
|
|
103
|
+
children: cellContent(cell, item, items !== null)
|
|
104
|
+
},
|
|
105
|
+
`${keyPrefix}-${index}`
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function repeatLength(sources, minRows) {
|
|
110
|
+
const longest = sources.reduce((max, source) => Math.max(max, source.length), 0);
|
|
111
|
+
return Math.max(longest, Math.max(0, Math.floor(minRows ?? 0)));
|
|
112
|
+
}
|
|
113
|
+
function spanOf(value, fallback = 1) {
|
|
114
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
|
|
115
|
+
}
|
|
116
|
+
function placeRecordSheetCells(rows, width) {
|
|
117
|
+
const carry = new Array(width).fill(0);
|
|
118
|
+
return rows.map((row) => {
|
|
119
|
+
const cells = row && !row.gap && Array.isArray(row.cells) ? row.cells : [];
|
|
120
|
+
const placed = [];
|
|
121
|
+
let col = 0;
|
|
122
|
+
for (const cell of cells) {
|
|
123
|
+
while (col < width && carry[col] > 0) col += 1;
|
|
124
|
+
const start = Math.min(col, width);
|
|
125
|
+
const end = Math.min(width, start + spanOf(cell?.span));
|
|
126
|
+
placed.push({ cell: cell ?? {}, start, end });
|
|
127
|
+
const rowSpan = spanOf(cell?.rowSpan);
|
|
128
|
+
if (rowSpan > 1) for (let c = start; c < end; c += 1) carry[c] = rowSpan;
|
|
129
|
+
col = end;
|
|
130
|
+
}
|
|
131
|
+
for (let c = 0; c < width; c += 1) if (carry[c] > 0) carry[c] -= 1;
|
|
132
|
+
return placed;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
var isLabelLike = (cell) => cell.kind === "label" || cell.kind === "section";
|
|
136
|
+
function pairsOf(cells) {
|
|
137
|
+
const pairs = [];
|
|
138
|
+
for (const cell of cells) {
|
|
139
|
+
if (isLabelLike(cell)) pairs.push({ label: cell, values: [] });
|
|
140
|
+
else if (pairs.length > 0) pairs[pairs.length - 1].values.push(cell);
|
|
141
|
+
else pairs.push({ label: null, values: [cell] });
|
|
142
|
+
}
|
|
143
|
+
return pairs;
|
|
144
|
+
}
|
|
145
|
+
function stackRecordSheet(rows, width) {
|
|
146
|
+
const list = Array.isArray(rows) ? rows : [];
|
|
147
|
+
const placedRows = placeRecordSheetCells(list, width);
|
|
148
|
+
const blocks = [];
|
|
149
|
+
let open = [];
|
|
150
|
+
const push = (block, part) => {
|
|
151
|
+
const last = block.parts[block.parts.length - 1];
|
|
152
|
+
if (last && last.kind === "pairs" && part.kind === "pairs") last.pairs.push(...part.pairs);
|
|
153
|
+
else if (last && last.kind === "grid" && part.kind === "grid") last.rows.push(...part.rows);
|
|
154
|
+
else block.parts.push(part);
|
|
155
|
+
};
|
|
156
|
+
list.forEach((row, index) => {
|
|
157
|
+
if (row?.gap) {
|
|
158
|
+
open = [];
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const placed = placedRows[index];
|
|
162
|
+
if (placed.length === 0) return;
|
|
163
|
+
if (placed.every((p) => p.cell.kind === "section")) {
|
|
164
|
+
open = placed.map((p) => ({ block: { section: p.cell, parts: [] }, start: p.start, end: p.end }));
|
|
165
|
+
blocks.push(...open.map((o) => o.block));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (open.length === 0) {
|
|
169
|
+
const block = { section: null, parts: [] };
|
|
170
|
+
blocks.push(block);
|
|
171
|
+
open = [{ block, start: 0, end: width }];
|
|
172
|
+
}
|
|
173
|
+
for (const target of open) {
|
|
174
|
+
const mine = placed.filter((p) => {
|
|
175
|
+
const owner = open.find((o) => p.start >= o.start && p.start < o.end) ?? open[0];
|
|
176
|
+
return owner === target;
|
|
177
|
+
});
|
|
178
|
+
if (mine.length === 0) continue;
|
|
179
|
+
const rest = [];
|
|
180
|
+
for (const p of mine) {
|
|
181
|
+
if (p.cell.kind === "photo") push(target.block, { kind: "photo", cell: p.cell });
|
|
182
|
+
else rest.push(p);
|
|
183
|
+
}
|
|
184
|
+
if (rest.length === 0) continue;
|
|
185
|
+
const repeated = Array.isArray(row.repeat);
|
|
186
|
+
const hasLabel = rest.some((p) => isLabelLike(p.cell));
|
|
187
|
+
const hasValue = rest.some((p) => !isLabelLike(p.cell));
|
|
188
|
+
if (!repeated && hasLabel && hasValue) {
|
|
189
|
+
push(target.block, { kind: "pairs", pairs: pairsOf(rest.map((p) => p.cell)) });
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const cells = rest.map((p) => ({ ...p, start: p.start - target.start, end: p.end - target.start }));
|
|
193
|
+
push(target.block, {
|
|
194
|
+
kind: "grid",
|
|
195
|
+
rows: [
|
|
196
|
+
repeated ? {
|
|
197
|
+
cells,
|
|
198
|
+
repeat: row.repeat.map((source) => Array.isArray(source) ? source : []),
|
|
199
|
+
minRows: row.minRows
|
|
200
|
+
} : { cells }
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
return blocks;
|
|
206
|
+
}
|
|
207
|
+
function gridBoundaries(rows) {
|
|
208
|
+
const set = /* @__PURE__ */ new Set();
|
|
209
|
+
for (const row of rows) for (const p of row.cells) set.add(p.start).add(p.end);
|
|
210
|
+
return [...set].sort((a, b) => a - b);
|
|
211
|
+
}
|
|
212
|
+
function StackGrid({ rows, keyPrefix }) {
|
|
213
|
+
const scrollRef = useRef(null);
|
|
214
|
+
const edges = useScrollEdges(scrollRef);
|
|
215
|
+
const bounds = gridBoundaries(rows);
|
|
216
|
+
const spanIn = (p) => {
|
|
217
|
+
const n = bounds.filter((b) => b >= p.start && b < p.end).length;
|
|
218
|
+
return n > 1 ? n : void 0;
|
|
219
|
+
};
|
|
220
|
+
const lines = [];
|
|
221
|
+
const cellsOf = (row, items, key) => row.cells.map((p, index) => {
|
|
222
|
+
const item = items ? items[p.cell.source ?? 0] ?? null : null;
|
|
223
|
+
return /* @__PURE__ */ jsx(
|
|
224
|
+
"td",
|
|
225
|
+
{
|
|
226
|
+
className: cellClass(p.cell),
|
|
227
|
+
colSpan: spanIn(p),
|
|
228
|
+
style: p.cell.align && p.cell.align !== "left" ? { textAlign: p.cell.align } : void 0,
|
|
229
|
+
children: cellContent(p.cell, item, items !== null)
|
|
230
|
+
},
|
|
231
|
+
`${key}-${index}`
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
rows.forEach((row, rowIndex) => {
|
|
235
|
+
if (!row.repeat) {
|
|
236
|
+
lines.push(/* @__PURE__ */ jsx("tr", { children: cellsOf(row, null, `${keyPrefix}-r${rowIndex}`) }, `${keyPrefix}-r${rowIndex}`));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const sources = row.repeat;
|
|
240
|
+
const used = new Set(row.cells.map((p) => p.cell.source ?? 0));
|
|
241
|
+
const longest = [...used].reduce((max, i) => Math.max(max, sources[i]?.length ?? 0), 0);
|
|
242
|
+
const count = longest > 0 ? longest : Math.min(1, Math.max(0, Math.floor(row.minRows ?? 0)));
|
|
243
|
+
for (let line = 0; line < count; line += 1) {
|
|
244
|
+
const key = `${keyPrefix}-r${rowIndex}-${line}`;
|
|
245
|
+
lines.push(/* @__PURE__ */ jsx("tr", { children: cellsOf(row, sources.map((source) => source[line] ?? null), key) }, key));
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return /* @__PURE__ */ jsx(
|
|
249
|
+
"div",
|
|
250
|
+
{
|
|
251
|
+
className: "erp-recsheet__frame",
|
|
252
|
+
"data-more-left": edges.left ? "" : void 0,
|
|
253
|
+
"data-more-right": edges.right ? "" : void 0,
|
|
254
|
+
children: /* @__PURE__ */ jsx("div", { ref: scrollRef, className: "erp-recsheet-stack__scroll", children: /* @__PURE__ */ jsx("table", { className: "erp-recsheet erp-recsheet-stack__grid", children: /* @__PURE__ */ jsx("tbody", { children: lines }) }) })
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
function StackPairs({ pairs, keyPrefix }) {
|
|
259
|
+
return /* @__PURE__ */ jsx("table", { className: "erp-recsheet-stack__pairs", children: /* @__PURE__ */ jsx("tbody", { children: pairs.map((pair, index) => {
|
|
260
|
+
const values = pair.values.map((cell, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
261
|
+
i > 0 ? " " : null,
|
|
262
|
+
cellContent(cell, null, false)
|
|
263
|
+
] }, i));
|
|
264
|
+
const mono = pair.values.length > 0 && pair.values.every((cell) => cell.mono);
|
|
265
|
+
return /* @__PURE__ */ jsx("tr", { className: "erp-recsheet-stack__pair", children: pair.label ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
266
|
+
/* @__PURE__ */ jsx("th", { scope: "row", children: pair.label.text }),
|
|
267
|
+
/* @__PURE__ */ jsx("td", { className: mono ? "erp-recsheet__mono" : void 0, children: values })
|
|
268
|
+
] }) : /* @__PURE__ */ jsx("td", { colSpan: 2, className: mono ? "erp-recsheet__mono" : void 0, children: values }) }, `${keyPrefix}-${index}`);
|
|
269
|
+
}) }) });
|
|
270
|
+
}
|
|
271
|
+
function RecordSheetStack({
|
|
272
|
+
width,
|
|
273
|
+
title,
|
|
274
|
+
rows,
|
|
275
|
+
note,
|
|
276
|
+
className,
|
|
277
|
+
style
|
|
278
|
+
}) {
|
|
279
|
+
const blocks = stackRecordSheet(rows, width);
|
|
280
|
+
return /* @__PURE__ */ jsxs("div", { className: className ? `erp-recsheet__frame ${className}` : "erp-recsheet__frame", style, children: [
|
|
281
|
+
/* @__PURE__ */ jsx(RecordSheetStyles, {}),
|
|
282
|
+
/* @__PURE__ */ jsxs("div", { className: "erp-recsheet-stack", children: [
|
|
283
|
+
title ? /* @__PURE__ */ jsx("div", { className: "erp-recsheet-stack__title", children: title }) : null,
|
|
284
|
+
blocks.map((block, blockIndex) => /* @__PURE__ */ jsxs("section", { className: "erp-recsheet-stack__block", children: [
|
|
285
|
+
block.section ? /* @__PURE__ */ jsx("div", { className: "erp-recsheet-stack__head", children: block.section.text }) : null,
|
|
286
|
+
block.parts.map((part, partIndex) => {
|
|
287
|
+
const key = `b${blockIndex}-p${partIndex}`;
|
|
288
|
+
if (part.kind === "photo") {
|
|
289
|
+
return /* @__PURE__ */ jsx("div", { className: "erp-recsheet-stack__photo", children: /* @__PURE__ */ jsx(PhotoCell, { src: part.cell.src, alt: part.cell.alt }) }, key);
|
|
290
|
+
}
|
|
291
|
+
if (part.kind === "pairs") return /* @__PURE__ */ jsx(StackPairs, { pairs: part.pairs, keyPrefix: key }, key);
|
|
292
|
+
return /* @__PURE__ */ jsx(StackGrid, { rows: part.rows, keyPrefix: key }, key);
|
|
293
|
+
})
|
|
294
|
+
] }, blockIndex)),
|
|
295
|
+
note ? /* @__PURE__ */ jsx("p", { className: "erp-recsheet__note", children: note }) : null
|
|
296
|
+
] })
|
|
297
|
+
] });
|
|
298
|
+
}
|
|
299
|
+
function RecordSheetImpl(props) {
|
|
300
|
+
const isMobile = useIsMobile();
|
|
301
|
+
if (isMobile) {
|
|
302
|
+
return /* @__PURE__ */ jsx(
|
|
303
|
+
RecordSheetStack,
|
|
304
|
+
{
|
|
305
|
+
width: gridColumns(props.columns),
|
|
306
|
+
title: props.title,
|
|
307
|
+
rows: Array.isArray(props.rows) ? props.rows : [],
|
|
308
|
+
note: props.note
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
return /* @__PURE__ */ jsx(RecordSheetGrid, { ...props });
|
|
313
|
+
}
|
|
314
|
+
function RecordSheetGrid({ columns, title, rows, note, className, style }) {
|
|
315
|
+
const scrollRef = useRef(null);
|
|
316
|
+
const edges = useScrollEdges(scrollRef);
|
|
317
|
+
const width = gridColumns(columns);
|
|
318
|
+
const list = Array.isArray(rows) ? rows : [];
|
|
319
|
+
const body = [];
|
|
320
|
+
list.forEach((row, rowIndex) => {
|
|
321
|
+
if (row?.gap) {
|
|
322
|
+
body.push(
|
|
323
|
+
/* @__PURE__ */ jsx("tr", { className: "erp-recsheet__gap", children: /* @__PURE__ */ jsx("td", { colSpan: width }) }, `gap-${rowIndex}`)
|
|
324
|
+
);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const cells = Array.isArray(row?.cells) ? row.cells : [];
|
|
328
|
+
if (cells.length === 0) return;
|
|
329
|
+
if (Array.isArray(row.repeat)) {
|
|
330
|
+
const sources = row.repeat.map((source) => Array.isArray(source) ? source : []);
|
|
331
|
+
const count = repeatLength(sources, row.minRows);
|
|
332
|
+
for (let line = 0; line < count; line += 1) {
|
|
333
|
+
body.push(
|
|
334
|
+
/* @__PURE__ */ jsx("tr", { children: renderCells(
|
|
335
|
+
cells,
|
|
336
|
+
sources.map((source) => source[line] ?? null),
|
|
337
|
+
`rep-${rowIndex}-${line}`
|
|
338
|
+
) }, `rep-${rowIndex}-${line}`)
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
body.push(/* @__PURE__ */ jsx("tr", { children: renderCells(cells, null, `row-${rowIndex}`) }, `row-${rowIndex}`));
|
|
344
|
+
});
|
|
345
|
+
return /* @__PURE__ */ jsx(
|
|
346
|
+
"div",
|
|
347
|
+
{
|
|
348
|
+
className: className ? `erp-recsheet__frame ${className}` : "erp-recsheet__frame",
|
|
349
|
+
style,
|
|
350
|
+
"data-more-left": edges.left ? "" : void 0,
|
|
351
|
+
"data-more-right": edges.right ? "" : void 0,
|
|
352
|
+
children: /* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "erp-recsheet__scroll", children: [
|
|
353
|
+
/* @__PURE__ */ jsx(RecordSheetStyles, {}),
|
|
354
|
+
/* @__PURE__ */ jsxs("table", { className: "erp-recsheet", children: [
|
|
355
|
+
/* @__PURE__ */ jsx("colgroup", { children: Array.from({ length: width }, (_, index) => /* @__PURE__ */ jsx("col", { style: { width: `${100 / width}%` } }, index)) }),
|
|
356
|
+
/* @__PURE__ */ jsxs("tbody", { children: [
|
|
357
|
+
title ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { className: "erp-recsheet__title", colSpan: width, children: title }) }) : null,
|
|
358
|
+
body
|
|
359
|
+
] })
|
|
360
|
+
] }),
|
|
361
|
+
note ? /* @__PURE__ */ jsx("p", { className: "erp-recsheet__note", children: note }) : null
|
|
362
|
+
] })
|
|
363
|
+
}
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
function useScrollEdges(ref) {
|
|
367
|
+
const [edges, setEdges] = useState({ left: false, right: false });
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
const el = ref.current;
|
|
370
|
+
if (!el) return;
|
|
371
|
+
const update = () => {
|
|
372
|
+
const left = el.scrollLeft > 1;
|
|
373
|
+
const right = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
374
|
+
setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
|
|
375
|
+
};
|
|
376
|
+
update();
|
|
377
|
+
el.addEventListener("scroll", update, { passive: true });
|
|
378
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
379
|
+
observer?.observe(el);
|
|
380
|
+
const table = el.querySelector("table");
|
|
381
|
+
if (table) observer?.observe(table);
|
|
382
|
+
return () => {
|
|
383
|
+
el.removeEventListener("scroll", update);
|
|
384
|
+
observer?.disconnect();
|
|
385
|
+
};
|
|
386
|
+
}, [ref]);
|
|
387
|
+
return edges;
|
|
388
|
+
}
|
|
389
|
+
var RecordSheet = boxed(RecordSheetImpl, "RecordSheet");
|
|
390
|
+
|
|
391
|
+
export { RecordSheet, placeRecordSheetCells, stackRecordSheet };
|
|
@@ -6,21 +6,25 @@ var MAX_ZOOM = 1.8;
|
|
|
6
6
|
var PINCH_CLICK_GRACE_MS = 400;
|
|
7
7
|
var PAN_SLOP_PX = 6;
|
|
8
8
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
9
|
-
function applyZoom(current, nextScale, focal) {
|
|
10
|
-
const scale = clamp(nextScale, MIN_ZOOM, MAX_ZOOM);
|
|
9
|
+
function applyZoom(current, nextScale, focal, minScale = MIN_ZOOM) {
|
|
10
|
+
const scale = clamp(nextScale, Math.min(MIN_ZOOM, minScale), MAX_ZOOM);
|
|
11
11
|
return {
|
|
12
12
|
scale,
|
|
13
13
|
x: focal.x - (focal.x - current.x) / current.scale * scale,
|
|
14
14
|
y: focal.y - (focal.y - current.y) / current.scale * scale
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
function applyPinch(start, startDistance, startMid, distance, mid) {
|
|
17
|
+
function applyPinch(start, startDistance, startMid, distance, mid, minScale = MIN_ZOOM) {
|
|
18
18
|
const ratio = startDistance > 0 ? distance / startDistance : 1;
|
|
19
|
-
const zoomed = applyZoom(start, start.scale * ratio, startMid);
|
|
19
|
+
const zoomed = applyZoom(start, start.scale * ratio, startMid, minScale);
|
|
20
20
|
return { ...zoomed, x: zoomed.x + mid.x - startMid.x, y: zoomed.y + mid.y - startMid.y };
|
|
21
21
|
}
|
|
22
22
|
function usePanZoomCanvas(options) {
|
|
23
23
|
const { stopSelector, initialView } = options;
|
|
24
|
+
const minScaleRef = useRef(options.minScale ?? MIN_ZOOM);
|
|
25
|
+
minScaleRef.current = options.minScale ?? MIN_ZOOM;
|
|
26
|
+
const wheelNeedsCtrlRef = useRef(Boolean(options.wheelNeedsCtrl));
|
|
27
|
+
wheelNeedsCtrlRef.current = Boolean(options.wheelNeedsCtrl);
|
|
24
28
|
const viewportRef = useRef(null);
|
|
25
29
|
const dragRef = useRef(null);
|
|
26
30
|
const interactedRef = useRef(false);
|
|
@@ -42,6 +46,8 @@ function usePanZoomCanvas(options) {
|
|
|
42
46
|
const [nativeFullscreen, setNativeFullscreen] = useState(false);
|
|
43
47
|
const [pseudoFullscreen, setPseudoFullscreen] = useState(false);
|
|
44
48
|
const isFullscreen = nativeFullscreen || pseudoFullscreen;
|
|
49
|
+
const isFullscreenRef = useRef(isFullscreen);
|
|
50
|
+
isFullscreenRef.current = isFullscreen;
|
|
45
51
|
useEffect(() => {
|
|
46
52
|
const handleFullscreenChange = () => {
|
|
47
53
|
setNativeFullscreen(document.fullscreenElement === viewportRef.current);
|
|
@@ -70,12 +76,13 @@ function usePanZoomCanvas(options) {
|
|
|
70
76
|
const viewport = viewportRef.current;
|
|
71
77
|
if (!viewport) return;
|
|
72
78
|
const onWheel = (event) => {
|
|
79
|
+
if (wheelNeedsCtrlRef.current && !isFullscreenRef.current && !event.ctrlKey) return;
|
|
73
80
|
event.preventDefault();
|
|
74
81
|
interactedRef.current = true;
|
|
75
82
|
const rect = viewport.getBoundingClientRect();
|
|
76
83
|
const focal = { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
77
84
|
setView(
|
|
78
|
-
(current) => applyZoom(current, current.scale * (event.deltaY > 0 ? 0.9 : 1.1), focal)
|
|
85
|
+
(current) => applyZoom(current, current.scale * (event.deltaY > 0 ? 0.9 : 1.1), focal, minScaleRef.current)
|
|
79
86
|
);
|
|
80
87
|
};
|
|
81
88
|
viewport.addEventListener("wheel", onWheel, { passive: false });
|
|
@@ -88,7 +95,7 @@ function usePanZoomCanvas(options) {
|
|
|
88
95
|
}, []);
|
|
89
96
|
const zoomAt = useCallback((nextScale, focal) => {
|
|
90
97
|
interactedRef.current = true;
|
|
91
|
-
setView((current) => applyZoom(current, nextScale, focal));
|
|
98
|
+
setView((current) => applyZoom(current, nextScale, focal, minScaleRef.current));
|
|
92
99
|
}, []);
|
|
93
100
|
const localPoint = (event) => {
|
|
94
101
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
@@ -165,7 +172,7 @@ function usePanZoomCanvas(options) {
|
|
|
165
172
|
const pinch = pinchRef.current;
|
|
166
173
|
if (pinch && pointersRef.current.size >= 2) {
|
|
167
174
|
const { distance, mid } = pinchGeometry();
|
|
168
|
-
setView(applyPinch(pinch.start, pinch.distance, pinch.mid, distance, mid));
|
|
175
|
+
setView(applyPinch(pinch.start, pinch.distance, pinch.mid, distance, mid, minScaleRef.current));
|
|
169
176
|
return;
|
|
170
177
|
}
|
|
171
178
|
const pending = pendingRef.current;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ImageLightbox } from './chunk-
|
|
2
|
-
import { useSduiSandbox, useSduiAdapter, hostRawFetchOf, defaultAdapter, useSduiAssetResolver } from './chunk-
|
|
3
|
-
import { Spinner, Icon, IconButton } from './chunk-
|
|
1
|
+
import { ImageLightbox } from './chunk-L6ODTHTX.js';
|
|
2
|
+
import { useSduiSandbox, useSduiAdapter, hostRawFetchOf, defaultAdapter, useSduiAssetResolver } from './chunk-ZBX2CAOO.js';
|
|
3
|
+
import { Spinner, Icon, IconButton } from './chunk-OWM7E55U.js';
|
|
4
4
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
5
5
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { usePanZoomCanvas, MIN_ZOOM, MAX_ZOOM } from './chunk-
|
|
2
|
-
import { IconButton, Badge } from './chunk-
|
|
1
|
+
import { usePanZoomCanvas, MIN_ZOOM, MAX_ZOOM } from './chunk-XDR6HC4U.js';
|
|
2
|
+
import { IconButton, Badge } from './chunk-OWM7E55U.js';
|
|
3
3
|
import { boxed } from './chunk-3JTBOABA.js';
|
|
4
4
|
import { useState, useMemo, useCallback, useEffect } from 'react';
|
|
5
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEV } from './chunk-
|
|
2
|
-
import { warnOnce } from './chunk-
|
|
1
|
+
import { DEV } from './chunk-TAVKGYH5.js';
|
|
2
|
+
import { warnOnce } from './chunk-OWM7E55U.js';
|
|
3
3
|
import { createContext, useContext } from 'react';
|
|
4
4
|
|
|
5
5
|
function isSafeNavigationTarget(to) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default, { CSSProperties, ReactNode, ComponentType } from 'react';
|
|
3
|
-
import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types-
|
|
4
|
-
export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types-
|
|
3
|
+
import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types-CMikpoN5.js';
|
|
4
|
+
export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types-CMikpoN5.js';
|
|
5
5
|
import { S as SduiBoxProps, a as SduiContainerLayoutProps, b as SduiColumnsScale, c as SduiGapScale, d as SduiWeightScale, e as SduiTextAlignScale } from './layout-DmRikwZb.js';
|
|
6
6
|
export { C as CHILD_LAYOUT_PROPS, L as LAYOUT_CSS, f as SduiAlignScale, g as SduiChildLayoutProps, h as SduiSizeScale, i as SduiSpanScale, j as childLayoutFrom, k as columnsClass, l as containerLayoutStyle, m as joinClass, n as mergeStyle, t as typographyStyle } from './layout-DmRikwZb.js';
|
|
7
|
-
import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-
|
|
8
|
-
export { b as DatePicker, c as DateRangePicker, d as DateRangeValue, e as TimePicker } from './DatePicker-
|
|
7
|
+
import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-BOOKdd5x.js';
|
|
8
|
+
export { b as DatePicker, c as DateRangePicker, d as DateRangeValue, e as TimePicker } from './DatePicker-BOOKdd5x.js';
|
|
9
|
+
import './calendar-nav-BSGsgJc4.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 호스트 앱 연결점 — ERP에서는 라우터·erpFetch·SSE가 하던 일을
|
|
@@ -461,9 +462,14 @@ interface BadgeProps extends React__default.HTMLAttributes<HTMLSpanElement> {
|
|
|
461
462
|
/** 선행 5px 점 — 라이브/진행 상태 */
|
|
462
463
|
dot?: boolean;
|
|
463
464
|
size?: 'md' | 'lg';
|
|
465
|
+
/**
|
|
466
|
+
* 긴 문구를 칸 폭 안에서 여러 줄로 감싼다(`wp-badge--wrap`, 1.6.1). 기본은 한 줄 고정 높이다.
|
|
467
|
+
* 예전에는 스펙이 style 로 height:auto·white-space:normal 등을 박아 흉내 냈다.
|
|
468
|
+
*/
|
|
469
|
+
wrap?: boolean;
|
|
464
470
|
children?: React__default.ReactNode;
|
|
465
471
|
}
|
|
466
|
-
declare function Badge({ tone, dot, size, children, className, ...rest }: BadgeProps): React__default.JSX.Element;
|
|
472
|
+
declare function Badge({ tone, dot, size, wrap, children, className, ...rest }: BadgeProps): React__default.JSX.Element;
|
|
467
473
|
interface TagProps extends React__default.HTMLAttributes<HTMLSpanElement> {
|
|
468
474
|
/** 선행 점의 CSS 색상 */
|
|
469
475
|
color?: string;
|
|
@@ -768,6 +774,8 @@ interface ResultTableColumn<T> {
|
|
|
768
774
|
strong?: boolean;
|
|
769
775
|
/** CSS width — "180px", "22%" */
|
|
770
776
|
width?: string;
|
|
777
|
+
/** 한 줄로 둔다 — `wp-table__nowrap`(white-space:nowrap). 날짜·번호처럼 갈라지면 읽기 어려운 짧은 값. */
|
|
778
|
+
nowrap?: boolean;
|
|
771
779
|
/**
|
|
772
780
|
* 칸 이름(문자열) — 각 `<td data-label>` 로 나간다. 좁은 화면에서 표를 행 카드로 쌓을 때
|
|
773
781
|
* 칸마다 "무슨 값인지"를 CSS(`attr(data-label)`)가 붙인다. 생략하면 `header` 가 문자열일
|
|
@@ -779,6 +787,12 @@ interface ResultTableColumn<T> {
|
|
|
779
787
|
* `title`: 카드 머리(라벨 없이 굵게), `hide`: 모바일 카드에서 숨김.
|
|
780
788
|
*/
|
|
781
789
|
mobile?: 'title' | 'hide';
|
|
790
|
+
/**
|
|
791
|
+
* 태블릿(768–1023.98px) 표에서의 역할 — `data-tablet` 속성으로 th·td 둘 다에 나간다(모양은 소비자 CSS).
|
|
792
|
+
* `hide`: 태블릿 폭의 표에서 이 열을 뺀다. 모바일 행 카드(`mobile`)와는 따로다 — 태블릿에서 빼고 싶은 긴
|
|
793
|
+
* 목록 열이 폰 카드에서는 값이 있어야 하는 경우가 있다(예전에는 `mobile:'hide'` 를 태블릿에도 빌려 썼다).
|
|
794
|
+
*/
|
|
795
|
+
tablet?: 'hide';
|
|
782
796
|
render?: (row: T, index: number) => React__default.ReactNode;
|
|
783
797
|
}
|
|
784
798
|
type SortDir = 'asc' | 'desc';
|
|
@@ -793,7 +807,16 @@ interface ResultTableProps<T extends {
|
|
|
793
807
|
};
|
|
794
808
|
onSort?: (key: string) => void;
|
|
795
809
|
onRowClick?: (row: T) => void;
|
|
810
|
+
/** 체크박스로 고른 행 — `aria-selected="true"`(선택 바탕)만 붙는다. SearchResults 의 일괄 선택이 여기로 온다. */
|
|
796
811
|
selectedIds?: string[];
|
|
812
|
+
/**
|
|
813
|
+
* 표시 전용 강조 행(1.6.1) — `aria-current="true"` + `wp-row--selected` 클래스. 체크박스 선택과 별개다:
|
|
814
|
+
* 옆 창에 열어 둔 행처럼 "지금 보고 있는 것"을 가리킬 뿐, 일괄 액션의 대상이 되지 않는다.
|
|
815
|
+
* 그래서 체크 선택의 `aria-selected` 를 빌리지 않는다 — 같은 속성이면 스크린리더가 둘을 "선택됨"으로
|
|
816
|
+
* 똑같이 읽는다. 바탕·막대는 클래스가 칠한다(aria-selected 규칙에 기대지 않는다).
|
|
817
|
+
* SearchResults 의 `selectedIds` 가 이리로 온다. id 비교는 문자열로 한다(행 id 가 숫자인 JSON 도 맞게).
|
|
818
|
+
*/
|
|
819
|
+
pickedIds?: readonly string[];
|
|
797
820
|
/** rows가 비었을 때 표 대신 렌더 */
|
|
798
821
|
empty?: React__default.ReactNode;
|
|
799
822
|
/** true면 스크롤 창 안에서 보이는 행만 렌더한다 */
|
|
@@ -811,7 +834,7 @@ interface ResultTableProps<T extends {
|
|
|
811
834
|
}
|
|
812
835
|
declare function ResultTable<T extends {
|
|
813
836
|
id: string;
|
|
814
|
-
}>({ columns, rows, sort, onSort, onRowClick, selectedIds, empty, virtual, height, rowHeight, stackable, }: ResultTableProps<T>): React__default.JSX.Element;
|
|
837
|
+
}>({ columns, rows, sort, onSort, onRowClick, selectedIds, pickedIds, empty, virtual, height, rowHeight, stackable, }: ResultTableProps<T>): React__default.JSX.Element;
|
|
815
838
|
interface ResultEmptyStateProps {
|
|
816
839
|
/** 목록 이름 — 기본 문구에 들어간다("대여 이력이 없습니다") */
|
|
817
840
|
title: string;
|
|
@@ -1139,6 +1162,10 @@ interface SearchColumn<T> {
|
|
|
1139
1162
|
* 아무 열도 `title` 이 아니면 `primaryKey` 열, 그다음 첫 `strong` 열이 머리가 된다.
|
|
1140
1163
|
*/
|
|
1141
1164
|
mobile?: 'title' | 'hide';
|
|
1165
|
+
/** 태블릿(768–1023.98px) 표에서 이 열을 뺀다(`hide`) — 모바일 카드의 `mobile` 과 따로 정한다. */
|
|
1166
|
+
tablet?: 'hide';
|
|
1167
|
+
/** 표 칸을 한 줄로 둔다(`wp-table__nowrap`). */
|
|
1168
|
+
nowrap?: boolean;
|
|
1142
1169
|
accessor?: (item: T) => string | number | Date | null | undefined;
|
|
1143
1170
|
render?: (item: T) => React__default.ReactNode;
|
|
1144
1171
|
}
|
|
@@ -1277,6 +1304,17 @@ interface SearchResultsProps<T> {
|
|
|
1277
1304
|
* (asset-18). endpoint 목록(RemoteSearchResults)은 이 값을 켠다.
|
|
1278
1305
|
*/
|
|
1279
1306
|
serverFiltered?: boolean;
|
|
1307
|
+
/**
|
|
1308
|
+
* 표시 전용 강조(1.6.1) — 이 id 의 행(목록 보기)·카드(카드 보기)를 강조한다. 체크박스 선택(`actions`)과
|
|
1309
|
+
* **별개**다: 일괄 액션의 대상이 되지 않고, 선택 바도 세우지 않는다. 옆 창·상세에 열어 둔 행을 목록에서
|
|
1310
|
+
* 가리키는 자리다 — 스펙은 `"selectedIds": [{"$state":"rt.$picked.id"}]` 처럼 준다.
|
|
1311
|
+
*
|
|
1312
|
+
* 행은 `aria-current="true"` + `wp-row--selected`, 카드는 `wp-card--selected` + `is-selected` +
|
|
1313
|
+
* `aria-current="true"` 다. 체크 선택의 `aria-selected` 는 쓰지 않는다 — 스크린리더가 강조와 체크 선택을
|
|
1314
|
+
* 똑같이 "선택됨"으로 읽게 되고, 카드(버튼·일반 상자 역할)는 aria-selected 를 가질 수도 없다. 비교는
|
|
1315
|
+
* 문자열로 하고, 바인딩이 아직 비어 `null`·`undefined` 인 원소는 버린다.
|
|
1316
|
+
*/
|
|
1317
|
+
selectedIds?: string[];
|
|
1280
1318
|
}
|
|
1281
1319
|
/**
|
|
1282
1320
|
* 스펙이 준 페이지 크기 목록을 다듬는다 — 양의 정수만, 중복 제거, 오름차순.
|
|
@@ -1285,7 +1323,7 @@ interface SearchResultsProps<T> {
|
|
|
1285
1323
|
declare function normalizePageSizes(sizes: number[] | undefined): number[] | undefined;
|
|
1286
1324
|
declare function SearchResults<T extends {
|
|
1287
1325
|
id: string;
|
|
1288
|
-
}>({ item, columns, gridConfig, leftFilters, rightFilters, tabs, summary, initialView, views, pageSizes, className, style, searchParams, onParamsChange, actions, disableGrid, disableList, onRowClick, title, headerActions, isLoading, hideHeader, advancedSearchFields: rawAdvancedSearchFields, searchPlaceholder, virtual, serverUnsortable, primaryKey, emptyTitle, emptyText, serverFiltered, }: SearchResultsProps<T>): React__default.JSX.Element;
|
|
1326
|
+
}>({ item, columns, gridConfig, leftFilters, rightFilters, tabs, summary, initialView, views, pageSizes, className, style, searchParams, onParamsChange, actions, disableGrid, disableList, onRowClick, title, headerActions, isLoading, hideHeader, advancedSearchFields: rawAdvancedSearchFields, searchPlaceholder, virtual, serverUnsortable, primaryKey, emptyTitle, emptyText, serverFiltered, selectedIds, }: SearchResultsProps<T>): React__default.JSX.Element;
|
|
1289
1327
|
|
|
1290
1328
|
/**
|
|
1291
1329
|
* 셀 표현 어휘 — 목록 컬럼의 셀과 카드 행의 값이 **같은 규칙**을 쓴다.
|
|
@@ -1473,6 +1511,13 @@ interface SduiSearchColumn {
|
|
|
1473
1511
|
* `hide`: 모바일에서 숨김(식별자·보조 열). 생략하면 보통 칸(라벨 + 값).
|
|
1474
1512
|
*/
|
|
1475
1513
|
mobile?: 'title' | 'hide';
|
|
1514
|
+
/**
|
|
1515
|
+
* 태블릿(768–1023.98px) 표에서의 역할 — `hide`: 이 폭의 표에서 열을 뺀다. 모바일 카드(`mobile`)와 따로다:
|
|
1516
|
+
* 태블릿 표에서는 넘치는 긴 목록 열이라도 폰 카드에서는 보여 줄 수 있다. 생략하면 태블릿에서도 보인다.
|
|
1517
|
+
*/
|
|
1518
|
+
tablet?: 'hide';
|
|
1519
|
+
/** 표 칸을 한 줄로 둔다(white-space:nowrap) — 날짜·번호처럼 두 줄로 갈라지면 읽기 어려운 짧은 값. */
|
|
1520
|
+
nowrap?: boolean;
|
|
1476
1521
|
/** 셀 표현. 생략하면 row[key]를 그대로 출력한다 — 어휘는 `cells.tsx` 참고 */
|
|
1477
1522
|
cell?: SduiCell;
|
|
1478
1523
|
}
|
|
@@ -1577,6 +1622,11 @@ interface SduiSearchCommonProps {
|
|
|
1577
1622
|
* 조건이 없으면 빈 문자열. 생략하면 아무것도 적지 않는다.
|
|
1578
1623
|
*/
|
|
1579
1624
|
queryStateKey?: string;
|
|
1625
|
+
/**
|
|
1626
|
+
* 표시 전용 강조 — 이 id 의 행·카드를 강조한다(체크박스 선택과 별개, 일괄 액션 대상 아님).
|
|
1627
|
+
* 옆 창에 열어 둔 행을 가리키는 자리: `"selectedIds": [{"$state":"rt.$picked.id"}]`. 계약은 SearchResultsProps.selectedIds.
|
|
1628
|
+
*/
|
|
1629
|
+
selectedIds?: string[];
|
|
1580
1630
|
}
|
|
1581
1631
|
interface SduiSearchResultsProps extends SduiSearchCommonProps {
|
|
1582
1632
|
data: SearchRow[];
|