twico-ui 1.14.1 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/index.cjs +190 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.mjs +190 -149
- package/dist/index.mjs.map +1 -1
- package/llms.txt +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Twico UI are documented here (newest first). This file is generated automatically on each release by [semantic-release](https://semantic-release.gitbook.io/) from [Conventional Commits](https://www.conventionalcommits.org/) — do not edit it by hand. The same notes appear on each [GitHub Release](https://github.com/EncryptionL/twico-ui/releases).
|
|
4
4
|
|
|
5
|
+
# [1.15.0](https://github.com/EncryptionL/twico-ui/compare/v1.14.1...v1.15.0) (2026-07-14)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **datatable:** add `diff` mode — re-home DiffTable on the Datatable engine ([#239](https://github.com/EncryptionL/twico-ui/issues/239)) ([d7cf524](https://github.com/EncryptionL/twico-ui/commit/d7cf524e44e579318b36ead62aa13b832142cd89)), closes [#205](https://github.com/EncryptionL/twico-ui/issues/205)
|
|
11
|
+
|
|
5
12
|
## [1.14.1](https://github.com/EncryptionL/twico-ui/compare/v1.14.0...v1.14.1) (2026-07-14)
|
|
6
13
|
|
|
7
14
|
|
package/dist/index.cjs
CHANGED
|
@@ -8034,6 +8034,78 @@ function Tooltip({
|
|
|
8034
8034
|
}
|
|
8035
8035
|
);
|
|
8036
8036
|
}
|
|
8037
|
+
|
|
8038
|
+
// components/_diff.js
|
|
8039
|
+
var DIFF_OPS = {
|
|
8040
|
+
added: { label: "Added", tone: "success" },
|
|
8041
|
+
removed: { label: "Removed", tone: "danger" },
|
|
8042
|
+
modified: { label: "Modified", tone: "warning" },
|
|
8043
|
+
moved: { label: "Moved", tone: "info" },
|
|
8044
|
+
unchanged: { label: "Unchanged", tone: "neutral" }
|
|
8045
|
+
};
|
|
8046
|
+
function lisIndexSet(seq) {
|
|
8047
|
+
const n = seq.length;
|
|
8048
|
+
if (n === 0) return /* @__PURE__ */ new Set();
|
|
8049
|
+
const dp = new Array(n).fill(1), prev = new Array(n).fill(-1);
|
|
8050
|
+
let best = 0;
|
|
8051
|
+
for (let i = 0; i < n; i++) {
|
|
8052
|
+
for (let j = 0; j < i; j++) {
|
|
8053
|
+
if (seq[j] < seq[i] && dp[j] + 1 > dp[i]) {
|
|
8054
|
+
dp[i] = dp[j] + 1;
|
|
8055
|
+
prev[i] = j;
|
|
8056
|
+
}
|
|
8057
|
+
}
|
|
8058
|
+
if (dp[i] > dp[best]) best = i;
|
|
8059
|
+
}
|
|
8060
|
+
const set = /* @__PURE__ */ new Set();
|
|
8061
|
+
for (let i = best; i !== -1; i = prev[i]) set.add(i);
|
|
8062
|
+
return set;
|
|
8063
|
+
}
|
|
8064
|
+
var cellVal = (col, row) => col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col.field];
|
|
8065
|
+
function classifyDiff(from = [], to = [], columns = [], rowKey, opts = {}) {
|
|
8066
|
+
const { moveDetection = true, compare } = opts;
|
|
8067
|
+
const k = rowKey || ((r2) => r2 == null ? r2 : r2.id);
|
|
8068
|
+
const valEq = (a, b, col) => {
|
|
8069
|
+
if (col.compare) return col.compare(a, b);
|
|
8070
|
+
if (compare) return compare(a, b, col.field);
|
|
8071
|
+
if (a === b) return true;
|
|
8072
|
+
if (a == null || b == null) return a === b;
|
|
8073
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
8074
|
+
};
|
|
8075
|
+
const fromMap = /* @__PURE__ */ new Map(), toMap = /* @__PURE__ */ new Map();
|
|
8076
|
+
from.forEach((r2, i) => fromMap.set(k(r2), { row: r2, i }));
|
|
8077
|
+
to.forEach((r2, i) => toMap.set(k(r2), { row: r2, i }));
|
|
8078
|
+
const movedKeys = /* @__PURE__ */ new Set();
|
|
8079
|
+
if (moveDetection) {
|
|
8080
|
+
const commonFrom = from.filter((r2) => toMap.has(k(r2)));
|
|
8081
|
+
const seq = commonFrom.map((r2) => toMap.get(k(r2)).i);
|
|
8082
|
+
const stable = lisIndexSet(seq);
|
|
8083
|
+
commonFrom.forEach((r2, idx) => {
|
|
8084
|
+
if (!stable.has(idx)) movedKeys.add(k(r2));
|
|
8085
|
+
});
|
|
8086
|
+
}
|
|
8087
|
+
const classify = (key) => {
|
|
8088
|
+
const a = fromMap.get(key), b = toMap.get(key);
|
|
8089
|
+
if (a && !b) return { op: "removed", from: a.row, to: null, changed: /* @__PURE__ */ new Set() };
|
|
8090
|
+
if (!a && b) return { op: "added", from: null, to: b.row, changed: /* @__PURE__ */ new Set() };
|
|
8091
|
+
const changed = /* @__PURE__ */ new Set();
|
|
8092
|
+
for (const col of columns) if (col.field && !valEq(cellVal(col, a.row), cellVal(col, b.row), col)) changed.add(col.field);
|
|
8093
|
+
if (changed.size) return { op: "modified", from: a.row, to: b.row, changed };
|
|
8094
|
+
if (movedKeys.has(key)) return { op: "moved", from: a.row, to: b.row, changed };
|
|
8095
|
+
return { op: "unchanged", from: a.row, to: b.row, changed };
|
|
8096
|
+
};
|
|
8097
|
+
const rows = [];
|
|
8098
|
+
to.forEach((r2) => rows.push({ key: k(r2), ...classify(k(r2)) }));
|
|
8099
|
+
from.forEach((r2) => {
|
|
8100
|
+
const key = k(r2);
|
|
8101
|
+
if (!toMap.has(key)) rows.push({ key, ...classify(key) });
|
|
8102
|
+
});
|
|
8103
|
+
const counts = { added: 0, removed: 0, modified: 0, moved: 0, unchanged: 0 };
|
|
8104
|
+
rows.forEach((r2) => {
|
|
8105
|
+
counts[r2.op] += 1;
|
|
8106
|
+
});
|
|
8107
|
+
return { rows, counts };
|
|
8108
|
+
}
|
|
8037
8109
|
var DT_CSS = `
|
|
8038
8110
|
.twc-dt { display: flex; flex-direction: column; font-family: var(--font-sans); color: var(--color-text);
|
|
8039
8111
|
border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
|
|
@@ -8272,6 +8344,18 @@ var DT_CSS = `
|
|
|
8272
8344
|
/* Row reordering */
|
|
8273
8345
|
.twc-dt__row[data-reorderable] { cursor: grab; }
|
|
8274
8346
|
.twc-dt__row[data-row-dragging] { opacity: 0.4; }
|
|
8347
|
+
/* #239 diff mode: row op tint + before\u2192after cells (single-line, clipped by the td's own overflow). */
|
|
8348
|
+
.twc-dt__row[data-op="added"] > .twc-dt__td { background: color-mix(in srgb, var(--color-success) 7%, transparent); }
|
|
8349
|
+
.twc-dt__row[data-op="removed"] > .twc-dt__td { background: color-mix(in srgb, var(--color-danger) 7%, transparent); }
|
|
8350
|
+
.twc-dt__row[data-op="modified"] > .twc-dt__td { background: color-mix(in srgb, var(--color-warning) 6%, transparent); }
|
|
8351
|
+
.twc-dt__diff-change { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; }
|
|
8352
|
+
.twc-dt__diff-old { text-decoration: line-through; color: var(--color-text-subtle); }
|
|
8353
|
+
.twc-dt__diff-new { color: var(--color-success-subtle-fg); font-weight: var(--font-medium); }
|
|
8354
|
+
.twc-dt__diff-arrow { color: var(--color-text-subtle); flex: none; }
|
|
8355
|
+
[dir="rtl"] .twc-dt__diff-arrow { transform: scaleX(-1); display: inline-block; }
|
|
8356
|
+
.twc-dt__diff-summary { display: inline-flex; align-items: center; gap: 4px; flex: none; }
|
|
8357
|
+
.twc-dt__diff-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--color-text-muted); cursor: pointer; white-space: nowrap; flex: none; }
|
|
8358
|
+
.twc-dt__diff-toggle input { width: 15px; height: 15px; accent-color: var(--color-primary); cursor: pointer; margin: 0; }
|
|
8275
8359
|
.twc-dt__row[data-row-dropbefore] > .twc-dt__td { box-shadow: inset 0 3px 0 var(--color-primary); }
|
|
8276
8360
|
.twc-dt__row[data-row-dropafter] > .twc-dt__td { box-shadow: inset 0 -3px 0 var(--color-primary); }
|
|
8277
8361
|
/* Keyboard row reorder (grabbed) */
|
|
@@ -8533,6 +8617,38 @@ var NUM_OPS = [
|
|
|
8533
8617
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8534
8618
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8535
8619
|
var getColVal = (col, row) => col && col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col && col.field];
|
|
8620
|
+
var diffValueNode = (col, v, row) => col.renderCell ? col.renderCell(v, row) : col.valueFormatter ? col.valueFormatter(v, row) : v == null ? "" : v;
|
|
8621
|
+
function renderDiffCell(col, val, row) {
|
|
8622
|
+
const meta = row && row.__diffMeta;
|
|
8623
|
+
if (!meta) return diffValueNode(col, val, row);
|
|
8624
|
+
if (meta.op === "removed") return React51__namespace.default.createElement("span", { className: "twc-dt__diff-old" }, diffValueNode(col, getColVal(col, meta.from), meta.from));
|
|
8625
|
+
if (meta.op === "added") return React51__namespace.default.createElement("span", { className: "twc-dt__diff-new" }, diffValueNode(col, getColVal(col, meta.to), meta.to));
|
|
8626
|
+
if (meta.op === "modified" && meta.changed.has(col.field)) {
|
|
8627
|
+
return React51__namespace.default.createElement(
|
|
8628
|
+
"span",
|
|
8629
|
+
{ className: "twc-dt__diff-change" },
|
|
8630
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-old" }, diffValueNode(col, getColVal(col, meta.from), meta.from)),
|
|
8631
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-arrow", "aria-hidden": "true" }, "\u2192"),
|
|
8632
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-new" }, diffValueNode(col, getColVal(col, meta.to), meta.to))
|
|
8633
|
+
);
|
|
8634
|
+
}
|
|
8635
|
+
return diffValueNode(col, val, row);
|
|
8636
|
+
}
|
|
8637
|
+
var DIFF_OP_COLUMN = {
|
|
8638
|
+
field: "__diffop",
|
|
8639
|
+
headerName: "Change",
|
|
8640
|
+
width: 122,
|
|
8641
|
+
pinned: "left",
|
|
8642
|
+
sortable: true,
|
|
8643
|
+
filterable: false,
|
|
8644
|
+
groupable: true,
|
|
8645
|
+
reorderable: false,
|
|
8646
|
+
resizable: true,
|
|
8647
|
+
wrappable: false,
|
|
8648
|
+
hideable: false,
|
|
8649
|
+
renderCell: (v) => v && DIFF_OPS[v] ? React51__namespace.default.createElement(Badge, { size: "sm", variant: "soft", tone: DIFF_OPS[v].tone }, DIFF_OPS[v].label) : null,
|
|
8650
|
+
exportValue: (v) => v && DIFF_OPS[v] ? DIFF_OPS[v].label : ""
|
|
8651
|
+
};
|
|
8536
8652
|
function testFilter(raw, op, target, type) {
|
|
8537
8653
|
if (op === "isEmpty") return raw == null || raw === "";
|
|
8538
8654
|
if (op === "isNotEmpty") return !(raw == null || raw === "");
|
|
@@ -8851,11 +8967,12 @@ function xlsxPackage(sheetXml) {
|
|
|
8851
8967
|
]);
|
|
8852
8968
|
}
|
|
8853
8969
|
function Datatable({
|
|
8854
|
-
columns,
|
|
8855
|
-
rows,
|
|
8970
|
+
columns: columnsProp,
|
|
8971
|
+
rows: rowsProp = [],
|
|
8856
8972
|
loading = false,
|
|
8857
|
-
rowKey,
|
|
8973
|
+
rowKey: rowKeyProp,
|
|
8858
8974
|
checkboxSelection = false,
|
|
8975
|
+
diff,
|
|
8859
8976
|
density: densityProp = "comfortable",
|
|
8860
8977
|
pageSize = 10,
|
|
8861
8978
|
pageSizeOptions = [5, 10, 25, 50],
|
|
@@ -8908,6 +9025,29 @@ function Datatable({
|
|
|
8908
9025
|
...rest
|
|
8909
9026
|
}) {
|
|
8910
9027
|
const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
|
|
9028
|
+
const isDiff = !!diff;
|
|
9029
|
+
const [diffOnly, setDiffOnly] = React51__namespace.default.useState(diff && diff.onlyChanged !== void 0 ? diff.onlyChanged : true);
|
|
9030
|
+
const diffRowKey = diff && diff.rowKey || rowKeyProp || ((r2) => r2 == null ? r2 : r2.id);
|
|
9031
|
+
const diffData = React51__namespace.default.useMemo(
|
|
9032
|
+
() => isDiff ? classifyDiff(diff.from || [], diff.to || [], columnsProp, diffRowKey, { moveDetection: diff.moveDetection, compare: diff.compare }) : null,
|
|
9033
|
+
[isDiff, diff, columnsProp]
|
|
9034
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
9035
|
+
);
|
|
9036
|
+
const onClassifiedRef = React51__namespace.default.useRef(diff && diff.onClassified);
|
|
9037
|
+
onClassifiedRef.current = diff && diff.onClassified;
|
|
9038
|
+
React51__namespace.default.useEffect(() => {
|
|
9039
|
+
if (diffData && onClassifiedRef.current) onClassifiedRef.current(diffData.counts);
|
|
9040
|
+
}, [diffData]);
|
|
9041
|
+
const diffRowKeyFn = React51__namespace.default.useCallback((r2) => r2.__diffKey, []);
|
|
9042
|
+
const columns = React51__namespace.default.useMemo(
|
|
9043
|
+
() => isDiff ? [DIFF_OP_COLUMN, ...columnsProp.map((c) => ({ ...c, renderCell: (val, row) => renderDiffCell(c, val, row) }))] : columnsProp,
|
|
9044
|
+
[isDiff, columnsProp]
|
|
9045
|
+
);
|
|
9046
|
+
const rows = React51__namespace.default.useMemo(
|
|
9047
|
+
() => isDiff ? diffData.rows.filter((r2) => !diffOnly || r2.op !== "unchanged").map((r2) => ({ ...r2.to || r2.from, __diffop: r2.op, __diffMeta: r2, __diffKey: r2.key })) : rowsProp,
|
|
9048
|
+
[isDiff, diffData, diffOnly, rowsProp]
|
|
9049
|
+
);
|
|
9050
|
+
const rowKey = isDiff ? diffRowKeyFn : rowKeyProp;
|
|
8911
9051
|
const cols = React51__namespace.default.useMemo(() => {
|
|
8912
9052
|
const out = columns.map((c) => {
|
|
8913
9053
|
const isActions = c.type === "actions";
|
|
@@ -10104,6 +10244,7 @@ function Datatable({
|
|
|
10104
10244
|
role: "row",
|
|
10105
10245
|
"aria-rowindex": (paginated && !serverMode ? pageVal * sizeVal : 0) + ri + 2,
|
|
10106
10246
|
"aria-selected": (checkboxSelection ? sel : rowActive) || void 0,
|
|
10247
|
+
"data-op": row.__diffop || void 0,
|
|
10107
10248
|
"data-selected": sel || void 0,
|
|
10108
10249
|
"data-active": rowActive || void 0,
|
|
10109
10250
|
"data-pinned-row": pinSide || void 0,
|
|
@@ -10354,6 +10495,28 @@ function Datatable({
|
|
|
10354
10495
|
))
|
|
10355
10496
|
] })
|
|
10356
10497
|
] }) : null,
|
|
10498
|
+
isDiff && diff.showSummary !== false ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__diff-summary", "aria-label": "Diff summary", children: [
|
|
10499
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "success", children: [
|
|
10500
|
+
"+",
|
|
10501
|
+
diffData.counts.added
|
|
10502
|
+
] }),
|
|
10503
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "warning", children: [
|
|
10504
|
+
"~",
|
|
10505
|
+
diffData.counts.modified
|
|
10506
|
+
] }),
|
|
10507
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "danger", children: [
|
|
10508
|
+
"\u2212",
|
|
10509
|
+
diffData.counts.removed
|
|
10510
|
+
] }),
|
|
10511
|
+
diffData.counts.moved ? /* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "info", children: [
|
|
10512
|
+
"\u21C5",
|
|
10513
|
+
diffData.counts.moved
|
|
10514
|
+
] }) : null
|
|
10515
|
+
] }) : null,
|
|
10516
|
+
isDiff && diff.showToggle !== false ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-dt__diff-toggle", children: [
|
|
10517
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: diffOnly, onChange: (e) => setDiffOnly(e.target.checked) }),
|
|
10518
|
+
diff.toggleLabel != null ? diff.toggleLabel : "Only changed"
|
|
10519
|
+
] }) : null,
|
|
10357
10520
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10358
10521
|
"button",
|
|
10359
10522
|
{
|
|
@@ -11690,55 +11853,13 @@ function CardGrid({
|
|
|
11690
11853
|
] }) : null
|
|
11691
11854
|
] });
|
|
11692
11855
|
}
|
|
11693
|
-
var
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
.twc-difft__table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
|
|
11701
|
-
.twc-difft__table th, .twc-difft__table td { text-align: start; padding: var(--space-2) var(--space-3); border-bottom: var(--border-thin) solid var(--color-divider); vertical-align: top; }
|
|
11702
|
-
.twc-difft__table thead th { position: sticky; top: 0; background: var(--color-surface-sunken); font-weight: var(--font-semibold); color: var(--color-text-muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap; z-index: 1; }
|
|
11703
|
-
.twc-difft__table tbody tr:last-child td { border-bottom: none; }
|
|
11704
|
-
.twc-difft__table tbody tr[data-op="added"] { background: color-mix(in srgb, var(--color-success) 8%, transparent); }
|
|
11705
|
-
.twc-difft__table tbody tr[data-op="removed"] { background: color-mix(in srgb, var(--color-danger) 8%, transparent); }
|
|
11706
|
-
.twc-difft__table tbody tr[data-op="modified"] { background: color-mix(in srgb, var(--color-warning) 8%, transparent); }
|
|
11707
|
-
.twc-difft__op { white-space: nowrap; }
|
|
11708
|
-
.twc-difft__change { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 2px; }
|
|
11709
|
-
.twc-difft__old { text-decoration: line-through; color: var(--color-text-subtle); }
|
|
11710
|
-
.twc-difft__new { color: var(--color-success-subtle-fg); font-weight: var(--font-medium); }
|
|
11711
|
-
.twc-difft__arrow { margin-inline: 6px; color: var(--color-text-subtle); }
|
|
11712
|
-
.twc-difft__empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--color-text-muted); }
|
|
11713
|
-
[dir="rtl"] .twc-difft__arrow { transform: scaleX(-1); display: inline-block; }
|
|
11714
|
-
`;
|
|
11715
|
-
var OPS = {
|
|
11716
|
-
added: { label: "Added", tone: "success" },
|
|
11717
|
-
removed: { label: "Removed", tone: "danger" },
|
|
11718
|
-
modified: { label: "Modified", tone: "warning" },
|
|
11719
|
-
moved: { label: "Moved", tone: "info" },
|
|
11720
|
-
unchanged: { label: "Unchanged", tone: "neutral" }
|
|
11721
|
-
};
|
|
11722
|
-
function lisIndexSet(seq) {
|
|
11723
|
-
const n = seq.length;
|
|
11724
|
-
if (n === 0) return /* @__PURE__ */ new Set();
|
|
11725
|
-
const dp = new Array(n).fill(1), prev = new Array(n).fill(-1);
|
|
11726
|
-
let best = 0;
|
|
11727
|
-
for (let i = 0; i < n; i++) {
|
|
11728
|
-
for (let j = 0; j < i; j++) {
|
|
11729
|
-
if (seq[j] < seq[i] && dp[j] + 1 > dp[i]) {
|
|
11730
|
-
dp[i] = dp[j] + 1;
|
|
11731
|
-
prev[i] = j;
|
|
11732
|
-
}
|
|
11733
|
-
}
|
|
11734
|
-
if (dp[i] > dp[best]) best = i;
|
|
11735
|
-
}
|
|
11736
|
-
const set = /* @__PURE__ */ new Set();
|
|
11737
|
-
for (let i = best; i !== -1; i = prev[i]) set.add(i);
|
|
11738
|
-
return set;
|
|
11739
|
-
}
|
|
11740
|
-
var getVal = (col, row) => col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col.field];
|
|
11741
|
-
var fmtVal = (col, v) => col.valueFormatter ? col.valueFormatter(v) : v == null ? "" : String(v);
|
|
11856
|
+
var toDatatableColumn = (c) => ({
|
|
11857
|
+
field: c.field,
|
|
11858
|
+
headerName: typeof c.headerName === "string" ? c.headerName : c.field,
|
|
11859
|
+
valueGetter: c.valueGetter,
|
|
11860
|
+
valueFormatter: c.valueFormatter,
|
|
11861
|
+
compare: c.compare
|
|
11862
|
+
});
|
|
11742
11863
|
function DiffTable({
|
|
11743
11864
|
from = [],
|
|
11744
11865
|
to = [],
|
|
@@ -11756,104 +11877,24 @@ function DiffTable({
|
|
|
11756
11877
|
className = "",
|
|
11757
11878
|
...rest
|
|
11758
11879
|
}) {
|
|
11759
|
-
const
|
|
11760
|
-
const
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
const k = rowKey || ((r2) => r2 == null ? r2 : r2.id);
|
|
11772
|
-
const fromMap = /* @__PURE__ */ new Map(), toMap = /* @__PURE__ */ new Map();
|
|
11773
|
-
from.forEach((r2, i) => fromMap.set(k(r2), { row: r2, i }));
|
|
11774
|
-
to.forEach((r2, i) => toMap.set(k(r2), { row: r2, i }));
|
|
11775
|
-
const movedKeys = /* @__PURE__ */ new Set();
|
|
11776
|
-
if (moveDetection) {
|
|
11777
|
-
const commonFrom = from.filter((r2) => toMap.has(k(r2)));
|
|
11778
|
-
const seq = commonFrom.map((r2) => toMap.get(k(r2)).i);
|
|
11779
|
-
const stable = lisIndexSet(seq);
|
|
11780
|
-
commonFrom.forEach((r2, idx) => {
|
|
11781
|
-
if (!stable.has(idx)) movedKeys.add(k(r2));
|
|
11782
|
-
});
|
|
11783
|
-
}
|
|
11784
|
-
const classify = (key) => {
|
|
11785
|
-
const a = fromMap.get(key), b = toMap.get(key);
|
|
11786
|
-
if (a && !b) return { op: "removed", from: a.row, to: null, changed: /* @__PURE__ */ new Set() };
|
|
11787
|
-
if (!a && b) return { op: "added", from: null, to: b.row, changed: /* @__PURE__ */ new Set() };
|
|
11788
|
-
const changed = /* @__PURE__ */ new Set();
|
|
11789
|
-
for (const col of columns) if (!valEq(getVal(col, a.row), getVal(col, b.row), col)) changed.add(col.field);
|
|
11790
|
-
if (changed.size) return { op: "modified", from: a.row, to: b.row, changed };
|
|
11791
|
-
if (movedKeys.has(key)) return { op: "moved", from: a.row, to: b.row, changed };
|
|
11792
|
-
return { op: "unchanged", from: a.row, to: b.row, changed };
|
|
11793
|
-
};
|
|
11794
|
-
const rows = [];
|
|
11795
|
-
to.forEach((r2) => rows.push({ key: k(r2), ...classify(k(r2)) }));
|
|
11796
|
-
from.forEach((r2) => {
|
|
11797
|
-
const key = k(r2);
|
|
11798
|
-
if (!toMap.has(key)) rows.push({ key, ...classify(key) });
|
|
11799
|
-
});
|
|
11800
|
-
const counts = { added: 0, removed: 0, modified: 0, moved: 0, unchanged: 0 };
|
|
11801
|
-
rows.forEach((r2) => {
|
|
11802
|
-
counts[r2.op] += 1;
|
|
11803
|
-
});
|
|
11804
|
-
return { rows, counts };
|
|
11805
|
-
}, [from, to, columns, rowKey, moveDetection, valEq]);
|
|
11806
|
-
const visible = only ? diff.rows.filter((r2) => r2.op !== "unchanged") : diff.rows;
|
|
11807
|
-
const renderCell = (r2, col) => {
|
|
11808
|
-
if (r2.op === "removed") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__old", children: fmtVal(col, getVal(col, r2.from)) });
|
|
11809
|
-
if (r2.op === "added") return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__new", children: fmtVal(col, getVal(col, r2.to)) });
|
|
11810
|
-
if (r2.op === "modified" && r2.changed.has(col.field)) {
|
|
11811
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-difft__change", children: [
|
|
11812
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__old", children: fmtVal(col, getVal(col, r2.from)) }),
|
|
11813
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__arrow", "aria-hidden": "true", children: "\u2192" }),
|
|
11814
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-difft__new", children: fmtVal(col, getVal(col, r2.to)) })
|
|
11815
|
-
] });
|
|
11880
|
+
const dtColumns = React51__namespace.default.useMemo(() => columns.map(toDatatableColumn), [columns]);
|
|
11881
|
+
const diff = React51__namespace.default.useMemo(
|
|
11882
|
+
() => ({ from, to, rowKey, onlyChanged, showToggle, showSummary, moveDetection, compare, toggleLabel }),
|
|
11883
|
+
[from, to, rowKey, onlyChanged, showToggle, showSummary, moveDetection, compare, toggleLabel]
|
|
11884
|
+
);
|
|
11885
|
+
const table = /* @__PURE__ */ jsxRuntime.jsx(
|
|
11886
|
+
Datatable,
|
|
11887
|
+
{
|
|
11888
|
+
columns: dtColumns,
|
|
11889
|
+
diff,
|
|
11890
|
+
emptyMessage: emptyState,
|
|
11891
|
+
...label ? {} : { id, className, ...rest }
|
|
11816
11892
|
}
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
label ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__label", children: label }) : null,
|
|
11823
|
-
showSummary ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-difft__summary", children: [
|
|
11824
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "success", children: [
|
|
11825
|
-
"+",
|
|
11826
|
-
diff.counts.added,
|
|
11827
|
-
" added"
|
|
11828
|
-
] }),
|
|
11829
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "warning", children: [
|
|
11830
|
-
"~",
|
|
11831
|
-
diff.counts.modified,
|
|
11832
|
-
" modified"
|
|
11833
|
-
] }),
|
|
11834
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "danger", children: [
|
|
11835
|
-
"-",
|
|
11836
|
-
diff.counts.removed,
|
|
11837
|
-
" removed"
|
|
11838
|
-
] }),
|
|
11839
|
-
diff.counts.moved ? /* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "info", children: [
|
|
11840
|
-
"\u21C5 ",
|
|
11841
|
-
diff.counts.moved,
|
|
11842
|
-
" moved"
|
|
11843
|
-
] }) : null
|
|
11844
|
-
] }) : null,
|
|
11845
|
-
showToggle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__toggle", children: /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { label: toggleLabel, checked: only, onChange: (e) => setOnly(e.target.checked) }) }) : null
|
|
11846
|
-
] }) : null,
|
|
11847
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-difft__scroll", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "twc-difft__table", children: [
|
|
11848
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
11849
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Change" }),
|
|
11850
|
-
columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: c.headerName || c.field }, c.field))
|
|
11851
|
-
] }) }),
|
|
11852
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: visible.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-difft__empty", colSpan: columns.length + 1, children: emptyState }) }) : visible.map((r2) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { "data-op": r2.op, children: [
|
|
11853
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "twc-difft__op", children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { size: "sm", variant: "soft", tone: OPS[r2.op].tone, children: OPS[r2.op].label }) }),
|
|
11854
|
-
columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: renderCell(r2, c) }, c.field))
|
|
11855
|
-
] }, r2.key)) })
|
|
11856
|
-
] }) })
|
|
11893
|
+
);
|
|
11894
|
+
if (!label) return table;
|
|
11895
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { id, className, ...rest, style: { display: "flex", flexDirection: "column", gap: "var(--space-2)", fontFamily: "var(--font-sans)" }, children: [
|
|
11896
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "var(--text-sm)", fontWeight: "var(--font-semibold)", color: "var(--color-text)" }, children: label }),
|
|
11897
|
+
table
|
|
11857
11898
|
] });
|
|
11858
11899
|
}
|
|
11859
11900
|
var FIELD_CSS3 = `
|