sellmate-design-system-react 9.0.0-beta.95 → 9.0.0-beta.97
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 +21 -2
- package/dist/components/SSelect/README.md +1 -0
- package/dist/components/SSelect/SSelect.d.ts +8 -0
- package/dist/components/STable/README.md +15 -1
- package/dist/components/STable/STable.d.ts +45 -1
- package/dist/components/STable/index.d.ts +1 -1
- package/dist/components/STreeTable/STreeTable.d.ts +1 -1
- package/dist/index.cjs +396 -205
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +396 -205
- package/dist/index.js.map +1 -1
- package/dist/lib/row-motion.d.ts +56 -0
- package/dist/llms-full.txt +37 -3
- package/dist/llms.txt +21 -2
- package/dist/styles.css +9 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15657,6 +15657,93 @@ function SCalendarBoard({
|
|
|
15657
15657
|
);
|
|
15658
15658
|
}
|
|
15659
15659
|
|
|
15660
|
+
// src/lib/row-motion.ts
|
|
15661
|
+
var EXPAND_MOTION = { duration: 220, easing: "ease-out" };
|
|
15662
|
+
var COLLAPSE_MOTION = { duration: 140, easing: "ease-in" };
|
|
15663
|
+
function sameKeys(a, b) {
|
|
15664
|
+
return a.size === b.size && [...a].every((key) => b.has(key));
|
|
15665
|
+
}
|
|
15666
|
+
function motionAllowed() {
|
|
15667
|
+
if (typeof window === "undefined" || typeof Element.prototype.animate !== "function")
|
|
15668
|
+
return false;
|
|
15669
|
+
return !window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
15670
|
+
}
|
|
15671
|
+
function startRowMotion({
|
|
15672
|
+
scrollEl,
|
|
15673
|
+
isInBlock,
|
|
15674
|
+
blockKeys,
|
|
15675
|
+
from,
|
|
15676
|
+
to
|
|
15677
|
+
}) {
|
|
15678
|
+
const spec = to === 1 ? EXPAND_MOTION : COLLAPSE_MOTION;
|
|
15679
|
+
const duration = spec.duration * Math.abs(to - from);
|
|
15680
|
+
if (duration < 1) return null;
|
|
15681
|
+
const trs = [
|
|
15682
|
+
...scrollEl.querySelectorAll("tr[data-row-index], tr[data-expansion-row]")
|
|
15683
|
+
].map((tr) => ({ tr, inBlock: isInBlock(tr), height: tr.getBoundingClientRect().height }));
|
|
15684
|
+
const viewBottom = scrollEl.scrollTop + scrollEl.clientHeight;
|
|
15685
|
+
const openAt = (offset) => from + (to - from) * offset;
|
|
15686
|
+
const translate = (shift2, s) => `translateY(${-shift2 * (1 - s)}px)`;
|
|
15687
|
+
const timing = {
|
|
15688
|
+
duration,
|
|
15689
|
+
easing: spec.easing,
|
|
15690
|
+
// 접힘은 남겨 둔 행이 빠질 때까지 끝 위치를 붙잡는다 — 놓으면 그 사이 한 프레임 제자리로 튄다
|
|
15691
|
+
fill: to === 0 ? "forwards" : "none"
|
|
15692
|
+
};
|
|
15693
|
+
const animations = [];
|
|
15694
|
+
let shift = 0;
|
|
15695
|
+
let blockHeight = 0;
|
|
15696
|
+
let y = 0;
|
|
15697
|
+
trs.forEach(({ tr, inBlock, height }, i) => {
|
|
15698
|
+
if (inBlock && !trs[i - 1]?.inBlock) {
|
|
15699
|
+
blockHeight = 0;
|
|
15700
|
+
for (let j = i; j < trs.length && trs[j].inBlock; j++) blockHeight += trs[j].height;
|
|
15701
|
+
shift += blockHeight;
|
|
15702
|
+
y = 0;
|
|
15703
|
+
}
|
|
15704
|
+
if (shift === 0 || tr.offsetTop - shift > viewBottom) return;
|
|
15705
|
+
if (!inBlock) {
|
|
15706
|
+
animations.push(
|
|
15707
|
+
tr.animate(
|
|
15708
|
+
[{ transform: translate(shift, from) }, { transform: translate(shift, to) }],
|
|
15709
|
+
timing
|
|
15710
|
+
)
|
|
15711
|
+
);
|
|
15712
|
+
return;
|
|
15713
|
+
}
|
|
15714
|
+
const rowY = y;
|
|
15715
|
+
const clipAt = (s) => Math.min(height, Math.max(0, blockHeight * (1 - s) - rowY));
|
|
15716
|
+
const bends = [1 - rowY / blockHeight, 1 - (rowY + height) / blockHeight].map((s) => (s - from) / (to - from)).filter((offset) => offset > 0 && offset < 1);
|
|
15717
|
+
const offsets = [0, ...bends, 1].sort((a, b) => a - b);
|
|
15718
|
+
animations.push(
|
|
15719
|
+
tr.animate(
|
|
15720
|
+
offsets.map((offset) => ({
|
|
15721
|
+
offset,
|
|
15722
|
+
transform: translate(shift, openAt(offset)),
|
|
15723
|
+
clipPath: `inset(${clipAt(openAt(offset))}px 0 0 0)`
|
|
15724
|
+
})),
|
|
15725
|
+
timing
|
|
15726
|
+
)
|
|
15727
|
+
);
|
|
15728
|
+
y += height;
|
|
15729
|
+
});
|
|
15730
|
+
if (animations.length === 0) return null;
|
|
15731
|
+
return {
|
|
15732
|
+
keys: blockKeys,
|
|
15733
|
+
to,
|
|
15734
|
+
done: false,
|
|
15735
|
+
finished: Promise.all(animations.map((animation) => animation.finished)).then(
|
|
15736
|
+
() => true,
|
|
15737
|
+
() => false
|
|
15738
|
+
),
|
|
15739
|
+
openness: () => {
|
|
15740
|
+
const progress = animations[0].effect?.getComputedTiming().progress;
|
|
15741
|
+
return progress == null ? to : openAt(progress);
|
|
15742
|
+
},
|
|
15743
|
+
cancel: () => animations.forEach((animation) => animation.cancel())
|
|
15744
|
+
};
|
|
15745
|
+
}
|
|
15746
|
+
|
|
15660
15747
|
// src/lib/row-metrics.ts
|
|
15661
15748
|
function createRowMetrics(count, estimate) {
|
|
15662
15749
|
const safeCount = Math.max(0, Math.floor(count));
|
|
@@ -16076,6 +16163,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
16076
16163
|
onSearchChange,
|
|
16077
16164
|
searchDebounce = DEFAULT_SEARCH_DEBOUNCE,
|
|
16078
16165
|
label,
|
|
16166
|
+
ariaLabel,
|
|
16079
16167
|
labelPosition,
|
|
16080
16168
|
subLabel,
|
|
16081
16169
|
labelWidth,
|
|
@@ -16778,6 +16866,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
16778
16866
|
style,
|
|
16779
16867
|
children: [
|
|
16780
16868
|
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selected.join(",") }),
|
|
16869
|
+
!label && ariaLabel && /* @__PURE__ */ jsx("span", { id: `${triggerId}-aria-label`, hidden: true, children: ariaLabel }),
|
|
16781
16870
|
/* @__PURE__ */ jsxs(
|
|
16782
16871
|
"div",
|
|
16783
16872
|
{
|
|
@@ -16786,7 +16875,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
16786
16875
|
role: "combobox",
|
|
16787
16876
|
tabIndex: effectiveDisabled ? -1 : 0,
|
|
16788
16877
|
"aria-disabled": effectiveDisabled || void 0,
|
|
16789
|
-
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerId}` : triggerId,
|
|
16878
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerId}` : ariaLabel ? `${triggerId}-aria-label ${triggerId}` : triggerId,
|
|
16790
16879
|
"aria-haspopup": isTree ? "tree" : "listbox",
|
|
16791
16880
|
"aria-expanded": open,
|
|
16792
16881
|
"aria-controls": open ? listboxId : void 0,
|
|
@@ -17394,6 +17483,7 @@ function CheckboxBox({
|
|
|
17394
17483
|
}
|
|
17395
17484
|
);
|
|
17396
17485
|
}
|
|
17486
|
+
var NO_KEYS = /* @__PURE__ */ new Set();
|
|
17397
17487
|
var DEFAULT_ROW_HEIGHT = 44;
|
|
17398
17488
|
var DENSE_ROW_HEIGHT = 32;
|
|
17399
17489
|
var SELECTABLE_COLUMN_WIDTH = 48;
|
|
@@ -17424,6 +17514,11 @@ var CONTEXT_MENU_ITEM_CLASS = cn(
|
|
|
17424
17514
|
"data-[highlighted]:bg-[var(--sys-color-bg-accent)] data-[highlighted]:text-[color:var(--sys-color-fg-inverse)]"
|
|
17425
17515
|
);
|
|
17426
17516
|
var ROW_INTERACTIVE_SELECTOR = 'button, a, input, select, textarea, label, [role="button"], [role="checkbox"], [contenteditable="true"]';
|
|
17517
|
+
function rowBlockHeight(tr) {
|
|
17518
|
+
const next = tr.nextElementSibling;
|
|
17519
|
+
const expansion = next instanceof HTMLElement && next.dataset.expansionRow != null ? next.offsetHeight : 0;
|
|
17520
|
+
return tr.offsetHeight + expansion;
|
|
17521
|
+
}
|
|
17427
17522
|
var colWidthFromDef = (c) => {
|
|
17428
17523
|
if (c.autoWidth) return 0;
|
|
17429
17524
|
if (c.width == null) return DEFAULT_COLUMN_WIDTH;
|
|
@@ -17436,6 +17531,8 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17436
17531
|
rows = [],
|
|
17437
17532
|
rowKey = "id",
|
|
17438
17533
|
selectable = false,
|
|
17534
|
+
rowSelectLabel,
|
|
17535
|
+
selectAllLabel = "\uC804\uCCB4 \uC120\uD0DD",
|
|
17439
17536
|
dragSelectable = false,
|
|
17440
17537
|
contextMenuItems,
|
|
17441
17538
|
onContextMenuItemClick,
|
|
@@ -17474,6 +17571,11 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17474
17571
|
tableId,
|
|
17475
17572
|
onRowClick,
|
|
17476
17573
|
onRowDoubleClick,
|
|
17574
|
+
renderExpansion,
|
|
17575
|
+
expansionColumn,
|
|
17576
|
+
expandedKeys,
|
|
17577
|
+
defaultExpandedKeys,
|
|
17578
|
+
onExpandedChange,
|
|
17477
17579
|
className,
|
|
17478
17580
|
style
|
|
17479
17581
|
}, ref) {
|
|
@@ -17488,6 +17590,44 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17488
17590
|
onDenseChange?.(next);
|
|
17489
17591
|
};
|
|
17490
17592
|
const visibleCols = useMemo(() => columns.filter((c) => c.visible !== false), [columns]);
|
|
17593
|
+
const expansionOn = renderExpansion != null;
|
|
17594
|
+
const [innerExpandedKeys, setInnerExpandedKeys] = useState(
|
|
17595
|
+
() => defaultExpandedKeys ?? []
|
|
17596
|
+
);
|
|
17597
|
+
const currentExpandedKeys = expandedKeys ?? innerExpandedKeys;
|
|
17598
|
+
const expandedSet = useMemo(() => new Set(currentExpandedKeys), [currentExpandedKeys]);
|
|
17599
|
+
const isRowExpanded = (row) => expansionOn && expandedSet.has(row[rowKey]);
|
|
17600
|
+
const [closingKeys, setClosingKeys] = useState(NO_KEYS);
|
|
17601
|
+
const [prevExpandedSet, setPrevExpandedSet] = useState(expandedSet);
|
|
17602
|
+
if (prevExpandedSet !== expandedSet) {
|
|
17603
|
+
setPrevExpandedSet(expandedSet);
|
|
17604
|
+
let nextClosing = NO_KEYS;
|
|
17605
|
+
if (expansionOn && motionAllowed()) {
|
|
17606
|
+
const collapsed = [...prevExpandedSet].filter((key) => !expandedSet.has(key));
|
|
17607
|
+
const opened = [...expandedSet].filter((key) => !prevExpandedSet.has(key));
|
|
17608
|
+
if (collapsed.length > 0 && opened.length === 0) nextClosing = new Set(collapsed);
|
|
17609
|
+
}
|
|
17610
|
+
if (nextClosing !== closingKeys) setClosingKeys(nextClosing);
|
|
17611
|
+
}
|
|
17612
|
+
const shownExpansionSet = useMemo(
|
|
17613
|
+
() => closingKeys.size === 0 ? expandedSet : /* @__PURE__ */ new Set([...expandedSet, ...closingKeys]),
|
|
17614
|
+
[expandedSet, closingKeys]
|
|
17615
|
+
);
|
|
17616
|
+
const toggleExpanded = (row) => {
|
|
17617
|
+
const key = row[rowKey];
|
|
17618
|
+
const next = expandedSet.has(key) ? currentExpandedKeys.filter((k) => k !== key) : [...currentExpandedKeys, key];
|
|
17619
|
+
if (expandedKeys === void 0) setInnerExpandedKeys(next);
|
|
17620
|
+
onExpandedChange?.(next, row);
|
|
17621
|
+
};
|
|
17622
|
+
const expansionColIndex = !expansionOn ? -1 : expansionColumn == null ? 0 : visibleCols.findIndex((c) => c.name === expansionColumn);
|
|
17623
|
+
if (expansionColIndex >= 0) {
|
|
17624
|
+
const col = visibleCols[expansionColIndex];
|
|
17625
|
+
if (col?.renderCell) {
|
|
17626
|
+
throw new Error(
|
|
17627
|
+
`[STable] \uD3BC\uCE68 \uCEEC\uB7FC(${col.name})\uC5D0\uB294 renderCell \uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. render \uB97C \uC4F0\uC138\uC694.`
|
|
17628
|
+
);
|
|
17629
|
+
}
|
|
17630
|
+
}
|
|
17491
17631
|
const headerGroupInfo = useMemo(() => {
|
|
17492
17632
|
if (!headerGroups || headerGroups.length === 0) return null;
|
|
17493
17633
|
const indexByName = new Map(visibleCols.map((col, index) => [col.name, index]));
|
|
@@ -17592,6 +17732,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17592
17732
|
metricsRef.current ?? (metricsRef.current = createRowMetrics(0, effectiveRowHeight));
|
|
17593
17733
|
const metrics = metricsRef.current;
|
|
17594
17734
|
const measuredKeyRef = useRef("");
|
|
17735
|
+
const measuredExpansionRef = useRef(shownExpansionSet);
|
|
17595
17736
|
const pendingRowRef = useRef(null);
|
|
17596
17737
|
const pinnedTopRef = useRef(-1);
|
|
17597
17738
|
const lastEstimateRef = useRef(effectiveRowHeight);
|
|
@@ -17605,6 +17746,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17605
17746
|
}
|
|
17606
17747
|
const [scrolledLeft, setScrolledLeft] = useState(false);
|
|
17607
17748
|
const [scrolledRight, setScrolledRight] = useState(false);
|
|
17749
|
+
const [viewportWidth, setViewportWidth] = useState(0);
|
|
17608
17750
|
const setRowCount = useCallback((count) => {
|
|
17609
17751
|
const safe = Math.max(0, Math.floor(Number.isFinite(count) ? count : 0));
|
|
17610
17752
|
lastReachEndRef.current = -1;
|
|
@@ -17630,6 +17772,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17630
17772
|
setHeaderHeight(headerH);
|
|
17631
17773
|
setScrolledLeft(el.scrollLeft > 0);
|
|
17632
17774
|
setScrolledRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
|
|
17775
|
+
setViewportWidth(el.clientWidth);
|
|
17633
17776
|
if (virtualScroll) {
|
|
17634
17777
|
const { start, end } = calcRange(el.scrollTop, el.clientHeight - headerH);
|
|
17635
17778
|
setVsRange((prev) => prev.start === start && prev.end === end ? prev : { start, end });
|
|
@@ -17647,6 +17790,13 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17647
17790
|
useEffect(() => {
|
|
17648
17791
|
handleScroll();
|
|
17649
17792
|
}, [handleScroll, rowCount, columnWidths, loading2, height]);
|
|
17793
|
+
useEffect(() => {
|
|
17794
|
+
const el = scrollRef.current;
|
|
17795
|
+
if (!expansionOn || !el || typeof ResizeObserver === "undefined") return;
|
|
17796
|
+
const observer = new ResizeObserver(() => handleScroll());
|
|
17797
|
+
observer.observe(el);
|
|
17798
|
+
return () => observer.disconnect();
|
|
17799
|
+
}, [expansionOn, handleScroll]);
|
|
17650
17800
|
const handleScrollRef = useRef(handleScroll);
|
|
17651
17801
|
handleScrollRef.current = handleScroll;
|
|
17652
17802
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -17656,9 +17806,10 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17656
17806
|
if (!el || m == null) return;
|
|
17657
17807
|
const pending2 = pendingRowRef.current;
|
|
17658
17808
|
const key = `${vsRange.start}:${vsRange.end}:${rowCount}`;
|
|
17659
|
-
const alreadyMeasured = measuredKeyRef.current === key;
|
|
17809
|
+
const alreadyMeasured = measuredKeyRef.current === key && measuredExpansionRef.current === shownExpansionSet;
|
|
17660
17810
|
if (alreadyMeasured && pending2 == null) return;
|
|
17661
17811
|
measuredKeyRef.current = key;
|
|
17812
|
+
measuredExpansionRef.current = shownExpansionSet;
|
|
17662
17813
|
const anchor = vsRange.start;
|
|
17663
17814
|
const anchorBefore = offsetOf(m, anchor);
|
|
17664
17815
|
let changed = false;
|
|
@@ -17666,7 +17817,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17666
17817
|
for (const tr of el.querySelectorAll("tr[data-row-index]")) {
|
|
17667
17818
|
const index = Number(tr.dataset.rowIndex);
|
|
17668
17819
|
if (!Number.isInteger(index)) continue;
|
|
17669
|
-
const h = tr
|
|
17820
|
+
const h = rowBlockHeight(tr);
|
|
17670
17821
|
if (h <= 0) continue;
|
|
17671
17822
|
if (setRowSize(m, index, h)) changed = true;
|
|
17672
17823
|
}
|
|
@@ -17688,6 +17839,54 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17688
17839
|
if (delta !== 0 && el.scrollTop > 0) el.scrollTop += delta;
|
|
17689
17840
|
handleScrollRef.current();
|
|
17690
17841
|
});
|
|
17842
|
+
const expansionMotionRef = useRef(null);
|
|
17843
|
+
const prevExpansionRef = useRef(null);
|
|
17844
|
+
useIsomorphicLayoutEffect(() => {
|
|
17845
|
+
if (!expansionOn) return;
|
|
17846
|
+
const prev = prevExpansionRef.current;
|
|
17847
|
+
prevExpansionRef.current = { rows, keys: expandedSet };
|
|
17848
|
+
const running = expansionMotionRef.current;
|
|
17849
|
+
if (running?.done) {
|
|
17850
|
+
running.cancel();
|
|
17851
|
+
expansionMotionRef.current = null;
|
|
17852
|
+
}
|
|
17853
|
+
if (!prev || prev.keys === expandedSet) return;
|
|
17854
|
+
const added = new Set([...expandedSet].filter((key) => !prev.keys.has(key)));
|
|
17855
|
+
const removed = new Set([...prev.keys].filter((key) => !expandedSet.has(key)));
|
|
17856
|
+
if (added.size === 0 && removed.size === 0) return;
|
|
17857
|
+
let from = added.size > 0 ? 0 : 1;
|
|
17858
|
+
if (expansionMotionRef.current) {
|
|
17859
|
+
const current = expansionMotionRef.current;
|
|
17860
|
+
const reversing = current.to === 0 && sameKeys(added, current.keys) || current.to === 1 && sameKeys(removed, current.keys);
|
|
17861
|
+
if (reversing) from = current.openness();
|
|
17862
|
+
current.cancel();
|
|
17863
|
+
expansionMotionRef.current = null;
|
|
17864
|
+
}
|
|
17865
|
+
const scrollEl = scrollRef.current;
|
|
17866
|
+
const keys = added.size > 0 ? added : removed;
|
|
17867
|
+
const keyNames = new Set([...keys].map(String));
|
|
17868
|
+
const canAnimate = scrollEl != null && prev.rows === rows && motionAllowed() && (added.size === 0 || removed.size === 0);
|
|
17869
|
+
const motion = canAnimate ? startRowMotion({
|
|
17870
|
+
scrollEl,
|
|
17871
|
+
isInBlock: (tr) => tr.dataset.expansionRow != null && keyNames.has(tr.dataset.expansionKey ?? ""),
|
|
17872
|
+
blockKeys: keys,
|
|
17873
|
+
from,
|
|
17874
|
+
to: added.size > 0 ? 1 : 0
|
|
17875
|
+
}) : null;
|
|
17876
|
+
if (motion) {
|
|
17877
|
+
expansionMotionRef.current = motion;
|
|
17878
|
+
if (motion.to === 0) {
|
|
17879
|
+
void motion.finished.then((completed) => {
|
|
17880
|
+
if (!completed || expansionMotionRef.current !== motion) return;
|
|
17881
|
+
motion.done = true;
|
|
17882
|
+
setClosingKeys(NO_KEYS);
|
|
17883
|
+
});
|
|
17884
|
+
}
|
|
17885
|
+
} else if (closingKeys.size > 0) {
|
|
17886
|
+
setClosingKeys(NO_KEYS);
|
|
17887
|
+
}
|
|
17888
|
+
}, [expandedSet, closingKeys]);
|
|
17889
|
+
useEffect(() => () => expansionMotionRef.current?.cancel(), []);
|
|
17691
17890
|
useEffect(() => {
|
|
17692
17891
|
if (!virtualScroll) return;
|
|
17693
17892
|
cbRef.current.onVirtualUpdate?.({ from: vsRange.start, to: vsRange.end });
|
|
@@ -17744,7 +17943,7 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
17744
17943
|
if (virtualScroll && m != null) return indexAtOffset(m, el.scrollTop);
|
|
17745
17944
|
const top = el.scrollTop;
|
|
17746
17945
|
for (const tr of el.querySelectorAll("tr[data-row-index]")) {
|
|
17747
|
-
if (tr.offsetTop + tr
|
|
17946
|
+
if (tr.offsetTop + rowBlockHeight(tr) > top) return Number(tr.dataset.rowIndex) || 0;
|
|
17748
17947
|
}
|
|
17749
17948
|
return 0;
|
|
17750
17949
|
},
|
|
@@ -18072,7 +18271,8 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
18072
18271
|
{
|
|
18073
18272
|
value: headerCheck,
|
|
18074
18273
|
disabled: !hasSelectableRow,
|
|
18075
|
-
onValueChange: toggleAll
|
|
18274
|
+
onValueChange: toggleAll,
|
|
18275
|
+
ariaLabel: selectAllLabel
|
|
18076
18276
|
}
|
|
18077
18277
|
) })
|
|
18078
18278
|
}
|
|
@@ -18118,7 +18318,8 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
18118
18318
|
{
|
|
18119
18319
|
value: headerCheck,
|
|
18120
18320
|
disabled: !hasSelectableRow,
|
|
18121
|
-
onValueChange: toggleAll
|
|
18321
|
+
onValueChange: toggleAll,
|
|
18322
|
+
ariaLabel: selectAllLabel
|
|
18122
18323
|
}
|
|
18123
18324
|
) }),
|
|
18124
18325
|
/* @__PURE__ */ jsx(
|
|
@@ -18318,112 +18519,168 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
18318
18519
|
const rowLocked = (selectable || dragSelectable) && !canSelectRow(row);
|
|
18319
18520
|
const rowBg = "bg-white";
|
|
18320
18521
|
const rowHover = hoverable && !rowLocked;
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
"
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
(
|
|
18338
|
-
dragSelectOn
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
"
|
|
18345
|
-
|
|
18346
|
-
|
|
18347
|
-
|
|
18348
|
-
|
|
18522
|
+
const expansionShown = expansionOn && shownExpansionSet.has(row[rowKey]);
|
|
18523
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
18524
|
+
/* @__PURE__ */ jsxs(
|
|
18525
|
+
"tr",
|
|
18526
|
+
{
|
|
18527
|
+
"data-row-index": rowIndex,
|
|
18528
|
+
onClick: onRowClick ? (event) => {
|
|
18529
|
+
const target = event.target;
|
|
18530
|
+
if (target.closest(ROW_INTERACTIVE_SELECTOR)) return;
|
|
18531
|
+
onRowClick(row);
|
|
18532
|
+
} : void 0,
|
|
18533
|
+
onDoubleClick: onRowDoubleClick ? (event) => {
|
|
18534
|
+
const target = event.target;
|
|
18535
|
+
if (target.closest(ROW_INTERACTIVE_SELECTOR)) return;
|
|
18536
|
+
onRowDoubleClick(row);
|
|
18537
|
+
} : void 0,
|
|
18538
|
+
onMouseDown: dragSelectOn ? (event) => startDragSelect(rowIndex, event) : void 0,
|
|
18539
|
+
onMouseEnter: dragSelectOn ? () => extendDragSelect(rowIndex) : void 0,
|
|
18540
|
+
onContextMenu: contextMenuOn ? (event) => openContextMenu(row, event) : void 0,
|
|
18541
|
+
className: cn(
|
|
18542
|
+
"group/table-row",
|
|
18543
|
+
rowHover && "hover:bg-[var(--color-grey-05)]",
|
|
18544
|
+
(onRowClick || onRowDoubleClick) && "cursor-pointer",
|
|
18545
|
+
dragSelectOn && "select-none",
|
|
18546
|
+
rowClassName?.(row)
|
|
18547
|
+
),
|
|
18548
|
+
style: { height: virtualScroll ? effectiveRowHeight : rowH },
|
|
18549
|
+
children: [
|
|
18550
|
+
selectable && /* @__PURE__ */ jsx(
|
|
18551
|
+
"td",
|
|
18552
|
+
{
|
|
18553
|
+
className: cn(
|
|
18554
|
+
// 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
|
|
18555
|
+
"sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle",
|
|
18556
|
+
rowBg,
|
|
18557
|
+
rowHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
|
|
18558
|
+
stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
|
|
18559
|
+
),
|
|
18560
|
+
style: {
|
|
18561
|
+
width: SELECTABLE_COLUMN_WIDTH,
|
|
18562
|
+
minWidth: SELECTABLE_COLUMN_WIDTH,
|
|
18563
|
+
maxWidth: SELECTABLE_COLUMN_WIDTH,
|
|
18564
|
+
// 선택 열도 행의 일부다 — 여기만 희지 않으면 회색 줄이 끊긴다
|
|
18565
|
+
background: rowLocked ? LOCKED_BG : void 0
|
|
18566
|
+
},
|
|
18567
|
+
onClick: (e) => e.stopPropagation(),
|
|
18568
|
+
onDoubleClick: (e) => e.stopPropagation(),
|
|
18569
|
+
onClickCapture: (e) => {
|
|
18570
|
+
shiftPressedRef.current = e.shiftKey;
|
|
18571
|
+
if (e.shiftKey) window.getSelection()?.removeAllRanges();
|
|
18572
|
+
},
|
|
18573
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex select-none items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
18574
|
+
SCheckbox,
|
|
18575
|
+
{
|
|
18576
|
+
value: isSel || !isRowIndeterminate?.(row) ? isSel : null,
|
|
18577
|
+
disabled: !canSelectRow(row),
|
|
18578
|
+
onValueChange: () => toggleRow(row, rowOffset + ri),
|
|
18579
|
+
ariaLabel: rowSelectLabel?.(row) ?? "\uD589 \uC120\uD0DD"
|
|
18580
|
+
}
|
|
18581
|
+
) })
|
|
18582
|
+
}
|
|
18583
|
+
),
|
|
18584
|
+
visibleCols.map((col, i) => {
|
|
18585
|
+
const tdClassName = cn(
|
|
18586
|
+
// 원본 .td: 컬럼 폭에 맞춰 내용 말줄임(overflow hidden + ellipsis) + 행 구분선(border-b)
|
|
18587
|
+
// 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
|
|
18588
|
+
"overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
|
|
18349
18589
|
rowBg,
|
|
18350
18590
|
rowHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
|
|
18351
|
-
|
|
18352
|
-
)
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18591
|
+
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
18592
|
+
);
|
|
18593
|
+
const tdPadX = cellPadXOf(col);
|
|
18594
|
+
const dragEdges = dragSel ? [
|
|
18595
|
+
dragTop && `inset 0 ${DRAG_EDGE_W} 0 0 ${DRAG_EDGE_C}`,
|
|
18596
|
+
dragBottom && `inset 0 ${DRAG_EDGE_NEG_W} 0 0 ${DRAG_EDGE_C}`,
|
|
18597
|
+
i === 0 && `inset ${DRAG_EDGE_W} 0 0 0 ${DRAG_EDGE_C}`,
|
|
18598
|
+
i === visibleCols.length - 1 && `inset ${DRAG_EDGE_NEG_W} 0 0 0 ${DRAG_EDGE_C}`
|
|
18599
|
+
].filter(Boolean) : [];
|
|
18600
|
+
const shadows = [...dragEdges, stickyShadowValue(i)].filter(Boolean);
|
|
18601
|
+
const tdStyle = {
|
|
18602
|
+
paddingLeft: tdPadX,
|
|
18603
|
+
paddingRight: tdPadX,
|
|
18604
|
+
paddingTop: cellPadY,
|
|
18605
|
+
paddingBottom: cellPadY,
|
|
18606
|
+
textAlign: col.align ?? "left",
|
|
18607
|
+
// 인라인이라 hover 배경보다 세다 — 고른 행은 hover 로 흐려지지 않는다.
|
|
18608
|
+
background: dragSel ? DRAG_BG : rowLocked ? LOCKED_BG : void 0,
|
|
18609
|
+
// 클래스의 기본 글자색을 덮는다. 셀이 자기 색을 정한 내용(SIcon 의
|
|
18610
|
+
// color, STag 등)까지는 닿지 않는다 — 그건 소비 앱 몫이다.
|
|
18611
|
+
color: rowLocked ? LOCKED_CONTENT : void 0,
|
|
18612
|
+
boxShadow: shadows.length > 0 ? shadows.join(", ") : void 0,
|
|
18613
|
+
...cellStyle(i)
|
|
18614
|
+
};
|
|
18615
|
+
if (col.renderCell) {
|
|
18616
|
+
const cell = col.renderCell({
|
|
18617
|
+
row,
|
|
18618
|
+
value: cellValue(col, row),
|
|
18619
|
+
column: col,
|
|
18620
|
+
colIndex: i,
|
|
18621
|
+
rowIndex: ri,
|
|
18622
|
+
isSelected: isSel,
|
|
18623
|
+
className: tdClassName,
|
|
18624
|
+
style: tdStyle
|
|
18625
|
+
});
|
|
18626
|
+
if (cell == null || cell === false) return null;
|
|
18627
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: cell }, col.name);
|
|
18628
|
+
}
|
|
18629
|
+
const content = col.render ? col.render(row, cellValue(col, row)) : cellValue(col, row);
|
|
18630
|
+
if (i === expansionColIndex) {
|
|
18631
|
+
return /* @__PURE__ */ jsx(
|
|
18632
|
+
"td",
|
|
18633
|
+
{
|
|
18634
|
+
className: cn(tdClassName, "cursor-pointer"),
|
|
18635
|
+
style: tdStyle,
|
|
18636
|
+
onClick: (event) => {
|
|
18637
|
+
if (isOwnControl(event.target, event.currentTarget)) return;
|
|
18638
|
+
event.stopPropagation();
|
|
18639
|
+
toggleExpanded(row);
|
|
18640
|
+
},
|
|
18641
|
+
onDoubleClick: (event) => event.stopPropagation(),
|
|
18642
|
+
children: /* @__PURE__ */ jsx(ExpansionToggleCell, { expanded: isRowExpanded(row), children: content })
|
|
18643
|
+
},
|
|
18644
|
+
col.name
|
|
18645
|
+
);
|
|
18646
|
+
}
|
|
18647
|
+
return /* @__PURE__ */ jsx("td", { className: tdClassName, style: tdStyle, children: content }, col.name);
|
|
18648
|
+
})
|
|
18649
|
+
]
|
|
18650
|
+
}
|
|
18651
|
+
),
|
|
18652
|
+
expansionShown && // 상세 영역 — 행이 아니므로 data-row-index 를 달지 않는다 (행 수·선택·실측 대상 밖)
|
|
18653
|
+
/* @__PURE__ */ jsx(
|
|
18654
|
+
"tr",
|
|
18655
|
+
{
|
|
18656
|
+
"data-expansion-row": "",
|
|
18657
|
+
"data-expansion-key": String(row[rowKey]),
|
|
18658
|
+
className: expandedSet.has(row[rowKey]) ? void 0 : "pointer-events-none",
|
|
18659
|
+
children: /* @__PURE__ */ jsx(
|
|
18660
|
+
"td",
|
|
18661
|
+
{
|
|
18662
|
+
colSpan: totalColSpan,
|
|
18663
|
+
className: "whitespace-normal border-b border-solid border-[color:var(--cmp-table-border-color)] bg-white p-0 text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
|
|
18664
|
+
children: /* @__PURE__ */ jsx(
|
|
18665
|
+
"div",
|
|
18368
18666
|
{
|
|
18369
|
-
|
|
18370
|
-
|
|
18371
|
-
|
|
18667
|
+
className: "sticky left-0 box-border min-w-0",
|
|
18668
|
+
style: {
|
|
18669
|
+
// 가로 스크롤이 있어도 보이는 폭에 머문다. 재기 전(0)에는 표 폭을 따른다
|
|
18670
|
+
width: viewportWidth > 0 ? viewportWidth : void 0,
|
|
18671
|
+
paddingLeft: "var(--cmp-table-body-paddingX-wide)",
|
|
18672
|
+
paddingRight: "var(--cmp-table-body-paddingX-wide)",
|
|
18673
|
+
paddingTop: cellPadY,
|
|
18674
|
+
paddingBottom: cellPadY
|
|
18675
|
+
},
|
|
18676
|
+
children: renderExpansion?.(row)
|
|
18372
18677
|
}
|
|
18373
|
-
)
|
|
18374
|
-
}
|
|
18375
|
-
),
|
|
18376
|
-
visibleCols.map((col, i) => {
|
|
18377
|
-
const tdClassName = cn(
|
|
18378
|
-
// 원본 .td: 컬럼 폭에 맞춰 내용 말줄임(overflow hidden + ellipsis) + 행 구분선(border-b)
|
|
18379
|
-
// 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
|
|
18380
|
-
"overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
|
|
18381
|
-
rowBg,
|
|
18382
|
-
rowHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
|
|
18383
|
-
typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
|
|
18384
|
-
);
|
|
18385
|
-
const tdPadX = cellPadXOf(col);
|
|
18386
|
-
const dragEdges = dragSel ? [
|
|
18387
|
-
dragTop && `inset 0 ${DRAG_EDGE_W} 0 0 ${DRAG_EDGE_C}`,
|
|
18388
|
-
dragBottom && `inset 0 ${DRAG_EDGE_NEG_W} 0 0 ${DRAG_EDGE_C}`,
|
|
18389
|
-
i === 0 && `inset ${DRAG_EDGE_W} 0 0 0 ${DRAG_EDGE_C}`,
|
|
18390
|
-
i === visibleCols.length - 1 && `inset ${DRAG_EDGE_NEG_W} 0 0 0 ${DRAG_EDGE_C}`
|
|
18391
|
-
].filter(Boolean) : [];
|
|
18392
|
-
const shadows = [...dragEdges, stickyShadowValue(i)].filter(Boolean);
|
|
18393
|
-
const tdStyle = {
|
|
18394
|
-
paddingLeft: tdPadX,
|
|
18395
|
-
paddingRight: tdPadX,
|
|
18396
|
-
paddingTop: cellPadY,
|
|
18397
|
-
paddingBottom: cellPadY,
|
|
18398
|
-
textAlign: col.align ?? "left",
|
|
18399
|
-
// 인라인이라 hover 배경보다 세다 — 고른 행은 hover 로 흐려지지 않는다.
|
|
18400
|
-
background: dragSel ? DRAG_BG : rowLocked ? LOCKED_BG : void 0,
|
|
18401
|
-
// 클래스의 기본 글자색을 덮는다. 셀이 자기 색을 정한 내용(SIcon 의
|
|
18402
|
-
// color, STag 등)까지는 닿지 않는다 — 그건 소비 앱 몫이다.
|
|
18403
|
-
color: rowLocked ? LOCKED_CONTENT : void 0,
|
|
18404
|
-
boxShadow: shadows.length > 0 ? shadows.join(", ") : void 0,
|
|
18405
|
-
...cellStyle(i)
|
|
18406
|
-
};
|
|
18407
|
-
if (col.renderCell) {
|
|
18408
|
-
const cell = col.renderCell({
|
|
18409
|
-
row,
|
|
18410
|
-
value: cellValue(col, row),
|
|
18411
|
-
column: col,
|
|
18412
|
-
colIndex: i,
|
|
18413
|
-
rowIndex: ri,
|
|
18414
|
-
isSelected: isSel,
|
|
18415
|
-
className: tdClassName,
|
|
18416
|
-
style: tdStyle
|
|
18417
|
-
});
|
|
18418
|
-
if (cell == null || cell === false) return null;
|
|
18419
|
-
return /* @__PURE__ */ jsx(Fragment$1, { children: cell }, col.name);
|
|
18678
|
+
)
|
|
18420
18679
|
}
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
row[rowKey] ?? ri
|
|
18426
|
-
);
|
|
18680
|
+
)
|
|
18681
|
+
}
|
|
18682
|
+
)
|
|
18683
|
+
] }, row[rowKey] ?? ri);
|
|
18427
18684
|
}),
|
|
18428
18685
|
virtualScroll && bottomSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: bottomSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) })
|
|
18429
18686
|
] })
|
|
@@ -18549,6 +18806,26 @@ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
|
|
|
18549
18806
|
);
|
|
18550
18807
|
});
|
|
18551
18808
|
var STable2 = STableImpl;
|
|
18809
|
+
function isOwnControl(target, cell) {
|
|
18810
|
+
if (!(target instanceof Element)) return false;
|
|
18811
|
+
if (target.closest("[data-expansion-toggle]")) return false;
|
|
18812
|
+
const control = target.closest(ROW_INTERACTIVE_SELECTOR);
|
|
18813
|
+
return control != null && cell.contains(control);
|
|
18814
|
+
}
|
|
18815
|
+
function ExpansionToggleCell({ expanded, children }) {
|
|
18816
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
18817
|
+
/* @__PURE__ */ jsx("span", { "data-expansion-toggle": true, className: "flex shrink-0", children: /* @__PURE__ */ jsx(
|
|
18818
|
+
SGhostButton,
|
|
18819
|
+
{
|
|
18820
|
+
icon: expanded ? "caretDown" : "caretRight",
|
|
18821
|
+
size: "xxs",
|
|
18822
|
+
ariaLabel: expanded ? "collapse row" : "expand row",
|
|
18823
|
+
ariaExpanded: expanded
|
|
18824
|
+
}
|
|
18825
|
+
) }),
|
|
18826
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children })
|
|
18827
|
+
] });
|
|
18828
|
+
}
|
|
18552
18829
|
var COUNT_NULL = "var(--cmp-table-bar-count-null)";
|
|
18553
18830
|
var totalColor = (n) => n > 0 ? "var(--cmp-table-bar-count-total)" : COUNT_NULL;
|
|
18554
18831
|
var selectedColor = (n) => n > 0 ? "var(--color-brilliantblue-75)" : COUNT_NULL;
|
|
@@ -18617,9 +18894,7 @@ var STableBar = /* @__PURE__ */ forwardRef(function STableBar2({ title, total, s
|
|
|
18617
18894
|
}
|
|
18618
18895
|
);
|
|
18619
18896
|
});
|
|
18620
|
-
var
|
|
18621
|
-
var EXPAND_MOTION = { duration: 220, easing: "ease-out" };
|
|
18622
|
-
var COLLAPSE_MOTION = { duration: 140, easing: "ease-in" };
|
|
18897
|
+
var NO_KEYS2 = /* @__PURE__ */ new Set();
|
|
18623
18898
|
function STreeTable({
|
|
18624
18899
|
rows = [],
|
|
18625
18900
|
columns = [],
|
|
@@ -18672,11 +18947,11 @@ function STreeTable({
|
|
|
18672
18947
|
[rows, expandedSet, rowKey, childrenKey]
|
|
18673
18948
|
);
|
|
18674
18949
|
const tableRef = useRef(null);
|
|
18675
|
-
const [closingKeys, setClosingKeys] = useState(
|
|
18950
|
+
const [closingKeys, setClosingKeys] = useState(NO_KEYS2);
|
|
18676
18951
|
const [prevExpand, setPrevExpand] = useState({ rows, expandedSet });
|
|
18677
18952
|
if (prevExpand.rows !== rows || prevExpand.expandedSet !== expandedSet) {
|
|
18678
18953
|
setPrevExpand({ rows, expandedSet });
|
|
18679
|
-
let nextClosing =
|
|
18954
|
+
let nextClosing = NO_KEYS2;
|
|
18680
18955
|
if (prevExpand.rows === rows && motionAllowed()) {
|
|
18681
18956
|
const collapsed = [...prevExpand.expandedSet].filter((key) => !expandedSet.has(key));
|
|
18682
18957
|
const expanded = [...expandedSet].filter((key) => !prevExpand.expandedSet.has(key));
|
|
@@ -18725,11 +19000,15 @@ function STreeTable({
|
|
|
18725
19000
|
motionRef.current = null;
|
|
18726
19001
|
}
|
|
18727
19002
|
const scrollEl = tableRef.current?.getScrollElement();
|
|
19003
|
+
const rowKeys = renderedRows.map(keyOf);
|
|
18728
19004
|
const keys = added.size > 0 ? added : removed;
|
|
18729
19005
|
const canAnimate = scrollEl != null && motionAllowed() && (added.size === 0 || removed.size === 0);
|
|
18730
19006
|
const motion = canAnimate ? startRowMotion({
|
|
18731
19007
|
scrollEl,
|
|
18732
|
-
|
|
19008
|
+
isInBlock: (tr) => {
|
|
19009
|
+
const key = rowKeys[Number(tr.dataset.rowIndex)];
|
|
19010
|
+
return key !== void 0 && keys.has(key);
|
|
19011
|
+
},
|
|
18733
19012
|
blockKeys: keys,
|
|
18734
19013
|
from,
|
|
18735
19014
|
to: added.size > 0 ? 1 : 0
|
|
@@ -18740,11 +19019,11 @@ function STreeTable({
|
|
|
18740
19019
|
void motion.finished.then((completed) => {
|
|
18741
19020
|
if (!completed || motionRef.current !== motion) return;
|
|
18742
19021
|
motion.done = true;
|
|
18743
|
-
setClosingKeys(
|
|
19022
|
+
setClosingKeys(NO_KEYS2);
|
|
18744
19023
|
});
|
|
18745
19024
|
}
|
|
18746
19025
|
} else if (closingKeys.size > 0) {
|
|
18747
|
-
setClosingKeys(
|
|
19026
|
+
setClosingKeys(NO_KEYS2);
|
|
18748
19027
|
}
|
|
18749
19028
|
}, [renderedRows]);
|
|
18750
19029
|
useEffect(() => () => motionRef.current?.cancel(), []);
|
|
@@ -18817,7 +19096,7 @@ function STreeTable({
|
|
|
18817
19096
|
className: cn(className, hasChildren && "cursor-pointer"),
|
|
18818
19097
|
style,
|
|
18819
19098
|
onClick: hasChildren ? (event) => {
|
|
18820
|
-
if (
|
|
19099
|
+
if (isOwnControl2(event.target, event.currentTarget)) return;
|
|
18821
19100
|
event.stopPropagation();
|
|
18822
19101
|
toggleExpanded(row);
|
|
18823
19102
|
} : void 0,
|
|
@@ -18872,96 +19151,8 @@ function flattenRows(nodes, isOpen, childrenOf) {
|
|
|
18872
19151
|
walk(nodes);
|
|
18873
19152
|
return out;
|
|
18874
19153
|
}
|
|
18875
|
-
function sameKeys(a, b) {
|
|
18876
|
-
return a.size === b.size && [...a].every((key) => b.has(key));
|
|
18877
|
-
}
|
|
18878
|
-
function motionAllowed() {
|
|
18879
|
-
if (typeof window === "undefined" || typeof Element.prototype.animate !== "function")
|
|
18880
|
-
return false;
|
|
18881
|
-
return !window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
18882
|
-
}
|
|
18883
|
-
function startRowMotion({
|
|
18884
|
-
scrollEl,
|
|
18885
|
-
rowKeys,
|
|
18886
|
-
blockKeys,
|
|
18887
|
-
from,
|
|
18888
|
-
to
|
|
18889
|
-
}) {
|
|
18890
|
-
const spec = to === 1 ? EXPAND_MOTION : COLLAPSE_MOTION;
|
|
18891
|
-
const duration = spec.duration * Math.abs(to - from);
|
|
18892
|
-
if (duration < 1) return null;
|
|
18893
|
-
const trs = [...scrollEl.querySelectorAll("tr[data-row-index]")].map((tr) => {
|
|
18894
|
-
const key = rowKeys[Number(tr.dataset.rowIndex)];
|
|
18895
|
-
return {
|
|
18896
|
-
tr,
|
|
18897
|
-
inBlock: key !== void 0 && blockKeys.has(key),
|
|
18898
|
-
height: tr.getBoundingClientRect().height
|
|
18899
|
-
};
|
|
18900
|
-
});
|
|
18901
|
-
const viewBottom = scrollEl.scrollTop + scrollEl.clientHeight;
|
|
18902
|
-
const openAt = (offset) => from + (to - from) * offset;
|
|
18903
|
-
const translate = (shift2, s) => `translateY(${-shift2 * (1 - s)}px)`;
|
|
18904
|
-
const timing = {
|
|
18905
|
-
duration,
|
|
18906
|
-
easing: spec.easing,
|
|
18907
|
-
// 접힘은 남겨 둔 행이 빠질 때까지 끝 위치를 붙잡는다 — 놓으면 그 사이 한 프레임 제자리로 튄다
|
|
18908
|
-
fill: to === 0 ? "forwards" : "none"
|
|
18909
|
-
};
|
|
18910
|
-
const animations = [];
|
|
18911
|
-
let shift = 0;
|
|
18912
|
-
let blockHeight = 0;
|
|
18913
|
-
let y = 0;
|
|
18914
|
-
trs.forEach(({ tr, inBlock, height }, i) => {
|
|
18915
|
-
if (inBlock && !trs[i - 1]?.inBlock) {
|
|
18916
|
-
blockHeight = 0;
|
|
18917
|
-
for (let j = i; j < trs.length && trs[j].inBlock; j++) blockHeight += trs[j].height;
|
|
18918
|
-
shift += blockHeight;
|
|
18919
|
-
y = 0;
|
|
18920
|
-
}
|
|
18921
|
-
if (shift === 0 || tr.offsetTop - shift > viewBottom) return;
|
|
18922
|
-
if (!inBlock) {
|
|
18923
|
-
animations.push(
|
|
18924
|
-
tr.animate(
|
|
18925
|
-
[{ transform: translate(shift, from) }, { transform: translate(shift, to) }],
|
|
18926
|
-
timing
|
|
18927
|
-
)
|
|
18928
|
-
);
|
|
18929
|
-
return;
|
|
18930
|
-
}
|
|
18931
|
-
const rowY = y;
|
|
18932
|
-
const clipAt = (s) => Math.min(height, Math.max(0, blockHeight * (1 - s) - rowY));
|
|
18933
|
-
const bends = [1 - rowY / blockHeight, 1 - (rowY + height) / blockHeight].map((s) => (s - from) / (to - from)).filter((offset) => offset > 0 && offset < 1);
|
|
18934
|
-
const offsets = [0, ...bends, 1].sort((a, b) => a - b);
|
|
18935
|
-
animations.push(
|
|
18936
|
-
tr.animate(
|
|
18937
|
-
offsets.map((offset) => ({
|
|
18938
|
-
offset,
|
|
18939
|
-
transform: translate(shift, openAt(offset)),
|
|
18940
|
-
clipPath: `inset(${clipAt(openAt(offset))}px 0 0 0)`
|
|
18941
|
-
})),
|
|
18942
|
-
timing
|
|
18943
|
-
)
|
|
18944
|
-
);
|
|
18945
|
-
y += height;
|
|
18946
|
-
});
|
|
18947
|
-
if (animations.length === 0) return null;
|
|
18948
|
-
return {
|
|
18949
|
-
keys: blockKeys,
|
|
18950
|
-
to,
|
|
18951
|
-
done: false,
|
|
18952
|
-
finished: Promise.all(animations.map((animation) => animation.finished)).then(
|
|
18953
|
-
() => true,
|
|
18954
|
-
() => false
|
|
18955
|
-
),
|
|
18956
|
-
openness: () => {
|
|
18957
|
-
const progress = animations[0].effect?.getComputedTiming().progress;
|
|
18958
|
-
return progress == null ? to : openAt(progress);
|
|
18959
|
-
},
|
|
18960
|
-
cancel: () => animations.forEach((animation) => animation.cancel())
|
|
18961
|
-
};
|
|
18962
|
-
}
|
|
18963
19154
|
var OWN_CONTROL_SELECTOR = 'a, button, input, select, textarea, label, [role="button"], [role="checkbox"], [contenteditable="true"]';
|
|
18964
|
-
function
|
|
19155
|
+
function isOwnControl2(target, cell) {
|
|
18965
19156
|
if (!(target instanceof Element)) return false;
|
|
18966
19157
|
if (target.closest("[data-tree-toggle]")) return false;
|
|
18967
19158
|
const control = target.closest(OWN_CONTROL_SELECTOR);
|