@ai-matrx/records-ui 0.115.38 → 0.115.40
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 +18 -0
- package/dist/index.cjs +323 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -2
- package/dist/index.d.ts +60 -2
- package/dist/index.js +320 -131
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -6029,9 +6029,12 @@ function withheldNoticeOf(hidden, key) {
|
|
|
6029
6029
|
return notice && typeof notice === "object" ? notice : null;
|
|
6030
6030
|
}
|
|
6031
6031
|
function withheldSentence(field2, notice) {
|
|
6032
|
-
const
|
|
6033
|
-
if (typeof says === "string" && says.trim() !== "") return says.trim();
|
|
6032
|
+
const extra = notice;
|
|
6033
|
+
if (typeof extra.says === "string" && extra.says.trim() !== "") return extra.says.trim();
|
|
6034
6034
|
const name = fieldName(field2);
|
|
6035
|
+
if (typeof extra.part === "string" && extra.part.trim() !== "" && typeof extra.who === "string" && extra.who.trim() !== "") {
|
|
6036
|
+
return `${name} is in ${extra.part.trim()} \u2014 ${extra.who.trim()} see it.`;
|
|
6037
|
+
}
|
|
6035
6038
|
const reason = notice.reason ? ` It is ${notice.reason}` : "";
|
|
6036
6039
|
const needs = notice.needs ? `${reason ? "," : " It"} and reading it needs ${notice.needs}` : "";
|
|
6037
6040
|
const or = notice.or ? `${needs || reason ? ", or" : " It needs"} ${notice.or}` : "";
|
|
@@ -11978,6 +11981,9 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
11978
11981
|
const startedFrom = (0, import_react66.useRef)(null);
|
|
11979
11982
|
const startedStored = (0, import_react66.useRef)(null);
|
|
11980
11983
|
const host = useRecordsUi();
|
|
11984
|
+
const fieldsRef = (0, import_react66.useRef)(fields);
|
|
11985
|
+
fieldsRef.current = fields;
|
|
11986
|
+
const forceNext = (0, import_react66.useRef)(/* @__PURE__ */ new Set());
|
|
11981
11987
|
const type = (0, import_react66.useCallback)((value) => {
|
|
11982
11988
|
typed2.current = value;
|
|
11983
11989
|
setDraft(value);
|
|
@@ -12134,6 +12140,47 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
12134
12140
|
delete next[id];
|
|
12135
12141
|
return next;
|
|
12136
12142
|
});
|
|
12143
|
+
const syncedField = fieldsRef.current.find((f) => f.key === key);
|
|
12144
|
+
if (syncedField?.source === "synced" && host.writeSyncedCell) {
|
|
12145
|
+
const force = forceNext.current.delete(id);
|
|
12146
|
+
let outcome;
|
|
12147
|
+
try {
|
|
12148
|
+
outcome = await host.writeSyncedCell({ tableId, recordId: rowId, fieldKey: key, value: shown5, force });
|
|
12149
|
+
} catch (thrown) {
|
|
12150
|
+
outcome = { ok: false, message: thrown instanceof Error ? thrown.message : String(thrown) };
|
|
12151
|
+
}
|
|
12152
|
+
setSaving((held) => {
|
|
12153
|
+
const next = { ...held };
|
|
12154
|
+
delete next[id];
|
|
12155
|
+
return next;
|
|
12156
|
+
});
|
|
12157
|
+
if (outcome.ok && outcome.status === "written") {
|
|
12158
|
+
if (typeof outcome.version === "number") {
|
|
12159
|
+
rememberVersion(versions.current, rowId, outcome.version);
|
|
12160
|
+
source.wrote(rowId, outcome.version);
|
|
12161
|
+
}
|
|
12162
|
+
settling.current.set(id, base2);
|
|
12163
|
+
writtenRef.current?.({ rowId, key, before: base2, after: shown5 });
|
|
12164
|
+
afterWrite();
|
|
12165
|
+
return;
|
|
12166
|
+
}
|
|
12167
|
+
setOptimistic((held) => {
|
|
12168
|
+
const next = { ...held };
|
|
12169
|
+
delete next[id];
|
|
12170
|
+
return next;
|
|
12171
|
+
});
|
|
12172
|
+
const sheetValue = outcome.ok ? outcome.sheetValue : null;
|
|
12173
|
+
setRefusals((held) => ({
|
|
12174
|
+
...held,
|
|
12175
|
+
[id]: outcome.ok ? {
|
|
12176
|
+
error: { code: "stale_write", message: `The sheet now says "${sheetValue ?? ""}". Retry keeps yours.` },
|
|
12177
|
+
conflict: null,
|
|
12178
|
+
attempted: value,
|
|
12179
|
+
sheet: { value: sheetValue }
|
|
12180
|
+
} : { error: { code: "refused_by_rule", message: outcome.message }, conflict: null, attempted: value }
|
|
12181
|
+
}));
|
|
12182
|
+
return;
|
|
12183
|
+
}
|
|
12137
12184
|
let written;
|
|
12138
12185
|
try {
|
|
12139
12186
|
let version = await versionOf(source, versions.current, versionReads.current, rowId);
|
|
@@ -12293,6 +12340,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
|
|
|
12293
12340
|
(rowId, key) => {
|
|
12294
12341
|
const held = refusals[cellKey(rowId, key)];
|
|
12295
12342
|
if (!held) return;
|
|
12343
|
+
if (held.sheet) forceNext.current.add(cellKey(rowId, key));
|
|
12296
12344
|
void writeCell(rowId, key, held.attempted, held.conflict?.contested_fields[key]);
|
|
12297
12345
|
},
|
|
12298
12346
|
[refusals, writeCell]
|
|
@@ -16955,6 +17003,7 @@ function useMergedGridControls(args) {
|
|
|
16955
17003
|
} = args;
|
|
16956
17004
|
const client = (0, import_react101.useRecordsClient)();
|
|
16957
17005
|
const linkRecord = useRecordsUi().linkRecord;
|
|
17006
|
+
const columnAccess = useRecordsUi().columnAccess;
|
|
16958
17007
|
const hrefForRecord = useRecordsUi().hrefForRecord;
|
|
16959
17008
|
const tableVersion = (0, recordVersions_exports.useTableVersion)(client, tableId, table);
|
|
16960
17009
|
const mutation = (0, import_react101.useFieldMutation)();
|
|
@@ -17136,6 +17185,14 @@ function useMergedGridControls(args) {
|
|
|
17136
17185
|
writeLook({ ...rest, ...next.size > 0 ? { wrapColumns: [...next] } : {} });
|
|
17137
17186
|
}
|
|
17138
17187
|
});
|
|
17188
|
+
if (columnAccess) {
|
|
17189
|
+
out.push({
|
|
17190
|
+
id: "col-access",
|
|
17191
|
+
label: "Who can see and edit\u2026",
|
|
17192
|
+
disabledReason: rights.structure ? void 0 : rights.why("structure"),
|
|
17193
|
+
onSelect: () => setDialog({ kind: "access", field: field2 })
|
|
17194
|
+
});
|
|
17195
|
+
}
|
|
17139
17196
|
out.push({
|
|
17140
17197
|
id: "col-duplicate",
|
|
17141
17198
|
label: "Duplicate property",
|
|
@@ -17417,6 +17474,7 @@ function useMergedGridControls(args) {
|
|
|
17417
17474
|
}
|
|
17418
17475
|
};
|
|
17419
17476
|
}, [
|
|
17477
|
+
columnAccess,
|
|
17420
17478
|
args,
|
|
17421
17479
|
colours,
|
|
17422
17480
|
fieldKeys,
|
|
@@ -17467,6 +17525,13 @@ function useMergedGridControls(args) {
|
|
|
17467
17525
|
const close = () => setDialog(null);
|
|
17468
17526
|
const dialogs = !enabled ? null : /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_jsx_runtime63.Fragment, { children: [
|
|
17469
17527
|
colours.dialogs,
|
|
17528
|
+
dialog?.kind === "access" && columnAccess ? columnAccess({
|
|
17529
|
+
tableId,
|
|
17530
|
+
fieldId: dialog.field.id,
|
|
17531
|
+
name: fieldName(dialog.field),
|
|
17532
|
+
onClose: () => setDialog(null),
|
|
17533
|
+
onChanged: () => (0, import_react101.tableShapeChanged)(tableId)
|
|
17534
|
+
}) : null,
|
|
17470
17535
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(RowActionsDialog, { tableId, open: rowActionsOpen, onOpenChange: setRowActionsOpen }),
|
|
17471
17536
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
17472
17537
|
RowLabelPicker,
|
|
@@ -20007,6 +20072,40 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
|
|
|
20007
20072
|
const name = fieldName(field2);
|
|
20008
20073
|
const format = cellFormatFor(field2, look?.format);
|
|
20009
20074
|
const workedOut = workedOutFrom(field2);
|
|
20075
|
+
const syncedMark = field2.source === "synced" ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
20076
|
+
"span",
|
|
20077
|
+
{
|
|
20078
|
+
"data-records-synced": field2.key,
|
|
20079
|
+
title: `Synced from ${look?.syncedFrom || "its source"}`,
|
|
20080
|
+
"aria-label": `Synced from ${look?.syncedFrom || "its source"}`,
|
|
20081
|
+
className: "text-[10px] text-muted-foreground",
|
|
20082
|
+
children: "\u27F3"
|
|
20083
|
+
}
|
|
20084
|
+
) : null;
|
|
20085
|
+
const restricted = field2.sensitivity === "confidential" || field2.sensitivity === "restricted";
|
|
20086
|
+
const lockMark = restricted ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
20087
|
+
"span",
|
|
20088
|
+
{
|
|
20089
|
+
"data-records-restricted": field2.key,
|
|
20090
|
+
title: "Fewer people see this column",
|
|
20091
|
+
"aria-label": "Fewer people see this column",
|
|
20092
|
+
className: "inline-flex text-muted-foreground",
|
|
20093
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("svg", { viewBox: "0 0 24 24", width: "11", height: "11", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
20094
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("rect", { x: "4", y: "11", width: "16", height: "10", rx: "2" }),
|
|
20095
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("path", { d: "M8 11V7a4 4 0 0 1 8 0v4" })
|
|
20096
|
+
] })
|
|
20097
|
+
}
|
|
20098
|
+
) : null;
|
|
20099
|
+
const withSynced = (inner2) => {
|
|
20100
|
+
const header = lockMark ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
20101
|
+
inner2,
|
|
20102
|
+
lockMark
|
|
20103
|
+
] }) : inner2;
|
|
20104
|
+
return syncedMark ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
20105
|
+
syncedMark,
|
|
20106
|
+
header
|
|
20107
|
+
] }) : header;
|
|
20108
|
+
};
|
|
20010
20109
|
return {
|
|
20011
20110
|
id: field2.key,
|
|
20012
20111
|
/*
|
|
@@ -20014,38 +20113,40 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
|
|
|
20014
20113
|
* (`custom.formula_eval`, on read or on write) and nobody types it — so its header carries
|
|
20015
20114
|
* the mark, and the formula it is worked out from is one hover away, in its own words.
|
|
20016
20115
|
*/
|
|
20017
|
-
header:
|
|
20018
|
-
|
|
20019
|
-
|
|
20116
|
+
header: withSynced(
|
|
20117
|
+
look?.rowLabel ? (
|
|
20118
|
+
// THE COLUMN THAT NAMES EACH RECORD says so (tranche 6i, the older grid's key marker).
|
|
20119
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
20120
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
20121
|
+
"span",
|
|
20122
|
+
{
|
|
20123
|
+
"data-records-row-label": field2.key,
|
|
20124
|
+
title: "This column names each record",
|
|
20125
|
+
"aria-label": "Names each record",
|
|
20126
|
+
className: "text-[10px] text-muted-foreground",
|
|
20127
|
+
children: "\u26BF"
|
|
20128
|
+
}
|
|
20129
|
+
),
|
|
20130
|
+
name
|
|
20131
|
+
] })
|
|
20132
|
+
) : workedOut && stampMarkOf(field2) ? (
|
|
20133
|
+
// A STAMP OR A RECORD NUMBER (walk 2026-10-08 D7): kept by the store, but nobody wrote a formula
|
|
20134
|
+
// for it, so its header wears its own mark — a clock, a person, a number sign — never "fx".
|
|
20135
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "inline-flex items-center", title: workedOut, "data-records-stamp": stampMarkOf(field2), children: withTypeMark(field2, name) })
|
|
20136
|
+
) : workedOut ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
20137
|
+
name,
|
|
20020
20138
|
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
20021
20139
|
"span",
|
|
20022
20140
|
{
|
|
20023
|
-
"data-records-
|
|
20024
|
-
title:
|
|
20025
|
-
"aria-label":
|
|
20026
|
-
className: "text-[10px] text-muted-foreground",
|
|
20027
|
-
children: "
|
|
20141
|
+
"data-records-worked-out": field2.key,
|
|
20142
|
+
title: workedOut,
|
|
20143
|
+
"aria-label": workedOut,
|
|
20144
|
+
className: "rounded bg-muted px-1 font-mono text-[10px] font-normal text-muted-foreground",
|
|
20145
|
+
children: "fx"
|
|
20028
20146
|
}
|
|
20029
|
-
)
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
) : workedOut && stampMarkOf(field2) ? (
|
|
20033
|
-
// A STAMP OR A RECORD NUMBER (walk 2026-10-08 D7): kept by the store, but nobody wrote a formula
|
|
20034
|
-
// for it, so its header wears its own mark — a clock, a person, a number sign — never "fx".
|
|
20035
|
-
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "inline-flex items-center", title: workedOut, "data-records-stamp": stampMarkOf(field2), children: withTypeMark(field2, name) })
|
|
20036
|
-
) : workedOut ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
20037
|
-
name,
|
|
20038
|
-
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
20039
|
-
"span",
|
|
20040
|
-
{
|
|
20041
|
-
"data-records-worked-out": field2.key,
|
|
20042
|
-
title: workedOut,
|
|
20043
|
-
"aria-label": workedOut,
|
|
20044
|
-
className: "rounded bg-muted px-1 font-mono text-[10px] font-normal text-muted-foreground",
|
|
20045
|
-
children: "fx"
|
|
20046
|
-
}
|
|
20047
|
-
)
|
|
20048
|
-
] }) : name,
|
|
20147
|
+
)
|
|
20148
|
+
] }) : name
|
|
20149
|
+
),
|
|
20049
20150
|
label: name,
|
|
20050
20151
|
accessorFn: (row) => row.document?.[field2.key],
|
|
20051
20152
|
// A column the store keeps no value for is not offered a sort it would refuse (`sortRefusal`).
|
|
@@ -21236,7 +21337,7 @@ function columnsSentence(mapped, total, unmapped) {
|
|
|
21236
21337
|
if (unmapped === "ignore") return `${mapped} of ${total} columns go into this table \xB7 ${rest} left out`;
|
|
21237
21338
|
return `${mapped} of ${total} go in now \xB7 ${rest} wait for approval with their values`;
|
|
21238
21339
|
}
|
|
21239
|
-
function ImportWizard({ tableId, source, onDone, onWrote, className }) {
|
|
21340
|
+
function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className }) {
|
|
21240
21341
|
const client = (0, import_react120.useRecordsClient)();
|
|
21241
21342
|
const table = (0, import_react120.useTable)(tableId);
|
|
21242
21343
|
const fields = (0, import_react120.useFields)(tableId);
|
|
@@ -21858,6 +21959,13 @@ function ImportWizard({ tableId, source, onDone, onWrote, className }) {
|
|
|
21858
21959
|
const refusedByRules = ruleVerdicts.reduce((n, v) => n + v.refused, 0);
|
|
21859
21960
|
const [goAheadAnyway, setGoAheadAnyway] = (0, import_react119.useState)(false);
|
|
21860
21961
|
(0, import_react119.useEffect)(() => setGoAheadAnyway(false), [ruleVerdicts]);
|
|
21962
|
+
const [autoRan, setAutoRan] = (0, import_react119.useState)(false);
|
|
21963
|
+
(0, import_react119.useEffect)(() => {
|
|
21964
|
+
if (!autoRun || autoRan || !source || phase !== "ready" || !plan) return;
|
|
21965
|
+
if (busy || !rights.write || rows.length === 0 || titleMissing || ruleVerdicts.length > 0) return;
|
|
21966
|
+
setAutoRan(true);
|
|
21967
|
+
void run();
|
|
21968
|
+
}, [autoRun, autoRan, source, phase, plan, busy, rights.write, rows.length, titleMissing, ruleVerdicts, run]);
|
|
21861
21969
|
const afterWrite = !busy && (phase === "done" || alreadyRan !== null || ledger !== null && ledger.seen > 0);
|
|
21862
21970
|
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: (0, import_design_system64.cn)("flex min-w-0 flex-col gap-2 text-xs", className), children: [
|
|
21863
21971
|
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
@@ -25981,7 +26089,8 @@ function GridBody({
|
|
|
25981
26089
|
...presentation.formats?.[field2.key] ? { format: presentation.formats[field2.key] } : {},
|
|
25982
26090
|
frozen: frozenKeys.has(field2.key),
|
|
25983
26091
|
// The column that names each record wears the mark (merged grid, tranche 6i).
|
|
25984
|
-
rowLabel: merged && field2.key === (table.data?.title_field ?? null)
|
|
26092
|
+
rowLabel: merged && field2.key === (table.data?.title_field ?? null),
|
|
26093
|
+
syncedFrom: syncedFromWords(table.data)
|
|
25985
26094
|
},
|
|
25986
26095
|
onAskWhoChanged,
|
|
25987
26096
|
{
|
|
@@ -27170,6 +27279,12 @@ function withHeaderMenus(columns, menuFor, filterFor) {
|
|
|
27170
27279
|
return filter ? { ...withMenu, ...filter } : withMenu;
|
|
27171
27280
|
});
|
|
27172
27281
|
}
|
|
27282
|
+
function syncedFromWords(table) {
|
|
27283
|
+
const source = table?.sync_source;
|
|
27284
|
+
if (!source?.provider) return null;
|
|
27285
|
+
const from = source.provider === "google_sheets" ? "Google Sheets" : source.provider === "csv_url" ? "a CSV link" : source.provider === "postgres" ? "an outside database" : source.provider === "matrx_view" ? "another table" : source.provider;
|
|
27286
|
+
return source.label ? `${from} \xB7 ${source.label}` : from;
|
|
27287
|
+
}
|
|
27173
27288
|
function withoutGoneColumns(query, liveKeys, openingSort) {
|
|
27174
27289
|
const sortGone = Boolean(query.sort && !liveKeys.has(query.sort.id));
|
|
27175
27290
|
const goneFilters = Object.keys(query.columnFilters ?? {}).filter((key) => !liveKeys.has(key));
|
|
@@ -28404,7 +28519,7 @@ function NewTableStart({
|
|
|
28404
28519
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_design_system74.Button, { disabled: !importReady || busy, onClick: () => void continueImport(), "data-new-table-continue": "", children: busy ? "Creating\u2026" : "Next: columns" })
|
|
28405
28520
|
] });
|
|
28406
28521
|
} else {
|
|
28407
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { "data-new-table-wizard": "", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ImportWizard, { tableId: step2.tableId, source: step2.source, onDone: () => onOpenTable?.(step2.tableId) }) });
|
|
28522
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { "data-new-table-wizard": "", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ImportWizard, { tableId: step2.tableId, source: step2.source, autoRun: step2.made, onDone: () => onOpenTable?.(step2.tableId) }) });
|
|
28408
28523
|
footer = /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_jsx_runtime89.Fragment, { children: [
|
|
28409
28524
|
!step2.made ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_design_system74.Button, { variant: "ghost", className: "mr-auto", onClick: () => setStep({ at: "import" }), children: "Back" }) : null,
|
|
28410
28525
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_design_system74.Button, { variant: "outline", onClick: () => onOpenTable?.(step2.tableId), "data-new-table-open": "", children: "Open the table" })
|
|
@@ -35168,6 +35283,7 @@ function TimelineView({
|
|
|
35168
35283
|
const [dragging, setDragging] = (0, import_react207.useState)(null);
|
|
35169
35284
|
const [linking, setLinking] = (0, import_react207.useState)(null);
|
|
35170
35285
|
const [ganttBusy, setGanttBusy] = (0, import_react207.useState)(false);
|
|
35286
|
+
const [linkTarget, setLinkTarget] = (0, import_react207.useState)(null);
|
|
35171
35287
|
const { placed, unscheduled } = (0, import_react207.useMemo)(() => {
|
|
35172
35288
|
const out = [];
|
|
35173
35289
|
const without = [];
|
|
@@ -35336,6 +35452,18 @@ function TimelineView({
|
|
|
35336
35452
|
label: `${titleOf(target)} now waits on ${titleOf(source)}`
|
|
35337
35453
|
});
|
|
35338
35454
|
};
|
|
35455
|
+
const taskRowAt = (x, y) => {
|
|
35456
|
+
const canvas = scroller.current?.querySelector("[data-timeline-canvas]");
|
|
35457
|
+
const body2 = scroller.current;
|
|
35458
|
+
if (!canvas || !body2) return null;
|
|
35459
|
+
const box = canvas.getBoundingClientRect();
|
|
35460
|
+
const frame2 = body2.getBoundingClientRect();
|
|
35461
|
+
if (frame2.width === 0 || x < frame2.left || x > frame2.right) return null;
|
|
35462
|
+
const index = Math.floor((y - box.top - LANE_PAD / 2) / ROW_PX);
|
|
35463
|
+
if (index < 0) return null;
|
|
35464
|
+
const lane = laneRows[0];
|
|
35465
|
+
return lane?.packed.find((b) => b.row === index)?.p.row.id ?? null;
|
|
35466
|
+
};
|
|
35339
35467
|
const beginLink = (p) => (e) => {
|
|
35340
35468
|
if (e.button !== void 0 && e.button !== 0) return;
|
|
35341
35469
|
e.stopPropagation();
|
|
@@ -35344,13 +35472,21 @@ function TimelineView({
|
|
|
35344
35472
|
const x1 = box.left + box.width / 2;
|
|
35345
35473
|
const y1 = box.top + box.height / 2;
|
|
35346
35474
|
setLinking({ id: p.row.id, x1, y1, x2: e.clientX, y2: e.clientY });
|
|
35347
|
-
const onMove = (ev) =>
|
|
35475
|
+
const onMove = (ev) => {
|
|
35476
|
+
const x = ev.clientX;
|
|
35477
|
+
const y = ev.clientY;
|
|
35478
|
+
setLinking((l) => l ? { ...l, x2: x, y2: y } : l);
|
|
35479
|
+
const over = taskRowAt(x, y);
|
|
35480
|
+
setLinkTarget(over && over !== p.row.id ? over : null);
|
|
35481
|
+
};
|
|
35348
35482
|
const onUp = (ev) => {
|
|
35349
35483
|
window.removeEventListener("pointermove", onMove);
|
|
35350
35484
|
window.removeEventListener("pointerup", onUp);
|
|
35351
35485
|
setLinking(null);
|
|
35486
|
+
setLinkTarget(null);
|
|
35487
|
+
const at = ev;
|
|
35352
35488
|
const hit = ev.target?.closest?.("[data-timeline-bar]");
|
|
35353
|
-
const id = hit?.getAttribute("data-timeline-bar");
|
|
35489
|
+
const id = taskRowAt(at.clientX, at.clientY) ?? hit?.getAttribute("data-timeline-bar");
|
|
35354
35490
|
if (id && id !== p.row.id) connect(p.row.id, id);
|
|
35355
35491
|
};
|
|
35356
35492
|
window.addEventListener("pointermove", onMove);
|
|
@@ -35362,7 +35498,7 @@ function TimelineView({
|
|
|
35362
35498
|
try {
|
|
35363
35499
|
const make = async (current, key, label) => {
|
|
35364
35500
|
if (current) return current.key;
|
|
35365
|
-
const made = await knobClient.fieldDeclare({ table_id: tableId, spec: { key, label,
|
|
35501
|
+
const made = await knobClient.fieldDeclare({ table_id: tableId, spec: { key, label, parity_type: "datetime", kind: "date" } });
|
|
35366
35502
|
if (!made.ok) {
|
|
35367
35503
|
moves.say(refusalSentence(made.error));
|
|
35368
35504
|
return null;
|
|
@@ -35581,6 +35717,7 @@ function TimelineView({
|
|
|
35581
35717
|
"data-timeline-span": `${first}..${last}`,
|
|
35582
35718
|
...p.marker ? { "data-timeline-marker": "" } : {},
|
|
35583
35719
|
...milestone ? { "data-timeline-milestone": "" } : {},
|
|
35720
|
+
...linkTarget === p.row.id ? { "data-timeline-drop-target": "" } : {},
|
|
35584
35721
|
...onCritical ? { "data-timeline-critical": "" } : {},
|
|
35585
35722
|
...slip !== null ? { "data-timeline-slip": slip } : {},
|
|
35586
35723
|
...may ? {} : { "data-timeline-locked": "" },
|
|
@@ -35594,6 +35731,7 @@ function TimelineView({
|
|
|
35594
35731
|
outside ? "overflow-visible" : "overflow-hidden",
|
|
35595
35732
|
milestone ? "border-transparent bg-transparent" : color ? import_data_table22.CHOICE_CHIP_CLASS[color] : "bg-muted",
|
|
35596
35733
|
onCritical ? "ring-2 ring-amber-500" : void 0,
|
|
35734
|
+
linkTarget === p.row.id ? "ring-2 ring-primary" : void 0,
|
|
35597
35735
|
may ? "cursor-grab active:cursor-grabbing" : "cursor-pointer",
|
|
35598
35736
|
dragging?.id === p.row.id ? "z-20 shadow-md" : "z-10",
|
|
35599
35737
|
refused ? "ring-2 ring-destructive" : void 0
|
|
@@ -35675,7 +35813,7 @@ function TimelineView({
|
|
|
35675
35813
|
/* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: [
|
|
35676
35814
|
settings,
|
|
35677
35815
|
/* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(import_design_system102.DropdownMenu, { children: [
|
|
35678
|
-
/* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_design_system102.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_design_system102.Button, { size: "sm", variant: ganttOn ? "secondary" :
|
|
35816
|
+
/* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_design_system102.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_design_system102.Button, { size: "sm", variant: "outline", className: ganttOn ? "bg-secondary" : void 0, "aria-label": "Gantt options", "data-timeline-gantt-menu": "", children: "Gantt" }) }),
|
|
35679
35817
|
/* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(import_design_system102.DropdownMenuContent, { align: "end", className: "min-w-48", children: [
|
|
35680
35818
|
/* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_design_system102.DropdownMenuCheckboxItem, { checked: ganttOn, onCheckedChange: (on) => setGantt({ mode: on === true }), children: "Gantt view" }),
|
|
35681
35819
|
ganttOn ? /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(import_jsx_runtime120.Fragment, { children: [
|
|
@@ -35753,6 +35891,7 @@ function TimelineView({
|
|
|
35753
35891
|
const ghost = baselineOf(b.p.row);
|
|
35754
35892
|
const at = shown5(b.p);
|
|
35755
35893
|
return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("div", { children: [
|
|
35894
|
+
linkTarget === b.p.row.id ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("div", { "aria-hidden": "true", "data-timeline-drop-band": b.p.row.id, className: "pointer-events-none absolute inset-x-0 bg-primary/10", style: { top: LANE_PAD / 2 + b.row * ROW_PX, height: ROW_PX } }) : null,
|
|
35756
35895
|
ghost ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
|
|
35757
35896
|
"div",
|
|
35758
35897
|
{
|
|
@@ -39055,6 +39194,9 @@ function ArchivedPortals({
|
|
|
39055
39194
|
var import_react230 = require("react");
|
|
39056
39195
|
var import_react231 = require("@ai-matrx/records/react");
|
|
39057
39196
|
var import_design_system112 = require("@ai-matrx/design-system");
|
|
39197
|
+
var import_core22 = require("@dnd-kit/core");
|
|
39198
|
+
var import_sortable = require("@dnd-kit/sortable");
|
|
39199
|
+
var import_utilities = require("@dnd-kit/utilities");
|
|
39058
39200
|
|
|
39059
39201
|
// src/seedOnce.ts
|
|
39060
39202
|
var import_react229 = require("react");
|
|
@@ -39076,7 +39218,7 @@ var NOOP3 = () => {
|
|
|
39076
39218
|
};
|
|
39077
39219
|
function viewActions(whyNot, host, locked = false, personal = false) {
|
|
39078
39220
|
const one = (base2, run) => {
|
|
39079
|
-
if (whyNot !== null) return { ...base2, disabledReason: whyNot, run: NOOP3 };
|
|
39221
|
+
if (whyNot !== null) return { ...base2, disabledReason: locked && base2.id !== "duplicate" && base2.id !== "lock" ? VIEW_LOCKED_REASON : whyNot, run: NOOP3 };
|
|
39080
39222
|
if (!run) return { ...base2, disabledReason: ACTION_NOT_HERE_REASON, run: NOOP3 };
|
|
39081
39223
|
return { ...base2, run };
|
|
39082
39224
|
};
|
|
@@ -39119,6 +39261,25 @@ function seedIsSatisfied(seed, views) {
|
|
|
39119
39261
|
if (views.some((v) => v.name === seed.name)) return true;
|
|
39120
39262
|
return seed.isDefault === true && views.some((v) => v.isDefault);
|
|
39121
39263
|
}
|
|
39264
|
+
function SectionBox({ id, children, ...rest }) {
|
|
39265
|
+
const { setNodeRef, isOver } = (0, import_core22.useDroppable)({ id });
|
|
39266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime131.jsx)("div", { ref: setNodeRef, className: (0, import_design_system112.cn)("rounded-sm", isOver && "bg-accent/40"), ...rest, children });
|
|
39267
|
+
}
|
|
39268
|
+
function SortableRow({ id, disabled, children }) {
|
|
39269
|
+
const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = (0, import_sortable.useSortable)({ id, disabled });
|
|
39270
|
+
return /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(
|
|
39271
|
+
"div",
|
|
39272
|
+
{
|
|
39273
|
+
ref: setNodeRef,
|
|
39274
|
+
style: { transform: import_utilities.CSS.Transform.toString(transform), transition },
|
|
39275
|
+
className: (0, import_design_system112.cn)(isDragging && "relative z-10 opacity-80"),
|
|
39276
|
+
"data-view-row": id,
|
|
39277
|
+
...disabled ? {} : attributes,
|
|
39278
|
+
...disabled ? {} : listeners2,
|
|
39279
|
+
children
|
|
39280
|
+
}
|
|
39281
|
+
);
|
|
39282
|
+
}
|
|
39122
39283
|
function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, initialViews, className }) {
|
|
39123
39284
|
const client = (0, import_react231.useRecordsClient)();
|
|
39124
39285
|
const claimSeed = useSeedGuard();
|
|
@@ -39150,6 +39311,26 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
|
|
|
39150
39311
|
}
|
|
39151
39312
|
});
|
|
39152
39313
|
const [renamingSection, setRenamingSection] = (0, import_react230.useState)(null);
|
|
39314
|
+
const [dragging, setDragging] = (0, import_react230.useState)(false);
|
|
39315
|
+
const justDragged = (0, import_react230.useRef)(false);
|
|
39316
|
+
const sensors = (0, import_core22.useSensors)((0, import_core22.useSensor)(import_core22.PointerSensor, { activationConstraint: { distance: 6 } }));
|
|
39317
|
+
async function dropped(event) {
|
|
39318
|
+
setDragging(false);
|
|
39319
|
+
justDragged.current = true;
|
|
39320
|
+
setTimeout(() => {
|
|
39321
|
+
justDragged.current = false;
|
|
39322
|
+
}, 250);
|
|
39323
|
+
if (!event.over || !views) return;
|
|
39324
|
+
const writes = (0, import_views2.planViewDrop)(views, String(event.active.id), String(event.over.id));
|
|
39325
|
+
for (const w of writes) {
|
|
39326
|
+
const written = await saveViewPatch(client, tableId, w.id, { position: w.position, ..."section" in w ? { section: w.section ?? null } : {} });
|
|
39327
|
+
if (!written.ok) {
|
|
39328
|
+
setError(written.error);
|
|
39329
|
+
break;
|
|
39330
|
+
}
|
|
39331
|
+
}
|
|
39332
|
+
if (writes.length > 0) await load();
|
|
39333
|
+
}
|
|
39153
39334
|
const toggleShut = (name) => {
|
|
39154
39335
|
setShut((all) => {
|
|
39155
39336
|
const next = all.includes(name) ? all.filter((n) => n !== name) : [...all, name];
|
|
@@ -39362,83 +39543,89 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
|
|
|
39362
39543
|
) }),
|
|
39363
39544
|
/* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(import_design_system112.PopoverContent, { sizing: "content", align: "start", className: "w-64 p-1", "data-view-picker-content": "", children: [
|
|
39364
39545
|
/* @__PURE__ */ (0, import_jsx_runtime131.jsxs)("div", { role: "group", "aria-label": "Saved views", className: "flex max-h-[50dvh] flex-col overflow-y-auto", children: [
|
|
39365
|
-
|
|
39366
|
-
|
|
39367
|
-
|
|
39368
|
-
|
|
39369
|
-
|
|
39370
|
-
|
|
39371
|
-
|
|
39372
|
-
|
|
39373
|
-
|
|
39374
|
-
|
|
39375
|
-
|
|
39376
|
-
|
|
39377
|
-
|
|
39378
|
-
|
|
39379
|
-
|
|
39380
|
-
|
|
39381
|
-
|
|
39382
|
-
|
|
39383
|
-
|
|
39384
|
-
|
|
39385
|
-
|
|
39386
|
-
|
|
39387
|
-
|
|
39388
|
-
|
|
39389
|
-
|
|
39390
|
-
|
|
39391
|
-
|
|
39392
|
-
|
|
39393
|
-
|
|
39394
|
-
|
|
39395
|
-
|
|
39396
|
-
|
|
39546
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_core22.DndContext, { sensors, collisionDetection: import_core22.closestCenter, onDragStart: () => setDragging(true), onDragCancel: () => setDragging(false), onDragEnd: (e) => void dropped(e), children: (() => {
|
|
39547
|
+
const groups = (0, import_views2.groupViewsBySection)(views);
|
|
39548
|
+
return groups.some((g) => g.name === null) || !dragging ? groups : [{ name: null, views: [] }, ...groups];
|
|
39549
|
+
})().map((group) => /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(SectionBox, { id: (0, import_views2.sectionDropId)(group.name), role: "group", "aria-label": group.name ?? "Views", "data-view-section": group.name ?? "", children: [
|
|
39550
|
+
group.name === null && group.views.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "block px-2 py-1.5 text-[11px] text-muted-foreground", children: "No section" }) : null,
|
|
39551
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(import_sortable.SortableContext, { items: group.views.map((v) => v.id), strategy: import_sortable.verticalListSortingStrategy, children: [
|
|
39552
|
+
group.name !== null ? renamingSection?.from === group.name ? /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(
|
|
39553
|
+
"form",
|
|
39554
|
+
{
|
|
39555
|
+
className: "flex items-center gap-1 px-1 py-1",
|
|
39556
|
+
onSubmit: (e) => {
|
|
39557
|
+
e.preventDefault();
|
|
39558
|
+
void renameSection(group.name, renamingSection.draft);
|
|
39559
|
+
},
|
|
39560
|
+
children: [
|
|
39561
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)(
|
|
39562
|
+
import_design_system112.Input,
|
|
39563
|
+
{
|
|
39564
|
+
autoFocus: true,
|
|
39565
|
+
"aria-label": "New name for this section",
|
|
39566
|
+
value: renamingSection.draft,
|
|
39567
|
+
onChange: (e) => setRenamingSection({ from: group.name, draft: e.target.value }),
|
|
39568
|
+
onKeyDown: (e) => {
|
|
39569
|
+
if (e.key === "Escape") {
|
|
39570
|
+
e.preventDefault();
|
|
39571
|
+
e.stopPropagation();
|
|
39572
|
+
setRenamingSection(null);
|
|
39573
|
+
}
|
|
39574
|
+
},
|
|
39575
|
+
className: "h-7 min-w-0 flex-1 text-xs"
|
|
39576
|
+
}
|
|
39577
|
+
),
|
|
39578
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Button, { size: "sm", type: "submit", className: "h-7", children: "Save" })
|
|
39579
|
+
]
|
|
39580
|
+
}
|
|
39581
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)("div", { className: "group flex min-h-7 items-center gap-1 px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: [
|
|
39582
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(
|
|
39583
|
+
"button",
|
|
39584
|
+
{
|
|
39585
|
+
type: "button",
|
|
39586
|
+
className: "flex min-w-0 flex-1 items-center gap-1 text-left",
|
|
39587
|
+
"aria-expanded": !shut.includes(group.name),
|
|
39588
|
+
"data-view-section-toggle": "",
|
|
39589
|
+
onClick: () => toggleShut(group.name),
|
|
39590
|
+
children: [
|
|
39591
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("svg", { viewBox: "0 0 24 24", className: (0, import_design_system112.cn)("h-3 w-3 shrink-0", shut.includes(group.name) && "-rotate-90"), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime131.jsx)("path", { d: "m6 9 6 6 6-6" }) }),
|
|
39592
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "truncate", children: group.name }),
|
|
39593
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "shrink-0 font-normal normal-case", children: group.views.length })
|
|
39594
|
+
]
|
|
39595
|
+
}
|
|
39596
|
+
),
|
|
39597
|
+
rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(import_jsx_runtime131.Fragment, { children: [
|
|
39598
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("button", { type: "button", className: "shrink-0 normal-case hover:text-foreground", "data-view-section-rename": "", onClick: () => setRenamingSection({ from: group.name, draft: group.name }), children: "Rename" }),
|
|
39599
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("button", { type: "button", className: "shrink-0 normal-case hover:text-destructive", "data-view-section-delete": "", title: "The views stay; they leave the section", onClick: () => void renameSection(group.name, null), children: "Delete" })
|
|
39600
|
+
] }) : null
|
|
39601
|
+
] }) : null,
|
|
39602
|
+
group.name !== null && shut.includes(group.name) && !group.views.some((v) => v.id === active) ? null : group.views.map((view) => /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(SortableRow, { id: view.id, disabled: !(rights.admin || view.personal) || view.presentation?.locked === true, children: /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(
|
|
39397
39603
|
"button",
|
|
39398
39604
|
{
|
|
39399
39605
|
type: "button",
|
|
39400
|
-
|
|
39401
|
-
|
|
39402
|
-
|
|
39403
|
-
|
|
39606
|
+
"aria-pressed": view.id === active,
|
|
39607
|
+
className: (0, import_design_system112.cn)(
|
|
39608
|
+
"flex min-h-8 w-full items-center gap-2 rounded-sm px-2 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
|
|
39609
|
+
group.name !== null && "pl-4",
|
|
39610
|
+
view.id === active && "font-medium"
|
|
39611
|
+
),
|
|
39612
|
+
onClick: () => {
|
|
39613
|
+
if (justDragged.current) return;
|
|
39614
|
+
setActive(view.id);
|
|
39615
|
+
onActiveView?.(view);
|
|
39616
|
+
setOpen(false);
|
|
39617
|
+
},
|
|
39618
|
+
title: view.ruleId ? "Membership is this view's Rule" : "The whole table",
|
|
39404
39619
|
children: [
|
|
39405
|
-
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("
|
|
39406
|
-
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("
|
|
39407
|
-
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("
|
|
39620
|
+
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "min-w-0 flex-1 truncate", children: view.name }),
|
|
39621
|
+
view.presentation?.locked === true ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-locked": "", title: VIEW_LOCKED_REASON, children: "Locked" }) : null,
|
|
39622
|
+
view.personal ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-personal": "", title: "Only you see this view", children: "Personal" }) : null,
|
|
39623
|
+
view.isDefault ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-default": "", children: "Default" }) : null
|
|
39408
39624
|
]
|
|
39409
39625
|
}
|
|
39410
|
-
),
|
|
39411
|
-
|
|
39412
|
-
|
|
39413
|
-
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("button", { type: "button", className: "shrink-0 normal-case hover:text-destructive", "data-view-section-delete": "", title: "The views stay; they leave the section", onClick: () => void renameSection(group.name, null), children: "Delete" })
|
|
39414
|
-
] }) : null
|
|
39415
|
-
] }) : null,
|
|
39416
|
-
group.name !== null && shut.includes(group.name) && !group.views.some((v) => v.id === active) ? null : group.views.map((view) => /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(
|
|
39417
|
-
"button",
|
|
39418
|
-
{
|
|
39419
|
-
type: "button",
|
|
39420
|
-
"aria-pressed": view.id === active,
|
|
39421
|
-
className: (0, import_design_system112.cn)(
|
|
39422
|
-
"flex min-h-8 w-full items-center gap-2 rounded-sm px-2 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
|
|
39423
|
-
group.name !== null && "pl-4",
|
|
39424
|
-
view.id === active && "font-medium"
|
|
39425
|
-
),
|
|
39426
|
-
onClick: () => {
|
|
39427
|
-
setActive(view.id);
|
|
39428
|
-
onActiveView?.(view);
|
|
39429
|
-
setOpen(false);
|
|
39430
|
-
},
|
|
39431
|
-
title: view.ruleId ? "Membership is this view's Rule" : "The whole table",
|
|
39432
|
-
children: [
|
|
39433
|
-
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "min-w-0 flex-1 truncate", children: view.name }),
|
|
39434
|
-
view.presentation?.locked === true ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-locked": "", title: VIEW_LOCKED_REASON, children: "Locked" }) : null,
|
|
39435
|
-
view.personal ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-personal": "", title: "Only you see this view", children: "Personal" }) : null,
|
|
39436
|
-
view.isDefault ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)(import_design_system112.Badge, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-default": "", children: "Default" }) : null
|
|
39437
|
-
]
|
|
39438
|
-
},
|
|
39439
|
-
view.id
|
|
39440
|
-
))
|
|
39441
|
-
] }, group.name ?? "__loose")),
|
|
39626
|
+
) }, view.id))
|
|
39627
|
+
] })
|
|
39628
|
+
] }, group.name ?? "__loose")) }),
|
|
39442
39629
|
views.length === 0 && !rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime131.jsx)("span", { className: "px-2 py-1 text-xs text-muted-foreground", children: rights.why("structure") }) : null
|
|
39443
39630
|
] }),
|
|
39444
39631
|
/* @__PURE__ */ (0, import_jsx_runtime131.jsx)("div", { className: "mt-1 border-t border-border pt-1", children: naming ? /* @__PURE__ */ (0, import_jsx_runtime131.jsxs)(
|
|
@@ -44719,9 +44906,9 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
|
|
|
44719
44906
|
var import_clipboard10 = require("@ai-matrx/kit/clipboard");
|
|
44720
44907
|
var import_design_system132 = require("@ai-matrx/design-system");
|
|
44721
44908
|
var import_react266 = require("react");
|
|
44722
|
-
var
|
|
44723
|
-
var
|
|
44724
|
-
var
|
|
44909
|
+
var import_core23 = require("@dnd-kit/core");
|
|
44910
|
+
var import_sortable2 = require("@dnd-kit/sortable");
|
|
44911
|
+
var import_utilities2 = require("@dnd-kit/utilities");
|
|
44725
44912
|
var import_react267 = require("@ai-matrx/records/react");
|
|
44726
44913
|
var import_records67 = require("@ai-matrx/records");
|
|
44727
44914
|
var import_design_system133 = require("@ai-matrx/design-system");
|
|
@@ -46352,9 +46539,9 @@ function QuestionList({
|
|
|
46352
46539
|
onQuestions,
|
|
46353
46540
|
onQuestion
|
|
46354
46541
|
}) {
|
|
46355
|
-
const sensors = (0,
|
|
46356
|
-
(0,
|
|
46357
|
-
(0,
|
|
46542
|
+
const sensors = (0, import_core23.useSensors)(
|
|
46543
|
+
(0, import_core23.useSensor)(import_core23.PointerSensor, { activationConstraint: { distance: 4 } }),
|
|
46544
|
+
(0, import_core23.useSensor)(import_core23.KeyboardSensor, { coordinateGetter: import_sortable2.sortableKeyboardCoordinates })
|
|
46358
46545
|
);
|
|
46359
46546
|
const askable = askableFields([...fields]);
|
|
46360
46547
|
const unasked = askable.filter((f) => !draft.questions.some((q) => q.field === f.key));
|
|
@@ -46367,7 +46554,7 @@ function QuestionList({
|
|
|
46367
46554
|
const from = draft.questions.findIndex((q) => q.field === event.active.id);
|
|
46368
46555
|
const to = event.over ? draft.questions.findIndex((q) => q.field === event.over.id) : -1;
|
|
46369
46556
|
if (from < 0 || to < 0 || from === to) return;
|
|
46370
|
-
onQuestions((0,
|
|
46557
|
+
onQuestions((0, import_sortable2.arrayMove)(draft.questions, from, to));
|
|
46371
46558
|
}
|
|
46372
46559
|
const notAskable = whyNotAskable([...fields]);
|
|
46373
46560
|
const leftUnasked = requiredLeftUnasked([...fields], draft.questions.map((q) => q.field));
|
|
@@ -46376,7 +46563,7 @@ function QuestionList({
|
|
|
46376
46563
|
/* @__PURE__ */ (0, import_jsx_runtime151.jsx)("span", { className: "font-medium text-foreground", children: "Questions" }),
|
|
46377
46564
|
/* @__PURE__ */ (0, import_jsx_runtime151.jsx)("span", { className: "tabular-nums", children: draft.questions.length })
|
|
46378
46565
|
] }),
|
|
46379
|
-
/* @__PURE__ */ (0, import_jsx_runtime151.jsx)(
|
|
46566
|
+
/* @__PURE__ */ (0, import_jsx_runtime151.jsx)(import_core23.DndContext, { sensors, collisionDetection: import_core23.closestCenter, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime151.jsx)(import_sortable2.SortableContext, { items: draft.questions.map((q) => q.field), strategy: import_sortable2.verticalListSortingStrategy, children: draft.questions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime151.jsx)(
|
|
46380
46567
|
QuestionRow,
|
|
46381
46568
|
{
|
|
46382
46569
|
index,
|
|
@@ -46429,14 +46616,14 @@ function QuestionRow({
|
|
|
46429
46616
|
onChange,
|
|
46430
46617
|
onRemove
|
|
46431
46618
|
}) {
|
|
46432
|
-
const sortable = (0,
|
|
46619
|
+
const sortable = (0, import_sortable2.useSortable)({ id: question.field });
|
|
46433
46620
|
const [open, setOpen] = (0, import_react266.useState)(true);
|
|
46434
46621
|
const name = field2 ? fieldName(field2) : question.field;
|
|
46435
46622
|
return /* @__PURE__ */ (0, import_jsx_runtime151.jsxs)(
|
|
46436
46623
|
"div",
|
|
46437
46624
|
{
|
|
46438
46625
|
ref: sortable.setNodeRef,
|
|
46439
|
-
style: { transform:
|
|
46626
|
+
style: { transform: import_utilities2.CSS.Transform.toString(sortable.transform), transition: sortable.transition },
|
|
46440
46627
|
className: (0, import_design_system133.cn)("rounded border bg-background px-2 py-1.5", sortable.isDragging && "z-10 shadow-md"),
|
|
46441
46628
|
"data-records-form-question-row": question.field,
|
|
46442
46629
|
children: [
|
|
@@ -47372,9 +47559,9 @@ var import_react280 = require("@ai-matrx/records/react");
|
|
|
47372
47559
|
var import_design_system140 = require("@ai-matrx/design-system");
|
|
47373
47560
|
|
|
47374
47561
|
// src/DashboardGrid.tsx
|
|
47375
|
-
var
|
|
47376
|
-
var
|
|
47377
|
-
var
|
|
47562
|
+
var import_core24 = require("@dnd-kit/core");
|
|
47563
|
+
var import_sortable3 = require("@dnd-kit/sortable");
|
|
47564
|
+
var import_utilities3 = require("@dnd-kit/utilities");
|
|
47378
47565
|
var import_design_system138 = require("@ai-matrx/design-system");
|
|
47379
47566
|
|
|
47380
47567
|
// src/dashboardLayout.ts
|
|
@@ -47428,7 +47615,7 @@ function withBlockIds(blocks) {
|
|
|
47428
47615
|
// src/DashboardGrid.tsx
|
|
47429
47616
|
var import_jsx_runtime156 = require("react/jsx-runtime");
|
|
47430
47617
|
var dashboardCollision = (args) => {
|
|
47431
|
-
const under = (0,
|
|
47618
|
+
const under = (0, import_core24.pointerWithin)(args);
|
|
47432
47619
|
if (under.length > 0) return under;
|
|
47433
47620
|
const at = args.collisionRect;
|
|
47434
47621
|
return args.droppableContainers.flatMap((container) => {
|
|
@@ -47438,9 +47625,9 @@ var dashboardCollision = (args) => {
|
|
|
47438
47625
|
}).sort((a, b) => a.data.value - b.data.value);
|
|
47439
47626
|
};
|
|
47440
47627
|
function DashboardGrid({ items, arranging, onMove, onSpan }) {
|
|
47441
|
-
const sensors = (0,
|
|
47442
|
-
(0,
|
|
47443
|
-
(0,
|
|
47628
|
+
const sensors = (0, import_core24.useSensors)(
|
|
47629
|
+
(0, import_core24.useSensor)(import_core24.PointerSensor, { activationConstraint: { distance: 4 } }),
|
|
47630
|
+
(0, import_core24.useSensor)(import_core24.KeyboardSensor, { coordinateGetter: import_sortable3.sortableKeyboardCoordinates })
|
|
47444
47631
|
);
|
|
47445
47632
|
const ids = items.map((item) => item.id);
|
|
47446
47633
|
function dragEnd(event) {
|
|
@@ -47450,7 +47637,7 @@ function DashboardGrid({ items, arranging, onMove, onSpan }) {
|
|
|
47450
47637
|
}
|
|
47451
47638
|
const grid = /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-12", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(GridCell2, { item, index, arranging, onSpan }, item.id)) });
|
|
47452
47639
|
if (!arranging) return grid;
|
|
47453
|
-
return /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(
|
|
47640
|
+
return /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(import_core24.DndContext, { sensors, collisionDetection: dashboardCollision, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(import_sortable3.SortableContext, { items: ids, strategy: import_sortable3.rectSortingStrategy, children: grid }) });
|
|
47454
47641
|
}
|
|
47455
47642
|
function GridCell2({
|
|
47456
47643
|
item,
|
|
@@ -47458,8 +47645,8 @@ function GridCell2({
|
|
|
47458
47645
|
arranging,
|
|
47459
47646
|
onSpan
|
|
47460
47647
|
}) {
|
|
47461
|
-
const sortable = (0,
|
|
47462
|
-
const style = arranging ? { transform:
|
|
47648
|
+
const sortable = (0, import_sortable3.useSortable)({ id: item.id, disabled: !arranging });
|
|
47649
|
+
const style = arranging ? { transform: import_utilities3.CSS.Transform.toString(sortable.transform), transition: sortable.transition } : void 0;
|
|
47463
47650
|
return /* @__PURE__ */ (0, import_jsx_runtime156.jsxs)(
|
|
47464
47651
|
"div",
|
|
47465
47652
|
{
|
|
@@ -49316,7 +49503,7 @@ function AgentAnswer({
|
|
|
49316
49503
|
// src/PageScreen.tsx
|
|
49317
49504
|
var import_react285 = require("react");
|
|
49318
49505
|
var import_react286 = require("@ai-matrx/records/react");
|
|
49319
|
-
var
|
|
49506
|
+
var import_core25 = require("@ai-matrx/records/core");
|
|
49320
49507
|
var import_design_system143 = require("@ai-matrx/design-system");
|
|
49321
49508
|
var import_forms4 = require("@ai-matrx/records/forms");
|
|
49322
49509
|
var import_jsx_runtime161 = require("react/jsx-runtime");
|
|
@@ -49733,7 +49920,7 @@ function ListBlockView({
|
|
|
49733
49920
|
...sort.length > 0 ? { sort } : {}
|
|
49734
49921
|
});
|
|
49735
49922
|
const reload = page.reload;
|
|
49736
|
-
(0, import_react285.useEffect)(() => (0,
|
|
49923
|
+
(0, import_react285.useEffect)(() => (0, import_core25.onRecordChanged)(() => reload()), [reload]);
|
|
49737
49924
|
const rows = nobodyIsMe ? [] : page.data?.rows ?? [];
|
|
49738
49925
|
const columns = block.columns && block.columns.length > 0 ? block.columns.map((k) => all.find((f) => f.key === k)).filter((f) => !!f) : [...all].sort((a, b) => (a.sort ?? 100) - (b.sort ?? 100)).slice(0, DEFAULT_COLUMNS);
|
|
49739
49926
|
const firstId = rows[0]?.id ?? null;
|
|
@@ -51362,9 +51549,9 @@ function CalendarSubscribeDialog({
|
|
|
51362
51549
|
|
|
51363
51550
|
// src/viewShare.ts
|
|
51364
51551
|
var import_clipboard15 = require("@ai-matrx/kit/clipboard");
|
|
51365
|
-
var
|
|
51552
|
+
var import_core26 = require("@ai-matrx/print/core");
|
|
51366
51553
|
var import_markdown = require("@ai-matrx/print/markdown");
|
|
51367
|
-
var
|
|
51554
|
+
var import_core27 = require("@ai-matrx/records/core");
|
|
51368
51555
|
var NO_VIEW_REASON = "No saved view yet";
|
|
51369
51556
|
function viewLink(tableId, viewId, origin) {
|
|
51370
51557
|
return `${tableLink(tableId, origin)}?view=${encodeURIComponent(viewId)}`;
|
|
@@ -51400,7 +51587,7 @@ async function downloadViewCsv(args) {
|
|
|
51400
51587
|
const columns = viewColumns(fields, view.presentation);
|
|
51401
51588
|
const rows = await rowsForFile({ client, host, fields: columns, records: read.rows, labels });
|
|
51402
51589
|
const name = fileNameOf(args.tableName) || "records";
|
|
51403
|
-
download(`${name}.csv`, "text/csv;charset=utf-8", (0,
|
|
51590
|
+
download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core27.exportCsv)(columns, rows));
|
|
51404
51591
|
host.notify?.success(read.cut ? cutWords(read.rows.length) : "CSV downloaded");
|
|
51405
51592
|
}
|
|
51406
51593
|
function downloadMarkdownAction(args) {
|
|
@@ -51429,7 +51616,7 @@ async function readViewMarkdown(args) {
|
|
|
51429
51616
|
if ("error" in read) return null;
|
|
51430
51617
|
const columns = viewColumns(fields, view.presentation);
|
|
51431
51618
|
const rows = await rowsForFile({ client, host, fields: columns, records: read.rows, labels });
|
|
51432
|
-
return { markdown: (0,
|
|
51619
|
+
return { markdown: (0, import_core27.exportMarkdown)(columns, rows), cut: read.cut, count: read.rows.length };
|
|
51433
51620
|
}
|
|
51434
51621
|
async function downloadViewMarkdown(args) {
|
|
51435
51622
|
const table = await readViewMarkdown(args);
|
|
@@ -51487,7 +51674,7 @@ async function runTablePageAction(kind, args) {
|
|
|
51487
51674
|
}
|
|
51488
51675
|
const page = (0, import_markdown.renderMarkdownDocument)(markdown, { title, withPrintActions: kind === "html-preview" });
|
|
51489
51676
|
if (kind === "html-preview") {
|
|
51490
|
-
(0,
|
|
51677
|
+
(0, import_core26.openPrintWindow)(page, title);
|
|
51491
51678
|
if (note) args.host.notify?.success(note);
|
|
51492
51679
|
} else if (kind === "copy-html-page") {
|
|
51493
51680
|
if (await (0, import_clipboard15.copyText)(page)) args.host.notify?.success(note ?? "HTML page copied");
|