@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.
@@ -1 +1 @@
1
- {"version":3,"file":"ExpressionField.d.ts","sourceRoot":"","sources":["../../../src/components/ExpressionField/ExpressionField.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,aAAa,EAIlB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAUf,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CAChC;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC1D;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWzD;AAyBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAiBpE;AAWD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAgB,EAChB,IAAQ,EACR,EAAE,EACF,SAAS,EACT,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAsB,EACtB,YAAY,EAAE,SAAS,GACxB,EAAE,oBAAoB,2CA+XtB;AA0HD,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ExpressionField.d.ts","sourceRoot":"","sources":["../../../src/components/ExpressionField/ExpressionField.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,aAAa,EAIlB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAaf,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CAChC;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC1D;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWzD;AAyBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAiBpE;AAuBD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,WAAW,EACX,UAAU,EACV,QAAgB,EAChB,IAAQ,EACR,EAAE,EACF,SAAS,EACT,KAAK,EACL,YAAY,EACZ,WAAW,EACX,cAAsB,EACtB,YAAY,EAAE,SAAS,GACxB,EAAE,oBAAoB,2CA8XtB;AAuND,eAAe,eAAe,CAAC"}
@@ -32,4 +32,21 @@ export declare function formatCall(name: string, args: string[]): string;
32
32
  * not a call, for hosts whose tokens are their own short form.
33
33
  */
34
34
  export declare function parseExpression(value: string, pillEveryToken?: boolean): Segment[];
35
+ /** The call at `path`, or the top-level call for an empty path. */
36
+ export declare function callAt(raw: string, path: number[]): {
37
+ name: string;
38
+ args: string[];
39
+ } | undefined;
40
+ /** The argument text at `path`, e.g. `[0]` → the first argument. */
41
+ export declare function argumentAt(raw: string, path: number[]): string | undefined;
42
+ /** A nested call is written bare; only the outermost one wears braces. */
43
+ export declare function formatNestedCall(name: string, args: string[]): string;
44
+ /**
45
+ * Replace the argument at `path`, rebuilding every call on the way back up.
46
+ * An empty path replaces the whole expression.
47
+ */
48
+ export declare function replaceArgument(raw: string, path: number[], next: string): string;
49
+ /** What kind of thing an argument is — the editor shows each differently. */
50
+ export type ArgumentKind = "reference" | "call" | "literal";
51
+ export declare function argumentKind(arg: string): ArgumentKind;
35
52
  //# sourceMappingURL=parseExpression.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseExpression.d.ts","sourceRoot":"","sources":["../../../src/components/ExpressionField/parseExpression.ts"],"names":[],"mappings":"AASA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,uDAAuD,CAAC;AAGrF,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA2ChE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA2CzD;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAQnF;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,UAAQ,GAAG,OAAO,EAAE,CA8BhF"}
1
+ {"version":3,"file":"parseExpression.d.ts","sourceRoot":"","sources":["../../../src/components/ExpressionField/parseExpression.ts"],"names":[],"mappings":"AASA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,uDAAuD,CAAC;AAGrF,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA2ChE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA2CzD;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAQnF;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,UAAQ,GAAG,OAAO,EAAE,CA8BhF;AAQD,mEAAmE;AACnE,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAShG;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAI1E;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAYjF;AAED,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAQtD"}
package/dist/index.cjs CHANGED
@@ -41467,6 +41467,39 @@ function parseExpression(value, pillEveryToken = false) {
41467
41467
  pushText(tail.slice(last));
41468
41468
  return segments;
41469
41469
  }
41470
+ function callAt(raw, path) {
41471
+ let current = parseCall(raw);
41472
+ for (const index of path) {
41473
+ if (!current) return void 0;
41474
+ const arg = current.args[index];
41475
+ if (arg === void 0) return void 0;
41476
+ current = parseCall(arg);
41477
+ }
41478
+ return current;
41479
+ }
41480
+ function formatNestedCall(name, args) {
41481
+ return `${name}(${args.filter((a) => a.trim() !== "").join(", ")})`;
41482
+ }
41483
+ function replaceArgument(raw, path, next) {
41484
+ if (path.length === 0) return next;
41485
+ const [index, ...rest] = path;
41486
+ const call = parseCall(raw);
41487
+ if (!call || index === void 0 || index > call.args.length) return raw;
41488
+ const args = [...call.args];
41489
+ if (args[index] === void 0) args[index] = "";
41490
+ args[index] = rest.length === 0 ? next : replaceArgument(args[index], rest, next);
41491
+ const wrapped = raw.trim().startsWith("{{");
41492
+ return wrapped ? formatCall(call.name, args) : formatNestedCall(call.name, args);
41493
+ }
41494
+ function argumentKind(arg) {
41495
+ const trimmed = arg.trim();
41496
+ if (!trimmed) return "literal";
41497
+ if (parseCall(trimmed)) return "call";
41498
+ if (trimmed.startsWith("{{") || trimmed.startsWith("ods://") || trimmed.startsWith("${")) {
41499
+ return "reference";
41500
+ }
41501
+ return "literal";
41502
+ }
41470
41503
 
41471
41504
  // src/components/ExpressionField/ExpressionField.tsx
41472
41505
  var import_jsx_runtime174 = require("react/jsx-runtime");
@@ -41525,8 +41558,14 @@ function insideCallArguments(textBeforeCaret) {
41525
41558
  }
41526
41559
  return depth > 0;
41527
41560
  }
41528
- function argSummary(arg) {
41561
+ function argSummary(arg, nameOf, depth = 2) {
41529
41562
  const trimmed = arg.trim();
41563
+ const call = parseCall(trimmed);
41564
+ if (call) {
41565
+ if (depth <= 0) return `${nameOf(call.name)}(\u2026)`;
41566
+ const inner = call.args.map((a) => argSummary(a, nameOf, depth - 1)).filter(Boolean).join(", ");
41567
+ return `${nameOf(call.name)}(${inner})`;
41568
+ }
41530
41569
  if (trimmed.startsWith("{{") || trimmed.startsWith("ods://") || trimmed.startsWith("${")) {
41531
41570
  return shortReferenceLabel(trimmed.startsWith("ods://") ? `{{${trimmed}}}` : trimmed);
41532
41571
  }
@@ -41564,7 +41603,7 @@ function ExpressionField({
41564
41603
  );
41565
41604
  const chipText = (0, import_react188.useCallback)(
41566
41605
  (name, args) => {
41567
- const summary = args.map(argSummary).filter(Boolean).join(", ");
41606
+ const summary = args.map((a) => argSummary(a, callLabel)).filter(Boolean).join(", ");
41568
41607
  return `${callLabel(name)}(${summary})`;
41569
41608
  },
41570
41609
  [callLabel]
@@ -41690,27 +41729,26 @@ function ExpressionField({
41690
41729
  }, []);
41691
41730
  const openEditor = (0, import_react188.useCallback)((chip) => {
41692
41731
  const raw = chip.getAttribute("data-value") ?? "";
41693
- const parsed = parseCall(raw);
41694
- if (!parsed) return;
41732
+ if (!parseCall(raw)) return;
41695
41733
  const box = chip.getBoundingClientRect();
41696
41734
  const host = fieldRef.current?.getBoundingClientRect();
41697
41735
  setEditing({
41698
41736
  el: chip,
41699
- name: parsed.name,
41700
- args: parsed.args.length ? parsed.args : [""],
41737
+ raw,
41701
41738
  rect: {
41702
41739
  top: box.bottom - (host?.top ?? 0) + 4,
41703
41740
  left: Math.max(0, box.left - (host?.left ?? 0)),
41704
- width: Math.max(260, box.width)
41741
+ width: Math.max(300, box.width)
41705
41742
  }
41706
41743
  });
41707
41744
  }, []);
41708
41745
  const applyEditor = (0, import_react188.useCallback)(
41709
- (args) => {
41746
+ (raw) => {
41710
41747
  if (!editing) return;
41711
- const raw = formatCall(editing.name, args);
41748
+ const call = parseCall(raw);
41749
+ if (!call) return;
41712
41750
  editing.el.setAttribute("data-value", raw);
41713
- editing.el.textContent = chipText(editing.name, args);
41751
+ editing.el.textContent = chipText(call.name, call.args);
41714
41752
  editing.el.title = raw;
41715
41753
  setEditing(null);
41716
41754
  commit();
@@ -41844,11 +41882,11 @@ function ExpressionField({
41844
41882
  editing && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41845
41883
  CallEditor,
41846
41884
  {
41847
- name: editing.name,
41848
- label: callLabel(editing.name),
41849
- initialArgs: editing.args,
41850
- signature: resolveCall?.(editing.name),
41885
+ raw: editing.raw,
41851
41886
  rect: editing.rect,
41887
+ nameOf: callLabel,
41888
+ labelFor,
41889
+ resolveCall,
41852
41890
  onCancel: () => setEditing(null),
41853
41891
  onApply: applyEditor
41854
41892
  }
@@ -41858,36 +41896,44 @@ function ExpressionField({
41858
41896
  ] });
41859
41897
  }
41860
41898
  function CallEditor({
41861
- name,
41862
- label,
41863
- initialArgs,
41864
- signature,
41899
+ raw,
41865
41900
  rect,
41901
+ nameOf,
41902
+ labelFor,
41903
+ resolveCall,
41866
41904
  onApply,
41867
41905
  onCancel
41868
41906
  }) {
41869
- const names = signature?.args ?? [];
41870
- const [args, setArgs] = (0, import_react188.useState)(() => {
41871
- const seeded = [...initialArgs];
41872
- while (seeded.length < names.length) seeded.push("");
41873
- return seeded.length ? seeded : [""];
41874
- });
41875
- const [raw, setRaw] = (0, import_react188.useState)(null);
41907
+ const [draft, setDraft] = (0, import_react188.useState)(raw);
41908
+ const [path, setPath] = (0, import_react188.useState)([]);
41909
+ const [rawMode, setRawMode] = (0, import_react188.useState)(false);
41876
41910
  const panelRef = (0, import_react188.useRef)(null);
41877
41911
  (0, import_react188.useEffect)(() => {
41878
- panelRef.current?.querySelector("input")?.focus();
41879
41912
  const onKey = (e) => {
41880
41913
  if (e.key === "Escape") onCancel();
41881
41914
  };
41882
41915
  document.addEventListener("keydown", onKey);
41883
41916
  return () => document.removeEventListener("keydown", onKey);
41884
41917
  }, [onCancel]);
41885
- const setArg = (idx, next) => setArgs((prev) => prev.map((a, i) => i === idx ? next : a));
41886
- const dropInto = (idx) => (e) => {
41887
- const ref = e.dataTransfer.getData("application/x-fx-insert");
41888
- if (!ref) return;
41918
+ const current = callAt(draft, path);
41919
+ const signature = current ? resolveCall?.(current.name) : void 0;
41920
+ const names = signature?.args ?? [];
41921
+ const args = current ? current.args.length ? current.args : [""] : [];
41922
+ const crumbs = [];
41923
+ for (let i = 0; i <= path.length; i++) {
41924
+ const at = callAt(draft, path.slice(0, i));
41925
+ if (at) crumbs.push({ label: nameOf(at.name), path: path.slice(0, i) });
41926
+ }
41927
+ const setArg = (index, next) => setDraft((d) => replaceArgument(d, [...path, index], next));
41928
+ const dropInto = (index) => (e) => {
41929
+ const dropped = e.dataTransfer.getData("application/x-fx-insert");
41930
+ if (!dropped) return;
41889
41931
  e.preventDefault();
41890
- setArg(idx, ref);
41932
+ e.stopPropagation();
41933
+ const kind = e.dataTransfer.getData("application/x-fx-type");
41934
+ const bare = dropped.startsWith("{{") && dropped.endsWith("}}") ? dropped.slice(2, -2).trim() : dropped;
41935
+ setDraft((d) => replaceArgument(d, [...path, index], bare));
41936
+ if (kind === "function" || parseCall(bare)) setPath((pth) => [...pth, index]);
41891
41937
  };
41892
41938
  return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
41893
41939
  "div",
@@ -41896,49 +41942,122 @@ function CallEditor({
41896
41942
  className: "ods-expression-field__editor",
41897
41943
  style: { top: rect.top, left: rect.left, width: rect.width },
41898
41944
  role: "dialog",
41899
- "aria-label": `Edit ${label}`,
41945
+ "aria-label": `Edit ${crumbs[0]?.label ?? "function"}`,
41900
41946
  children: [
41901
41947
  /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { className: "ods-expression-field__editor-head", children: [
41902
- /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("code", { children: label }),
41903
- /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("button", { type: "button", className: "ods-expression-field__editor-link", onClick: () => setRaw(raw === null ? formatCall(name, args) : null), children: raw === null ? "Edit as text" : "Back to fields" })
41904
- ] }),
41905
- raw === null ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { className: "ods-expression-field__editor-rows", children: [
41906
- args.map((arg, idx) => (
41907
- // eslint-disable-next-line react/no-array-index-key
41908
- /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("label", { className: "ods-expression-field__editor-row", children: [
41909
- /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { children: names[idx] ?? `argument ${idx + 1}` }),
41910
- /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41911
- "input",
41912
- {
41913
- value: arg,
41914
- placeholder: "value, or drag one in",
41915
- onChange: (e) => setArg(idx, e.target.value),
41916
- onDragOver: (e) => {
41917
- if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
41918
- },
41919
- onDrop: dropInto(idx)
41920
- }
41921
- )
41922
- ] }, idx)
41923
- )),
41948
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("nav", { className: "ods-expression-field__editor-crumbs", "aria-label": "Nested functions", children: crumbs.map((crumb, i) => /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { children: [
41949
+ i > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "aria-hidden": "true", children: " \u203A " }),
41950
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41951
+ "button",
41952
+ {
41953
+ type: "button",
41954
+ disabled: i === crumbs.length - 1,
41955
+ onClick: () => setPath(crumb.path),
41956
+ children: crumb.label
41957
+ }
41958
+ )
41959
+ ] }, crumb.path.join(".") || "root")) }),
41924
41960
  /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41925
41961
  "button",
41926
41962
  {
41927
41963
  type: "button",
41928
41964
  className: "ods-expression-field__editor-link",
41929
- onClick: () => setArgs((prev) => [...prev, ""]),
41930
- children: "+ argument"
41965
+ onClick: () => setRawMode((r) => !r),
41966
+ children: rawMode ? "Back to fields" : "Edit as text"
41931
41967
  }
41932
41968
  )
41933
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41969
+ ] }),
41970
+ rawMode ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
41934
41971
  "textarea",
41935
41972
  {
41936
41973
  className: "ods-expression-field__editor-raw",
41937
- value: raw,
41974
+ value: draft,
41938
41975
  rows: 3,
41939
- onChange: (e) => setRaw(e.target.value)
41976
+ "aria-label": "Expression",
41977
+ onChange: (e) => setDraft(e.target.value)
41940
41978
  }
41941
- ),
41979
+ ) : /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { className: "ods-expression-field__editor-rows", children: [
41980
+ args.map((arg, index) => {
41981
+ const kind = argumentKind(arg);
41982
+ const rowLabel = names[index] ?? `argument ${index + 1}`;
41983
+ const nested = kind === "call" ? parseCall(arg) : void 0;
41984
+ return (
41985
+ // eslint-disable-next-line react/no-array-index-key
41986
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { className: "ods-expression-field__editor-row", children: [
41987
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { id: `arg-${index}-label`, children: rowLabel }),
41988
+ nested ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
41989
+ "div",
41990
+ {
41991
+ className: "ods-expression-field__editor-nested",
41992
+ onDragOver: (e) => {
41993
+ if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
41994
+ },
41995
+ onDrop: dropInto(index),
41996
+ children: [
41997
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("code", { children: argSummary(arg, nameOf) }),
41998
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { children: [
41999
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("button", { type: "button", onClick: () => setPath([...path, index]), children: "Open" }),
42000
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("button", { type: "button", onClick: () => setArg(index, ""), "aria-label": `Clear ${rowLabel}`, children: "Clear" })
42001
+ ] })
42002
+ ]
42003
+ }
42004
+ ) : kind === "reference" ? (
42005
+ // A reference is a value from somewhere else — named, never
42006
+ // its raw `ods://…` path, here as much as in the field.
42007
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
42008
+ "div",
42009
+ {
42010
+ className: "ods-expression-field__editor-ref",
42011
+ onDragOver: (e) => {
42012
+ if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
42013
+ },
42014
+ onDrop: dropInto(index),
42015
+ children: [
42016
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
42017
+ "span",
42018
+ {
42019
+ className: "ods-expression-field__pill",
42020
+ title: arg,
42021
+ "aria-labelledby": `arg-${index}-label`,
42022
+ children: labelFor(arg.startsWith("ods://") ? `{{${arg}}}` : arg)
42023
+ }
42024
+ ),
42025
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("button", { type: "button", onClick: () => setArg(index, ""), "aria-label": `Clear ${rowLabel}`, children: "Clear" })
42026
+ ]
42027
+ }
42028
+ )
42029
+ ) : /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
42030
+ "input",
42031
+ {
42032
+ "aria-labelledby": `arg-${index}-label`,
42033
+ value: arg,
42034
+ placeholder: 'a value, "text", or drag one in',
42035
+ "data-kind": kind,
42036
+ onChange: (e) => setArg(index, e.target.value),
42037
+ onDragOver: (e) => {
42038
+ if (e.dataTransfer.types.includes("application/x-fx-insert")) e.preventDefault();
42039
+ },
42040
+ onDrop: dropInto(index)
42041
+ }
42042
+ )
42043
+ ] }, index)
42044
+ );
42045
+ }),
42046
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
42047
+ "button",
42048
+ {
42049
+ type: "button",
42050
+ className: "ods-expression-field__editor-link",
42051
+ onClick: () => setDraft((d) => {
42052
+ const at = callAt(d, path);
42053
+ if (!at) return d;
42054
+ const next = [...at.args, '""'];
42055
+ return path.length === 0 ? formatCall(at.name, next) : replaceArgument(d, path, `${at.name}(${next.join(", ")})`);
42056
+ }),
42057
+ children: "+ argument"
42058
+ }
42059
+ )
42060
+ ] }),
41942
42061
  /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { className: "ods-expression-field__editor-foot", children: [
41943
42062
  /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("button", { type: "button", onClick: onCancel, children: "Cancel" }),
41944
42063
  /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
@@ -41946,11 +42065,7 @@ function CallEditor({
41946
42065
  {
41947
42066
  type: "button",
41948
42067
  className: "ods-expression-field__editor-primary",
41949
- onClick: () => {
41950
- if (raw === null) return onApply(args);
41951
- const parsed = parseCall(raw);
41952
- onApply(parsed ? parsed.args : splitArguments(raw));
41953
- },
42068
+ onClick: () => onApply(draft),
41954
42069
  children: "Apply"
41955
42070
  }
41956
42071
  )