@ai-matrx/records-ui 0.115.78 → 0.115.80
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 +29 -1
- package/dist/index.cjs +220 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +578 -428
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +129 -49
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +162 -82
- package/dist/pickers.js.map +1 -1
- package/package.json +5 -5
package/dist/pickers.js
CHANGED
|
@@ -890,7 +890,7 @@ import {
|
|
|
890
890
|
SelectItem as SelectItem7,
|
|
891
891
|
SelectTrigger as SelectTrigger7,
|
|
892
892
|
SelectValue as SelectValue7,
|
|
893
|
-
cn as
|
|
893
|
+
cn as cn25
|
|
894
894
|
} from "@ai-matrx/design-system";
|
|
895
895
|
|
|
896
896
|
// src/dates.ts
|
|
@@ -2046,7 +2046,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
|
|
|
2046
2046
|
|
|
2047
2047
|
// src/buttonCell.tsx
|
|
2048
2048
|
import { useState as useState24 } from "react";
|
|
2049
|
-
import { Button as Button16, Dialog as Dialog2, DialogContent as DialogContent2, DialogDescription, DialogHeader as DialogHeader2, DialogTitle as DialogTitle2, Popover as Popover4, PopoverContent as PopoverContent4, PopoverTrigger as PopoverTrigger4, cn as
|
|
2049
|
+
import { Button as Button16, Dialog as Dialog2, DialogContent as DialogContent2, DialogDescription, DialogHeader as DialogHeader2, DialogTitle as DialogTitle2, Popover as Popover4, PopoverContent as PopoverContent4, PopoverTrigger as PopoverTrigger4, cn as cn22 } from "@ai-matrx/design-system";
|
|
2050
2050
|
import { CHOICE_CHIP_CLASS as CHOICE_CHIP_CLASS2, NEUTRAL_CHIP_CLASS as NEUTRAL_CHIP_CLASS2, isStyleColor as isStyleColor2 } from "@ai-matrx/design-system/data-table";
|
|
2051
2051
|
import { buttonNeeds as buttonNeeds2, buttonOf as buttonOf2 } from "@ai-matrx/records";
|
|
2052
2052
|
import { useOptionalRecordsClient as useOptionalRecordsClient8 } from "@ai-matrx/records/react";
|
|
@@ -2114,7 +2114,7 @@ import {
|
|
|
2114
2114
|
SelectTrigger as SelectTrigger6,
|
|
2115
2115
|
SelectValue as SelectValue6,
|
|
2116
2116
|
Separator,
|
|
2117
|
-
cn as
|
|
2117
|
+
cn as cn21
|
|
2118
2118
|
} from "@ai-matrx/design-system";
|
|
2119
2119
|
|
|
2120
2120
|
// src/ReferenceBuilder.tsx
|
|
@@ -2841,7 +2841,7 @@ import { tableShapeChanged, useRecordsClient as useRecordsClient6 } from "@ai-ma
|
|
|
2841
2841
|
// src/values.tsx
|
|
2842
2842
|
import { SWATCH_CLASS as SWATCH_CLASS2, formatColumnValue } from "@ai-matrx/design-system/data-table";
|
|
2843
2843
|
import { formatFieldValue as formatFieldValue3 } from "@ai-matrx/design-system/field-formats";
|
|
2844
|
-
import { Badge as Badge5, cn as
|
|
2844
|
+
import { Badge as Badge5, cn as cn19 } from "@ai-matrx/design-system";
|
|
2845
2845
|
|
|
2846
2846
|
// src/embeddedLook.tsx
|
|
2847
2847
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
@@ -3940,7 +3940,7 @@ function linkChipText(raw) {
|
|
|
3940
3940
|
// src/gridAttachments.tsx
|
|
3941
3941
|
import { useEffect as useEffect11, useRef as useRef10, useState as useState17 } from "react";
|
|
3942
3942
|
import { useOptionalRecordsClient as useOptionalRecordsClient5 } from "@ai-matrx/records/react";
|
|
3943
|
-
import { Badge as Badge3, Button as Button10, Dialog, DialogContent, DialogHeader, DialogTitle } from "@ai-matrx/design-system";
|
|
3943
|
+
import { Badge as Badge3, Button as Button10, cn as cn17, Dialog, DialogContent, DialogHeader, DialogTitle } from "@ai-matrx/design-system";
|
|
3944
3944
|
|
|
3945
3945
|
// src/FilePicker.tsx
|
|
3946
3946
|
import { useCallback as useCallback4, useId, useRef as useRef9, useState as useState16 } from "react";
|
|
@@ -4096,46 +4096,63 @@ function AttachmentChip({ id, onRemove, onPreview }) {
|
|
|
4096
4096
|
const words = read?.name ?? (read ? FILE_CHIP_UNREAD : "\u2026");
|
|
4097
4097
|
const href = read?.fileId ? host.hrefForFile?.({ fileId: read.fileId }) : void 0;
|
|
4098
4098
|
const title = onPreview ? `Preview ${words}` : href ? `Open ${words}` : read?.why ?? FILE_CHIP_NO_PAGE;
|
|
4099
|
-
return /* @__PURE__ */ jsxs19(
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4099
|
+
return /* @__PURE__ */ jsxs19(
|
|
4100
|
+
Badge3,
|
|
4101
|
+
{
|
|
4102
|
+
variant: "secondary",
|
|
4103
|
+
className: cn17("max-w-[14rem] gap-1 text-[11px]", onPreview && "cursor-pointer"),
|
|
4104
|
+
"data-records-file-chip": id,
|
|
4105
|
+
title,
|
|
4106
|
+
...onPreview ? {
|
|
4106
4107
|
onClick: (event) => {
|
|
4107
4108
|
event.stopPropagation();
|
|
4108
4109
|
onPreview();
|
|
4109
4110
|
},
|
|
4110
4111
|
onMouseDown: (event) => event.stopPropagation(),
|
|
4111
|
-
onDoubleClick: (event) => event.stopPropagation()
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4112
|
+
onDoubleClick: (event) => event.stopPropagation()
|
|
4113
|
+
} : {},
|
|
4114
|
+
children: [
|
|
4115
|
+
onPreview ? /* @__PURE__ */ jsx21(
|
|
4116
|
+
"button",
|
|
4117
|
+
{
|
|
4118
|
+
type: "button",
|
|
4119
|
+
className: "truncate underline-offset-2 hover:underline",
|
|
4120
|
+
"data-records-file-preview": id,
|
|
4121
|
+
onClick: (event) => {
|
|
4122
|
+
event.stopPropagation();
|
|
4123
|
+
onPreview();
|
|
4124
|
+
},
|
|
4125
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
4126
|
+
onDoubleClick: (event) => event.stopPropagation(),
|
|
4127
|
+
children: words
|
|
4128
|
+
}
|
|
4129
|
+
) : href ? /* @__PURE__ */ jsx21(
|
|
4130
|
+
OutboundLink4,
|
|
4131
|
+
{
|
|
4132
|
+
href,
|
|
4133
|
+
className: "truncate underline-offset-2 hover:underline",
|
|
4134
|
+
"data-records-file-link": read?.fileId ?? "",
|
|
4135
|
+
onClick: (event) => event.stopPropagation(),
|
|
4136
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
4137
|
+
children: words
|
|
4138
|
+
}
|
|
4139
|
+
) : /* @__PURE__ */ jsx21("span", { className: "truncate", children: words }),
|
|
4140
|
+
onRemove ? /* @__PURE__ */ jsx21(
|
|
4141
|
+
"button",
|
|
4142
|
+
{
|
|
4143
|
+
type: "button",
|
|
4144
|
+
"aria-label": `Remove ${words}`,
|
|
4145
|
+
className: "shrink-0 rounded px-0.5 text-muted-foreground hover:text-foreground",
|
|
4146
|
+
onClick: (event) => {
|
|
4147
|
+
event.stopPropagation();
|
|
4148
|
+
onRemove();
|
|
4149
|
+
},
|
|
4150
|
+
children: "\xD7"
|
|
4151
|
+
}
|
|
4152
|
+
) : null
|
|
4153
|
+
]
|
|
4154
|
+
}
|
|
4155
|
+
);
|
|
4139
4156
|
}
|
|
4140
4157
|
function AttachmentChips({ value, onRemove }) {
|
|
4141
4158
|
const host = useRecordsUi();
|
|
@@ -4176,6 +4193,18 @@ function AttachmentViewer({
|
|
|
4176
4193
|
{
|
|
4177
4194
|
className: "sm:max-w-3xl",
|
|
4178
4195
|
"data-records-attachment-viewer": id,
|
|
4196
|
+
tabIndex: -1,
|
|
4197
|
+
onOpenAutoFocus: (event) => {
|
|
4198
|
+
event.preventDefault();
|
|
4199
|
+
event.currentTarget.focus();
|
|
4200
|
+
},
|
|
4201
|
+
onCloseAutoFocus: (event) => {
|
|
4202
|
+
const chip = document.querySelector(`[data-records-file-preview="${ids[index]}"]`);
|
|
4203
|
+
if (chip) {
|
|
4204
|
+
event.preventDefault();
|
|
4205
|
+
chip.focus();
|
|
4206
|
+
}
|
|
4207
|
+
},
|
|
4179
4208
|
onKeyDown: (event) => {
|
|
4180
4209
|
if (event.key === "ArrowLeft") {
|
|
4181
4210
|
event.preventDefault();
|
|
@@ -4284,7 +4313,7 @@ function AttachmentControl({
|
|
|
4284
4313
|
|
|
4285
4314
|
// src/ReferenceChips.tsx
|
|
4286
4315
|
import { entityRefsOf as entityRefsOf2 } from "@ai-matrx/records";
|
|
4287
|
-
import { Badge as Badge4, Skeleton as Skeleton2, cn as
|
|
4316
|
+
import { Badge as Badge4, Skeleton as Skeleton2, cn as cn18 } from "@ai-matrx/design-system";
|
|
4288
4317
|
|
|
4289
4318
|
// src/kindValues.ts
|
|
4290
4319
|
import { tryDecodeDirective } from "@ai-matrx/content-ir/directives";
|
|
@@ -4389,7 +4418,7 @@ function ReferenceChip({ reference, waiting }) {
|
|
|
4389
4418
|
return /* @__PURE__ */ jsxs20(
|
|
4390
4419
|
"span",
|
|
4391
4420
|
{
|
|
4392
|
-
className:
|
|
4421
|
+
className: cn18(
|
|
4393
4422
|
"inline-flex max-w-full min-w-0 items-center gap-1.5 text-sm text-foreground hover:underline [&_a]:text-inherit [&_a]:no-underline [&_a:hover]:underline",
|
|
4394
4423
|
reference.archived && "opacity-70"
|
|
4395
4424
|
),
|
|
@@ -4409,7 +4438,7 @@ function ReferenceChip({ reference, waiting }) {
|
|
|
4409
4438
|
Badge4,
|
|
4410
4439
|
{
|
|
4411
4440
|
variant: "secondary",
|
|
4412
|
-
className:
|
|
4441
|
+
className: cn18(
|
|
4413
4442
|
"max-w-full min-w-0 gap-1 px-1.5 py-0 text-[11px] font-normal",
|
|
4414
4443
|
reference.archived && "opacity-70"
|
|
4415
4444
|
),
|
|
@@ -4437,7 +4466,7 @@ function KindValueCell({
|
|
|
4437
4466
|
return /* @__PURE__ */ jsx22("span", { className: "flex min-w-0 max-w-full items-center", "data-records-kind-value": kv.kind, children: host.renderKind({ value: kv.value, kind: kv.kind, where, title }) });
|
|
4438
4467
|
}
|
|
4439
4468
|
const named = kv.items.map(kindItemWords).filter((w) => w !== null);
|
|
4440
|
-
return /* @__PURE__ */ jsx22("span", { className:
|
|
4469
|
+
return /* @__PURE__ */ jsx22("span", { className: cn18("flex min-w-0 flex-wrap gap-1"), "data-records-kind-value": kv.kind, title: JSON.stringify(kv.value), children: named.length > 0 ? named.map((w, i) => /* @__PURE__ */ jsx22(Badge4, { variant: "secondary", className: "px-1.5 py-0 text-[11px] font-normal", children: w }, `${w}-${i}`)) : /* @__PURE__ */ jsx22(Badge4, { variant: "outline", className: "px-1.5 py-0 text-[11px] font-normal", children: kindLabel(kv.kind) }) });
|
|
4441
4470
|
}
|
|
4442
4471
|
|
|
4443
4472
|
// src/formulaNames.ts
|
|
@@ -4604,11 +4633,11 @@ function renderValue(field, value, document2, labels, stillWaitingFor, look) {
|
|
|
4604
4633
|
Badge5,
|
|
4605
4634
|
{
|
|
4606
4635
|
variant: "outline",
|
|
4607
|
-
className:
|
|
4636
|
+
className: cn19("text-[11px]", chip.className),
|
|
4608
4637
|
"data-records-choice-chip": "",
|
|
4609
4638
|
...chip.tinted ? { "data-records-choice-tint": "" } : {},
|
|
4610
4639
|
children: [
|
|
4611
|
-
look?.choiceDot ? /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", "data-matrx-pill-ink": "", "data-records-choice-dot": "", className:
|
|
4640
|
+
look?.choiceDot ? /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", "data-matrx-pill-ink": "", "data-records-choice-dot": "", className: cn19("mr-1.5 inline-block size-1.5 shrink-0 rounded-full", chip.dot) }) : null,
|
|
4612
4641
|
statusMark(field, item, Array.isArray(value) ? void 0 : document2),
|
|
4613
4642
|
scalarText(field, item, labels, Array.isArray(value) ? void 0 : stillWaitingFor)
|
|
4614
4643
|
]
|
|
@@ -4657,7 +4686,7 @@ function renderValue(field, value, document2, labels, stillWaitingFor, look) {
|
|
|
4657
4686
|
if (typeof value === "boolean") {
|
|
4658
4687
|
return /* @__PURE__ */ jsx23("span", { className: kind === "checkbox" ? "text-sm" : "", title: value ? "Yes" : "No", children: value ? "\u2713" : "\u2014" });
|
|
4659
4688
|
}
|
|
4660
|
-
return /* @__PURE__ */ jsx23("span", { className:
|
|
4689
|
+
return /* @__PURE__ */ jsx23("span", { className: cn19("truncate", kind === "number" || kind === "currency" || kind === "percent" ? "tabular-nums" : ""), children: scalarText(field, value, labels, stillWaitingFor) });
|
|
4661
4690
|
}
|
|
4662
4691
|
function scalarText(field, value, labels, stillWaitingFor) {
|
|
4663
4692
|
if (value === null || value === void 0) return "\u2014";
|
|
@@ -4813,6 +4842,33 @@ var CONDITION_OPS = [
|
|
|
4813
4842
|
{ op: "gte", label: "is at least" },
|
|
4814
4843
|
{ op: "lte", label: "is at most" }
|
|
4815
4844
|
];
|
|
4845
|
+
var LIST_TERMS = [
|
|
4846
|
+
{ op: "contains", label: "contains" },
|
|
4847
|
+
{ op: "not_contains", label: "does not contain" },
|
|
4848
|
+
{ op: "is_empty", label: "is empty" },
|
|
4849
|
+
{ op: "is_not_empty", label: "is not empty" }
|
|
4850
|
+
];
|
|
4851
|
+
var VALUELESS_OPS = /* @__PURE__ */ new Set(["present", "is_empty", "is_not_empty"]);
|
|
4852
|
+
var LINK_SEP = ">";
|
|
4853
|
+
function linkedNode(viaId, innerId, op, value) {
|
|
4854
|
+
return {
|
|
4855
|
+
op: "linked",
|
|
4856
|
+
match: op === "eq" ? "any" : "none",
|
|
4857
|
+
args: [{ field: viaId }, { op: "eq", args: [{ field: innerId }, { const: value }] }]
|
|
4858
|
+
};
|
|
4859
|
+
}
|
|
4860
|
+
function linkedOf(expr) {
|
|
4861
|
+
const node = asNode(expr);
|
|
4862
|
+
if (!node || node["op"] !== "linked") return null;
|
|
4863
|
+
const [rel, cond] = argsOf(node);
|
|
4864
|
+
const innerNode = asNode(cond);
|
|
4865
|
+
const [a, b] = innerNode ? argsOf(innerNode) : [];
|
|
4866
|
+
const match = node["match"] ?? "any";
|
|
4867
|
+
if (!rel || typeof rel["field"] !== "string" || !innerNode || innerNode["op"] !== "eq") return null;
|
|
4868
|
+
if (!a || typeof a["field"] !== "string" || !b || !("const" in b)) return null;
|
|
4869
|
+
if (match !== "any" && match !== "none") return null;
|
|
4870
|
+
return { via: rel["field"], inner: a["field"], op: match === "any" ? "eq" : "ne", value: b["const"] };
|
|
4871
|
+
}
|
|
4816
4872
|
var FilterTermsContext = createContext4(false);
|
|
4817
4873
|
var RELATIVE_DAY_TERMS = [
|
|
4818
4874
|
{ kind: "today", label: "is today" },
|
|
@@ -4925,13 +4981,15 @@ function ChoiceValue({ field, value, onChange }) {
|
|
|
4925
4981
|
}
|
|
4926
4982
|
function conditionIsSimple(expr) {
|
|
4927
4983
|
if (expr === null || expr === void 0) return true;
|
|
4928
|
-
if (relativeDayOf(expr) !== null || meOf(expr) !== null) return true;
|
|
4984
|
+
if (relativeDayOf(expr) !== null || meOf(expr) !== null || linkedOf(expr) !== null) return true;
|
|
4929
4985
|
const node = expr;
|
|
4930
|
-
if (typeof node.op !== "string" || !CONDITION_OPS.some((c) => c.op === node.op))
|
|
4986
|
+
if (typeof node.op !== "string" || !(CONDITION_OPS.some((c) => c.op === node.op) || LIST_TERMS.some((c) => c.op === node.op))) {
|
|
4987
|
+
return false;
|
|
4988
|
+
}
|
|
4931
4989
|
if (!Array.isArray(node.args)) return false;
|
|
4932
4990
|
const first = node.args[0];
|
|
4933
4991
|
if (!first || typeof first.field !== "string") return false;
|
|
4934
|
-
if (node.op
|
|
4992
|
+
if (VALUELESS_OPS.has(node.op)) return node.args.length === 1;
|
|
4935
4993
|
const second = node.args[1];
|
|
4936
4994
|
return node.args.length === 2 && !!second && "const" in second;
|
|
4937
4995
|
}
|
|
@@ -4949,7 +5007,13 @@ function conditionInWords(expr, fields) {
|
|
|
4949
5007
|
lte: "is at most",
|
|
4950
5008
|
and: "and",
|
|
4951
5009
|
or: "or",
|
|
4952
|
-
matches: "matches"
|
|
5010
|
+
matches: "matches",
|
|
5011
|
+
contains: "contains",
|
|
5012
|
+
not_contains: "does not contain",
|
|
5013
|
+
has_any: "has any of",
|
|
5014
|
+
has_all: "has all of",
|
|
5015
|
+
has_none: "has none of",
|
|
5016
|
+
is_exactly: "is exactly"
|
|
4953
5017
|
};
|
|
4954
5018
|
const walk = (node) => {
|
|
4955
5019
|
if (node === null || node === void 0) return "nothing";
|
|
@@ -4970,6 +5034,12 @@ function conditionInWords(expr, fields) {
|
|
|
4970
5034
|
const args = Array.isArray(n["args"]) ? n["args"] : [];
|
|
4971
5035
|
if (op === "not") return `not ${walk(args[0])}`;
|
|
4972
5036
|
if (op === "present") return `${walk(args[0])} has been answered`;
|
|
5037
|
+
if (op === "is_empty") return `${walk(args[0])} is empty`;
|
|
5038
|
+
if (op === "is_not_empty") return `${walk(args[0])} is not empty`;
|
|
5039
|
+
if (op === "linked") {
|
|
5040
|
+
const how = n["match"] === "every" ? "every" : n["match"] === "none" ? "none of" : "any";
|
|
5041
|
+
return `${how} linked record in ${walk(args[0])}: ${walk(args[1])}`;
|
|
5042
|
+
}
|
|
4973
5043
|
const dayRange = relativeDayOf(n);
|
|
4974
5044
|
if (dayRange) {
|
|
4975
5045
|
const term = RELATIVE_DAY_TERMS.find((t) => t.kind === dayRange.kind);
|
|
@@ -5002,12 +5072,14 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5002
5072
|
const filterTerms = useContext4(FilterTermsContext);
|
|
5003
5073
|
const relative = relativeDayOf(expr);
|
|
5004
5074
|
const reader = meOf(expr);
|
|
5005
|
-
const
|
|
5006
|
-
const
|
|
5007
|
-
const
|
|
5075
|
+
const linked = linkedOf(expr);
|
|
5076
|
+
const op = relative ? `rel:${relative.kind}` : reader ? reader.which : linked ? linked.op : node?.op ?? "";
|
|
5077
|
+
const onField = linked ? `${linked.via}${LINK_SEP}${linked.inner}` : node?.args?.[0]?.field ?? "";
|
|
5078
|
+
const value = relative || reader ? "" : linked ? linked.value : node?.args?.[1]?.const ?? "";
|
|
5008
5079
|
const chosen = fields.find((f) => f.id === onField);
|
|
5009
5080
|
const chosenKind = chosen?.field ? String(editorKindFor(chosen.field)) : "";
|
|
5010
|
-
const extraTerms = !filterTerms ? [] : chosenKind === "datetime" ? RELATIVE_DAY_TERMS.map((t) => ({ op: `rel:${t.kind}`, label: t.label })) : chosenKind === "member" ? [{ op: "me", label: "is me" }, { op: "not_me", label: "is not me" }] : [];
|
|
5081
|
+
const extraTerms = !filterTerms || chosen?.via ? [] : chosenKind === "datetime" ? RELATIVE_DAY_TERMS.map((t) => ({ op: `rel:${t.kind}`, label: t.label })) : chosenKind === "member" ? [{ op: "me", label: "is me" }, { op: "not_me", label: "is not me" }] : chosenKind === "multi_select" ? LIST_TERMS : [];
|
|
5082
|
+
const baseTerms = chosen?.via ? CONDITION_OPS.filter((c) => c.op === "eq" || c.op === "ne") : CONDITION_OPS;
|
|
5011
5083
|
const relativeTerm = relative ? RELATIVE_DAY_TERMS.find((t) => t.kind === relative.kind) : void 0;
|
|
5012
5084
|
function write(next) {
|
|
5013
5085
|
const picked = next.op;
|
|
@@ -5020,8 +5092,11 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5020
5092
|
onChange(relativeDayNode(fieldNow, relative.kind, next.days));
|
|
5021
5093
|
return;
|
|
5022
5094
|
}
|
|
5023
|
-
if (next.field !== void 0 && (relative || reader)) {
|
|
5024
|
-
|
|
5095
|
+
if (next.field !== void 0 && (relative || reader || linked)) {
|
|
5096
|
+
const target2 = fields.find((f) => f.id === next.field);
|
|
5097
|
+
onChange(
|
|
5098
|
+
!next.field ? null : target2?.via ? linkedNode(target2.via.id, target2.via.fieldId, "eq", "") : { op: CONDITION_OPS[0].op, args: [{ field: next.field }, { const: "" }] }
|
|
5099
|
+
);
|
|
5025
5100
|
return;
|
|
5026
5101
|
}
|
|
5027
5102
|
const chosenOp = next.op ?? (op || (next.field ? CONDITION_OPS[0].op : ""));
|
|
@@ -5031,8 +5106,13 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5031
5106
|
onChange(null);
|
|
5032
5107
|
return;
|
|
5033
5108
|
}
|
|
5109
|
+
const target = fields.find((f) => f.id === chosenField);
|
|
5110
|
+
if (target?.via) {
|
|
5111
|
+
onChange(linkedNode(target.via.id, target.via.fieldId, chosenOp === "ne" ? "ne" : "eq", chosenValue));
|
|
5112
|
+
return;
|
|
5113
|
+
}
|
|
5034
5114
|
onChange(
|
|
5035
|
-
chosenOp
|
|
5115
|
+
VALUELESS_OPS.has(chosenOp) ? { op: chosenOp, args: [{ field: chosenField }] } : { op: chosenOp, args: [{ field: chosenField }, { const: chosenValue }] }
|
|
5036
5116
|
);
|
|
5037
5117
|
}
|
|
5038
5118
|
return /* @__PURE__ */ jsxs23("div", { className: className ?? "flex flex-wrap items-center gap-1 text-xs", children: [
|
|
@@ -5065,7 +5145,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5065
5145
|
className: "h-8 w-auto min-w-[6rem] text-xs",
|
|
5066
5146
|
value: op,
|
|
5067
5147
|
onChange: (next) => write({ op: next }),
|
|
5068
|
-
options: [...
|
|
5148
|
+
options: [...baseTerms, ...extraTerms].map((c) => ({ value: c.op, label: c.label })),
|
|
5069
5149
|
attrs: { "data-condition": "comparison" }
|
|
5070
5150
|
}
|
|
5071
5151
|
),
|
|
@@ -5079,7 +5159,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5079
5159
|
value: String(relative.days ?? 7),
|
|
5080
5160
|
onChange: (e) => write({ days: Math.max(0, Math.floor(Number(e.target.value) || 0)) })
|
|
5081
5161
|
}
|
|
5082
|
-
) : null : reader || op
|
|
5162
|
+
) : null : reader || VALUELESS_OPS.has(op) ? null : pointsAtARecord(chosen) ? (
|
|
5083
5163
|
// A RECORD IS PICKED BY ITS WORDS, NEVER TYPED AS AN ID. The same picker the
|
|
5084
5164
|
// cell uses, on the same `relation_words_many` the cell reads, so a filter and
|
|
5085
5165
|
// the column it filters can never disagree about what a record is called. It
|
|
@@ -5097,7 +5177,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5097
5177
|
allowCreate: false
|
|
5098
5178
|
}
|
|
5099
5179
|
)
|
|
5100
|
-
) : isChoiceColumn(chosen) && (op === "eq" || op === "ne") ? /* @__PURE__ */ jsx25(ChoiceValue, { field: chosen.field, value: String(value ?? ""), onChange: (word) => write({ value: word }) }) : /* @__PURE__ */ jsx25(
|
|
5180
|
+
) : isChoiceColumn(chosen) && (op === "eq" || op === "ne" || op === "contains" || op === "not_contains") ? /* @__PURE__ */ jsx25(ChoiceValue, { field: chosen.field, value: String(value ?? ""), onChange: (word) => write({ value: word }) }) : /* @__PURE__ */ jsx25(
|
|
5101
5181
|
BasicInput7,
|
|
5102
5182
|
{
|
|
5103
5183
|
className: "h-8 w-28 text-xs",
|
|
@@ -6026,7 +6106,7 @@ import { useOptionalRecordsClient as useOptionalRecordsClient7 } from "@ai-matrx
|
|
|
6026
6106
|
|
|
6027
6107
|
// src/AccentSwatches.tsx
|
|
6028
6108
|
import { PORTAL_ACCENTS } from "@ai-matrx/records";
|
|
6029
|
-
import { cn as
|
|
6109
|
+
import { cn as cn20 } from "@ai-matrx/design-system";
|
|
6030
6110
|
import { STYLE_COLOR_LABELS as STYLE_COLOR_LABELS2, SWATCH_CLASS as SWATCH_CLASS3 } from "@ai-matrx/design-system/data-table";
|
|
6031
6111
|
import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
6032
6112
|
function AccentSwatches({ value, onChange, options = PORTAL_ACCENTS, noneLabel = "App colour" }) {
|
|
@@ -6038,7 +6118,7 @@ function AccentSwatches({ value, onChange, options = PORTAL_ACCENTS, noneLabel =
|
|
|
6038
6118
|
role: "radio",
|
|
6039
6119
|
"aria-checked": value === "",
|
|
6040
6120
|
onClick: () => onChange(""),
|
|
6041
|
-
className:
|
|
6121
|
+
className: cn20(
|
|
6042
6122
|
"h-7 rounded border px-2 text-xs",
|
|
6043
6123
|
value === "" ? "border-foreground" : "border-border text-muted-foreground"
|
|
6044
6124
|
),
|
|
@@ -6054,7 +6134,7 @@ function AccentSwatches({ value, onChange, options = PORTAL_ACCENTS, noneLabel =
|
|
|
6054
6134
|
"aria-label": STYLE_COLOR_LABELS2[c],
|
|
6055
6135
|
title: STYLE_COLOR_LABELS2[c],
|
|
6056
6136
|
onClick: () => onChange(c),
|
|
6057
|
-
className:
|
|
6137
|
+
className: cn20("h-7 w-7 rounded-full border-2", SWATCH_CLASS3[c], value === c ? "border-foreground" : "border-transparent")
|
|
6058
6138
|
},
|
|
6059
6139
|
c
|
|
6060
6140
|
))
|
|
@@ -6527,7 +6607,7 @@ function FieldEditor(props) {
|
|
|
6527
6607
|
const offersMany = multiApplies(type) && !isTitle;
|
|
6528
6608
|
if (!mayShape) {
|
|
6529
6609
|
if (onEntity && entityRights.loading) return null;
|
|
6530
|
-
return /* @__PURE__ */ jsx32("p", { className:
|
|
6610
|
+
return /* @__PURE__ */ jsx32("p", { className: cn21("text-xs text-muted-foreground", className), children: props.tableLabel && storeLabel && whyNot ? whyNot.split(storeLabel).join(props.tableLabel) : whyNot });
|
|
6531
6611
|
}
|
|
6532
6612
|
const options = newChoices.map((r) => r.words.trim()).filter((word) => word !== "");
|
|
6533
6613
|
const shownStatusRows = type !== "status" ? [] : statusGroupRows(field, editing ? choiceList ?? [] : newChoices, statusKeys, statusGroups);
|
|
@@ -6727,7 +6807,7 @@ function FieldEditor(props) {
|
|
|
6727
6807
|
if (gone) (onRemoved ?? onSaved)?.();
|
|
6728
6808
|
else setAskingToRemove(false);
|
|
6729
6809
|
};
|
|
6730
|
-
return /* @__PURE__ */ jsxs30("div", { className:
|
|
6810
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn21("flex min-w-0 flex-col gap-3 text-xs", className), "data-records-field-editor": "", children: [
|
|
6731
6811
|
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
|
|
6732
6812
|
/* @__PURE__ */ jsx32("span", { className: "font-medium", children: field ? `Field \xB7 ${fieldName(field)}` : "New field" }),
|
|
6733
6813
|
/* @__PURE__ */ jsx32("span", { className: "ml-auto text-muted-foreground", children: tableLabel })
|
|
@@ -7184,8 +7264,8 @@ function FieldEditor(props) {
|
|
|
7184
7264
|
the dialog card 0.2278 and closing it 0.1303. The consequence is the tooltip of
|
|
7185
7265
|
"Remove it" (interface-text: the slot holds a label, never a paragraph). */
|
|
7186
7266
|
/* @__PURE__ */ jsxs30("div", { className: "ml-auto grid shrink-0 items-center", "data-field-editor-remove": askingToRemove ? "asking" : "idle", children: [
|
|
7187
|
-
/* @__PURE__ */ jsx32("div", { className:
|
|
7188
|
-
/* @__PURE__ */ jsxs30("div", { className:
|
|
7267
|
+
/* @__PURE__ */ jsx32("div", { className: cn21("col-start-1 row-start-1 flex items-center justify-end gap-2", askingToRemove && "invisible"), "aria-hidden": askingToRemove || void 0, children: /* @__PURE__ */ jsx32(Button15, { size: "sm", variant: "outline", tabIndex: askingToRemove ? -1 : void 0, onClick: () => setAskingToRemove(true), children: "Remove this field" }) }),
|
|
7268
|
+
/* @__PURE__ */ jsxs30("div", { className: cn21("col-start-1 row-start-1 flex items-center justify-end gap-2", !askingToRemove && "invisible"), "aria-hidden": !askingToRemove || void 0, children: [
|
|
7189
7269
|
/* @__PURE__ */ jsx32("span", { className: "whitespace-nowrap text-destructive", "data-field-editor-remove-ask": "", children: "Archive this field?" }),
|
|
7190
7270
|
/* @__PURE__ */ jsx32(
|
|
7191
7271
|
Button15,
|
|
@@ -7624,7 +7704,7 @@ function ButtonValue({ field, recordId, inCell }) {
|
|
|
7624
7704
|
"data-records-button-unset": needs ? "" : void 0,
|
|
7625
7705
|
"aria-busy": busy || void 0,
|
|
7626
7706
|
disabled: busy,
|
|
7627
|
-
className:
|
|
7707
|
+
className: cn22("max-w-full gap-1 border px-2 font-medium", inCell ? "h-5" : "h-6", color, needs && "border-dashed opacity-80"),
|
|
7628
7708
|
onPointerDown: stop,
|
|
7629
7709
|
onDoubleClick: stop,
|
|
7630
7710
|
onClick: (event) => {
|
|
@@ -7678,7 +7758,7 @@ function ButtonValue({ field, recordId, inCell }) {
|
|
|
7678
7758
|
import { useCallback as useCallback6, useEffect as useEffect18, useMemo as useMemo11, useRef as useRef13, useState as useState25 } from "react";
|
|
7679
7759
|
import { rankTypedMatches as rankTypedMatches3 } from "@ai-matrx/records";
|
|
7680
7760
|
import { useOptionalRecordsClient as useOptionalRecordsClient9 } from "@ai-matrx/records/react";
|
|
7681
|
-
import { cn as
|
|
7761
|
+
import { cn as cn23 } from "@ai-matrx/design-system";
|
|
7682
7762
|
import { Fragment as Fragment11, jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7683
7763
|
function personFromRow(row) {
|
|
7684
7764
|
const data = row.document ?? {};
|
|
@@ -7760,10 +7840,10 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
|
|
|
7760
7840
|
}, [client, personTable, picked.length, people.length]);
|
|
7761
7841
|
const listed = rankTypedMatches3(members ?? [], search, memberName);
|
|
7762
7842
|
if (!membersPort || !client) {
|
|
7763
|
-
return /* @__PURE__ */ jsx34("p", { className:
|
|
7843
|
+
return /* @__PURE__ */ jsx34("p", { className: cn23("text-xs text-muted-foreground", className), children: NO_MEMBERS_REASON });
|
|
7764
7844
|
}
|
|
7765
7845
|
if (!personTable) {
|
|
7766
|
-
return /* @__PURE__ */ jsxs32("p", { className:
|
|
7846
|
+
return /* @__PURE__ */ jsxs32("p", { className: cn23("text-xs text-muted-foreground", className), children: [
|
|
7767
7847
|
fieldName(field),
|
|
7768
7848
|
" is a person field, but it does not say which Table the people are records of yet, so there is nothing to pick from. A table admin sets its target in the field editor."
|
|
7769
7849
|
] });
|
|
@@ -7814,7 +7894,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
|
|
|
7814
7894
|
);
|
|
7815
7895
|
const anchored = autoOpen === true;
|
|
7816
7896
|
const cellChips = picked.map((recordId) => /* @__PURE__ */ jsx34(PersonChip, { name: nameOfRecord(recordId), ...disabled || anchored ? {} : { onRemove: () => drop(recordId) } }, recordId));
|
|
7817
|
-
return /* @__PURE__ */ jsxs32("div", { className:
|
|
7897
|
+
return /* @__PURE__ */ jsxs32("div", { className: cn23("flex flex-wrap items-center gap-1", className), children: [
|
|
7818
7898
|
anchored && !disabled ? null : cellChips,
|
|
7819
7899
|
disabled ? null : (
|
|
7820
7900
|
// THE ONE "PICK OR ADD" BUILDER (lane CELL-EDITORS, 2026-10-06): the person list used to carry
|
|
@@ -8022,7 +8102,7 @@ function formatControl(args) {
|
|
|
8022
8102
|
|
|
8023
8103
|
// src/typedDateHelper.tsx
|
|
8024
8104
|
import { useState as useState28 } from "react";
|
|
8025
|
-
import { Popover as Popover5, PopoverContent as PopoverContent5, PopoverTrigger as PopoverTrigger5, cn as
|
|
8105
|
+
import { Popover as Popover5, PopoverContent as PopoverContent5, PopoverTrigger as PopoverTrigger5, cn as cn24 } from "@ai-matrx/design-system";
|
|
8026
8106
|
import { readTypedDate, readTypedTime, typedDateText, typedTimeText } from "@ai-matrx/records";
|
|
8027
8107
|
import { jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
8028
8108
|
var WEEK = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -8147,7 +8227,7 @@ function TypedDateHelper({
|
|
|
8147
8227
|
type: "button",
|
|
8148
8228
|
...keepFocus,
|
|
8149
8229
|
"data-records-date-helper-day": key,
|
|
8150
|
-
className:
|
|
8230
|
+
className: cn24(
|
|
8151
8231
|
"h-6 w-6 rounded tabular-nums hover:bg-muted",
|
|
8152
8232
|
key === held.day ? "bg-primary text-primary-foreground hover:bg-primary" : "",
|
|
8153
8233
|
key === todayKey && key !== held.day ? "ring-1 ring-ring" : ""
|
|
@@ -8166,7 +8246,7 @@ function TypedDateHelper({
|
|
|
8166
8246
|
type: "button",
|
|
8167
8247
|
...keepFocus,
|
|
8168
8248
|
"data-records-date-helper-time": `${pad(t.h)}:${pad(t.m)}`,
|
|
8169
|
-
className:
|
|
8249
|
+
className: cn24(
|
|
8170
8250
|
"whitespace-nowrap rounded px-2 py-0.5 text-left tabular-nums hover:bg-muted",
|
|
8171
8251
|
held.time && held.time.h === t.h && held.time.m === t.m ? "bg-primary text-primary-foreground" : ""
|
|
8172
8252
|
),
|
|
@@ -8955,7 +9035,7 @@ function OpenChoicePicker({
|
|
|
8955
9035
|
const pickedOptions = current.map((v) => options.find((o) => isTheChosen(o, v)));
|
|
8956
9036
|
const cellChips = pickedWords.map((word, i) => {
|
|
8957
9037
|
const chip = chipOf(pickedOptions[i], word);
|
|
8958
|
-
return /* @__PURE__ */ jsx38(Badge6, { variant: "outline", className:
|
|
9038
|
+
return /* @__PURE__ */ jsx38(Badge6, { variant: "outline", className: cn25("text-[11px]", chip.className), "data-records-choice-chip": "", children: word }, word);
|
|
8959
9039
|
});
|
|
8960
9040
|
const headChips = pickedWords.map((word, i) => {
|
|
8961
9041
|
const option = pickedOptions[i];
|
|
@@ -9028,7 +9108,7 @@ function RecordChip({
|
|
|
9028
9108
|
// name. So it caps at its container and ends in an ellipsis with the whole name in
|
|
9029
9109
|
// its tooltip, rather than being cut mid-word by whatever box it landed in
|
|
9030
9110
|
// (lane FIX-14, 2026-09-22).
|
|
9031
|
-
/* @__PURE__ */ jsxs36(Badge6, { variant: "secondary", className:
|
|
9111
|
+
/* @__PURE__ */ jsxs36(Badge6, { variant: "secondary", className: cn25("max-w-full gap-1 text-[11px]", className), title, children: [
|
|
9032
9112
|
/* @__PURE__ */ jsx38("span", { className: "min-w-0 truncate", children: title }),
|
|
9033
9113
|
onRemove ? /* @__PURE__ */ jsx38("button", { type: "button", onClick: onRemove, "aria-label": `Remove ${title}`, className: "shrink-0 opacity-60 hover:opacity-100", children: "\xD7" }) : null
|
|
9034
9114
|
] })
|
|
@@ -9083,7 +9163,7 @@ function ChoiceAnswer({
|
|
|
9083
9163
|
tabIndex: field.multi || choice.key === tabStop ? 0 : -1,
|
|
9084
9164
|
onClick: () => press(choice),
|
|
9085
9165
|
"data-records-choice-answer": choice.key,
|
|
9086
|
-
className:
|
|
9166
|
+
className: cn25(
|
|
9087
9167
|
"flex min-h-11 w-full items-center gap-3 rounded-md border px-3 py-2 text-left text-base font-medium text-foreground transition-colors sm:min-h-10 sm:text-sm",
|
|
9088
9168
|
chosen ? "border-primary bg-primary/10" : "border-primary/30 bg-primary/[0.03] hover:bg-primary/10"
|
|
9089
9169
|
),
|
|
@@ -9092,7 +9172,7 @@ function ChoiceAnswer({
|
|
|
9092
9172
|
"kbd",
|
|
9093
9173
|
{
|
|
9094
9174
|
"aria-hidden": "true",
|
|
9095
|
-
className:
|
|
9175
|
+
className: cn25(
|
|
9096
9176
|
"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border font-sans text-xs font-semibold",
|
|
9097
9177
|
chosen ? "border-primary bg-primary text-primary-foreground" : "border-primary/40 text-primary"
|
|
9098
9178
|
),
|
|
@@ -9400,7 +9480,7 @@ function RecordPicker({ tableId, value, onChange, disabled }) {
|
|
|
9400
9480
|
import { useEffect as useEffect23, useMemo as useMemo13 } from "react";
|
|
9401
9481
|
import { isEntityReferenceConfig } from "@ai-matrx/records";
|
|
9402
9482
|
import { useFields as useFields4, useTable as useTable3 } from "@ai-matrx/records/react";
|
|
9403
|
-
import { BasicInput as BasicInput12, Button as Button19, CreatablePicker as CreatablePicker2, cn as
|
|
9483
|
+
import { BasicInput as BasicInput12, Button as Button19, CreatablePicker as CreatablePicker2, cn as cn26 } from "@ai-matrx/design-system";
|
|
9404
9484
|
import { jsx as jsx41, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
9405
9485
|
var DATA_BINDING_SHAPES = [
|
|
9406
9486
|
{ value: "collection", label: "The whole table" },
|
|
@@ -9576,7 +9656,7 @@ function BindingDetails({
|
|
|
9576
9656
|
/* @__PURE__ */ jsx41(
|
|
9577
9657
|
"textarea",
|
|
9578
9658
|
{
|
|
9579
|
-
className:
|
|
9659
|
+
className: cn26(
|
|
9580
9660
|
"min-h-[3.5rem] w-full rounded-md border border-border bg-background px-2 py-1.5 font-mono text-xs"
|
|
9581
9661
|
),
|
|
9582
9662
|
"aria-label": "Each row reads as",
|