@octaviaflow/core 3.1.0-beta.103 → 3.1.0-beta.104
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/dist/components/ExpressionField/ExpressionField.d.ts.map +1 -1
- package/dist/components/ExpressionField/parseExpression.d.ts +17 -0
- package/dist/components/ExpressionField/parseExpression.d.ts.map +1 -1
- package/dist/index.cjs +180 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -65
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34556,6 +34556,39 @@ function parseExpression(value, pillEveryToken = false) {
|
|
|
34556
34556
|
pushText(tail.slice(last));
|
|
34557
34557
|
return segments;
|
|
34558
34558
|
}
|
|
34559
|
+
function callAt(raw, path) {
|
|
34560
|
+
let current = parseCall(raw);
|
|
34561
|
+
for (const index of path) {
|
|
34562
|
+
if (!current) return void 0;
|
|
34563
|
+
const arg = current.args[index];
|
|
34564
|
+
if (arg === void 0) return void 0;
|
|
34565
|
+
current = parseCall(arg);
|
|
34566
|
+
}
|
|
34567
|
+
return current;
|
|
34568
|
+
}
|
|
34569
|
+
function formatNestedCall(name, args) {
|
|
34570
|
+
return `${name}(${args.filter((a) => a.trim() !== "").join(", ")})`;
|
|
34571
|
+
}
|
|
34572
|
+
function replaceArgument(raw, path, next) {
|
|
34573
|
+
if (path.length === 0) return next;
|
|
34574
|
+
const [index, ...rest] = path;
|
|
34575
|
+
const call = parseCall(raw);
|
|
34576
|
+
if (!call || index === void 0 || index > call.args.length) return raw;
|
|
34577
|
+
const args = [...call.args];
|
|
34578
|
+
if (args[index] === void 0) args[index] = "";
|
|
34579
|
+
args[index] = rest.length === 0 ? next : replaceArgument(args[index], rest, next);
|
|
34580
|
+
const wrapped = raw.trim().startsWith("{{");
|
|
34581
|
+
return wrapped ? formatCall(call.name, args) : formatNestedCall(call.name, args);
|
|
34582
|
+
}
|
|
34583
|
+
function argumentKind(arg) {
|
|
34584
|
+
const trimmed = arg.trim();
|
|
34585
|
+
if (!trimmed) return "literal";
|
|
34586
|
+
if (parseCall(trimmed)) return "call";
|
|
34587
|
+
if (trimmed.startsWith("{{") || trimmed.startsWith("ods://") || trimmed.startsWith("${")) {
|
|
34588
|
+
return "reference";
|
|
34589
|
+
}
|
|
34590
|
+
return "literal";
|
|
34591
|
+
}
|
|
34559
34592
|
|
|
34560
34593
|
// src/components/ExpressionField/ExpressionField.tsx
|
|
34561
34594
|
import { jsx as jsx147, jsxs as jsxs141 } from "react/jsx-runtime";
|
|
@@ -34614,8 +34647,14 @@ function insideCallArguments(textBeforeCaret) {
|
|
|
34614
34647
|
}
|
|
34615
34648
|
return depth > 0;
|
|
34616
34649
|
}
|
|
34617
|
-
function argSummary(arg) {
|
|
34650
|
+
function argSummary(arg, nameOf, depth = 2) {
|
|
34618
34651
|
const trimmed = arg.trim();
|
|
34652
|
+
const call = parseCall(trimmed);
|
|
34653
|
+
if (call) {
|
|
34654
|
+
if (depth <= 0) return `${nameOf(call.name)}(\u2026)`;
|
|
34655
|
+
const inner = call.args.map((a) => argSummary(a, nameOf, depth - 1)).filter(Boolean).join(", ");
|
|
34656
|
+
return `${nameOf(call.name)}(${inner})`;
|
|
34657
|
+
}
|
|
34619
34658
|
if (trimmed.startsWith("{{") || trimmed.startsWith("ods://") || trimmed.startsWith("${")) {
|
|
34620
34659
|
return shortReferenceLabel(trimmed.startsWith("ods://") ? `{{${trimmed}}}` : trimmed);
|
|
34621
34660
|
}
|
|
@@ -34653,7 +34692,7 @@ function ExpressionField({
|
|
|
34653
34692
|
);
|
|
34654
34693
|
const chipText = useCallback50(
|
|
34655
34694
|
(name, args) => {
|
|
34656
|
-
const summary = args.map(argSummary).filter(Boolean).join(", ");
|
|
34695
|
+
const summary = args.map((a) => argSummary(a, callLabel)).filter(Boolean).join(", ");
|
|
34657
34696
|
return `${callLabel(name)}(${summary})`;
|
|
34658
34697
|
},
|
|
34659
34698
|
[callLabel]
|
|
@@ -34779,27 +34818,26 @@ function ExpressionField({
|
|
|
34779
34818
|
}, []);
|
|
34780
34819
|
const openEditor = useCallback50((chip) => {
|
|
34781
34820
|
const raw = chip.getAttribute("data-value") ?? "";
|
|
34782
|
-
|
|
34783
|
-
if (!parsed) return;
|
|
34821
|
+
if (!parseCall(raw)) return;
|
|
34784
34822
|
const box = chip.getBoundingClientRect();
|
|
34785
34823
|
const host = fieldRef.current?.getBoundingClientRect();
|
|
34786
34824
|
setEditing({
|
|
34787
34825
|
el: chip,
|
|
34788
|
-
|
|
34789
|
-
args: parsed.args.length ? parsed.args : [""],
|
|
34826
|
+
raw,
|
|
34790
34827
|
rect: {
|
|
34791
34828
|
top: box.bottom - (host?.top ?? 0) + 4,
|
|
34792
34829
|
left: Math.max(0, box.left - (host?.left ?? 0)),
|
|
34793
|
-
width: Math.max(
|
|
34830
|
+
width: Math.max(300, box.width)
|
|
34794
34831
|
}
|
|
34795
34832
|
});
|
|
34796
34833
|
}, []);
|
|
34797
34834
|
const applyEditor = useCallback50(
|
|
34798
|
-
(
|
|
34835
|
+
(raw) => {
|
|
34799
34836
|
if (!editing) return;
|
|
34800
|
-
const
|
|
34837
|
+
const call = parseCall(raw);
|
|
34838
|
+
if (!call) return;
|
|
34801
34839
|
editing.el.setAttribute("data-value", raw);
|
|
34802
|
-
editing.el.textContent = chipText(
|
|
34840
|
+
editing.el.textContent = chipText(call.name, call.args);
|
|
34803
34841
|
editing.el.title = raw;
|
|
34804
34842
|
setEditing(null);
|
|
34805
34843
|
commit();
|
|
@@ -34933,11 +34971,11 @@ function ExpressionField({
|
|
|
34933
34971
|
editing && /* @__PURE__ */ jsx147(
|
|
34934
34972
|
CallEditor,
|
|
34935
34973
|
{
|
|
34936
|
-
|
|
34937
|
-
label: callLabel(editing.name),
|
|
34938
|
-
initialArgs: editing.args,
|
|
34939
|
-
signature: resolveCall?.(editing.name),
|
|
34974
|
+
raw: editing.raw,
|
|
34940
34975
|
rect: editing.rect,
|
|
34976
|
+
nameOf: callLabel,
|
|
34977
|
+
labelFor,
|
|
34978
|
+
resolveCall,
|
|
34941
34979
|
onCancel: () => setEditing(null),
|
|
34942
34980
|
onApply: applyEditor
|
|
34943
34981
|
}
|
|
@@ -34947,36 +34985,44 @@ function ExpressionField({
|
|
|
34947
34985
|
] });
|
|
34948
34986
|
}
|
|
34949
34987
|
function CallEditor({
|
|
34950
|
-
|
|
34951
|
-
label,
|
|
34952
|
-
initialArgs,
|
|
34953
|
-
signature,
|
|
34988
|
+
raw,
|
|
34954
34989
|
rect,
|
|
34990
|
+
nameOf,
|
|
34991
|
+
labelFor,
|
|
34992
|
+
resolveCall,
|
|
34955
34993
|
onApply,
|
|
34956
34994
|
onCancel
|
|
34957
34995
|
}) {
|
|
34958
|
-
const
|
|
34959
|
-
const [
|
|
34960
|
-
|
|
34961
|
-
while (seeded.length < names.length) seeded.push("");
|
|
34962
|
-
return seeded.length ? seeded : [""];
|
|
34963
|
-
});
|
|
34964
|
-
const [raw, setRaw] = useState71(null);
|
|
34996
|
+
const [draft, setDraft] = useState71(raw);
|
|
34997
|
+
const [path, setPath] = useState71([]);
|
|
34998
|
+
const [rawMode, setRawMode] = useState71(false);
|
|
34965
34999
|
const panelRef = useRef50(null);
|
|
34966
35000
|
useEffect56(() => {
|
|
34967
|
-
panelRef.current?.querySelector("input")?.focus();
|
|
34968
35001
|
const onKey = (e) => {
|
|
34969
35002
|
if (e.key === "Escape") onCancel();
|
|
34970
35003
|
};
|
|
34971
35004
|
document.addEventListener("keydown", onKey);
|
|
34972
35005
|
return () => document.removeEventListener("keydown", onKey);
|
|
34973
35006
|
}, [onCancel]);
|
|
34974
|
-
const
|
|
34975
|
-
const
|
|
34976
|
-
|
|
34977
|
-
|
|
35007
|
+
const current = callAt(draft, path);
|
|
35008
|
+
const signature = current ? resolveCall?.(current.name) : void 0;
|
|
35009
|
+
const names = signature?.args ?? [];
|
|
35010
|
+
const args = current ? current.args.length ? current.args : [""] : [];
|
|
35011
|
+
const crumbs = [];
|
|
35012
|
+
for (let i = 0; i <= path.length; i++) {
|
|
35013
|
+
const at = callAt(draft, path.slice(0, i));
|
|
35014
|
+
if (at) crumbs.push({ label: nameOf(at.name), path: path.slice(0, i) });
|
|
35015
|
+
}
|
|
35016
|
+
const setArg = (index, next) => setDraft((d) => replaceArgument(d, [...path, index], next));
|
|
35017
|
+
const dropInto = (index) => (e) => {
|
|
35018
|
+
const dropped = e.dataTransfer.getData("application/x-fx-insert");
|
|
35019
|
+
if (!dropped) return;
|
|
34978
35020
|
e.preventDefault();
|
|
34979
|
-
|
|
35021
|
+
e.stopPropagation();
|
|
35022
|
+
const kind = e.dataTransfer.getData("application/x-fx-type");
|
|
35023
|
+
const bare = dropped.startsWith("{{") && dropped.endsWith("}}") ? dropped.slice(2, -2).trim() : dropped;
|
|
35024
|
+
setDraft((d) => replaceArgument(d, [...path, index], bare));
|
|
35025
|
+
if (kind === "function" || parseCall(bare)) setPath((pth) => [...pth, index]);
|
|
34980
35026
|
};
|
|
34981
35027
|
return /* @__PURE__ */ jsxs141(
|
|
34982
35028
|
"div",
|
|
@@ -34985,49 +35031,122 @@ function CallEditor({
|
|
|
34985
35031
|
className: "ods-expression-field__editor",
|
|
34986
35032
|
style: { top: rect.top, left: rect.left, width: rect.width },
|
|
34987
35033
|
role: "dialog",
|
|
34988
|
-
"aria-label": `Edit ${label}`,
|
|
35034
|
+
"aria-label": `Edit ${crumbs[0]?.label ?? "function"}`,
|
|
34989
35035
|
children: [
|
|
34990
35036
|
/* @__PURE__ */ jsxs141("div", { className: "ods-expression-field__editor-head", children: [
|
|
34991
|
-
/* @__PURE__ */ jsx147("
|
|
34992
|
-
|
|
34993
|
-
|
|
34994
|
-
|
|
34995
|
-
|
|
34996
|
-
|
|
34997
|
-
|
|
34998
|
-
|
|
34999
|
-
|
|
35000
|
-
|
|
35001
|
-
|
|
35002
|
-
|
|
35003
|
-
placeholder: "value, or drag one in",
|
|
35004
|
-
onChange: (e) => setArg(idx, e.target.value),
|
|
35005
|
-
onDragOver: (e) => {
|
|
35006
|
-
if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
|
|
35007
|
-
},
|
|
35008
|
-
onDrop: dropInto(idx)
|
|
35009
|
-
}
|
|
35010
|
-
)
|
|
35011
|
-
] }, idx)
|
|
35012
|
-
)),
|
|
35037
|
+
/* @__PURE__ */ jsx147("nav", { className: "ods-expression-field__editor-crumbs", "aria-label": "Nested functions", children: crumbs.map((crumb, i) => /* @__PURE__ */ jsxs141("span", { children: [
|
|
35038
|
+
i > 0 && /* @__PURE__ */ jsx147("span", { "aria-hidden": "true", children: " \u203A " }),
|
|
35039
|
+
/* @__PURE__ */ jsx147(
|
|
35040
|
+
"button",
|
|
35041
|
+
{
|
|
35042
|
+
type: "button",
|
|
35043
|
+
disabled: i === crumbs.length - 1,
|
|
35044
|
+
onClick: () => setPath(crumb.path),
|
|
35045
|
+
children: crumb.label
|
|
35046
|
+
}
|
|
35047
|
+
)
|
|
35048
|
+
] }, crumb.path.join(".") || "root")) }),
|
|
35013
35049
|
/* @__PURE__ */ jsx147(
|
|
35014
35050
|
"button",
|
|
35015
35051
|
{
|
|
35016
35052
|
type: "button",
|
|
35017
35053
|
className: "ods-expression-field__editor-link",
|
|
35018
|
-
onClick: () =>
|
|
35019
|
-
children: "
|
|
35054
|
+
onClick: () => setRawMode((r) => !r),
|
|
35055
|
+
children: rawMode ? "Back to fields" : "Edit as text"
|
|
35020
35056
|
}
|
|
35021
35057
|
)
|
|
35022
|
-
] })
|
|
35058
|
+
] }),
|
|
35059
|
+
rawMode ? /* @__PURE__ */ jsx147(
|
|
35023
35060
|
"textarea",
|
|
35024
35061
|
{
|
|
35025
35062
|
className: "ods-expression-field__editor-raw",
|
|
35026
|
-
value:
|
|
35063
|
+
value: draft,
|
|
35027
35064
|
rows: 3,
|
|
35028
|
-
|
|
35065
|
+
"aria-label": "Expression",
|
|
35066
|
+
onChange: (e) => setDraft(e.target.value)
|
|
35029
35067
|
}
|
|
35030
|
-
),
|
|
35068
|
+
) : /* @__PURE__ */ jsxs141("div", { className: "ods-expression-field__editor-rows", children: [
|
|
35069
|
+
args.map((arg, index) => {
|
|
35070
|
+
const kind = argumentKind(arg);
|
|
35071
|
+
const rowLabel = names[index] ?? `argument ${index + 1}`;
|
|
35072
|
+
const nested = kind === "call" ? parseCall(arg) : void 0;
|
|
35073
|
+
return (
|
|
35074
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
35075
|
+
/* @__PURE__ */ jsxs141("div", { className: "ods-expression-field__editor-row", children: [
|
|
35076
|
+
/* @__PURE__ */ jsx147("span", { id: `arg-${index}-label`, children: rowLabel }),
|
|
35077
|
+
nested ? /* @__PURE__ */ jsxs141(
|
|
35078
|
+
"div",
|
|
35079
|
+
{
|
|
35080
|
+
className: "ods-expression-field__editor-nested",
|
|
35081
|
+
onDragOver: (e) => {
|
|
35082
|
+
if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
|
|
35083
|
+
},
|
|
35084
|
+
onDrop: dropInto(index),
|
|
35085
|
+
children: [
|
|
35086
|
+
/* @__PURE__ */ jsx147("code", { children: argSummary(arg, nameOf) }),
|
|
35087
|
+
/* @__PURE__ */ jsxs141("span", { children: [
|
|
35088
|
+
/* @__PURE__ */ jsx147("button", { type: "button", onClick: () => setPath([...path, index]), children: "Open" }),
|
|
35089
|
+
/* @__PURE__ */ jsx147("button", { type: "button", onClick: () => setArg(index, ""), "aria-label": `Clear ${rowLabel}`, children: "Clear" })
|
|
35090
|
+
] })
|
|
35091
|
+
]
|
|
35092
|
+
}
|
|
35093
|
+
) : kind === "reference" ? (
|
|
35094
|
+
// A reference is a value from somewhere else — named, never
|
|
35095
|
+
// its raw `ods://…` path, here as much as in the field.
|
|
35096
|
+
/* @__PURE__ */ jsxs141(
|
|
35097
|
+
"div",
|
|
35098
|
+
{
|
|
35099
|
+
className: "ods-expression-field__editor-ref",
|
|
35100
|
+
onDragOver: (e) => {
|
|
35101
|
+
if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
|
|
35102
|
+
},
|
|
35103
|
+
onDrop: dropInto(index),
|
|
35104
|
+
children: [
|
|
35105
|
+
/* @__PURE__ */ jsx147(
|
|
35106
|
+
"span",
|
|
35107
|
+
{
|
|
35108
|
+
className: "ods-expression-field__pill",
|
|
35109
|
+
title: arg,
|
|
35110
|
+
"aria-labelledby": `arg-${index}-label`,
|
|
35111
|
+
children: labelFor(arg.startsWith("ods://") ? `{{${arg}}}` : arg)
|
|
35112
|
+
}
|
|
35113
|
+
),
|
|
35114
|
+
/* @__PURE__ */ jsx147("button", { type: "button", onClick: () => setArg(index, ""), "aria-label": `Clear ${rowLabel}`, children: "Clear" })
|
|
35115
|
+
]
|
|
35116
|
+
}
|
|
35117
|
+
)
|
|
35118
|
+
) : /* @__PURE__ */ jsx147(
|
|
35119
|
+
"input",
|
|
35120
|
+
{
|
|
35121
|
+
"aria-labelledby": `arg-${index}-label`,
|
|
35122
|
+
value: arg,
|
|
35123
|
+
placeholder: 'a value, "text", or drag one in',
|
|
35124
|
+
"data-kind": kind,
|
|
35125
|
+
onChange: (e) => setArg(index, e.target.value),
|
|
35126
|
+
onDragOver: (e) => {
|
|
35127
|
+
if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
|
|
35128
|
+
},
|
|
35129
|
+
onDrop: dropInto(index)
|
|
35130
|
+
}
|
|
35131
|
+
)
|
|
35132
|
+
] }, index)
|
|
35133
|
+
);
|
|
35134
|
+
}),
|
|
35135
|
+
/* @__PURE__ */ jsx147(
|
|
35136
|
+
"button",
|
|
35137
|
+
{
|
|
35138
|
+
type: "button",
|
|
35139
|
+
className: "ods-expression-field__editor-link",
|
|
35140
|
+
onClick: () => setDraft((d) => {
|
|
35141
|
+
const at = callAt(d, path);
|
|
35142
|
+
if (!at) return d;
|
|
35143
|
+
const next = [...at.args, '""'];
|
|
35144
|
+
return path.length === 0 ? formatCall(at.name, next) : replaceArgument(d, path, `${at.name}(${next.join(", ")})`);
|
|
35145
|
+
}),
|
|
35146
|
+
children: "+ argument"
|
|
35147
|
+
}
|
|
35148
|
+
)
|
|
35149
|
+
] }),
|
|
35031
35150
|
/* @__PURE__ */ jsxs141("div", { className: "ods-expression-field__editor-foot", children: [
|
|
35032
35151
|
/* @__PURE__ */ jsx147("button", { type: "button", onClick: onCancel, children: "Cancel" }),
|
|
35033
35152
|
/* @__PURE__ */ jsx147(
|
|
@@ -35035,11 +35154,7 @@ function CallEditor({
|
|
|
35035
35154
|
{
|
|
35036
35155
|
type: "button",
|
|
35037
35156
|
className: "ods-expression-field__editor-primary",
|
|
35038
|
-
onClick: () =>
|
|
35039
|
-
if (raw === null) return onApply(args);
|
|
35040
|
-
const parsed = parseCall(raw);
|
|
35041
|
-
onApply(parsed ? parsed.args : splitArguments(raw));
|
|
35042
|
-
},
|
|
35157
|
+
onClick: () => onApply(draft),
|
|
35043
35158
|
children: "Apply"
|
|
35044
35159
|
}
|
|
35045
35160
|
)
|