sellmate-design-system-react 9.0.0-beta.50 → 9.0.0-beta.52
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/AGENTS.md +105 -37
- package/dist/components/SBarChart/barChart.config.d.ts +41 -14
- package/dist/components/SLoginCard/sellmate-wordmark.d.ts +2 -1
- package/dist/components/SScrollArea/README.md +1 -0
- package/dist/components/SScrollArea/SScrollArea.d.ts +17 -0
- package/dist/components/SSelect/select.config.d.ts +1 -1
- package/dist/components/SSystemActionButton/README.md +12 -7
- package/dist/components/SSystemActionButton/SSystemActionButton.d.ts +15 -9
- package/dist/components/STable/README.md +6 -1
- package/dist/components/STable/STable.d.ts +61 -1
- package/dist/components/STableBar/README.md +1 -0
- package/dist/components/STableBar/STableBar.d.ts +8 -1
- package/dist/index.cjs +692 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +692 -384
- package/dist/index.js.map +1 -1
- package/dist/lib/chart/tooltip.d.ts +12 -4
- package/dist/lib/chart/use-element-size.d.ts +22 -0
- package/dist/lib/overlay-scrollbar.d.ts +32 -0
- package/dist/{components/SSelect → lib}/row-metrics.d.ts +1 -0
- package/dist/llms-full.txt +125 -45
- package/dist/llms.txt +105 -37
- package/dist/styles.css +17 -20
- package/dist/theme.css +8 -4
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -6423,8 +6423,8 @@ function SellmateWordmark({ className }) {
|
|
|
6423
6423
|
"svg",
|
|
6424
6424
|
{
|
|
6425
6425
|
className,
|
|
6426
|
-
width: "
|
|
6427
|
-
height: "
|
|
6426
|
+
width: "220.8",
|
|
6427
|
+
height: "32",
|
|
6428
6428
|
viewBox: "0 0 276 40",
|
|
6429
6429
|
fill: "#00275F",
|
|
6430
6430
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -6458,7 +6458,7 @@ var SLoginCardImpl = /* @__PURE__ */ react.forwardRef(function SLoginCard({ prod
|
|
|
6458
6458
|
// 로그인 화면 밖(모달·스토리)에서도 그대로 쓸 수 있는 이유다.
|
|
6459
6459
|
"flex h-full w-full max-w-[640px] min-w-[368px] shrink-0 flex-col items-center justify-center gap-sd-60",
|
|
6460
6460
|
// 라운드 24px·폭 상하한(640/368px)은 대응 토큰이 없어 값으로 둔다 (디자인팀 토큰 추가 요청 대상).
|
|
6461
|
-
"rounded-[24px] bg-(--sys-color-bg-frame) p-sd-
|
|
6461
|
+
"rounded-[24px] bg-(--sys-color-bg-frame) p-sd-16 text-center",
|
|
6462
6462
|
// 한글은 기본 규칙으로 두면 어절 한가운데서도 줄이 바뀐다 — `break-keep` 으로 띄어쓰기에서만
|
|
6463
6463
|
// 끊는다. 끊을 자리가 아예 없는 긴 토큰(URL·주문번호)만 `wrap-break-word` 로 흘려보낸다.
|
|
6464
6464
|
"break-keep wrap-break-word",
|
|
@@ -6471,7 +6471,7 @@ var SLoginCardImpl = /* @__PURE__ */ react.forwardRef(function SLoginCard({ prod
|
|
|
6471
6471
|
/* @__PURE__ */ jsxRuntime.jsx(SellmateWordmark, {}),
|
|
6472
6472
|
product != null && // 24px 는 typo 프리셋(최대 18px)에 없는 등급이다 — 제품명은 로고의 일부처럼 읽혀야
|
|
6473
6473
|
// 해서 본문 스케일 위에 선다. 여기만 값으로 두고, 프리셋이 생기면 갈아탄다.
|
|
6474
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 text-[24px] leading-[
|
|
6474
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 text-[24px] leading-[28px] font-bold text-(--sys-color-fg-accentLight)", children: product })
|
|
6475
6475
|
] }),
|
|
6476
6476
|
hasIntro && // 소개와 보조 설명은 한 문단으로 읽힌다.
|
|
6477
6477
|
// `text-balance` 는 상속되므로 여기 한 번만 걸어 둘을 함께 덮는다 — 가운데 정렬에서는
|
|
@@ -7124,6 +7124,149 @@ var SSectionHeaderCardRootImpl = /* @__PURE__ */ react.forwardRef(
|
|
|
7124
7124
|
}
|
|
7125
7125
|
);
|
|
7126
7126
|
var SSectionHeaderCard2 = /* @__PURE__ */ withDisplayName(SSectionHeaderCardRootImpl, "SSectionHeaderCard");
|
|
7127
|
+
var OVERLAY_SCROLLBAR_SIZE = 12;
|
|
7128
|
+
var MIN_THUMB_SIZE = 32;
|
|
7129
|
+
var AUTO_HIDE_DELAY = 1e3;
|
|
7130
|
+
var FADE_CLASS = "transition-opacity duration-200 ease-out motion-reduce:transition-none";
|
|
7131
|
+
var HIDDEN = { visible: false, thumbSize: 0, thumbOffset: 0 };
|
|
7132
|
+
function getMetrics(viewportSize, contentSize, scrollOffset) {
|
|
7133
|
+
if (contentSize <= viewportSize) return HIDDEN;
|
|
7134
|
+
const trackSize = viewportSize;
|
|
7135
|
+
const maxScrollOffset = contentSize - viewportSize;
|
|
7136
|
+
const thumbSize = Math.min(
|
|
7137
|
+
trackSize,
|
|
7138
|
+
Math.max(MIN_THUMB_SIZE, viewportSize / contentSize * trackSize)
|
|
7139
|
+
);
|
|
7140
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
7141
|
+
const thumbOffset = maxScrollOffset > 0 ? scrollOffset / maxScrollOffset * maxThumbOffset : 0;
|
|
7142
|
+
return { visible: true, thumbSize, thumbOffset };
|
|
7143
|
+
}
|
|
7144
|
+
function OverlayScrollbars({
|
|
7145
|
+
scrollRef,
|
|
7146
|
+
vertical: showVertical = true,
|
|
7147
|
+
horizontal: showHorizontal = true,
|
|
7148
|
+
autoHide = false
|
|
7149
|
+
}) {
|
|
7150
|
+
const [vertical, setVertical] = react.useState(HIDDEN);
|
|
7151
|
+
const [horizontal, setHorizontal] = react.useState(HIDDEN);
|
|
7152
|
+
const [scrolling, setScrolling] = react.useState(false);
|
|
7153
|
+
const [dragging, setDragging] = react.useState(false);
|
|
7154
|
+
const hideTimer = react.useRef(null);
|
|
7155
|
+
const shown = !autoHide || scrolling || dragging;
|
|
7156
|
+
const update = react.useCallback(() => {
|
|
7157
|
+
const el = scrollRef.current;
|
|
7158
|
+
if (!el) return;
|
|
7159
|
+
setVertical(showVertical ? getMetrics(el.clientHeight, el.scrollHeight, el.scrollTop) : HIDDEN);
|
|
7160
|
+
setHorizontal(
|
|
7161
|
+
showHorizontal ? getMetrics(el.clientWidth, el.scrollWidth, el.scrollLeft) : HIDDEN
|
|
7162
|
+
);
|
|
7163
|
+
}, [scrollRef, showVertical, showHorizontal]);
|
|
7164
|
+
const wake = react.useCallback(() => {
|
|
7165
|
+
setScrolling(true);
|
|
7166
|
+
if (hideTimer.current) clearTimeout(hideTimer.current);
|
|
7167
|
+
hideTimer.current = setTimeout(() => setScrolling(false), AUTO_HIDE_DELAY);
|
|
7168
|
+
}, []);
|
|
7169
|
+
react.useEffect(() => () => void (hideTimer.current && clearTimeout(hideTimer.current)), []);
|
|
7170
|
+
react.useEffect(() => {
|
|
7171
|
+
const el = scrollRef.current;
|
|
7172
|
+
if (!el) return;
|
|
7173
|
+
const onScroll = () => {
|
|
7174
|
+
update();
|
|
7175
|
+
if (autoHide) wake();
|
|
7176
|
+
};
|
|
7177
|
+
update();
|
|
7178
|
+
el.addEventListener("scroll", onScroll, { passive: true });
|
|
7179
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
7180
|
+
observer?.observe(el);
|
|
7181
|
+
if (el.firstElementChild) observer?.observe(el.firstElementChild);
|
|
7182
|
+
return () => {
|
|
7183
|
+
el.removeEventListener("scroll", onScroll);
|
|
7184
|
+
observer?.disconnect();
|
|
7185
|
+
};
|
|
7186
|
+
}, [scrollRef, update, autoHide, wake]);
|
|
7187
|
+
const drag = (axis) => (startEvent) => {
|
|
7188
|
+
const el = scrollRef.current;
|
|
7189
|
+
const metrics = axis === "vertical" ? vertical : horizontal;
|
|
7190
|
+
if (!el || !metrics.visible) return;
|
|
7191
|
+
startEvent.preventDefault();
|
|
7192
|
+
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
7193
|
+
setDragging(true);
|
|
7194
|
+
const isVertical = axis === "vertical";
|
|
7195
|
+
const startPointer = isVertical ? startEvent.clientY : startEvent.clientX;
|
|
7196
|
+
const startScroll = isVertical ? el.scrollTop : el.scrollLeft;
|
|
7197
|
+
const viewportSize = isVertical ? el.clientHeight : el.clientWidth;
|
|
7198
|
+
const contentSize = isVertical ? el.scrollHeight : el.scrollWidth;
|
|
7199
|
+
const maxThumbOffset = viewportSize - metrics.thumbSize;
|
|
7200
|
+
const maxScroll = contentSize - viewportSize;
|
|
7201
|
+
if (maxThumbOffset <= 0 || maxScroll <= 0) {
|
|
7202
|
+
setDragging(false);
|
|
7203
|
+
return;
|
|
7204
|
+
}
|
|
7205
|
+
const onPointerMove = (moveEvent) => {
|
|
7206
|
+
const delta = (isVertical ? moveEvent.clientY : moveEvent.clientX) - startPointer;
|
|
7207
|
+
const next = startScroll + delta / maxThumbOffset * maxScroll;
|
|
7208
|
+
if (isVertical) el.scrollTop = next;
|
|
7209
|
+
else el.scrollLeft = next;
|
|
7210
|
+
};
|
|
7211
|
+
const onPointerUp = () => {
|
|
7212
|
+
setDragging(false);
|
|
7213
|
+
if (autoHide) wake();
|
|
7214
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
7215
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
7216
|
+
};
|
|
7217
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
7218
|
+
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
7219
|
+
};
|
|
7220
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7221
|
+
vertical.visible && // 트랙은 포인터를 받지 않는다 — 막대가 없는 자리는 아래 콘텐츠가 그대로 눌린다.
|
|
7222
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7223
|
+
"div",
|
|
7224
|
+
{
|
|
7225
|
+
"aria-hidden": "true",
|
|
7226
|
+
className: cn(
|
|
7227
|
+
"pointer-events-none absolute top-0 right-0 bottom-0 z-[1] w-[12px]",
|
|
7228
|
+
FADE_CLASS,
|
|
7229
|
+
shown ? "opacity-100" : "opacity-0"
|
|
7230
|
+
),
|
|
7231
|
+
style: { bottom: horizontal.visible ? OVERLAY_SCROLLBAR_SIZE : 0 },
|
|
7232
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7233
|
+
"div",
|
|
7234
|
+
{
|
|
7235
|
+
className: "pointer-events-auto absolute right-[2px] w-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
7236
|
+
style: {
|
|
7237
|
+
height: vertical.thumbSize,
|
|
7238
|
+
transform: `translateY(${vertical.thumbOffset}px)`
|
|
7239
|
+
},
|
|
7240
|
+
onPointerDown: drag("vertical")
|
|
7241
|
+
}
|
|
7242
|
+
)
|
|
7243
|
+
}
|
|
7244
|
+
),
|
|
7245
|
+
horizontal.visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7246
|
+
"div",
|
|
7247
|
+
{
|
|
7248
|
+
"aria-hidden": "true",
|
|
7249
|
+
className: cn(
|
|
7250
|
+
"pointer-events-none absolute right-0 bottom-0 left-0 z-[1] h-[12px]",
|
|
7251
|
+
FADE_CLASS,
|
|
7252
|
+
shown ? "opacity-100" : "opacity-0"
|
|
7253
|
+
),
|
|
7254
|
+
style: { right: vertical.visible ? OVERLAY_SCROLLBAR_SIZE : 0 },
|
|
7255
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7256
|
+
"div",
|
|
7257
|
+
{
|
|
7258
|
+
className: "pointer-events-auto absolute bottom-[2px] h-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
7259
|
+
style: {
|
|
7260
|
+
width: horizontal.thumbSize,
|
|
7261
|
+
transform: `translateX(${horizontal.thumbOffset}px)`
|
|
7262
|
+
},
|
|
7263
|
+
onPointerDown: drag("horizontal")
|
|
7264
|
+
}
|
|
7265
|
+
)
|
|
7266
|
+
}
|
|
7267
|
+
)
|
|
7268
|
+
] });
|
|
7269
|
+
}
|
|
7127
7270
|
|
|
7128
7271
|
// src/lib/scrollbar.ts
|
|
7129
7272
|
var FIREFOX_SCROLLBAR_CLASS = "supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-width:thin] supports-[not_selector(::-webkit-scrollbar)]:[scrollbar-color:var(--color-grey-45)_transparent]";
|
|
@@ -7143,30 +7286,61 @@ var SScrollArea = /* @__PURE__ */ react.forwardRef(function SScrollArea2({
|
|
|
7143
7286
|
bordered = false,
|
|
7144
7287
|
maxHeight,
|
|
7145
7288
|
maxWidth,
|
|
7289
|
+
overlayScrollbar = false,
|
|
7146
7290
|
className,
|
|
7147
7291
|
style,
|
|
7148
7292
|
children,
|
|
7149
7293
|
...rest
|
|
7150
7294
|
}, ref) {
|
|
7295
|
+
const scrollRef = react.useRef(null);
|
|
7296
|
+
const setScrollRef = react.useCallback(
|
|
7297
|
+
(node) => {
|
|
7298
|
+
scrollRef.current = node;
|
|
7299
|
+
if (typeof ref === "function") ref(node);
|
|
7300
|
+
else if (ref) ref.current = node;
|
|
7301
|
+
},
|
|
7302
|
+
[ref]
|
|
7303
|
+
);
|
|
7151
7304
|
const mergedStyle = { ...style };
|
|
7152
7305
|
if (maxHeight) mergedStyle.maxHeight = maxHeight;
|
|
7153
7306
|
if (maxWidth) mergedStyle.maxWidth = maxWidth;
|
|
7154
|
-
|
|
7307
|
+
const scroller = /* @__PURE__ */ jsxRuntime.jsx(
|
|
7155
7308
|
"div",
|
|
7156
7309
|
{
|
|
7157
|
-
ref,
|
|
7310
|
+
ref: setScrollRef,
|
|
7158
7311
|
className: cn(
|
|
7159
7312
|
AXIS_CLASS[axis],
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7313
|
+
overlayScrollbar ? (
|
|
7314
|
+
// 바깥 상자가 크기를 쥐었으므로 스크롤 요소는 그 안을 채우기만 한다.
|
|
7315
|
+
`${SCROLLBAR_HIDDEN_CLASS} h-full w-full`
|
|
7316
|
+
) : cn(
|
|
7317
|
+
SCROLLBAR_CLASS,
|
|
7318
|
+
background && SCROLLBAR_TRACK_BG_CLASS,
|
|
7319
|
+
bordered && SCROLLBAR_TRACK_BORDER_CLASS
|
|
7320
|
+
),
|
|
7321
|
+
!overlayScrollbar && className
|
|
7164
7322
|
),
|
|
7165
|
-
style: mergedStyle,
|
|
7323
|
+
style: overlayScrollbar ? void 0 : mergedStyle,
|
|
7166
7324
|
...rest,
|
|
7167
7325
|
children
|
|
7168
7326
|
}
|
|
7169
7327
|
);
|
|
7328
|
+
if (!overlayScrollbar) return scroller;
|
|
7329
|
+
return (
|
|
7330
|
+
// 막대가 기준으로 삼을 상자. overflow-hidden 은 막대가 모서리 밖으로 새지 않게 한다.
|
|
7331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative overflow-hidden", className), style: mergedStyle, children: [
|
|
7332
|
+
scroller,
|
|
7333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7334
|
+
OverlayScrollbars,
|
|
7335
|
+
{
|
|
7336
|
+
scrollRef,
|
|
7337
|
+
vertical: axis !== "horizontal",
|
|
7338
|
+
horizontal: axis !== "vertical",
|
|
7339
|
+
autoHide: true
|
|
7340
|
+
}
|
|
7341
|
+
)
|
|
7342
|
+
] })
|
|
7343
|
+
);
|
|
7170
7344
|
});
|
|
7171
7345
|
|
|
7172
7346
|
// src/components/SScrollArea/scrollArea.config.ts
|
|
@@ -11799,22 +11973,6 @@ var NATIVE_SCROLLBAR_BACKGROUND_CLASS = {
|
|
|
11799
11973
|
neutral: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
|
|
11800
11974
|
screen: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
|
|
11801
11975
|
};
|
|
11802
|
-
var SCROLLBAR_SIZE = 12;
|
|
11803
|
-
var SCROLLBAR_MIN_THUMB_SIZE = 32;
|
|
11804
|
-
var getMetrics = (viewportSize, contentSize, scrollOffset) => {
|
|
11805
|
-
if (contentSize <= viewportSize) {
|
|
11806
|
-
return { visible: false, thumbSize: 0, thumbOffset: 0 };
|
|
11807
|
-
}
|
|
11808
|
-
const trackSize = viewportSize;
|
|
11809
|
-
const maxScrollOffset = contentSize - viewportSize;
|
|
11810
|
-
const thumbSize = Math.min(
|
|
11811
|
-
trackSize,
|
|
11812
|
-
Math.max(SCROLLBAR_MIN_THUMB_SIZE, viewportSize / contentSize * trackSize)
|
|
11813
|
-
);
|
|
11814
|
-
const maxThumbOffset = trackSize - thumbSize;
|
|
11815
|
-
const thumbOffset = maxScrollOffset > 0 ? scrollOffset / maxScrollOffset * maxThumbOffset : 0;
|
|
11816
|
-
return { visible: true, thumbSize, thumbOffset };
|
|
11817
|
-
};
|
|
11818
11976
|
var setForwardedRef = (ref, node) => {
|
|
11819
11977
|
if (typeof ref === "function") {
|
|
11820
11978
|
ref(node);
|
|
@@ -11822,119 +11980,6 @@ var setForwardedRef = (ref, node) => {
|
|
|
11822
11980
|
}
|
|
11823
11981
|
if (ref) ref.current = node;
|
|
11824
11982
|
};
|
|
11825
|
-
function SPageOverlayScrollbars({ scrollRef }) {
|
|
11826
|
-
const [vertical, setVertical] = react.useState({
|
|
11827
|
-
visible: false,
|
|
11828
|
-
thumbSize: 0,
|
|
11829
|
-
thumbOffset: 0
|
|
11830
|
-
});
|
|
11831
|
-
const [horizontal, setHorizontal] = react.useState({
|
|
11832
|
-
visible: false,
|
|
11833
|
-
thumbSize: 0,
|
|
11834
|
-
thumbOffset: 0
|
|
11835
|
-
});
|
|
11836
|
-
const update = react.useCallback(() => {
|
|
11837
|
-
const el = scrollRef.current;
|
|
11838
|
-
if (!el) return;
|
|
11839
|
-
setVertical(getMetrics(el.clientHeight, el.scrollHeight, el.scrollTop));
|
|
11840
|
-
setHorizontal(getMetrics(el.clientWidth, el.scrollWidth, el.scrollLeft));
|
|
11841
|
-
}, [scrollRef]);
|
|
11842
|
-
react.useEffect(() => {
|
|
11843
|
-
const el = scrollRef.current;
|
|
11844
|
-
if (!el) return;
|
|
11845
|
-
update();
|
|
11846
|
-
el.addEventListener("scroll", update, { passive: true });
|
|
11847
|
-
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
|
|
11848
|
-
observer?.observe(el);
|
|
11849
|
-
if (el.firstElementChild) observer?.observe(el.firstElementChild);
|
|
11850
|
-
return () => {
|
|
11851
|
-
el.removeEventListener("scroll", update);
|
|
11852
|
-
observer?.disconnect();
|
|
11853
|
-
};
|
|
11854
|
-
}, [scrollRef, update]);
|
|
11855
|
-
const dragVertical = (startEvent) => {
|
|
11856
|
-
const el = scrollRef.current;
|
|
11857
|
-
if (!el || !vertical.visible) return;
|
|
11858
|
-
startEvent.preventDefault();
|
|
11859
|
-
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
11860
|
-
const startPointer = startEvent.clientY;
|
|
11861
|
-
const startScrollTop = el.scrollTop;
|
|
11862
|
-
const maxThumbOffset = el.clientHeight - vertical.thumbSize;
|
|
11863
|
-
const maxScrollTop = el.scrollHeight - el.clientHeight;
|
|
11864
|
-
if (maxThumbOffset <= 0 || maxScrollTop <= 0) return;
|
|
11865
|
-
const onPointerMove = (moveEvent) => {
|
|
11866
|
-
const delta = moveEvent.clientY - startPointer;
|
|
11867
|
-
el.scrollTop = startScrollTop + delta / maxThumbOffset * maxScrollTop;
|
|
11868
|
-
};
|
|
11869
|
-
const onPointerUp = () => {
|
|
11870
|
-
window.removeEventListener("pointermove", onPointerMove);
|
|
11871
|
-
window.removeEventListener("pointerup", onPointerUp);
|
|
11872
|
-
};
|
|
11873
|
-
window.addEventListener("pointermove", onPointerMove);
|
|
11874
|
-
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
11875
|
-
};
|
|
11876
|
-
const dragHorizontal = (startEvent) => {
|
|
11877
|
-
const el = scrollRef.current;
|
|
11878
|
-
if (!el || !horizontal.visible) return;
|
|
11879
|
-
startEvent.preventDefault();
|
|
11880
|
-
startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
|
|
11881
|
-
const startPointer = startEvent.clientX;
|
|
11882
|
-
const startScrollLeft = el.scrollLeft;
|
|
11883
|
-
const maxThumbOffset = el.clientWidth - horizontal.thumbSize;
|
|
11884
|
-
const maxScrollLeft = el.scrollWidth - el.clientWidth;
|
|
11885
|
-
if (maxThumbOffset <= 0 || maxScrollLeft <= 0) return;
|
|
11886
|
-
const onPointerMove = (moveEvent) => {
|
|
11887
|
-
const delta = moveEvent.clientX - startPointer;
|
|
11888
|
-
el.scrollLeft = startScrollLeft + delta / maxThumbOffset * maxScrollLeft;
|
|
11889
|
-
};
|
|
11890
|
-
const onPointerUp = () => {
|
|
11891
|
-
window.removeEventListener("pointermove", onPointerMove);
|
|
11892
|
-
window.removeEventListener("pointerup", onPointerUp);
|
|
11893
|
-
};
|
|
11894
|
-
window.addEventListener("pointermove", onPointerMove);
|
|
11895
|
-
window.addEventListener("pointerup", onPointerUp, { once: true });
|
|
11896
|
-
};
|
|
11897
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11898
|
-
vertical.visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11899
|
-
"div",
|
|
11900
|
-
{
|
|
11901
|
-
"aria-hidden": "true",
|
|
11902
|
-
className: "pointer-events-none absolute bottom-0 right-0 top-0 z-[1] w-[12px]",
|
|
11903
|
-
style: { bottom: horizontal.visible ? SCROLLBAR_SIZE : 0 },
|
|
11904
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11905
|
-
"div",
|
|
11906
|
-
{
|
|
11907
|
-
className: "pointer-events-auto absolute right-[2px] w-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
11908
|
-
style: {
|
|
11909
|
-
height: vertical.thumbSize,
|
|
11910
|
-
transform: `translateY(${vertical.thumbOffset}px)`
|
|
11911
|
-
},
|
|
11912
|
-
onPointerDown: dragVertical
|
|
11913
|
-
}
|
|
11914
|
-
)
|
|
11915
|
-
}
|
|
11916
|
-
),
|
|
11917
|
-
horizontal.visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11918
|
-
"div",
|
|
11919
|
-
{
|
|
11920
|
-
"aria-hidden": "true",
|
|
11921
|
-
className: "pointer-events-none absolute bottom-0 left-0 right-0 z-[1] h-[12px]",
|
|
11922
|
-
style: { right: vertical.visible ? SCROLLBAR_SIZE : 0 },
|
|
11923
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11924
|
-
"div",
|
|
11925
|
-
{
|
|
11926
|
-
className: "pointer-events-auto absolute bottom-[2px] h-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
|
|
11927
|
-
style: {
|
|
11928
|
-
width: horizontal.thumbSize,
|
|
11929
|
-
transform: `translateX(${horizontal.thumbOffset}px)`
|
|
11930
|
-
},
|
|
11931
|
-
onPointerDown: dragHorizontal
|
|
11932
|
-
}
|
|
11933
|
-
)
|
|
11934
|
-
}
|
|
11935
|
-
)
|
|
11936
|
-
] });
|
|
11937
|
-
}
|
|
11938
11983
|
var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
11939
11984
|
background = "frame",
|
|
11940
11985
|
scrollEndSpacing = false,
|
|
@@ -12007,7 +12052,7 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
|
|
|
12007
12052
|
style: gridStyle,
|
|
12008
12053
|
children: [
|
|
12009
12054
|
main,
|
|
12010
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12055
|
+
/* @__PURE__ */ jsxRuntime.jsx(OverlayScrollbars, { scrollRef })
|
|
12011
12056
|
]
|
|
12012
12057
|
}
|
|
12013
12058
|
);
|
|
@@ -13468,47 +13513,167 @@ function SCalendarBoard({
|
|
|
13468
13513
|
);
|
|
13469
13514
|
}
|
|
13470
13515
|
|
|
13471
|
-
// src/lib/
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
const
|
|
13476
|
-
|
|
13516
|
+
// src/lib/row-metrics.ts
|
|
13517
|
+
function createRowMetrics(count, estimate) {
|
|
13518
|
+
const safeCount = Math.max(0, Math.floor(count));
|
|
13519
|
+
const safeEstimate = Math.max(1, estimate);
|
|
13520
|
+
const metrics = {
|
|
13521
|
+
sizes: new Array(safeCount).fill(safeEstimate),
|
|
13522
|
+
measured: new Array(safeCount).fill(false),
|
|
13523
|
+
offsets: [],
|
|
13524
|
+
estimate: safeEstimate,
|
|
13525
|
+
measuredCount: 0,
|
|
13526
|
+
measuredTotal: 0,
|
|
13527
|
+
dirtyFrom: 0
|
|
13528
|
+
};
|
|
13529
|
+
rebuildOffsets(metrics);
|
|
13530
|
+
return metrics;
|
|
13477
13531
|
}
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13532
|
+
function resizeRowMetrics(metrics, count) {
|
|
13533
|
+
const next = Math.max(0, Math.floor(count));
|
|
13534
|
+
const prev = metrics.sizes.length;
|
|
13535
|
+
if (next === prev) return;
|
|
13536
|
+
if (next < prev) {
|
|
13537
|
+
for (let i = next; i < prev; i++) {
|
|
13538
|
+
if (metrics.measured[i]) {
|
|
13539
|
+
metrics.measuredCount--;
|
|
13540
|
+
metrics.measuredTotal -= metrics.sizes[i];
|
|
13541
|
+
}
|
|
13542
|
+
}
|
|
13543
|
+
metrics.sizes.length = next;
|
|
13544
|
+
metrics.measured.length = next;
|
|
13545
|
+
} else {
|
|
13546
|
+
for (let i = prev; i < next; i++) {
|
|
13547
|
+
metrics.sizes.push(metrics.estimate);
|
|
13548
|
+
metrics.measured.push(false);
|
|
13549
|
+
}
|
|
13490
13550
|
}
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
}
|
|
13511
|
-
|
|
13551
|
+
markDirty(metrics, Math.min(prev, next));
|
|
13552
|
+
}
|
|
13553
|
+
function resetRowMetrics(metrics, count) {
|
|
13554
|
+
const fresh = createRowMetrics(count, metrics.estimate);
|
|
13555
|
+
metrics.sizes = fresh.sizes;
|
|
13556
|
+
metrics.measured = fresh.measured;
|
|
13557
|
+
metrics.offsets = fresh.offsets;
|
|
13558
|
+
metrics.measuredCount = 0;
|
|
13559
|
+
metrics.measuredTotal = 0;
|
|
13560
|
+
metrics.dirtyFrom = Infinity;
|
|
13561
|
+
}
|
|
13562
|
+
function setRowSize(metrics, index, size) {
|
|
13563
|
+
if (index < 0 || index >= metrics.sizes.length) return false;
|
|
13564
|
+
const next = Math.max(1, Math.round(size));
|
|
13565
|
+
const wasMeasured = metrics.measured[index];
|
|
13566
|
+
const prev = metrics.sizes[index];
|
|
13567
|
+
if (wasMeasured && prev === next) return false;
|
|
13568
|
+
if (wasMeasured) {
|
|
13569
|
+
metrics.measuredTotal += next - prev;
|
|
13570
|
+
} else {
|
|
13571
|
+
metrics.measured[index] = true;
|
|
13572
|
+
metrics.measuredCount++;
|
|
13573
|
+
metrics.measuredTotal += next;
|
|
13574
|
+
}
|
|
13575
|
+
metrics.sizes[index] = next;
|
|
13576
|
+
let changedFrom = prev === next ? Infinity : index;
|
|
13577
|
+
const average = Math.max(1, Math.round(metrics.measuredTotal / metrics.measuredCount));
|
|
13578
|
+
if (average !== metrics.estimate) {
|
|
13579
|
+
metrics.estimate = average;
|
|
13580
|
+
for (let i = 0; i < metrics.sizes.length; i++) {
|
|
13581
|
+
if (metrics.measured[i] || metrics.sizes[i] === average) continue;
|
|
13582
|
+
metrics.sizes[i] = average;
|
|
13583
|
+
if (i < changedFrom) changedFrom = i;
|
|
13584
|
+
}
|
|
13585
|
+
}
|
|
13586
|
+
if (changedFrom === Infinity) return false;
|
|
13587
|
+
markDirty(metrics, changedFrom);
|
|
13588
|
+
return true;
|
|
13589
|
+
}
|
|
13590
|
+
function markDirty(metrics, from) {
|
|
13591
|
+
metrics.dirtyFrom = Math.min(metrics.dirtyFrom, Math.max(0, from));
|
|
13592
|
+
}
|
|
13593
|
+
function rebuildOffsets(metrics) {
|
|
13594
|
+
const count = metrics.sizes.length;
|
|
13595
|
+
const stale = metrics.offsets.length !== count + 1;
|
|
13596
|
+
if (!stale && metrics.dirtyFrom === Infinity) return;
|
|
13597
|
+
const start = stale ? 0 : Math.min(metrics.dirtyFrom, count);
|
|
13598
|
+
const acc0 = start === 0 ? 0 : metrics.offsets[start] ?? 0;
|
|
13599
|
+
metrics.offsets.length = count + 1;
|
|
13600
|
+
let acc = acc0;
|
|
13601
|
+
for (let i = start; i < count; i++) {
|
|
13602
|
+
metrics.offsets[i] = acc;
|
|
13603
|
+
acc += metrics.sizes[i];
|
|
13604
|
+
}
|
|
13605
|
+
metrics.offsets[count] = acc;
|
|
13606
|
+
metrics.dirtyFrom = Infinity;
|
|
13607
|
+
}
|
|
13608
|
+
function totalSize(metrics) {
|
|
13609
|
+
rebuildOffsets(metrics);
|
|
13610
|
+
return metrics.offsets[metrics.sizes.length] ?? 0;
|
|
13611
|
+
}
|
|
13612
|
+
function offsetOf(metrics, index) {
|
|
13613
|
+
rebuildOffsets(metrics);
|
|
13614
|
+
const clamped = Math.max(0, Math.min(Math.floor(index), metrics.sizes.length));
|
|
13615
|
+
return metrics.offsets[clamped] ?? 0;
|
|
13616
|
+
}
|
|
13617
|
+
function sizeOf(metrics, index) {
|
|
13618
|
+
if (index < 0 || index >= metrics.sizes.length) return metrics.estimate;
|
|
13619
|
+
return metrics.sizes[index];
|
|
13620
|
+
}
|
|
13621
|
+
function indexAtOffset(metrics, y) {
|
|
13622
|
+
rebuildOffsets(metrics);
|
|
13623
|
+
const count = metrics.sizes.length;
|
|
13624
|
+
if (count === 0) return 0;
|
|
13625
|
+
const target = Math.max(0, y);
|
|
13626
|
+
let lo = 0;
|
|
13627
|
+
let hi = count - 1;
|
|
13628
|
+
while (lo < hi) {
|
|
13629
|
+
const mid = lo + hi + 1 >> 1;
|
|
13630
|
+
if (metrics.offsets[mid] <= target) lo = mid;
|
|
13631
|
+
else hi = mid - 1;
|
|
13632
|
+
}
|
|
13633
|
+
return lo;
|
|
13634
|
+
}
|
|
13635
|
+
|
|
13636
|
+
// src/lib/floating-height.ts
|
|
13637
|
+
var POPOVER_AVAILABLE_HEIGHT = "var(--radix-popover-content-available-height)";
|
|
13638
|
+
function clampToAvailableHeight(value, availableHeight) {
|
|
13639
|
+
if (value == null || value === "") return availableHeight;
|
|
13640
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
13641
|
+
return `min(${css}, ${availableHeight})`;
|
|
13642
|
+
}
|
|
13643
|
+
var FONT = {
|
|
13644
|
+
sm: {
|
|
13645
|
+
fontSize: 12,
|
|
13646
|
+
lineHeight: 20,
|
|
13647
|
+
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
13648
|
+
gap: "var(--cmp-textinput-sm-gap)"
|
|
13649
|
+
},
|
|
13650
|
+
md: {
|
|
13651
|
+
fontSize: 14,
|
|
13652
|
+
lineHeight: 24,
|
|
13653
|
+
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
13654
|
+
gap: "var(--cmp-textinput-md-gap)"
|
|
13655
|
+
}
|
|
13656
|
+
};
|
|
13657
|
+
var SSearchInput = /* @__PURE__ */ react.forwardRef(function SSearchInput2({
|
|
13658
|
+
value,
|
|
13659
|
+
onValueChange,
|
|
13660
|
+
onChange,
|
|
13661
|
+
onSearch,
|
|
13662
|
+
size = "sm",
|
|
13663
|
+
placeholder = "\uACB0\uACFC \uB0B4 \uAC80\uC0C9",
|
|
13664
|
+
clearable = false,
|
|
13665
|
+
disabled = false,
|
|
13666
|
+
width,
|
|
13667
|
+
focused,
|
|
13668
|
+
hovered,
|
|
13669
|
+
inputClassName,
|
|
13670
|
+
inputStyle,
|
|
13671
|
+
className,
|
|
13672
|
+
style,
|
|
13673
|
+
onKeyDown,
|
|
13674
|
+
...rest
|
|
13675
|
+
}, ref) {
|
|
13676
|
+
const f = FONT[size];
|
|
13512
13677
|
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
13513
13678
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13514
13679
|
SField,
|
|
@@ -13636,126 +13801,6 @@ var OPTION_ROW_HEIGHT = 28;
|
|
|
13636
13801
|
var DEFAULT_VIRTUAL_BUFFER = 10;
|
|
13637
13802
|
var DEFAULT_REACH_END_THRESHOLD = 10;
|
|
13638
13803
|
var DEFAULT_SEARCH_DEBOUNCE = 300;
|
|
13639
|
-
|
|
13640
|
-
// src/components/SSelect/row-metrics.ts
|
|
13641
|
-
function createRowMetrics(count, estimate) {
|
|
13642
|
-
const safeCount = Math.max(0, Math.floor(count));
|
|
13643
|
-
const safeEstimate = Math.max(1, estimate);
|
|
13644
|
-
const metrics = {
|
|
13645
|
-
sizes: new Array(safeCount).fill(safeEstimate),
|
|
13646
|
-
measured: new Array(safeCount).fill(false),
|
|
13647
|
-
offsets: [],
|
|
13648
|
-
estimate: safeEstimate,
|
|
13649
|
-
measuredCount: 0,
|
|
13650
|
-
measuredTotal: 0,
|
|
13651
|
-
dirtyFrom: 0
|
|
13652
|
-
};
|
|
13653
|
-
rebuildOffsets(metrics);
|
|
13654
|
-
return metrics;
|
|
13655
|
-
}
|
|
13656
|
-
function resizeRowMetrics(metrics, count) {
|
|
13657
|
-
const next = Math.max(0, Math.floor(count));
|
|
13658
|
-
const prev = metrics.sizes.length;
|
|
13659
|
-
if (next === prev) return;
|
|
13660
|
-
if (next < prev) {
|
|
13661
|
-
for (let i = next; i < prev; i++) {
|
|
13662
|
-
if (metrics.measured[i]) {
|
|
13663
|
-
metrics.measuredCount--;
|
|
13664
|
-
metrics.measuredTotal -= metrics.sizes[i];
|
|
13665
|
-
}
|
|
13666
|
-
}
|
|
13667
|
-
metrics.sizes.length = next;
|
|
13668
|
-
metrics.measured.length = next;
|
|
13669
|
-
} else {
|
|
13670
|
-
for (let i = prev; i < next; i++) {
|
|
13671
|
-
metrics.sizes.push(metrics.estimate);
|
|
13672
|
-
metrics.measured.push(false);
|
|
13673
|
-
}
|
|
13674
|
-
}
|
|
13675
|
-
markDirty(metrics, Math.min(prev, next));
|
|
13676
|
-
}
|
|
13677
|
-
function resetRowMetrics(metrics, count) {
|
|
13678
|
-
const fresh = createRowMetrics(count, metrics.estimate);
|
|
13679
|
-
metrics.sizes = fresh.sizes;
|
|
13680
|
-
metrics.measured = fresh.measured;
|
|
13681
|
-
metrics.offsets = fresh.offsets;
|
|
13682
|
-
metrics.measuredCount = 0;
|
|
13683
|
-
metrics.measuredTotal = 0;
|
|
13684
|
-
metrics.dirtyFrom = Infinity;
|
|
13685
|
-
}
|
|
13686
|
-
function setRowSize(metrics, index, size) {
|
|
13687
|
-
if (index < 0 || index >= metrics.sizes.length) return false;
|
|
13688
|
-
const next = Math.max(1, Math.round(size));
|
|
13689
|
-
const wasMeasured = metrics.measured[index];
|
|
13690
|
-
const prev = metrics.sizes[index];
|
|
13691
|
-
if (wasMeasured && prev === next) return false;
|
|
13692
|
-
if (wasMeasured) {
|
|
13693
|
-
metrics.measuredTotal += next - prev;
|
|
13694
|
-
} else {
|
|
13695
|
-
metrics.measured[index] = true;
|
|
13696
|
-
metrics.measuredCount++;
|
|
13697
|
-
metrics.measuredTotal += next;
|
|
13698
|
-
}
|
|
13699
|
-
metrics.sizes[index] = next;
|
|
13700
|
-
let changedFrom = prev === next ? Infinity : index;
|
|
13701
|
-
const average = Math.max(1, Math.round(metrics.measuredTotal / metrics.measuredCount));
|
|
13702
|
-
if (average !== metrics.estimate) {
|
|
13703
|
-
metrics.estimate = average;
|
|
13704
|
-
for (let i = 0; i < metrics.sizes.length; i++) {
|
|
13705
|
-
if (metrics.measured[i] || metrics.sizes[i] === average) continue;
|
|
13706
|
-
metrics.sizes[i] = average;
|
|
13707
|
-
if (i < changedFrom) changedFrom = i;
|
|
13708
|
-
}
|
|
13709
|
-
}
|
|
13710
|
-
if (changedFrom === Infinity) return false;
|
|
13711
|
-
markDirty(metrics, changedFrom);
|
|
13712
|
-
return true;
|
|
13713
|
-
}
|
|
13714
|
-
function markDirty(metrics, from) {
|
|
13715
|
-
metrics.dirtyFrom = Math.min(metrics.dirtyFrom, Math.max(0, from));
|
|
13716
|
-
}
|
|
13717
|
-
function rebuildOffsets(metrics) {
|
|
13718
|
-
const count = metrics.sizes.length;
|
|
13719
|
-
const stale = metrics.offsets.length !== count + 1;
|
|
13720
|
-
if (!stale && metrics.dirtyFrom === Infinity) return;
|
|
13721
|
-
const start = stale ? 0 : Math.min(metrics.dirtyFrom, count);
|
|
13722
|
-
const acc0 = start === 0 ? 0 : metrics.offsets[start] ?? 0;
|
|
13723
|
-
metrics.offsets.length = count + 1;
|
|
13724
|
-
let acc = acc0;
|
|
13725
|
-
for (let i = start; i < count; i++) {
|
|
13726
|
-
metrics.offsets[i] = acc;
|
|
13727
|
-
acc += metrics.sizes[i];
|
|
13728
|
-
}
|
|
13729
|
-
metrics.offsets[count] = acc;
|
|
13730
|
-
metrics.dirtyFrom = Infinity;
|
|
13731
|
-
}
|
|
13732
|
-
function totalSize(metrics) {
|
|
13733
|
-
rebuildOffsets(metrics);
|
|
13734
|
-
return metrics.offsets[metrics.sizes.length] ?? 0;
|
|
13735
|
-
}
|
|
13736
|
-
function offsetOf(metrics, index) {
|
|
13737
|
-
rebuildOffsets(metrics);
|
|
13738
|
-
const clamped = Math.max(0, Math.min(Math.floor(index), metrics.sizes.length));
|
|
13739
|
-
return metrics.offsets[clamped] ?? 0;
|
|
13740
|
-
}
|
|
13741
|
-
function sizeOf(metrics, index) {
|
|
13742
|
-
if (index < 0 || index >= metrics.sizes.length) return metrics.estimate;
|
|
13743
|
-
return metrics.sizes[index];
|
|
13744
|
-
}
|
|
13745
|
-
function indexAtOffset(metrics, y) {
|
|
13746
|
-
rebuildOffsets(metrics);
|
|
13747
|
-
const count = metrics.sizes.length;
|
|
13748
|
-
if (count === 0) return 0;
|
|
13749
|
-
const target = Math.max(0, y);
|
|
13750
|
-
let lo = 0;
|
|
13751
|
-
let hi = count - 1;
|
|
13752
|
-
while (lo < hi) {
|
|
13753
|
-
const mid = lo + hi + 1 >> 1;
|
|
13754
|
-
if (metrics.offsets[mid] <= target) lo = mid;
|
|
13755
|
-
else hi = mid - 1;
|
|
13756
|
-
}
|
|
13757
|
-
return lo;
|
|
13758
|
-
}
|
|
13759
13804
|
var SEARCH_THRESHOLD = 11;
|
|
13760
13805
|
var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
13761
13806
|
value,
|
|
@@ -14654,6 +14699,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14654
14699
|
rows = [],
|
|
14655
14700
|
rowKey = "id",
|
|
14656
14701
|
selectable = false,
|
|
14702
|
+
isRowSelectable,
|
|
14657
14703
|
selected = [],
|
|
14658
14704
|
onSelectedChange,
|
|
14659
14705
|
sort = null,
|
|
@@ -14680,6 +14726,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14680
14726
|
rowHeight,
|
|
14681
14727
|
virtualBuffer = 5,
|
|
14682
14728
|
virtualEndThreshold = 10,
|
|
14729
|
+
onScroll,
|
|
14683
14730
|
onVirtualUpdate,
|
|
14684
14731
|
onVirtualReachEnd,
|
|
14685
14732
|
tableId,
|
|
@@ -14763,16 +14810,21 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14763
14810
|
(row) => selectedKeys.has(row[rowKey]),
|
|
14764
14811
|
[selectedKeys, rowKey]
|
|
14765
14812
|
);
|
|
14813
|
+
const canSelectRow = react.useCallback(
|
|
14814
|
+
(row) => isRowSelectable ? isRowSelectable(row) : true,
|
|
14815
|
+
[isRowSelectable]
|
|
14816
|
+
);
|
|
14766
14817
|
const getIsAllChecked = react.useCallback(
|
|
14767
14818
|
(rws) => {
|
|
14768
|
-
const
|
|
14819
|
+
const targets = rws.filter(canSelectRow);
|
|
14820
|
+
const total = targets.length;
|
|
14769
14821
|
if (total === 0) return false;
|
|
14770
|
-
const cnt =
|
|
14822
|
+
const cnt = targets.filter((r) => selectedKeys.has(r[rowKey])).length;
|
|
14771
14823
|
if (cnt === 0) return false;
|
|
14772
14824
|
if (cnt === total) return true;
|
|
14773
14825
|
return null;
|
|
14774
14826
|
},
|
|
14775
|
-
[selectedKeys, rowKey]
|
|
14827
|
+
[selectedKeys, rowKey, canSelectRow]
|
|
14776
14828
|
);
|
|
14777
14829
|
const [currentPage, setCurrentPage] = react.useState(pagination?.page ?? 1);
|
|
14778
14830
|
const [innerRowsPerPage, setInnerRowsPerPage] = react.useState(pagination?.rowsPerPage ?? 10);
|
|
@@ -14787,8 +14839,23 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14787
14839
|
const [headerGutter, setHeaderGutter] = react.useState(0);
|
|
14788
14840
|
const [vsRange, setVsRange] = react.useState({ start: 0, end: 0 });
|
|
14789
14841
|
const lastReachEndRef = react.useRef(-1);
|
|
14790
|
-
const cbRef = react.useRef({ onVirtualUpdate, onVirtualReachEnd });
|
|
14791
|
-
cbRef.current = { onVirtualUpdate, onVirtualReachEnd };
|
|
14842
|
+
const cbRef = react.useRef({ onVirtualUpdate, onVirtualReachEnd, onScroll });
|
|
14843
|
+
cbRef.current = { onVirtualUpdate, onVirtualReachEnd, onScroll };
|
|
14844
|
+
const metricsRef = react.useRef(null);
|
|
14845
|
+
metricsRef.current ?? (metricsRef.current = createRowMetrics(0, effectiveRowHeight));
|
|
14846
|
+
const metrics = metricsRef.current;
|
|
14847
|
+
const measuredKeyRef = react.useRef("");
|
|
14848
|
+
const pendingRowRef = react.useRef(null);
|
|
14849
|
+
const pinnedTopRef = react.useRef(-1);
|
|
14850
|
+
const lastEstimateRef = react.useRef(effectiveRowHeight);
|
|
14851
|
+
if (lastEstimateRef.current !== effectiveRowHeight) {
|
|
14852
|
+
lastEstimateRef.current = effectiveRowHeight;
|
|
14853
|
+
metrics.estimate = Math.max(1, effectiveRowHeight);
|
|
14854
|
+
resetRowMetrics(metrics, rowCount);
|
|
14855
|
+
measuredKeyRef.current = "";
|
|
14856
|
+
} else {
|
|
14857
|
+
resizeRowMetrics(metrics, rowCount);
|
|
14858
|
+
}
|
|
14792
14859
|
const [scrolledLeft, setScrolledLeft] = react.useState(false);
|
|
14793
14860
|
const [scrolledRight, setScrolledRight] = react.useState(false);
|
|
14794
14861
|
const setRowCount = react.useCallback((count) => {
|
|
@@ -14798,13 +14865,16 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14798
14865
|
}, []);
|
|
14799
14866
|
const calcRange = react.useCallback(
|
|
14800
14867
|
(scrollTop, containerHeight) => {
|
|
14801
|
-
const
|
|
14868
|
+
const m = metricsRef.current;
|
|
14869
|
+
if (m == null) return { start: 0, end: 0 };
|
|
14802
14870
|
const buf = Math.max(0, Math.floor(virtualBuffer));
|
|
14803
|
-
const
|
|
14804
|
-
const
|
|
14805
|
-
|
|
14871
|
+
const viewTop = Math.max(0, scrollTop);
|
|
14872
|
+
const viewBottom = viewTop + Math.max(0, containerHeight);
|
|
14873
|
+
const start = Math.max(0, indexAtOffset(m, viewTop) - buf);
|
|
14874
|
+
const end = Math.min(rowCount, indexAtOffset(m, viewBottom) + 1 + buf);
|
|
14875
|
+
return { start, end };
|
|
14806
14876
|
},
|
|
14807
|
-
[
|
|
14877
|
+
[virtualBuffer, rowCount]
|
|
14808
14878
|
);
|
|
14809
14879
|
const handleScroll = react.useCallback(() => {
|
|
14810
14880
|
const el = scrollRef.current;
|
|
@@ -14822,9 +14892,59 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14822
14892
|
setVsRange((prev) => prev.start === start && prev.end === end ? prev : { start, end });
|
|
14823
14893
|
}
|
|
14824
14894
|
}, [virtualScroll, calcRange]);
|
|
14895
|
+
const handleScrollEvent = react.useCallback(
|
|
14896
|
+
(event) => {
|
|
14897
|
+
pendingRowRef.current = null;
|
|
14898
|
+
pinnedTopRef.current = -1;
|
|
14899
|
+
handleScroll();
|
|
14900
|
+
cbRef.current.onScroll?.(event);
|
|
14901
|
+
},
|
|
14902
|
+
[handleScroll]
|
|
14903
|
+
);
|
|
14825
14904
|
react.useEffect(() => {
|
|
14826
14905
|
handleScroll();
|
|
14827
14906
|
}, [handleScroll, rowCount, columnWidths, loading2, height]);
|
|
14907
|
+
const handleScrollRef = react.useRef(handleScroll);
|
|
14908
|
+
handleScrollRef.current = handleScroll;
|
|
14909
|
+
useIsomorphicLayoutEffect(() => {
|
|
14910
|
+
if (!virtualScroll) return;
|
|
14911
|
+
const el = scrollRef.current;
|
|
14912
|
+
const m = metricsRef.current;
|
|
14913
|
+
if (!el || m == null) return;
|
|
14914
|
+
const pending2 = pendingRowRef.current;
|
|
14915
|
+
const key = `${vsRange.start}:${vsRange.end}:${rowCount}`;
|
|
14916
|
+
const alreadyMeasured = measuredKeyRef.current === key;
|
|
14917
|
+
if (alreadyMeasured && pending2 == null) return;
|
|
14918
|
+
measuredKeyRef.current = key;
|
|
14919
|
+
const anchor = vsRange.start;
|
|
14920
|
+
const anchorBefore = offsetOf(m, anchor);
|
|
14921
|
+
let changed = false;
|
|
14922
|
+
if (!alreadyMeasured) {
|
|
14923
|
+
for (const tr of el.querySelectorAll("tr[data-row-index]")) {
|
|
14924
|
+
const index = Number(tr.dataset.rowIndex);
|
|
14925
|
+
if (!Number.isInteger(index)) continue;
|
|
14926
|
+
const h = tr.offsetHeight;
|
|
14927
|
+
if (h <= 0) continue;
|
|
14928
|
+
if (setRowSize(m, index, h)) changed = true;
|
|
14929
|
+
}
|
|
14930
|
+
}
|
|
14931
|
+
if (pending2 != null) {
|
|
14932
|
+
const top = offsetOf(m, pending2);
|
|
14933
|
+
if (pinnedTopRef.current === top) {
|
|
14934
|
+
pendingRowRef.current = null;
|
|
14935
|
+
pinnedTopRef.current = -1;
|
|
14936
|
+
return;
|
|
14937
|
+
}
|
|
14938
|
+
pinnedTopRef.current = top;
|
|
14939
|
+
el.scrollTop = top;
|
|
14940
|
+
handleScrollRef.current();
|
|
14941
|
+
return;
|
|
14942
|
+
}
|
|
14943
|
+
if (!changed) return;
|
|
14944
|
+
const delta = offsetOf(m, anchor) - anchorBefore;
|
|
14945
|
+
if (delta !== 0 && el.scrollTop > 0) el.scrollTop += delta;
|
|
14946
|
+
handleScrollRef.current();
|
|
14947
|
+
});
|
|
14828
14948
|
react.useEffect(() => {
|
|
14829
14949
|
if (!virtualScroll) return;
|
|
14830
14950
|
cbRef.current.onVirtualUpdate?.({ from: vsRange.start, to: vsRange.end });
|
|
@@ -14873,15 +14993,42 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14873
14993
|
};
|
|
14874
14994
|
},
|
|
14875
14995
|
getStickyStyle,
|
|
14996
|
+
getScrollElement: () => scrollRef.current,
|
|
14997
|
+
getFirstVisibleRow: () => {
|
|
14998
|
+
const el = scrollRef.current;
|
|
14999
|
+
const m = metricsRef.current;
|
|
15000
|
+
if (!el) return 0;
|
|
15001
|
+
if (virtualScroll && m != null) return indexAtOffset(m, el.scrollTop);
|
|
15002
|
+
const top = el.scrollTop;
|
|
15003
|
+
for (const tr of el.querySelectorAll("tr[data-row-index]")) {
|
|
15004
|
+
if (tr.offsetTop + tr.offsetHeight > top) return Number(tr.dataset.rowIndex) || 0;
|
|
15005
|
+
}
|
|
15006
|
+
return 0;
|
|
15007
|
+
},
|
|
15008
|
+
scrollToRow: (index) => {
|
|
15009
|
+
const el = scrollRef.current;
|
|
15010
|
+
const m = metricsRef.current;
|
|
15011
|
+
if (!el) return;
|
|
15012
|
+
const target = Math.min(Math.max(0, Math.floor(index)), Math.max(0, rowCount - 1));
|
|
15013
|
+
if (virtualScroll && m != null) {
|
|
15014
|
+
pendingRowRef.current = target;
|
|
15015
|
+
pinnedTopRef.current = -1;
|
|
15016
|
+
el.scrollTop = offsetOf(m, target);
|
|
15017
|
+
return;
|
|
15018
|
+
}
|
|
15019
|
+
const tr = el.querySelector(`tr[data-row-index="${target}"]`);
|
|
15020
|
+
if (tr) el.scrollTop = tr.offsetTop;
|
|
15021
|
+
},
|
|
14876
15022
|
setRowCount,
|
|
14877
15023
|
updateRowSelect: (row) => {
|
|
15024
|
+
if (!canSelectRow(row)) return;
|
|
14878
15025
|
if (selectedKeys.has(row[rowKey]))
|
|
14879
15026
|
onSelectedChange?.(selected.filter((r) => r[rowKey] !== row[rowKey]));
|
|
14880
15027
|
else onSelectedChange?.([...selected, row]);
|
|
14881
15028
|
},
|
|
14882
15029
|
toggleSelectAll: (checked, rws) => {
|
|
14883
15030
|
if (checked) {
|
|
14884
|
-
const add = rws.filter((r) => !selectedKeys.has(r[rowKey]));
|
|
15031
|
+
const add = rws.filter((r) => canSelectRow(r) && !selectedKeys.has(r[rowKey]));
|
|
14885
15032
|
onSelectedChange?.([...selected, ...add]);
|
|
14886
15033
|
} else {
|
|
14887
15034
|
const keys = new Set(rws.map((r) => r[rowKey]));
|
|
@@ -14892,8 +15039,11 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14892
15039
|
[
|
|
14893
15040
|
isRowSelected,
|
|
14894
15041
|
getIsAllChecked,
|
|
15042
|
+
canSelectRow,
|
|
14895
15043
|
getStickyStyle,
|
|
14896
15044
|
setRowCount,
|
|
15045
|
+
virtualScroll,
|
|
15046
|
+
rowCount,
|
|
14897
15047
|
internalPagination,
|
|
14898
15048
|
pagination,
|
|
14899
15049
|
currentPage,
|
|
@@ -14944,12 +15094,13 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14944
15094
|
if (virtualScroll) {
|
|
14945
15095
|
bodyRows = rows.slice(vsRange.start, vsRange.end);
|
|
14946
15096
|
rowOffset = vsRange.start;
|
|
14947
|
-
topSpacer = vsRange.start
|
|
14948
|
-
bottomSpacer = Math.max(0, (
|
|
15097
|
+
topSpacer = offsetOf(metrics, vsRange.start);
|
|
15098
|
+
bottomSpacer = Math.max(0, totalSize(metrics) - offsetOf(metrics, vsRange.end));
|
|
14949
15099
|
} else if (pageInfo) {
|
|
14950
15100
|
bodyRows = rows.slice(pageInfo.startIndex, pageInfo.endIndex);
|
|
14951
15101
|
rowOffset = pageInfo.startIndex;
|
|
14952
15102
|
}
|
|
15103
|
+
const hasSelectableRow = bodyRows.some(canSelectRow);
|
|
14953
15104
|
const isNoData = rowCount === 0 && !loading2;
|
|
14954
15105
|
const showNoDataSlot = isNoData && emptySlot != null;
|
|
14955
15106
|
const showPagination = !virtualScroll && (pagination != null || internalPagination);
|
|
@@ -14977,17 +15128,18 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
14977
15128
|
const pageKeys = new Set(bodyRows.map((r) => r[rowKey]));
|
|
14978
15129
|
onSelectedChange?.(selected.filter((r) => !pageKeys.has(r[rowKey])));
|
|
14979
15130
|
} else {
|
|
14980
|
-
const add = bodyRows.filter((r) => !selectedKeys.has(r[rowKey]));
|
|
15131
|
+
const add = bodyRows.filter((r) => canSelectRow(r) && !selectedKeys.has(r[rowKey]));
|
|
14981
15132
|
onSelectedChange?.([...selected, ...add]);
|
|
14982
15133
|
}
|
|
14983
15134
|
};
|
|
14984
15135
|
const toggleRow = (row, index) => {
|
|
15136
|
+
if (!canSelectRow(row)) return;
|
|
14985
15137
|
const anchor = rangeAnchorRef.current;
|
|
14986
15138
|
const anchorAlive = anchor != null && anchor.index !== index && rows[anchor.index]?.[rowKey] === anchor.key;
|
|
14987
15139
|
if (shiftPressedRef.current && anchor != null && anchorAlive) {
|
|
14988
15140
|
const [from, to] = anchor.index < index ? [anchor.index, index] : [index, anchor.index];
|
|
14989
15141
|
const shouldSelect = selectedKeys.has(anchor.key);
|
|
14990
|
-
const range = rows.slice(from, to + 1);
|
|
15142
|
+
const range = rows.slice(from, to + 1).filter(canSelectRow);
|
|
14991
15143
|
if (shouldSelect) {
|
|
14992
15144
|
const add = range.filter((r) => !selectedKeys.has(r[rowKey]));
|
|
14993
15145
|
onSelectedChange?.([...selected, ...add]);
|
|
@@ -15141,7 +15293,14 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15141
15293
|
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
15142
15294
|
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
15143
15295
|
},
|
|
15144
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15296
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15297
|
+
SCheckbox,
|
|
15298
|
+
{
|
|
15299
|
+
value: headerCheck,
|
|
15300
|
+
disabled: !hasSelectableRow,
|
|
15301
|
+
onValueChange: toggleAll
|
|
15302
|
+
}
|
|
15303
|
+
) })
|
|
15145
15304
|
}
|
|
15146
15305
|
),
|
|
15147
15306
|
headerGroupInfo.cells.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -15183,7 +15342,14 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15183
15342
|
maxWidth: SELECTABLE_COLUMN_WIDTH
|
|
15184
15343
|
},
|
|
15185
15344
|
children: [
|
|
15186
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15345
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15346
|
+
SCheckbox,
|
|
15347
|
+
{
|
|
15348
|
+
value: headerCheck,
|
|
15349
|
+
disabled: !hasSelectableRow,
|
|
15350
|
+
onValueChange: toggleAll
|
|
15351
|
+
}
|
|
15352
|
+
) }),
|
|
15187
15353
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15188
15354
|
"span",
|
|
15189
15355
|
{
|
|
@@ -15310,7 +15476,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15310
15476
|
"div",
|
|
15311
15477
|
{
|
|
15312
15478
|
ref: scrollRef,
|
|
15313
|
-
onScroll:
|
|
15479
|
+
onScroll: handleScrollEvent,
|
|
15314
15480
|
className: cn(
|
|
15315
15481
|
bodyScrollClass,
|
|
15316
15482
|
// 원본 sd-table__scroll-container--loading/--no-data: 로딩·데이터 없음 시 스크롤 차단
|
|
@@ -15331,6 +15497,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15331
15497
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15332
15498
|
"tr",
|
|
15333
15499
|
{
|
|
15500
|
+
"data-row-index": rowOffset + ri,
|
|
15334
15501
|
onClick: () => onRowClick?.(row),
|
|
15335
15502
|
className: cn(
|
|
15336
15503
|
"group/table-row",
|
|
@@ -15363,6 +15530,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15363
15530
|
SCheckbox,
|
|
15364
15531
|
{
|
|
15365
15532
|
value: isSel,
|
|
15533
|
+
disabled: !canSelectRow(row),
|
|
15366
15534
|
onValueChange: () => toggleRow(row, rowOffset + ri)
|
|
15367
15535
|
}
|
|
15368
15536
|
) })
|
|
@@ -15480,15 +15648,20 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
|
|
|
15480
15648
|
var COUNT_NULL = "var(--cmp-table-bar-count-null)";
|
|
15481
15649
|
var totalColor = (n) => n > 0 ? "var(--cmp-table-bar-count-total)" : COUNT_NULL;
|
|
15482
15650
|
var selectedColor = (n) => n > 0 ? "var(--color-brilliantblue-75)" : COUNT_NULL;
|
|
15483
|
-
var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, selected, actions, rightActions, className, ...rest }, ref) {
|
|
15651
|
+
var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ title, total, selected, actions, rightActions, className, ...rest }, ref) {
|
|
15484
15652
|
const hasTotal = total != null;
|
|
15485
15653
|
const hasSelected = selected != null;
|
|
15486
15654
|
const hasCount = hasTotal || hasSelected;
|
|
15655
|
+
const hasTitle = title != null;
|
|
15656
|
+
const hasLeading = hasTitle || hasCount;
|
|
15657
|
+
const titleId = react.useId();
|
|
15658
|
+
const isToolbar = Boolean(actions || rightActions);
|
|
15487
15659
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15488
15660
|
"div",
|
|
15489
15661
|
{
|
|
15490
15662
|
ref,
|
|
15491
|
-
role:
|
|
15663
|
+
role: isToolbar ? "toolbar" : void 0,
|
|
15664
|
+
"aria-labelledby": isToolbar && hasTitle ? titleId : void 0,
|
|
15492
15665
|
className: cn(
|
|
15493
15666
|
"flex w-full items-center gap-[var(--cmp-table-bar-section-gap)] px-[var(--sys-space-table-padding-md)]",
|
|
15494
15667
|
"h-[var(--cmp-table-bar-height)] shrink-0",
|
|
@@ -15497,6 +15670,14 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
|
|
|
15497
15670
|
),
|
|
15498
15671
|
...rest,
|
|
15499
15672
|
children: [
|
|
15673
|
+
hasTitle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15674
|
+
"span",
|
|
15675
|
+
{
|
|
15676
|
+
id: titleId,
|
|
15677
|
+
className: "typo-table-accent whitespace-nowrap text-[var(--sys-color-fg-primary)]",
|
|
15678
|
+
children: title
|
|
15679
|
+
}
|
|
15680
|
+
),
|
|
15500
15681
|
hasCount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[var(--cmp-table-content-gap)]", children: [
|
|
15501
15682
|
hasTotal && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "typo-table-accent whitespace-nowrap text-[var(--sys-color-fg-primary)]", children: [
|
|
15502
15683
|
"\uCD1D ",
|
|
@@ -15517,7 +15698,7 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
|
|
|
15517
15698
|
] })
|
|
15518
15699
|
] }),
|
|
15519
15700
|
actions && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[var(--cmp-table-bar-section-gap)] has-[>div:empty]:hidden", children: [
|
|
15520
|
-
|
|
15701
|
+
hasLeading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15521
15702
|
SDivider,
|
|
15522
15703
|
{
|
|
15523
15704
|
vertical: true,
|
|
@@ -18168,10 +18349,10 @@ function ChartLegend({ items, align = "center", activeIndex, className }) {
|
|
|
18168
18349
|
"li",
|
|
18169
18350
|
{
|
|
18170
18351
|
className: cn(
|
|
18171
|
-
"flex items-center gap-(--cmp-chart-
|
|
18172
|
-
"py-(--cmp-chart-
|
|
18173
|
-
"typo-body-sm-medium text-(--cmp-chart-
|
|
18174
|
-
"transition-opacity",
|
|
18352
|
+
"flex items-center gap-(--cmp-chart-legendItem-gap)",
|
|
18353
|
+
"py-(--cmp-chart-legendItem-paddingY)",
|
|
18354
|
+
"typo-body-sm-medium text-(--cmp-chart-legendItem-color)",
|
|
18355
|
+
"transition-opacity duration-200 ease-out motion-reduce:transition-none",
|
|
18175
18356
|
activeIndex != null && activeIndex !== index && "opacity-(--opacity-060)"
|
|
18176
18357
|
),
|
|
18177
18358
|
children: [
|
|
@@ -18254,17 +18435,41 @@ function useElementSize() {
|
|
|
18254
18435
|
}, []);
|
|
18255
18436
|
return { ref, size };
|
|
18256
18437
|
}
|
|
18438
|
+
function useSvgTextMetrics() {
|
|
18439
|
+
const ref = react.useRef(null);
|
|
18440
|
+
const [metrics, setMetrics] = react.useState({ top: 0, width: 0 });
|
|
18441
|
+
react.useEffect(() => {
|
|
18442
|
+
const element = ref.current;
|
|
18443
|
+
if (!element) return;
|
|
18444
|
+
let box3;
|
|
18445
|
+
try {
|
|
18446
|
+
box3 = element.getBBox();
|
|
18447
|
+
} catch {
|
|
18448
|
+
return;
|
|
18449
|
+
}
|
|
18450
|
+
setMetrics(
|
|
18451
|
+
(prev) => Math.abs(prev.top - box3.y) < 0.5 && Math.abs(prev.width - box3.width) < 0.5 ? prev : { top: box3.y, width: box3.width }
|
|
18452
|
+
);
|
|
18453
|
+
});
|
|
18454
|
+
return { ref, metrics };
|
|
18455
|
+
}
|
|
18257
18456
|
var DOT_SIZE2 = 6;
|
|
18258
|
-
var
|
|
18259
|
-
|
|
18260
|
-
|
|
18261
|
-
const after =
|
|
18457
|
+
var ANCHOR_GAP_X = 4;
|
|
18458
|
+
var ANCHOR_GAP_Y = 0;
|
|
18459
|
+
function placeX(anchor, size, extent) {
|
|
18460
|
+
const after = anchor.right + ANCHOR_GAP_X;
|
|
18461
|
+
if (!extent) return after;
|
|
18262
18462
|
if (after + size <= extent) return after;
|
|
18263
|
-
const before =
|
|
18463
|
+
const before = anchor.left - ANCHOR_GAP_X - size;
|
|
18264
18464
|
if (before >= 0) return before;
|
|
18265
18465
|
return Math.max(0, Math.min(after, extent - size));
|
|
18266
18466
|
}
|
|
18267
|
-
function
|
|
18467
|
+
function placeY(anchor, size, extent) {
|
|
18468
|
+
const top = anchor.top + ANCHOR_GAP_Y;
|
|
18469
|
+
if (!extent) return top;
|
|
18470
|
+
return Math.max(0, Math.min(top, extent - size));
|
|
18471
|
+
}
|
|
18472
|
+
function ChartTooltip({ title, items, anchor, bounds, className }) {
|
|
18268
18473
|
const { ref, size } = useElementSize();
|
|
18269
18474
|
const measured = size.width > 0 && size.height > 0;
|
|
18270
18475
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -18273,7 +18478,7 @@ function ChartTooltip({ title, items, x, y, bounds, className }) {
|
|
|
18273
18478
|
ref,
|
|
18274
18479
|
role: "tooltip",
|
|
18275
18480
|
className: cn(
|
|
18276
|
-
// left/top 대신 transform 으로 옮긴다. 좌표를 바꾸면
|
|
18481
|
+
// left/top 대신 transform 으로 옮긴다. 좌표를 바꾸면 짚은 항목이 바뀔 때마다
|
|
18277
18482
|
// 리플로우가 나 차트가 미세하게 흔들려 보인다. transform 은 레이아웃을
|
|
18278
18483
|
// 건드리지 않으므로, 크기를 재기 전에 잠깐 밖으로 나가도 스크롤이 생기지 않는다.
|
|
18279
18484
|
"pointer-events-none absolute top-0 left-0 z-10 w-max",
|
|
@@ -18283,11 +18488,11 @@ function ChartTooltip({ title, items, x, y, bounds, className }) {
|
|
|
18283
18488
|
className
|
|
18284
18489
|
),
|
|
18285
18490
|
style: {
|
|
18286
|
-
// 크기를 재기 전에는 원점에 숨겨 둔다.
|
|
18491
|
+
// 크기를 재기 전에는 원점에 숨겨 둔다. 막대 옆에 그려 두면 그림 밖으로
|
|
18287
18492
|
// 넘쳐 스크롤 영역이 잠깐 늘어나고, 차트 전체가 한 번 흔들린다.
|
|
18288
18493
|
// transform 도 스크롤 영역 계산에는 포함되므로 위치만 바꿔서는 못 막는다.
|
|
18289
|
-
transform: measured ? `translate(${
|
|
18290
|
-
|
|
18494
|
+
transform: measured ? `translate(${placeX(anchor, size.width, bounds?.width ?? 0)}px, ${placeY(
|
|
18495
|
+
anchor,
|
|
18291
18496
|
size.height,
|
|
18292
18497
|
bounds?.height ?? 0
|
|
18293
18498
|
)}px)` : void 0,
|
|
@@ -18295,18 +18500,21 @@ function ChartTooltip({ title, items, x, y, bounds, className }) {
|
|
|
18295
18500
|
},
|
|
18296
18501
|
children: [
|
|
18297
18502
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-md-bold text-(--cmp-chart-chartTooltip-title-color)", children: title }),
|
|
18298
|
-
items.map((item4, index) =>
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
"
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18503
|
+
items.map((item4, index) => (
|
|
18504
|
+
// TODO: 토큰 생성되면 gap 을 `--cmp-chart-chartTooltipItem-gap` 으로 교체
|
|
18505
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-sd-8", children: [
|
|
18506
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18507
|
+
"span",
|
|
18508
|
+
{
|
|
18509
|
+
"aria-hidden": true,
|
|
18510
|
+
className: "shrink-0 rounded-full",
|
|
18511
|
+
style: { width: DOT_SIZE2, height: DOT_SIZE2, background: item4.color }
|
|
18512
|
+
}
|
|
18513
|
+
),
|
|
18514
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-default text-(--sys-color-fg-primary)", children: item4.label }),
|
|
18515
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-bold ml-auto text-(--sys-color-fg-primary)", children: item4.value })
|
|
18516
|
+
] }, `${item4.label}-${index}`)
|
|
18517
|
+
))
|
|
18310
18518
|
]
|
|
18311
18519
|
}
|
|
18312
18520
|
);
|
|
@@ -18318,11 +18526,16 @@ var BAR_SIZE_MAX = 80;
|
|
|
18318
18526
|
var BAR_GAP = 6;
|
|
18319
18527
|
var GROUP_PADDING_MIN = 8;
|
|
18320
18528
|
var GROUP_PADDING_MAX = 24;
|
|
18529
|
+
var AXIS_EDGE_PADDING = 24;
|
|
18321
18530
|
var VALUE_LABEL_GAP = 6;
|
|
18322
18531
|
var BAR_RADIUS = 8;
|
|
18323
|
-
var BAR_OPACITY_DEFAULT = "var(--opacity-
|
|
18324
|
-
var BAR_OPACITY_DIMMED = "var(--opacity-
|
|
18325
|
-
var
|
|
18532
|
+
var BAR_OPACITY_DEFAULT = "var(--cmp-chart-bar-opacity-default)";
|
|
18533
|
+
var BAR_OPACITY_DIMMED = "var(--cmp-chart-bar-opacity-dimmed)";
|
|
18534
|
+
var BAR_OPACITY_HOVER = 1;
|
|
18535
|
+
var BAR_DATA_LABEL_COLOR = "var(--cmp-chart-bar-dataLabel-color-default)";
|
|
18536
|
+
var BAR_DATA_LABEL_TYPO = "typo-body-sm-medium";
|
|
18537
|
+
var BAR_DATA_LABEL_TYPO_HOVER = "typo-body-md-bold";
|
|
18538
|
+
var BAR_HOVER_TRANSITION = "transition-opacity duration-200 ease-out motion-reduce:transition-none";
|
|
18326
18539
|
function bandLayout(size, categoryCount, seriesCount, barSizeMax = BAR_SIZE_MAX) {
|
|
18327
18540
|
const categories = Math.max(1, categoryCount);
|
|
18328
18541
|
const series = Math.max(1, seriesCount);
|
|
@@ -18333,7 +18546,8 @@ function bandLayout(size, categoryCount, seriesCount, barSizeMax = BAR_SIZE_MAX)
|
|
|
18333
18546
|
const tMax = (maxBar - BAR_SIZE_MIN) / barRange;
|
|
18334
18547
|
const bandMin = BAR_SIZE_MIN * series + gaps + GROUP_PADDING_MIN * 2;
|
|
18335
18548
|
const span = barRange * series + padRange * 2;
|
|
18336
|
-
const
|
|
18549
|
+
const inner = Math.max(0, size - AXIS_EDGE_PADDING * 2);
|
|
18550
|
+
const band = Math.min(inner / categories, bandMin + span * tMax);
|
|
18337
18551
|
const t = Math.min(Math.max((band - bandMin) / span, 0), tMax);
|
|
18338
18552
|
const bar = BAR_SIZE_MIN + barRange * t;
|
|
18339
18553
|
const padding = GROUP_PADDING_MIN + padRange * t;
|
|
@@ -18343,7 +18557,7 @@ function bandLayout(size, categoryCount, seriesCount, barSizeMax = BAR_SIZE_MAX)
|
|
|
18343
18557
|
bar,
|
|
18344
18558
|
group,
|
|
18345
18559
|
padding,
|
|
18346
|
-
offset: Math.max(0, (
|
|
18560
|
+
offset: AXIS_EDGE_PADDING + Math.max(0, (inner - band * categories) / 2)
|
|
18347
18561
|
};
|
|
18348
18562
|
}
|
|
18349
18563
|
var defaultFormat = (value) => value.toLocaleString();
|
|
@@ -18351,6 +18565,10 @@ function minBand(seriesCount) {
|
|
|
18351
18565
|
const series = Math.max(1, seriesCount);
|
|
18352
18566
|
return series * BAR_SIZE_MIN + (series - 1) * BAR_GAP + GROUP_PADDING_MIN * 2;
|
|
18353
18567
|
}
|
|
18568
|
+
function barOpacity(hoveredCategory, categoryIndex) {
|
|
18569
|
+
if (hoveredCategory == null) return BAR_OPACITY_DEFAULT;
|
|
18570
|
+
return hoveredCategory === categoryIndex ? BAR_OPACITY_HOVER : BAR_OPACITY_DIMMED;
|
|
18571
|
+
}
|
|
18354
18572
|
function barPath(x, y, width, height, direction, negative) {
|
|
18355
18573
|
const r = Math.max(0, Math.min(BAR_RADIUS, width / 2, height / 2));
|
|
18356
18574
|
if (r === 0) return `M${x} ${y}h${width}v${height}h${-width}Z`;
|
|
@@ -18396,8 +18614,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18396
18614
|
const { ref: axisTextRef, size: axisText } = useElementSize();
|
|
18397
18615
|
const { ref: axisSampleRef, size: axisSample } = useElementSize();
|
|
18398
18616
|
const clipId = react.useId();
|
|
18399
|
-
const [
|
|
18400
|
-
const hoveredCategory = hovered?.category ?? null;
|
|
18617
|
+
const [hoveredCategory, setHoveredCategory] = react.useState(null);
|
|
18401
18618
|
const perCategory = series.length === 1;
|
|
18402
18619
|
const colorAt = react.useCallback(
|
|
18403
18620
|
(seriesIndex, categoryIndex) => paletteColor(palette, perCategory ? categoryIndex : seriesIndex, customColors),
|
|
@@ -18431,30 +18648,92 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18431
18648
|
[axisLength, categories.length, barSlots, barSize]
|
|
18432
18649
|
);
|
|
18433
18650
|
const zeroRatio = ratioOf(0, scale);
|
|
18434
|
-
const minPlotWidth = vertical ? categories.length * minBand(barSlots) : 0;
|
|
18651
|
+
const minPlotWidth = vertical ? categories.length * minBand(barSlots) + AXIS_EDGE_PADDING * 2 : 0;
|
|
18435
18652
|
const totalHeight = height ?? (vertical ? 320 : void 0);
|
|
18436
|
-
const plotHeight = totalHeight == null ? Math.max(1, categories.length) * minBand(barSlots) : typeof totalHeight === "number" ? Math.max(0, totalHeight - axisText.height) : `calc(${totalHeight} - ${axisText.height}px)`;
|
|
18653
|
+
const plotHeight = totalHeight == null ? Math.max(1, categories.length) * minBand(barSlots) + AXIS_EDGE_PADDING * 2 : typeof totalHeight === "number" ? Math.max(0, totalHeight - axisText.height) : `calc(${totalHeight} - ${axisText.height}px)`;
|
|
18437
18654
|
const legend = showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { items: series.map((s, i) => ({ name: s.name, color: colorAt(i, 0) })) }) : null;
|
|
18438
18655
|
const handleMove = (event) => {
|
|
18439
18656
|
if (!showTooltip || categories.length === 0 || series.length === 0) return;
|
|
18440
18657
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
18441
|
-
const
|
|
18442
|
-
const y = event.clientY - rect.top;
|
|
18443
|
-
const along = (vertical ? x : y) - layout.offset;
|
|
18658
|
+
const along = (vertical ? event.clientX - rect.left : event.clientY - rect.top) - layout.offset;
|
|
18444
18659
|
const category = Math.floor(along / layout.band);
|
|
18445
|
-
|
|
18446
|
-
setHovered(null);
|
|
18447
|
-
return;
|
|
18448
|
-
}
|
|
18449
|
-
setHovered({ category, x, y });
|
|
18660
|
+
setHoveredCategory(category >= 0 && category < categories.length ? category : null);
|
|
18450
18661
|
};
|
|
18451
|
-
const tooltipItems =
|
|
18452
|
-
const value = s.data[
|
|
18662
|
+
const tooltipItems = hoveredCategory == null ? [] : series.flatMap((s, i) => {
|
|
18663
|
+
const value = s.data[hoveredCategory];
|
|
18453
18664
|
if (value == null || !Number.isFinite(value)) return [];
|
|
18454
|
-
return [
|
|
18455
|
-
{ color: colorAt(i, hovered.category), label: s.name, value: formatValue(value) }
|
|
18456
|
-
];
|
|
18665
|
+
return [{ color: colorAt(i, hoveredCategory), label: s.name, value: formatValue(value) }];
|
|
18457
18666
|
});
|
|
18667
|
+
const anchorBar = react.useMemo(() => {
|
|
18668
|
+
if (hoveredCategory == null || size.width <= 0 || size.height <= 0) return null;
|
|
18669
|
+
const pxOf = (value) => vertical ? size.height - ratioOf(value, scale) * size.height : ratioOf(value, scale) * size.width;
|
|
18670
|
+
const anchorOf = (value, from, to, start, thickness) => vertical ? {
|
|
18671
|
+
value,
|
|
18672
|
+
left: start,
|
|
18673
|
+
right: start + thickness,
|
|
18674
|
+
top: Math.min(pxOf(from), pxOf(to))
|
|
18675
|
+
} : {
|
|
18676
|
+
value,
|
|
18677
|
+
left: Math.min(pxOf(from), pxOf(to)),
|
|
18678
|
+
right: Math.max(pxOf(from), pxOf(to)),
|
|
18679
|
+
top: start
|
|
18680
|
+
};
|
|
18681
|
+
if (stacked) {
|
|
18682
|
+
const total = stackTotals[hoveredCategory];
|
|
18683
|
+
if (total == null) return null;
|
|
18684
|
+
const barStart = layout.offset + hoveredCategory * layout.band + (layout.band - layout.bar) / 2;
|
|
18685
|
+
return anchorOf(
|
|
18686
|
+
total.positive + total.negative,
|
|
18687
|
+
total.negative,
|
|
18688
|
+
total.positive,
|
|
18689
|
+
barStart,
|
|
18690
|
+
layout.bar
|
|
18691
|
+
);
|
|
18692
|
+
}
|
|
18693
|
+
let bestIndex = -1;
|
|
18694
|
+
let bestValue = 0;
|
|
18695
|
+
series.forEach((s, seriesIndex) => {
|
|
18696
|
+
const value = s.data[hoveredCategory];
|
|
18697
|
+
if (value == null || !Number.isFinite(value)) return;
|
|
18698
|
+
if (bestIndex === -1 || value > bestValue) {
|
|
18699
|
+
bestIndex = seriesIndex;
|
|
18700
|
+
bestValue = value;
|
|
18701
|
+
}
|
|
18702
|
+
});
|
|
18703
|
+
if (bestIndex === -1) return null;
|
|
18704
|
+
const groupStart = layout.offset + hoveredCategory * layout.band + (layout.band - layout.group) / 2;
|
|
18705
|
+
return anchorOf(
|
|
18706
|
+
bestValue,
|
|
18707
|
+
0,
|
|
18708
|
+
bestValue,
|
|
18709
|
+
groupStart + bestIndex * (layout.bar + BAR_GAP),
|
|
18710
|
+
layout.bar
|
|
18711
|
+
);
|
|
18712
|
+
}, [
|
|
18713
|
+
hoveredCategory,
|
|
18714
|
+
size.width,
|
|
18715
|
+
size.height,
|
|
18716
|
+
vertical,
|
|
18717
|
+
scale,
|
|
18718
|
+
stacked,
|
|
18719
|
+
stackTotals,
|
|
18720
|
+
layout,
|
|
18721
|
+
series
|
|
18722
|
+
]);
|
|
18723
|
+
const { ref: valueLabelRef, metrics: valueLabel } = useSvgTextMetrics();
|
|
18724
|
+
const anchorLabel = anchorBar == null ? "" : formatValue(anchorBar.value);
|
|
18725
|
+
const tooltipAnchor = react.useMemo(() => {
|
|
18726
|
+
if (anchorBar == null) return null;
|
|
18727
|
+
if (!showValueLabel || anchorBar.value < 0) return anchorBar;
|
|
18728
|
+
return vertical ? (
|
|
18729
|
+
// 라벨의 기준선은 막대 윗변에서 VALUE_LABEL_GAP 만큼 위. 거기서 글자
|
|
18730
|
+
// 윗변까지가 metrics.top(음수)이다.
|
|
18731
|
+
{ ...anchorBar, top: anchorBar.top - VALUE_LABEL_GAP + valueLabel.top }
|
|
18732
|
+
) : (
|
|
18733
|
+
// 가로 막대의 라벨은 막대 오른쪽 끝에서 시작해 폭만큼 뻗는다.
|
|
18734
|
+
{ ...anchorBar, right: anchorBar.right + VALUE_LABEL_GAP + valueLabel.width }
|
|
18735
|
+
);
|
|
18736
|
+
}, [anchorBar, showValueLabel, vertical, valueLabel.top, valueLabel.width]);
|
|
18458
18737
|
const categoryLabels = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18459
18738
|
"div",
|
|
18460
18739
|
{
|
|
@@ -18495,6 +18774,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18495
18774
|
const value = s.data[categoryIndex];
|
|
18496
18775
|
if (value == null || !Number.isFinite(value)) return null;
|
|
18497
18776
|
const dimmed = hoveredCategory != null && hoveredCategory !== categoryIndex;
|
|
18777
|
+
const opacity = barOpacity(hoveredCategory, categoryIndex);
|
|
18498
18778
|
const groupStart = layout.offset + categoryIndex * layout.band + (layout.band - layout.group) / 2;
|
|
18499
18779
|
const offset = groupStart + seriesIndex * (layout.bar + BAR_GAP);
|
|
18500
18780
|
const valueRatio = ratioOf(value, scale);
|
|
@@ -18529,9 +18809,10 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18529
18809
|
"path",
|
|
18530
18810
|
{
|
|
18531
18811
|
d: barPath(x, y, width, barHeight, direction, negative),
|
|
18812
|
+
className: BAR_HOVER_TRANSITION,
|
|
18532
18813
|
style: {
|
|
18533
18814
|
fill: colorAt(seriesIndex, categoryIndex),
|
|
18534
|
-
opacity
|
|
18815
|
+
opacity,
|
|
18535
18816
|
cursor: onBarClick ? "pointer" : void 0
|
|
18536
18817
|
},
|
|
18537
18818
|
onClick: onBarClick ? () => onBarClick({ seriesIndex, categoryIndex, value }) : void 0,
|
|
@@ -18543,8 +18824,14 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18543
18824
|
{
|
|
18544
18825
|
x: labelX,
|
|
18545
18826
|
y: labelY,
|
|
18546
|
-
className:
|
|
18547
|
-
|
|
18827
|
+
className: cn(
|
|
18828
|
+
hoveredCategory === categoryIndex ? BAR_DATA_LABEL_TYPO_HOVER : BAR_DATA_LABEL_TYPO,
|
|
18829
|
+
BAR_HOVER_TRANSITION
|
|
18830
|
+
),
|
|
18831
|
+
style: {
|
|
18832
|
+
fill: BAR_DATA_LABEL_COLOR,
|
|
18833
|
+
opacity: dimmed ? BAR_OPACITY_DIMMED : void 0
|
|
18834
|
+
},
|
|
18548
18835
|
textAnchor: vertical ? "middle" : negative ? "end" : "start",
|
|
18549
18836
|
dominantBaseline: vertical ? "auto" : "central",
|
|
18550
18837
|
children: formatValue(value)
|
|
@@ -18576,6 +18863,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18576
18863
|
const pxOf = (value) => vertical ? size.height - ratioOf(value, scale) * size.height : ratioOf(value, scale) * size.width;
|
|
18577
18864
|
return categories.map((_, categoryIndex) => {
|
|
18578
18865
|
const dimmed = hoveredCategory != null && hoveredCategory !== categoryIndex;
|
|
18866
|
+
const opacity = barOpacity(hoveredCategory, categoryIndex);
|
|
18579
18867
|
const barStart = layout.offset + categoryIndex * layout.band + (layout.band - layout.bar) / 2;
|
|
18580
18868
|
let positive = 0;
|
|
18581
18869
|
let negative = 0;
|
|
@@ -18619,10 +18907,12 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18619
18907
|
width: box3.width,
|
|
18620
18908
|
height: box3.height,
|
|
18621
18909
|
clipPath: `url(#${segment.value < 0 ? negativeClip : positiveClip})`,
|
|
18910
|
+
className: BAR_HOVER_TRANSITION,
|
|
18622
18911
|
style: {
|
|
18912
|
+
// 조각과 라벨에 따로 건다 — 묶음(<g>)에 걸면 호버가 없을 때의
|
|
18913
|
+
// 기본 흐림까지 합계 라벨에 묻어 숫자가 늘 옅어진다.
|
|
18623
18914
|
fill: colorAt(segment.seriesIndex, categoryIndex),
|
|
18624
|
-
|
|
18625
|
-
opacity: dimmed ? BAR_OPACITY_DIMMED : BAR_OPACITY_DEFAULT,
|
|
18915
|
+
opacity,
|
|
18626
18916
|
cursor: onBarClick ? "pointer" : void 0
|
|
18627
18917
|
},
|
|
18628
18918
|
onClick: onBarClick ? () => onBarClick({
|
|
@@ -18640,8 +18930,14 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18640
18930
|
{
|
|
18641
18931
|
x: labelX,
|
|
18642
18932
|
y: labelY,
|
|
18643
|
-
className:
|
|
18644
|
-
|
|
18933
|
+
className: cn(
|
|
18934
|
+
hoveredCategory === categoryIndex ? BAR_DATA_LABEL_TYPO_HOVER : BAR_DATA_LABEL_TYPO,
|
|
18935
|
+
BAR_HOVER_TRANSITION
|
|
18936
|
+
),
|
|
18937
|
+
style: {
|
|
18938
|
+
fill: BAR_DATA_LABEL_COLOR,
|
|
18939
|
+
opacity: dimmed ? BAR_OPACITY_DIMMED : void 0
|
|
18940
|
+
},
|
|
18645
18941
|
textAnchor: vertical ? "middle" : total >= 0 ? "start" : "end",
|
|
18646
18942
|
dominantBaseline: vertical ? "auto" : "central",
|
|
18647
18943
|
children: formatValue(total)
|
|
@@ -18691,7 +18987,7 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18691
18987
|
ref: plotRef,
|
|
18692
18988
|
className: "relative h-full w-full",
|
|
18693
18989
|
onMouseMove: handleMove,
|
|
18694
|
-
onMouseLeave: () =>
|
|
18990
|
+
onMouseLeave: () => setHoveredCategory(null),
|
|
18695
18991
|
children: [
|
|
18696
18992
|
size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18697
18993
|
"svg",
|
|
@@ -18701,6 +18997,19 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18701
18997
|
role: "img",
|
|
18702
18998
|
"aria-label": `${categories.length}\uAC1C \uD56D\uBAA9, ${series.length}\uAC1C \uACC4\uC5F4 ${stacked ? "\uB204\uC801 " : ""}\uB9C9\uB300 \uADF8\uB798\uD504`,
|
|
18703
18999
|
children: [
|
|
19000
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19001
|
+
"text",
|
|
19002
|
+
{
|
|
19003
|
+
ref: valueLabelRef,
|
|
19004
|
+
"aria-hidden": true,
|
|
19005
|
+
x: 0,
|
|
19006
|
+
y: 0,
|
|
19007
|
+
className: BAR_DATA_LABEL_TYPO_HOVER,
|
|
19008
|
+
dominantBaseline: "auto",
|
|
19009
|
+
style: { visibility: "hidden" },
|
|
19010
|
+
children: anchorLabel || "0"
|
|
19011
|
+
}
|
|
19012
|
+
),
|
|
18704
19013
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18705
19014
|
ChartGrid,
|
|
18706
19015
|
{
|
|
@@ -18710,12 +19019,12 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18710
19019
|
height: size.height
|
|
18711
19020
|
}
|
|
18712
19021
|
),
|
|
18713
|
-
|
|
19022
|
+
hoveredCategory != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18714
19023
|
"rect",
|
|
18715
19024
|
{
|
|
18716
19025
|
"aria-hidden": true,
|
|
18717
|
-
x: vertical ? layout.offset +
|
|
18718
|
-
y: vertical ? 0 : layout.offset +
|
|
19026
|
+
x: vertical ? layout.offset + hoveredCategory * layout.band : 0,
|
|
19027
|
+
y: vertical ? 0 : layout.offset + hoveredCategory * layout.band,
|
|
18719
19028
|
width: vertical ? layout.band : size.width,
|
|
18720
19029
|
height: vertical ? size.height : layout.band,
|
|
18721
19030
|
style: {
|
|
@@ -18728,13 +19037,12 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
|
|
|
18728
19037
|
]
|
|
18729
19038
|
}
|
|
18730
19039
|
),
|
|
18731
|
-
showTooltip &&
|
|
19040
|
+
showTooltip && hoveredCategory != null && tooltipAnchor != null && tooltipItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18732
19041
|
ChartTooltip,
|
|
18733
19042
|
{
|
|
18734
|
-
title: categories[
|
|
19043
|
+
title: categories[hoveredCategory] ?? "",
|
|
18735
19044
|
items: tooltipItems,
|
|
18736
|
-
|
|
18737
|
-
y: hovered.y,
|
|
19045
|
+
anchor: tooltipAnchor,
|
|
18738
19046
|
bounds: size
|
|
18739
19047
|
}
|
|
18740
19048
|
)
|