@wipco/sdui 1.5.0 → 1.6.1
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-C_TT_SOw.d.ts → DatePicker-DX9juElE.d.ts} +10 -1
- package/dist/{chunk-7P7N43JV.js → chunk-34BABTH4.js} +2 -2
- package/dist/{chunk-DMLDKW7K.js → chunk-37BNG4DT.js} +1 -1
- package/dist/{chunk-5WW4MBRO.js → chunk-3JTBOABA.js} +6 -2
- package/dist/{chunk-HBIIEYKW.js → chunk-3PCR73OC.js} +4 -4
- package/dist/{chunk-VY7MVBSE.js → chunk-3PT5OBOU.js} +2 -2
- package/dist/{chunk-YVTV4ZV6.js → chunk-4YPPL7JK.js} +1 -1
- package/dist/{chunk-E6ISNQK3.js → chunk-6YBSBC77.js} +31 -8
- package/dist/{chunk-YWUDBLO6.js → chunk-7G6J6QFC.js} +2 -2
- package/dist/{chunk-UV6HHFEW.js → chunk-A57GKV5F.js} +129 -68
- package/dist/{chunk-I45EUZC6.js → chunk-AJ3KDBEE.js} +4 -2
- package/dist/chunk-BITS7UJY.js +333 -0
- package/dist/{chunk-DOL57OOP.js → chunk-BV37UCDF.js} +3 -3
- package/dist/chunk-CSZCWBOE.js +256 -0
- package/dist/{chunk-XGFDY43I.js → chunk-CUFGH3LB.js} +88 -18
- package/dist/{chunk-A6LAIGUS.js → chunk-EGFDELSF.js} +7 -4
- package/dist/{chunk-JIV4YHCZ.js → chunk-EJIWOD7W.js} +1 -1
- package/dist/{chunk-CXW6KT6X.js → chunk-ESAFQXEU.js} +3 -3
- package/dist/{chunk-N5RKM6IC.js → chunk-EUSC5NMZ.js} +4 -4
- package/dist/{chunk-RWSH2MBU.js → chunk-FP32LNFK.js} +73 -19
- package/dist/{chunk-44TDRCKR.js → chunk-GKYUDTMI.js} +5 -5
- package/dist/chunk-GSM664TX.js +38 -0
- package/dist/{chunk-I5SD7XRA.js → chunk-GSXD52XG.js} +3 -3
- package/dist/{chunk-O4IISNE7.js → chunk-IB2ZPUTF.js} +51 -12
- package/dist/{chunk-YOZN35HD.js → chunk-IIRVHSNK.js} +3 -3
- package/dist/{chunk-FNMS7OB7.js → chunk-J7BZF4T4.js} +5 -5
- package/dist/{chunk-KO6OEY3G.js → chunk-JHFA5RDN.js} +3 -13
- package/dist/{chunk-DKVSM5HX.js → chunk-KDKRFWIF.js} +6 -6
- package/dist/chunk-KO3EUNWB.js +380 -0
- package/dist/{chunk-JYAR7D5U.js → chunk-NLSR3JYU.js} +2 -2
- package/dist/{chunk-ZORQPB6B.js → chunk-O4EMQWCV.js} +325 -360
- package/dist/{chunk-2HLXCKK7.js → chunk-OCYJ2ZOV.js} +2 -2
- package/dist/{chunk-OQ52XMGG.js → chunk-OKNF2SBB.js} +4 -4
- package/dist/{chunk-GNA6SX2H.js → chunk-OQ7A3SFM.js} +2 -2
- package/dist/{chunk-A5XQOEVH.js → chunk-PCFH74RD.js} +4 -4
- package/dist/{chunk-BEM2YS7U.js → chunk-SGGIWPP6.js} +3 -3
- package/dist/{chunk-NIJUVTEW.js → chunk-TB7G5DXQ.js} +3 -3
- package/dist/{chunk-GZBY7I4Y.js → chunk-TWUKNUUQ.js} +66 -10
- package/dist/{chunk-WPSK2CB5.js → chunk-UC725BGW.js} +16 -5
- package/dist/{chunk-ZFNFPXPR.js → chunk-US3K6Q5T.js} +2 -2
- package/dist/{chunk-MPT7WJG2.js → chunk-USNPJEXH.js} +5 -5
- package/dist/{chunk-SAPBDJJQ.js → chunk-UZZLMPRW.js} +2 -2
- package/dist/{chunk-Q4SWUINA.js → chunk-VAXRTBJH.js} +1 -1
- package/dist/{chunk-RYBBPFI7.js → chunk-VQKX5PJ4.js} +4 -4
- package/dist/chunk-VR5MFUD2.js +106 -0
- package/dist/{chunk-JZXU22PE.js → chunk-VSNHDHGS.js} +208 -117
- package/dist/{chunk-2YP5N4VV.js → chunk-VZOQRQAR.js} +1 -1
- package/dist/{chunk-AXGF4M57.js → chunk-XAXROQKB.js} +1 -1
- package/dist/{chunk-IZ3JA2BR.js → chunk-XFKNU6QN.js} +3 -3
- package/dist/{chunk-GTGS2QRL.js → chunk-XUVWIRZJ.js} +3 -3
- package/dist/{chunk-RNOUXUBO.js → chunk-YYAGE733.js} +323 -59
- package/dist/index.d.ts +449 -91
- package/dist/index.js +1060 -138
- package/dist/{layout-C3nRXMwb.d.ts → layout-DmRikwZb.d.ts} +5 -4
- package/dist/meta.d.ts +1 -1
- package/dist/meta.js +351 -25
- package/dist/rich/ExcelUploadCard.d.ts +1 -1
- package/dist/rich/ExcelUploadCard.js +5 -4
- package/dist/rich.d.ts +22 -3
- package/dist/rich.js +304 -35
- package/dist/styles.css +119 -4
- package/dist/{types-COjGKgmd.d.ts → types-CMikpoN5.d.ts} +65 -2
- package/dist/widgets/ApprovalLineEditor.d.ts +1 -1
- package/dist/widgets/ApprovalLineEditor.js +9 -8
- package/dist/widgets/ApprovalOverridesEditor.d.ts +1 -1
- package/dist/widgets/ApprovalOverridesEditor.js +11 -10
- package/dist/widgets/ApprovalStepper.d.ts +29 -4
- package/dist/widgets/ApprovalStepper.js +3 -3
- package/dist/widgets/AutocompleteField.d.ts +1 -1
- package/dist/widgets/AutocompleteField.js +9 -8
- package/dist/widgets/ColumnBoard.d.ts +1 -1
- package/dist/widgets/ColumnBoard.js +3 -3
- package/dist/widgets/DiffView.d.ts +1 -1
- package/dist/widgets/DiffView.js +3 -3
- package/dist/widgets/Disclosure.d.ts +1 -1
- package/dist/widgets/Disclosure.js +3 -3
- package/dist/widgets/EventCalendar.d.ts +5 -1
- package/dist/widgets/EventCalendar.js +5 -3
- package/dist/widgets/FileDropzone.d.ts +1 -1
- package/dist/widgets/FileDropzone.js +9 -7
- package/dist/widgets/ImageLightbox.d.ts +1 -1
- package/dist/widgets/ImageLightbox.js +7 -5
- package/dist/widgets/InlineEdit.d.ts +1 -1
- package/dist/widgets/InlineEdit.js +3 -3
- package/dist/widgets/JsonField.d.ts +1 -1
- package/dist/widgets/JsonField.js +3 -3
- package/dist/widgets/LiveClock.d.ts +1 -1
- package/dist/widgets/LiveClock.js +2 -2
- package/dist/widgets/OptionSchemaEditor.d.ts +1 -1
- package/dist/widgets/OptionSchemaEditor.js +4 -4
- package/dist/widgets/OptionValueFields.d.ts +1 -1
- package/dist/widgets/OptionValueFields.js +4 -4
- package/dist/widgets/OrgChart.d.ts +1 -1
- package/dist/widgets/OrgChart.js +4 -4
- package/dist/widgets/OrgChartBoard.d.ts +15 -33
- package/dist/widgets/OrgChartBoard.js +10 -8
- package/dist/widgets/PeriodFilter.d.ts +1 -1
- package/dist/widgets/PeriodFilter.js +6 -5
- package/dist/widgets/PermissionMatrixEditor.d.ts +34 -2
- package/dist/widgets/PermissionMatrixEditor.js +6 -4
- package/dist/widgets/PositionSelect.d.ts +1 -1
- package/dist/widgets/PositionSelect.js +5 -4
- package/dist/widgets/PrintSheet.d.ts +15 -2
- package/dist/widgets/PrintSheet.js +3 -3
- package/dist/widgets/ProfileEditDiffCard.d.ts +1 -1
- package/dist/widgets/ProfileEditDiffCard.js +5 -4
- package/dist/widgets/QRDisplay.d.ts +1 -1
- package/dist/widgets/QRDisplay.js +5 -4
- package/dist/widgets/RankBoard.d.ts +1 -1
- package/dist/widgets/RankBoard.js +8 -6
- package/dist/widgets/RecordSheet.d.ts +1 -1
- package/dist/widgets/RecordSheet.js +2 -2
- package/dist/widgets/RoleMemberPicker.d.ts +1 -1
- package/dist/widgets/RoleMemberPicker.js +6 -5
- package/dist/widgets/SearchableMultiPicker.d.ts +1 -1
- package/dist/widgets/SearchableMultiPicker.js +7 -6
- package/dist/widgets/SecureScreen.d.ts +1 -1
- package/dist/widgets/SecureScreen.js +3 -3
- package/dist/widgets/StackedMeter.d.ts +1 -1
- package/dist/widgets/StackedMeter.js +2 -2
- package/dist/widgets/StagePeriodEditor.d.ts +1 -1
- package/dist/widgets/StagePeriodEditor.js +6 -5
- package/dist/widgets/Strip.d.ts +1 -1
- package/dist/widgets/Strip.js +2 -2
- package/dist/widgets/SummaryTable.d.ts +1 -1
- package/dist/widgets/SummaryTable.js +2 -2
- package/dist/widgets/TagInput.d.ts +1 -1
- package/dist/widgets/TagInput.js +3 -3
- package/dist/widgets/TagMultiSelect.d.ts +1 -1
- package/dist/widgets/TagMultiSelect.js +5 -4
- package/dist/widgets/Timeline.d.ts +1 -1
- package/dist/widgets/Timeline.js +4 -4
- package/dist/widgets/TreePicker.d.ts +1 -1
- package/dist/widgets/TreePicker.js +8 -7
- package/dist/widgets/TreeView.d.ts +17 -3
- package/dist/widgets/TreeView.js +7 -6
- package/dist/widgets/index.d.ts +3 -3
- package/dist/widgets/index.js +84 -83
- package/package.json +1 -1
- package/dist/chunk-LFEJLOFN.js +0 -352
- package/dist/chunk-MMIGOPO5.js +0 -111
- package/dist/chunk-TFGNKFL2.js +0 -39
- package/dist/chunk-XQPTSEJC.js +0 -135
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { loadOptionalModule } from '../chunk-
|
|
2
|
-
import { useSduiAdapter, useSduiSandbox, hostFetchOf, defaultAdapter, hostRawFetchOf } from '../chunk-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { loadOptionalModule } from '../chunk-4YPPL7JK.js';
|
|
2
|
+
import { useSduiAdapter, useSduiSandbox, hostFetchOf, defaultAdapter, hostRawFetchOf } from '../chunk-JHFA5RDN.js';
|
|
3
|
+
import '../chunk-GSM664TX.js';
|
|
4
|
+
import { Select, Input, Card, Button, Spinner, Icon, Alert, StatCard, Badge, Table, EmptyState } from '../chunk-YYAGE733.js';
|
|
5
|
+
import { boxed } from '../chunk-3JTBOABA.js';
|
|
5
6
|
import { useRef, useState, useMemo, useCallback } from 'react';
|
|
6
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
8
|
|
package/dist/rich.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React__default from 'react';
|
|
2
|
-
export { b as DatePicker, D as DatePickerProps, c as DateRangePicker, a as DateRangePickerProps, d as DateRangeValue, e as TimePicker, T as TimePickerProps } from './DatePicker-
|
|
3
|
-
import './layout-
|
|
2
|
+
export { b as DatePicker, D as DatePickerProps, c as DateRangePicker, a as DateRangePickerProps, d as DateRangeValue, e as TimePicker, T as TimePickerProps } from './DatePicker-DX9juElE.js';
|
|
3
|
+
import './layout-DmRikwZb.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Chart — 선언형 recharts 래퍼 (ERP `app/components/widgets/Chart.tsx` 이식).
|
|
@@ -26,6 +26,11 @@ interface ChartSeries {
|
|
|
26
26
|
kind?: 'bar' | 'line' | 'dashed-line';
|
|
27
27
|
/** 같은 문자열끼리 막대를 쌓는다 (stackId). */
|
|
28
28
|
stack?: string;
|
|
29
|
+
/**
|
|
30
|
+
* 카르테시안 전용: 어느 y축에 그릴지. 기본 'left'. 단위가 다른 시리즈(원 막대 + km 선)를
|
|
31
|
+
* 한 축에 그리면 작은 쪽이 0에 붙는다 — 'right'를 주면 오른쪽 보조축이 생긴다.
|
|
32
|
+
*/
|
|
33
|
+
axis?: 'left' | 'right';
|
|
29
34
|
}
|
|
30
35
|
interface ChartProps {
|
|
31
36
|
type: ChartType;
|
|
@@ -59,8 +64,22 @@ interface ChartProps {
|
|
|
59
64
|
};
|
|
60
65
|
/** 데이터가 없을 때 보여줄 문구. */
|
|
61
66
|
emptyText?: string;
|
|
67
|
+
/** 오른쪽 보조축(시리즈 axis:'right')의 값 포맷. 기본 'number'. 툴팁도 그 시리즈에는 이 포맷을 쓴다. */
|
|
68
|
+
rightValueFormat?: ChartValueFormat;
|
|
69
|
+
/**
|
|
70
|
+
* y축 눈금을 정수만 쓸지. 생략하면 축마다 자동 — 그 축에 그리는 값이 전부 정수(건수·인원)면
|
|
71
|
+
* 정수 눈금만 쓴다(0.3명·0.5건 같은 눈금이 나오지 않게). true/false는 두 축 모두에 강제한다.
|
|
72
|
+
*/
|
|
73
|
+
integer?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* x축 범주 라벨을 **모두** 보인다. 긴 라벨은 칸 폭에 맞춰 줄을 바꾸고(최대 3줄),
|
|
76
|
+
* 그래도 모자라면 45° 기울인다(첫 라벨들이 왼쪽 밖으로 잘리지 않게 왼쪽 여백을 늘린다).
|
|
77
|
+
* 칸이 그보다도 좁으면 겹치는 라벨만 건너뛴다(기본 동작).
|
|
78
|
+
* 끄면(기본) recharts가 겹치는 라벨을 건너뛴다 — 본부명처럼 긴 범주에서 라벨이 사라진다.
|
|
79
|
+
*/
|
|
80
|
+
xTickWrap?: boolean;
|
|
62
81
|
}
|
|
63
|
-
declare function Chart({ type, data, xKey, series, height, valueFormat, legend, legendPlacement, legendTotal, donutCenter, emptyText, }: ChartProps): React__default.JSX.Element;
|
|
82
|
+
declare function Chart({ type, data, xKey, series, height, valueFormat, legend, legendPlacement, legendTotal, donutCenter, emptyText, rightValueFormat, integer, xTickWrap, }: ChartProps): React__default.JSX.Element;
|
|
64
83
|
|
|
65
84
|
/**
|
|
66
85
|
* MapPreview — OpenLayers 기반 위치 미리보기 지도 (ERP `app/components/widgets/MapPreview.tsx` 이식).
|
package/dist/rich.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { useOptionalModule, DependencyPlaceholder } from './chunk-
|
|
2
|
-
export { DatePicker, DateRangePicker, TimePicker } from './chunk-
|
|
1
|
+
import { useOptionalModule, DependencyPlaceholder } from './chunk-4YPPL7JK.js';
|
|
2
|
+
export { DatePicker, DateRangePicker, TimePicker } from './chunk-FP32LNFK.js';
|
|
3
|
+
import './chunk-BITS7UJY.js';
|
|
3
4
|
import { HoistedStyle } from './chunk-RIZRM7OO.js';
|
|
4
|
-
import './chunk-
|
|
5
|
-
import
|
|
6
|
-
import { Spinner, EmptyState } from './chunk-
|
|
7
|
-
import './chunk-
|
|
5
|
+
import { useSduiAssetResolver } from './chunk-JHFA5RDN.js';
|
|
6
|
+
import './chunk-GSM664TX.js';
|
|
7
|
+
import { Spinner, EmptyState } from './chunk-YYAGE733.js';
|
|
8
|
+
import './chunk-3JTBOABA.js';
|
|
8
9
|
import { useRef, useCallback, useMemo, useState, useEffect, useLayoutEffect } from 'react';
|
|
9
10
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
11
|
|
|
@@ -47,24 +48,165 @@ function useSeriesPalette(ref) {
|
|
|
47
48
|
return palette;
|
|
48
49
|
}
|
|
49
50
|
var formatNumber = (v) => v.toLocaleString("ko-KR", { maximumFractionDigits: 1 });
|
|
51
|
+
var eokText = (abs) => {
|
|
52
|
+
const eok = abs / 1e8;
|
|
53
|
+
return `${eok.toLocaleString("ko-KR", { maximumFractionDigits: eok >= 100 ? 0 : 1 })}\uC5B5`;
|
|
54
|
+
};
|
|
55
|
+
var manText = (abs) => {
|
|
56
|
+
const man = abs / 1e4;
|
|
57
|
+
return `${man.toLocaleString("ko-KR", { maximumFractionDigits: man >= 100 ? 0 : 1 })}\uB9CC`;
|
|
58
|
+
};
|
|
50
59
|
var formatCurrency = (v) => {
|
|
51
60
|
const sign = v < 0 ? "-" : "";
|
|
52
61
|
const abs = Math.abs(v);
|
|
53
|
-
if (abs >= 1e8) {
|
|
54
|
-
|
|
55
|
-
return `${sign}${eok.toLocaleString("ko-KR", { maximumFractionDigits: eok >= 100 ? 0 : 1 })}\uC5B5`;
|
|
56
|
-
}
|
|
57
|
-
if (abs >= 1e4) {
|
|
58
|
-
return `${sign}${Math.round(abs / 1e4).toLocaleString("ko-KR")}\uB9CC`;
|
|
59
|
-
}
|
|
62
|
+
if (abs >= 1e8) return `${sign}${eokText(abs)}`;
|
|
63
|
+
if (abs >= 1e4) return `${sign}${manText(abs)}`;
|
|
60
64
|
return `${sign}${abs.toLocaleString("ko-KR")}`;
|
|
61
65
|
};
|
|
66
|
+
var currencyAxisFormatter = (maxAbs) => {
|
|
67
|
+
if (!(maxAbs >= 1e5)) return (v) => v.toLocaleString("ko-KR", { maximumFractionDigits: 1 });
|
|
68
|
+
return (v) => {
|
|
69
|
+
const abs = Math.abs(v);
|
|
70
|
+
if (abs === 0) return "0";
|
|
71
|
+
const sign = v < 0 ? "-" : "";
|
|
72
|
+
return `${sign}${abs >= 1e8 ? eokText(abs) : manText(abs)}`;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
62
75
|
var formatPercent = (v) => `${v.toLocaleString("ko-KR", { maximumFractionDigits: 1 })}%`;
|
|
63
76
|
var getFormatter = (format) => {
|
|
64
77
|
if (format === "currency") return formatCurrency;
|
|
65
78
|
if (format === "percent") return formatPercent;
|
|
66
79
|
return formatNumber;
|
|
67
80
|
};
|
|
81
|
+
var axisFormatter = (format, extent) => format === "currency" ? currencyAxisFormatter(extent.maxAbs) : getFormatter(format);
|
|
82
|
+
function axisExtent(rows, series) {
|
|
83
|
+
let maxAbs = 0;
|
|
84
|
+
let allInteger = true;
|
|
85
|
+
for (const row of rows) {
|
|
86
|
+
if (row === null || typeof row !== "object") continue;
|
|
87
|
+
const positive = /* @__PURE__ */ new Map();
|
|
88
|
+
const negative = /* @__PURE__ */ new Map();
|
|
89
|
+
for (const s of series) {
|
|
90
|
+
const raw = row[s.key];
|
|
91
|
+
if (raw === null || raw === void 0 || raw === "" || typeof raw === "boolean") continue;
|
|
92
|
+
const n = Number(raw);
|
|
93
|
+
if (!Number.isFinite(n)) continue;
|
|
94
|
+
if (!Number.isInteger(n)) allInteger = false;
|
|
95
|
+
if (s.stack) {
|
|
96
|
+
const bucket = n >= 0 ? positive : negative;
|
|
97
|
+
bucket.set(s.stack, (bucket.get(s.stack) ?? 0) + n);
|
|
98
|
+
} else {
|
|
99
|
+
maxAbs = Math.max(maxAbs, Math.abs(n));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const total of [...positive.values(), ...negative.values()]) {
|
|
103
|
+
maxAbs = Math.max(maxAbs, Math.abs(total));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { maxAbs, allInteger };
|
|
107
|
+
}
|
|
108
|
+
function estimateTextWidth(text, fontSize = 12) {
|
|
109
|
+
let w = 0;
|
|
110
|
+
for (const ch of text) {
|
|
111
|
+
if (/\s/.test(ch)) w += fontSize * 0.3;
|
|
112
|
+
else if (/[\u1100-\u11ff\u3000-\u9fff\uac00-\ud7af\uf900-\ufaff\uff00-\uffef]/.test(ch)) w += fontSize;
|
|
113
|
+
else w += fontSize * 0.6;
|
|
114
|
+
}
|
|
115
|
+
return w;
|
|
116
|
+
}
|
|
117
|
+
function wrapLabel(label, maxWidth, measure) {
|
|
118
|
+
const text = label.trim();
|
|
119
|
+
if (!text) return [""];
|
|
120
|
+
if (!(maxWidth > 0) || measure(text) <= maxWidth) return [text];
|
|
121
|
+
const lines = [];
|
|
122
|
+
let line = "";
|
|
123
|
+
const push = () => {
|
|
124
|
+
if (line.trim()) lines.push(line.trim());
|
|
125
|
+
line = "";
|
|
126
|
+
};
|
|
127
|
+
for (const word of text.split(/(\s+)/)) {
|
|
128
|
+
if (!word) continue;
|
|
129
|
+
const candidate = line + word;
|
|
130
|
+
if (measure(candidate.trim()) <= maxWidth) {
|
|
131
|
+
line = candidate;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (/^\s+$/.test(word)) {
|
|
135
|
+
push();
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
push();
|
|
139
|
+
if (measure(word) <= maxWidth) {
|
|
140
|
+
line = word;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const chars = [...word];
|
|
144
|
+
const total = measure(word);
|
|
145
|
+
const parts = Math.ceil(total / maxWidth);
|
|
146
|
+
let acc = 0;
|
|
147
|
+
let boundary = total / parts;
|
|
148
|
+
for (const ch of chars) {
|
|
149
|
+
const w = measure(ch);
|
|
150
|
+
if (line && acc + w / 2 > boundary + 0.01) {
|
|
151
|
+
push();
|
|
152
|
+
boundary += total / parts;
|
|
153
|
+
}
|
|
154
|
+
line += ch;
|
|
155
|
+
acc += w;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
push();
|
|
159
|
+
return lines.length > 0 ? lines : [text];
|
|
160
|
+
}
|
|
161
|
+
var TICK_FONT = 12;
|
|
162
|
+
var TICK_LINE_H = 14;
|
|
163
|
+
var MAX_TICK_LINES = 3;
|
|
164
|
+
function planXTicks(labels, bandWidth, measure) {
|
|
165
|
+
if (!(bandWidth > 0) || labels.length === 0) return { mode: "skip" };
|
|
166
|
+
const room = Math.max(0, bandWidth - 6);
|
|
167
|
+
const lines = /* @__PURE__ */ new Map();
|
|
168
|
+
let maxLines = 1;
|
|
169
|
+
let fits = room >= TICK_FONT;
|
|
170
|
+
for (const label of labels) {
|
|
171
|
+
const wrapped = wrapLabel(label, room, measure);
|
|
172
|
+
lines.set(label.trim(), wrapped);
|
|
173
|
+
maxLines = Math.max(maxLines, wrapped.length);
|
|
174
|
+
if (wrapped.some((line) => measure(line) > room + TICK_FONT / 2)) fits = false;
|
|
175
|
+
}
|
|
176
|
+
if (fits && maxLines <= MAX_TICK_LINES) {
|
|
177
|
+
return { mode: "wrap", lines, height: Math.ceil(8 + maxLines * TICK_LINE_H + 4) };
|
|
178
|
+
}
|
|
179
|
+
if (bandWidth * Math.SQRT1_2 >= TICK_FONT * 1.25) {
|
|
180
|
+
const longest = Math.max(...labels.map((label) => measure(label)));
|
|
181
|
+
return { mode: "rotate", height: Math.ceil(8 + (longest + TICK_FONT) * Math.SQRT1_2 + 4) };
|
|
182
|
+
}
|
|
183
|
+
return { mode: "skip" };
|
|
184
|
+
}
|
|
185
|
+
var ROTATE_EDGE_PAD = 2;
|
|
186
|
+
function rotatedTickInset(widths, axisWidth, span, point = false) {
|
|
187
|
+
const n = widths.length;
|
|
188
|
+
if (n === 0 || !(span > 0)) return 0;
|
|
189
|
+
let inset = 0;
|
|
190
|
+
widths.forEach((width, i) => {
|
|
191
|
+
const f = point ? n > 1 ? i / (n - 1) : 0.5 : (i + 0.5) / n;
|
|
192
|
+
if (f >= 1) return;
|
|
193
|
+
const reach = (width + TICK_FONT / 2) * Math.SQRT1_2 + ROTATE_EDGE_PAD;
|
|
194
|
+
const need = (reach - axisWidth - span * f) / (1 - f);
|
|
195
|
+
if (need > inset) inset = need;
|
|
196
|
+
});
|
|
197
|
+
return Math.ceil(inset);
|
|
198
|
+
}
|
|
199
|
+
var ROTATE_MIN_BAND = TICK_FONT * 1.25 / Math.SQRT1_2;
|
|
200
|
+
function planXTicksWithInset(labels, span, axisWidth, measure, point = false) {
|
|
201
|
+
const count = Math.max(1, labels.length);
|
|
202
|
+
const plan = planXTicks(labels, span / count, measure);
|
|
203
|
+
if (plan.mode !== "rotate") return { plan, inset: 0 };
|
|
204
|
+
const want = rotatedTickInset(labels.map((label) => measure(label)), axisWidth, span, point);
|
|
205
|
+
const inset = Math.max(0, Math.min(want, Math.floor(span - count * ROTATE_MIN_BAND)));
|
|
206
|
+
if (inset === 0) return { plan, inset: 0 };
|
|
207
|
+
const narrowed = planXTicks(labels, (span - inset) / count, measure);
|
|
208
|
+
return narrowed.mode === "rotate" ? { plan: narrowed, inset } : { plan, inset: 0 };
|
|
209
|
+
}
|
|
68
210
|
var tooltipBoxStyle = {
|
|
69
211
|
background: "var(--wp-surface-card)",
|
|
70
212
|
border: "1px solid var(--wp-border-subtle)",
|
|
@@ -80,7 +222,7 @@ var dotStyle = (color) => ({
|
|
|
80
222
|
background: color,
|
|
81
223
|
flexShrink: 0
|
|
82
224
|
});
|
|
83
|
-
function renderTooltipContent(props,
|
|
225
|
+
function renderTooltipContent(props, formatOf) {
|
|
84
226
|
const { active, payload, label } = props;
|
|
85
227
|
if (!active || !payload || payload.length === 0) return null;
|
|
86
228
|
return /* @__PURE__ */ jsxs("div", { style: tooltipBoxStyle, children: [
|
|
@@ -88,7 +230,7 @@ function renderTooltipContent(props, format) {
|
|
|
88
230
|
/* @__PURE__ */ jsx("div", { style: { display: "grid", gap: 2 }, children: payload.filter((entry) => entry.type !== "none").map((entry, i) => {
|
|
89
231
|
const fillFromDatum = entry.payload !== null && typeof entry.payload === "object" ? entry.payload.fill : void 0;
|
|
90
232
|
const color = entry.color ?? fillFromDatum ?? "var(--wp-text-muted)";
|
|
91
|
-
const value = typeof entry.value === "number" ?
|
|
233
|
+
const value = typeof entry.value === "number" ? formatOf(entry)(entry.value) : String(entry.value ?? "");
|
|
92
234
|
return /* @__PURE__ */ jsxs(
|
|
93
235
|
"div",
|
|
94
236
|
{
|
|
@@ -169,6 +311,9 @@ function SliceLegendTable({
|
|
|
169
311
|
style: {
|
|
170
312
|
flex: "none",
|
|
171
313
|
minWidth: 148,
|
|
314
|
+
// 차트 옆 한 줄에서는 차트가 남는 폭을 다 먹어 여백이 0이다. 좁아서 아래 줄로
|
|
315
|
+
// 내려가면(wp-chart__split 이 wrap) 혼자 남은 줄에서 가운데에 선다.
|
|
316
|
+
marginInline: "auto",
|
|
172
317
|
display: "flex",
|
|
173
318
|
flexDirection: "column",
|
|
174
319
|
justifyContent: "center",
|
|
@@ -208,7 +353,60 @@ function SliceLegendTable({
|
|
|
208
353
|
}
|
|
209
354
|
);
|
|
210
355
|
}
|
|
356
|
+
var measureCanvas;
|
|
357
|
+
function makeMeasure(fontFamily) {
|
|
358
|
+
if (measureCanvas === void 0) {
|
|
359
|
+
try {
|
|
360
|
+
measureCanvas = typeof document !== "undefined" ? document.createElement("canvas").getContext("2d") : null;
|
|
361
|
+
} catch {
|
|
362
|
+
measureCanvas = null;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const ctx = measureCanvas;
|
|
366
|
+
if (!ctx || !fontFamily) return (text) => estimateTextWidth(text, TICK_FONT);
|
|
367
|
+
const font = `${TICK_FONT}px ${fontFamily}`;
|
|
368
|
+
return (text) => {
|
|
369
|
+
ctx.font = font;
|
|
370
|
+
return ctx.measureText(text).width;
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function useHostBox(ref, enabled) {
|
|
374
|
+
const [box, setBox] = useState({
|
|
375
|
+
width: 0,
|
|
376
|
+
fontFamily: null
|
|
377
|
+
});
|
|
378
|
+
useLayoutEffect(() => {
|
|
379
|
+
const el = ref.current;
|
|
380
|
+
if (!enabled || el === null) return;
|
|
381
|
+
const read = () => {
|
|
382
|
+
const width = Math.round(el.getBoundingClientRect().width);
|
|
383
|
+
const fontFamily = getComputedStyle(el).fontFamily || null;
|
|
384
|
+
setBox((prev) => prev.width === width && prev.fontFamily === fontFamily ? prev : { width, fontFamily });
|
|
385
|
+
};
|
|
386
|
+
read();
|
|
387
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
388
|
+
const observer = new ResizeObserver(read);
|
|
389
|
+
observer.observe(el);
|
|
390
|
+
return () => observer.disconnect();
|
|
391
|
+
});
|
|
392
|
+
return box;
|
|
393
|
+
}
|
|
211
394
|
var axisTick = { fill: "var(--wp-text-muted)", fontSize: 12 };
|
|
395
|
+
var SIDE_LEGEND_CHART_MIN = 96;
|
|
396
|
+
function renderCategoryTick(plan) {
|
|
397
|
+
const CategoryTick = (props) => {
|
|
398
|
+
const x = Number(props.x) || 0;
|
|
399
|
+
const y = Number(props.y) || 0;
|
|
400
|
+
const label = String(props.payload?.value ?? "");
|
|
401
|
+
const textStyle = { fill: axisTick.fill, fontSize: axisTick.fontSize };
|
|
402
|
+
if (plan.mode === "rotate") {
|
|
403
|
+
return /* @__PURE__ */ jsx("g", { transform: `translate(${x},${y})`, children: /* @__PURE__ */ jsx("text", { x: 0, y: 0, dy: "0.71em", textAnchor: "end", transform: "rotate(-45)", style: textStyle, children: label }) });
|
|
404
|
+
}
|
|
405
|
+
const lines = plan.lines.get(label.trim()) ?? [label];
|
|
406
|
+
return /* @__PURE__ */ jsx("g", { transform: `translate(${x},${y})`, children: /* @__PURE__ */ jsx("text", { x: 0, y: 0, textAnchor: "middle", style: textStyle, children: lines.map((line, i) => /* @__PURE__ */ jsx("tspan", { x: 0, dy: i === 0 ? "0.71em" : TICK_LINE_H, children: line }, i)) }) });
|
|
407
|
+
};
|
|
408
|
+
return CategoryTick;
|
|
409
|
+
}
|
|
212
410
|
function Chart({
|
|
213
411
|
type,
|
|
214
412
|
data,
|
|
@@ -220,11 +418,16 @@ function Chart({
|
|
|
220
418
|
legendPlacement = "bottom",
|
|
221
419
|
legendTotal,
|
|
222
420
|
donutCenter,
|
|
223
|
-
emptyText
|
|
421
|
+
emptyText,
|
|
422
|
+
rightValueFormat = "number",
|
|
423
|
+
integer,
|
|
424
|
+
xTickWrap = false
|
|
224
425
|
}) {
|
|
225
426
|
const hostRef = useRef(null);
|
|
226
427
|
const palette = useSeriesPalette(hostRef);
|
|
227
428
|
const recharts = useOptionalModule(loadRecharts);
|
|
429
|
+
const cartesianType = type === "bar" || type === "line" || type === "composed";
|
|
430
|
+
const hostBox = useHostBox(hostRef, xTickWrap === true && cartesianType);
|
|
228
431
|
const resolveColor = useCallback(
|
|
229
432
|
(color, index) => {
|
|
230
433
|
if (!color) return palette[index % palette.length];
|
|
@@ -270,7 +473,7 @@ function Chart({
|
|
|
270
473
|
XAxis,
|
|
271
474
|
YAxis
|
|
272
475
|
} = recharts.module;
|
|
273
|
-
const tooltipContent = (props) => renderTooltipContent(props, format);
|
|
476
|
+
const tooltipContent = (props) => renderTooltipContent(props, () => format);
|
|
274
477
|
if (type === "donut" || type === "pie") {
|
|
275
478
|
const nameKey = xKey ?? "name";
|
|
276
479
|
const valueKey = seriesList[0].key;
|
|
@@ -283,7 +486,7 @@ function Chart({
|
|
|
283
486
|
const chartArea = /* @__PURE__ */ jsxs(
|
|
284
487
|
"div",
|
|
285
488
|
{
|
|
286
|
-
style: sideLegend ? { position: "relative", flex:
|
|
489
|
+
style: sideLegend ? { position: "relative", flex: `1 1 ${SIDE_LEGEND_CHART_MIN}px`, minWidth: 0, height } : { position: "relative", width: "100%", height },
|
|
287
490
|
children: [
|
|
288
491
|
/* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { children: [
|
|
289
492
|
/* @__PURE__ */ jsx(Tooltip, { content: tooltipContent }),
|
|
@@ -333,17 +536,24 @@ function Chart({
|
|
|
333
536
|
};
|
|
334
537
|
const denomOverride = Number(legendTotal);
|
|
335
538
|
return shell(
|
|
336
|
-
/* @__PURE__ */ jsxs(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
{
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
539
|
+
/* @__PURE__ */ jsxs(
|
|
540
|
+
"div",
|
|
541
|
+
{
|
|
542
|
+
className: "wp-chart__split",
|
|
543
|
+
style: { display: "flex", flexWrap: "wrap", alignItems: "center", gap: "var(--wp-space-6)" },
|
|
544
|
+
children: [
|
|
545
|
+
chartArea,
|
|
546
|
+
/* @__PURE__ */ jsx(
|
|
547
|
+
SliceLegendTable,
|
|
548
|
+
{
|
|
549
|
+
rows: rows.map((row, i) => ({ ...legendItems2[i], value: sliceValue(row) })),
|
|
550
|
+
format,
|
|
551
|
+
total: legendTotal !== void 0 && Number.isFinite(denomOverride) ? denomOverride : void 0
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
)
|
|
347
557
|
);
|
|
348
558
|
}
|
|
349
559
|
return shell(
|
|
@@ -369,6 +579,25 @@ function Chart({
|
|
|
369
579
|
color: resolveColor(s.color, i),
|
|
370
580
|
dashed: kindOf(s) === "dashed-line"
|
|
371
581
|
}));
|
|
582
|
+
const onRight = (s) => s.axis === "right";
|
|
583
|
+
const dual = seriesList.some(onRight) && seriesList.some((s) => !onRight(s));
|
|
584
|
+
const axisIdOf = (s) => dual ? onRight(s) ? "right" : "left" : void 0;
|
|
585
|
+
const extentOf = (list) => axisExtent(
|
|
586
|
+
rows,
|
|
587
|
+
list.map((s) => ({ key: s.key, stack: kindOf(s) === "bar" ? s.stack : void 0 }))
|
|
588
|
+
);
|
|
589
|
+
const leftExtent = extentOf(dual ? seriesList.filter((s) => !onRight(s)) : seriesList);
|
|
590
|
+
const rightExtent = dual ? extentOf(seriesList.filter(onRight)) : null;
|
|
591
|
+
const allowDecimals = (extent) => typeof integer === "boolean" ? !integer : !extent.allInteger;
|
|
592
|
+
const tickCountFor = (extent) => !allowDecimals(extent) && extent.maxAbs < 4 ? Math.max(2, Math.ceil(extent.maxAbs) + 1) : void 0;
|
|
593
|
+
const leftTickFormat = axisFormatter(valueFormat, leftExtent);
|
|
594
|
+
const rightFormat = getFormatter(rightValueFormat);
|
|
595
|
+
const rightTickFormat = rightExtent ? axisFormatter(rightValueFormat, rightExtent) : rightFormat;
|
|
596
|
+
const rightKeys = new Set(dual ? seriesList.filter(onRight).map((s) => s.key) : []);
|
|
597
|
+
const cartesianTooltip = (props) => renderTooltipContent(
|
|
598
|
+
props,
|
|
599
|
+
(entry) => typeof entry.dataKey === "string" && rightKeys.has(entry.dataKey) ? rightFormat : format
|
|
600
|
+
);
|
|
372
601
|
const marks = seriesList.map((s, i) => {
|
|
373
602
|
const color = resolveColor(s.color, i);
|
|
374
603
|
const name = s.label ?? s.key;
|
|
@@ -380,6 +609,7 @@ function Chart({
|
|
|
380
609
|
name,
|
|
381
610
|
fill: color,
|
|
382
611
|
stackId: s.stack,
|
|
612
|
+
yAxisId: axisIdOf(s),
|
|
383
613
|
maxBarSize: 48,
|
|
384
614
|
radius: barRadius(s, i),
|
|
385
615
|
isAnimationActive: false
|
|
@@ -396,6 +626,7 @@ function Chart({
|
|
|
396
626
|
stroke: color,
|
|
397
627
|
strokeWidth: 2,
|
|
398
628
|
strokeDasharray: kindOf(s) === "dashed-line" ? "6 4" : void 0,
|
|
629
|
+
yAxisId: axisIdOf(s),
|
|
399
630
|
dot: false,
|
|
400
631
|
activeDot: { r: 4, strokeWidth: 2, stroke: "var(--wp-surface-card)" },
|
|
401
632
|
isAnimationActive: false
|
|
@@ -403,8 +634,29 @@ function Chart({
|
|
|
403
634
|
s.key
|
|
404
635
|
);
|
|
405
636
|
});
|
|
637
|
+
const margin = { top: 8, right: 8, bottom: 0, left: 0 };
|
|
638
|
+
const Y_AXIS_WIDTH = 52;
|
|
639
|
+
let xTick = {};
|
|
640
|
+
if (xTickWrap && hostBox.width > 0) {
|
|
641
|
+
const labels = rows.map((row) => String((xKey ? row[xKey] : void 0) ?? ""));
|
|
642
|
+
const measure = makeMeasure(hostBox.fontFamily);
|
|
643
|
+
const span = hostBox.width - margin.right - Y_AXIS_WIDTH * (dual ? 2 : 1);
|
|
644
|
+
const { plan, inset } = planXTicksWithInset(labels, span - margin.left, Y_AXIS_WIDTH, measure, !hasBar);
|
|
645
|
+
margin.left += inset;
|
|
646
|
+
if (plan.mode !== "skip") {
|
|
647
|
+
xTick = { interval: 0, height: plan.height, tick: renderCategoryTick(plan) };
|
|
648
|
+
}
|
|
649
|
+
}
|
|
406
650
|
const axes = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
407
|
-
/* @__PURE__ */ jsx(
|
|
651
|
+
/* @__PURE__ */ jsx(
|
|
652
|
+
CartesianGrid,
|
|
653
|
+
{
|
|
654
|
+
strokeDasharray: "3 3",
|
|
655
|
+
stroke: "var(--wp-divider)",
|
|
656
|
+
vertical: false,
|
|
657
|
+
yAxisId: dual ? "left" : void 0
|
|
658
|
+
}
|
|
659
|
+
),
|
|
408
660
|
/* @__PURE__ */ jsx(
|
|
409
661
|
XAxis,
|
|
410
662
|
{
|
|
@@ -412,28 +664,45 @@ function Chart({
|
|
|
412
664
|
tickLine: false,
|
|
413
665
|
axisLine: { stroke: "var(--wp-border-subtle)" },
|
|
414
666
|
tick: axisTick,
|
|
415
|
-
tickMargin: 6
|
|
667
|
+
tickMargin: 6,
|
|
668
|
+
...xTick
|
|
416
669
|
}
|
|
417
670
|
),
|
|
418
671
|
/* @__PURE__ */ jsx(
|
|
419
672
|
YAxis,
|
|
420
673
|
{
|
|
674
|
+
yAxisId: dual ? "left" : void 0,
|
|
421
675
|
tickLine: false,
|
|
422
676
|
axisLine: false,
|
|
423
677
|
tick: axisTick,
|
|
424
|
-
tickFormatter: (v) =>
|
|
425
|
-
|
|
678
|
+
tickFormatter: (v) => leftTickFormat(v),
|
|
679
|
+
allowDecimals: allowDecimals(leftExtent),
|
|
680
|
+
tickCount: tickCountFor(leftExtent),
|
|
681
|
+
width: Y_AXIS_WIDTH
|
|
426
682
|
}
|
|
427
683
|
),
|
|
684
|
+
dual && rightExtent ? /* @__PURE__ */ jsx(
|
|
685
|
+
YAxis,
|
|
686
|
+
{
|
|
687
|
+
yAxisId: "right",
|
|
688
|
+
orientation: "right",
|
|
689
|
+
tickLine: false,
|
|
690
|
+
axisLine: false,
|
|
691
|
+
tick: axisTick,
|
|
692
|
+
tickFormatter: (v) => rightTickFormat(v),
|
|
693
|
+
allowDecimals: allowDecimals(rightExtent),
|
|
694
|
+
tickCount: tickCountFor(rightExtent),
|
|
695
|
+
width: Y_AXIS_WIDTH
|
|
696
|
+
}
|
|
697
|
+
) : null,
|
|
428
698
|
/* @__PURE__ */ jsx(
|
|
429
699
|
Tooltip,
|
|
430
700
|
{
|
|
431
701
|
cursor: hasBar ? { fill: "var(--wp-surface-sunken)", fillOpacity: 0.5 } : { stroke: "var(--wp-border-subtle)", strokeDasharray: "3 3" },
|
|
432
|
-
content:
|
|
702
|
+
content: cartesianTooltip
|
|
433
703
|
}
|
|
434
704
|
)
|
|
435
705
|
] });
|
|
436
|
-
const margin = { top: 8, right: 8, bottom: 0, left: 0 };
|
|
437
706
|
const cartesian = type === "bar" ? /* @__PURE__ */ jsxs(BarChart, { data: rows, margin, children: [
|
|
438
707
|
axes,
|
|
439
708
|
marks
|