@ai-matrx/records-ui 0.115.79 → 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 +17 -1
- package/dist/index.cjs +96 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +97 -17
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs +65 -14
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js +65 -14
- package/dist/pickers.js.map +1 -1
- package/package.json +4 -4
package/dist/pickers.cjs
CHANGED
|
@@ -4778,6 +4778,33 @@ var CONDITION_OPS = [
|
|
|
4778
4778
|
{ op: "gte", label: "is at least" },
|
|
4779
4779
|
{ op: "lte", label: "is at most" }
|
|
4780
4780
|
];
|
|
4781
|
+
var LIST_TERMS = [
|
|
4782
|
+
{ op: "contains", label: "contains" },
|
|
4783
|
+
{ op: "not_contains", label: "does not contain" },
|
|
4784
|
+
{ op: "is_empty", label: "is empty" },
|
|
4785
|
+
{ op: "is_not_empty", label: "is not empty" }
|
|
4786
|
+
];
|
|
4787
|
+
var VALUELESS_OPS = /* @__PURE__ */ new Set(["present", "is_empty", "is_not_empty"]);
|
|
4788
|
+
var LINK_SEP = ">";
|
|
4789
|
+
function linkedNode(viaId, innerId, op, value) {
|
|
4790
|
+
return {
|
|
4791
|
+
op: "linked",
|
|
4792
|
+
match: op === "eq" ? "any" : "none",
|
|
4793
|
+
args: [{ field: viaId }, { op: "eq", args: [{ field: innerId }, { const: value }] }]
|
|
4794
|
+
};
|
|
4795
|
+
}
|
|
4796
|
+
function linkedOf(expr) {
|
|
4797
|
+
const node = asNode(expr);
|
|
4798
|
+
if (!node || node["op"] !== "linked") return null;
|
|
4799
|
+
const [rel, cond] = argsOf(node);
|
|
4800
|
+
const innerNode = asNode(cond);
|
|
4801
|
+
const [a, b] = innerNode ? argsOf(innerNode) : [];
|
|
4802
|
+
const match = node["match"] ?? "any";
|
|
4803
|
+
if (!rel || typeof rel["field"] !== "string" || !innerNode || innerNode["op"] !== "eq") return null;
|
|
4804
|
+
if (!a || typeof a["field"] !== "string" || !b || !("const" in b)) return null;
|
|
4805
|
+
if (match !== "any" && match !== "none") return null;
|
|
4806
|
+
return { via: rel["field"], inner: a["field"], op: match === "any" ? "eq" : "ne", value: b["const"] };
|
|
4807
|
+
}
|
|
4781
4808
|
var FilterTermsContext = (0, import_react36.createContext)(false);
|
|
4782
4809
|
var RELATIVE_DAY_TERMS = [
|
|
4783
4810
|
{ kind: "today", label: "is today" },
|
|
@@ -4890,13 +4917,15 @@ function ChoiceValue({ field, value, onChange }) {
|
|
|
4890
4917
|
}
|
|
4891
4918
|
function conditionIsSimple(expr) {
|
|
4892
4919
|
if (expr === null || expr === void 0) return true;
|
|
4893
|
-
if (relativeDayOf(expr) !== null || meOf(expr) !== null) return true;
|
|
4920
|
+
if (relativeDayOf(expr) !== null || meOf(expr) !== null || linkedOf(expr) !== null) return true;
|
|
4894
4921
|
const node = expr;
|
|
4895
|
-
if (typeof node.op !== "string" || !CONDITION_OPS.some((c) => c.op === node.op))
|
|
4922
|
+
if (typeof node.op !== "string" || !(CONDITION_OPS.some((c) => c.op === node.op) || LIST_TERMS.some((c) => c.op === node.op))) {
|
|
4923
|
+
return false;
|
|
4924
|
+
}
|
|
4896
4925
|
if (!Array.isArray(node.args)) return false;
|
|
4897
4926
|
const first = node.args[0];
|
|
4898
4927
|
if (!first || typeof first.field !== "string") return false;
|
|
4899
|
-
if (node.op
|
|
4928
|
+
if (VALUELESS_OPS.has(node.op)) return node.args.length === 1;
|
|
4900
4929
|
const second = node.args[1];
|
|
4901
4930
|
return node.args.length === 2 && !!second && "const" in second;
|
|
4902
4931
|
}
|
|
@@ -4914,7 +4943,13 @@ function conditionInWords(expr, fields) {
|
|
|
4914
4943
|
lte: "is at most",
|
|
4915
4944
|
and: "and",
|
|
4916
4945
|
or: "or",
|
|
4917
|
-
matches: "matches"
|
|
4946
|
+
matches: "matches",
|
|
4947
|
+
contains: "contains",
|
|
4948
|
+
not_contains: "does not contain",
|
|
4949
|
+
has_any: "has any of",
|
|
4950
|
+
has_all: "has all of",
|
|
4951
|
+
has_none: "has none of",
|
|
4952
|
+
is_exactly: "is exactly"
|
|
4918
4953
|
};
|
|
4919
4954
|
const walk = (node) => {
|
|
4920
4955
|
if (node === null || node === void 0) return "nothing";
|
|
@@ -4935,6 +4970,12 @@ function conditionInWords(expr, fields) {
|
|
|
4935
4970
|
const args = Array.isArray(n["args"]) ? n["args"] : [];
|
|
4936
4971
|
if (op === "not") return `not ${walk(args[0])}`;
|
|
4937
4972
|
if (op === "present") return `${walk(args[0])} has been answered`;
|
|
4973
|
+
if (op === "is_empty") return `${walk(args[0])} is empty`;
|
|
4974
|
+
if (op === "is_not_empty") return `${walk(args[0])} is not empty`;
|
|
4975
|
+
if (op === "linked") {
|
|
4976
|
+
const how = n["match"] === "every" ? "every" : n["match"] === "none" ? "none of" : "any";
|
|
4977
|
+
return `${how} linked record in ${walk(args[0])}: ${walk(args[1])}`;
|
|
4978
|
+
}
|
|
4938
4979
|
const dayRange = relativeDayOf(n);
|
|
4939
4980
|
if (dayRange) {
|
|
4940
4981
|
const term = RELATIVE_DAY_TERMS.find((t) => t.kind === dayRange.kind);
|
|
@@ -4967,12 +5008,14 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
4967
5008
|
const filterTerms = (0, import_react36.useContext)(FilterTermsContext);
|
|
4968
5009
|
const relative = relativeDayOf(expr);
|
|
4969
5010
|
const reader = meOf(expr);
|
|
4970
|
-
const
|
|
4971
|
-
const
|
|
4972
|
-
const
|
|
5011
|
+
const linked = linkedOf(expr);
|
|
5012
|
+
const op = relative ? `rel:${relative.kind}` : reader ? reader.which : linked ? linked.op : node?.op ?? "";
|
|
5013
|
+
const onField = linked ? `${linked.via}${LINK_SEP}${linked.inner}` : node?.args?.[0]?.field ?? "";
|
|
5014
|
+
const value = relative || reader ? "" : linked ? linked.value : node?.args?.[1]?.const ?? "";
|
|
4973
5015
|
const chosen = fields.find((f) => f.id === onField);
|
|
4974
5016
|
const chosenKind = chosen?.field ? String(editorKindFor(chosen.field)) : "";
|
|
4975
|
-
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" }] : [];
|
|
5017
|
+
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 : [];
|
|
5018
|
+
const baseTerms = chosen?.via ? CONDITION_OPS.filter((c) => c.op === "eq" || c.op === "ne") : CONDITION_OPS;
|
|
4976
5019
|
const relativeTerm = relative ? RELATIVE_DAY_TERMS.find((t) => t.kind === relative.kind) : void 0;
|
|
4977
5020
|
function write(next) {
|
|
4978
5021
|
const picked = next.op;
|
|
@@ -4985,8 +5028,11 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
4985
5028
|
onChange(relativeDayNode(fieldNow, relative.kind, next.days));
|
|
4986
5029
|
return;
|
|
4987
5030
|
}
|
|
4988
|
-
if (next.field !== void 0 && (relative || reader)) {
|
|
4989
|
-
|
|
5031
|
+
if (next.field !== void 0 && (relative || reader || linked)) {
|
|
5032
|
+
const target2 = fields.find((f) => f.id === next.field);
|
|
5033
|
+
onChange(
|
|
5034
|
+
!next.field ? null : target2?.via ? linkedNode(target2.via.id, target2.via.fieldId, "eq", "") : { op: CONDITION_OPS[0].op, args: [{ field: next.field }, { const: "" }] }
|
|
5035
|
+
);
|
|
4990
5036
|
return;
|
|
4991
5037
|
}
|
|
4992
5038
|
const chosenOp = next.op ?? (op || (next.field ? CONDITION_OPS[0].op : ""));
|
|
@@ -4996,8 +5042,13 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
4996
5042
|
onChange(null);
|
|
4997
5043
|
return;
|
|
4998
5044
|
}
|
|
5045
|
+
const target = fields.find((f) => f.id === chosenField);
|
|
5046
|
+
if (target?.via) {
|
|
5047
|
+
onChange(linkedNode(target.via.id, target.via.fieldId, chosenOp === "ne" ? "ne" : "eq", chosenValue));
|
|
5048
|
+
return;
|
|
5049
|
+
}
|
|
4999
5050
|
onChange(
|
|
5000
|
-
chosenOp
|
|
5051
|
+
VALUELESS_OPS.has(chosenOp) ? { op: chosenOp, args: [{ field: chosenField }] } : { op: chosenOp, args: [{ field: chosenField }, { const: chosenValue }] }
|
|
5001
5052
|
);
|
|
5002
5053
|
}
|
|
5003
5054
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: className ?? "flex flex-wrap items-center gap-1 text-xs", children: [
|
|
@@ -5030,7 +5081,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5030
5081
|
className: "h-8 w-auto min-w-[6rem] text-xs",
|
|
5031
5082
|
value: op,
|
|
5032
5083
|
onChange: (next) => write({ op: next }),
|
|
5033
|
-
options: [...
|
|
5084
|
+
options: [...baseTerms, ...extraTerms].map((c) => ({ value: c.op, label: c.label })),
|
|
5034
5085
|
attrs: { "data-condition": "comparison" }
|
|
5035
5086
|
}
|
|
5036
5087
|
),
|
|
@@ -5044,7 +5095,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5044
5095
|
value: String(relative.days ?? 7),
|
|
5045
5096
|
onChange: (e) => write({ days: Math.max(0, Math.floor(Number(e.target.value) || 0)) })
|
|
5046
5097
|
}
|
|
5047
|
-
) : null : reader || op
|
|
5098
|
+
) : null : reader || VALUELESS_OPS.has(op) ? null : pointsAtARecord(chosen) ? (
|
|
5048
5099
|
// A RECORD IS PICKED BY ITS WORDS, NEVER TYPED AS AN ID. The same picker the
|
|
5049
5100
|
// cell uses, on the same `relation_words_many` the cell reads, so a filter and
|
|
5050
5101
|
// the column it filters can never disagree about what a record is called. It
|
|
@@ -5062,7 +5113,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5062
5113
|
allowCreate: false
|
|
5063
5114
|
}
|
|
5064
5115
|
)
|
|
5065
|
-
) : isChoiceColumn(chosen) && (op === "eq" || op === "ne") ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChoiceValue, { field: chosen.field, value: String(value ?? ""), onChange: (word) => write({ value: word }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5116
|
+
) : isChoiceColumn(chosen) && (op === "eq" || op === "ne" || op === "contains" || op === "not_contains") ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChoiceValue, { field: chosen.field, value: String(value ?? ""), onChange: (word) => write({ value: word }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5066
5117
|
import_design_system23.BasicInput,
|
|
5067
5118
|
{
|
|
5068
5119
|
className: "h-8 w-28 text-xs",
|