twico-ui 1.14.1 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.cjs +196 -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 +196 -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,20 @@
|
|
|
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.1](https://github.com/EncryptionL/twico-ui/compare/v1.15.0...v1.15.1) (2026-07-14)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **datatable:** keep pinned cells opaque in diff mode ([#242](https://github.com/EncryptionL/twico-ui/issues/242)) ([072b15e](https://github.com/EncryptionL/twico-ui/commit/072b15ea73443ad535b3f149d8b620618702b389)), closes [#239](https://github.com/EncryptionL/twico-ui/issues/239)
|
|
11
|
+
|
|
12
|
+
# [1.15.0](https://github.com/EncryptionL/twico-ui/compare/v1.14.1...v1.15.0) (2026-07-14)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **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)
|
|
18
|
+
|
|
5
19
|
## [1.14.1](https://github.com/EncryptionL/twico-ui/compare/v1.14.0...v1.14.1) (2026-07-14)
|
|
6
20
|
|
|
7
21
|
|
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,24 @@ 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
|
+
/* #242: pinned cells in a diff row must stay OPAQUE (composite the tint over the surface, not over
|
|
8352
|
+
transparent) or the cells scrolling under a sticky column bleed through. Specificity (0,4,0) wins
|
|
8353
|
+
over the (0,3,0) tint above and matches the non-pinned cells' effective color (tint over surface). */
|
|
8354
|
+
.twc-dt__row[data-op="added"] > .twc-dt__td[data-pin] { background: color-mix(in srgb, var(--color-success) 7%, var(--color-surface)); }
|
|
8355
|
+
.twc-dt__row[data-op="removed"] > .twc-dt__td[data-pin] { background: color-mix(in srgb, var(--color-danger) 7%, var(--color-surface)); }
|
|
8356
|
+
.twc-dt__row[data-op="modified"] > .twc-dt__td[data-pin] { background: color-mix(in srgb, var(--color-warning) 6%, var(--color-surface)); }
|
|
8357
|
+
.twc-dt__diff-change { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; }
|
|
8358
|
+
.twc-dt__diff-old { text-decoration: line-through; color: var(--color-text-subtle); }
|
|
8359
|
+
.twc-dt__diff-new { color: var(--color-success-subtle-fg); font-weight: var(--font-medium); }
|
|
8360
|
+
.twc-dt__diff-arrow { color: var(--color-text-subtle); flex: none; }
|
|
8361
|
+
[dir="rtl"] .twc-dt__diff-arrow { transform: scaleX(-1); display: inline-block; }
|
|
8362
|
+
.twc-dt__diff-summary { display: inline-flex; align-items: center; gap: 4px; flex: none; }
|
|
8363
|
+
.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; }
|
|
8364
|
+
.twc-dt__diff-toggle input { width: 15px; height: 15px; accent-color: var(--color-primary); cursor: pointer; margin: 0; }
|
|
8275
8365
|
.twc-dt__row[data-row-dropbefore] > .twc-dt__td { box-shadow: inset 0 3px 0 var(--color-primary); }
|
|
8276
8366
|
.twc-dt__row[data-row-dropafter] > .twc-dt__td { box-shadow: inset 0 -3px 0 var(--color-primary); }
|
|
8277
8367
|
/* Keyboard row reorder (grabbed) */
|
|
@@ -8533,6 +8623,38 @@ var NUM_OPS = [
|
|
|
8533
8623
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8534
8624
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8535
8625
|
var getColVal = (col, row) => col && col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col && col.field];
|
|
8626
|
+
var diffValueNode = (col, v, row) => col.renderCell ? col.renderCell(v, row) : col.valueFormatter ? col.valueFormatter(v, row) : v == null ? "" : v;
|
|
8627
|
+
function renderDiffCell(col, val, row) {
|
|
8628
|
+
const meta = row && row.__diffMeta;
|
|
8629
|
+
if (!meta) return diffValueNode(col, val, row);
|
|
8630
|
+
if (meta.op === "removed") return React51__namespace.default.createElement("span", { className: "twc-dt__diff-old" }, diffValueNode(col, getColVal(col, meta.from), meta.from));
|
|
8631
|
+
if (meta.op === "added") return React51__namespace.default.createElement("span", { className: "twc-dt__diff-new" }, diffValueNode(col, getColVal(col, meta.to), meta.to));
|
|
8632
|
+
if (meta.op === "modified" && meta.changed.has(col.field)) {
|
|
8633
|
+
return React51__namespace.default.createElement(
|
|
8634
|
+
"span",
|
|
8635
|
+
{ className: "twc-dt__diff-change" },
|
|
8636
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-old" }, diffValueNode(col, getColVal(col, meta.from), meta.from)),
|
|
8637
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-arrow", "aria-hidden": "true" }, "\u2192"),
|
|
8638
|
+
React51__namespace.default.createElement("span", { className: "twc-dt__diff-new" }, diffValueNode(col, getColVal(col, meta.to), meta.to))
|
|
8639
|
+
);
|
|
8640
|
+
}
|
|
8641
|
+
return diffValueNode(col, val, row);
|
|
8642
|
+
}
|
|
8643
|
+
var DIFF_OP_COLUMN = {
|
|
8644
|
+
field: "__diffop",
|
|
8645
|
+
headerName: "Change",
|
|
8646
|
+
width: 122,
|
|
8647
|
+
pinned: "left",
|
|
8648
|
+
sortable: true,
|
|
8649
|
+
filterable: false,
|
|
8650
|
+
groupable: true,
|
|
8651
|
+
reorderable: false,
|
|
8652
|
+
resizable: true,
|
|
8653
|
+
wrappable: false,
|
|
8654
|
+
hideable: false,
|
|
8655
|
+
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,
|
|
8656
|
+
exportValue: (v) => v && DIFF_OPS[v] ? DIFF_OPS[v].label : ""
|
|
8657
|
+
};
|
|
8536
8658
|
function testFilter(raw, op, target, type) {
|
|
8537
8659
|
if (op === "isEmpty") return raw == null || raw === "";
|
|
8538
8660
|
if (op === "isNotEmpty") return !(raw == null || raw === "");
|
|
@@ -8851,11 +8973,12 @@ function xlsxPackage(sheetXml) {
|
|
|
8851
8973
|
]);
|
|
8852
8974
|
}
|
|
8853
8975
|
function Datatable({
|
|
8854
|
-
columns,
|
|
8855
|
-
rows,
|
|
8976
|
+
columns: columnsProp,
|
|
8977
|
+
rows: rowsProp = [],
|
|
8856
8978
|
loading = false,
|
|
8857
|
-
rowKey,
|
|
8979
|
+
rowKey: rowKeyProp,
|
|
8858
8980
|
checkboxSelection = false,
|
|
8981
|
+
diff,
|
|
8859
8982
|
density: densityProp = "comfortable",
|
|
8860
8983
|
pageSize = 10,
|
|
8861
8984
|
pageSizeOptions = [5, 10, 25, 50],
|
|
@@ -8908,6 +9031,29 @@ function Datatable({
|
|
|
8908
9031
|
...rest
|
|
8909
9032
|
}) {
|
|
8910
9033
|
const __twcStyles = useScopedStyles("twc-dt-styles", DT_CSS);
|
|
9034
|
+
const isDiff = !!diff;
|
|
9035
|
+
const [diffOnly, setDiffOnly] = React51__namespace.default.useState(diff && diff.onlyChanged !== void 0 ? diff.onlyChanged : true);
|
|
9036
|
+
const diffRowKey = diff && diff.rowKey || rowKeyProp || ((r2) => r2 == null ? r2 : r2.id);
|
|
9037
|
+
const diffData = React51__namespace.default.useMemo(
|
|
9038
|
+
() => isDiff ? classifyDiff(diff.from || [], diff.to || [], columnsProp, diffRowKey, { moveDetection: diff.moveDetection, compare: diff.compare }) : null,
|
|
9039
|
+
[isDiff, diff, columnsProp]
|
|
9040
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
9041
|
+
);
|
|
9042
|
+
const onClassifiedRef = React51__namespace.default.useRef(diff && diff.onClassified);
|
|
9043
|
+
onClassifiedRef.current = diff && diff.onClassified;
|
|
9044
|
+
React51__namespace.default.useEffect(() => {
|
|
9045
|
+
if (diffData && onClassifiedRef.current) onClassifiedRef.current(diffData.counts);
|
|
9046
|
+
}, [diffData]);
|
|
9047
|
+
const diffRowKeyFn = React51__namespace.default.useCallback((r2) => r2.__diffKey, []);
|
|
9048
|
+
const columns = React51__namespace.default.useMemo(
|
|
9049
|
+
() => isDiff ? [DIFF_OP_COLUMN, ...columnsProp.map((c) => ({ ...c, renderCell: (val, row) => renderDiffCell(c, val, row) }))] : columnsProp,
|
|
9050
|
+
[isDiff, columnsProp]
|
|
9051
|
+
);
|
|
9052
|
+
const rows = React51__namespace.default.useMemo(
|
|
9053
|
+
() => isDiff ? diffData.rows.filter((r2) => !diffOnly || r2.op !== "unchanged").map((r2) => ({ ...r2.to || r2.from, __diffop: r2.op, __diffMeta: r2, __diffKey: r2.key })) : rowsProp,
|
|
9054
|
+
[isDiff, diffData, diffOnly, rowsProp]
|
|
9055
|
+
);
|
|
9056
|
+
const rowKey = isDiff ? diffRowKeyFn : rowKeyProp;
|
|
8911
9057
|
const cols = React51__namespace.default.useMemo(() => {
|
|
8912
9058
|
const out = columns.map((c) => {
|
|
8913
9059
|
const isActions = c.type === "actions";
|
|
@@ -10104,6 +10250,7 @@ function Datatable({
|
|
|
10104
10250
|
role: "row",
|
|
10105
10251
|
"aria-rowindex": (paginated && !serverMode ? pageVal * sizeVal : 0) + ri + 2,
|
|
10106
10252
|
"aria-selected": (checkboxSelection ? sel : rowActive) || void 0,
|
|
10253
|
+
"data-op": row.__diffop || void 0,
|
|
10107
10254
|
"data-selected": sel || void 0,
|
|
10108
10255
|
"data-active": rowActive || void 0,
|
|
10109
10256
|
"data-pinned-row": pinSide || void 0,
|
|
@@ -10354,6 +10501,28 @@ function Datatable({
|
|
|
10354
10501
|
))
|
|
10355
10502
|
] })
|
|
10356
10503
|
] }) : null,
|
|
10504
|
+
isDiff && diff.showSummary !== false ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__diff-summary", "aria-label": "Diff summary", children: [
|
|
10505
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "success", children: [
|
|
10506
|
+
"+",
|
|
10507
|
+
diffData.counts.added
|
|
10508
|
+
] }),
|
|
10509
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "warning", children: [
|
|
10510
|
+
"~",
|
|
10511
|
+
diffData.counts.modified
|
|
10512
|
+
] }),
|
|
10513
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "danger", children: [
|
|
10514
|
+
"\u2212",
|
|
10515
|
+
diffData.counts.removed
|
|
10516
|
+
] }),
|
|
10517
|
+
diffData.counts.moved ? /* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", variant: "soft", tone: "info", children: [
|
|
10518
|
+
"\u21C5",
|
|
10519
|
+
diffData.counts.moved
|
|
10520
|
+
] }) : null
|
|
10521
|
+
] }) : null,
|
|
10522
|
+
isDiff && diff.showToggle !== false ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "twc-dt__diff-toggle", children: [
|
|
10523
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: diffOnly, onChange: (e) => setDiffOnly(e.target.checked) }),
|
|
10524
|
+
diff.toggleLabel != null ? diff.toggleLabel : "Only changed"
|
|
10525
|
+
] }) : null,
|
|
10357
10526
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10358
10527
|
"button",
|
|
10359
10528
|
{
|
|
@@ -11690,55 +11859,13 @@ function CardGrid({
|
|
|
11690
11859
|
] }) : null
|
|
11691
11860
|
] });
|
|
11692
11861
|
}
|
|
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);
|
|
11862
|
+
var toDatatableColumn = (c) => ({
|
|
11863
|
+
field: c.field,
|
|
11864
|
+
headerName: typeof c.headerName === "string" ? c.headerName : c.field,
|
|
11865
|
+
valueGetter: c.valueGetter,
|
|
11866
|
+
valueFormatter: c.valueFormatter,
|
|
11867
|
+
compare: c.compare
|
|
11868
|
+
});
|
|
11742
11869
|
function DiffTable({
|
|
11743
11870
|
from = [],
|
|
11744
11871
|
to = [],
|
|
@@ -11756,104 +11883,24 @@ function DiffTable({
|
|
|
11756
11883
|
className = "",
|
|
11757
11884
|
...rest
|
|
11758
11885
|
}) {
|
|
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
|
-
] });
|
|
11886
|
+
const dtColumns = React51__namespace.default.useMemo(() => columns.map(toDatatableColumn), [columns]);
|
|
11887
|
+
const diff = React51__namespace.default.useMemo(
|
|
11888
|
+
() => ({ from, to, rowKey, onlyChanged, showToggle, showSummary, moveDetection, compare, toggleLabel }),
|
|
11889
|
+
[from, to, rowKey, onlyChanged, showToggle, showSummary, moveDetection, compare, toggleLabel]
|
|
11890
|
+
);
|
|
11891
|
+
const table = /* @__PURE__ */ jsxRuntime.jsx(
|
|
11892
|
+
Datatable,
|
|
11893
|
+
{
|
|
11894
|
+
columns: dtColumns,
|
|
11895
|
+
diff,
|
|
11896
|
+
emptyMessage: emptyState,
|
|
11897
|
+
...label ? {} : { id, className, ...rest }
|
|
11816
11898
|
}
|
|
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
|
-
] }) })
|
|
11899
|
+
);
|
|
11900
|
+
if (!label) return table;
|
|
11901
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { id, className, ...rest, style: { display: "flex", flexDirection: "column", gap: "var(--space-2)", fontFamily: "var(--font-sans)" }, children: [
|
|
11902
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "var(--text-sm)", fontWeight: "var(--font-semibold)", color: "var(--color-text)" }, children: label }),
|
|
11903
|
+
table
|
|
11857
11904
|
] });
|
|
11858
11905
|
}
|
|
11859
11906
|
var FIELD_CSS3 = `
|