@ai-matrx/records-ui 0.103.0 → 0.103.2
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 +12 -0
- package/dist/index.cjs +150 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +150 -46
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +10 -2
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +10 -2
- package/dist/pickers.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
## 0.103.2
|
|
4
|
+
|
|
5
|
+
- Republish of 0.103.1 (its publish stopped on two suites fixed on main after its tag: the form runner's date placeholder and a formula clause). No change of its own.
|
|
6
|
+
|
|
7
|
+
**Consumer action:** none.
|
|
8
|
+
|
|
9
|
+
## 0.103.1
|
|
10
|
+
|
|
11
|
+
- `ConditionGroup` takes `maxDepth`: how many levels of groups a person may add below the whole condition (Notion's advanced filter is 2). A deeper saved question still draws; only "Add a group" stops. Left out, no limit (unchanged). Test: `src/condition-group.test.tsx`.
|
|
12
|
+
|
|
13
|
+
**Consumer action:** none.
|
|
14
|
+
|
|
3
15
|
## 0.103.0
|
|
4
16
|
|
|
5
17
|
- **Notion's calculation row on the embedded grid** (Spaces N6): every column's footer cell says "Calculate" on hover and offers Notion's list in Notion's words — Count all · Count unique values · Count empty · Count not empty · Percent empty · Percent not empty · Sum · Average · Median · Min · Max · Range — narrowed to what the column can mean and to the store's `custom.agg_operations`. The pick is reported through `onPresentationChange` as `summaries` (unchanged door). The band stays plain until one is picked.
|
package/dist/index.cjs
CHANGED
|
@@ -1696,6 +1696,7 @@ function PickChips({ chips }) {
|
|
|
1696
1696
|
) });
|
|
1697
1697
|
}
|
|
1698
1698
|
function PickOrAdd({
|
|
1699
|
+
triggerSize = "field",
|
|
1699
1700
|
triggerLabel,
|
|
1700
1701
|
triggerText,
|
|
1701
1702
|
triggerId,
|
|
@@ -1754,7 +1755,7 @@ function PickOrAdd({
|
|
|
1754
1755
|
}
|
|
1755
1756
|
) : null;
|
|
1756
1757
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Popover, { open, onOpenChange, children: [
|
|
1757
|
-
anchored ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex min-h-6 w-full min-w-0 flex-wrap items-center gap-1", "aria-label": triggerLabel, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Button, { id: triggerId, type: "button", size: "sm", variant: "outline", "aria-label": triggerLabel, children: triggerText }) }),
|
|
1758
|
+
anchored ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-pick-anchor": "", className: "flex min-h-6 w-full min-w-0 flex-wrap items-center gap-1", "aria-label": triggerLabel, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Button, { id: triggerId, type: "button", size: "sm", variant: "outline", className: triggerSize === "field" ? "h-9" : void 0, "aria-label": triggerLabel, children: triggerText }) }),
|
|
1758
1759
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1759
1760
|
import_design_system5.PopoverContent,
|
|
1760
1761
|
{
|
|
@@ -4133,6 +4134,7 @@ function PickOne({
|
|
|
4133
4134
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: (0, import_design_system12.cn)("inline-flex min-w-0", className), "data-records-pick-one": "search", "data-pick-value": value, ...attrs ?? {}, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
4134
4135
|
PickOrAdd,
|
|
4135
4136
|
{
|
|
4137
|
+
triggerSize: "compact",
|
|
4136
4138
|
triggerLabel: label,
|
|
4137
4139
|
triggerText: current?.label ?? placeholder ?? "",
|
|
4138
4140
|
triggerId: id,
|
|
@@ -5218,7 +5220,7 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
5218
5220
|
disabled,
|
|
5219
5221
|
autoComplete: "off",
|
|
5220
5222
|
"aria-invalid": refusal4 ? true : void 0,
|
|
5221
|
-
placeholder: helper
|
|
5223
|
+
placeholder: helper ? typedDatePlaceholder(helper) : void 0,
|
|
5222
5224
|
onChange: (e) => retype(e.target.value),
|
|
5223
5225
|
onBlur: () => {
|
|
5224
5226
|
if (!refusal4) return;
|
|
@@ -5232,6 +5234,12 @@ function TypedWordsControl({ field: field2, value, onChange, disabled, id }) {
|
|
|
5232
5234
|
refusal4 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "data-records-typed-refusal": "", "data-records-cell-note": "", role: "status", title: why, className: "text-[11px] leading-snug text-amber-700 dark:text-amber-400", children: refusal4 }) : null
|
|
5233
5235
|
] });
|
|
5234
5236
|
}
|
|
5237
|
+
function typedDatePlaceholder(helper) {
|
|
5238
|
+
const time = "h:mm AM";
|
|
5239
|
+
if (helper === "time") return time;
|
|
5240
|
+
const pattern = (0, import_records12.typedDateText)("2026-11-22").replace("2026", "YYYY").replace("11", "MM").replace("22", "DD");
|
|
5241
|
+
return helper === "datetime" ? `${pattern} ${time}` : pattern;
|
|
5242
|
+
}
|
|
5235
5243
|
function CheckboxControl({ field: field2, value, onChange, disabled, id }) {
|
|
5236
5244
|
const unanswered = value === null || value === void 0;
|
|
5237
5245
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
@@ -6885,16 +6893,16 @@ function cellMarkSentence(field2, document2, value) {
|
|
|
6885
6893
|
const kept = keptAsideFor(document2, field2.key);
|
|
6886
6894
|
return kept ? keptAsideReason(field2, kept) : null;
|
|
6887
6895
|
}
|
|
6888
|
-
|
|
6889
|
-
function WorkedOutError({ field: field2, sentence: sentence2 }) {
|
|
6896
|
+
function WorkedOutError({ field: field2, sentence: sentence2, floated = false }) {
|
|
6890
6897
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
6891
6898
|
"span",
|
|
6892
6899
|
{
|
|
6893
6900
|
"data-records-worked-out-error": field2.key,
|
|
6901
|
+
role: "img",
|
|
6894
6902
|
title: sentence2,
|
|
6895
|
-
"aria-label":
|
|
6896
|
-
className: "cursor-help
|
|
6897
|
-
children:
|
|
6903
|
+
"aria-label": sentence2,
|
|
6904
|
+
className: (floated ? "absolute right-1 top-1/2 z-10 flex -translate-y-1/2 " : "inline-flex align-middle ") + "h-4 w-4 shrink-0 cursor-help items-center justify-center rounded-full bg-destructive text-[10px] font-bold leading-none text-destructive-foreground",
|
|
6905
|
+
children: "!"
|
|
6898
6906
|
}
|
|
6899
6907
|
);
|
|
6900
6908
|
}
|
|
@@ -7123,7 +7131,7 @@ function RecordValue({
|
|
|
7123
7131
|
if (withheld && (value === null || value === void 0)) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(WithheldValue, { field: field2, notice: withheld });
|
|
7124
7132
|
if (value === null || value === void 0) {
|
|
7125
7133
|
const failed = workedOutErrorFor(document2, field2.key);
|
|
7126
|
-
if (failed) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(WorkedOutError, { field: field2, sentence: failed });
|
|
7134
|
+
if (failed) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(WorkedOutError, { field: field2, sentence: failed, floated: Boolean(inCell) });
|
|
7127
7135
|
}
|
|
7128
7136
|
if (inCell) {
|
|
7129
7137
|
const kept = keptAsideFor(document2, field2.key);
|
|
@@ -7746,6 +7754,22 @@ function GridCell({
|
|
|
7746
7754
|
const open = Boolean(
|
|
7747
7755
|
editing && editing.editing?.rowId === row.id && editing.editing.key === field2.key
|
|
7748
7756
|
);
|
|
7757
|
+
const closedControl = (0, import_react38.useRef)(null);
|
|
7758
|
+
const wasOpen = (0, import_react38.useRef)(false);
|
|
7759
|
+
(0, import_react38.useEffect)(() => {
|
|
7760
|
+
if (open) {
|
|
7761
|
+
wasOpen.current = true;
|
|
7762
|
+
return;
|
|
7763
|
+
}
|
|
7764
|
+
if (!wasOpen.current) return;
|
|
7765
|
+
wasOpen.current = false;
|
|
7766
|
+
if (!clickOpens) return;
|
|
7767
|
+
const frame = requestAnimationFrame(() => {
|
|
7768
|
+
const active = document.activeElement;
|
|
7769
|
+
if (!active || active === document.body) closedControl.current?.focus({ preventScroll: true });
|
|
7770
|
+
});
|
|
7771
|
+
return () => cancelAnimationFrame(frame);
|
|
7772
|
+
}, [open, clickOpens]);
|
|
7749
7773
|
const wasActive = (0, import_react38.useRef)(false);
|
|
7750
7774
|
const singlePress = (0, import_react38.useRef)(null);
|
|
7751
7775
|
const cancelSinglePress = () => {
|
|
@@ -7889,9 +7913,13 @@ function GridCell({
|
|
|
7889
7913
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
7890
7914
|
"span",
|
|
7891
7915
|
{
|
|
7916
|
+
ref: closedControl,
|
|
7892
7917
|
role: editable ? "button" : void 0,
|
|
7893
7918
|
"aria-label": editable ? `Edit ${fieldName(field2)}` : void 0,
|
|
7894
|
-
title: cellMark ? cellMark : editable ?
|
|
7919
|
+
title: cellMark ? cellMark : editable ? (
|
|
7920
|
+
// The words match the gesture (WALK3-FIX): one click opens a record-page field.
|
|
7921
|
+
clickOpens ? `${fieldName(field2)} \u2014 click to edit` : `${fieldName(field2)} \u2014 double-click or press Enter to edit`
|
|
7922
|
+
) : fieldIsEditable(field2) ? (
|
|
7895
7923
|
// NOT A DEAD CONTROL AND NOT A SILENT ONE: the cell is plain
|
|
7896
7924
|
// text, and hovering it says exactly why, in the level's own
|
|
7897
7925
|
// words. The editor was never offered, so nothing is refused
|
|
@@ -9151,6 +9179,7 @@ function ChoiceValue({ field: field2, value, onChange }) {
|
|
|
9151
9179
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "inline-flex min-w-0", "data-records-condition-choice": "", "data-pick-value": value, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
9152
9180
|
PickOrAdd,
|
|
9153
9181
|
{
|
|
9182
|
+
triggerSize: "compact",
|
|
9154
9183
|
triggerLabel: `Choice for ${field2.label || field2.key}`,
|
|
9155
9184
|
triggerText: value || "Choose",
|
|
9156
9185
|
open,
|
|
@@ -9374,6 +9403,7 @@ function ConditionGroup({
|
|
|
9374
9403
|
onChange,
|
|
9375
9404
|
emptyLabel = "always",
|
|
9376
9405
|
allowNesting = true,
|
|
9406
|
+
maxDepth,
|
|
9377
9407
|
depth = 0,
|
|
9378
9408
|
onRemove,
|
|
9379
9409
|
className
|
|
@@ -9444,6 +9474,7 @@ function ConditionGroup({
|
|
|
9444
9474
|
onChange: (next) => replaceAt(index, next),
|
|
9445
9475
|
onRemove: () => replaceAt(index, null),
|
|
9446
9476
|
emptyLabel,
|
|
9477
|
+
maxDepth,
|
|
9447
9478
|
depth: depth + 1
|
|
9448
9479
|
}
|
|
9449
9480
|
) }, key);
|
|
@@ -9487,7 +9518,7 @@ function ConditionGroup({
|
|
|
9487
9518
|
children: "Add another condition"
|
|
9488
9519
|
}
|
|
9489
9520
|
),
|
|
9490
|
-
allowNesting ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
9521
|
+
allowNesting && (maxDepth === void 0 || depth < maxDepth) ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
9491
9522
|
import_design_system29.Button,
|
|
9492
9523
|
{
|
|
9493
9524
|
size: "sm",
|
|
@@ -11137,6 +11168,7 @@ function FieldEditor(props) {
|
|
|
11137
11168
|
const [formulaWritten, setFormulaWritten] = (0, import_react59.useState)(() => startingFormulaText.trim() !== "" || Boolean(field2));
|
|
11138
11169
|
const [formulaOk, setFormulaOk] = (0, import_react59.useState)(null);
|
|
11139
11170
|
const [askingToRemove, setAskingToRemove] = (0, import_react59.useState)(false);
|
|
11171
|
+
const [attempted, setAttempted] = (0, import_react59.useState)(false);
|
|
11140
11172
|
const [showsAs, setShowsAs] = (0, import_react59.useState)(() => field2 ? startingChoice(field2) : { format: null, retype: null });
|
|
11141
11173
|
const [backfillError, setBackfillError] = (0, import_react59.useState)(null);
|
|
11142
11174
|
const [notLanded, setNotLanded] = (0, import_react59.useState)(false);
|
|
@@ -11186,6 +11218,8 @@ function FieldEditor(props) {
|
|
|
11186
11218
|
const missing = editing ? formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(choiceList) : null) : formulaMissing ?? (listsChoices ? whatTheChoiceListIsMissing(newChoices) : null) ?? (type === "formula" && formulaWritten ? null : whatIsMissing(
|
|
11187
11219
|
type === "count" ? { type: "rollup", label, options, via, pick, agg: "count", of, relations: totalSources, formulaFields, relationTarget, allowedTypes, noun } : { type, label, options, via, pick, agg, of, relations: sourcesFor(type), formulaFields, relationTarget, allowedTypes, noun }
|
|
11188
11220
|
));
|
|
11221
|
+
const missingShown = missing && (attempted || formulaMissing) ? missing : null;
|
|
11222
|
+
const removeConsequence = field2 ? `${archiveConfirmSentence(`the field \u201C${fieldName(field2)}\u201D`)} Its values stay in every record and come back with it.${linkReaders.length > 0 ? ` ${readersSentence(linkReaders.length, farTable.data?.name ?? null)}` : ""}` : "";
|
|
11189
11223
|
const save = async () => {
|
|
11190
11224
|
if (missing) return;
|
|
11191
11225
|
if (editing && field2) {
|
|
@@ -11333,8 +11367,8 @@ function FieldEditor(props) {
|
|
|
11333
11367
|
const remove = async () => {
|
|
11334
11368
|
if (!field2) return;
|
|
11335
11369
|
const gone = await tableMutation.retire({ field_id: field2.id });
|
|
11336
|
-
setAskingToRemove(false);
|
|
11337
11370
|
if (gone) (onRemoved ?? onSaved)?.();
|
|
11371
|
+
else setAskingToRemove(false);
|
|
11338
11372
|
};
|
|
11339
11373
|
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: (0, import_design_system34.cn)("flex min-w-0 flex-col gap-3 text-xs", className), "data-records-field-editor": "", children: [
|
|
11340
11374
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
@@ -11351,7 +11385,12 @@ function FieldEditor(props) {
|
|
|
11351
11385
|
autoFocus: true,
|
|
11352
11386
|
"aria-label": "Field name",
|
|
11353
11387
|
placeholder: "Day rate",
|
|
11354
|
-
onChange: (e) => setLabel(e.target.value)
|
|
11388
|
+
onChange: (e) => setLabel(e.target.value),
|
|
11389
|
+
onBlur: (e) => {
|
|
11390
|
+
const to = e.relatedTarget;
|
|
11391
|
+
if (to?.textContent === "Cancel") return;
|
|
11392
|
+
setAttempted(true);
|
|
11393
|
+
}
|
|
11355
11394
|
}
|
|
11356
11395
|
)
|
|
11357
11396
|
] }),
|
|
@@ -11639,7 +11678,6 @@ function FieldEditor(props) {
|
|
|
11639
11678
|
] }),
|
|
11640
11679
|
editing && field2 && !onEntity && rulesChanged(savedRules, editedRules) ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(FieldRulePreview, { field: field2, tableId, rules: editedRules }) : null,
|
|
11641
11680
|
mutation.error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RefusalNotice, { error: mutation.error }) : null,
|
|
11642
|
-
missing ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { id: "field-editor-missing", className: "text-[11px] text-muted-foreground", "data-field-editor-missing": "", children: missing }) : null,
|
|
11643
11681
|
notLanded ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
11644
11682
|
RefusalNotice,
|
|
11645
11683
|
{
|
|
@@ -11684,27 +11722,61 @@ function FieldEditor(props) {
|
|
|
11684
11722
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[11px]", children: "The column is made. The records already in the table were not numbered:" }),
|
|
11685
11723
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RefusalNotice, { error: backfillError })
|
|
11686
11724
|
] }) : null,
|
|
11687
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-
|
|
11725
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex min-w-0 flex-nowrap items-center gap-2", "data-field-editor-footer": "", children: [
|
|
11688
11726
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
11689
11727
|
import_design_system34.Button,
|
|
11690
11728
|
{
|
|
11691
11729
|
size: "sm",
|
|
11692
|
-
disabled: mutation.saving ||
|
|
11693
|
-
...
|
|
11694
|
-
onClick: () =>
|
|
11730
|
+
disabled: mutation.saving || Boolean(formulaMissing),
|
|
11731
|
+
...missingShown ? { "aria-describedby": "field-editor-missing" } : {},
|
|
11732
|
+
onClick: () => {
|
|
11733
|
+
if (missing) {
|
|
11734
|
+
setAttempted(true);
|
|
11735
|
+
return;
|
|
11736
|
+
}
|
|
11737
|
+
void save();
|
|
11738
|
+
},
|
|
11695
11739
|
children: mutation.saving ? "Saving\u2026" : field2 ? EDIT_FIELD_SAVE_LABEL : onEntity ? ADD_STANDARD_FIELD_SAVE_LABEL : ADD_FIELD_SAVE_LABEL
|
|
11696
11740
|
}
|
|
11697
11741
|
),
|
|
11698
11742
|
onCancel ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Button, { size: "sm", variant: "ghost", onClick: onCancel, children: "Cancel" }) : null,
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11743
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
11744
|
+
"span",
|
|
11745
|
+
{
|
|
11746
|
+
id: "field-editor-missing",
|
|
11747
|
+
"data-field-editor-missing": missingShown ? "" : void 0,
|
|
11748
|
+
title: missingShown ?? void 0,
|
|
11749
|
+
className: "min-w-0 flex-1 truncate text-[11px] text-muted-foreground",
|
|
11750
|
+
children: missingShown
|
|
11751
|
+
}
|
|
11752
|
+
),
|
|
11753
|
+
field2 ? (
|
|
11754
|
+
/* WALK3-FIX (2026-10-07): the confirm appears IN PLACE. Both states share one grid cell,
|
|
11755
|
+
the idle one drawn invisibly under the asking one and the other way round, so the
|
|
11756
|
+
footer is always as wide and as tall as its larger state: opening the confirm moved
|
|
11757
|
+
the dialog card 0.2278 and closing it 0.1303. The consequence is the tooltip of
|
|
11758
|
+
"Remove it" (interface-text: the slot holds a label, never a paragraph). */
|
|
11759
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "ml-auto grid shrink-0 items-center", "data-field-editor-remove": askingToRemove ? "asking" : "idle", children: [
|
|
11760
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: (0, import_design_system34.cn)("col-start-1 row-start-1 flex items-center justify-end gap-2", askingToRemove && "invisible"), "aria-hidden": askingToRemove || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Button, { size: "sm", variant: "outline", tabIndex: askingToRemove ? -1 : void 0, onClick: () => setAskingToRemove(true), children: "Remove this field" }) }),
|
|
11761
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: (0, import_design_system34.cn)("col-start-1 row-start-1 flex items-center justify-end gap-2", !askingToRemove && "invisible"), "aria-hidden": !askingToRemove || void 0, children: [
|
|
11762
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "whitespace-nowrap text-destructive", "data-field-editor-remove-ask": "", children: "Archive this field?" }),
|
|
11763
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
11764
|
+
import_design_system34.Button,
|
|
11765
|
+
{
|
|
11766
|
+
size: "sm",
|
|
11767
|
+
variant: "destructive",
|
|
11768
|
+
tabIndex: askingToRemove ? void 0 : -1,
|
|
11769
|
+
disabled: mutation.saving,
|
|
11770
|
+
title: removeConsequence,
|
|
11771
|
+
"aria-description": removeConsequence,
|
|
11772
|
+
onClick: () => void remove(),
|
|
11773
|
+
children: "Remove it"
|
|
11774
|
+
}
|
|
11775
|
+
),
|
|
11776
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system34.Button, { size: "sm", variant: "ghost", tabIndex: askingToRemove ? void 0 : -1, onClick: () => setAskingToRemove(false), children: "Keep it" })
|
|
11777
|
+
] })
|
|
11778
|
+
] })
|
|
11779
|
+
) : null
|
|
11708
11780
|
] })
|
|
11709
11781
|
] });
|
|
11710
11782
|
}
|
|
@@ -14527,6 +14599,13 @@ function useMergedGridControls(args) {
|
|
|
14527
14599
|
const tableVersion = useTableVersion(client, tableId, table);
|
|
14528
14600
|
const mutation = (0, import_react81.useFieldMutation)();
|
|
14529
14601
|
const [dialog, setDialog] = (0, import_react80.useState)(null);
|
|
14602
|
+
const lastColumnDialog = (0, import_react80.useRef)(null);
|
|
14603
|
+
const insertEpoch = (0, import_react80.useRef)(0);
|
|
14604
|
+
if (dialog?.kind === "settings" || dialog?.kind === "insert") {
|
|
14605
|
+
if (dialog !== lastColumnDialog.current) insertEpoch.current += 1;
|
|
14606
|
+
lastColumnDialog.current = dialog;
|
|
14607
|
+
}
|
|
14608
|
+
const columnDialog = dialog?.kind === "settings" || dialog?.kind === "insert" ? dialog : lastColumnDialog.current;
|
|
14530
14609
|
const [renameTo, setRenameTo] = (0, import_react80.useState)("");
|
|
14531
14610
|
const [deleteBusy, setDeleteBusy] = (0, import_react80.useState)(false);
|
|
14532
14611
|
const [labelling, setLabelling] = (0, import_react80.useState)(false);
|
|
@@ -15016,27 +15095,27 @@ function useMergedGridControls(args) {
|
|
|
15016
15095
|
},
|
|
15017
15096
|
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_design_system46.DialogContent, { className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl", children: [
|
|
15018
15097
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_design_system46.DialogHeader, { children: [
|
|
15019
|
-
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system46.DialogTitle, { children:
|
|
15098
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system46.DialogTitle, { children: columnDialog?.kind === "settings" ? `Column settings \xB7 ${fieldName(columnDialog.field)}` : columnDialog?.kind === "insert" && columnDialog.anchor ? `Add column ${columnDialog.side === "left" ? "left" : "right"} of ${fieldOf2(columnDialog.anchor) ? fieldName(fieldOf2(columnDialog.anchor)) : columnDialog.anchor}` : ADD_FIELD_OPEN_LABEL }),
|
|
15020
15099
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system46.DialogDescription, { className: "sr-only", children: "Name, type and look" })
|
|
15021
15100
|
] }),
|
|
15022
|
-
|
|
15101
|
+
columnDialog?.kind === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
15023
15102
|
FieldEditor,
|
|
15024
15103
|
{
|
|
15025
15104
|
tableId,
|
|
15026
|
-
field:
|
|
15105
|
+
field: columnDialog.field,
|
|
15027
15106
|
onSaved: () => {
|
|
15028
|
-
notify?.success(`${fieldName(
|
|
15107
|
+
notify?.success(`${fieldName(columnDialog.field)} is saved.`);
|
|
15029
15108
|
close();
|
|
15030
15109
|
},
|
|
15031
15110
|
onRemoved: () => {
|
|
15032
|
-
if (args.onColumnRetired) args.onColumnRetired(
|
|
15033
|
-
else notify?.success(`${fieldName(
|
|
15111
|
+
if (args.onColumnRetired) args.onColumnRetired(columnDialog.field);
|
|
15112
|
+
else notify?.success(`${fieldName(columnDialog.field)} is gone from the table. It can be brought back from Archived.`);
|
|
15034
15113
|
close();
|
|
15035
15114
|
},
|
|
15036
15115
|
onCancel: close
|
|
15037
15116
|
},
|
|
15038
|
-
|
|
15039
|
-
) :
|
|
15117
|
+
`${columnDialog.field.id}-${insertEpoch.current}`
|
|
15118
|
+
) : columnDialog?.kind === "insert" ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
15040
15119
|
FieldEditor,
|
|
15041
15120
|
{
|
|
15042
15121
|
tableId,
|
|
@@ -15045,10 +15124,11 @@ function useMergedGridControls(args) {
|
|
|
15045
15124
|
close();
|
|
15046
15125
|
},
|
|
15047
15126
|
onSaved: () => {
|
|
15048
|
-
pendingInsert.current = { before: new Set(fieldKeys), anchor:
|
|
15127
|
+
pendingInsert.current = { before: new Set(fieldKeys), anchor: columnDialog.anchor, side: columnDialog.side };
|
|
15049
15128
|
close();
|
|
15050
15129
|
}
|
|
15051
|
-
}
|
|
15130
|
+
},
|
|
15131
|
+
`insert-${insertEpoch.current}`
|
|
15052
15132
|
) : null
|
|
15053
15133
|
] })
|
|
15054
15134
|
}
|
|
@@ -20551,7 +20631,7 @@ function UndoRedoPair({ face, onUndo, onRedo }) {
|
|
|
20551
20631
|
)
|
|
20552
20632
|
] });
|
|
20553
20633
|
}
|
|
20554
|
-
function UndoNotice({ undo }) {
|
|
20634
|
+
function UndoNotice({ undo, placement = "frame" }) {
|
|
20555
20635
|
const notice = undo.notice;
|
|
20556
20636
|
const dismiss = undo.dismiss;
|
|
20557
20637
|
(0, import_react105.useEffect)(() => {
|
|
@@ -20565,7 +20645,8 @@ function UndoNotice({ undo }) {
|
|
|
20565
20645
|
{
|
|
20566
20646
|
role: "status",
|
|
20567
20647
|
"data-records-undo-notice": notice.refusal ? "refused" : "done",
|
|
20568
|
-
|
|
20648
|
+
"data-records-undo-placement": placement,
|
|
20649
|
+
className: `pointer-events-auto ${placement === "viewport" ? "fixed bottom-4 z-50" : "absolute bottom-3 z-30"} left-1/2 flex max-w-[min(36rem,calc(100%-2rem))] -translate-x-1/2 items-center gap-2 rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-lg`,
|
|
20569
20650
|
children: [
|
|
20570
20651
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: notice.says }),
|
|
20571
20652
|
notice.canUndo && undo.canUndo ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_design_system57.Button, { size: "sm", variant: "outline", className: "ml-auto h-6", "data-records-undo-now": "", onClick: () => void undo.undo(), children: "Undo" }) : null,
|
|
@@ -21910,6 +21991,11 @@ function GridBody({
|
|
|
21910
21991
|
page: query.page
|
|
21911
21992
|
});
|
|
21912
21993
|
}, [reportQuery, query.sort, query.columnFilters, query.search, query.page, openingKey]);
|
|
21994
|
+
const liveKeys = (0, import_react113.useMemo)(() => fields.data ? new Set(fields.data.map((f) => f.key)) : null, [fields.data]);
|
|
21995
|
+
(0, import_react113.useEffect)(() => {
|
|
21996
|
+
if (!liveKeys) return;
|
|
21997
|
+
setQuery((held) => withoutGoneColumns(held, liveKeys, openingSort));
|
|
21998
|
+
}, [liveKeys]);
|
|
21913
21999
|
const resetEpoch = address?.resetEpoch ?? 0;
|
|
21914
22000
|
const resetSeen = (0, import_react113.useRef)(resetEpoch);
|
|
21915
22001
|
(0, import_react113.useEffect)(() => {
|
|
@@ -21963,7 +22049,9 @@ function GridBody({
|
|
|
21963
22049
|
page: classicInCard ? 0 : page,
|
|
21964
22050
|
...readFilter ? { filter: readFilter } : {}
|
|
21965
22051
|
});
|
|
21966
|
-
const
|
|
22052
|
+
const pageAskedFor = (0, import_react113.useRef)(null);
|
|
22053
|
+
if (fields.data && !table.loading) pageAskedFor.current = tableId;
|
|
22054
|
+
const pageAsked = !storePaged || Boolean(fields.data) && pageAskedFor.current === tableId;
|
|
21967
22055
|
const serverRead = (0, import_react114.useRecordPage)(storePaged && pageAsked ? tableId : null, {
|
|
21968
22056
|
pageSize: query.pageSize,
|
|
21969
22057
|
page: Math.max(0, query.page - 1),
|
|
@@ -23415,7 +23503,7 @@ function GridBody({
|
|
|
23415
23503
|
}, [rowsAnswered, rowMemoryKey, rows.length, embedded, tableId]);
|
|
23416
23504
|
if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(RefusalNotice, { error: table.error, className });
|
|
23417
23505
|
if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(RefusalNotice, { error: fields.error, className });
|
|
23418
|
-
const nothingToShowYet = table.loading || fields.loading || !rights.known || records.loading && rows.length === 0 || // The page read has neither answered nor refused: nothing has been said yet, so nothing is empty.
|
|
23506
|
+
const nothingToShowYet = table.loading && !table.data || fields.loading && !fields.data || !rights.known || records.loading && rows.length === 0 || // The page read has neither answered nor refused: nothing has been said yet, so nothing is empty.
|
|
23419
23507
|
!records.data && !records.error || countedButNotReturned || manual && hand.loading && rows.length === 0;
|
|
23420
23508
|
const refreshing = !nothingToShowYet && (records.loading || manual && hand.loading);
|
|
23421
23509
|
const noColumnsYet = !nothingToShowYet && (fields.data ?? []).length === 0;
|
|
@@ -23870,6 +23958,15 @@ function withHeaderMenus(columns, menuFor, filterFor) {
|
|
|
23870
23958
|
return filter ? { ...withMenu, ...filter } : withMenu;
|
|
23871
23959
|
});
|
|
23872
23960
|
}
|
|
23961
|
+
function withoutGoneColumns(query, liveKeys, openingSort) {
|
|
23962
|
+
const sortGone = Boolean(query.sort && !liveKeys.has(query.sort.id));
|
|
23963
|
+
const goneFilters = Object.keys(query.columnFilters ?? {}).filter((key) => !liveKeys.has(key));
|
|
23964
|
+
if (!sortGone && goneFilters.length === 0) return query;
|
|
23965
|
+
const columnFilters = { ...query.columnFilters };
|
|
23966
|
+
for (const key of goneFilters) delete columnFilters[key];
|
|
23967
|
+
const fallback = openingSort && liveKeys.has(openingSort.id) ? openingSort : null;
|
|
23968
|
+
return { ...query, sort: sortGone ? fallback : query.sort, columnFilters, page: 1 };
|
|
23969
|
+
}
|
|
23873
23970
|
|
|
23874
23971
|
// src/RecordsTableCard.tsx
|
|
23875
23972
|
var import_data_table13 = require("@ai-matrx/design-system/data-table");
|
|
@@ -29027,7 +29124,7 @@ function RecordFieldsInPlace({
|
|
|
29027
29124
|
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
29028
29125
|
"dd",
|
|
29029
29126
|
{
|
|
29030
|
-
className: "min-w-0 rounded hover:bg-muted/50 [&_[data-matrx-cell-editor]_input:not([type=checkbox]):not([type=radio])]:!h-7",
|
|
29127
|
+
className: "min-w-0 rounded hover:bg-muted/50 [&_[data-matrx-cell-editor]_input:not([type=checkbox]):not([type=radio])]:!h-7 [&_[data-pick-anchor]]:!w-fit",
|
|
29031
29128
|
"data-records-in-place-field": field2.key,
|
|
29032
29129
|
children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
29033
29130
|
GridCell,
|
|
@@ -29045,7 +29142,7 @@ function RecordFieldsInPlace({
|
|
|
29045
29142
|
)
|
|
29046
29143
|
] }, field2.id);
|
|
29047
29144
|
}) }),
|
|
29048
|
-
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(UndoNotice, { undo })
|
|
29145
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(UndoNotice, { undo, placement: "viewport" })
|
|
29049
29146
|
]
|
|
29050
29147
|
}
|
|
29051
29148
|
);
|
|
@@ -29271,6 +29368,7 @@ function Peek({ tableId, recordId, onClose, className, onPage = false }) {
|
|
|
29271
29368
|
if (record.error) return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(RefusalNotice, { error: record.error, className });
|
|
29272
29369
|
if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(RefusalNotice, { error: fields.error, className });
|
|
29273
29370
|
const document2 = record.data?.document;
|
|
29371
|
+
const computedShown = computedLinesWorthShowing(record.data?.computed, document2);
|
|
29274
29372
|
const title = document2 ? recordNameIn(table.data, document2) : "";
|
|
29275
29373
|
const bodyKey = onPage ? bodyFieldOf(fields.data ?? [])?.key : void 0;
|
|
29276
29374
|
const shownFields = (fields.data ?? []).filter((field2) => !onPage || !drawnBelowOnPage(field2, bodyKey));
|
|
@@ -29370,15 +29468,20 @@ function Peek({ tableId, recordId, onClose, className, onPage = false }) {
|
|
|
29370
29468
|
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(import_design_system85.Separator, {}),
|
|
29371
29469
|
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("p", { className: "text-muted-foreground", children: "Nothing here can say which columns the system worked out for itself: that part of the record is not readable from your seat. Everything above is the record as it stands." })
|
|
29372
29470
|
] }) : null,
|
|
29373
|
-
|
|
29471
|
+
computedShown.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
|
|
29374
29472
|
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(import_design_system85.Separator, {}),
|
|
29375
29473
|
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
29376
29474
|
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "font-medium", children: "Worked out by the system" }),
|
|
29377
|
-
|
|
29475
|
+
computedShown.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("p", { className: "text-muted-foreground", children: computedInPlainWords(row, (fields.data ?? []).find((f) => f.key === row.field_key)) }, i))
|
|
29378
29476
|
] })
|
|
29379
29477
|
] }) : null
|
|
29380
29478
|
] });
|
|
29381
29479
|
}
|
|
29480
|
+
function computedLinesWorthShowing(rows, document2) {
|
|
29481
|
+
return (rows ?? []).filter(
|
|
29482
|
+
(row) => !((row.value === null || row.value === void 0 || row.value === "") && workedOutErrorFor(document2, row.field_key))
|
|
29483
|
+
);
|
|
29484
|
+
}
|
|
29382
29485
|
function computedInPlainWords(row, field2) {
|
|
29383
29486
|
const name = field2 ? fieldName(field2) : (0, import_text_case12.humanizeIdentifier)(row.field_key);
|
|
29384
29487
|
const shown4 = row.value === null || row.value === void 0 || row.value === "" ? "nothing" : field2 ? scalarText(field2, row.value) : String(row.value);
|
|
@@ -36474,7 +36577,8 @@ function HistoryPanel({ tableId, recordId, onAskAboutField, className }) {
|
|
|
36474
36577
|
ref: listRef,
|
|
36475
36578
|
role: "listbox",
|
|
36476
36579
|
"aria-label": "Versions of this record, newest first",
|
|
36477
|
-
|
|
36580
|
+
"data-records-history-list": "",
|
|
36581
|
+
className: "flex max-h-[9.25rem] min-h-0 flex-col divide-y overflow-y-auto rounded border",
|
|
36478
36582
|
onKeyDown: (event) => {
|
|
36479
36583
|
const at = entries.findIndex((e) => e.version === open);
|
|
36480
36584
|
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
@@ -47796,7 +47900,7 @@ function TablePage({
|
|
|
47796
47900
|
if (hostFromLink || opened.layout || layoutChosen) return;
|
|
47797
47901
|
setHostLayout(face.hostLayout);
|
|
47798
47902
|
}, [face.kind, face.kind === "designated" ? face.hostLayout : null, layoutChosen]);
|
|
47799
|
-
const faceUnknown = !hostFromLink && !opened.layout && (views === void 0 || Array.isArray(views) && views.length > 0 &&
|
|
47903
|
+
const faceUnknown = !hostFromLink && !opened.layout && (views === void 0 || looks === void 0 || Array.isArray(views) && views.length > 0 && view === null);
|
|
47800
47904
|
const shownLayout = layoutFromLink ?? shown4?.layout ?? "grid";
|
|
47801
47905
|
const shownFilter = filter ?? (shown4?.where ? shown4.where : null) ?? (shown4?.filters && Object.keys(shown4.filters).length > 0 ? shown4.filters : null);
|
|
47802
47906
|
const press = (pressed) => {
|