@ai-matrx/design-system 0.18.2 → 0.18.4
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 +24 -0
- package/README.md +22 -0
- package/dist/content-transfer.cjs +127 -30
- package/dist/content-transfer.cjs.map +1 -1
- package/dist/content-transfer.d.cts +2 -0
- package/dist/content-transfer.d.ts +2 -0
- package/dist/content-transfer.js +127 -30
- package/dist/content-transfer.js.map +1 -1
- package/dist/data-table/copy-helpers.d.cts +1 -1
- package/dist/data-table/copy-helpers.d.ts +1 -1
- package/dist/data-table/data-row-inspector.cjs +127 -30
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js +127 -30
- package/dist/data-table/data-row-inspector.js.map +1 -1
- package/dist/data-table/data-row-window.cjs +127 -30
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js +127 -30
- package/dist/data-table/data-row-window.js.map +1 -1
- package/dist/data-table/filter-engine.d.cts +1 -1
- package/dist/data-table/filter-engine.d.ts +1 -1
- package/dist/data-table/index.cjs +1158 -956
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.d.cts +23 -3
- package/dist/data-table/index.d.ts +23 -3
- package/dist/data-table/index.js +1158 -956
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/infer-filter.d.cts +1 -1
- package/dist/data-table/infer-filter.d.ts +1 -1
- package/dist/data-table/layered-filters.d.cts +1 -1
- package/dist/data-table/layered-filters.d.ts +1 -1
- package/dist/data-table/pagination.cjs +2 -2
- package/dist/data-table/pagination.cjs.map +1 -1
- package/dist/data-table/pagination.js +2 -2
- package/dist/data-table/pagination.js.map +1 -1
- package/dist/data-table/query-control.d.cts +1 -1
- package/dist/data-table/query-control.d.ts +1 -1
- package/dist/data-table/types.cjs.map +1 -1
- package/dist/data-table/types.d.cts +1 -1
- package/dist/data-table/types.d.ts +1 -1
- package/dist/data-table/url-state.d.cts +1 -1
- package/dist/data-table/url-state.d.ts +1 -1
- package/dist/data-table/xlsx.d.cts +1 -1
- package/dist/data-table/xlsx.d.ts +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/{types-CD4xGL5Z.d.cts → types-Bx9SfdJM.d.cts} +2 -0
- package/dist/{types-BhSkeZQ_.d.ts → types-DyByb6tW.d.ts} +2 -0
- package/package.json +1 -1
|
@@ -648,6 +648,10 @@ function materialIdentity(material) {
|
|
|
648
648
|
}
|
|
649
649
|
return `payload:${id}`;
|
|
650
650
|
}
|
|
651
|
+
function snapshotContent(snapshot) {
|
|
652
|
+
const { sourceId, label, payload, coverage, unsavedChanges, omissions, sections, limits } = snapshot;
|
|
653
|
+
return JSON.stringify({ sourceId, label, payload, coverage, unsavedChanges, omissions, sections, limits });
|
|
654
|
+
}
|
|
651
655
|
function useFence() {
|
|
652
656
|
const mounted = React7.useRef(true);
|
|
653
657
|
const nextId = React7.useRef(0);
|
|
@@ -750,7 +754,7 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
|
|
|
750
754
|
const captured = await material.capture(signal);
|
|
751
755
|
sourceMaterial = { id: captured.snapshot.sourceId, label: captured.snapshot.label, capture: async () => captured };
|
|
752
756
|
} else if ("kind" in material) {
|
|
753
|
-
sourceMaterial =
|
|
757
|
+
sourceMaterial = { id: materialIdentity(material), label: sourceLabel, capture: async () => directSource(material, { sourceId: materialIdentity(material), label: sourceLabel, ...applyMenuProjection && projection ? { projection } : {}, ...applyMenuProjection && sections ? { sections } : {} }) };
|
|
754
758
|
} else if (applyMenuProjection && (projection || sections)) {
|
|
755
759
|
sourceMaterial = {
|
|
756
760
|
id: material.id,
|
|
@@ -767,7 +771,7 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
|
|
|
767
771
|
} else {
|
|
768
772
|
sourceMaterial = material;
|
|
769
773
|
}
|
|
770
|
-
const raw =
|
|
774
|
+
const raw = await sourceMaterial.capture({ scope, signal });
|
|
771
775
|
const constrained = resolveTransferPreferences(providerPreferences, preferences, raw.snapshot.limits);
|
|
772
776
|
const result = await capture({ id: raw.snapshot.sourceId, label: raw.snapshot.label, capture: async () => ({ ...raw, snapshot: { ...raw.snapshot, limits: constrained.limits } }) }, signal, scope);
|
|
773
777
|
if (scope !== "all-matching" || !collectPages) return result;
|
|
@@ -827,31 +831,117 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
|
|
|
827
831
|
fence.finish(controller);
|
|
828
832
|
}
|
|
829
833
|
}, [captureOne, capturePrimary, fence, formatSources, initialScope, preferences, providerPreferences, report, transport]);
|
|
830
|
-
const openWorkspace = React7.useCallback(
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
834
|
+
const openWorkspace = React7.useCallback(
|
|
835
|
+
async (key = primaryWorkspaceKey, variant) => {
|
|
836
|
+
const variantMaterial = variant && "kind" in variant.source ? {
|
|
837
|
+
id: `variant:${key}`,
|
|
838
|
+
label: variant.label,
|
|
839
|
+
capture: async () => directSource(variant.source, {
|
|
840
|
+
sourceId: `variant:${key}`,
|
|
841
|
+
label: variant.label
|
|
842
|
+
})
|
|
843
|
+
} : variant?.source;
|
|
844
|
+
const captureWorkspace = (scope, signal, collectPages = true) => captureOne(variantMaterial ?? primary, scope, signal, true, collectPages);
|
|
845
|
+
workspaceCaptures.current.set(key, captureWorkspace);
|
|
846
|
+
const existing = workspaces[key];
|
|
847
|
+
const { controller, id } = fence.begin();
|
|
848
|
+
if (existing) {
|
|
849
|
+
try {
|
|
850
|
+
const allMatching = existing.scope === "all-matching";
|
|
851
|
+
const fresh = await captureWorkspace(
|
|
852
|
+
existing.scope,
|
|
853
|
+
controller.signal,
|
|
854
|
+
!allMatching
|
|
855
|
+
);
|
|
856
|
+
if (!fence.valid(id, controller) || !workspaceCaptures.current.has(key))
|
|
857
|
+
return;
|
|
858
|
+
if (allMatching && (!existing.allMatching || !fresh.allMatching))
|
|
859
|
+
throw new Error(
|
|
860
|
+
"This source can no longer provide an all-matching snapshot."
|
|
861
|
+
);
|
|
862
|
+
const collectionIdentity = (value) => value && {
|
|
863
|
+
query: value.source.query,
|
|
864
|
+
projection: value.projection,
|
|
865
|
+
columns: value.columns,
|
|
866
|
+
limits: value.limits
|
|
867
|
+
};
|
|
868
|
+
const changed = allMatching ? JSON.stringify(collectionIdentity(existing.allMatching)) !== JSON.stringify(collectionIdentity(fresh.allMatching)) : snapshotContent(existing.snapshot) !== snapshotContent(fresh.snapshot);
|
|
869
|
+
setWorkspaces((current) => {
|
|
870
|
+
const retained = current[key];
|
|
871
|
+
if (!retained) return current;
|
|
872
|
+
return {
|
|
873
|
+
...current,
|
|
874
|
+
[key]: {
|
|
875
|
+
...retained,
|
|
876
|
+
error: fresh.collectionError,
|
|
877
|
+
...allMatching ? { sourceStale: changed } : changed ? { pending: { ...fresh, scope: retained.scope } } : { pending: void 0 }
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
});
|
|
881
|
+
setWorkspaceKey(key);
|
|
882
|
+
setWorkspaceOpen(true);
|
|
883
|
+
} catch (error) {
|
|
884
|
+
if (fence.valid(id, controller) && workspaceCaptures.current.has(key)) {
|
|
885
|
+
setWorkspaces(
|
|
886
|
+
(current) => current[key] ? {
|
|
887
|
+
...current,
|
|
888
|
+
[key]: {
|
|
889
|
+
...current[key],
|
|
890
|
+
error: errorMessage(error, "Could not refresh source")
|
|
891
|
+
}
|
|
892
|
+
} : current
|
|
893
|
+
);
|
|
894
|
+
setWorkspaceKey(key);
|
|
895
|
+
setWorkspaceOpen(true);
|
|
896
|
+
}
|
|
897
|
+
} finally {
|
|
898
|
+
fence.finish(controller);
|
|
899
|
+
}
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
try {
|
|
903
|
+
const result = await captureWorkspace(initialScope, controller.signal);
|
|
904
|
+
if (!fence.valid(id, controller)) return;
|
|
905
|
+
const resolved = resolveTransferPreferences(
|
|
906
|
+
providerPreferences,
|
|
907
|
+
preferences,
|
|
908
|
+
result.snapshot.limits
|
|
909
|
+
);
|
|
910
|
+
const original = createDraft(result.snapshot);
|
|
911
|
+
const base = {
|
|
912
|
+
...result,
|
|
913
|
+
key,
|
|
914
|
+
original,
|
|
915
|
+
draft: original,
|
|
916
|
+
scope: initialScope,
|
|
917
|
+
preferences: resolved,
|
|
918
|
+
...result.collectionError ? { error: result.collectionError } : {}
|
|
919
|
+
};
|
|
920
|
+
setWorkspaces((current) => ({
|
|
921
|
+
...current,
|
|
922
|
+
[key]: { ...base, draft: rebuild(base, initialControls(base)) }
|
|
923
|
+
}));
|
|
924
|
+
setWorkspaceKey(key);
|
|
925
|
+
setWorkspaceOpen(true);
|
|
926
|
+
} catch (error) {
|
|
927
|
+
if (fence.valid(id, controller))
|
|
928
|
+
setNotice(errorMessage(error, "Could not capture content"));
|
|
929
|
+
} finally {
|
|
930
|
+
fence.finish(controller);
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
[
|
|
934
|
+
captureOne,
|
|
935
|
+
capturePrimary,
|
|
936
|
+
fence,
|
|
937
|
+
initialScope,
|
|
938
|
+
preferences,
|
|
939
|
+
primaryWorkspaceKey,
|
|
940
|
+
primary,
|
|
941
|
+
providerPreferences,
|
|
942
|
+
workspaces
|
|
943
|
+
]
|
|
944
|
+
);
|
|
855
945
|
React7.useImperativeHandle(controllerRef, () => ({
|
|
856
946
|
focusTrigger: () => triggerRef.current?.focus(),
|
|
857
947
|
prepare: async (requestedSource, options) => {
|
|
@@ -1074,7 +1164,7 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
|
|
|
1074
1164
|
setBusy("capture");
|
|
1075
1165
|
try {
|
|
1076
1166
|
const result = await captureScope(scope, controller.signal);
|
|
1077
|
-
if (fence.valid(id, controller) && latest.current.draft.revision === revision) onChange({ ...latest.current, pending: { ...result, scope }, error: result.collectionError });
|
|
1167
|
+
if (fence.valid(id, controller) && latest.current.draft.revision === revision) onChange({ ...latest.current, pending: { ...result, scope }, sourceStale: false, error: result.collectionError });
|
|
1078
1168
|
} catch (error) {
|
|
1079
1169
|
if (fence.valid(id, controller)) onChange({ ...latest.current, error: errorMessage(error, "Refresh failed") });
|
|
1080
1170
|
} finally {
|
|
@@ -1317,6 +1407,7 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
|
|
|
1317
1407
|
/* @__PURE__ */ jsx7(Button, { type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
|
|
1318
1408
|
/* @__PURE__ */ jsx7(Button, { type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
|
|
1319
1409
|
] }) : null,
|
|
1410
|
+
state.sourceStale ? /* @__PURE__ */ jsx7("p", { role: "alert", className: "matrx-alchemy-decision", children: "The source changed since this draft. Use Refresh source to review the latest data." }) : null,
|
|
1320
1411
|
state.pending ? /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-decision", role: "alert", children: [
|
|
1321
1412
|
/* @__PURE__ */ jsx7("p", { children: "A fresh source snapshot is ready." }),
|
|
1322
1413
|
/* @__PURE__ */ jsx7(Button, { type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
|
|
@@ -1423,6 +1514,7 @@ var actionDone = (message) => ({
|
|
|
1423
1514
|
mimeTypes: [],
|
|
1424
1515
|
message
|
|
1425
1516
|
});
|
|
1517
|
+
var isSafeFilename = (filename) => filename === filename.trim() && filename.length > 0 && !/^\.+$/.test(filename) && !/[\\/\x00-\x1F\x7F]/.test(filename);
|
|
1426
1518
|
var sourceFor = (id, label, build) => ({
|
|
1427
1519
|
id,
|
|
1428
1520
|
label,
|
|
@@ -1571,7 +1663,8 @@ function MatrxCopyMenuSession(props) {
|
|
|
1571
1663
|
value: {
|
|
1572
1664
|
bytes: Array.from(bytes),
|
|
1573
1665
|
mime: file.mime,
|
|
1574
|
-
extension: file.extension
|
|
1666
|
+
extension: file.extension,
|
|
1667
|
+
...file.filename !== void 0 ? { filename: file.filename } : {}
|
|
1575
1668
|
}
|
|
1576
1669
|
};
|
|
1577
1670
|
},
|
|
@@ -1588,12 +1681,16 @@ function MatrxCopyMenuSession(props) {
|
|
|
1588
1681
|
(byte) => typeof byte !== "number" || !Number.isInteger(byte) || byte < 0 || byte > 255
|
|
1589
1682
|
))
|
|
1590
1683
|
throw new Error(`${item.label} did not capture a valid file.`);
|
|
1684
|
+
if (value.filename !== void 0 && (typeof value.filename !== "string" || !isSafeFilename(value.filename)))
|
|
1685
|
+
throw new Error(
|
|
1686
|
+
`${item.label} has an unsafe filename. Use a nonempty basename without leading or trailing whitespace, dots only, path separators, or control characters.`
|
|
1687
|
+
);
|
|
1591
1688
|
if (draft.omissions.some((omission) => omission.reason !== "duplicate"))
|
|
1592
1689
|
throw new Error(
|
|
1593
1690
|
"This custom file exceeds the configured export limits or contains excluded content. Use a standard format or revise the source options."
|
|
1594
1691
|
);
|
|
1595
1692
|
const bytes = new Uint8Array(value.bytes);
|
|
1596
|
-
const filename = `${props.label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "export"}.${value.extension.replace(/[^a-zA-Z0-9.-]/g, "") || "bin"}`;
|
|
1693
|
+
const filename = typeof value.filename === "string" ? value.filename : `${props.label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "export"}.${value.extension.replace(/[^a-zA-Z0-9.-]/g, "") || "bin"}`;
|
|
1597
1694
|
return transport.download(
|
|
1598
1695
|
sealTransferArtifact2({
|
|
1599
1696
|
snapshotId: snapshot.id,
|