@wipco/sdui 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -1
- package/dist/meta.d.ts +1 -1
- package/dist/meta.js +20 -0
- package/dist/rich.d.ts +14 -1
- package/dist/rich.js +93 -4
- package/dist/{types-C7y9CpgF.d.ts → types-COjGKgmd.d.ts} +7 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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-COjGKgmd.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-COjGKgmd.js';
|
|
5
5
|
import { S as SduiBoxProps, a as SduiContainerLayoutProps, b as SduiColumnsScale, c as SduiGapScale, d as SduiWeightScale, e as SduiTextAlignScale } from './layout-C3nRXMwb.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-C3nRXMwb.js';
|
|
7
7
|
import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-C_TT_SOw.js';
|
package/dist/index.js
CHANGED
|
@@ -2181,6 +2181,9 @@ function nearestArgsFrame(scope) {
|
|
|
2181
2181
|
}
|
|
2182
2182
|
return void 0;
|
|
2183
2183
|
}
|
|
2184
|
+
function hasExplicitPageHead(body) {
|
|
2185
|
+
return Array.isArray(body) && body.some((child) => isPlainObject(child) && child.component === "PageHead");
|
|
2186
|
+
}
|
|
2184
2187
|
function isStateRef(v) {
|
|
2185
2188
|
return isPlainObject(v) && typeof v.$state === "string";
|
|
2186
2189
|
}
|
|
@@ -3035,7 +3038,7 @@ function SduiRenderer({
|
|
|
3035
3038
|
// 컴포넌트(목록 조회 등)도 호스트가 건 잠금 안에서 움직이게 하기 위해서다(adapter.ts 주석).
|
|
3036
3039
|
/* @__PURE__ */ jsx(SduiAdapterContext.Provider, { value: host, children: /* @__PURE__ */ jsx(SduiDispatchContext.Provider, { value: dispatch, children: /* @__PURE__ */ jsx(SduiRuntimeContext.Provider, { value: runtime, children: /* @__PURE__ */ jsx(SduiPermissionProvider, { can, children: /* @__PURE__ */ jsxs("div", { className: "sdui-root", children: [
|
|
3037
3040
|
/* @__PURE__ */ jsx(HoistedStyle, { id: "wp-sdui-layout", css: LAYOUT_CSS }),
|
|
3038
|
-
page.title || page.subtitle ? /* @__PURE__ */ jsx("div", { className: "wp-page-head", children: /* @__PURE__ */ jsxs("div", { className: "wp-page-head__text", children: [
|
|
3041
|
+
!hasExplicitPageHead(page.body) && (page.title || page.subtitle) ? /* @__PURE__ */ jsx("div", { className: "wp-page-head", children: /* @__PURE__ */ jsxs("div", { className: "wp-page-head__text", children: [
|
|
3039
3042
|
page.title ? /* @__PURE__ */ jsx("h1", { className: "wp-page-head__title", children: page.title }) : null,
|
|
3040
3043
|
page.subtitle ? /* @__PURE__ */ jsx("div", { className: "wp-page-head__sub", children: page.subtitle }) : null
|
|
3041
3044
|
] }) }) : null,
|
package/dist/meta.d.ts
CHANGED
package/dist/meta.js
CHANGED
|
@@ -3273,6 +3273,26 @@ var ChartMeta = {
|
|
|
3273
3273
|
description: "\uB2E8\uC77C \uC2DC\uB9AC\uC988 \uCE74\uB974\uD14C\uC2DC\uC548 \uCC28\uD2B8\uB294 \uCF1C\uB3C4 \uC0DD\uB7B5\uB41C\uB2E4.",
|
|
3274
3274
|
group: "appearance"
|
|
3275
3275
|
},
|
|
3276
|
+
{
|
|
3277
|
+
name: "legendPlacement",
|
|
3278
|
+
kind: "enum",
|
|
3279
|
+
label: "\uBC94\uB840 \uC704\uCE58",
|
|
3280
|
+
default: "bottom",
|
|
3281
|
+
description: 'pie/donut \uC804\uC6A9. "\uC6B0\uCE21 \uC218\uCE58 \uD45C"\uB294 \uC810 \uBC94\uB840 \uB300\uC2E0 \uC804\uCCB4 \uD589 + \uC870\uAC01\uBCC4 \uAC12\xB7\uC810\uC720\uC728\uC744 \uCC28\uD2B8 \uC624\uB978\uCABD\uC5D0 \uC801\uB294\uB2E4.',
|
|
3282
|
+
options: [
|
|
3283
|
+
{ value: "bottom", label: "\uC544\uB798 \uC810 \uBC94\uB840" },
|
|
3284
|
+
{ value: "right", label: "\uC6B0\uCE21 \uC218\uCE58 \uD45C" }
|
|
3285
|
+
],
|
|
3286
|
+
group: "appearance"
|
|
3287
|
+
},
|
|
3288
|
+
{
|
|
3289
|
+
name: "legendTotal",
|
|
3290
|
+
kind: "number",
|
|
3291
|
+
label: "\uC804\uCCB4 \uAC12 \uC7AC\uC815\uC758",
|
|
3292
|
+
bindable: true,
|
|
3293
|
+
description: '\uC6B0\uCE21 \uC218\uCE58 \uD45C\uC758 "\uC804\uCCB4" \uD589 \uAC12\uC774\uC790 \uC810\uC720\uC728 \uBD84\uBAA8. \uC0DD\uB7B5\uD558\uBA74 \uC870\uAC01 \uAC12\uC758 \uD569 \u2014 \uC870\uAC01\uC774 \uACB9\uCCD0 \uC138\uC5B4\uC9C0\uB294 \uC9D1\uACC4\uB294 \uC5EC\uAE30\uC5D0 \uC2E4\uC81C \uBAA8\uC218\uB97C \uBC14\uC778\uB529\uD55C\uB2E4.',
|
|
3294
|
+
group: "appearance"
|
|
3295
|
+
},
|
|
3276
3296
|
{
|
|
3277
3297
|
name: "donutCenter",
|
|
3278
3298
|
kind: "object",
|
package/dist/rich.d.ts
CHANGED
|
@@ -39,6 +39,19 @@ interface ChartProps {
|
|
|
39
39
|
valueFormat?: ChartValueFormat;
|
|
40
40
|
/** 범례 표시 여부. 기본 true (단일 시리즈 카르테시안 차트는 생략). */
|
|
41
41
|
legend?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* pie/donut 전용: 범례 위치. `'right'`는 아래쪽 점 범례 대신 차트 오른쪽에
|
|
44
|
+
* 전체 행 + 조각별 값·점유율 표를 붙인다({@link SliceLegendTable}).
|
|
45
|
+
* 카르테시안 차트에서는 무시된다. 기본 'bottom'.
|
|
46
|
+
*/
|
|
47
|
+
legendPlacement?: 'bottom' | 'right';
|
|
48
|
+
/**
|
|
49
|
+
* 우측 수치 표의 "전체" 값(점유율 분모) 재정의. 생략하면 조각 값의 합.
|
|
50
|
+
*
|
|
51
|
+
* 조각이 겹치는 집계(수리 중인 장비가 대여 상태 어느 한쪽에도 이미 세어진 경우 등)는
|
|
52
|
+
* 합이 실제 모수보다 커진다 — 화면의 다른 총계와 어긋나 보이지 않게 모수를 직접 준다.
|
|
53
|
+
*/
|
|
54
|
+
legendTotal?: number;
|
|
42
55
|
/** donut 중앙 오버레이 텍스트. */
|
|
43
56
|
donutCenter?: {
|
|
44
57
|
label?: string;
|
|
@@ -47,7 +60,7 @@ interface ChartProps {
|
|
|
47
60
|
/** 데이터가 없을 때 보여줄 문구. */
|
|
48
61
|
emptyText?: string;
|
|
49
62
|
}
|
|
50
|
-
declare function Chart({ type, data, xKey, series, height, valueFormat, legend, donutCenter, emptyText, }: ChartProps): React__default.JSX.Element;
|
|
63
|
+
declare function Chart({ type, data, xKey, series, height, valueFormat, legend, legendPlacement, legendTotal, donutCenter, emptyText, }: ChartProps): React__default.JSX.Element;
|
|
51
64
|
|
|
52
65
|
/**
|
|
53
66
|
* MapPreview — OpenLayers 기반 위치 미리보기 지도 (ERP `app/components/widgets/MapPreview.tsx` 이식).
|
package/dist/rich.js
CHANGED
|
@@ -149,6 +149,65 @@ function HtmlLegend({ items }) {
|
|
|
149
149
|
}
|
|
150
150
|
);
|
|
151
151
|
}
|
|
152
|
+
function SliceLegendTable({
|
|
153
|
+
rows,
|
|
154
|
+
format,
|
|
155
|
+
total
|
|
156
|
+
}) {
|
|
157
|
+
const denom = total ?? rows.reduce((sum, r) => sum + r.value, 0);
|
|
158
|
+
const share = (v) => denom > 0 ? `${(v / denom * 100).toLocaleString("ko-KR", { minimumFractionDigits: 1, maximumFractionDigits: 1 })}%` : "0.0%";
|
|
159
|
+
const valueStyle = {
|
|
160
|
+
fontSize: 13,
|
|
161
|
+
fontWeight: 600,
|
|
162
|
+
color: "var(--wp-text-strong)",
|
|
163
|
+
fontVariantNumeric: "tabular-nums",
|
|
164
|
+
whiteSpace: "nowrap"
|
|
165
|
+
};
|
|
166
|
+
return /* @__PURE__ */ jsxs(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
style: {
|
|
170
|
+
flex: "none",
|
|
171
|
+
minWidth: 148,
|
|
172
|
+
display: "flex",
|
|
173
|
+
flexDirection: "column",
|
|
174
|
+
justifyContent: "center",
|
|
175
|
+
gap: "var(--wp-space-2)"
|
|
176
|
+
},
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsxs(
|
|
179
|
+
"div",
|
|
180
|
+
{
|
|
181
|
+
style: {
|
|
182
|
+
display: "flex",
|
|
183
|
+
alignItems: "baseline",
|
|
184
|
+
justifyContent: "space-between",
|
|
185
|
+
gap: "var(--wp-space-4)",
|
|
186
|
+
paddingBottom: "var(--wp-space-2)",
|
|
187
|
+
borderBottom: "1px solid var(--wp-divider)"
|
|
188
|
+
},
|
|
189
|
+
children: [
|
|
190
|
+
/* @__PURE__ */ jsx("span", { className: "wp-caption", children: "\uC804\uCCB4" }),
|
|
191
|
+
/* @__PURE__ */ jsx("span", { style: valueStyle, children: `${format(denom)} (${share(denom)})` })
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
rows.map((row, i) => /* @__PURE__ */ jsxs(
|
|
196
|
+
"div",
|
|
197
|
+
{
|
|
198
|
+
style: { display: "flex", alignItems: "center", gap: "var(--wp-space-2)" },
|
|
199
|
+
children: [
|
|
200
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, style: dotStyle(row.color) }),
|
|
201
|
+
/* @__PURE__ */ jsx("span", { className: "wp-caption", style: { flex: 1, minWidth: 0, overflowWrap: "anywhere" }, children: row.label }),
|
|
202
|
+
/* @__PURE__ */ jsx("span", { style: valueStyle, children: `${format(row.value)} (${share(row.value)})` })
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
`${row.label}-${i}`
|
|
206
|
+
))
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
152
211
|
var axisTick = { fill: "var(--wp-text-muted)", fontSize: 12 };
|
|
153
212
|
function Chart({
|
|
154
213
|
type,
|
|
@@ -158,6 +217,8 @@ function Chart({
|
|
|
158
217
|
height = 300,
|
|
159
218
|
valueFormat = "number",
|
|
160
219
|
legend = true,
|
|
220
|
+
legendPlacement = "bottom",
|
|
221
|
+
legendTotal,
|
|
161
222
|
donutCenter,
|
|
162
223
|
emptyText
|
|
163
224
|
}) {
|
|
@@ -218,9 +279,12 @@ function Chart({
|
|
|
218
279
|
label: String(row[nameKey] ?? `\uD56D\uBAA9 ${i + 1}`),
|
|
219
280
|
color: sliceColor(row, i)
|
|
220
281
|
}));
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
282
|
+
const sideLegend = legend && legendPlacement === "right";
|
|
283
|
+
const chartArea = /* @__PURE__ */ jsxs(
|
|
284
|
+
"div",
|
|
285
|
+
{
|
|
286
|
+
style: sideLegend ? { position: "relative", flex: "1 1 0%", minWidth: 0, height } : { position: "relative", width: "100%", height },
|
|
287
|
+
children: [
|
|
224
288
|
/* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { children: [
|
|
225
289
|
/* @__PURE__ */ jsx(Tooltip, { content: tooltipContent }),
|
|
226
290
|
/* @__PURE__ */ jsx(
|
|
@@ -259,7 +323,32 @@ function Chart({
|
|
|
259
323
|
]
|
|
260
324
|
}
|
|
261
325
|
)
|
|
262
|
-
]
|
|
326
|
+
]
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
if (sideLegend) {
|
|
330
|
+
const sliceValue = (row) => {
|
|
331
|
+
const n = Number(row[valueKey]);
|
|
332
|
+
return Number.isFinite(n) ? n : 0;
|
|
333
|
+
};
|
|
334
|
+
const denomOverride = Number(legendTotal);
|
|
335
|
+
return shell(
|
|
336
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "var(--wp-space-6)" }, children: [
|
|
337
|
+
chartArea,
|
|
338
|
+
/* @__PURE__ */ jsx(
|
|
339
|
+
SliceLegendTable,
|
|
340
|
+
{
|
|
341
|
+
rows: rows.map((row, i) => ({ ...legendItems2[i], value: sliceValue(row) })),
|
|
342
|
+
format,
|
|
343
|
+
total: legendTotal !== void 0 && Number.isFinite(denomOverride) ? denomOverride : void 0
|
|
344
|
+
}
|
|
345
|
+
)
|
|
346
|
+
] })
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
return shell(
|
|
350
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
351
|
+
chartArea,
|
|
263
352
|
legend && /* @__PURE__ */ jsx(HtmlLegend, { items: legendItems2 })
|
|
264
353
|
] })
|
|
265
354
|
);
|
|
@@ -397,7 +397,13 @@ interface SduiPageQuery {
|
|
|
397
397
|
}
|
|
398
398
|
interface SduiPage {
|
|
399
399
|
version: 1;
|
|
400
|
-
/**
|
|
400
|
+
/**
|
|
401
|
+
* 문서 <title> 및 페이지 헤더에 쓰인다.
|
|
402
|
+
*
|
|
403
|
+
* body **최상위**에 `PageHead` 노드가 있으면 자동 페이지 헤더는 접히고 그쪽이
|
|
404
|
+
* 시각 헤더가 된다 — 제목 줄 우측에 액션(필터·버튼)을 놓으려는 스펙이
|
|
405
|
+
* title(문서 제목)을 포기하지 않아도 되는 자리다.
|
|
406
|
+
*/
|
|
401
407
|
title?: string;
|
|
402
408
|
subtitle?: string;
|
|
403
409
|
/** 실시간 채널 구독 — 어댑터의 subscribe로 위임(이벤트 수신 시 조용한 재조회) */
|