@oomol-lab/open-flow 0.1.0-beta.76 → 0.1.0-beta.78

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.
Files changed (74) hide show
  1. package/README.md +3 -0
  2. package/dist/browser/{ContentIcon-Cm1hbVzW.js → ContentIcon-CMn0c-kl.js} +99 -6
  3. package/dist/browser/{FlowCanvas-NzKtla_c.js → FlowCanvas-BQGBcfoL.js} +1709 -613
  4. package/dist/browser/{createResourceDialog-BgdedQqu.js → createResourceDialog-DCGxfKFM.js} +63 -57
  5. package/dist/browser/{dialog-aSElFFw2.js → dialog-WzR4CRFH.js} +76 -77
  6. package/dist/browser/{exportSvg-Dcz4HTo_.js → exportSvg-CYwyYiuH.js} +2 -2
  7. package/dist/browser/{flowChanges-NZyS7HSp.js → flowChanges-Bz4dbDN_.js} +6875 -11091
  8. package/dist/browser/{flowWorkspace-Bl0SDehy.js → flowWorkspace-BI6L6a4r.js} +1415 -3037
  9. package/dist/browser/licenses.md +1 -1
  10. package/dist/browser/preview.css +619 -462
  11. package/dist/browser/preview.js +9016 -14956
  12. package/dist/browser/theme.css +4 -2
  13. package/dist/browser/{tooltip-3XMK9jkr.js → tooltip-BDcVTNpu.js} +65 -2
  14. package/dist/browser/{typeScriptSession-C9sBGOKZ.js → typeScriptSession-CRoezJPN.js} +1 -1
  15. package/dist/browser/ui.css +112 -24
  16. package/dist/browser/ui.js +3 -2
  17. package/dist/browser/workbench.css +10020 -9842
  18. package/dist/browser/workbench.d.ts +5 -2
  19. package/dist/browser/workbench.js +2382 -2668
  20. package/dist/browser/{workbenchSelect-DBGP7Y4Z.js → workbenchSelect-DtAd0zc4.js} +2 -2
  21. package/dist/command/index.js +48 -48
  22. package/dist/common/authoring.d.ts +4 -4
  23. package/dist/common/authoringExamples.d.ts +3 -2
  24. package/dist/common/authoringSchema.d.ts +15 -4
  25. package/dist/common/control-api-conformance.js +155 -15
  26. package/dist/common/control-api-errors.d.ts +12 -0
  27. package/dist/common/control-api.d.ts +39 -2
  28. package/dist/common/control-api.js +180 -37
  29. package/dist/common/control-requests.d.ts +23 -3
  30. package/dist/common/control-requests.js +141 -14
  31. package/dist/common/engine-contract.d.ts +3 -2
  32. package/dist/common/flow-authoring.js +47 -7
  33. package/dist/common/flow-change-schema.d.ts +1 -1
  34. package/dist/common/flow-change.d.ts +2 -2
  35. package/dist/common/flow-change.js +48 -8
  36. package/dist/common/flow-encoding.js +47 -7
  37. package/dist/common/flow-semantics.js +86 -8
  38. package/dist/common/flow-state.d.ts +100 -0
  39. package/dist/common/flow-state.js +5794 -0
  40. package/dist/common/mcp.d.ts +96 -3
  41. package/dist/common/mcp.js +158 -13
  42. package/dist/common/run-events.js +19 -8
  43. package/dist/common/runtime-contract.d.ts +14 -0
  44. package/dist/common/runtime-contract.js +124 -17
  45. package/dist/common/runtime-nodejs-compat.js +11 -12
  46. package/dist/common/scheduler-node-execution.d.ts +1 -0
  47. package/dist/common/scheduler.d.ts +2 -1
  48. package/dist/common/scheduler.js +95 -40
  49. package/dist/common/state-conformance.d.ts +16 -0
  50. package/dist/common/tags.d.ts +4 -0
  51. package/dist/index.d.ts +11 -0
  52. package/package.json +5 -1
  53. package/src/control/common/api.ts +101 -11
  54. package/src/control/common/authoring.ts +7 -1
  55. package/src/control/common/authoringExamples.ts +9 -0
  56. package/src/control/common/authoringSchema.ts +18 -12
  57. package/src/control/common/errors.ts +6 -0
  58. package/src/control/common/flowDecoders.ts +1 -0
  59. package/src/control/common/mcp.ts +16 -0
  60. package/src/control/common/requests.ts +16 -2
  61. package/src/control/common/tags.ts +20 -0
  62. package/src/execution/common/events.ts +22 -7
  63. package/src/execution/common/node-execution.ts +3 -0
  64. package/src/execution/common/scheduler.ts +29 -13
  65. package/src/flow/common/change.ts +2 -1
  66. package/src/flow/common/changeSchema.ts +11 -1
  67. package/src/flow/common/errorHandling.ts +1 -1
  68. package/src/flow/common/semantics.ts +27 -1
  69. package/src/runtime/common/engineContract.ts +6 -3
  70. package/src/runtime/common/nodejsGuest.generated.json +11 -12
  71. package/src/runtime/common/runtime.ts +122 -7
  72. package/src/state/common/conformance.ts +81 -0
  73. package/src/state/common/state.ts +141 -0
  74. package/src/types/index.ts +11 -0
@@ -1,8 +1,8 @@
1
1
  import { o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
2
- import { $ as ko_default, B as MenuPopup, C as DropdownMenuContent, D as DropdownMenuRadioGroup, E as DropdownMenuLabel, F as findRootOwnerId, G as MenuRootContext, H as MenuGroup, J as waitBranchDescription, K as useMenuRootContext, L as MenuRoot, N as DropdownMenuTrigger, O as DropdownMenuRadioItem, Q as ru_default, R as MenuPositioner, S as DropdownMenuCheckboxItem, T as DropdownMenuItem, U as ContextMenuRootContext, V as MenuItem, W as useContextMenuRootContext, X as zh_TW_default, Z as zh_CN_default, _ as NativeScrollArea, at as Checkbox, d as PopoverContent, et as ja_default, g as PopoverTrigger, h as PopoverTitle, k as DropdownMenuSeparator, l as wrapLayout, nt as en_default, q as uiLocales, rt as I18n, st as IconThemeContext, t as ContentIcon, tt as fr_default, u as Popover, v as ScrollArea, w as DropdownMenuGroup, x as DropdownMenu, z as MenuPortal } from "./ContentIcon-Cm1hbVzW.js";
2
+ import { $ as zh_CN_default, A as DropdownMenuSeparator, B as MenuPositioner, C as DropdownMenuCheckboxItem, D as DropdownMenuLabel, E as DropdownMenuItem, F as isElementDisabled, G as ContextMenuRootContext, H as MenuPopup, I as findRootOwnerId, J as useMenuRootContext, K as useContextMenuRootContext, L as CompositeItem, O as DropdownMenuRadioGroup, P as DropdownMenuTrigger, Q as zh_TW_default, S as DropdownMenu, T as DropdownMenuGroup, U as MenuItem, V as MenuPortal, W as MenuGroup, X as waitBranchDescription, Y as uiLocales, _ as PopoverTrigger, at as I18n, ct as useAriaLabelledBy, d as Popover, et as ru_default, f as PopoverContent, g as PopoverTitle, it as en_default, k as DropdownMenuRadioItem, l as wrapLayout, lt as useFieldItemContext, nt as ja_default, q as MenuRootContext, rt as fr_default, st as Checkbox, t as ContentIcon, tt as ko_default, u as canvasDirection, ut as IconThemeContext, v as NativeScrollArea, w as DropdownMenuContent, y as ScrollArea, z as MenuRoot } from "./ContentIcon-CMn0c-kl.js";
3
3
  import { a as derive, c as strictEqual, i as compute, l as val, n as attachSetter, r as combine, s as readonlyVal } from "./dist-bO8nvHFH.js";
4
4
  import { c as useLang, i as isString, l as useTranslate, n as isBoolean, o as I18nProvider, r as isPlainObject, t as isArray$1, u as useVal } from "./dist-BFmpkX4P.js";
5
- import { $t as require_with_selector, A as string, An as ownerDocument, C as literal, Cr as useRenderElement, Mn as createLucideIcon, Sr as clsx, T as number, Tn as getTarget, Un as cancelOpen, Vn as createChangeEventDetails, an as useTimeout, ar as triggerPress, bn as stopEvent$1, br as cn$1, fr as useId$1, ft as pressableTriggerOpenStateMapping, i as TooltipTrigger, k as strictObject, n as TooltipContent, p as timeZoneOffsetMinutes, qt as addEventListener, r as TooltipProvider, t as Tooltip, vr as Button, wn as contains, y as discriminatedUnion } from "./tooltip-3XMK9jkr.js";
5
+ import { A as string, B as ARROW_LEFT, Bn as transitionStatusMapping, C as literal, Cr as cn$1, Dn as getTarget, Dr as EMPTY_ARRAY$1, En as contains, Er as useRenderElement, Fn as createLucideIcon, Fr as formatErrorMessage, G as HORIZONTAL_KEYS, H as ARROW_UP, J as SHIFT, K as HORIZONTAL_KEYS_WITH_EXTRA_KEYS, Kn as cancelOpen, L as ALL_KEYS, Lr as useIsoLayoutEffect, Mn as ownerDocument, Mr as useButton, Nn as useLabelableId, Nr as CompositeRootContext, Or as EMPTY_OBJECT, Q as scrollIntoViewIfNeeded, R as ARROW_DOWN, Sn as stopEvent$1, T as number, Tr as clsx, Un as useValueChanged, V as ARROW_RIGHT, Wn as createChangeEventDetails, X as VERTICAL_KEYS_WITH_EXTRA_KEYS, Y as VERTICAL_KEYS, Yt as addEventListener, Z as isNativeInput, _n as getMaxListIndex, _r as fieldValidityMapping, bn as isListIndexDisabled, br as useControlled, cr as triggerPress, ct as CompositeList, dr as useFormContext, fn as createGridCellMap, fr as useRegisterFieldControl, gn as getGridNavigatedIndex, gt as serializeValue, hn as getGridCellIndices, hr as useId$1, i as TooltipTrigger, jr as useMergedRefs, k as strictObject, kr as NOOP, mn as getGridCellIndexOfCorner, mr as useBaseUiId, n as TooltipContent, p as timeZoneOffsetMinutes, pn as findNonDisabledListIndex, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, q as MODIFIER_KEYS$1, r as TooltipProvider, rr as none$1, sn as useTimeout, st as useDirection, t as Tooltip, tn as require_with_selector, ur as useLabelableContext, vn as getMinListIndex, vr as visuallyHidden, xr as Button, y as discriminatedUnion, yn as isIndexOutOfListBounds, yr as visuallyHiddenInput, z as ARROW_KEYS, zr as useStableCallback } from "./tooltip-BDcVTNpu.js";
6
6
  import { r as resolveUiLanguage } from "./languages-gYzoQqCi.js";
7
7
  import * as React from "react";
8
8
  import reactExports, { Children, Suspense, createContext, forwardRef, isValidElement, lazy, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
@@ -20,6 +20,19 @@ var Zap = createLucideIcon("Zap", [["path", {
20
20
  key: "1xq2db"
21
21
  }]]);
22
22
  //#endregion
23
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/fieldset/root/FieldsetRootContext.js
24
+ var FieldsetRootContext = /*#__PURE__*/ React.createContext({
25
+ legendId: void 0,
26
+ setLegendId: () => {},
27
+ disabled: void 0
28
+ });
29
+ if (process.env.NODE_ENV !== "production") FieldsetRootContext.displayName = "FieldsetRootContext";
30
+ function useFieldsetRootContext(optional = false) {
31
+ const context = React.useContext(FieldsetRootContext);
32
+ if (!context && !optional) throw new Error(process.env.NODE_ENV !== "production" ? "Base UI: FieldsetRootContext is missing. Fieldset parts must be placed within <Fieldset.Root>." : formatErrorMessage(86));
33
+ return context;
34
+ }
35
+ //#endregion
23
36
  //#region ../../node_modules/.bun/@dagrejs+dagre@3.1.1/node_modules/@dagrejs/dagre/dist/dagre.esm.js
24
37
  var Te = Object.defineProperty;
25
38
  var In = (e, n, t) => n in e ? Te(e, n, {
@@ -2549,6 +2562,13 @@ var NODE_TYPE = /* @__PURE__ */ function(NODE_TYPE) {
2549
2562
  //#endregion
2550
2563
  //#region src/canvas/browser/base/canvas.ts
2551
2564
  var CANVAS_CLASSNAME = "open-flow-canvas";
2565
+ function minimumCanvasCardWidth(direction, branchCount) {
2566
+ return direction === "vertical" && branchCount > 0 ? Math.max(320, branchCount * 96 + (branchCount - 1) * 6 + 16 + 2) : 320;
2567
+ }
2568
+ function canvasCardWidth(direction, branchCount, preferredWidth) {
2569
+ const minimum = minimumCanvasCardWidth(direction, branchCount);
2570
+ return direction === "vertical" && preferredWidth != null && Number.isFinite(preferredWidth) ? Math.max(minimum, preferredWidth) : minimum;
2571
+ }
2552
2572
  /** Marks an area that React Flow can drag. */
2553
2573
  var NODE_HANDLE_CLASSNAME = "open-flow-canvas-node-handle";
2554
2574
  var DEFAULT_POSITION = /* @__PURE__ */ Object.freeze({
@@ -2701,7 +2721,7 @@ function createNodeInteraction(initial) {
2701
2721
  }
2702
2722
  //#endregion
2703
2723
  //#region src/canvas/browser/stores/node/commentNode.store.ts
2704
- var minimumSize = {
2724
+ var COMMENT_MINIMUM_SIZE = {
2705
2725
  width: 350,
2706
2726
  height: 160
2707
2727
  };
@@ -2719,8 +2739,8 @@ var CommentNodeStore = class CommentNodeStore {
2719
2739
  this.nodeType = NODE_TYPE.CommentNode;
2720
2740
  this.resize = ({ width, height }) => {
2721
2741
  this.$$.size.set({
2722
- width: Math.max(minimumSize.width, width),
2723
- height: Math.max(minimumSize.height, height)
2742
+ width: Math.max(COMMENT_MINIMUM_SIZE.width, width),
2743
+ height: Math.max(COMMENT_MINIMUM_SIZE.height, height)
2724
2744
  });
2725
2745
  };
2726
2746
  this.togglePreview = () => {
@@ -3142,9 +3162,16 @@ var FLOW_RUN_STATUS = /* @__PURE__ */ function(FLOW_RUN_STATUS) {
3142
3162
  //#endregion
3143
3163
  //#region src/canvas/browser/stores/canvas/canvas.store.ts
3144
3164
  var CanvasStore = class {
3165
+ get canChangeDirection() {
3166
+ return this.#callbacks.onChangeDirection != null;
3167
+ }
3145
3168
  get canChangeNodeContentHidden() {
3146
3169
  return this.#callbacks.onChangeNodeContentHidden != null;
3147
3170
  }
3171
+ get canChangeNodeWidth() {
3172
+ return this.#callbacks.onChangeNodeWidth != null;
3173
+ }
3174
+ #modelDirection;
3148
3175
  #connections;
3149
3176
  #callbacks;
3150
3177
  #entries;
@@ -3160,32 +3187,54 @@ var CanvasStore = class {
3160
3187
  this.ignoreNodes = (nodeIds, ignored) => {
3161
3188
  if (this.$.editable.value) this.#callbacks.onIgnoreNodes?.(nodeIds, ignored);
3162
3189
  };
3190
+ this.changeDirection = (direction) => {
3191
+ if (!this.$.editable.value || !this.canChangeDirection || this.$.changingDirection.value || this.$.direction.value === direction) return;
3192
+ this.layoutComplete = false;
3193
+ this.layoutMeasurementAttempts = 0;
3194
+ this.$$.changingDirection.set(true);
3195
+ this.$$.direction.set(direction);
3196
+ };
3197
+ this.changeNodeWidth = async (nodeId, width, position) => {
3198
+ const node = this.$.nodes.get(nodeId);
3199
+ if (!this.$.editable.value || this.$.changingDirection.value || this.$.direction.value !== "vertical" || node?.content$.value.kind !== "condition") return false;
3200
+ try {
3201
+ return await this.#callbacks.onChangeNodeWidth?.(nodeId, width, position) ?? false;
3202
+ } catch (error) {
3203
+ console.error("Failed to save node width.", error);
3204
+ return false;
3205
+ }
3206
+ };
3163
3207
  this.changeNodeContentHidden = (nodeId, hidden) => {
3164
3208
  if (this.$.editable.value) this.#callbacks.onChangeNodeContentHidden?.(nodeId, hidden);
3165
3209
  };
3166
3210
  this.disposed = false;
3167
3211
  this.layoutMeasurementAttempts = 0;
3212
+ this.#modelDirection = "horizontal";
3168
3213
  this.pendingNodeDeletes = /* @__PURE__ */ new Set();
3169
3214
  this.pendingDisconnects = /* @__PURE__ */ new Map();
3170
3215
  this.#entries = /* @__PURE__ */ new Map();
3171
3216
  this.#modelPositions = /* @__PURE__ */ new Map();
3172
3217
  this.#selectedNodeIds = /* @__PURE__ */ new Set();
3173
3218
  this.completeLayout = (availableWidth) => {
3174
- if (this.layoutComplete) return true;
3219
+ if (this.disposed || this.layoutComplete) return true;
3175
3220
  const nodes = this.allLayoutNodes();
3176
- if (nodes.length === 0) return true;
3221
+ if (nodes.length === 0 && !this.$.changingDirection.value) return true;
3177
3222
  for (const node of nodes) {
3178
3223
  const measured = node.$.measured.value;
3179
3224
  if (!measured?.width || !measured.height) {
3180
3225
  if (this.layoutMeasurementAttempts++ < 5) return false;
3181
3226
  this.layoutMeasurementAttempts = 0;
3182
3227
  this.layoutComplete = true;
3228
+ this.#restoreDirection();
3183
3229
  return true;
3184
3230
  }
3185
3231
  }
3186
- this.doRelayout(availableWidth);
3232
+ const positions = this.layoutPositions(nodes, availableWidth);
3233
+ this.applyPositions(positions);
3187
3234
  this.layoutMeasurementAttempts = 0;
3188
3235
  this.layoutComplete = true;
3236
+ if (this.$.changingDirection.value) this.#saveDirection(positions);
3237
+ else this.#callbacks.onMoveNodes(positions);
3189
3238
  return "relayout";
3190
3239
  };
3191
3240
  this.onBeforeDelete = async () => this.$.editable.value;
@@ -3216,6 +3265,7 @@ var CanvasStore = class {
3216
3265
  });
3217
3266
  };
3218
3267
  this.onRelayout = (availableWidth) => {
3268
+ if (this.$.changingDirection.value) return;
3219
3269
  try {
3220
3270
  this.doRelayout(availableWidth);
3221
3271
  } catch (e) {
@@ -3328,6 +3378,8 @@ var CanvasStore = class {
3328
3378
  miniMapExpanded: this.dispose.add(val()),
3329
3379
  viewport,
3330
3380
  interactiveMode: interactiveMode$ ?? this.dispose.add(val("touchpad")),
3381
+ direction: this.dispose.add(val(canvasDirection(model.direction))),
3382
+ changingDirection: this.dispose.add(val(false)),
3331
3383
  nodes,
3332
3384
  commentNodes
3333
3385
  };
@@ -3353,6 +3405,22 @@ var CanvasStore = class {
3353
3405
  };
3354
3406
  this.#syncModel(model);
3355
3407
  }
3408
+ async #saveDirection(positions) {
3409
+ try {
3410
+ if (!await this.#callbacks.onChangeDirection?.(this.$.direction.value, positions) && !this.disposed) this.#restoreDirection();
3411
+ } catch (error) {
3412
+ if (!this.disposed) this.#restoreDirection();
3413
+ console.error("Failed to save canvas direction.", error);
3414
+ } finally {
3415
+ if (!this.disposed) this.$$.changingDirection.set(false);
3416
+ }
3417
+ }
3418
+ #restoreDirection() {
3419
+ if (!this.$.changingDirection.value) return;
3420
+ this.$$.direction.set(this.#modelDirection);
3421
+ this.applyPositions(Object.fromEntries(this.#modelPositions));
3422
+ this.$$.changingDirection.set(false);
3423
+ }
3356
3424
  allLayoutNodes() {
3357
3425
  return [...this.$.nodes.values()];
3358
3426
  }
@@ -3378,10 +3446,31 @@ var CanvasStore = class {
3378
3446
  };
3379
3447
  }
3380
3448
  doRelayout(availableWidth) {
3381
- const nodes = this.allLayoutNodes();
3449
+ const selected = this.$.selectedNodes.value.length > 1 ? this.$.selectedNodes.value : [];
3450
+ const nodes = selected.length > 0 ? selected.filter(NodeStore.is) : this.allLayoutNodes();
3451
+ if (nodes.length === 0) return;
3452
+ let positions = this.layoutPositions(nodes, availableWidth);
3453
+ if (selected.length > 0) {
3454
+ const offsetX = Math.min(...nodes.map((node) => node.$.position.value.x)) - Math.min(...Object.values(positions).map((position) => position.x));
3455
+ const offsetY = Math.min(...nodes.map((node) => node.$.position.value.y)) - Math.min(...Object.values(positions).map((position) => position.y));
3456
+ positions = Object.fromEntries(Object.entries(positions).map(([id, position]) => [id, {
3457
+ x: position.x + offsetX,
3458
+ y: position.y + offsetY
3459
+ }]));
3460
+ }
3461
+ this.applyPositions(positions);
3462
+ this.#callbacks.onMoveNodes(positions);
3463
+ }
3464
+ applyPositions(positions) {
3465
+ for (const node of this.allLayoutNodes()) {
3466
+ const position = positions[node.nodeId];
3467
+ if (position) node.$$.position.set(position);
3468
+ }
3469
+ }
3470
+ layoutPositions(nodes, availableWidth) {
3382
3471
  const g = new ie.Graph().setDefaultEdgeLabel(() => ({}));
3383
3472
  g.setGraph({
3384
- rankdir: "LR",
3473
+ rankdir: this.$.direction.value === "vertical" ? "TB" : "LR",
3385
3474
  ranksep: 80
3386
3475
  });
3387
3476
  const singles = /* @__PURE__ */ new Set();
@@ -3394,13 +3483,34 @@ var CanvasStore = class {
3394
3483
  });
3395
3484
  }
3396
3485
  for (const rfEdge of this.$.rfEdges.value) {
3486
+ if (!g.hasNode(rfEdge.source) || !g.hasNode(rfEdge.target)) continue;
3397
3487
  singles.delete(rfEdge.source);
3398
3488
  singles.delete(rfEdge.target);
3399
3489
  g.setEdge(rfEdge.source, rfEdge.target);
3400
3490
  }
3401
3491
  if (singles.size > 0) for (const list of cluster([...singles], 10)) for (let i = 0; i < list.length - 1; i++) g.setEdge(list[i], list[i + 1]);
3402
- Oe(g);
3403
- const positions = wrapLayout(nodes.map((node) => {
3492
+ const constraints = [];
3493
+ const ordering = new ie.Graph();
3494
+ for (const node of nodes) {
3495
+ const content = node.content$.value;
3496
+ if (content.kind !== "condition" && content.kind !== "approval" && content.kind !== "wait") continue;
3497
+ const targets = [...new Set(content.outputs.flatMap((port) => "handle" in port ? this.#connections.value.filter((edge) => edge.source === node.nodeId && edge.sourceHandle === `$branch:${port.handle}`).flatMap((edge) => {
3498
+ const target = this.$.nodes.get(edge.target);
3499
+ return target && g.hasNode(target.rfNodeId) ? [target.rfNodeId] : [];
3500
+ }) : []))];
3501
+ for (let index = 1; index < targets.length; index++) {
3502
+ const left = targets[index - 1];
3503
+ const right = targets[index];
3504
+ ordering.setEdge(left, right);
3505
+ if (ie.alg.isAcyclic(ordering)) constraints.push({
3506
+ left,
3507
+ right
3508
+ });
3509
+ else ordering.removeEdge(left, right);
3510
+ }
3511
+ }
3512
+ Oe(g, { constraints });
3513
+ const layoutNodes = nodes.map((node) => {
3404
3514
  const { x, y, width, height, rank } = g.node(node.rfNodeId);
3405
3515
  return {
3406
3516
  id: node.nodeId,
@@ -3410,9 +3520,11 @@ var CanvasStore = class {
3410
3520
  width,
3411
3521
  height
3412
3522
  };
3413
- }), availableWidth);
3414
- for (const node of nodes) node.$$.position.set(positions[node.nodeId]);
3415
- this.#callbacks.onMoveNodes(positions);
3523
+ });
3524
+ return this.$.direction.value === "horizontal" ? wrapLayout(layoutNodes, availableWidth) : Object.fromEntries(layoutNodes.map(({ id, x, y }) => [id, {
3525
+ x,
3526
+ y
3527
+ }]));
3416
3528
  }
3417
3529
  doRemoveNodes(nodes) {
3418
3530
  if (this.disposed || !nodes?.size) return;
@@ -3459,6 +3571,8 @@ var CanvasStore = class {
3459
3571
  this.#syncSelection(selectedNodeIds);
3460
3572
  }
3461
3573
  #syncModel(model) {
3574
+ this.#modelDirection = canvasDirection(model.direction);
3575
+ if (!this.$.changingDirection.value) this.$$.direction.set(this.#modelDirection);
3462
3576
  const runStatus = model.runStatus == "running" ? FLOW_RUN_STATUS.Running : FLOW_RUN_STATUS.Idle;
3463
3577
  if (this.#runStatus.value != runStatus) this.#runStatus.set(runStatus);
3464
3578
  if (this.#modelViewport == null || this.#modelViewport.x != model.viewport.x || this.#modelViewport.y != model.viewport.y || this.#modelViewport.zoom != model.viewport.zoom) {
@@ -10378,7 +10492,7 @@ function useReactFlow() {
10378
10492
  };
10379
10493
  }, [viewportInitialized]);
10380
10494
  }
10381
- var selected$1 = (item) => item.selected;
10495
+ var selected$2 = (item) => item.selected;
10382
10496
  var win$1 = typeof window !== "undefined" ? window : void 0;
10383
10497
  /**
10384
10498
  * Hook for handling global key events.
@@ -10394,8 +10508,8 @@ function useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode }) {
10394
10508
  if (deleteKeyPressed) {
10395
10509
  const { edges, nodes } = store.getState();
10396
10510
  deleteElements({
10397
- nodes: nodes.filter(selected$1),
10398
- edges: edges.filter(selected$1)
10511
+ nodes: nodes.filter(selected$2),
10512
+ edges: edges.filter(selected$2)
10399
10513
  });
10400
10514
  store.setState({ nodesSelectionActive: false });
10401
10515
  }
@@ -14583,14 +14697,21 @@ function connectionNodeBounds(node) {
14583
14697
  height: node.measured.height
14584
14698
  };
14585
14699
  }
14586
- /** Return connections offset both side turns and horizontal lanes by their endpoint distance. */
14700
+ /** Align arrows with their ports and route returns outside both cards. */
14587
14701
  function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
14588
- const { sourceX, sourceY, targetX, targetY, sourcePosition = Position.Bottom, targetPosition = Position.Top } = params;
14589
- const reverse = sourcePosition === Position.Left && targetPosition === Position.Right;
14590
- const horizontal = sourcePosition === Position.Right && targetPosition === Position.Left || reverse;
14702
+ const { sourcePosition = Position.Bottom, targetPosition = Position.Top } = params;
14703
+ const vertical = sourcePosition === Position.Bottom && targetPosition === Position.Top || sourcePosition === Position.Top && targetPosition === Position.Bottom;
14704
+ const reverse = sourcePosition === Position.Left && targetPosition === Position.Right || sourcePosition === Position.Top && targetPosition === Position.Bottom;
14705
+ const horizontal = sourcePosition === Position.Right && targetPosition === Position.Left || sourcePosition === Position.Left && targetPosition === Position.Right;
14706
+ const primary = (x, y) => vertical ? y : x;
14707
+ const cross = (x, y) => vertical ? x : y;
14708
+ const sourceX = primary(params.sourceX, params.sourceY);
14709
+ const sourceY = cross(params.sourceX, params.sourceY);
14710
+ const targetX = primary(params.targetX, params.targetY);
14711
+ const targetY = cross(params.targetX, params.targetY);
14591
14712
  const outputX = reverse ? targetX : sourceX;
14592
14713
  const inputX = reverse ? sourceX : targetX;
14593
- if (!horizontal || outputX < inputX) {
14714
+ if (!horizontal && !vertical) {
14594
14715
  const [path, x, y] = getBezierPath(params);
14595
14716
  return [
14596
14717
  path,
@@ -14598,8 +14719,26 @@ function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
14598
14719
  y
14599
14720
  ];
14600
14721
  }
14601
- const outputBounds = reverse ? targetBounds : sourceBounds;
14602
- const inputBounds = reverse ? sourceBounds : targetBounds;
14722
+ if (outputX < inputX) {
14723
+ const [path, x, y] = vertical ? getSmoothStepPath({
14724
+ ...params,
14725
+ borderRadius: 16,
14726
+ offset: Math.min(16, (inputX - outputX) / 4)
14727
+ }) : getBezierPath(params);
14728
+ return [
14729
+ path,
14730
+ x,
14731
+ y
14732
+ ];
14733
+ }
14734
+ const axes = (bounds) => bounds && (vertical ? {
14735
+ x: bounds.y,
14736
+ y: bounds.x,
14737
+ width: bounds.height,
14738
+ height: bounds.width
14739
+ } : bounds);
14740
+ const outputBounds = axes(reverse ? targetBounds : sourceBounds);
14741
+ const inputBounds = axes(reverse ? sourceBounds : targetBounds);
14603
14742
  const outputY = reverse ? targetY : sourceY;
14604
14743
  const inputY = reverse ? sourceY : targetY;
14605
14744
  const minimumOffset = 40;
@@ -14643,7 +14782,10 @@ function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
14643
14782
  x: inputX,
14644
14783
  y: inputY
14645
14784
  }
14646
- ].filter((point, index, all) => index === 0 || point.x !== all[index - 1].x || point.y !== all[index - 1].y);
14785
+ ].filter((point, index, all) => index === 0 || point.x !== all[index - 1].x || point.y !== all[index - 1].y).map((point) => vertical ? {
14786
+ x: point.y,
14787
+ y: point.x
14788
+ } : point);
14647
14789
  if (reverse) points.reverse();
14648
14790
  const radius = 16;
14649
14791
  let path = `M ${points[0].x} ${points[0].y}`;
@@ -14658,10 +14800,11 @@ function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
14658
14800
  path += ` Q ${corner.x} ${corner.y} ${corner.x + (next.x - corner.x) * r / after} ${corner.y + (next.y - corner.y) * r / after}`;
14659
14801
  }
14660
14802
  const end = points.at(-1);
14803
+ const middle = (left + right) / 2;
14661
14804
  return [
14662
14805
  `${path} L ${end.x} ${end.y}`,
14663
- (left + right) / 2,
14664
- laneY
14806
+ vertical ? laneY : middle,
14807
+ vertical ? middle : laneY
14665
14808
  ];
14666
14809
  }
14667
14810
  //#endregion
@@ -14769,43 +14912,51 @@ function BasicEdge(props) {
14769
14912
  ] });
14770
14913
  }
14771
14914
  var NodeLayout_module_default = {
14772
- outerContainer: "NodeLayout_outerContainer_198c4",
14773
- enter: "NodeLayout_enter_198c4",
14774
- "node-enter": "NodeLayout_node-enter_198c4",
14775
- skipOuter: "NodeLayout_skipOuter_198c4",
14776
- skip: "NodeLayout_skip_198c4",
14777
- offsetContainer: "NodeLayout_offsetContainer_198c4",
14778
- container: "NodeLayout_container_198c4",
14779
- cardContainer: "NodeLayout_cardContainer_198c4",
14780
- triggerIcon: "NodeLayout_triggerIcon_198c4",
14781
- compact: "NodeLayout_compact_198c4",
14782
- executionHead: "NodeLayout_executionHead_198c4",
14783
- executionBranch: "NodeLayout_executionBranch_198c4",
14784
- branchRow: "NodeLayout_branchRow_198c4",
14785
- branchName: "NodeLayout_branchName_198c4",
14786
- branchRule: "NodeLayout_branchRule_198c4",
14787
- branchGroup: "NodeLayout_branchGroup_198c4",
14788
- branchExpression: "NodeLayout_branchExpression_198c4",
14789
- branchOperandIcon: "NodeLayout_branchOperandIcon_198c4",
14790
- branchArrow: "NodeLayout_branchArrow_198c4",
14791
- executionHandle: "NodeLayout_executionHandle_198c4",
14792
- connected: "NodeLayout_connected_198c4",
14793
- connecting: "NodeLayout_connecting_198c4",
14794
- connectionHint: "NodeLayout_connectionHint_198c4",
14795
- inputHint: "NodeLayout_inputHint_198c4",
14796
- hintLeaving: "NodeLayout_hintLeaving_198c4",
14797
- "connection-hint-nudge": "NodeLayout_connection-hint-nudge_198c4",
14798
- compactContent: "NodeLayout_compactContent_198c4"
14915
+ outerContainer: "NodeLayout_outerContainer_d0397",
14916
+ enter: "NodeLayout_enter_d0397",
14917
+ "node-enter": "NodeLayout_node-enter_d0397",
14918
+ skipOuter: "NodeLayout_skipOuter_d0397",
14919
+ skip: "NodeLayout_skip_d0397",
14920
+ offsetContainer: "NodeLayout_offsetContainer_d0397",
14921
+ container: "NodeLayout_container_d0397",
14922
+ cardContainer: "NodeLayout_cardContainer_d0397",
14923
+ triggerIcon: "NodeLayout_triggerIcon_d0397",
14924
+ compact: "NodeLayout_compact_d0397",
14925
+ executionHead: "NodeLayout_executionHead_d0397",
14926
+ branchList: "NodeLayout_branchList_d0397",
14927
+ branchRow: "NodeLayout_branchRow_d0397",
14928
+ branchContent: "NodeLayout_branchContent_d0397",
14929
+ vertical: "NodeLayout_vertical_d0397",
14930
+ branchRule: "NodeLayout_branchRule_d0397",
14931
+ branchName: "NodeLayout_branchName_d0397",
14932
+ branchArrow: "NodeLayout_branchArrow_d0397",
14933
+ executionHandle: "NodeLayout_executionHandle_d0397",
14934
+ widthResize: "NodeLayout_widthResize_d0397",
14935
+ widthResizeLeft: "NodeLayout_widthResizeLeft_d0397",
14936
+ widthResizeRight: "NodeLayout_widthResizeRight_d0397",
14937
+ branchGroup: "NodeLayout_branchGroup_d0397",
14938
+ branchExpression: "NodeLayout_branchExpression_d0397",
14939
+ branchOperand: "NodeLayout_branchOperand_d0397",
14940
+ branchOperator: "NodeLayout_branchOperator_d0397",
14941
+ branchOperandIcon: "NodeLayout_branchOperandIcon_d0397",
14942
+ connected: "NodeLayout_connected_d0397",
14943
+ connecting: "NodeLayout_connecting_d0397",
14944
+ connectionHint: "NodeLayout_connectionHint_d0397",
14945
+ leftHint: "NodeLayout_leftHint_d0397",
14946
+ topHint: "NodeLayout_topHint_d0397",
14947
+ bottomHint: "NodeLayout_bottomHint_d0397",
14948
+ hintLeaving: "NodeLayout_hintLeaving_d0397",
14949
+ "connection-hint-nudge": "NodeLayout_connection-hint-nudge_d0397",
14950
+ compactContent: "NodeLayout_compactContent_d0397"
14799
14951
  };
14800
14952
  var handle_module_default = {
14801
- wrapper: "handle_wrapper_6698c",
14802
- left: "handle_left_6698c",
14803
- handle: "handle_handle_6698c",
14804
- right: "handle_right_6698c",
14805
- active: "handle_active_6698c",
14806
- hasData: "handle_hasData_6698c",
14807
- disabled: "handle_disabled_6698c",
14808
- pointerDown: "handle_pointerDown_6698c"
14953
+ wrapper: "handle_wrapper_c0108",
14954
+ handle: "handle_handle_c0108",
14955
+ left: "handle_left_c0108",
14956
+ right: "handle_right_c0108",
14957
+ top: "handle_top_c0108",
14958
+ bottom: "handle_bottom_c0108",
14959
+ selected: "handle_selected_c0108"
14809
14960
  };
14810
14961
  //#endregion
14811
14962
  //#region src/canvas/browser/components/handle.tsx
@@ -14815,14 +14966,12 @@ function Handle(props) {
14815
14966
  const Component = context?.Handle ?? HandleImpl;
14816
14967
  const position = props.position ?? (props.type === "input" ? "left" : "right");
14817
14968
  return /* @__PURE__ */ jsxs("div", {
14818
- className: clsx(handle_module_default.wrapper, position === "left" ? handle_module_default.left : handle_module_default.right, props.disabled && handle_module_default.disabled, props.onPointerDown && handle_module_default.pointerDown, props.className),
14819
- onPointerDown: props.onPointerDown,
14820
- style: props.kind && { ["--bg"]: `var(--edge-${props.kind})` },
14969
+ className: clsx(handle_module_default.wrapper, handle_module_default[position], props.selected && handle_module_default.selected, props.className),
14821
14970
  children: [/* @__PURE__ */ jsx(Component, {
14822
14971
  id: props.id,
14823
14972
  type: props.type === "input" ? "target" : "source",
14824
- position: position === "left" ? "left" : "right",
14825
- className: clsx(handle_module_default.handle, props.active && handle_module_default.active, props.hasData && handle_module_default.hasData),
14973
+ position,
14974
+ className: handle_module_default.handle,
14826
14975
  isConnectable: props.isConnectable,
14827
14976
  tabIndex: props.tabIndex,
14828
14977
  "aria-hidden": props.ariaHidden
@@ -14956,12 +15105,11 @@ var useNodeStore = () => {
14956
15105
  return context;
14957
15106
  };
14958
15107
  var CanvasNode_module_default = {
14959
- summary: "CanvasNode_summary_f29c7",
14960
- footer: "CanvasNode_footer_f29c7",
14961
- interval: "CanvasNode_interval_f29c7",
14962
- scheduleText: "CanvasNode_scheduleText_f29c7",
14963
- timezone: "CanvasNode_timezone_f29c7",
14964
- valueKey: "CanvasNode_valueKey_f29c7"
15108
+ summary: "CanvasNode_summary_27330",
15109
+ interval: "CanvasNode_interval_27330",
15110
+ scheduleText: "CanvasNode_scheduleText_27330",
15111
+ timezone: "CanvasNode_timezone_27330",
15112
+ valueKey: "CanvasNode_valueKey_27330"
14965
15113
  };
14966
15114
  //#endregion
14967
15115
  //#region ../../node_modules/.bun/cronstrue@3.25.0/node_modules/cronstrue/dist/cronstrue.js
@@ -18636,33 +18784,31 @@ function IconStack({ icons, count, limit = 3, size = "default", countClassName }
18636
18784
  });
18637
18785
  }
18638
18786
  var CanvasCard_module_default = {
18639
- card: "CanvasCard_card_77a06",
18640
- value: "CanvasCard_value_77a06",
18641
- preview: "CanvasCard_preview_77a06",
18642
- comment: "CanvasCard_comment_77a06",
18643
- selected: "CanvasCard_selected_77a06",
18644
- problem: "CanvasCard_problem_77a06",
18645
- runningBeam: "CanvasCard_runningBeam_77a06",
18646
- "running-beam": "CanvasCard_running-beam_77a06",
18647
- header: "CanvasCard_header_77a06",
18648
- icon: "CanvasCard_icon_77a06",
18649
- identity: "CanvasCard_identity_77a06",
18650
- indicator: "CanvasCard_indicator_77a06",
18651
- warning: "CanvasCard_warning_77a06",
18652
- danger: "CanvasCard_danger_77a06",
18653
- content: "CanvasCard_content_77a06",
18654
- footer: "CanvasCard_footer_77a06",
18655
- afterPreview: "CanvasCard_afterPreview_77a06",
18656
- branches: "CanvasCard_branches_77a06",
18657
- collapse: "CanvasCard_collapse_77a06",
18658
- collapseInner: "CanvasCard_collapseInner_77a06",
18659
- compactIdentity: "CanvasCard_compactIdentity_77a06",
18660
- compact: "CanvasCard_compact_77a06",
18661
- withBody: "CanvasCard_withBody_77a06",
18662
- compactContent: "CanvasCard_compactContent_77a06",
18663
- singleContent: "CanvasCard_singleContent_77a06",
18664
- subtitle: "CanvasCard_subtitle_77a06",
18665
- fill: "CanvasCard_fill_77a06"
18787
+ card: "CanvasCard_card_5d8a7",
18788
+ value: "CanvasCard_value_5d8a7",
18789
+ preview: "CanvasCard_preview_5d8a7",
18790
+ comment: "CanvasCard_comment_5d8a7",
18791
+ selected: "CanvasCard_selected_5d8a7",
18792
+ problem: "CanvasCard_problem_5d8a7",
18793
+ runningBeam: "CanvasCard_runningBeam_5d8a7",
18794
+ "running-beam": "CanvasCard_running-beam_5d8a7",
18795
+ header: "CanvasCard_header_5d8a7",
18796
+ icon: "CanvasCard_icon_5d8a7",
18797
+ identity: "CanvasCard_identity_5d8a7",
18798
+ indicator: "CanvasCard_indicator_5d8a7",
18799
+ warning: "CanvasCard_warning_5d8a7",
18800
+ danger: "CanvasCard_danger_5d8a7",
18801
+ content: "CanvasCard_content_5d8a7",
18802
+ branches: "CanvasCard_branches_5d8a7",
18803
+ collapse: "CanvasCard_collapse_5d8a7",
18804
+ collapseInner: "CanvasCard_collapseInner_5d8a7",
18805
+ compactIdentity: "CanvasCard_compactIdentity_5d8a7",
18806
+ compact: "CanvasCard_compact_5d8a7",
18807
+ withBody: "CanvasCard_withBody_5d8a7",
18808
+ compactContent: "CanvasCard_compactContent_5d8a7",
18809
+ singleContent: "CanvasCard_singleContent_5d8a7",
18810
+ subtitle: "CanvasCard_subtitle_5d8a7",
18811
+ fill: "CanvasCard_fill_5d8a7"
18666
18812
  };
18667
18813
  //#endregion
18668
18814
  //#region src/ui/browser/hooks.ts
@@ -18688,208 +18834,25 @@ function isEmptyReactNode(node) {
18688
18834
  if (isValidElement(node)) return false;
18689
18835
  return true;
18690
18836
  }
18691
- //#endregion
18692
- //#region src/canvas/browser/graph/Nodes/components/CanvasCard.tsx
18693
- var runningBeamPathLength = 1e3;
18694
- var runningBeamLength = 160;
18695
- var runningBeamLayerCount = 48;
18696
- var runningBeamPeakOpacity = .9;
18697
- var runningBeamLayers = Array.from({ length: runningBeamLayerCount }, (_, index) => {
18698
- const length = runningBeamLength * (1 - index / runningBeamLayerCount);
18699
- const gap = (runningBeamPathLength - length) / 2;
18700
- const previousOpacity = runningBeamPeakOpacity * Math.sin(index / runningBeamLayerCount * (Math.PI / 2)) ** 2;
18701
- const opacity = runningBeamPeakOpacity * Math.sin((index + 1) / runningBeamLayerCount * (Math.PI / 2)) ** 2;
18702
- return {
18703
- dash: `0 ${gap} ${length} ${gap}`,
18704
- opacity: (opacity - previousOpacity) / (1 - previousOpacity)
18705
- };
18706
- });
18707
- function CanvasCard({ title, tone, titleContent, icon, subtitle, subtitleAccessory, children, preview, branches, footer, actions, problem, problemIcon, problemTone = "danger", selected, running = false, fill = false, compact = false, compactContent = false, contentHidden = false, footerHidden = false }) {
18708
- const hasContent = Children.toArray(children).some((child) => typeof child != "string" || child.trim().length > 0);
18709
- const hasBranches = !isEmptyReactNode(branches);
18710
- const hasBody = !contentHidden && (hasContent || !isEmptyReactNode(preview)) || hasBranches || !footerHidden && !isEmptyReactNode(footer);
18711
- const statusIndicator = problem && /* @__PURE__ */ jsx(CanvasTooltip, {
18712
- title: problem,
18713
- placement: "top",
18714
- children: /* @__PURE__ */ jsx("span", {
18715
- className: clsx(CanvasCard_module_default.icon, CanvasCard_module_default.indicator, problemTone == "warning" ? CanvasCard_module_default.warning : CanvasCard_module_default.danger),
18716
- "aria-label": problem,
18717
- role: "img",
18718
- tabIndex: 0,
18719
- children: problemIcon ?? /* @__PURE__ */ jsx("i", {
18720
- "aria-hidden": "true",
18721
- className: "i-lucide-light:triangle-alert"
18722
- })
18723
- })
18724
- });
18725
- return /* @__PURE__ */ jsxs("article", {
18726
- className: clsx(CanvasCard_module_default.card, fill && CanvasCard_module_default.fill, compact && CanvasCard_module_default.compact, compactContent && CanvasCard_module_default.compactContent, tone && CanvasCard_module_default[tone], selected && CanvasCard_module_default.selected, problem && problemTone == "danger" && CanvasCard_module_default.problem),
18727
- children: [
18728
- /* @__PURE__ */ jsxs("header", {
18729
- className: clsx(CanvasCard_module_default.header, hasBody && CanvasCard_module_default.withBody),
18730
- children: [
18731
- /* @__PURE__ */ jsxs("div", {
18732
- className: CanvasCard_module_default.compactIdentity,
18733
- children: [
18734
- /* @__PURE__ */ jsx("span", {
18735
- className: CanvasCard_module_default.icon,
18736
- children: icon
18737
- }),
18738
- /* @__PURE__ */ jsx("strong", {
18739
- title,
18740
- children: title
18741
- }),
18742
- statusIndicator
18743
- ]
18744
- }),
18745
- /* @__PURE__ */ jsx("span", {
18746
- className: CanvasCard_module_default.icon,
18747
- children: icon
18748
- }),
18749
- /* @__PURE__ */ jsxs("div", {
18750
- className: CanvasCard_module_default.identity,
18751
- children: [/* @__PURE__ */ jsx("strong", {
18752
- title,
18753
- children: titleContent ?? title
18754
- }), subtitle && /* @__PURE__ */ jsxs("span", {
18755
- className: CanvasCard_module_default.subtitle,
18756
- children: [/* @__PURE__ */ jsx("span", { children: subtitle }), subtitleAccessory]
18757
- })]
18758
- }),
18759
- statusIndicator,
18760
- actions
18761
- ]
18762
- }),
18763
- /* @__PURE__ */ jsxs("div", {
18764
- className: clsx(hasBody && !hasBranches && CanvasCard_module_default.singleContent),
18765
- children: [
18766
- (hasContent || !isEmptyReactNode(preview)) && /* @__PURE__ */ jsxs(CardCollapse, {
18767
- hidden: contentHidden,
18768
- children: [hasContent && /* @__PURE__ */ jsx("div", {
18769
- className: CanvasCard_module_default.content,
18770
- children
18771
- }), !isEmptyReactNode(preview) && /* @__PURE__ */ jsx("div", {
18772
- className: CanvasCard_module_default.preview,
18773
- children: preview
18774
- })]
18775
- }),
18776
- !isEmptyReactNode(branches) && /* @__PURE__ */ jsx("div", {
18777
- className: CanvasCard_module_default.branches,
18778
- children: branches
18779
- }),
18780
- !isEmptyReactNode(footer) && /* @__PURE__ */ jsx(CardCollapse, {
18781
- hidden: footerHidden,
18782
- children: /* @__PURE__ */ jsx("footer", {
18783
- className: clsx(CanvasCard_module_default.footer, !contentHidden && !isEmptyReactNode(preview) && CanvasCard_module_default.afterPreview),
18784
- children: footer
18785
- })
18786
- })
18787
- ]
18788
- }),
18789
- running && /* @__PURE__ */ jsx("svg", {
18790
- className: CanvasCard_module_default.runningBeam,
18791
- "aria-hidden": "true",
18792
- children: runningBeamLayers.map((layer, index) => /* @__PURE__ */ jsx("rect", {
18793
- x: "0.5",
18794
- y: "0.5",
18795
- pathLength: runningBeamPathLength,
18796
- strokeDasharray: layer.dash,
18797
- strokeOpacity: layer.opacity
18798
- }, index))
18799
- })
18800
- ]
18801
- });
18802
- }
18803
- /** Retain content only while the closing transition needs it. */
18804
- function CardCollapse({ hidden, children }) {
18805
- const elementRef = useRef(null);
18806
- const [present, setPresent] = useState(!hidden);
18807
- useLayoutEffect(() => {
18808
- const element = elementRef.current;
18809
- element.toggleAttribute("inert", hidden);
18810
- if (!hidden) {
18811
- setPresent(true);
18812
- return;
18813
- }
18814
- element.getBoundingClientRect();
18815
- const animations = element.getAnimations();
18816
- let cancelled = false;
18817
- Promise.allSettled(animations.map((animation) => animation.finished)).then(() => {
18818
- if (!cancelled) setPresent(false);
18819
- });
18820
- return () => {
18821
- cancelled = true;
18822
- };
18823
- }, [hidden]);
18824
- return /* @__PURE__ */ jsx("div", {
18825
- className: CanvasCard_module_default.collapse,
18826
- "data-hidden": hidden,
18827
- "aria-hidden": hidden || void 0,
18828
- ref: elementRef,
18829
- children: /* @__PURE__ */ jsx("div", {
18830
- className: CanvasCard_module_default.collapseInner,
18831
- children: (!hidden || present) && children
18832
- })
18833
- });
18834
- }
18835
- //#endregion
18836
- //#region src/canvas/browser/graph/Nodes/components/constants.ts
18837
- var defaultNodeIcon = "i-carbon:hexagon-vertical-outline";
18838
- var defaultConditionIcon = "i-carbon:child-node";
18839
- var defaultTriggerIcon = "i-codicon:symbol-event";
18840
- var iconForNodeType = (nodeType) => nodeType === NODE_TYPE.TaskNode ? "i-carbon:code" : nodeType === NODE_TYPE.ConditionNode ? defaultConditionIcon : nodeType === NODE_TYPE.TriggerNode ? defaultTriggerIcon : defaultNodeIcon;
18841
- //#endregion
18842
- //#region src/canvas/browser/graph/Nodes/components/CanvasNodeIcon.tsx
18843
- function nodeTypeForKind(kind) {
18844
- switch (kind) {
18845
- case "task": return NODE_TYPE.TaskNode;
18846
- case "condition": return NODE_TYPE.ConditionNode;
18847
- case "trigger": return NODE_TYPE.TriggerNode;
18848
- case "comment": return NODE_TYPE.CommentNode;
18849
- default: return NODE_TYPE.ValueNode;
18850
- }
18851
- }
18852
- function CanvasNodeIcon({ kind, icon, fallbackIcon, nodeType, className }) {
18853
- const defaultIcon = fallbackIcon ?? (kind == "wait" ? ":carbon:hourglass:" : kind == "approval" ? ":carbon:stamp:" : void 0);
18854
- return /* @__PURE__ */ jsx(ContentIcon, {
18855
- src: icon ?? defaultIcon,
18856
- className,
18857
- fallback: /* @__PURE__ */ jsx(ContentIcon, {
18858
- src: defaultIcon,
18859
- className,
18860
- fallback: /* @__PURE__ */ jsx("i", {
18861
- "aria-hidden": "true",
18862
- className: iconForNodeType(nodeType ?? nodeTypeForKind(kind))
18863
- })
18864
- })
18865
- });
18866
- }
18867
- var NodeContentRows_module_default = { rows: "NodeContentRows_rows_01c56" };
18868
- //#endregion
18869
- //#region src/canvas/browser/graph/Nodes/components/NodeContentRows.tsx
18870
- function NodeContentRows({ children }) {
18871
- return /* @__PURE__ */ jsx("ul", {
18872
- className: NodeContentRows_module_default.rows,
18873
- children
18874
- });
18875
- }
18876
18837
  var RunChips_module_default = {
18877
- chip: "RunChips_chip_80ab6",
18878
- popup: "RunChips_popup_80ab6",
18879
- statusPopup: "RunChips_statusPopup_80ab6",
18880
- heading: "RunChips_heading_80ab6",
18881
- metadata: "RunChips_metadata_80ab6",
18882
- runId: "RunChips_runId_80ab6",
18883
- separator: "RunChips_separator_80ab6",
18884
- record: "RunChips_record_80ab6",
18885
- log: "RunChips_log_80ab6",
18886
- preview: "RunChips_preview_80ab6",
18887
- previewAction: "RunChips_previewAction_80ab6",
18888
- gallery: "RunChips_gallery_80ab6",
18889
- row: "RunChips_row_80ab6",
18890
- links: "RunChips_links_80ab6",
18891
- status: "RunChips_status_80ab6",
18892
- "run-spin": "RunChips_run-spin_80ab6"
18838
+ chip: "RunChips_chip_c07c0",
18839
+ popup: "RunChips_popup_c07c0",
18840
+ statusPopup: "RunChips_statusPopup_c07c0",
18841
+ heading: "RunChips_heading_c07c0",
18842
+ metadata: "RunChips_metadata_c07c0",
18843
+ runId: "RunChips_runId_c07c0",
18844
+ separator: "RunChips_separator_c07c0",
18845
+ record: "RunChips_record_c07c0",
18846
+ log: "RunChips_log_c07c0",
18847
+ preview: "RunChips_preview_c07c0",
18848
+ previewAction: "RunChips_previewAction_c07c0",
18849
+ gallery: "RunChips_gallery_c07c0",
18850
+ row: "RunChips_row_c07c0",
18851
+ links: "RunChips_links_c07c0",
18852
+ statusIndicator: "RunChips_statusIndicator_c07c0",
18853
+ status: "RunChips_status_c07c0",
18854
+ "run-spin": "RunChips_run-spin_c07c0",
18855
+ compactChip: "RunChips_compactChip_c07c0"
18893
18856
  };
18894
18857
  //#endregion
18895
18858
  //#region ../../node_modules/.bun/sonner@2.0.7+6dbf9a050bc9aadb/node_modules/sonner/dist/index.mjs
@@ -19699,22 +19662,27 @@ var JSONViewer = /* @__PURE__ */ memo(({ className, data, disableTopLevelExpand,
19699
19662
  });
19700
19663
  //#endregion
19701
19664
  //#region src/canvas/browser/graph/Nodes/components/RunChips.tsx
19702
- function RecordChip({ label, run, children, icon, status }) {
19665
+ function RecordChip({ label, run, children, icon, status, compact = false }) {
19703
19666
  const t = useTranslate();
19704
19667
  const popupContainer = useGetStaticPopupContainer()();
19705
19668
  const runId = run.runId;
19706
- return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
19669
+ const trigger = /* @__PURE__ */ jsxs(PopoverTrigger, {
19707
19670
  render: /* @__PURE__ */ jsx("button", {
19708
19671
  type: "button",
19709
- className: `${RunChips_module_default.chip} ${status ? RunChips_module_default.status : ""} nodrag nopan nokey`,
19672
+ "aria-label": compact ? label : void 0,
19673
+ className: `${RunChips_module_default.chip} ${status ? RunChips_module_default.status : ""} ${compact ? RunChips_module_default.compactChip : ""} nodrag nopan nokey`,
19710
19674
  "data-status": status,
19711
19675
  onClick: (event) => event.stopPropagation()
19712
19676
  }),
19713
19677
  children: [icon && /* @__PURE__ */ jsx("i", {
19714
19678
  className: icon,
19715
19679
  "aria-hidden": "true"
19716
- }), /* @__PURE__ */ jsx("span", { children: label })]
19717
- }), /* @__PURE__ */ jsxs(PopoverContent, {
19680
+ }), !compact && /* @__PURE__ */ jsx("span", { children: label })]
19681
+ });
19682
+ return /* @__PURE__ */ jsxs(Popover, { children: [compact ? /* @__PURE__ */ jsx(CanvasTooltip, {
19683
+ title: label,
19684
+ children: trigger
19685
+ }) : trigger, /* @__PURE__ */ jsxs(PopoverContent, {
19718
19686
  container: popupContainer,
19719
19687
  side: "bottom",
19720
19688
  align: "start",
@@ -19800,19 +19768,45 @@ function ImagePreview({ images, run, title }) {
19800
19768
  })]
19801
19769
  });
19802
19770
  }
19771
+ function runStatusLabel(run, t) {
19772
+ const elapsed = run.startedAt != null && run.finishedAt != null ? Date.parse(run.finishedAt) - Date.parse(run.startedAt) : void 0;
19773
+ return `${t(`canvasCard.status.${run.status}`)}${run.status == "running" && run.progress != null && Number.isFinite(run.progress) ? ` · ${Math.round(Math.min(100, Math.max(0, run.progress)))}%` : ""}${elapsed != null && Number.isFinite(elapsed) && elapsed >= 0 ? ` · ${formatDuration(elapsed)}` : ""}`;
19774
+ }
19775
+ function runStatusIcon(state) {
19776
+ return state == "handled" ? "i-lucide-light:triangle-alert" : state == "running" ? "i-codicon:loading" : state == "success" ? "i-codicon:check" : state == "error" ? "i-codicon:error" : state == "waiting" ? "i-carbon:time" : "i-codicon:circle-outline";
19777
+ }
19778
+ function RunStatusIndicator({ run }) {
19779
+ const label = runStatusLabel(run, useTranslate());
19780
+ return /* @__PURE__ */ jsx(CanvasTooltip, {
19781
+ title: label,
19782
+ placement: "top",
19783
+ children: /* @__PURE__ */ jsx("span", {
19784
+ className: RunChips_module_default.statusIndicator,
19785
+ "data-status": run.status,
19786
+ role: "img",
19787
+ "aria-label": label,
19788
+ tabIndex: 0,
19789
+ children: /* @__PURE__ */ jsx("i", {
19790
+ className: runStatusIcon(run.status),
19791
+ "aria-hidden": "true"
19792
+ })
19793
+ })
19794
+ });
19795
+ }
19796
+ function hasRunRecords(run) {
19797
+ return run != null && (run.status !== "idle" || run.outputs !== void 0 || (run.logs?.length ?? 0) > 0 || (run.artifacts?.length ?? 0) > 0);
19798
+ }
19803
19799
  function RunChips({ run }) {
19804
19800
  const t = useTranslate();
19805
- const elapsed = run.startedAt != null && run.finishedAt != null ? Date.parse(run.finishedAt) - Date.parse(run.startedAt) : void 0;
19806
- const status = `${t(`canvasCard.status.${run.status}`)}${run.status == "running" && run.progress != null && Number.isFinite(run.progress) ? ` · ${Math.round(Math.min(100, Math.max(0, run.progress)))}%` : ""}${elapsed != null && Number.isFinite(elapsed) && elapsed >= 0 ? ` · ${formatDuration(elapsed)}` : ""}`;
19807
- const state = run.status;
19808
- const icon = state == "handled" ? "i-lucide-light:triangle-alert" : state == "running" ? "i-codicon:loading" : state == "success" ? "i-codicon:check" : state == "error" ? "i-codicon:error" : state == "waiting" ? "i-carbon:time" : "i-codicon:circle-outline";
19801
+ if (!hasRunRecords(run)) return null;
19809
19802
  return /* @__PURE__ */ jsxs("div", {
19810
19803
  className: RunChips_module_default.row,
19811
- children: [/* @__PURE__ */ jsx(RecordChip, {
19812
- label: status,
19804
+ children: [run.status !== "idle" && /* @__PURE__ */ jsx(RecordChip, {
19805
+ label: runStatusLabel(run, t),
19813
19806
  run,
19814
- icon,
19815
- status: state,
19807
+ icon: runStatusIcon(run.status),
19808
+ status: run.status,
19809
+ compact: true,
19816
19810
  children: run.error != null && /* @__PURE__ */ jsx(JSONViewer, {
19817
19811
  data: run.error,
19818
19812
  shouldExpandNode: collapseAllNested
@@ -19824,6 +19818,7 @@ function RunChips({ run }) {
19824
19818
  label: t("canvasCard.result"),
19825
19819
  run,
19826
19820
  icon: "i-codicon:output",
19821
+ compact: true,
19827
19822
  children: /* @__PURE__ */ jsx(JSONViewer, {
19828
19823
  data: run.outputs,
19829
19824
  shouldExpandNode: collapseAllNested
@@ -19833,6 +19828,7 @@ function RunChips({ run }) {
19833
19828
  label: t("canvasCard.logs", { count: run.logs?.length ?? 0 }),
19834
19829
  run,
19835
19830
  icon: "i-codicon:list-unordered",
19831
+ compact: true,
19836
19832
  children: run.logs?.map((log, index) => /* @__PURE__ */ jsxs("div", {
19837
19833
  className: RunChips_module_default.log,
19838
19834
  children: [/* @__PURE__ */ jsxs("small", { children: [
@@ -19846,6 +19842,7 @@ function RunChips({ run }) {
19846
19842
  label: t("canvasCard.files", { count: run.artifacts?.length ?? 0 }),
19847
19843
  run,
19848
19844
  icon: "i-codicon:files",
19845
+ compact: true,
19849
19846
  children: [/* @__PURE__ */ jsx("p", { children: t("canvasCard.artifactMetadata") }), /* @__PURE__ */ jsx(JSONViewer, {
19850
19847
  data: run.artifacts,
19851
19848
  shouldExpandNode: collapseAllNested
@@ -19855,49 +19852,229 @@ function RunChips({ run }) {
19855
19852
  })]
19856
19853
  });
19857
19854
  }
19858
- var ValuePreview_module_default = {
19859
- trigger: "ValuePreview_trigger_4d5e2",
19860
- popup: "ValuePreview_popup_4d5e2",
19861
- content: "ValuePreview_content_4d5e2",
19862
- json: "ValuePreview_json_4d5e2"
19863
- };
19864
- //#endregion
19865
- //#region src/canvas/browser/graph/Nodes/components/ValuePreview.tsx
19866
- function ValuePreview({ name, value }) {
19867
- const getContainer = useGetStaticPopupContainer();
19868
- return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
19869
- openOnHover: true,
19870
- delay: 200,
19871
- closeDelay: 150,
19872
- render: /* @__PURE__ */ jsx("button", {
19873
- type: "button",
19874
- className: `${ValuePreview_module_default.trigger} nodrag nopan nokey`,
19875
- onClick: (event) => event.stopPropagation()
19876
- }),
19877
- children: JSON.stringify(value)
19878
- }), /* @__PURE__ */ jsx(PopoverContent, {
19879
- container: getContainer(),
19880
- side: "top",
19881
- align: "center",
19882
- sideOffset: 8,
19883
- className: `${ValuePreview_module_default.popup} nodrag nopan nowheel nokey`,
19884
- "aria-label": name,
19885
- "data-canvas-control-scope": true,
19886
- onClick: (event) => event.stopPropagation(),
19887
- children: /* @__PURE__ */ jsx(ScrollArea, {
19888
- className: ValuePreview_module_default.content,
19889
- children: /* @__PURE__ */ jsx(JSONViewer, {
19890
- className: ValuePreview_module_default.json,
19891
- data: value,
19892
- shouldExpandNode: collapseAllNested
19893
- })
19894
- })
19895
- })] });
19896
- }
19897
19855
  //#endregion
19898
- //#region src/canvas/browser/graph/Nodes/components/CanvasNode.tsx
19899
- function CanvasNode({ nodeStore, problem, branches, compact = false, compactContent = false }) {
19900
- const t = useTranslate();
19856
+ //#region src/canvas/browser/graph/Nodes/components/CanvasCard.tsx
19857
+ var runningBeamPathLength = 1e3;
19858
+ var runningBeamLength = 160;
19859
+ var runningBeamLayerCount = 48;
19860
+ var runningBeamPeakOpacity = .9;
19861
+ var runningBeamLayers = Array.from({ length: runningBeamLayerCount }, (_, index) => {
19862
+ const length = runningBeamLength * (1 - index / runningBeamLayerCount);
19863
+ const gap = (runningBeamPathLength - length) / 2;
19864
+ const previousOpacity = runningBeamPeakOpacity * Math.sin(index / runningBeamLayerCount * (Math.PI / 2)) ** 2;
19865
+ const opacity = runningBeamPeakOpacity * Math.sin((index + 1) / runningBeamLayerCount * (Math.PI / 2)) ** 2;
19866
+ return {
19867
+ dash: `0 ${gap} ${length} ${gap}`,
19868
+ opacity: (opacity - previousOpacity) / (1 - previousOpacity)
19869
+ };
19870
+ });
19871
+ function CanvasCard({ title, tone, titleContent, icon, subtitle, subtitleAccessory, children, preview, branches, actions, diagnostic, run, selected, running = run?.status === "running", fill = false, compact = false, compactContent = false, contentHidden = false }) {
19872
+ const hasContent = Children.toArray(children).some((child) => typeof child != "string" || child.trim().length > 0);
19873
+ const hasBranches = !isEmptyReactNode(branches);
19874
+ const runControls = hasRunRecords(run) ? /* @__PURE__ */ jsx(RunChips, { run }) : void 0;
19875
+ const hasBody = !contentHidden && (hasContent || !isEmptyReactNode(preview)) || hasBranches;
19876
+ const hasError = run?.status === "error" || diagnostic != null && diagnostic.tone !== "warning";
19877
+ const diagnosticIndicator = diagnostic && /* @__PURE__ */ jsx(CanvasTooltip, {
19878
+ title: diagnostic.message,
19879
+ placement: "top",
19880
+ children: /* @__PURE__ */ jsx("span", {
19881
+ className: clsx(CanvasCard_module_default.icon, CanvasCard_module_default.indicator, diagnostic.tone === "warning" ? CanvasCard_module_default.warning : CanvasCard_module_default.danger),
19882
+ "aria-label": diagnostic.message,
19883
+ role: "img",
19884
+ tabIndex: 0,
19885
+ children: diagnostic.icon ?? /* @__PURE__ */ jsx("i", {
19886
+ "aria-hidden": "true",
19887
+ className: "i-lucide-light:triangle-alert"
19888
+ })
19889
+ })
19890
+ });
19891
+ return /* @__PURE__ */ jsxs("article", {
19892
+ className: clsx(CanvasCard_module_default.card, fill && CanvasCard_module_default.fill, compact && CanvasCard_module_default.compact, compactContent && CanvasCard_module_default.compactContent, tone && CanvasCard_module_default[tone], selected && CanvasCard_module_default.selected, hasError && CanvasCard_module_default.problem),
19893
+ children: [
19894
+ /* @__PURE__ */ jsxs("header", {
19895
+ className: clsx(CanvasCard_module_default.header, hasBody && CanvasCard_module_default.withBody),
19896
+ children: [
19897
+ compact && /* @__PURE__ */ jsxs("div", {
19898
+ className: CanvasCard_module_default.compactIdentity,
19899
+ children: [
19900
+ /* @__PURE__ */ jsx("span", {
19901
+ className: CanvasCard_module_default.icon,
19902
+ children: icon
19903
+ }),
19904
+ /* @__PURE__ */ jsx("strong", {
19905
+ title,
19906
+ children: title
19907
+ }),
19908
+ diagnosticIndicator || run && run.status !== "idle" && /* @__PURE__ */ jsx("span", {
19909
+ className: clsx(CanvasCard_module_default.icon, CanvasCard_module_default.indicator),
19910
+ children: /* @__PURE__ */ jsx(RunStatusIndicator, { run })
19911
+ })
19912
+ ]
19913
+ }),
19914
+ /* @__PURE__ */ jsx("span", {
19915
+ className: CanvasCard_module_default.icon,
19916
+ children: icon
19917
+ }),
19918
+ /* @__PURE__ */ jsxs("div", {
19919
+ className: CanvasCard_module_default.identity,
19920
+ children: [/* @__PURE__ */ jsx("strong", {
19921
+ title,
19922
+ children: titleContent ?? title
19923
+ }), subtitle && /* @__PURE__ */ jsxs("span", {
19924
+ className: CanvasCard_module_default.subtitle,
19925
+ children: [/* @__PURE__ */ jsx("span", { children: subtitle }), subtitleAccessory]
19926
+ })]
19927
+ }),
19928
+ diagnosticIndicator || runControls,
19929
+ actions
19930
+ ]
19931
+ }),
19932
+ /* @__PURE__ */ jsxs("div", {
19933
+ className: clsx(hasBody && !hasBranches && CanvasCard_module_default.singleContent),
19934
+ children: [(hasContent || !isEmptyReactNode(preview)) && /* @__PURE__ */ jsxs(CardCollapse, {
19935
+ hidden: contentHidden,
19936
+ children: [hasContent && /* @__PURE__ */ jsx("div", {
19937
+ className: CanvasCard_module_default.content,
19938
+ children
19939
+ }), !isEmptyReactNode(preview) && /* @__PURE__ */ jsx("div", {
19940
+ className: CanvasCard_module_default.preview,
19941
+ children: preview
19942
+ })]
19943
+ }), !isEmptyReactNode(branches) && /* @__PURE__ */ jsx("div", {
19944
+ className: CanvasCard_module_default.branches,
19945
+ children: branches
19946
+ })]
19947
+ }),
19948
+ running && /* @__PURE__ */ jsx("svg", {
19949
+ className: CanvasCard_module_default.runningBeam,
19950
+ "aria-hidden": "true",
19951
+ children: runningBeamLayers.map((layer, index) => /* @__PURE__ */ jsx("rect", {
19952
+ x: "0.5",
19953
+ y: "0.5",
19954
+ pathLength: runningBeamPathLength,
19955
+ strokeDasharray: layer.dash,
19956
+ strokeOpacity: layer.opacity
19957
+ }, index))
19958
+ })
19959
+ ]
19960
+ });
19961
+ }
19962
+ /** Retain content only while the closing transition needs it. */
19963
+ function CardCollapse({ hidden, children }) {
19964
+ const elementRef = useRef(null);
19965
+ const [present, setPresent] = useState(!hidden);
19966
+ useLayoutEffect(() => {
19967
+ const element = elementRef.current;
19968
+ element.toggleAttribute("inert", hidden);
19969
+ if (!hidden) {
19970
+ setPresent(true);
19971
+ return;
19972
+ }
19973
+ element.getBoundingClientRect();
19974
+ const animations = element.getAnimations();
19975
+ let cancelled = false;
19976
+ Promise.allSettled(animations.map((animation) => animation.finished)).then(() => {
19977
+ if (!cancelled) setPresent(false);
19978
+ });
19979
+ return () => {
19980
+ cancelled = true;
19981
+ };
19982
+ }, [hidden]);
19983
+ return /* @__PURE__ */ jsx("div", {
19984
+ className: CanvasCard_module_default.collapse,
19985
+ "data-hidden": hidden,
19986
+ "aria-hidden": hidden || void 0,
19987
+ ref: elementRef,
19988
+ children: /* @__PURE__ */ jsx("div", {
19989
+ className: CanvasCard_module_default.collapseInner,
19990
+ children: (!hidden || present) && children
19991
+ })
19992
+ });
19993
+ }
19994
+ //#endregion
19995
+ //#region src/canvas/browser/graph/Nodes/components/constants.ts
19996
+ var defaultNodeIcon = "i-carbon:hexagon-vertical-outline";
19997
+ var defaultConditionIcon = "i-carbon:child-node";
19998
+ var defaultTriggerIcon = "i-codicon:symbol-event";
19999
+ var iconForNodeType = (nodeType) => nodeType === NODE_TYPE.TaskNode ? "i-carbon:code" : nodeType === NODE_TYPE.ConditionNode ? defaultConditionIcon : nodeType === NODE_TYPE.TriggerNode ? defaultTriggerIcon : defaultNodeIcon;
20000
+ //#endregion
20001
+ //#region src/canvas/browser/graph/Nodes/components/CanvasNodeIcon.tsx
20002
+ function nodeTypeForKind(kind) {
20003
+ switch (kind) {
20004
+ case "task": return NODE_TYPE.TaskNode;
20005
+ case "condition": return NODE_TYPE.ConditionNode;
20006
+ case "trigger": return NODE_TYPE.TriggerNode;
20007
+ case "comment": return NODE_TYPE.CommentNode;
20008
+ default: return NODE_TYPE.ValueNode;
20009
+ }
20010
+ }
20011
+ function CanvasNodeIcon({ kind, icon, fallbackIcon, nodeType, className }) {
20012
+ const defaultIcon = fallbackIcon ?? (kind == "wait" ? ":carbon:hourglass:" : kind == "approval" ? ":carbon:stamp:" : void 0);
20013
+ return /* @__PURE__ */ jsx(ContentIcon, {
20014
+ src: icon ?? defaultIcon,
20015
+ className,
20016
+ fallback: /* @__PURE__ */ jsx(ContentIcon, {
20017
+ src: defaultIcon,
20018
+ className,
20019
+ fallback: /* @__PURE__ */ jsx("i", {
20020
+ "aria-hidden": "true",
20021
+ className: iconForNodeType(nodeType ?? nodeTypeForKind(kind))
20022
+ })
20023
+ })
20024
+ });
20025
+ }
20026
+ var NodeContentRows_module_default = { rows: "NodeContentRows_rows_01c56" };
20027
+ //#endregion
20028
+ //#region src/canvas/browser/graph/Nodes/components/NodeContentRows.tsx
20029
+ function NodeContentRows({ children }) {
20030
+ return /* @__PURE__ */ jsx("ul", {
20031
+ className: NodeContentRows_module_default.rows,
20032
+ children
20033
+ });
20034
+ }
20035
+ var ValuePreview_module_default = {
20036
+ trigger: "ValuePreview_trigger_4d5e2",
20037
+ popup: "ValuePreview_popup_4d5e2",
20038
+ content: "ValuePreview_content_4d5e2",
20039
+ json: "ValuePreview_json_4d5e2"
20040
+ };
20041
+ //#endregion
20042
+ //#region src/canvas/browser/graph/Nodes/components/ValuePreview.tsx
20043
+ function ValuePreview({ name, value }) {
20044
+ const getContainer = useGetStaticPopupContainer();
20045
+ return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
20046
+ openOnHover: true,
20047
+ delay: 200,
20048
+ closeDelay: 150,
20049
+ render: /* @__PURE__ */ jsx("button", {
20050
+ type: "button",
20051
+ className: `${ValuePreview_module_default.trigger} nodrag nopan nokey`,
20052
+ onClick: (event) => event.stopPropagation()
20053
+ }),
20054
+ children: JSON.stringify(value)
20055
+ }), /* @__PURE__ */ jsx(PopoverContent, {
20056
+ container: getContainer(),
20057
+ side: "top",
20058
+ align: "center",
20059
+ sideOffset: 8,
20060
+ className: `${ValuePreview_module_default.popup} nodrag nopan nowheel nokey`,
20061
+ "aria-label": name,
20062
+ "data-canvas-control-scope": true,
20063
+ onClick: (event) => event.stopPropagation(),
20064
+ children: /* @__PURE__ */ jsx(ScrollArea, {
20065
+ className: ValuePreview_module_default.content,
20066
+ children: /* @__PURE__ */ jsx(JSONViewer, {
20067
+ className: ValuePreview_module_default.json,
20068
+ data: value,
20069
+ shouldExpandNode: collapseAllNested
20070
+ })
20071
+ })
20072
+ })] });
20073
+ }
20074
+ //#endregion
20075
+ //#region src/canvas/browser/graph/Nodes/components/CanvasNode.tsx
20076
+ function CanvasNode({ nodeStore, diagnostic, branches, compact = false, compactContent = false }) {
20077
+ const t = useTranslate();
19901
20078
  const language = useLang();
19902
20079
  const selected = useVal(nodeStore.$.selected);
19903
20080
  const node = useVal(nodeStore.content$);
@@ -19911,9 +20088,22 @@ function CanvasNode({ nodeStore, problem, branches, compact = false, compactCont
19911
20088
  const kind = node?.kind ?? "task";
19912
20089
  const triggerSource = node.kind == "trigger" ? node.presentation?.kind == "error" || node.presentation?.kind == "manual" || node.presentation?.kind == "start" || node.presentation?.kind == "cron" || node.presentation?.kind == "webhook" ? t(`canvasCard.triggerSource.${node.presentation.kind}`) : node.presentation?.source : void 0;
19913
20090
  const subtitle = inline ? summary : node.kind == "task" ? node.executorName || t("canvasCard.kind.task") : node.kind == "trigger" && triggerSource ? `${t("canvasCard.kind.trigger")} · ${triggerSource}` : t(`canvasCard.kind.${kind}`);
19914
- const runContent = node?.run == null || node.run.status == "idle" ? void 0 : /* @__PURE__ */ jsx(RunChips, { run: node.run });
19915
20091
  const connectionRequired = (node.kind == "task" || node.kind == "trigger") && node.connectionRequired;
19916
- const connectionDeferred = node.kind == "task" && node.connectionDeferred && !connectionRequired && !problem;
20092
+ const connectionDeferred = node.kind == "task" && node.connectionDeferred && !connectionRequired && !diagnostic && node.run?.status !== "error";
20093
+ const cardDiagnostic = connectionRequired ? {
20094
+ message: t("nodeStatus.connectionRequired"),
20095
+ icon: /* @__PURE__ */ jsx("i", {
20096
+ "aria-hidden": "true",
20097
+ className: "i-lucide-light:unplug"
20098
+ })
20099
+ } : diagnostic ? { message: diagnostic } : connectionDeferred ? {
20100
+ message: t("nodeStatus.connectionDeferred"),
20101
+ tone: "warning",
20102
+ icon: /* @__PURE__ */ jsx("i", {
20103
+ "aria-hidden": "true",
20104
+ className: "i-lucide-light:unplug"
20105
+ })
20106
+ } : void 0;
19917
20107
  return /* @__PURE__ */ jsx("div", {
19918
20108
  className: NODE_HANDLE_CLASSNAME,
19919
20109
  children: /* @__PURE__ */ jsx(CanvasCard, {
@@ -19921,7 +20111,6 @@ function CanvasNode({ nodeStore, problem, branches, compact = false, compactCont
19921
20111
  compact,
19922
20112
  compactContent,
19923
20113
  contentHidden: hidden,
19924
- footerHidden: hidden && !runContent,
19925
20114
  title,
19926
20115
  icon: /* @__PURE__ */ jsx(CanvasNodeIcon, {
19927
20116
  icon: node.icon,
@@ -19948,18 +20137,9 @@ function CanvasNode({ nodeStore, problem, branches, compact = false, compactCont
19948
20137
  })
19949
20138
  }) : void 0,
19950
20139
  selected,
19951
- running: node.run?.status === "running",
19952
- problem: connectionRequired ? t("nodeStatus.connectionRequired") : problem ?? (connectionDeferred ? t("nodeStatus.connectionDeferred") : void 0),
19953
- problemTone: connectionDeferred ? "warning" : "danger",
19954
- problemIcon: connectionRequired || connectionDeferred ? /* @__PURE__ */ jsx("i", {
19955
- "aria-hidden": "true",
19956
- className: "i-lucide-light:unplug"
19957
- }) : void 0,
20140
+ diagnostic: cardDiagnostic,
20141
+ run: node.run,
19958
20142
  branches,
19959
- footer: runContent ? /* @__PURE__ */ jsx("div", {
19960
- className: CanvasNode_module_default.footer,
19961
- children: runContent
19962
- }) : void 0,
19963
20143
  preview: (values.length > 0 || Boolean(schedules?.length) || node?.run != null && images.length > 0) && /* @__PURE__ */ jsxs(Fragment$1, { children: [
19964
20144
  schedules != null && schedules.length > 0 && /* @__PURE__ */ jsx(NodeContentRows, { children: schedules.map((schedule, index) => {
19965
20145
  const description = schedule.type === "cron" ? cronDescription(schedule.expression, language) : void 0;
@@ -20101,6 +20281,107 @@ var MarkdownPreview = /* @__PURE__ */ memo(({ dark, unstyled, components, conten
20101
20281
  });
20102
20282
  });
20103
20283
  //#endregion
20284
+ //#region src/canvas/browser/graph/Nodes/components/NodeResizeHandle.tsx
20285
+ /** Shared canvas-space dragging and keyboard resizing for node controls. */
20286
+ function NodeResizeHandle({ children, className, disabled, label, minimum, position, showTooltip = true, size, onStart, onResize, onCommit, onCancel, onReset }) {
20287
+ const reactFlow = useStoreApi();
20288
+ const drag = useRef();
20289
+ const cancel = useRef(onCancel);
20290
+ cancel.current = onCancel;
20291
+ useEffect(() => () => {
20292
+ if (drag.current) {
20293
+ drag.current = void 0;
20294
+ cancel.current?.();
20295
+ }
20296
+ }, []);
20297
+ const resized = (initial, dx, dy) => {
20298
+ const width = Math.max(minimum.width, initial.width + (position === "left" ? -dx : dx));
20299
+ return {
20300
+ width,
20301
+ height: position === "bottom-right" ? Math.max(minimum.height, initial.height + dy) : initial.height,
20302
+ offsetX: position === "left" ? initial.width - width : 0
20303
+ };
20304
+ };
20305
+ const finish = () => {
20306
+ const start = drag.current;
20307
+ drag.current = void 0;
20308
+ if (!start) return;
20309
+ if (start.last.width === start.size.width && start.last.height === start.size.height) onCancel?.();
20310
+ else onCommit?.(start.last);
20311
+ };
20312
+ const handle = /* @__PURE__ */ jsx("button", {
20313
+ type: "button",
20314
+ className: `${className} nodrag nopan`,
20315
+ "aria-label": label,
20316
+ disabled,
20317
+ onDoubleClick: (event) => {
20318
+ event.stopPropagation();
20319
+ onReset?.();
20320
+ },
20321
+ onPointerDown: (event) => {
20322
+ if (!event.isPrimary || event.button !== 0) return;
20323
+ event.stopPropagation();
20324
+ event.currentTarget.setPointerCapture(event.pointerId);
20325
+ onStart?.();
20326
+ drag.current = {
20327
+ x: event.clientX,
20328
+ y: event.clientY,
20329
+ size,
20330
+ zoom: reactFlow.getState().transform[2],
20331
+ last: {
20332
+ ...size,
20333
+ offsetX: 0
20334
+ }
20335
+ };
20336
+ },
20337
+ onPointerMove: (event) => {
20338
+ const start = drag.current;
20339
+ if (!start || !event.currentTarget.hasPointerCapture(event.pointerId)) return;
20340
+ start.last = resized(start.size, (event.clientX - start.x) / start.zoom, (event.clientY - start.y) / start.zoom);
20341
+ onResize(start.last);
20342
+ },
20343
+ onPointerUp: (event) => {
20344
+ finish();
20345
+ if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
20346
+ },
20347
+ onLostPointerCapture: () => {
20348
+ if (!drag.current) return;
20349
+ drag.current = void 0;
20350
+ onCancel?.();
20351
+ },
20352
+ onKeyDown: (event) => {
20353
+ if (event.key === "Escape" && drag.current) {
20354
+ event.preventDefault();
20355
+ event.stopPropagation();
20356
+ drag.current = void 0;
20357
+ onCancel?.();
20358
+ return;
20359
+ }
20360
+ const step = event.shiftKey ? 40 : 10;
20361
+ const delta = {
20362
+ ArrowLeft: [-step, 0],
20363
+ ArrowRight: [step, 0],
20364
+ ArrowUp: [0, -step],
20365
+ ArrowDown: [0, step]
20366
+ }[event.key];
20367
+ if (!delta || position !== "bottom-right" && delta[1] !== 0) return;
20368
+ event.preventDefault();
20369
+ event.stopPropagation();
20370
+ const change = resized(size, delta[0], delta[1]);
20371
+ if (change.width === size.width && change.height === size.height) return;
20372
+ onStart?.();
20373
+ onResize(change);
20374
+ onCommit?.(change);
20375
+ },
20376
+ children
20377
+ });
20378
+ return showTooltip ? /* @__PURE__ */ jsx(CanvasTooltip, {
20379
+ title: label,
20380
+ placement: "bottom",
20381
+ children: handle
20382
+ }) : handle;
20383
+ }
20384
+ //#endregion
20104
20385
  //#region src/canvas/browser/graph/Nodes/components/CommentNodeContent.tsx
20105
20386
  var markdownComponents = { input: ({ type, checked }) => type === "checkbox" ? /* @__PURE__ */ jsx(Checkbox, {
20106
20387
  className: CommentNodeContent_module_default.taskCheckbox,
@@ -20154,75 +20435,36 @@ function CommentNodeContent({ store }) {
20154
20435
  className: clsx("h-full min-h-0 field-sizing-fixed resize-none rounded-none border-0 bg-transparent px-3.5 py-3 text-inherit shadow-none focus-visible:outline-none", focused && "nodrag"),
20155
20436
  value: content ?? "",
20156
20437
  onCompositionStart: () => setComposing(true),
20157
- onCompositionEnd: (event) => {
20158
- store.$$.content.set(event.currentTarget.value);
20159
- setComposing(false);
20160
- },
20161
- onChange: (event) => store.$$.content.set(event.target.value),
20162
- onBlur: (event) => {
20163
- setFocused(false);
20164
- if (editable && !composing) store.saveContent(event.target.value);
20165
- }
20166
- }) : /* @__PURE__ */ jsx(MarkdownPreview, {
20167
- components: markdownComponents,
20168
- unstyled: true,
20169
- contentClassName: CommentNodeContent_module_default.markdown,
20170
- content: content ?? "",
20171
- dark,
20172
- draggable: true
20173
- })
20174
- }), editable && /* @__PURE__ */ jsx(CommentResizeButton, { store })]
20175
- });
20176
- }
20177
- function CommentResizeButton({ store }) {
20178
- const t = useTranslate();
20179
- const reactFlow = useStoreApi();
20180
- const drag = useRef(null);
20181
- return /* @__PURE__ */ jsx("button", {
20182
- type: "button",
20183
- className: `${CommentNodeContent_module_default.resizeButton} nodrag nopan`,
20184
- "aria-label": t("comment.resize"),
20185
- title: t("comment.resize"),
20186
- onDoubleClick: (event) => event.stopPropagation(),
20187
- onPointerDown: (event) => {
20188
- if (!event.isPrimary || event.button !== 0) return;
20189
- event.stopPropagation();
20190
- event.currentTarget.setPointerCapture(event.pointerId);
20191
- drag.current = {
20192
- x: event.clientX,
20193
- y: event.clientY,
20194
- ...store.$.size.value,
20195
- zoom: reactFlow.getState().transform[2]
20196
- };
20197
- },
20198
- onPointerMove: (event) => {
20199
- const start = drag.current;
20200
- if (!start || !event.currentTarget.hasPointerCapture(event.pointerId)) return;
20201
- store.resize({
20202
- width: start.width + (event.clientX - start.x) / start.zoom,
20203
- height: start.height + (event.clientY - start.y) / start.zoom
20204
- });
20205
- },
20206
- onLostPointerCapture: () => {
20207
- drag.current = null;
20208
- },
20209
- onKeyDown: (event) => {
20210
- const step = event.shiftKey ? 40 : 10;
20211
- const delta = {
20212
- ArrowLeft: [-step, 0],
20213
- ArrowRight: [step, 0],
20214
- ArrowUp: [0, -step],
20215
- ArrowDown: [0, step]
20216
- }[event.key];
20217
- if (!delta) return;
20218
- event.preventDefault();
20219
- event.stopPropagation();
20220
- const size = store.$.size.value;
20221
- store.resize({
20222
- width: size.width + delta[0],
20223
- height: size.height + delta[1]
20224
- });
20225
- },
20438
+ onCompositionEnd: (event) => {
20439
+ store.$$.content.set(event.currentTarget.value);
20440
+ setComposing(false);
20441
+ },
20442
+ onChange: (event) => store.$$.content.set(event.target.value),
20443
+ onBlur: (event) => {
20444
+ setFocused(false);
20445
+ if (editable && !composing) store.saveContent(event.target.value);
20446
+ }
20447
+ }) : /* @__PURE__ */ jsx(MarkdownPreview, {
20448
+ components: markdownComponents,
20449
+ unstyled: true,
20450
+ contentClassName: CommentNodeContent_module_default.markdown,
20451
+ content: content ?? "",
20452
+ dark,
20453
+ draggable: true
20454
+ })
20455
+ }), editable && /* @__PURE__ */ jsx(CommentResizeButton, { store })]
20456
+ });
20457
+ }
20458
+ function CommentResizeButton({ store }) {
20459
+ const t = useTranslate();
20460
+ const size = useVal(store.$.size);
20461
+ return /* @__PURE__ */ jsx(NodeResizeHandle, {
20462
+ className: CommentNodeContent_module_default.resizeButton,
20463
+ label: t("comment.resize"),
20464
+ position: "bottom-right",
20465
+ minimum: COMMENT_MINIMUM_SIZE,
20466
+ size,
20467
+ onResize: store.resize,
20226
20468
  children: /* @__PURE__ */ jsx("i", {
20227
20469
  "aria-hidden": "true",
20228
20470
  className: "i-mdi:resize-bottom-right"
@@ -20452,6 +20694,9 @@ function CommentTitle({ store }) {
20452
20694
  });
20453
20695
  }
20454
20696
  //#endregion
20697
+ //#region src/canvas/browser/nodeActions.tsx
20698
+ var NodeHistoryContext = createContext(void 0);
20699
+ //#endregion
20455
20700
  //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/context-menu/root/ContextMenuRoot.js
20456
20701
  /**
20457
20702
  * A component that creates a context menu activated by right clicking or long pressing.
@@ -20689,11 +20934,15 @@ function NodeHeadContextMenu({ canvasStore, children }) {
20689
20934
  const getPopupContainer = useGetStaticPopupContainer();
20690
20935
  const nodeStore = useNodeStore();
20691
20936
  const editable = useVal(canvasStore.$.editable);
20937
+ const onDelete = toTrue(editable && canvasStore.canDeleteNodes) && (() => canvasStore.deleteNodes([nodeStore]));
20938
+ const content = useVal(NodeStore.to(nodeStore)?.content$);
20939
+ const direction = useVal(canvasStore.$.direction);
20940
+ const resetWidth = editable && direction === "vertical" && canvasStore.canChangeNodeWidth && content?.kind === "condition" && content.verticalWidth != null;
20692
20941
  const items = useNodeMenuItems({
20693
20942
  t,
20694
20943
  nodeStore,
20695
20944
  editable,
20696
- onDelete: toTrue(editable && canvasStore.canDeleteNodes) && (() => canvasStore.deleteNodes([nodeStore]))
20945
+ onDelete
20697
20946
  });
20698
20947
  return /* @__PURE__ */ jsxs(ContextMenu$1, { children: [/* @__PURE__ */ jsx(ContextMenuTrigger, {
20699
20948
  className: "flex-1",
@@ -20702,18 +20951,30 @@ function NodeHeadContextMenu({ canvasStore, children }) {
20702
20951
  align: "start",
20703
20952
  className: NodeHead_module_default.menu,
20704
20953
  container: getPopupContainer(),
20705
- children: /* @__PURE__ */ jsx(ContextMenuGroup, { children: items.map((item) => item && /* @__PURE__ */ jsxs(ContextMenuItem, {
20954
+ children: /* @__PURE__ */ jsxs(ContextMenuGroup, { children: [items.map((item) => item && /* @__PURE__ */ jsxs(ContextMenuItem, {
20706
20955
  disabled: item.disabled,
20707
20956
  onClick: item.onClick,
20708
20957
  variant: item.danger ? "destructive" : "default",
20709
20958
  children: [item.icon, item.label]
20710
- }, item.key)) })
20959
+ }, item.key)), resetWidth && /* @__PURE__ */ jsx(ContextMenuItem, {
20960
+ onClick: () => void canvasStore.changeNodeWidth(nodeStore.nodeId, void 0),
20961
+ children: t("nodeWidth.reset")
20962
+ })] })
20711
20963
  })] });
20712
20964
  }
20713
20965
  function useNodeMenuItems({ t, nodeStore, onDelete, editable }) {
20714
20966
  const skip = useVal(NodeStore.to(nodeStore)?.ignore);
20715
20967
  const { duplicateNode } = nodeStore;
20968
+ const history = useContext(NodeHistoryContext)?.(nodeStore.nodeId);
20716
20969
  return coalesce([
20970
+ history && {
20971
+ ...history,
20972
+ key: "$history",
20973
+ icon: /* @__PURE__ */ jsx("i", {
20974
+ "aria-hidden": "true",
20975
+ className: "i-lucide-light:database"
20976
+ })
20977
+ },
20717
20978
  editable && duplicateNode && {
20718
20979
  label: t("nodeActions.duplicate"),
20719
20980
  key: "$duplicate",
@@ -20844,6 +21105,61 @@ function CommentCard({ store }) {
20844
21105
  })
20845
21106
  });
20846
21107
  }
21108
+ //#endregion
21109
+ //#region src/canvas/browser/graph/Nodes/components/ConditionWidthControls.tsx
21110
+ function ConditionWidthControls({ canvasStore, nodeStore, minimum, width, onPreview }) {
21111
+ const t = useTranslate();
21112
+ const origin = useRef();
21113
+ const [saving, setSaving] = useState(false);
21114
+ const start = () => {
21115
+ origin.current = nodeStore.$.position.value;
21116
+ };
21117
+ const cancel = () => {
21118
+ if (origin.current) nodeStore.$$.position.set(origin.current);
21119
+ origin.current = void 0;
21120
+ onPreview(void 0);
21121
+ };
21122
+ const preview = (change) => {
21123
+ if (!origin.current) return;
21124
+ onPreview(change.width);
21125
+ nodeStore.$$.position.set({
21126
+ x: origin.current.x + change.offsetX,
21127
+ y: origin.current.y
21128
+ });
21129
+ };
21130
+ const commit = async (change) => {
21131
+ const previousPosition = origin.current;
21132
+ origin.current = void 0;
21133
+ setSaving(true);
21134
+ const position = change.offsetX === 0 ? void 0 : nodeStore.$.position.value;
21135
+ try {
21136
+ if (!await canvasStore.changeNodeWidth(nodeStore.nodeId, change.width, position) && previousPosition) nodeStore.$$.position.set(previousPosition);
21137
+ } finally {
21138
+ onPreview(void 0);
21139
+ setSaving(false);
21140
+ }
21141
+ };
21142
+ return ["left", "right"].map((side) => /* @__PURE__ */ jsx(NodeResizeHandle, {
21143
+ className: `${NodeLayout_module_default.widthResize} ${side === "left" ? NodeLayout_module_default.widthResizeLeft : NodeLayout_module_default.widthResizeRight}`,
21144
+ label: t(side === "left" ? "nodeWidth.resizeLeft" : "nodeWidth.resizeRight"),
21145
+ position: side,
21146
+ showTooltip: false,
21147
+ size: {
21148
+ width,
21149
+ height: 0
21150
+ },
21151
+ minimum: {
21152
+ width: minimum,
21153
+ height: 0
21154
+ },
21155
+ disabled: saving,
21156
+ onStart: start,
21157
+ onResize: preview,
21158
+ onCommit: (change) => void commit(change),
21159
+ onCancel: cancel,
21160
+ onReset: () => void canvasStore.changeNodeWidth(nodeStore.nodeId, void 0)
21161
+ }, side));
21162
+ }
20847
21163
  var NodeMinimap_module_default = { wrapper: "NodeMinimap_wrapper_e79d7" };
20848
21164
  //#endregion
20849
21165
  //#region src/canvas/browser/graph/Nodes/components/NodeMinimap.tsx
@@ -20861,9 +21177,11 @@ function NodeMimimapContent() {
20861
21177
  }
20862
21178
  //#endregion
20863
21179
  //#region src/canvas/browser/graph/Nodes/components/NodeLayout.tsx
20864
- var CARD_WIDTH = 320;
20865
21180
  function ConditionOperand({ operand }) {
20866
- if (typeof operand == "string") return operand;
21181
+ if (typeof operand == "string") return /* @__PURE__ */ jsx("span", {
21182
+ className: NodeLayout_module_default.branchOperand,
21183
+ children: operand
21184
+ });
20867
21185
  if (operand.kind == "environment") return /* @__PURE__ */ jsx("i", {
20868
21186
  "aria-label": operand.label,
20869
21187
  className: "i-lucide-light:sliders-horizontal",
@@ -20889,7 +21207,10 @@ function ConditionRule({ item, t }) {
20889
21207
  className: NodeLayout_module_default.branchExpression,
20890
21208
  children: [
20891
21209
  /* @__PURE__ */ jsx(ConditionOperand, { operand: expression.left }),
20892
- /* @__PURE__ */ jsx("span", { children: conditionOperatorSummary(expression.operator, t) }),
21210
+ /* @__PURE__ */ jsx("span", {
21211
+ className: NodeLayout_module_default.branchOperator,
21212
+ children: conditionOperatorSummary(expression.operator, t)
21213
+ }),
20893
21214
  expression.right !== void 0 && /* @__PURE__ */ jsx(ConditionOperand, { operand: expression.right }),
20894
21215
  expressionIndex < group.expressions.length - 1 && /* @__PURE__ */ jsx("span", { children: "∧" })
20895
21216
  ]
@@ -20907,14 +21228,35 @@ function ConditionRule({ item, t }) {
20907
21228
  }
20908
21229
  var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
20909
21230
  const t = useTranslate();
21231
+ const direction = useVal(canvasStore.$.direction);
21232
+ const vertical = direction === "vertical";
21233
+ const updateNodeInternals = useUpdateNodeInternals();
20910
21234
  const modelNode = useVal(NodeStore.to(nodeStore)?.content$);
20911
21235
  const annotation = useNodeAnnotation(modelNode);
20912
21236
  const branches = modelNode?.kind == "condition" || modelNode?.kind == "approval" || modelNode?.kind == "wait" ? modelNode.outputs.flatMap((port) => "handle" in port ? [port.handle] : []) : void 0;
21237
+ const branchHandles = branches?.join("\0");
21238
+ const [previewWidth, setPreviewWidth] = useState();
21239
+ const minimumWidth = minimumCanvasCardWidth(direction, branches?.length ?? 0);
21240
+ const savedWidth = modelNode?.kind === "condition" ? modelNode.verticalWidth : void 0;
21241
+ const width = canvasCardWidth(direction, branches?.length ?? 0, previewWidth ?? savedWidth);
21242
+ useLayoutEffect(() => {
21243
+ const frame = requestAnimationFrame(() => updateNodeInternals(nodeStore.rfNodeId));
21244
+ return () => cancelAnimationFrame(frame);
21245
+ }, [
21246
+ direction,
21247
+ branchHandles,
21248
+ width,
21249
+ nodeStore.rfNodeId,
21250
+ updateNodeInternals
21251
+ ]);
21252
+ useEffect(() => {
21253
+ setPreviewWidth(void 0);
21254
+ }, [direction]);
20913
21255
  const executionInput = modelNode != null && modelNode.kind != "trigger" && modelNode.kind != "value";
20914
21256
  const editable = useVal(canvasStore.$.editable);
20915
21257
  const selected = useVal(nodeStore.$.selected);
20916
21258
  const showError = useShowNodeError(nodeStore);
20917
- const problem = showError ? t("nodeStatus.hasError") : modelNode?.run?.status == "error" ? t("canvasCard.status.error") : void 0;
21259
+ const diagnostic = showError ? t("nodeStatus.hasError") : void 0;
20918
21260
  const [hovered, setHovered] = useState(false);
20919
21261
  const [hintTriggered, setHintTriggered] = useState(false);
20920
21262
  const hintRequested = !showError && hintTriggered && (hovered || selected === true) && visible;
@@ -20938,61 +21280,72 @@ var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
20938
21280
  const initialized = useVal(canvasStore.$.initialized);
20939
21281
  const animateEntry = useRef(initialized).current;
20940
21282
  const executionPortColor = useVal(cardStore?.$.executionPortColor);
20941
- const problemColor = problem ? "var(--accent-red-1)" : void 0;
21283
+ const hasError = showError || modelNode?.run?.status === "error";
21284
+ const errorColor = hasError ? "var(--accent-red-1)" : void 0;
20942
21285
  const conditionNode = modelNode?.kind == "condition" ? modelNode : void 0;
20943
21286
  const containerStyle = {
20944
- width: cardStore ? CARD_WIDTH : void 0,
20945
- ["--node-selected-border-color"]: problemColor,
21287
+ width: cardStore ? width : void 0,
21288
+ ["--branch-count"]: branches?.length ?? 0,
21289
+ ["--branch-gap"]: `6px`,
21290
+ ["--branch-inline-padding"]: `8px`,
21291
+ ["--node-selected-border-color"]: errorColor,
21292
+ ["--header-handle-y"]: `38px`,
20946
21293
  ["--execution-port-color"]: executionPortColor,
20947
- ["--execution-port-active-color"]: problemColor,
20948
- ["--execution-port-overlap"]: problem ? "1px" : void 0,
21294
+ ["--execution-port-active-color"]: errorColor,
21295
+ ["--execution-port-overlap"]: hasError ? "1px" : void 0,
20949
21296
  ["--node-selected-shadow"]: showError ? "var(--node-error-selected-shadow)" : void 0
20950
21297
  };
20951
21298
  const card = cardStore ? /* @__PURE__ */ jsx(CanvasNode, {
20952
21299
  nodeStore: cardStore,
20953
21300
  compact: canvasMiniMapPhase !== NodeMiniMapPhase.None,
20954
21301
  compactContent,
20955
- problem,
20956
- branches: branches?.map((branch) => {
20957
- const conditionCase = conditionNode?.cases.find((item) => item.output == branch);
20958
- const caseDescription = conditionCase?.description?.trim() || void 0;
20959
- const summary = conditionNode != null ? conditionBranchSummary(conditionNode, branch, t) : modelNode?.kind == "approval" || modelNode?.kind == "wait" ? t(`canvasCard.waitBranch.${branch}`) : "";
20960
- const tooltip = modelNode?.kind == "approval" || modelNode?.kind == "wait" ? waitBranchDescription(t, modelNode.kind, branch) : conditionNode?.defaultOutput === branch ? t("condition.defaultHelp") : void 0;
20961
- return /* @__PURE__ */ jsx(CanvasTooltip, {
20962
- placement: "top",
20963
- sideOffset: 12,
20964
- title: tooltip,
20965
- children: /* @__PURE__ */ jsxs("div", {
20966
- className: clsx(NodeLayout_module_default.executionBranch, NodeLayout_module_default.branchRow),
20967
- tabIndex: tooltip ? 0 : void 0,
20968
- children: [
20969
- summary && /* @__PURE__ */ jsx("span", {
20970
- className: NodeLayout_module_default.branchRule,
20971
- style: conditionNode && branch !== conditionNode.defaultOutput ? { color: problemColor } : void 0,
20972
- title: conditionNode && !tooltip ? summary : void 0,
20973
- children: conditionCase != null && caseDescription == null && conditionCaseHasExpressions(conditionCase) && (conditionNode?.diagnostics ?? 0) === 0 && conditionNode?.run?.status !== "error" ? /* @__PURE__ */ jsx(ConditionRule, {
20974
- item: conditionCase,
20975
- t
20976
- }) : summary
20977
- }),
20978
- summary && /* @__PURE__ */ jsx("span", {
20979
- "aria-hidden": "true",
20980
- className: NodeLayout_module_default.branchArrow,
20981
- children: "→"
20982
- }),
20983
- /* @__PURE__ */ jsx("span", {
20984
- className: NodeLayout_module_default.branchName,
20985
- children: conditionNode?.defaultOutput === branch ? "default" : branch
20986
- }),
20987
- /* @__PURE__ */ jsx(ExecutionHandle, {
21302
+ diagnostic,
21303
+ branches: branches && /* @__PURE__ */ jsx("div", {
21304
+ className: NodeLayout_module_default.branchList,
21305
+ children: branches.map((branch) => {
21306
+ const conditionCase = conditionNode?.cases.find((item) => item.output == branch);
21307
+ const caseDescription = conditionCase?.description?.trim() || void 0;
21308
+ const summary = conditionNode != null ? conditionBranchSummary(conditionNode, branch, t) : modelNode?.kind == "approval" || modelNode?.kind == "wait" ? t(`canvasCard.waitBranch.${branch}`) : "";
21309
+ const tooltip = modelNode?.kind == "approval" || modelNode?.kind == "wait" ? waitBranchDescription(t, modelNode.kind, branch) : conditionNode?.defaultOutput === branch ? t("condition.defaultHelp") : void 0;
21310
+ return /* @__PURE__ */ jsx(CanvasTooltip, {
21311
+ placement: "top",
21312
+ sideOffset: 12,
21313
+ title: tooltip,
21314
+ children: /* @__PURE__ */ jsxs("div", {
21315
+ className: NodeLayout_module_default.branchRow,
21316
+ tabIndex: tooltip ? 0 : void 0,
21317
+ children: [/* @__PURE__ */ jsxs("div", {
21318
+ className: NodeLayout_module_default.branchContent,
21319
+ children: [
21320
+ summary && /* @__PURE__ */ jsx("span", {
21321
+ className: NodeLayout_module_default.branchRule,
21322
+ style: conditionNode && branch !== conditionNode.defaultOutput ? { color: errorColor } : void 0,
21323
+ title: conditionNode && !tooltip ? summary : void 0,
21324
+ children: conditionCase != null && caseDescription == null && conditionCaseHasExpressions(conditionCase) && (conditionNode?.diagnostics ?? 0) === 0 && conditionNode?.run?.status !== "error" ? /* @__PURE__ */ jsx(ConditionRule, {
21325
+ item: conditionCase,
21326
+ t
21327
+ }) : summary
21328
+ }),
21329
+ summary && /* @__PURE__ */ jsx("span", {
21330
+ "aria-hidden": "true",
21331
+ className: NodeLayout_module_default.branchArrow,
21332
+ children: "→"
21333
+ }),
21334
+ /* @__PURE__ */ jsx("span", {
21335
+ className: NodeLayout_module_default.branchName,
21336
+ children: conditionNode?.defaultOutput === branch ? "default" : branch
21337
+ })
21338
+ ]
21339
+ }), /* @__PURE__ */ jsx(ExecutionHandle, {
20988
21340
  id: toRFHandleName(`$branch:${branch}`),
20989
21341
  type: "output",
21342
+ position: vertical ? "bottom" : "right",
20990
21343
  isConnectable: editable,
20991
21344
  hintRequested
20992
- })
20993
- ]
20994
- })
20995
- }, branch);
21345
+ })]
21346
+ })
21347
+ }, branch);
21348
+ })
20996
21349
  })
20997
21350
  }) : void 0;
20998
21351
  return /* @__PURE__ */ jsx(NodeMiniMapProvider, {
@@ -21001,6 +21354,7 @@ var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
21001
21354
  value: nodeStore,
21002
21355
  children: /* @__PURE__ */ jsx("div", {
21003
21356
  ...annotation,
21357
+ style: { padding: 8 },
21004
21358
  className: clsx(NodeLayout_module_default.outerContainer, animateEntry && NodeLayout_module_default.enter, !initialized && "open-flow-canvas-fitting-view", nodeMiniMapPhase >= NodeMiniMapPhase.Phase1 && "open-flow-canvas-node-minimap1", nodeMiniMapPhase >= NodeMiniMapPhase.Phase2 && "open-flow-canvas-node-minimap2"),
21005
21359
  children: /* @__PURE__ */ jsxs("div", {
21006
21360
  className: clsx(NodeLayout_module_default.offsetContainer, skip && NodeLayout_module_default.skipOuter),
@@ -21015,33 +21369,45 @@ var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
21015
21369
  if (event.pointerType !== "touch") setHovered(true);
21016
21370
  },
21017
21371
  onPointerLeave: () => setHovered(false),
21018
- className: clsx(NodeLayout_module_default.container, NodeLayout_module_default.cardContainer, canvasMiniMapPhase !== NodeMiniMapPhase.None && NodeLayout_module_default.compact, compactContent && NodeLayout_module_default.compactContent, skip && NodeLayout_module_default.skip),
21372
+ className: clsx(NodeLayout_module_default.container, NodeLayout_module_default.cardContainer, vertical && NodeLayout_module_default.vertical, canvasMiniMapPhase !== NodeMiniMapPhase.None && NodeLayout_module_default.compact, compactContent && NodeLayout_module_default.compactContent, skip && NodeLayout_module_default.skip),
21019
21373
  style: containerStyle,
21020
- children: [modelNode?.kind === "trigger" && /* @__PURE__ */ jsx(Zap, {
21021
- "aria-hidden": "true",
21022
- className: NodeLayout_module_default.triggerIcon,
21023
- strokeWidth: 1.5
21024
- }), /* @__PURE__ */ jsxs("div", {
21025
- className: NodeLayout_module_default.executionHead,
21026
- children: [
21027
- card ? /* @__PURE__ */ jsx(NodeHeadContextMenu, {
21028
- canvasStore,
21029
- children: card
21030
- }) : CommentNodeStore.is(nodeStore) ? /* @__PURE__ */ jsx(CommentCard, { store: nodeStore }) : null,
21031
- executionInput && /* @__PURE__ */ jsx(ExecutionHandle, {
21032
- id: toRFHandleName("$in"),
21033
- type: "input",
21034
- isConnectable: editable,
21035
- hintRequested
21036
- }),
21037
- nodeStore.nodeType != NODE_TYPE.CommentNode && modelNode?.kind != "outputs" && branches == null && /* @__PURE__ */ jsx(ExecutionHandle, {
21038
- id: toRFHandleName("$out"),
21039
- type: "output",
21040
- isConnectable: editable,
21041
- hintRequested
21042
- })
21043
- ]
21044
- })]
21374
+ children: [
21375
+ modelNode?.kind === "trigger" && /* @__PURE__ */ jsx(Zap, {
21376
+ "aria-hidden": "true",
21377
+ className: NodeLayout_module_default.triggerIcon,
21378
+ strokeWidth: 1.5
21379
+ }),
21380
+ /* @__PURE__ */ jsxs("div", {
21381
+ className: NodeLayout_module_default.executionHead,
21382
+ children: [
21383
+ card ? /* @__PURE__ */ jsx(NodeHeadContextMenu, {
21384
+ canvasStore,
21385
+ children: card
21386
+ }) : CommentNodeStore.is(nodeStore) ? /* @__PURE__ */ jsx(CommentCard, { store: nodeStore }) : null,
21387
+ executionInput && /* @__PURE__ */ jsx(ExecutionHandle, {
21388
+ id: toRFHandleName("$in"),
21389
+ type: "input",
21390
+ position: vertical ? "top" : "left",
21391
+ isConnectable: editable,
21392
+ hintRequested
21393
+ }),
21394
+ nodeStore.nodeType != NODE_TYPE.CommentNode && modelNode?.kind != "outputs" && branches == null && /* @__PURE__ */ jsx(ExecutionHandle, {
21395
+ id: toRFHandleName("$out"),
21396
+ type: "output",
21397
+ position: vertical ? "bottom" : "right",
21398
+ isConnectable: editable,
21399
+ hintRequested
21400
+ })
21401
+ ]
21402
+ }),
21403
+ cardStore && vertical && conditionNode && editable && canvasStore.canChangeNodeWidth && /* @__PURE__ */ jsx(ConditionWidthControls, {
21404
+ canvasStore,
21405
+ nodeStore: cardStore,
21406
+ minimum: minimumWidth,
21407
+ width,
21408
+ onPreview: setPreviewWidth
21409
+ })
21410
+ ]
21045
21411
  })
21046
21412
  ]
21047
21413
  })
@@ -21049,7 +21415,7 @@ var NodeLayout = /* @__PURE__ */ memo(({ canvasStore, nodeStore, visible }) => {
21049
21415
  })
21050
21416
  });
21051
21417
  });
21052
- function ExecutionHandle({ id, type, isConnectable, hintRequested }) {
21418
+ function ExecutionHandle({ id, type, position, isConnectable, hintRequested }) {
21053
21419
  const handleType = type == "input" ? "target" : "source";
21054
21420
  const sideConnections = useNodeConnections({ handleType });
21055
21421
  const connecting = useConnection((connection) => connection.inProgress && connection.fromHandle.type != handleType);
@@ -21075,12 +21441,13 @@ function ExecutionHandle({ id, type, isConnectable, hintRequested }) {
21075
21441
  return /* @__PURE__ */ jsx(Handle, {
21076
21442
  id,
21077
21443
  type,
21444
+ position,
21078
21445
  isConnectable,
21079
21446
  className: clsx(NodeLayout_module_default.executionHandle, sideConnections.length > 0 && NodeLayout_module_default.connected, isConnectable && connecting && NodeLayout_module_default.connecting),
21080
21447
  children: canHint && hintMounted && /* @__PURE__ */ jsx("span", {
21081
21448
  "aria-hidden": "true",
21082
- className: clsx(NodeLayout_module_default.connectionHint, type === "input" && NodeLayout_module_default.inputHint, (!showHint || hintFinished) && NodeLayout_module_default.hintLeaving),
21083
- children: /* @__PURE__ */ jsx("i", { className: type === "input" ? "i-lucide:chevron-left" : "i-lucide:chevron-right" })
21449
+ className: clsx(NodeLayout_module_default.connectionHint, position && NodeLayout_module_default[`${position}Hint`], (!showHint || hintFinished) && NodeLayout_module_default.hintLeaving),
21450
+ children: /* @__PURE__ */ jsx("i", { className: position === "top" ? "i-lucide-light:chevron-up" : position === "bottom" ? "i-lucide-light:chevron-down" : position === "left" ? "i-lucide-light:chevron-left" : "i-lucide-light:chevron-right" })
21084
21451
  })
21085
21452
  });
21086
21453
  }
@@ -21227,27 +21594,27 @@ var fitViewOptions = {
21227
21594
  maxZoom: 1
21228
21595
  };
21229
21596
  var ReactFlowContainer_module_default = {
21230
- container: "ReactFlowContainer_container_b3d0e",
21231
- flow: "ReactFlowContainer_flow_b3d0e",
21232
- contextMenu: "ReactFlowContainer_contextMenu_b3d0e",
21233
- movingLayout: "ReactFlowContainer_movingLayout_b3d0e",
21234
- layoutPending: "ReactFlowContainer_layoutPending_b3d0e",
21235
- dock: "ReactFlowContainer_dock_b3d0e",
21236
- viewDock: "ReactFlowContainer_viewDock_b3d0e",
21237
- expandedViewControls: "ReactFlowContainer_expandedViewControls_b3d0e",
21238
- viewOptionButtons: "ReactFlowContainer_viewOptionButtons_b3d0e",
21239
- compactViewControls: "ReactFlowContainer_compactViewControls_b3d0e",
21240
- createDock: "ReactFlowContainer_createDock_b3d0e",
21241
- zoomValue: "ReactFlowContainer_zoomValue_b3d0e",
21242
- interactiveModeTrigger: "ReactFlowContainer_interactiveModeTrigger_b3d0e",
21243
- interactiveModePanel: "ReactFlowContainer_interactiveModePanel_b3d0e",
21244
- interactiveModeChoices: "ReactFlowContainer_interactiveModeChoices_b3d0e",
21245
- interactiveModeChoice: "ReactFlowContainer_interactiveModeChoice_b3d0e",
21246
- dockActions: "ReactFlowContainer_dockActions_b3d0e",
21247
- miniMap: "ReactFlowContainer_miniMap_b3d0e",
21248
- viewOptions: "ReactFlowContainer_viewOptions_b3d0e",
21249
- viewOptionsClip: "ReactFlowContainer_viewOptionsClip_b3d0e",
21250
- viewSeparator: "ReactFlowContainer_viewSeparator_b3d0e"
21597
+ container: "ReactFlowContainer_container_40f4d",
21598
+ flow: "ReactFlowContainer_flow_40f4d",
21599
+ contextMenu: "ReactFlowContainer_contextMenu_40f4d",
21600
+ movingLayout: "ReactFlowContainer_movingLayout_40f4d",
21601
+ layoutPending: "ReactFlowContainer_layoutPending_40f4d",
21602
+ dock: "ReactFlowContainer_dock_40f4d",
21603
+ viewDock: "ReactFlowContainer_viewDock_40f4d",
21604
+ expandedViewControls: "ReactFlowContainer_expandedViewControls_40f4d",
21605
+ viewOptionButtons: "ReactFlowContainer_viewOptionButtons_40f4d",
21606
+ compactViewControls: "ReactFlowContainer_compactViewControls_40f4d",
21607
+ createDock: "ReactFlowContainer_createDock_40f4d",
21608
+ zoomValue: "ReactFlowContainer_zoomValue_40f4d",
21609
+ viewChoiceTrigger: "ReactFlowContainer_viewChoiceTrigger_40f4d",
21610
+ viewChoicePanel: "ReactFlowContainer_viewChoicePanel_40f4d",
21611
+ viewChoices: "ReactFlowContainer_viewChoices_40f4d",
21612
+ viewChoice: "ReactFlowContainer_viewChoice_40f4d",
21613
+ dockActions: "ReactFlowContainer_dockActions_40f4d",
21614
+ miniMap: "ReactFlowContainer_miniMap_40f4d",
21615
+ viewOptions: "ReactFlowContainer_viewOptions_40f4d",
21616
+ viewOptionsClip: "ReactFlowContainer_viewOptionsClip_40f4d",
21617
+ viewSeparator: "ReactFlowContainer_viewSeparator_40f4d"
21251
21618
  };
21252
21619
  //#endregion
21253
21620
  //#region src/canvas/browser/addItemDrag.ts
@@ -21293,6 +21660,636 @@ var isWithConditionType = (dataTransfer) => dataTransfer.types.includes(TRANSFER
21293
21660
  var isWithCommentType = (dataTransfer) => dataTransfer.types.includes(TRANSFER_COMMENT_KEY);
21294
21661
  var getTriggerType = (dataTransfer) => dataTransfer.getData(TRANSFER_TRIGGER_KEY);
21295
21662
  //#endregion
21663
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio/root/RadioRootDataAttributes.js
21664
+ var RadioRootDataAttributes = /*#__PURE__*/ function(RadioRootDataAttributes) {
21665
+ /**
21666
+ * Present when the radio is checked.
21667
+ */
21668
+ RadioRootDataAttributes["checked"] = "data-checked";
21669
+ /**
21670
+ * Present when the radio is not checked.
21671
+ */
21672
+ RadioRootDataAttributes["unchecked"] = "data-unchecked";
21673
+ /**
21674
+ * Present when the radio is disabled.
21675
+ */
21676
+ RadioRootDataAttributes["disabled"] = "data-disabled";
21677
+ /**
21678
+ * Present when the radio is readonly.
21679
+ */
21680
+ RadioRootDataAttributes["readonly"] = "data-readonly";
21681
+ /**
21682
+ * Present when the radio is required.
21683
+ */
21684
+ RadioRootDataAttributes["required"] = "data-required";
21685
+ /**
21686
+ * Present when the radio is in a valid state (when wrapped in Field.Root).
21687
+ */
21688
+ RadioRootDataAttributes["valid"] = "data-valid";
21689
+ /**
21690
+ * Present when the radio is in an invalid state (when wrapped in Field.Root).
21691
+ */
21692
+ RadioRootDataAttributes["invalid"] = "data-invalid";
21693
+ /**
21694
+ * Present when the radio has been touched (when wrapped in Field.Root).
21695
+ */
21696
+ RadioRootDataAttributes["touched"] = "data-touched";
21697
+ /**
21698
+ * Present when the radio's value has changed (when wrapped in Field.Root).
21699
+ */
21700
+ RadioRootDataAttributes["dirty"] = "data-dirty";
21701
+ /**
21702
+ * Present when the radio is checked (when wrapped in Field.Root).
21703
+ */
21704
+ RadioRootDataAttributes["filled"] = "data-filled";
21705
+ /**
21706
+ * Present when the radio is focused (when wrapped in Field.Root).
21707
+ */
21708
+ RadioRootDataAttributes["focused"] = "data-focused";
21709
+ return RadioRootDataAttributes;
21710
+ }({});
21711
+ //#endregion
21712
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio/utils/stateAttributesMapping.js
21713
+ var stateAttributesMapping = {
21714
+ checked(value) {
21715
+ if (value) return { [RadioRootDataAttributes.checked]: "" };
21716
+ return { [RadioRootDataAttributes.unchecked]: "" };
21717
+ },
21718
+ ...transitionStatusMapping,
21719
+ ...fieldValidityMapping
21720
+ };
21721
+ //#endregion
21722
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/constants.js
21723
+ var ACTIVE_COMPOSITE_ITEM = "data-composite-item-active";
21724
+ //#endregion
21725
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio-group/RadioGroupContext.js
21726
+ var RadioGroupContext = /*#__PURE__*/ React.createContext(void 0);
21727
+ if (process.env.NODE_ENV !== "production") RadioGroupContext.displayName = "RadioGroupContext";
21728
+ function useRadioGroupContext() {
21729
+ return React.useContext(RadioGroupContext);
21730
+ }
21731
+ //#endregion
21732
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio/root/RadioRootContext.js
21733
+ var RadioRootContext = /*#__PURE__*/ React.createContext(void 0);
21734
+ if (process.env.NODE_ENV !== "production") RadioRootContext.displayName = "RadioRootContext";
21735
+ //#endregion
21736
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio/root/RadioRoot.js
21737
+ /**
21738
+ * Represents the radio button itself.
21739
+ * Renders a `<span>` element and a hidden `<input>` beside.
21740
+ *
21741
+ * Documentation: [Base UI Radio](https://base-ui.com/react/components/radio)
21742
+ */
21743
+ var RadioRoot = /*#__PURE__*/ React.forwardRef(function RadioRoot(componentProps, forwardedRef) {
21744
+ const { render, className, disabled: disabledProp = false, readOnly: readOnlyProp = false, required: requiredProp = false, "aria-labelledby": ariaLabelledByProp, value, inputRef: inputRefProp, nativeButton = false, id: idProp, style, ...elementProps } = componentProps;
21745
+ const groupContext = useRadioGroupContext();
21746
+ const { disabled: disabledGroup, readOnly: readOnlyGroup, required: requiredGroup, form: formGroup, checkedValue, touched = false, validation, name } = groupContext ?? {};
21747
+ const setCheckedValue = groupContext?.setCheckedValue ?? NOOP;
21748
+ const setTouched = groupContext?.setTouched ?? NOOP;
21749
+ const registerControlRef = groupContext?.registerControlRef ?? NOOP;
21750
+ const registerInputRef = groupContext?.registerInputRef ?? NOOP;
21751
+ const { setDirty, validityData, setTouched: setFieldTouched, setFilled, state: fieldState, disabled: fieldDisabled } = useFieldRootContext();
21752
+ const fieldItemContext = useFieldItemContext();
21753
+ const { labelId, getDescriptionProps } = useLabelableContext();
21754
+ const disabled = fieldDisabled || fieldItemContext.disabled || disabledGroup || disabledProp;
21755
+ const readOnly = readOnlyGroup || readOnlyProp;
21756
+ const required = requiredGroup || requiredProp;
21757
+ const form = formGroup;
21758
+ const checked = groupContext ? checkedValue === value : value === "";
21759
+ const serializedValue = React.useMemo(() => serializeValue(value), [value]);
21760
+ const radioRef = React.useRef(null);
21761
+ const inputRef = React.useRef(null);
21762
+ const handleControlRef = useStableCallback((element) => {
21763
+ if (!element) return;
21764
+ registerControlRef(element, disabled);
21765
+ });
21766
+ const mergedInputRef = useMergedRefs(inputRefProp, inputRef, registerInputRef);
21767
+ useIsoLayoutEffect(() => {
21768
+ if (inputRef.current?.checked) setFilled(true);
21769
+ }, [setFilled]);
21770
+ useIsoLayoutEffect(() => {
21771
+ if (!inputRef.current) return;
21772
+ if (disabled && checked) {
21773
+ registerInputRef(null);
21774
+ return;
21775
+ }
21776
+ if (radioRef.current) registerControlRef(radioRef.current, disabled);
21777
+ registerInputRef(inputRef.current);
21778
+ }, [
21779
+ checked,
21780
+ disabled,
21781
+ registerControlRef,
21782
+ registerInputRef
21783
+ ]);
21784
+ const id = useBaseUiId();
21785
+ const inputId = useLabelableId({
21786
+ id: idProp,
21787
+ implicit: false,
21788
+ controlRef: radioRef
21789
+ });
21790
+ const hiddenInputId = nativeButton ? void 0 : inputId;
21791
+ const ariaLabelledBy = useAriaLabelledBy(ariaLabelledByProp, labelId, inputRef, !nativeButton, hiddenInputId);
21792
+ const rootProps = {
21793
+ role: "radio",
21794
+ "aria-checked": checked,
21795
+ "aria-required": required || void 0,
21796
+ "aria-readonly": readOnly || void 0,
21797
+ "aria-labelledby": ariaLabelledBy,
21798
+ [ACTIVE_COMPOSITE_ITEM]: checked ? "" : void 0,
21799
+ id: nativeButton ? inputId : id,
21800
+ onKeyDown(event) {
21801
+ if (event.key === "Enter") event.preventDefault();
21802
+ },
21803
+ onClick(event) {
21804
+ if (event.defaultPrevented || disabled || readOnly) return;
21805
+ event.preventDefault();
21806
+ inputRef.current?.dispatchEvent(new PointerEvent("click", {
21807
+ bubbles: true,
21808
+ shiftKey: event.shiftKey,
21809
+ ctrlKey: event.ctrlKey,
21810
+ altKey: event.altKey,
21811
+ metaKey: event.metaKey
21812
+ }));
21813
+ },
21814
+ onFocus(event) {
21815
+ if (event.defaultPrevented || disabled || readOnly || !touched) return;
21816
+ inputRef.current?.click();
21817
+ setTouched(false);
21818
+ }
21819
+ };
21820
+ const { getButtonProps, buttonRef } = useButton({
21821
+ disabled,
21822
+ native: nativeButton
21823
+ });
21824
+ const inputProps = {
21825
+ type: "radio",
21826
+ ref: mergedInputRef,
21827
+ form,
21828
+ id: hiddenInputId,
21829
+ name,
21830
+ tabIndex: -1,
21831
+ style: name ? visuallyHiddenInput : visuallyHidden,
21832
+ "aria-hidden": true,
21833
+ ...value !== void 0 ? { value: serializedValue } : EMPTY_OBJECT,
21834
+ disabled,
21835
+ checked,
21836
+ required,
21837
+ readOnly,
21838
+ onChange(event) {
21839
+ if (event.nativeEvent.defaultPrevented) return;
21840
+ if (disabled || readOnly || value === void 0) return;
21841
+ const details = createChangeEventDetails(none$1, event.nativeEvent);
21842
+ if (details.isCanceled) return;
21843
+ setFieldTouched(true);
21844
+ setDirty(value !== validityData.initialValue);
21845
+ setFilled(true);
21846
+ setCheckedValue(value, details);
21847
+ },
21848
+ onFocus() {
21849
+ radioRef.current?.focus();
21850
+ }
21851
+ };
21852
+ const state = React.useMemo(() => ({
21853
+ ...fieldState,
21854
+ required,
21855
+ disabled,
21856
+ readOnly,
21857
+ checked
21858
+ }), [
21859
+ fieldState,
21860
+ disabled,
21861
+ readOnly,
21862
+ checked,
21863
+ required
21864
+ ]);
21865
+ const contextValue = state;
21866
+ const isRadioGroup = groupContext !== void 0;
21867
+ const refs = [
21868
+ forwardedRef,
21869
+ radioRef,
21870
+ buttonRef,
21871
+ handleControlRef
21872
+ ];
21873
+ const props = [
21874
+ rootProps,
21875
+ getDescriptionProps,
21876
+ validation?.getValidationProps ?? EMPTY_OBJECT,
21877
+ elementProps,
21878
+ getButtonProps
21879
+ ];
21880
+ const element = useRenderElement("span", componentProps, {
21881
+ enabled: !isRadioGroup,
21882
+ state,
21883
+ ref: refs,
21884
+ props,
21885
+ stateAttributesMapping
21886
+ });
21887
+ return /*#__PURE__*/ jsxs(RadioRootContext.Provider, {
21888
+ value: contextValue,
21889
+ children: [isRadioGroup ? /*#__PURE__*/ jsx(CompositeItem, {
21890
+ tag: "span",
21891
+ render,
21892
+ className,
21893
+ style,
21894
+ state,
21895
+ refs,
21896
+ props,
21897
+ stateAttributesMapping
21898
+ }) : element, /*#__PURE__*/ jsx("input", {
21899
+ ...inputProps,
21900
+ suppressHydrationWarning: true
21901
+ })]
21902
+ });
21903
+ });
21904
+ if (process.env.NODE_ENV !== "production") RadioRoot.displayName = "RadioRoot";
21905
+ //#endregion
21906
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/useCompositeRoot.js
21907
+ var EMPTY_ARRAY = [];
21908
+ function useCompositeRoot(params) {
21909
+ const { itemSizes, cols = 1, loopFocus = true, onLoop, dense = false, orientation = "both", direction, highlightedIndex: externalHighlightedIndex, onHighlightedIndexChange: externalSetHighlightedIndex, rootRef: externalRef, enableHomeAndEndKeys = false, stopEventPropagation = false, disabledIndices, modifierKeys = EMPTY_ARRAY } = params;
21910
+ const [internalHighlightedIndex, internalSetHighlightedIndex] = React.useState(0);
21911
+ const isGrid = cols > 1;
21912
+ const rootRef = React.useRef(null);
21913
+ const mergedRef = useMergedRefs(rootRef, externalRef);
21914
+ const elementsRef = React.useRef([]);
21915
+ const hasSetDefaultIndexRef = React.useRef(false);
21916
+ const highlightedIndex = externalHighlightedIndex ?? internalHighlightedIndex;
21917
+ const onHighlightedIndexChange = useStableCallback((index, shouldScrollIntoView = false) => {
21918
+ (externalSetHighlightedIndex ?? internalSetHighlightedIndex)(index);
21919
+ if (shouldScrollIntoView) {
21920
+ const newActiveItem = elementsRef.current[index];
21921
+ scrollIntoViewIfNeeded(rootRef.current, newActiveItem, direction, orientation);
21922
+ }
21923
+ });
21924
+ const onMapChange = useStableCallback((map) => {
21925
+ if (map.size === 0 || hasSetDefaultIndexRef.current) return;
21926
+ hasSetDefaultIndexRef.current = true;
21927
+ const sortedElements = Array.from(map.keys());
21928
+ const activeItem = sortedElements.find((compositeElement) => compositeElement?.hasAttribute("data-composite-item-active")) ?? null;
21929
+ const activeIndex = activeItem ? sortedElements.indexOf(activeItem) : -1;
21930
+ if (activeIndex !== -1) onHighlightedIndexChange(activeIndex);
21931
+ scrollIntoViewIfNeeded(rootRef.current, activeItem, direction, orientation);
21932
+ });
21933
+ const wrappedOnLoop = useStableCallback((event, prevIndex, nextIndex) => {
21934
+ if (!onLoop) return nextIndex;
21935
+ return onLoop?.(event, prevIndex, nextIndex, elementsRef);
21936
+ });
21937
+ const props = React.useMemo(() => ({
21938
+ "aria-orientation": orientation === "both" ? void 0 : orientation,
21939
+ ref: mergedRef,
21940
+ onFocus(event) {
21941
+ const element = rootRef.current;
21942
+ const target = getTarget(event.nativeEvent);
21943
+ if (!element || target == null || !isNativeInput(target)) return;
21944
+ target.setSelectionRange(0, target.value.length ?? 0);
21945
+ },
21946
+ onKeyDown(event) {
21947
+ const RELEVANT_KEYS = enableHomeAndEndKeys ? ALL_KEYS : ARROW_KEYS;
21948
+ if (!RELEVANT_KEYS.has(event.key)) return;
21949
+ if (isModifierKeySet(event, modifierKeys)) return;
21950
+ if (!rootRef.current) return;
21951
+ const isRtl = direction === "rtl";
21952
+ const horizontalForwardKey = isRtl ? ARROW_LEFT : ARROW_RIGHT;
21953
+ const forwardKey = {
21954
+ horizontal: horizontalForwardKey,
21955
+ vertical: ARROW_DOWN,
21956
+ both: horizontalForwardKey
21957
+ }[orientation];
21958
+ const horizontalBackwardKey = isRtl ? ARROW_RIGHT : ARROW_LEFT;
21959
+ const backwardKey = {
21960
+ horizontal: horizontalBackwardKey,
21961
+ vertical: ARROW_UP,
21962
+ both: horizontalBackwardKey
21963
+ }[orientation];
21964
+ const target = getTarget(event.nativeEvent);
21965
+ if (target != null && isNativeInput(target) && !isElementDisabled(target)) {
21966
+ const selectionStart = target.selectionStart;
21967
+ const selectionEnd = target.selectionEnd;
21968
+ const textContent = target.value ?? "";
21969
+ if (selectionStart == null || event.shiftKey || selectionStart !== selectionEnd) return;
21970
+ if (event.key !== backwardKey && selectionStart < textContent.length) return;
21971
+ if (event.key !== forwardKey && selectionStart > 0) return;
21972
+ }
21973
+ let nextIndex = highlightedIndex;
21974
+ const minIndex = getMinListIndex(elementsRef, disabledIndices);
21975
+ const maxIndex = getMaxListIndex(elementsRef, disabledIndices);
21976
+ if (isGrid) {
21977
+ const sizes = itemSizes || Array.from({ length: elementsRef.current.length }, () => ({
21978
+ width: 1,
21979
+ height: 1
21980
+ }));
21981
+ const cellMap = createGridCellMap(sizes, cols, dense);
21982
+ const minGridIndex = cellMap.findIndex((index) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices));
21983
+ const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices) ? cellIndex : foundIndex, -1);
21984
+ nextIndex = cellMap[getGridNavigatedIndex(cellMap.map((itemIndex) => itemIndex != null ? elementsRef.current[itemIndex] : null), {
21985
+ event,
21986
+ orientation,
21987
+ loopFocus,
21988
+ onLoop: wrappedOnLoop,
21989
+ cols,
21990
+ disabledIndices: getGridCellIndices([...disabledIndices || elementsRef.current.map((_, index) => isListIndexDisabled(elementsRef.current, index) ? index : void 0), void 0], cellMap),
21991
+ minIndex: minGridIndex,
21992
+ maxIndex: maxGridIndex,
21993
+ prevIndex: getGridCellIndexOfCorner(highlightedIndex > maxIndex ? minIndex : highlightedIndex, sizes, cellMap, cols, event.key === "ArrowDown" ? "bl" : event.key === "ArrowRight" ? "tr" : "tl"),
21994
+ rtl: isRtl
21995
+ })];
21996
+ }
21997
+ const forwardKeys = {
21998
+ horizontal: [horizontalForwardKey],
21999
+ vertical: [ARROW_DOWN],
22000
+ both: [horizontalForwardKey, ARROW_DOWN]
22001
+ }[orientation];
22002
+ const backwardKeys = {
22003
+ horizontal: [horizontalBackwardKey],
22004
+ vertical: [ARROW_UP],
22005
+ both: [horizontalBackwardKey, ARROW_UP]
22006
+ }[orientation];
22007
+ const preventedKeys = isGrid ? RELEVANT_KEYS : {
22008
+ horizontal: enableHomeAndEndKeys ? HORIZONTAL_KEYS_WITH_EXTRA_KEYS : HORIZONTAL_KEYS,
22009
+ vertical: enableHomeAndEndKeys ? VERTICAL_KEYS_WITH_EXTRA_KEYS : VERTICAL_KEYS,
22010
+ both: RELEVANT_KEYS
22011
+ }[orientation];
22012
+ if (enableHomeAndEndKeys) {
22013
+ if (event.key === "Home") nextIndex = minIndex;
22014
+ else if (event.key === "End") nextIndex = maxIndex;
22015
+ }
22016
+ if (nextIndex === highlightedIndex && (forwardKeys.includes(event.key) || backwardKeys.includes(event.key))) {
22017
+ if (loopFocus && nextIndex === maxIndex && forwardKeys.includes(event.key)) {
22018
+ nextIndex = minIndex;
22019
+ if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
22020
+ } else if (loopFocus && nextIndex === minIndex && backwardKeys.includes(event.key)) {
22021
+ nextIndex = maxIndex;
22022
+ if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
22023
+ } else nextIndex = findNonDisabledListIndex(elementsRef.current, {
22024
+ startingIndex: nextIndex,
22025
+ decrement: backwardKeys.includes(event.key),
22026
+ disabledIndices
22027
+ });
22028
+ }
22029
+ if (nextIndex !== highlightedIndex && !isIndexOutOfListBounds(elementsRef.current, nextIndex)) {
22030
+ if (stopEventPropagation) event.stopPropagation();
22031
+ if (preventedKeys.has(event.key)) event.preventDefault();
22032
+ onHighlightedIndexChange(nextIndex, true);
22033
+ queueMicrotask(() => {
22034
+ elementsRef.current[nextIndex]?.focus();
22035
+ });
22036
+ }
22037
+ }
22038
+ }), [
22039
+ cols,
22040
+ dense,
22041
+ direction,
22042
+ disabledIndices,
22043
+ elementsRef,
22044
+ enableHomeAndEndKeys,
22045
+ highlightedIndex,
22046
+ isGrid,
22047
+ itemSizes,
22048
+ loopFocus,
22049
+ onLoop,
22050
+ wrappedOnLoop,
22051
+ mergedRef,
22052
+ modifierKeys,
22053
+ onHighlightedIndexChange,
22054
+ orientation,
22055
+ stopEventPropagation
22056
+ ]);
22057
+ return React.useMemo(() => ({
22058
+ props,
22059
+ highlightedIndex,
22060
+ onHighlightedIndexChange,
22061
+ elementsRef,
22062
+ disabledIndices,
22063
+ onMapChange,
22064
+ relayKeyboardEvent: props.onKeyDown
22065
+ }), [
22066
+ props,
22067
+ highlightedIndex,
22068
+ onHighlightedIndexChange,
22069
+ elementsRef,
22070
+ disabledIndices,
22071
+ onMapChange
22072
+ ]);
22073
+ }
22074
+ function isModifierKeySet(event, ignoredModifierKeys) {
22075
+ for (const key of MODIFIER_KEYS$1.values()) {
22076
+ if (ignoredModifierKeys.includes(key)) continue;
22077
+ if (event.getModifierState(key)) return true;
22078
+ }
22079
+ return false;
22080
+ }
22081
+ //#endregion
22082
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/CompositeRoot.js
22083
+ /**
22084
+ * @internal
22085
+ */
22086
+ function CompositeRoot(componentProps) {
22087
+ const { render, className, style, refs = EMPTY_ARRAY$1, props = EMPTY_ARRAY$1, state = EMPTY_OBJECT, stateAttributesMapping, highlightedIndex: highlightedIndexProp, onHighlightedIndexChange: onHighlightedIndexChangeProp, orientation, dense, itemSizes, loopFocus, onLoop, cols, enableHomeAndEndKeys, onMapChange: onMapChangeProp, stopEventPropagation = true, rootRef, disabledIndices, modifierKeys, highlightItemOnHover = false, tag = "div", ...elementProps } = componentProps;
22088
+ const { props: defaultProps, highlightedIndex, onHighlightedIndexChange, elementsRef, onMapChange: onMapChangeUnwrapped, relayKeyboardEvent } = useCompositeRoot({
22089
+ itemSizes,
22090
+ cols,
22091
+ loopFocus,
22092
+ onLoop,
22093
+ dense,
22094
+ orientation,
22095
+ highlightedIndex: highlightedIndexProp,
22096
+ onHighlightedIndexChange: onHighlightedIndexChangeProp,
22097
+ rootRef,
22098
+ stopEventPropagation,
22099
+ enableHomeAndEndKeys,
22100
+ direction: useDirection(),
22101
+ disabledIndices,
22102
+ modifierKeys
22103
+ });
22104
+ const element = useRenderElement(tag, componentProps, {
22105
+ state,
22106
+ ref: refs,
22107
+ props: [
22108
+ defaultProps,
22109
+ ...props,
22110
+ elementProps
22111
+ ],
22112
+ stateAttributesMapping
22113
+ });
22114
+ const contextValue = React.useMemo(() => ({
22115
+ highlightedIndex,
22116
+ onHighlightedIndexChange,
22117
+ highlightItemOnHover,
22118
+ relayKeyboardEvent
22119
+ }), [
22120
+ highlightedIndex,
22121
+ onHighlightedIndexChange,
22122
+ highlightItemOnHover,
22123
+ relayKeyboardEvent
22124
+ ]);
22125
+ return /*#__PURE__*/ jsx(CompositeRootContext.Provider, {
22126
+ value: contextValue,
22127
+ children: /*#__PURE__*/ jsx(CompositeList, {
22128
+ elementsRef,
22129
+ onMapChange: (newMap) => {
22130
+ onMapChangeProp?.(newMap);
22131
+ onMapChangeUnwrapped(newMap);
22132
+ },
22133
+ children: element
22134
+ })
22135
+ });
22136
+ }
22137
+ //#endregion
22138
+ //#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio-group/RadioGroup.js
22139
+ var MODIFIER_KEYS = [SHIFT];
22140
+ /**
22141
+ * Provides a shared state to a series of radio buttons.
22142
+ * Renders a `<div>` element.
22143
+ *
22144
+ * Documentation: [Base UI Radio Group](https://base-ui.com/react/components/radio)
22145
+ */
22146
+ var RadioGroup = /*#__PURE__*/ React.forwardRef(function RadioGroup(componentProps, forwardedRef) {
22147
+ const { render, className, disabled: disabledProp, readOnly, required, onValueChange: onValueChangeProp, value: externalValue, defaultValue, form, name: nameProp, inputRef: inputRefProp, id: idProp, style, ...elementProps } = componentProps;
22148
+ const { setTouched: setFieldTouched, setFocused, shouldValidateOnChange, validationMode, name: fieldName, disabled: fieldDisabled, state: fieldState, validation, setDirty, setFilled, validityData } = useFieldRootContext();
22149
+ const { labelId } = useLabelableContext();
22150
+ const { clearErrors } = useFormContext();
22151
+ const fieldsetContext = useFieldsetRootContext(true);
22152
+ const disabled = fieldDisabled || disabledProp;
22153
+ const name = fieldName ?? nameProp;
22154
+ const id = useBaseUiId(idProp);
22155
+ const [checkedValue, setCheckedValueUnwrapped] = useControlled({
22156
+ controlled: externalValue,
22157
+ default: defaultValue,
22158
+ name: "RadioGroup",
22159
+ state: "value"
22160
+ });
22161
+ const onValueChange = useStableCallback(onValueChangeProp);
22162
+ const setCheckedValue = useStableCallback((value, eventDetails) => {
22163
+ onValueChange(value, eventDetails);
22164
+ if (eventDetails.isCanceled) return;
22165
+ setCheckedValueUnwrapped(value);
22166
+ });
22167
+ const controlRef = React.useRef(null);
22168
+ const groupInputRef = React.useRef(null);
22169
+ const firstEnabledInputRef = React.useRef(null);
22170
+ function setInputRef(hiddenInput) {
22171
+ let cleanup = void 0;
22172
+ if (inputRefProp) {
22173
+ if (typeof inputRefProp === "function") cleanup = inputRefProp(hiddenInput);
22174
+ else inputRefProp.current = hiddenInput;
22175
+ }
22176
+ groupInputRef.current = hiddenInput;
22177
+ validation.inputRef.current = hiddenInput;
22178
+ return cleanup;
22179
+ }
22180
+ const registerControlRef = useStableCallback((element, isDisabled = false) => {
22181
+ if (!element) return;
22182
+ if (isDisabled) {
22183
+ if (controlRef.current === element) controlRef.current = null;
22184
+ return;
22185
+ }
22186
+ if (controlRef.current == null) controlRef.current = element;
22187
+ });
22188
+ const registerInputRef = useStableCallback((input) => {
22189
+ if (!input || input.disabled) return;
22190
+ if (!firstEnabledInputRef.current) firstEnabledInputRef.current = input;
22191
+ const currentInput = groupInputRef.current;
22192
+ if (input.checked || currentInput == null || currentInput.disabled) return setInputRef(input);
22193
+ });
22194
+ const getFieldValue = useStableCallback(() => checkedValue ?? null);
22195
+ useRegisterFieldControl(controlRef, {
22196
+ id,
22197
+ value: checkedValue,
22198
+ getValue: getFieldValue
22199
+ });
22200
+ useValueChanged(checkedValue, () => {
22201
+ clearErrors(name);
22202
+ setDirty(checkedValue !== validityData.initialValue);
22203
+ setFilled(checkedValue != null);
22204
+ if (shouldValidateOnChange()) validation.commit(checkedValue);
22205
+ else validation.commit(checkedValue, true);
22206
+ const fallbackInput = firstEnabledInputRef.current;
22207
+ if (checkedValue == null && fallbackInput && !fallbackInput.disabled) setInputRef(fallbackInput);
22208
+ });
22209
+ const [touched, setTouched] = React.useState(false);
22210
+ const ariaLabelledby = elementProps["aria-labelledby"] ?? labelId ?? fieldsetContext?.legendId;
22211
+ const state = {
22212
+ ...fieldState,
22213
+ disabled: disabled ?? false,
22214
+ required: required ?? false,
22215
+ readOnly: readOnly ?? false
22216
+ };
22217
+ const contextValue = React.useMemo(() => ({
22218
+ ...fieldState,
22219
+ checkedValue,
22220
+ disabled,
22221
+ form,
22222
+ validation,
22223
+ name,
22224
+ onValueChange,
22225
+ readOnly,
22226
+ registerControlRef,
22227
+ registerInputRef,
22228
+ required,
22229
+ setCheckedValue,
22230
+ setTouched,
22231
+ touched
22232
+ }), [
22233
+ checkedValue,
22234
+ disabled,
22235
+ form,
22236
+ validation,
22237
+ fieldState,
22238
+ name,
22239
+ onValueChange,
22240
+ readOnly,
22241
+ registerControlRef,
22242
+ registerInputRef,
22243
+ required,
22244
+ setCheckedValue,
22245
+ setTouched,
22246
+ touched
22247
+ ]);
22248
+ const defaultProps = {
22249
+ role: "radiogroup",
22250
+ "aria-required": required || void 0,
22251
+ "aria-disabled": disabled || void 0,
22252
+ "aria-readonly": readOnly || void 0,
22253
+ "aria-labelledby": ariaLabelledby,
22254
+ onFocus() {
22255
+ setFocused(true);
22256
+ },
22257
+ onBlur(event) {
22258
+ if (!contains(event.currentTarget, event.relatedTarget)) {
22259
+ setFieldTouched(true);
22260
+ setFocused(false);
22261
+ if (validationMode === "onBlur") validation.commit(checkedValue);
22262
+ }
22263
+ },
22264
+ onKeyDownCapture(event) {
22265
+ if (event.key.startsWith("Arrow")) {
22266
+ setFieldTouched(true);
22267
+ setTouched(true);
22268
+ setFocused(true);
22269
+ }
22270
+ }
22271
+ };
22272
+ return /*#__PURE__*/ jsx(RadioGroupContext.Provider, {
22273
+ value: contextValue,
22274
+ children: /*#__PURE__*/ jsx(CompositeRoot, {
22275
+ render,
22276
+ className,
22277
+ style,
22278
+ state,
22279
+ props: [
22280
+ defaultProps,
22281
+ validation.getValidationProps,
22282
+ elementProps
22283
+ ],
22284
+ refs: [forwardedRef],
22285
+ stateAttributesMapping: fieldValidityMapping,
22286
+ enableHomeAndEndKeys: false,
22287
+ modifierKeys: MODIFIER_KEYS
22288
+ })
22289
+ });
22290
+ });
22291
+ if (process.env.NODE_ENV !== "production") RadioGroup.displayName = "RadioGroup";
22292
+ //#endregion
21296
22293
  //#region src/canvas/browser/graph/ReactFlowContainer/CanvasMiniMap.tsx
21297
22294
  function CanvasMiniMapMenuItem({ miniMapExpanded$ }) {
21298
22295
  const t = useTranslate();
@@ -21338,9 +22335,7 @@ function CanvasMiniMapButton({ miniMapExpanded$ }) {
21338
22335
  }
21339
22336
  //#endregion
21340
22337
  //#region src/canvas/browser/graph/ReactFlowContainer/CanvasControls.tsx
21341
- function CanvasInteractiveMode({ interactiveMode$, defaultOpen = false }) {
21342
- const t = useTranslate();
21343
- const mode = useVal(interactiveMode$);
22338
+ function CanvasOptionPicker({ label, value, options, onValueChange, disabled = false, defaultOpen = false }) {
21344
22339
  const [open, setOpen] = useState(defaultOpen);
21345
22340
  const getPopupContainer = useGetStaticPopupContainer();
21346
22341
  return /* @__PURE__ */ jsxs(Popover, {
@@ -21348,70 +22343,79 @@ function CanvasInteractiveMode({ interactiveMode$, defaultOpen = false }) {
21348
22343
  onOpenChange: setOpen,
21349
22344
  children: [/* @__PURE__ */ jsx(CanvasTooltip, {
21350
22345
  placement: "top",
21351
- title: t("interactiveMode.title"),
22346
+ title: label,
21352
22347
  children: /* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Button, {
21353
- "aria-label": t("interactiveMode.title"),
21354
- className: ReactFlowContainer_module_default.interactiveModeTrigger,
22348
+ "aria-label": label,
22349
+ className: ReactFlowContainer_module_default.viewChoiceTrigger,
22350
+ disabled,
21355
22351
  size: "icon",
21356
22352
  type: "button",
21357
22353
  variant: "ghost",
21358
- children: /* @__PURE__ */ jsx("i", {
21359
- className: mode == "mouse" ? "i-lucide-light:mouse" : "i-lucide-light:touchpad",
21360
- "data-mode-icon": true
21361
- })
22354
+ children: options.find((option) => option.value === value)?.icon
21362
22355
  }) })
21363
22356
  }), /* @__PURE__ */ jsx(PopoverContent, {
21364
22357
  align: "start",
21365
- className: ReactFlowContainer_module_default.interactiveModePanel,
22358
+ "aria-label": label,
22359
+ className: ReactFlowContainer_module_default.viewChoicePanel,
21366
22360
  "data-canvas-control-scope": true,
21367
22361
  container: typeof document == "undefined" ? void 0 : getPopupContainer(),
21368
22362
  side: "top",
21369
22363
  sideOffset: 14,
21370
- children: /* @__PURE__ */ jsxs("div", {
21371
- "aria-label": t("interactiveMode.title"),
21372
- className: ReactFlowContainer_module_default.interactiveModeChoices,
21373
- role: "radiogroup",
21374
- children: [/* @__PURE__ */ jsxs(Button, {
21375
- "aria-checked": mode == "mouse",
21376
- className: ReactFlowContainer_module_default.interactiveModeChoice,
21377
- onClick: () => {
21378
- interactiveMode$.set("mouse");
21379
- setOpen(false);
21380
- },
21381
- role: "radio",
21382
- type: "button",
21383
- variant: "outline",
21384
- children: [
21385
- /* @__PURE__ */ jsx("i", {
21386
- "aria-hidden": "true",
21387
- className: "i-lucide-light:mouse"
21388
- }),
21389
- /* @__PURE__ */ jsx("strong", { children: t("interactiveMode.mouse") }),
21390
- /* @__PURE__ */ jsx("span", { children: t("interactiveMode.mouseDescription") })
21391
- ]
21392
- }), /* @__PURE__ */ jsxs(Button, {
21393
- "aria-checked": mode == "touchpad",
21394
- className: ReactFlowContainer_module_default.interactiveModeChoice,
21395
- onClick: () => {
21396
- interactiveMode$.set("touchpad");
21397
- setOpen(false);
21398
- },
21399
- role: "radio",
21400
- type: "button",
21401
- variant: "outline",
22364
+ children: /* @__PURE__ */ jsx(RadioGroup, {
22365
+ "aria-label": label,
22366
+ className: ReactFlowContainer_module_default.viewChoices,
22367
+ disabled,
22368
+ onValueChange: (next) => {
22369
+ onValueChange(next);
22370
+ setOpen(false);
22371
+ },
22372
+ value,
22373
+ children: options.map((option) => /* @__PURE__ */ jsxs(RadioRoot, {
22374
+ nativeButton: true,
22375
+ value: option.value,
22376
+ render: /* @__PURE__ */ jsx(Button, {
22377
+ className: ReactFlowContainer_module_default.viewChoice,
22378
+ onClick: () => setOpen(false),
22379
+ type: "button",
22380
+ variant: "outline"
22381
+ }),
21402
22382
  children: [
21403
- /* @__PURE__ */ jsx("i", {
21404
- "aria-hidden": "true",
21405
- className: "i-lucide-light:touchpad"
21406
- }),
21407
- /* @__PURE__ */ jsx("strong", { children: t("interactiveMode.touchpad") }),
21408
- /* @__PURE__ */ jsx("span", { children: t("interactiveMode.touchpadDescription") })
22383
+ option.icon,
22384
+ /* @__PURE__ */ jsx("strong", { children: option.label }),
22385
+ /* @__PURE__ */ jsx("span", { children: option.description })
21409
22386
  ]
21410
- })]
22387
+ }, option.value))
21411
22388
  })
21412
22389
  })]
21413
22390
  });
21414
22391
  }
22392
+ function CanvasInteractiveMode({ interactiveMode$, defaultOpen = false }) {
22393
+ const t = useTranslate();
22394
+ const mode = useVal(interactiveMode$);
22395
+ return /* @__PURE__ */ jsx(CanvasOptionPicker, {
22396
+ defaultOpen,
22397
+ label: t("interactiveMode.title"),
22398
+ onValueChange: (next) => interactiveMode$.set(next),
22399
+ options: [{
22400
+ value: "mouse",
22401
+ icon: /* @__PURE__ */ jsx("i", {
22402
+ "aria-hidden": "true",
22403
+ className: "i-lucide-light:mouse"
22404
+ }),
22405
+ label: t("interactiveMode.mouse"),
22406
+ description: t("interactiveMode.mouseDescription")
22407
+ }, {
22408
+ value: "touchpad",
22409
+ icon: /* @__PURE__ */ jsx("i", {
22410
+ "aria-hidden": "true",
22411
+ className: "i-lucide-light:touchpad"
22412
+ }),
22413
+ label: t("interactiveMode.touchpad"),
22414
+ description: t("interactiveMode.touchpadDescription")
22415
+ }],
22416
+ value: mode
22417
+ });
22418
+ }
21415
22419
  function CanvasInteractiveModeMenu({ interactiveMode$ }) {
21416
22420
  const t = useTranslate();
21417
22421
  const mode = useVal(interactiveMode$);
@@ -21433,21 +22437,61 @@ function CanvasInteractiveModeMenu({ interactiveMode$ }) {
21433
22437
  })]
21434
22438
  })] })] });
21435
22439
  }
21436
- function CanvasOptionsMenu({ onRelayout, miniMapExpanded$, interactiveMode$ }) {
22440
+ function CanvasDirectionIcon({ direction }) {
22441
+ return /* @__PURE__ */ jsx("i", {
22442
+ "aria-hidden": "true",
22443
+ className: direction === "vertical" ? "i-tabler-light:arrow-autofit-down" : "i-tabler-light:arrow-autofit-right"
22444
+ });
22445
+ }
22446
+ function CanvasDirectionButton({ direction = "horizontal", changingDirection, onChangeDirection }) {
22447
+ const t = useTranslate();
22448
+ return /* @__PURE__ */ jsx(CanvasOptionPicker, {
22449
+ disabled: changingDirection,
22450
+ label: t("layoutDirection.title"),
22451
+ onValueChange: (next) => onChangeDirection?.(next),
22452
+ options: [{
22453
+ value: "vertical",
22454
+ icon: /* @__PURE__ */ jsx(CanvasDirectionIcon, { direction: "vertical" }),
22455
+ label: t("layoutDirection.vertical"),
22456
+ description: t("layoutDirection.verticalDescription")
22457
+ }, {
22458
+ value: "horizontal",
22459
+ icon: /* @__PURE__ */ jsx(CanvasDirectionIcon, { direction: "horizontal" }),
22460
+ label: t("layoutDirection.horizontal"),
22461
+ description: t("layoutDirection.horizontalDescription")
22462
+ }],
22463
+ value: direction
22464
+ });
22465
+ }
22466
+ function CanvasOptionsMenu({ onRelayout, miniMapExpanded$, interactiveMode$, direction = "horizontal", changingDirection, onChangeDirection }) {
21437
22467
  const t = useTranslate();
21438
22468
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
21439
22469
  onRelayout != null && /* @__PURE__ */ jsxs(DropdownMenuItem, {
22470
+ disabled: changingDirection,
21440
22471
  onClick: onRelayout,
21441
22472
  children: [/* @__PURE__ */ jsx("i", {
21442
22473
  "aria-hidden": "true",
21443
- className: "i-carbon:template"
22474
+ className: "i-lucide-light:layout-template"
21444
22475
  }), t("optimize")]
21445
22476
  }),
22477
+ onChangeDirection && /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: t("layoutDirection.title") }), /* @__PURE__ */ jsxs(DropdownMenuRadioGroup, {
22478
+ value: direction,
22479
+ onValueChange: (value) => onChangeDirection(value),
22480
+ children: [/* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
22481
+ disabled: changingDirection,
22482
+ value: "vertical",
22483
+ children: [/* @__PURE__ */ jsx(CanvasDirectionIcon, { direction: "vertical" }), t("layoutDirection.vertical")]
22484
+ }), /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
22485
+ disabled: changingDirection,
22486
+ value: "horizontal",
22487
+ children: [/* @__PURE__ */ jsx(CanvasDirectionIcon, { direction: "horizontal" }), t("layoutDirection.horizontal")]
22488
+ })]
22489
+ })] }),
21446
22490
  miniMapExpanded$ != null && /* @__PURE__ */ jsx(CanvasMiniMapMenuItem, { miniMapExpanded$ }),
21447
22491
  interactiveMode$ != null && /* @__PURE__ */ jsx(CanvasInteractiveModeMenu, { interactiveMode$ })
21448
22492
  ] });
21449
22493
  }
21450
- function CanvasViewControls({ readOnly = false, interactiveMode$, miniMapExpanded$, maxZoomReached, minZoomReached, onFitView, onRelayout, onZoomIn, onZoomOut, onZoomReset, zoom }) {
22494
+ function CanvasViewControls({ readOnly = false, direction, changingDirection, onChangeDirection, interactiveMode$, miniMapExpanded$, maxZoomReached, minZoomReached, onFitView, onRelayout, onZoomIn, onZoomOut, onZoomReset, zoom }) {
21451
22495
  const t = useTranslate();
21452
22496
  const [optionsExpanded, setOptionsExpanded] = useState(false);
21453
22497
  const [popupContainer, setPopupContainer] = useState(null);
@@ -21517,6 +22561,9 @@ function CanvasViewControls({ readOnly = false, interactiveMode$, miniMapExpande
21517
22561
  }),
21518
22562
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
21519
22563
  /* @__PURE__ */ jsx(CanvasOptionsMenu, {
22564
+ direction,
22565
+ changingDirection,
22566
+ onChangeDirection,
21520
22567
  onRelayout,
21521
22568
  miniMapExpanded$,
21522
22569
  interactiveMode$
@@ -21578,7 +22625,7 @@ function CanvasViewControls({ readOnly = false, interactiveMode$, miniMapExpande
21578
22625
  children: /* @__PURE__ */ jsx("i", { className: "i-lucide-light:scan" })
21579
22626
  })
21580
22627
  }),
21581
- (onRelayout != null || miniMapExpanded$ != null || interactiveMode$ != null) && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
22628
+ (onChangeDirection != null || onRelayout != null || miniMapExpanded$ != null || interactiveMode$ != null) && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
21582
22629
  className: ReactFlowContainer_module_default.viewOptions,
21583
22630
  "data-expanded": optionsExpanded,
21584
22631
  "aria-hidden": !optionsExpanded,
@@ -21596,16 +22643,22 @@ function CanvasViewControls({ readOnly = false, interactiveMode$, miniMapExpande
21596
22643
  title: t("optimize"),
21597
22644
  children: /* @__PURE__ */ jsx(Button, {
21598
22645
  "aria-label": t("optimize"),
22646
+ disabled: changingDirection,
21599
22647
  onClick: onRelayout,
21600
22648
  size: "icon",
21601
22649
  type: "button",
21602
22650
  variant: "ghost",
21603
22651
  children: /* @__PURE__ */ jsx("i", {
21604
22652
  "aria-hidden": "true",
21605
- className: "i-carbon:template"
22653
+ className: "i-lucide-light:layout-template"
21606
22654
  })
21607
22655
  })
21608
22656
  }),
22657
+ onChangeDirection != null && /* @__PURE__ */ jsx(CanvasDirectionButton, {
22658
+ direction,
22659
+ changingDirection,
22660
+ onChangeDirection
22661
+ }),
21609
22662
  miniMapExpanded$ != null && /* @__PURE__ */ jsx(CanvasMiniMapButton, { miniMapExpanded$ }),
21610
22663
  interactiveMode$ != null && /* @__PURE__ */ jsx(CanvasInteractiveMode, { interactiveMode$ })
21611
22664
  ]
@@ -21963,7 +23016,6 @@ var selector = (s) => ({
21963
23016
  });
21964
23017
  var FlowControls = /*#__PURE__*/ memo((props) => {
21965
23018
  const rf = useReactFlow();
21966
- const flowState = useStoreApi();
21967
23019
  const { minZoomReached, maxZoomReached, zoom } = useStore(selector, shallowPlainObjectEqual);
21968
23020
  const nodes = useNodes();
21969
23021
  const bgId = useId().replaceAll(":", "");
@@ -21973,11 +23025,6 @@ var FlowControls = /*#__PURE__*/ memo((props) => {
21973
23025
  duration: props.layoutMotion === false ? 0 : 150,
21974
23026
  maxZoom: 1
21975
23027
  };
21976
- const relayout = props.onRelayout == null ? void 0 : () => {
21977
- props.onRelayout?.(getLayoutWidth(flowState.getState()));
21978
- props.onBeforeFitView?.();
21979
- setTimeout(() => rf.fitView(fitViewOptions), 100);
21980
- };
21981
23028
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
21982
23029
  props.dottedBackground && /* @__PURE__ */ jsx(Background, {
21983
23030
  id: bgId,
@@ -21989,6 +23036,9 @@ var FlowControls = /*#__PURE__*/ memo((props) => {
21989
23036
  /* @__PURE__ */ jsx(CanvasViewControls, {
21990
23037
  readOnly: !props.editable,
21991
23038
  interactiveMode$: props.interactiveMode$,
23039
+ direction: props.direction,
23040
+ changingDirection: props.changingDirection,
23041
+ onChangeDirection: props.onChangeDirection,
21992
23042
  miniMapExpanded$: props.miniMapExpanded$,
21993
23043
  maxZoomReached,
21994
23044
  minZoomReached,
@@ -22003,7 +23053,7 @@ var FlowControls = /*#__PURE__*/ memo((props) => {
22003
23053
  props.onFitView?.();
22004
23054
  }, 100);
22005
23055
  },
22006
- onRelayout: relayout,
23056
+ onRelayout: props.onRelayout,
22007
23057
  onZoomIn: () => rf.zoomIn({ duration: getViewportTransitionDuration() }),
22008
23058
  onZoomOut: () => rf.zoomOut({ duration: getViewportTransitionDuration() }),
22009
23059
  onZoomReset: () => rf.zoomTo(1, { duration: getViewportTransitionDuration() }),
@@ -22124,16 +23174,21 @@ var ReactFlowContainerInner = (props) => {
22124
23174
  if (tooShort(state.from, position)) return;
22125
23175
  const nodeId = toManifestNodeId(state.fromNode.id);
22126
23176
  const handle = toManifestHandleName(state.fromHandle.id);
22127
- const connectionSide = state.fromHandle.type == "target" ? "left" : "right";
23177
+ const upstream = state.fromHandle.type === "target";
23178
+ const connectionDirection = upstream ? "upstream" : "downstream";
23179
+ const nodePosition = props.direction === "vertical" ? {
23180
+ x: position.x - 160 - 8,
23181
+ y: position.y - (upstream ? 84 : 8)
23182
+ } : {
23183
+ x: position.x - (upstream ? 328 : 8),
23184
+ y: position.y - 38 - 8
23185
+ };
22128
23186
  cancelAnimationFrame(pickerFrame.current);
22129
23187
  pickerFrame.current = requestAnimationFrame(() => props.onRequestAddNode?.({
22130
- position: connectionSide == "left" ? {
22131
- x: position.x - 250,
22132
- y: position.y
22133
- } : position,
23188
+ position: nodePosition,
22134
23189
  screenPosition,
22135
- connectionSide,
22136
- connection: connectionSide == "left" ? (source) => ({
23190
+ connectionDirection,
23191
+ connection: upstream ? (source) => ({
22137
23192
  source,
22138
23193
  sourceHandle: "$out",
22139
23194
  target: nodeId,
@@ -22148,7 +23203,8 @@ var ReactFlowContainerInner = (props) => {
22148
23203
  }, [
22149
23204
  rf,
22150
23205
  props.editable,
22151
- props.onRequestAddNode
23206
+ props.onRequestAddNode,
23207
+ props.direction
22152
23208
  ]);
22153
23209
  const editable = toTrue(props.editable);
22154
23210
  const interactiveMode = useVal(props.interactiveMode$);
@@ -22177,6 +23233,25 @@ var ReactFlowContainerInner = (props) => {
22177
23233
  const [fittingView, setFittingView] = useState(false);
22178
23234
  const [layoutReady, setLayoutReady] = useState(props.layoutMotion !== false || props.onLayoutMeasured == null);
22179
23235
  const onBeforeFitView = useCallback(() => setFittingView(true), []);
23236
+ const relayout = useCallback(() => {
23237
+ props.onRelayout?.(getLayoutWidth(flowState.getState()));
23238
+ }, [flowState, props.onRelayout]);
23239
+ const relayoutAndFitView = useCallback(() => {
23240
+ relayout();
23241
+ onBeforeFitView();
23242
+ setTimeout(() => rf.fitView({
23243
+ padding: .15,
23244
+ duration: props.layoutMotion === false ? 0 : 150,
23245
+ maxZoom: 1,
23246
+ nodes: selectedNodes.length > 1 ? selectedNodes : void 0
23247
+ }), 100);
23248
+ }, [
23249
+ relayout,
23250
+ onBeforeFitView,
23251
+ props.layoutMotion,
23252
+ rf,
23253
+ selectedNodes
23254
+ ]);
22180
23255
  useLayoutEffect(() => {
22181
23256
  setLayoutReady(props.layoutMotion !== false || props.onLayoutMeasured == null);
22182
23257
  }, [props.layoutMotion, props.onLayoutMeasured]);
@@ -22226,6 +23301,7 @@ var ReactFlowContainerInner = (props) => {
22226
23301
  onBeforeFitView,
22227
23302
  props.layoutMotion,
22228
23303
  props.onLayoutMeasured,
23304
+ props.direction,
22229
23305
  rf,
22230
23306
  updateNodeInternals
22231
23307
  ]);
@@ -22351,7 +23427,7 @@ var ReactFlowContainerInner = (props) => {
22351
23427
  onViewportChange,
22352
23428
  maxZoom: 3,
22353
23429
  minZoom: canvasMinZoom,
22354
- nodesDraggable: props.nodesDraggable ?? props.editable,
23430
+ nodesDraggable: !props.changingDirection && (props.nodesDraggable ?? props.editable),
22355
23431
  nodesConnectable: editable && props.onConnect != null,
22356
23432
  onEdgeContextMenu: (event, edge) => (event.preventDefault(), setEdgeContextMenu({
22357
23433
  edge,
@@ -22415,7 +23491,9 @@ var ReactFlowContainerInner = (props) => {
22415
23491
  editable: !!editable,
22416
23492
  nodes: selectedNodes,
22417
23493
  onDelete: deleteSelectedNodes,
22418
- duplicateNodes: props.duplicateNodes
23494
+ duplicateNodes: props.duplicateNodes,
23495
+ onRelayout: props.onRelayout ? relayout : void 0,
23496
+ changingDirection: props.changingDirection
22419
23497
  }),
22420
23498
  /* @__PURE__ */ jsx(FlowControls, {
22421
23499
  editable: props.editable,
@@ -22426,9 +23504,12 @@ var ReactFlowContainerInner = (props) => {
22426
23504
  toolbar: props.toolbar,
22427
23505
  miniMapExpanded$: props.miniMapExpanded$,
22428
23506
  interactiveMode$: props.interactiveMode$,
23507
+ direction: props.direction,
23508
+ changingDirection: props.changingDirection,
23509
+ onChangeDirection: props.onChangeDirection,
22429
23510
  layoutMotion: props.layoutMotion,
22430
23511
  onBeforeFitView,
22431
- onRelayout: props.onRelayout,
23512
+ onRelayout: props.onRelayout ? relayoutAndFitView : void 0,
22432
23513
  onFitView: props.onFitView,
22433
23514
  dottedBackground: props.dottedBackground
22434
23515
  }),
@@ -22610,6 +23691,16 @@ function useSelectionItems(props) {
22610
23691
  icon: /* @__PURE__ */ jsx("i", { className: "i-codicon:copy" }),
22611
23692
  onClick: duplicateNodes
22612
23693
  },
23694
+ props.onRelayout && {
23695
+ label: t("optimize"),
23696
+ key: "$relayout",
23697
+ icon: /* @__PURE__ */ jsx("i", {
23698
+ "aria-hidden": "true",
23699
+ className: "i-lucide-light:layout-template"
23700
+ }),
23701
+ onClick: props.onRelayout,
23702
+ disabled: props.changingDirection
23703
+ },
22613
23704
  toTrue(hasSkip) && {
22614
23705
  label: skip ? t("nodeActions.skipDisableAll") : t("nodeActions.skipEnableAll"),
22615
23706
  key: "$skip",
@@ -22634,6 +23725,8 @@ function tooShort(from, to) {
22634
23725
  //#region src/canvas/browser/graph/FlowCanvas/FlowCanvas.tsx
22635
23726
  var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onSelectionStart, onSelectionEnd, onInspectSelection, inspectorOpen = false, onRequestAddNode, cornerTools, cornerLeading, topLeftTools, bottomRightTools, toolbar, dark, dottedBackground, fitView, nodesDraggable, layoutMotion, className, addNodeRequest, addItemRequest, onMove, onMoveEnd, onNodeDragStop, onSelectionChange, isValidConnection, onDropAddItem }) => {
22636
23727
  const editable = useVal(flowCanvasStore.$.editable);
23728
+ const direction = useVal(flowCanvasStore.$.direction);
23729
+ const changingDirection = useVal(flowCanvasStore.$.changingDirection);
22637
23730
  const nodeMiniMapPhase = useVal(flowCanvasStore.$.nodeMiniMapPhase);
22638
23731
  useEffect(flowCanvasStore.setupForceDelete, []);
22639
23732
  return /* @__PURE__ */ jsx(CanvasAnnotationContext.Provider, {
@@ -22655,6 +23748,9 @@ var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onS
22655
23748
  bottomRightTools,
22656
23749
  toolbar,
22657
23750
  editable,
23751
+ direction,
23752
+ changingDirection,
23753
+ onChangeDirection: editable && flowCanvasStore.canChangeDirection ? flowCanvasStore.changeDirection : void 0,
22658
23754
  nodesDraggable: nodesDraggable ?? editable,
22659
23755
  className,
22660
23756
  i18n: flowCanvasStore.i18n,
@@ -22703,4 +23799,4 @@ var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onS
22703
23799
  });
22704
23800
  };
22705
23801
  //#endregion
22706
- export { isSameViewport as C, isMac as S, CanvasTooltip as _, collapseAllNested as a, toManifestHandleName as b, defaultTriggerIcon as c, selectableTimeZones as d, timeZoneLabel as f, E as g, cronDescription as h, JSONViewer as i, useDebouncedValue as l, timeZoneOffset as m, setAddItemId as n, formatDuration as o, timeZoneLongLabel as p, Textarea as r, CanvasNodeIcon as s, FlowCanvas as t, IconStack as u, CanvasStore as v, toManifestNodeId as x, toViewEdge as y };
23802
+ export { toManifestHandleName as C, isSameViewport as E, toViewEdge as S, isMac as T, timeZoneOffset as _, NodeHistoryContext as a, CanvasTooltip as b, defaultTriggerIcon as c, formatDuration as d, useDebouncedValue as f, timeZoneLongLabel as g, timeZoneLabel as h, setAddItemId as i, JSONViewer as l, selectableTimeZones as m, CompositeRoot as n, Textarea as o, IconStack as p, ACTIVE_COMPOSITE_ITEM as r, CanvasNodeIcon as s, FlowCanvas as t, collapseAllNested as u, cronDescription as v, toManifestNodeId as w, CanvasStore as x, E as y };