@ai-matrx/records-ui 0.115.79 → 0.115.81
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 +103 -17
- 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 +104 -18
- 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 +3 -3
package/dist/pickers.js
CHANGED
|
@@ -4842,6 +4842,33 @@ var CONDITION_OPS = [
|
|
|
4842
4842
|
{ op: "gte", label: "is at least" },
|
|
4843
4843
|
{ op: "lte", label: "is at most" }
|
|
4844
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
|
+
}
|
|
4845
4872
|
var FilterTermsContext = createContext4(false);
|
|
4846
4873
|
var RELATIVE_DAY_TERMS = [
|
|
4847
4874
|
{ kind: "today", label: "is today" },
|
|
@@ -4954,13 +4981,15 @@ function ChoiceValue({ field, value, onChange }) {
|
|
|
4954
4981
|
}
|
|
4955
4982
|
function conditionIsSimple(expr) {
|
|
4956
4983
|
if (expr === null || expr === void 0) return true;
|
|
4957
|
-
if (relativeDayOf(expr) !== null || meOf(expr) !== null) return true;
|
|
4984
|
+
if (relativeDayOf(expr) !== null || meOf(expr) !== null || linkedOf(expr) !== null) return true;
|
|
4958
4985
|
const node = expr;
|
|
4959
|
-
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
|
+
}
|
|
4960
4989
|
if (!Array.isArray(node.args)) return false;
|
|
4961
4990
|
const first = node.args[0];
|
|
4962
4991
|
if (!first || typeof first.field !== "string") return false;
|
|
4963
|
-
if (node.op
|
|
4992
|
+
if (VALUELESS_OPS.has(node.op)) return node.args.length === 1;
|
|
4964
4993
|
const second = node.args[1];
|
|
4965
4994
|
return node.args.length === 2 && !!second && "const" in second;
|
|
4966
4995
|
}
|
|
@@ -4978,7 +5007,13 @@ function conditionInWords(expr, fields) {
|
|
|
4978
5007
|
lte: "is at most",
|
|
4979
5008
|
and: "and",
|
|
4980
5009
|
or: "or",
|
|
4981
|
-
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"
|
|
4982
5017
|
};
|
|
4983
5018
|
const walk = (node) => {
|
|
4984
5019
|
if (node === null || node === void 0) return "nothing";
|
|
@@ -4999,6 +5034,12 @@ function conditionInWords(expr, fields) {
|
|
|
4999
5034
|
const args = Array.isArray(n["args"]) ? n["args"] : [];
|
|
5000
5035
|
if (op === "not") return `not ${walk(args[0])}`;
|
|
5001
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
|
+
}
|
|
5002
5043
|
const dayRange = relativeDayOf(n);
|
|
5003
5044
|
if (dayRange) {
|
|
5004
5045
|
const term = RELATIVE_DAY_TERMS.find((t) => t.kind === dayRange.kind);
|
|
@@ -5031,12 +5072,14 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5031
5072
|
const filterTerms = useContext4(FilterTermsContext);
|
|
5032
5073
|
const relative = relativeDayOf(expr);
|
|
5033
5074
|
const reader = meOf(expr);
|
|
5034
|
-
const
|
|
5035
|
-
const
|
|
5036
|
-
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 ?? "";
|
|
5037
5079
|
const chosen = fields.find((f) => f.id === onField);
|
|
5038
5080
|
const chosenKind = chosen?.field ? String(editorKindFor(chosen.field)) : "";
|
|
5039
|
-
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;
|
|
5040
5083
|
const relativeTerm = relative ? RELATIVE_DAY_TERMS.find((t) => t.kind === relative.kind) : void 0;
|
|
5041
5084
|
function write(next) {
|
|
5042
5085
|
const picked = next.op;
|
|
@@ -5049,8 +5092,11 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5049
5092
|
onChange(relativeDayNode(fieldNow, relative.kind, next.days));
|
|
5050
5093
|
return;
|
|
5051
5094
|
}
|
|
5052
|
-
if (next.field !== void 0 && (relative || reader)) {
|
|
5053
|
-
|
|
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
|
+
);
|
|
5054
5100
|
return;
|
|
5055
5101
|
}
|
|
5056
5102
|
const chosenOp = next.op ?? (op || (next.field ? CONDITION_OPS[0].op : ""));
|
|
@@ -5060,8 +5106,13 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5060
5106
|
onChange(null);
|
|
5061
5107
|
return;
|
|
5062
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
|
+
}
|
|
5063
5114
|
onChange(
|
|
5064
|
-
chosenOp
|
|
5115
|
+
VALUELESS_OPS.has(chosenOp) ? { op: chosenOp, args: [{ field: chosenField }] } : { op: chosenOp, args: [{ field: chosenField }, { const: chosenValue }] }
|
|
5065
5116
|
);
|
|
5066
5117
|
}
|
|
5067
5118
|
return /* @__PURE__ */ jsxs23("div", { className: className ?? "flex flex-wrap items-center gap-1 text-xs", children: [
|
|
@@ -5094,7 +5145,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5094
5145
|
className: "h-8 w-auto min-w-[6rem] text-xs",
|
|
5095
5146
|
value: op,
|
|
5096
5147
|
onChange: (next) => write({ op: next }),
|
|
5097
|
-
options: [...
|
|
5148
|
+
options: [...baseTerms, ...extraTerms].map((c) => ({ value: c.op, label: c.label })),
|
|
5098
5149
|
attrs: { "data-condition": "comparison" }
|
|
5099
5150
|
}
|
|
5100
5151
|
),
|
|
@@ -5108,7 +5159,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5108
5159
|
value: String(relative.days ?? 7),
|
|
5109
5160
|
onChange: (e) => write({ days: Math.max(0, Math.floor(Number(e.target.value) || 0)) })
|
|
5110
5161
|
}
|
|
5111
|
-
) : null : reader || op
|
|
5162
|
+
) : null : reader || VALUELESS_OPS.has(op) ? null : pointsAtARecord(chosen) ? (
|
|
5112
5163
|
// A RECORD IS PICKED BY ITS WORDS, NEVER TYPED AS AN ID. The same picker the
|
|
5113
5164
|
// cell uses, on the same `relation_words_many` the cell reads, so a filter and
|
|
5114
5165
|
// the column it filters can never disagree about what a record is called. It
|
|
@@ -5126,7 +5177,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
5126
5177
|
allowCreate: false
|
|
5127
5178
|
}
|
|
5128
5179
|
)
|
|
5129
|
-
) : 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(
|
|
5130
5181
|
BasicInput7,
|
|
5131
5182
|
{
|
|
5132
5183
|
className: "h-8 w-28 text-xs",
|