@octaviaflow/core 3.0.18-beta.2 → 3.0.18-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11905,7 +11905,7 @@ Drawer.displayName = "Drawer";
11905
11905
 
11906
11906
  // src/components/DropdownMenu/DropdownMenu.tsx
11907
11907
  import { AnimatePresence as AnimatePresence13, motion as motion18 } from "framer-motion";
11908
- import { useEffect as useEffect17, useRef as useRef22 } from "react";
11908
+ import { useEffect as useEffect17, useMemo as useMemo13, useRef as useRef22 } from "react";
11909
11909
  import { useButton as useButton4, useMenu, useMenuItem, useMenuTrigger } from "react-aria";
11910
11910
  import { createPortal as createPortal8 } from "react-dom";
11911
11911
  import { Fragment as Fragment21, jsx as jsx41, jsxs as jsxs40 } from "react/jsx-runtime";
@@ -11938,7 +11938,8 @@ function MenuPopup({
11938
11938
  align,
11939
11939
  className,
11940
11940
  closeOnOutsideClick,
11941
- closeOnEscape
11941
+ closeOnEscape,
11942
+ matchTriggerWidth
11942
11943
  }) {
11943
11944
  const menuRef = useRef22(null);
11944
11945
  useEffect17(() => {
@@ -11980,19 +11981,45 @@ function MenuPopup({
11980
11981
  nonSepItems[idx]?.onClick?.();
11981
11982
  state.close();
11982
11983
  };
11984
+ const ESTIMATED_ITEM_H = 34;
11985
+ const ESTIMATED_SEPARATOR_H = 9;
11986
+ const POPUP_PADDING_V = 8;
11987
+ const VIEWPORT_MARGIN = 8;
11988
+ const estimatedHeight = useMemo13(() => {
11989
+ const itemsTotal = menuItems.reduce(
11990
+ (acc, item) => acc + (item.separator ? ESTIMATED_SEPARATOR_H : ESTIMATED_ITEM_H),
11991
+ 0
11992
+ );
11993
+ return itemsTotal + POPUP_PADDING_V * 2;
11994
+ }, [menuItems]);
11983
11995
  const getStyle = () => {
11984
11996
  if (!triggerRef.current) return {};
11985
11997
  const rect = triggerRef.current.getBoundingClientRect();
11998
+ const viewportH = window.innerHeight;
11999
+ const spaceBelow = viewportH - rect.bottom;
12000
+ const spaceAbove = rect.top;
12001
+ const openUp = spaceBelow < estimatedHeight && spaceAbove > spaceBelow;
11986
12002
  const style = {
11987
12003
  position: "fixed",
11988
12004
  zIndex: 1200,
11989
- top: rect.bottom + 4
12005
+ // Cap the menu so it never spills beyond the viewport — pairs
12006
+ // with overflow-y:auto on the popup itself (set in CSS).
12007
+ maxHeight: Math.max(120, (openUp ? spaceAbove : spaceBelow) - VIEWPORT_MARGIN)
11990
12008
  };
12009
+ if (openUp) {
12010
+ style.bottom = viewportH - rect.top + 4;
12011
+ } else {
12012
+ style.top = rect.bottom + 4;
12013
+ }
11991
12014
  if (align === "end") {
11992
12015
  style.right = window.innerWidth - rect.right;
11993
12016
  } else {
11994
12017
  style.left = rect.left;
11995
12018
  }
12019
+ if (matchTriggerWidth) {
12020
+ style.width = rect.width;
12021
+ style.minWidth = rect.width;
12022
+ }
11996
12023
  return style;
11997
12024
  };
11998
12025
  let nonSepIdx = 0;
@@ -12048,6 +12075,7 @@ function DropdownMenu({
12048
12075
  triggerClassName,
12049
12076
  closeOnOutsideClick = true,
12050
12077
  closeOnEscape = true,
12078
+ matchTriggerWidth = false,
12051
12079
  "aria-label": ariaLabel,
12052
12080
  "aria-labelledby": ariaLabelledby
12053
12081
  }) {
@@ -12081,7 +12109,8 @@ function DropdownMenu({
12081
12109
  align,
12082
12110
  className,
12083
12111
  closeOnOutsideClick,
12084
- closeOnEscape
12112
+ closeOnEscape,
12113
+ matchTriggerWidth
12085
12114
  }
12086
12115
  )
12087
12116
  ] });
@@ -12130,7 +12159,7 @@ EmptyState.displayName = "EmptyState";
12130
12159
 
12131
12160
  // src/components/ExecutionConsole/ExecutionConsole.tsx
12132
12161
  import { motion as motion19 } from "framer-motion";
12133
- import { useEffect as useEffect18, useMemo as useMemo13, useRef as useRef23, useState as useState20 } from "react";
12162
+ import { useEffect as useEffect18, useMemo as useMemo14, useRef as useRef23, useState as useState20 } from "react";
12134
12163
  import { Fragment as Fragment22, jsx as jsx43, jsxs as jsxs42 } from "react/jsx-runtime";
12135
12164
  var iconProps = {
12136
12165
  xmlns: "http://www.w3.org/2000/svg",
@@ -12202,7 +12231,7 @@ function ExecutionConsole({
12202
12231
  const [autoScroll, setAutoScroll] = useState20(true);
12203
12232
  const [expandedLines, setExpandedLines] = useState20(/* @__PURE__ */ new Set());
12204
12233
  const [exportMenuOpen, setExportMenuOpen] = useState20(false);
12205
- const nodeOptions = useMemo13(() => {
12234
+ const nodeOptions = useMemo14(() => {
12206
12235
  const seen = /* @__PURE__ */ new Map();
12207
12236
  for (const log of logs) {
12208
12237
  if (log.nodeId && !seen.has(log.nodeId)) {
@@ -12211,7 +12240,7 @@ function ExecutionConsole({
12211
12240
  }
12212
12241
  return Array.from(seen.entries()).map(([id, label]) => ({ id, label }));
12213
12242
  }, [logs]);
12214
- const filteredLogs = useMemo13(() => {
12243
+ const filteredLogs = useMemo14(() => {
12215
12244
  const q2 = query.trim().toLowerCase();
12216
12245
  return logs.filter((log) => {
12217
12246
  if (!activeLevels.has(log.level)) return false;
@@ -12283,7 +12312,7 @@ function ExecutionConsole({
12283
12312
  document.body.removeChild(a);
12284
12313
  URL.revokeObjectURL(url);
12285
12314
  };
12286
- const levelCounts = useMemo13(() => {
12315
+ const levelCounts = useMemo14(() => {
12287
12316
  const counts = {
12288
12317
  info: 0,
12289
12318
  warn: 0,
@@ -13833,7 +13862,7 @@ function FlowCanvas2({
13833
13862
  import {
13834
13863
  useCallback as useCallback20,
13835
13864
  useEffect as useEffect21,
13836
- useMemo as useMemo14,
13865
+ useMemo as useMemo15,
13837
13866
  useRef as useRef27,
13838
13867
  useState as useState24
13839
13868
  } from "react";
@@ -13852,7 +13881,7 @@ function FlowMinimap({
13852
13881
  }) {
13853
13882
  const scaleX = MINIMAP_WIDTH / totalWidth;
13854
13883
  const scaleY = MINIMAP_HEIGHT / totalHeight;
13855
- const scaledNodes = useMemo14(
13884
+ const scaledNodes = useMemo15(
13856
13885
  () => nodes.map((n) => ({
13857
13886
  ...n,
13858
13887
  sx: n.x * scaleX,
@@ -13862,7 +13891,7 @@ function FlowMinimap({
13862
13891
  })),
13863
13892
  [nodes, scaleX, scaleY]
13864
13893
  );
13865
- const scaledEdges = useMemo14(
13894
+ const scaledEdges = useMemo15(
13866
13895
  () => edges.map((e) => ({
13867
13896
  x1: e.from.x * scaleX,
13868
13897
  y1: e.from.y * scaleY,
@@ -13871,7 +13900,7 @@ function FlowMinimap({
13871
13900
  })),
13872
13901
  [edges, scaleX, scaleY]
13873
13902
  );
13874
- const scaledViewport = useMemo14(() => {
13903
+ const scaledViewport = useMemo15(() => {
13875
13904
  if (!viewportRect) return null;
13876
13905
  return {
13877
13906
  x: viewportRect.x * scaleX,
@@ -14546,7 +14575,7 @@ import { motion as motion21 } from "framer-motion";
14546
14575
  import {
14547
14576
  forwardRef as forwardRef43,
14548
14577
  useId as useId24,
14549
- useMemo as useMemo15
14578
+ useMemo as useMemo16
14550
14579
  } from "react";
14551
14580
  import { jsx as jsx53, jsxs as jsxs51 } from "react/jsx-runtime";
14552
14581
  var defaultFormat3 = (n) => {
@@ -14585,7 +14614,7 @@ var Gauge = forwardRef43(function Gauge2({
14585
14614
  const clamped = Math.max(min, Math.min(max, value));
14586
14615
  const pct = (clamped - min) / Math.max(1e-6, max - min);
14587
14616
  const fillColor = resolveBandColor(clamped, bands, color);
14588
- const resolvedAriaLabel = useMemo15(() => {
14617
+ const resolvedAriaLabel = useMemo16(() => {
14589
14618
  if (ariaLabel) return ariaLabel;
14590
14619
  const t = typeof title === "string" ? title : "Gauge";
14591
14620
  return `${t} \u2014 ${formatValue(clamped)} of ${formatValue(max)}`;
@@ -14932,7 +14961,7 @@ import {
14932
14961
  forwardRef as forwardRef45,
14933
14962
  useCallback as useCallback21,
14934
14963
  useId as useId25,
14935
- useMemo as useMemo16,
14964
+ useMemo as useMemo17,
14936
14965
  useState as useState26
14937
14966
  } from "react";
14938
14967
  import { jsx as jsx55, jsxs as jsxs52 } from "react/jsx-runtime";
@@ -14985,24 +15014,24 @@ var Heatmap = forwardRef45(
14985
15014
  ...rest
14986
15015
  }, ref) {
14987
15016
  const reactId = useId25();
14988
- const xs = useMemo16(() => {
15017
+ const xs = useMemo17(() => {
14989
15018
  if (xLabels) return xLabels;
14990
15019
  return Array.from(new Set(data.map((d) => d.x)));
14991
15020
  }, [xLabels, data]);
14992
- const ys = useMemo16(() => {
15021
+ const ys = useMemo17(() => {
14993
15022
  if (yLabels) return yLabels;
14994
15023
  return Array.from(new Set(data.map((d) => d.y)));
14995
15024
  }, [yLabels, data]);
14996
- const cellMap = useMemo16(() => {
15025
+ const cellMap = useMemo17(() => {
14997
15026
  const m = /* @__PURE__ */ new Map();
14998
15027
  for (const c of data) m.set(`${c.x}|${c.y}`, c);
14999
15028
  return m;
15000
15029
  }, [data]);
15001
- const vMin = useMemo16(
15030
+ const vMin = useMemo17(
15002
15031
  () => domainMin ?? (data.length ? Math.min(...data.map((d) => d.value)) : 0),
15003
15032
  [domainMin, data]
15004
15033
  );
15005
- const vMax = useMemo16(
15034
+ const vMax = useMemo17(
15006
15035
  () => domainMax ?? (data.length ? Math.max(...data.map((d) => d.value)) : 1),
15007
15036
  [domainMax, data]
15008
15037
  );
@@ -15024,7 +15053,7 @@ var Heatmap = forwardRef45(
15024
15053
  },
15025
15054
  [onCellClick]
15026
15055
  );
15027
- const resolvedAriaLabel = useMemo16(() => {
15056
+ const resolvedAriaLabel = useMemo17(() => {
15028
15057
  if (ariaLabel) return ariaLabel;
15029
15058
  const t = typeof title === "string" ? title : "Heatmap";
15030
15059
  return `${t} \u2014 ${xs.length}\xD7${ys.length} grid, ${data.length} cells, range ${formatValue(vMin)} to ${formatValue(vMax)}`;
@@ -15814,7 +15843,7 @@ IntegrationCard.displayName = "IntegrationCard";
15814
15843
  import { CheckmarkIcon as CheckmarkIcon6, ChevronRightIcon as ChevronRightIcon3, CopyIcon as CopyIcon3 } from "@octaviaflow/icons";
15815
15844
  import {
15816
15845
  forwardRef as forwardRef50,
15817
- useMemo as useMemo17,
15846
+ useMemo as useMemo18,
15818
15847
  useState as useState28
15819
15848
  } from "react";
15820
15849
  import { Fragment as Fragment28, jsx as jsx61, jsxs as jsxs58 } from "react/jsx-runtime";
@@ -15867,7 +15896,7 @@ function JsonNode({
15867
15896
  const isObject = value !== null && typeof value === "object" && !Array.isArray(value);
15868
15897
  const isArray = Array.isArray(value);
15869
15898
  const isContainer = isObject || isArray;
15870
- const renderKey = useMemo17(() => {
15899
+ const renderKey = useMemo18(() => {
15871
15900
  if (name === void 0) return null;
15872
15901
  if (typeof name === "number") {
15873
15902
  return showIndexes ? /* @__PURE__ */ jsx61("span", { className: "ods-json-viewer__key ods-json-viewer__key--index", children: name }) : null;
@@ -16206,7 +16235,7 @@ import {
16206
16235
  useCallback as useCallback23,
16207
16236
  useEffect as useEffect24,
16208
16237
  useId as useId30,
16209
- useMemo as useMemo18,
16238
+ useMemo as useMemo19,
16210
16239
  useRef as useRef31,
16211
16240
  useState as useState29
16212
16241
  } from "react";
@@ -16274,7 +16303,7 @@ var LineChart = forwardRef53(
16274
16303
  ...rest
16275
16304
  }, ref) {
16276
16305
  const reactId = useId30();
16277
- const allLines = useMemo18(() => {
16306
+ const allLines = useMemo19(() => {
16278
16307
  if (series && series.length > 0) return series;
16279
16308
  return [
16280
16309
  {
@@ -16291,20 +16320,20 @@ var LineChart = forwardRef53(
16291
16320
  );
16292
16321
  const totalX = allLines[0]?.data.length ?? 0;
16293
16322
  const visibleRange = zoom ?? { start: 0, end: Math.max(0, totalX - 1) };
16294
- const lines = useMemo18(
16323
+ const lines = useMemo19(
16295
16324
  () => allLines.map((s) => ({
16296
16325
  ...s,
16297
16326
  data: s.data.slice(visibleRange.start, visibleRange.end + 1)
16298
16327
  })),
16299
16328
  [allLines, visibleRange.start, visibleRange.end]
16300
16329
  );
16301
- const xLabels = useMemo18(
16330
+ const xLabels = useMemo19(
16302
16331
  () => lines[0]?.data.map((p) => p.x) ?? [],
16303
16332
  [lines]
16304
16333
  );
16305
16334
  const xCount = xLabels.length;
16306
16335
  const stepX = (W - PAD * 2) / Math.max(1, xCount - 1);
16307
- const allYs = useMemo18(
16336
+ const allYs = useMemo19(
16308
16337
  () => lines.flatMap((s) => s.data.map((p) => p.y)),
16309
16338
  [lines]
16310
16339
  );
@@ -16312,7 +16341,7 @@ var LineChart = forwardRef53(
16312
16341
  const dataMax = allYs.length ? Math.max(...allYs) : 1;
16313
16342
  const lo = yMin ?? Math.min(0, dataMin);
16314
16343
  const hi = Math.max(lo + 1, yMax ?? dataMax);
16315
- const projected = useMemo18(
16344
+ const projected = useMemo19(
16316
16345
  () => lines.map(
16317
16346
  (s) => s.data.map(
16318
16347
  (p, i) => [
@@ -16323,7 +16352,7 @@ var LineChart = forwardRef53(
16323
16352
  ),
16324
16353
  [lines, stepX, lo, hi]
16325
16354
  );
16326
- const ticks = useMemo18(
16355
+ const ticks = useMemo19(
16327
16356
  () => buildTicks2(lo, hi, Math.max(2, yTicks)),
16328
16357
  [lo, hi, yTicks]
16329
16358
  );
@@ -16420,7 +16449,7 @@ var LineChart = forwardRef53(
16420
16449
  const p = s?.data[hoveredIdx];
16421
16450
  if (p) onPointClick(p, s.id, visibleRange.start + hoveredIdx);
16422
16451
  }, [hoveredIdx, lines, onPointClick, visibleRange.start]);
16423
- const resolvedAriaLabel = useMemo18(() => {
16452
+ const resolvedAriaLabel = useMemo19(() => {
16424
16453
  if (ariaLabel) return ariaLabel;
16425
16454
  const titleText = typeof title === "string" ? title : "";
16426
16455
  const summary = lines.map((s) => {
@@ -16927,7 +16956,7 @@ import { motion as motion24 } from "framer-motion";
16927
16956
  import {
16928
16957
  forwardRef as forwardRef56,
16929
16958
  useId as useId31,
16930
- useMemo as useMemo19
16959
+ useMemo as useMemo20
16931
16960
  } from "react";
16932
16961
  import { Fragment as Fragment30, jsx as jsx66, jsxs as jsxs64 } from "react/jsx-runtime";
16933
16962
  var defaultFormat6 = (n) => {
@@ -16980,7 +17009,7 @@ var Sparkline = forwardRef56(
16980
17009
  const PAD2 = 1;
16981
17010
  const hasData = data.length > 0;
16982
17011
  const canDrawLine = variant === "line" ? data.length >= 2 : hasData;
16983
- const resolvedAriaLabel = useMemo19(() => {
17012
+ const resolvedAriaLabel = useMemo20(() => {
16984
17013
  if (ariaLabel) return ariaLabel;
16985
17014
  if (!hasData) return "Sparkline \u2014 no data";
16986
17015
  const first = formatValue(data[0]);
@@ -17467,7 +17496,7 @@ import {
17467
17496
  useEffect as useEffect26,
17468
17497
  useId as useId33,
17469
17498
  useLayoutEffect as useLayoutEffect6,
17470
- useMemo as useMemo20,
17499
+ useMemo as useMemo21,
17471
17500
  useRef as useRef33,
17472
17501
  useState as useState31
17473
17502
  } from "react";
@@ -17537,11 +17566,11 @@ var MultiSelect = forwardRef58(
17537
17566
  },
17538
17567
  [controlledValue, onChange]
17539
17568
  );
17540
- const selectedSet = useMemo20(
17569
+ const selectedSet = useMemo21(
17541
17570
  () => new Set(selectedValues),
17542
17571
  [selectedValues]
17543
17572
  );
17544
- const filteredOptions = useMemo20(() => {
17573
+ const filteredOptions = useMemo21(() => {
17545
17574
  const base = hideSelected ? options.filter((o) => !selectedSet.has(o.value)) : options;
17546
17575
  if (!query.trim()) return base;
17547
17576
  const q2 = query.trim().toLowerCase();
@@ -18255,7 +18284,7 @@ import {
18255
18284
  forwardRef as forwardRef61,
18256
18285
  useCallback as useCallback27,
18257
18286
  useId as useId36,
18258
- useMemo as useMemo21,
18287
+ useMemo as useMemo22,
18259
18288
  useState as useState32
18260
18289
  } from "react";
18261
18290
  import { jsx as jsx72, jsxs as jsxs70 } from "react/jsx-runtime";
@@ -18349,7 +18378,7 @@ var Pagination = forwardRef61(
18349
18378
  },
18350
18379
  [currentPage, isControlled, onPageChange, totalPages]
18351
18380
  );
18352
- const pages = useMemo21(
18381
+ const pages = useMemo22(
18353
18382
  () => buildPageRange(totalPages, currentPage, siblingCount, boundaryCount),
18354
18383
  [totalPages, currentPage, siblingCount, boundaryCount]
18355
18384
  );
@@ -18545,7 +18574,7 @@ import {
18545
18574
  import { CheckmarkIcon as CheckmarkIcon7, ViewIcon, ViewOffIcon } from "@octaviaflow/icons";
18546
18575
 
18547
18576
  // src/hooks/usePasswordStrength.ts
18548
- import { useMemo as useMemo22 } from "react";
18577
+ import { useMemo as useMemo23 } from "react";
18549
18578
  var DEFAULT_PASSWORD_RULES = [
18550
18579
  { id: "length-8", label: "At least 8 characters", test: /.{8,}/ },
18551
18580
  { id: "lowercase", label: "A lower-case letter", test: /[a-z]/ },
@@ -18553,7 +18582,7 @@ var DEFAULT_PASSWORD_RULES = [
18553
18582
  { id: "digit", label: "A digit", test: /\d/ }
18554
18583
  ];
18555
18584
  function usePasswordStrength(value, rules = DEFAULT_PASSWORD_RULES) {
18556
- return useMemo22(() => {
18585
+ return useMemo23(() => {
18557
18586
  const evaluated = rules.map((r) => ({
18558
18587
  id: r.id,
18559
18588
  label: r.label,
@@ -22553,7 +22582,8 @@ function SidebarUserCard({ user }) {
22553
22582
  {
22554
22583
  trigger: body,
22555
22584
  items: user.menu,
22556
- align: "end",
22585
+ align: "start",
22586
+ matchTriggerWidth: true,
22557
22587
  "aria-label": labelText,
22558
22588
  triggerClassName: "ods-sidebar__user-card"
22559
22589
  }
@@ -23436,7 +23466,7 @@ import {
23436
23466
  useCallback as useCallback35,
23437
23467
  useEffect as useEffect34,
23438
23468
  useLayoutEffect as useLayoutEffect9,
23439
- useMemo as useMemo23,
23469
+ useMemo as useMemo24,
23440
23470
  useState as useState42
23441
23471
  } from "react";
23442
23472
  import { createPortal as createPortal14 } from "react-dom";
@@ -23463,7 +23493,7 @@ var Spotlight = forwardRef85(
23463
23493
  width: typeof window !== "undefined" ? window.innerWidth : 0,
23464
23494
  height: typeof window !== "undefined" ? window.innerHeight : 0
23465
23495
  }));
23466
- const maskId = useMemo23(
23496
+ const maskId = useMemo24(
23467
23497
  () => `ods-spotlight-${Math.random().toString(36).slice(2, 9)}`,
23468
23498
  []
23469
23499
  );
@@ -23640,7 +23670,7 @@ import {
23640
23670
  forwardRef as forwardRef87,
23641
23671
  useCallback as useCallback36,
23642
23672
  useId as useId48,
23643
- useMemo as useMemo24,
23673
+ useMemo as useMemo25,
23644
23674
  useState as useState43
23645
23675
  } from "react";
23646
23676
  import { jsx as jsx104, jsxs as jsxs98 } from "react/jsx-runtime";
@@ -23678,7 +23708,7 @@ var StatusTiles = forwardRef87(
23678
23708
  ...rest
23679
23709
  }, ref) {
23680
23710
  const reactId = useId48();
23681
- const visible = useMemo24(
23711
+ const visible = useMemo25(
23682
23712
  () => max < data.length ? data.slice(data.length - max) : data,
23683
23713
  [data, max]
23684
23714
  );
@@ -23705,7 +23735,7 @@ var StatusTiles = forwardRef87(
23705
23735
  },
23706
23736
  [visible, onTileClick]
23707
23737
  );
23708
- const resolvedAriaLabel = useMemo24(() => {
23738
+ const resolvedAriaLabel = useMemo25(() => {
23709
23739
  if (ariaLabel) return ariaLabel;
23710
23740
  const t = typeof title === "string" ? title : "Status";
23711
23741
  const tally = {};
@@ -23960,7 +23990,7 @@ import {
23960
23990
  forwardRef as forwardRef89,
23961
23991
  useCallback as useCallback37,
23962
23992
  useId as useId50,
23963
- useMemo as useMemo25,
23993
+ useMemo as useMemo26,
23964
23994
  useState as useState44
23965
23995
  } from "react";
23966
23996
  import { jsx as jsx106, jsxs as jsxs100 } from "react/jsx-runtime";
@@ -24025,12 +24055,12 @@ var Sankey = forwardRef89(function Sankey2({
24025
24055
  ...rest
24026
24056
  }, ref) {
24027
24057
  const reactId = useId50();
24028
- const columnMap = useMemo25(
24058
+ const columnMap = useMemo26(
24029
24059
  () => assignColumns(nodes, links),
24030
24060
  [nodes, links]
24031
24061
  );
24032
24062
  const columnCount = Math.max(0, ...Array.from(columnMap.values())) + 1;
24033
- const flows = useMemo25(() => {
24063
+ const flows = useMemo26(() => {
24034
24064
  const inFlow = /* @__PURE__ */ new Map();
24035
24065
  const outFlow = /* @__PURE__ */ new Map();
24036
24066
  for (const n of nodes) {
@@ -24043,7 +24073,7 @@ var Sankey = forwardRef89(function Sankey2({
24043
24073
  }
24044
24074
  return { inFlow, outFlow };
24045
24075
  }, [nodes, links]);
24046
- const columns = useMemo25(() => {
24076
+ const columns = useMemo26(() => {
24047
24077
  const grouped = Array.from(
24048
24078
  { length: columnCount },
24049
24079
  () => []
@@ -24054,7 +24084,7 @@ var Sankey = forwardRef89(function Sankey2({
24054
24084
  }
24055
24085
  return grouped;
24056
24086
  }, [nodes, columnMap, columnCount]);
24057
- const columnFlows = useMemo25(
24087
+ const columnFlows = useMemo26(
24058
24088
  () => columns.map(
24059
24089
  (col) => col.reduce((s, n) => {
24060
24090
  const f = Math.max(
@@ -24068,11 +24098,11 @@ var Sankey = forwardRef89(function Sankey2({
24068
24098
  );
24069
24099
  const maxColumnFlow = Math.max(1, ...columnFlows);
24070
24100
  const colAvail = (col) => height - Math.max(0, col.length - 1) * nodeGap;
24071
- const scale = useMemo25(() => {
24101
+ const scale = useMemo26(() => {
24072
24102
  const avail = Math.min(...columns.map(colAvail));
24073
24103
  return avail / maxColumnFlow;
24074
24104
  }, [columns, height, nodeGap, maxColumnFlow]);
24075
- const layoutNodes = useMemo25(() => {
24105
+ const layoutNodes = useMemo26(() => {
24076
24106
  const m = /* @__PURE__ */ new Map();
24077
24107
  const colX = (c) => {
24078
24108
  if (columnCount <= 1) return 0;
@@ -24113,7 +24143,7 @@ var Sankey = forwardRef89(function Sankey2({
24113
24143
  }
24114
24144
  return m;
24115
24145
  }, [columns, columnCount, width, nodeWidth, flows, scale, height, nodeGap]);
24116
- const layoutLinks = useMemo25(() => {
24146
+ const layoutLinks = useMemo26(() => {
24117
24147
  const sourceOffset = /* @__PURE__ */ new Map();
24118
24148
  const targetOffset = /* @__PURE__ */ new Map();
24119
24149
  for (const n of nodes) {
@@ -24182,7 +24212,7 @@ var Sankey = forwardRef89(function Sankey2({
24182
24212
  },
24183
24213
  [onNodeClick]
24184
24214
  );
24185
- const resolvedAriaLabel = useMemo25(() => {
24215
+ const resolvedAriaLabel = useMemo26(() => {
24186
24216
  if (ariaLabel) return ariaLabel;
24187
24217
  const t = typeof title === "string" ? title : "Sankey";
24188
24218
  return `${t} \u2014 ${nodes.length} nodes, ${links.length} flows`;
@@ -24590,7 +24620,7 @@ function TableRow({
24590
24620
 
24591
24621
  // src/components/Tabs/Tabs.tsx
24592
24622
  import { motion as motion33 } from "framer-motion";
24593
- import { useCallback as useCallback39, useEffect as useEffect35, useId as useId51, useMemo as useMemo26, useRef as useRef45, useState as useState46 } from "react";
24623
+ import { useCallback as useCallback39, useEffect as useEffect35, useId as useId51, useMemo as useMemo27, useRef as useRef45, useState as useState46 } from "react";
24594
24624
  import { useTab, useTabList, useTabPanel } from "react-aria";
24595
24625
  import { jsx as jsx109, jsxs as jsxs103 } from "react/jsx-runtime";
24596
24626
  function TabButton({
@@ -24651,7 +24681,7 @@ function Tabs({
24651
24681
  if (!value) setInternalValue(keyStr);
24652
24682
  onChange?.(keyStr);
24653
24683
  };
24654
- const panelContentMap = useMemo26(() => {
24684
+ const panelContentMap = useMemo27(() => {
24655
24685
  const map = /* @__PURE__ */ new Map();
24656
24686
  items.forEach((item) => {
24657
24687
  map.set(item.value, item.children);
@@ -25253,7 +25283,7 @@ import { CopyIcon as CopyIcon4, CutIcon } from "@octaviaflow/icons";
25253
25283
  import {
25254
25284
  useCallback as useCallback40,
25255
25285
  useEffect as useEffect36,
25256
- useMemo as useMemo27,
25286
+ useMemo as useMemo28,
25257
25287
  useRef as useRef46,
25258
25288
  useState as useState48
25259
25289
  } from "react";
@@ -25342,7 +25372,7 @@ function useTextareaCommands({
25342
25372
  const dismissedAtRef = useRef46(
25343
25373
  null
25344
25374
  );
25345
- const items = useMemo27(() => {
25375
+ const items = useMemo28(() => {
25346
25376
  const q2 = query.trim().toLowerCase();
25347
25377
  if (!q2) return commands.slice(0, maxItems);
25348
25378
  return commands.filter((c) => {
@@ -25635,7 +25665,7 @@ import {
25635
25665
  TextStrikethroughIcon,
25636
25666
  UndoIcon
25637
25667
  } from "@octaviaflow/icons";
25638
- import { useCallback as useCallback42, useMemo as useMemo28, useRef as useRef47 } from "react";
25668
+ import { useCallback as useCallback42, useMemo as useMemo29, useRef as useRef47 } from "react";
25639
25669
  import { jsx as jsx113 } from "react/jsx-runtime";
25640
25670
  function useTextareaTools({
25641
25671
  textareaRef,
@@ -25645,7 +25675,7 @@ function useTextareaTools({
25645
25675
  }) {
25646
25676
  const valueRef = useRef47(value);
25647
25677
  valueRef.current = value;
25648
- const helpers = useMemo28(() => {
25678
+ const helpers = useMemo29(() => {
25649
25679
  const getTa = () => textareaRef.current;
25650
25680
  const getSelection = () => {
25651
25681
  const ta = getTa();
@@ -25743,7 +25773,7 @@ function useTextareaTools({
25743
25773
  getTextarea: getTa
25744
25774
  };
25745
25775
  }, [textareaRef, onChange]);
25746
- const visibleTools = useMemo28(
25776
+ const visibleTools = useMemo29(
25747
25777
  () => tools.filter((t) => t.isVisible ? t.isVisible(helpers) : true),
25748
25778
  [tools, helpers]
25749
25779
  );
@@ -26711,7 +26741,7 @@ import {
26711
26741
  useCallback as useCallback44,
26712
26742
  useEffect as useEffect40,
26713
26743
  useId as useId57,
26714
- useMemo as useMemo29,
26744
+ useMemo as useMemo30,
26715
26745
  useRef as useRef50,
26716
26746
  useState as useState52
26717
26747
  } from "react";
@@ -26773,11 +26803,11 @@ var TimezonePicker = forwardRef98(
26773
26803
  else if (forwardedRef)
26774
26804
  forwardedRef.current = node;
26775
26805
  };
26776
- const selected = useMemo29(
26806
+ const selected = useMemo30(
26777
26807
  () => options.find((o) => o.iana === value),
26778
26808
  [options, value]
26779
26809
  );
26780
- const filtered = useMemo29(() => {
26810
+ const filtered = useMemo30(() => {
26781
26811
  if (!query.trim()) return options;
26782
26812
  const q2 = query.trim().toLowerCase();
26783
26813
  return options.filter(
@@ -27020,7 +27050,7 @@ import {
27020
27050
  createContext as createContext2,
27021
27051
  useCallback as useCallback45,
27022
27052
  useContext as useContext2,
27023
- useMemo as useMemo30,
27053
+ useMemo as useMemo31,
27024
27054
  useRef as useRef51,
27025
27055
  useState as useState53
27026
27056
  } from "react";
@@ -27174,7 +27204,7 @@ function PositionStack({ items, position, onDismiss, maxStack }) {
27174
27204
  const [hovered, setHovered] = useState53(false);
27175
27205
  const [pinned, setPinned] = useState53(false);
27176
27206
  const expanded = hovered || pinned;
27177
- const ordered = useMemo30(() => [...items].reverse(), [items]);
27207
+ const ordered = useMemo31(() => [...items].reverse(), [items]);
27178
27208
  const isBottom = position.startsWith("bottom");
27179
27209
  const dir = isBottom ? -1 : 1;
27180
27210
  if (pinned && items.length === 0) setPinned(false);
@@ -27325,7 +27355,7 @@ function ToastProvider({
27325
27355
  },
27326
27356
  [dismiss, defaultPosition]
27327
27357
  );
27328
- const groups = useMemo30(() => {
27358
+ const groups = useMemo31(() => {
27329
27359
  const out = {
27330
27360
  "top-left": [],
27331
27361
  "top-center": [],
@@ -27986,7 +28016,7 @@ import {
27986
28016
  useCallback as useCallback48,
27987
28017
  useEffect as useEffect41,
27988
28018
  useId as useId61,
27989
- useMemo as useMemo31,
28019
+ useMemo as useMemo32,
27990
28020
  useState as useState55
27991
28021
  } from "react";
27992
28022
  import { jsx as jsx124, jsxs as jsxs117 } from "react/jsx-runtime";
@@ -28033,7 +28063,7 @@ var TreeView = forwardRef101(
28033
28063
  (node) => node.children ?? loaded[node.id],
28034
28064
  [loaded]
28035
28065
  );
28036
- const resolvedNodes = useMemo31(() => {
28066
+ const resolvedNodes = useMemo32(() => {
28037
28067
  const walk = (ns) => ns.map((n) => {
28038
28068
  const kids = resolveChildren(n);
28039
28069
  if (kids) return { ...n, children: walk(kids) };
@@ -28041,7 +28071,7 @@ var TreeView = forwardRef101(
28041
28071
  });
28042
28072
  return walk(nodes);
28043
28073
  }, [nodes, resolveChildren]);
28044
- const visibleList = useMemo31(
28074
+ const visibleList = useMemo32(
28045
28075
  () => buildVisibleList(resolvedNodes, expandedSet),
28046
28076
  [resolvedNodes, expandedSet]
28047
28077
  );
@@ -28406,10 +28436,10 @@ var UserCard = forwardRef102(
28406
28436
  UserCard.displayName = "UserCard";
28407
28437
 
28408
28438
  // src/components/WorkflowEditor/WorkflowEditor.tsx
28409
- import { useCallback as useCallback50, useMemo as useMemo33, useState as useState56 } from "react";
28439
+ import { useCallback as useCallback50, useMemo as useMemo34, useState as useState56 } from "react";
28410
28440
 
28411
28441
  // src/hooks/useWorkflow.ts
28412
- import { useCallback as useCallback49, useMemo as useMemo32, useReducer } from "react";
28442
+ import { useCallback as useCallback49, useMemo as useMemo33, useReducer } from "react";
28413
28443
 
28414
28444
  // src/workflow/types.ts
28415
28445
  var types_exports = {};
@@ -28889,7 +28919,7 @@ function genId(prefix) {
28889
28919
  return `${prefix}_${Date.now().toString(36)}_${idCounter}`;
28890
28920
  }
28891
28921
  function useWorkflow(options = {}) {
28892
- const initial = useMemo32(
28922
+ const initial = useMemo33(
28893
28923
  () => buildInitialWorkflow({
28894
28924
  metadata: options.metadata ? { ...options.metadata } : void 0,
28895
28925
  canvas: {
@@ -29206,11 +29236,11 @@ function WorkflowEditor({
29206
29236
  if (onReset) onReset();
29207
29237
  else dispatch({ type: "RESET" });
29208
29238
  }, [onReset, dispatch]);
29209
- const nextNodes = useMemo33(
29239
+ const nextNodes = useMemo34(
29210
29240
  () => workflow.canvas.nodes.map(toNextNode),
29211
29241
  [workflow.canvas.nodes]
29212
29242
  );
29213
- const nextEdges = useMemo33(() => workflow.canvas.edges.map(toNextEdge), [workflow.canvas.edges]);
29243
+ const nextEdges = useMemo34(() => workflow.canvas.edges.map(toNextEdge), [workflow.canvas.edges]);
29214
29244
  const onNodesChange = useCallback50(
29215
29245
  (changes) => {
29216
29246
  const reduced = applyNodeChanges(
@@ -29301,7 +29331,7 @@ function WorkflowEditor({
29301
29331
  const cy = (minY + maxY) / 2;
29302
29332
  wf.setViewport({ x: cw / 2 - cx * zoom, y: ch / 2 - cy * zoom, zoom });
29303
29333
  }, [workflow.canvas.nodes, canvasSize, wf]);
29304
- const defaultToolbar = useMemo33(
29334
+ const defaultToolbar = useMemo34(
29305
29335
  () => /* @__PURE__ */ jsxs119(FlowToolbar, { placement: "left", children: [
29306
29336
  onSave && /* @__PURE__ */ jsx126(
29307
29337
  FlowToolbarButton,
@@ -29516,7 +29546,7 @@ import {
29516
29546
  forwardRef as forwardRef103,
29517
29547
  useCallback as useCallback51,
29518
29548
  useId as useId63,
29519
- useMemo as useMemo34,
29549
+ useMemo as useMemo35,
29520
29550
  useState as useState57
29521
29551
  } from "react";
29522
29552
  import { Fragment as Fragment48, jsx as jsx127, jsxs as jsxs120 } from "react/jsx-runtime";
@@ -29603,7 +29633,7 @@ var XmlViewer = forwardRef103(
29603
29633
  }, ref) {
29604
29634
  const reactId = useId63();
29605
29635
  const baseId = providedId ?? `ods-xml-viewer-${reactId}`;
29606
- const parsed = useMemo34(() => parseXml(data), [data]);
29636
+ const parsed = useMemo35(() => parseXml(data), [data]);
29607
29637
  const bodyStyle = height !== void 0 ? { height: typeof height === "number" ? `${height}px` : height } : maxHeight !== void 0 ? {
29608
29638
  maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
29609
29639
  } : void 0;
@@ -29795,7 +29825,7 @@ import {
29795
29825
  forwardRef as forwardRef104,
29796
29826
  useCallback as useCallback52,
29797
29827
  useId as useId64,
29798
- useMemo as useMemo35,
29828
+ useMemo as useMemo36,
29799
29829
  useState as useState58
29800
29830
  } from "react";
29801
29831
  import { Fragment as Fragment49, jsx as jsx128, jsxs as jsxs121 } from "react/jsx-runtime";
@@ -29940,7 +29970,7 @@ var YamlViewer = forwardRef104(
29940
29970
  }, ref) {
29941
29971
  const reactId = useId64();
29942
29972
  const baseId = providedId ?? `ods-yaml-viewer-${reactId}`;
29943
- const text = useMemo35(() => {
29973
+ const text = useMemo36(() => {
29944
29974
  if (typeof data === "string") return data;
29945
29975
  try {
29946
29976
  return toYaml(data);
@@ -29948,7 +29978,7 @@ var YamlViewer = forwardRef104(
29948
29978
  return JSON.stringify(data, null, 2);
29949
29979
  }
29950
29980
  }, [data]);
29951
- const tokens = useMemo35(() => tokenizeYaml(text), [text]);
29981
+ const tokens = useMemo36(() => tokenizeYaml(text), [text]);
29952
29982
  const [collapsed, setCollapsed] = useState58(() => {
29953
29983
  const s = /* @__PURE__ */ new Set();
29954
29984
  tokens.forEach((t) => {
@@ -29964,7 +29994,7 @@ var YamlViewer = forwardRef104(
29964
29994
  return next;
29965
29995
  });
29966
29996
  }, []);
29967
- const hidden = useMemo35(() => {
29997
+ const hidden = useMemo36(() => {
29968
29998
  const hide = /* @__PURE__ */ new Set();
29969
29999
  for (let i = 0; i < tokens.length; i++) {
29970
30000
  const t = tokens[i];
@@ -30513,12 +30543,12 @@ function useTraceTimeline({
30513
30543
 
30514
30544
  // src/provider/OdsProvider.tsx
30515
30545
  import { generateCssVars, resolveConfig } from "@octaviaflow/config";
30516
- import { createContext as createContext3, useContext as useContext3, useEffect as useEffect44, useMemo as useMemo36 } from "react";
30546
+ import { createContext as createContext3, useContext as useContext3, useEffect as useEffect44, useMemo as useMemo37 } from "react";
30517
30547
  import { OverlayProvider as OverlayProvider3 } from "react-aria";
30518
30548
  import { jsx as jsx129 } from "react/jsx-runtime";
30519
30549
  var OdsContext = createContext3(null);
30520
30550
  function OdsProvider({ config: userConfig, children }) {
30521
- const resolved = useMemo36(() => resolveConfig(userConfig), [userConfig]);
30551
+ const resolved = useMemo37(() => resolveConfig(userConfig), [userConfig]);
30522
30552
  useEffect44(() => {
30523
30553
  const cssVarsBlock = generateCssVars(resolved);
30524
30554
  const match = cssVarsBlock.match(/:root\s*\{([\s\S]*)\}/);
@@ -30535,7 +30565,7 @@ function OdsProvider({ config: userConfig, children }) {
30535
30565
  }
30536
30566
  }
30537
30567
  }, [resolved]);
30538
- const contextValue = useMemo36(() => ({ config: resolved }), [resolved]);
30568
+ const contextValue = useMemo37(() => ({ config: resolved }), [resolved]);
30539
30569
  return /* @__PURE__ */ jsx129(OdsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx129(OverlayProvider3, { children }) });
30540
30570
  }
30541
30571
  function useOds() {
@@ -30555,7 +30585,7 @@ var emptyMotion = {
30555
30585
  };
30556
30586
  function useOdsMotion() {
30557
30587
  const config = useOds();
30558
- return useMemo36(() => {
30588
+ return useMemo37(() => {
30559
30589
  if (!config.motion.enabled) {
30560
30590
  return emptyMotion;
30561
30591
  }