@ai-matrx/records-ui 0.115.78 → 0.115.79
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 +13 -1
- package/dist/index.cjs +124 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +481 -411
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +64 -35
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +97 -68
- package/dist/pickers.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
-
## 0.115.
|
|
3
|
+
## 0.115.79
|
|
4
4
|
|
|
5
5
|
UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
|
|
6
6
|
Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/records-ui/src`.
|
|
7
7
|
|
|
8
|
+
## 0.115.78
|
|
9
|
+
|
|
10
|
+
SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
|
|
11
|
+
so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
|
|
12
|
+
Diff: `git diff 254d4d3f8b c3135c57b9 -- apps/shared/records-ui/src`
|
|
13
|
+
|
|
14
|
+
Changed shipped source files (4):
|
|
15
|
+
- `apps/shared/records-ui/src/Grid.tsx`
|
|
16
|
+
- `apps/shared/records-ui/src/ViewSwitcher.tsx`
|
|
17
|
+
- `apps/shared/records-ui/src/newRowValues.tsx`
|
|
18
|
+
- `apps/shared/records-ui/src/recordMoves.tsx`
|
|
19
|
+
|
|
8
20
|
## 0.115.77
|
|
9
21
|
|
|
10
22
|
SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
|
package/dist/index.cjs
CHANGED
|
@@ -6886,46 +6886,63 @@ function AttachmentChip({ id, onRemove, onPreview }) {
|
|
|
6886
6886
|
const words2 = read?.name ?? (read ? FILE_CHIP_UNREAD : "\u2026");
|
|
6887
6887
|
const href = read?.fileId ? host.hrefForFile?.({ fileId: read.fileId }) : void 0;
|
|
6888
6888
|
const title = onPreview ? `Preview ${words2}` : href ? `Open ${words2}` : read?.why ?? FILE_CHIP_NO_PAGE;
|
|
6889
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6889
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
6890
|
+
import_design_system22.Badge,
|
|
6891
|
+
{
|
|
6892
|
+
variant: "secondary",
|
|
6893
|
+
className: (0, import_design_system22.cn)("max-w-[14rem] gap-1 text-[11px]", onPreview && "cursor-pointer"),
|
|
6894
|
+
"data-records-file-chip": id,
|
|
6895
|
+
title,
|
|
6896
|
+
...onPreview ? {
|
|
6896
6897
|
onClick: (event) => {
|
|
6897
6898
|
event.stopPropagation();
|
|
6898
6899
|
onPreview();
|
|
6899
6900
|
},
|
|
6900
6901
|
onMouseDown: (event) => event.stopPropagation(),
|
|
6901
|
-
onDoubleClick: (event) => event.stopPropagation()
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6902
|
+
onDoubleClick: (event) => event.stopPropagation()
|
|
6903
|
+
} : {},
|
|
6904
|
+
children: [
|
|
6905
|
+
onPreview ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6906
|
+
"button",
|
|
6907
|
+
{
|
|
6908
|
+
type: "button",
|
|
6909
|
+
className: "truncate underline-offset-2 hover:underline",
|
|
6910
|
+
"data-records-file-preview": id,
|
|
6911
|
+
onClick: (event) => {
|
|
6912
|
+
event.stopPropagation();
|
|
6913
|
+
onPreview();
|
|
6914
|
+
},
|
|
6915
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
6916
|
+
onDoubleClick: (event) => event.stopPropagation(),
|
|
6917
|
+
children: words2
|
|
6918
|
+
}
|
|
6919
|
+
) : href ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6920
|
+
import_outbound_react4.OutboundLink,
|
|
6921
|
+
{
|
|
6922
|
+
href,
|
|
6923
|
+
className: "truncate underline-offset-2 hover:underline",
|
|
6924
|
+
"data-records-file-link": read?.fileId ?? "",
|
|
6925
|
+
onClick: (event) => event.stopPropagation(),
|
|
6926
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
6927
|
+
children: words2
|
|
6928
|
+
}
|
|
6929
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "truncate", children: words2 }),
|
|
6930
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6931
|
+
"button",
|
|
6932
|
+
{
|
|
6933
|
+
type: "button",
|
|
6934
|
+
"aria-label": `Remove ${words2}`,
|
|
6935
|
+
className: "shrink-0 rounded px-0.5 text-muted-foreground hover:text-foreground",
|
|
6936
|
+
onClick: (event) => {
|
|
6937
|
+
event.stopPropagation();
|
|
6938
|
+
onRemove();
|
|
6939
|
+
},
|
|
6940
|
+
children: "\xD7"
|
|
6941
|
+
}
|
|
6942
|
+
) : null
|
|
6943
|
+
]
|
|
6944
|
+
}
|
|
6945
|
+
);
|
|
6929
6946
|
}
|
|
6930
6947
|
function AttachmentChips({ value, onRemove }) {
|
|
6931
6948
|
const host = useRecordsUi();
|
|
@@ -6966,6 +6983,18 @@ function AttachmentViewer({
|
|
|
6966
6983
|
{
|
|
6967
6984
|
className: "sm:max-w-3xl",
|
|
6968
6985
|
"data-records-attachment-viewer": id,
|
|
6986
|
+
tabIndex: -1,
|
|
6987
|
+
onOpenAutoFocus: (event) => {
|
|
6988
|
+
event.preventDefault();
|
|
6989
|
+
event.currentTarget.focus();
|
|
6990
|
+
},
|
|
6991
|
+
onCloseAutoFocus: (event) => {
|
|
6992
|
+
const chip = document.querySelector(`[data-records-file-preview="${ids[index]}"]`);
|
|
6993
|
+
if (chip) {
|
|
6994
|
+
event.preventDefault();
|
|
6995
|
+
chip.focus();
|
|
6996
|
+
}
|
|
6997
|
+
},
|
|
6969
6998
|
onKeyDown: (event) => {
|
|
6970
6999
|
if (event.key === "ArrowLeft") {
|
|
6971
7000
|
event.preventDefault();
|
|
@@ -20700,6 +20729,8 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
|
|
|
20700
20729
|
] }) : name
|
|
20701
20730
|
),
|
|
20702
20731
|
label: name,
|
|
20732
|
+
// The field's own description, one hover away on every header (not only the type mark's glyph).
|
|
20733
|
+
...fieldHelpText(field2) ? { helpText: fieldHelpText(field2) } : {},
|
|
20703
20734
|
accessorFn: (row) => row.document?.[field2.key],
|
|
20704
20735
|
// A column the store keeps no value for is not offered a sort it would refuse (`sortRefusal`).
|
|
20705
20736
|
sortable: sortRefusal(field2) === null,
|
|
@@ -21853,9 +21884,9 @@ var import_records43 = require("@ai-matrx/records");
|
|
|
21853
21884
|
|
|
21854
21885
|
// src/importRuleCheck.ts
|
|
21855
21886
|
var import_core13 = require("@ai-matrx/records/core");
|
|
21856
|
-
function
|
|
21887
|
+
function refusedCellsOf(fields, rows, mapping, choiceOptions, relationNames) {
|
|
21857
21888
|
const byKey = new Map(fields.map((f) => [f.key, f]));
|
|
21858
|
-
const
|
|
21889
|
+
const cells = [];
|
|
21859
21890
|
for (const [header, key] of Object.entries(mapping)) {
|
|
21860
21891
|
const field2 = byKey.get(key);
|
|
21861
21892
|
if (!field2) continue;
|
|
@@ -21865,9 +21896,8 @@ function checkImportRules(fields, rows, mapping, choiceOptions, relationNames) {
|
|
|
21865
21896
|
if (isChoice && !options) continue;
|
|
21866
21897
|
const named = relationNames?.get(key);
|
|
21867
21898
|
if (kind2 === "relation" && !named) continue;
|
|
21868
|
-
let refused = 0;
|
|
21869
21899
|
let judged = 0;
|
|
21870
|
-
|
|
21900
|
+
const mine = [];
|
|
21871
21901
|
rows.forEach((row, i) => {
|
|
21872
21902
|
const raw = String(row[header] ?? "").trim();
|
|
21873
21903
|
if (raw === "") return;
|
|
@@ -21883,17 +21913,20 @@ function checkImportRules(fields, rows, mapping, choiceOptions, relationNames) {
|
|
|
21883
21913
|
);
|
|
21884
21914
|
if (predicted.length > 0) why = predicted[0].message;
|
|
21885
21915
|
}
|
|
21886
|
-
if (why !== null) {
|
|
21887
|
-
refused += 1;
|
|
21888
|
-
if (!first) first = { why, line: i + 1, raw };
|
|
21889
|
-
}
|
|
21916
|
+
if (why !== null) mine.push({ header, line: i + 1, raw, why });
|
|
21890
21917
|
});
|
|
21891
|
-
|
|
21892
|
-
|
|
21893
|
-
|
|
21894
|
-
|
|
21918
|
+
for (const c of mine) cells.push({ ...c, judged, field: field2 });
|
|
21919
|
+
}
|
|
21920
|
+
return cells;
|
|
21921
|
+
}
|
|
21922
|
+
function checkImportRules(fields, rows, mapping, choiceOptions, relationNames) {
|
|
21923
|
+
const verdicts = /* @__PURE__ */ new Map();
|
|
21924
|
+
for (const c of refusedCellsOf(fields, rows, mapping, choiceOptions, relationNames)) {
|
|
21925
|
+
const have = verdicts.get(c.header);
|
|
21926
|
+
if (have) have.refused += 1;
|
|
21927
|
+
else verdicts.set(c.header, { header: c.header, field: c.field, refused: 1, judged: c.judged, firstWhy: c.why, firstLine: c.line, firstRaw: c.raw });
|
|
21895
21928
|
}
|
|
21896
|
-
return verdicts;
|
|
21929
|
+
return [...verdicts.values()];
|
|
21897
21930
|
}
|
|
21898
21931
|
|
|
21899
21932
|
// src/ImportWizard.tsx
|
|
@@ -22305,7 +22338,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22305
22338
|
},
|
|
22306
22339
|
[client, openRun]
|
|
22307
22340
|
);
|
|
22308
|
-
const declared2 = fields.data ?? [];
|
|
22341
|
+
const declared2 = (0, import_react122.useMemo)(() => fields.data ?? [], [fields.data]);
|
|
22309
22342
|
const titleKey = table.data?.title_field ?? null;
|
|
22310
22343
|
const titleHeader = titleFrom ?? (titleKey ? Object.entries(mapping).find(([h, key]) => key === titleKey && h !== TITLE_COPY)?.[0] ?? null : null);
|
|
22311
22344
|
const distinctRows = (0, import_react122.useMemo)(() => {
|
|
@@ -22599,6 +22632,12 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22599
22632
|
() => exactDuplicateRows(effectiveRows, (plan?.columns ?? []).map((c) => c.header).filter((h) => !leftOut.has(h))),
|
|
22600
22633
|
[effectiveRows, plan, leftOut]
|
|
22601
22634
|
);
|
|
22635
|
+
const [goAheadAnyway, setGoAheadAnyway] = (0, import_react122.useState)(false);
|
|
22636
|
+
const refusedCells = (0, import_react122.useMemo)(
|
|
22637
|
+
() => goAheadAnyway ? refusedCellsOf(declared2, effectiveRows, mapping, choiceIndex, relationIndex) : [],
|
|
22638
|
+
[goAheadAnyway, declared2, effectiveRows, mapping, choiceIndex, relationIndex]
|
|
22639
|
+
);
|
|
22640
|
+
const [keptAside, setKeptAside] = (0, import_react122.useState)([]);
|
|
22602
22641
|
const rowsToSend = (0, import_react122.useCallback)(
|
|
22603
22642
|
(index) => {
|
|
22604
22643
|
const repeated = new Set(skipRepeats ? repeats.map((r) => r.row) : []);
|
|
@@ -22608,6 +22647,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22608
22647
|
if (repeated.has(at)) return;
|
|
22609
22648
|
const out = {};
|
|
22610
22649
|
for (const [header, value] of Object.entries(row)) if (!leftOut.has(header)) out[header] = value;
|
|
22650
|
+
for (const c of refusedCells) if (c.line === at + 1 && c.header in out) out[c.header] = "";
|
|
22611
22651
|
if (titleFrom) out[TITLE_COPY] = String(row[titleFrom] ?? "").trim();
|
|
22612
22652
|
for (const { header, field: field2 } of mappedRelations) {
|
|
22613
22653
|
const named = index.get(field2.key);
|
|
@@ -22637,7 +22677,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22637
22677
|
return { rows: sent, lines };
|
|
22638
22678
|
},
|
|
22639
22679
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- choiceFor reads unlinkedChoice
|
|
22640
|
-
[effectiveRows, combined, titleFrom, leftOut, mappedRelations, unlinkedChoice, dateAsks, dateMiss, repeats, skipRepeats]
|
|
22680
|
+
[effectiveRows, combined, titleFrom, leftOut, mappedRelations, unlinkedChoice, dateAsks, dateMiss, repeats, skipRepeats, refusedCells]
|
|
22641
22681
|
);
|
|
22642
22682
|
const run = (0, import_react122.useCallback)(async () => {
|
|
22643
22683
|
if (!plan) return;
|
|
@@ -22705,6 +22745,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22705
22745
|
index = reread;
|
|
22706
22746
|
}
|
|
22707
22747
|
const { rows: sendRows, lines: sendLines } = rowsToSend(index);
|
|
22748
|
+
setKeptAside(refusedCells.map(({ header, line, raw, why }) => ({ header, line, raw, why })));
|
|
22708
22749
|
setSentLines(sendLines);
|
|
22709
22750
|
setRepeatsSkipped(effectiveRows.length - sendRows.length);
|
|
22710
22751
|
let sendMapping = mapping;
|
|
@@ -22838,7 +22879,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22838
22879
|
setPhase("done");
|
|
22839
22880
|
onWrote?.(finished.data.rows_written);
|
|
22840
22881
|
void loadRuns();
|
|
22841
|
-
}, [newColumns, makesColumns, kindChoice, guessedKind, addChoiceWords, client, dedupeKey, effectiveRows, fileBytes, fileHash, fileName, format, leftOut, loadRuns, mappedRelations, mapping, newChoiceWords, nudge, onDuplicate, onWrote, plan, readRelationNames, relationAsks, relationIndex, rights.admin, rowsToSend, tableId, unmapped, unlinkedChoice]);
|
|
22882
|
+
}, [newColumns, makesColumns, kindChoice, guessedKind, addChoiceWords, client, dedupeKey, effectiveRows, fileBytes, fileHash, fileName, format, leftOut, loadRuns, mappedRelations, mapping, newChoiceWords, nudge, onDuplicate, onWrote, plan, readRelationNames, refusedCells, relationAsks, relationIndex, rights.admin, rowsToSend, tableId, unmapped, unlinkedChoice]);
|
|
22842
22883
|
const counts = (0, import_react122.useMemo)(() => {
|
|
22843
22884
|
let landed = 0;
|
|
22844
22885
|
let duplicate = 0;
|
|
@@ -22867,8 +22908,8 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
22867
22908
|
);
|
|
22868
22909
|
const ruleVerdictOf = (0, import_react122.useMemo)(() => new Map(ruleVerdicts.map((v) => [v.header, v])), [ruleVerdicts]);
|
|
22869
22910
|
const refusedByRules = ruleVerdicts.reduce((n, v) => n + v.refused, 0);
|
|
22870
|
-
const
|
|
22871
|
-
(0, import_react122.useEffect)(() => setGoAheadAnyway(false), [
|
|
22911
|
+
const verdictKey = ruleVerdicts.map((v) => `${v.header}:${v.refused}/${v.judged}`).join("|");
|
|
22912
|
+
(0, import_react122.useEffect)(() => setGoAheadAnyway(false), [verdictKey]);
|
|
22872
22913
|
const [autoRan, setAutoRan] = (0, import_react122.useState)(false);
|
|
22873
22914
|
(0, import_react122.useEffect)(() => {
|
|
22874
22915
|
if (!autoRun || autoRan || !source || phase !== "ready" || !plan) return;
|
|
@@ -23458,6 +23499,23 @@ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className })
|
|
|
23458
23499
|
] })
|
|
23459
23500
|
}
|
|
23460
23501
|
) }) : null,
|
|
23502
|
+
afterWrite && keptAside.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { "data-import-kept-aside": "", className: "flex flex-col gap-0.5", children: [
|
|
23503
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("p", { children: [
|
|
23504
|
+
keptAside.length,
|
|
23505
|
+
" cell",
|
|
23506
|
+
keptAside.length === 1 ? " was" : "s were",
|
|
23507
|
+
" kept aside and left empty; every other value in those rows was written."
|
|
23508
|
+
] }),
|
|
23509
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("ul", { className: "flex flex-col gap-0.5 text-muted-foreground", children: keptAside.map((c) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("li", { children: [
|
|
23510
|
+
c.header,
|
|
23511
|
+
", ",
|
|
23512
|
+
source ? `row ${c.line}` : `line ${lineInYourFile(c.line)}`,
|
|
23513
|
+
": ",
|
|
23514
|
+
c.raw,
|
|
23515
|
+
" \u2014 ",
|
|
23516
|
+
c.why
|
|
23517
|
+
] }, `${c.header}:${c.line}`)) })
|
|
23518
|
+
] }) : null,
|
|
23461
23519
|
repeatsSkipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("p", { className: "text-muted-foreground", "data-import-repeats-skipped": "", children: [
|
|
23462
23520
|
repeatsSkipped,
|
|
23463
23521
|
" repeated row",
|
|
@@ -39885,6 +39943,9 @@ function settingsToCopy(source, target) {
|
|
|
39885
39943
|
const same3 = source.layout === target.layout;
|
|
39886
39944
|
return {
|
|
39887
39945
|
where: source.where ?? null,
|
|
39946
|
+
// The flat filter map a view may carry instead of (or beside) `where`: every stored filter shape travels.
|
|
39947
|
+
filters: source.filters ?? null,
|
|
39948
|
+
// saveViewPatch sends null to the door, which clears it
|
|
39888
39949
|
sorts: source.sorts ?? [],
|
|
39889
39950
|
groupField: source.groupField ?? null,
|
|
39890
39951
|
presentation: look,
|
|
@@ -39919,7 +39980,7 @@ function SortableRow({ id, disabled, children }) {
|
|
|
39919
39980
|
}
|
|
39920
39981
|
);
|
|
39921
39982
|
}
|
|
39922
|
-
function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, initialViews, className }) {
|
|
39983
|
+
function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, onSettingsCopied, initialViews, className }) {
|
|
39923
39984
|
const client = (0, import_react233.useRecordsClient)();
|
|
39924
39985
|
const claimSeed = useSeedGuard();
|
|
39925
39986
|
const table = (0, import_react234.useTable)(tableId);
|
|
@@ -40092,6 +40153,7 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
|
|
|
40092
40153
|
return;
|
|
40093
40154
|
}
|
|
40094
40155
|
setCopying(false);
|
|
40156
|
+
onSettingsCopied?.(into.id);
|
|
40095
40157
|
await load();
|
|
40096
40158
|
notify?.success(`Copied settings from \u201C${source.name}\u201D`);
|
|
40097
40159
|
}
|
|
@@ -54534,6 +54596,14 @@ function TablePage({
|
|
|
54534
54596
|
}
|
|
54535
54597
|
},
|
|
54536
54598
|
onViews: setViews,
|
|
54599
|
+
onSettingsCopied: (copiedId) => {
|
|
54600
|
+
setAddressResetEpoch((n) => n + 1);
|
|
54601
|
+
setLooks((all) => {
|
|
54602
|
+
const { [copiedId]: _gone, ...rest } = all ?? {};
|
|
54603
|
+
return rest;
|
|
54604
|
+
});
|
|
54605
|
+
void keepLook(client, tableId, copiedId, null);
|
|
54606
|
+
},
|
|
54537
54607
|
...seededViews && viewsEpoch === 0 ? { initialViews: seededViews } : {},
|
|
54538
54608
|
seed: seedViews ?? [defaultView(tableId)],
|
|
54539
54609
|
settings: view && main === "records" && shownLayout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { className: "flex flex-col gap-0.5 px-1 py-1", role: "radiogroup", "aria-label": FOOTER_WORDS.label, children: [
|