@flowsterix/react 0.11.0 → 0.12.0

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 (33) hide show
  1. package/dist/chunk-D5LQLRSU.cjs +289 -0
  2. package/dist/chunk-FCOKCGV3.cjs +21 -0
  3. package/dist/chunk-HPVLOLCD.cjs +1 -0
  4. package/dist/components/TourPopoverPortal.d.ts +1 -1
  5. package/dist/components/TourPopoverPortal.d.ts.map +1 -1
  6. package/dist/context.d.ts +6 -0
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/devtools/DevToolsProvider.d.ts.map +1 -1
  9. package/dist/devtools/components/FlowEditModal.d.ts.map +1 -1
  10. package/dist/devtools/components/FlowItem.d.ts.map +1 -1
  11. package/dist/devtools/components/GrabberOverlay.d.ts +1 -0
  12. package/dist/devtools/components/GrabberOverlay.d.ts.map +1 -1
  13. package/dist/devtools/components/StepItem.d.ts.map +1 -1
  14. package/dist/devtools/components/StepList.d.ts.map +1 -1
  15. package/dist/devtools/components/TabNav.d.ts.map +1 -1
  16. package/dist/devtools/components/Toolbar.d.ts.map +1 -1
  17. package/dist/devtools/globalBridge.d.ts +24 -0
  18. package/dist/devtools/globalBridge.d.ts.map +1 -0
  19. package/dist/devtools/hooks/useFlowsData.d.ts.map +1 -1
  20. package/dist/devtools/index.cjs +849 -577
  21. package/dist/devtools/index.mjs +605 -281
  22. package/dist/devtools/motion.d.ts +64 -0
  23. package/dist/devtools/motion.d.ts.map +1 -0
  24. package/dist/hooks/useHiddenTargetFallback.d.ts.map +1 -1
  25. package/dist/hooks/useTourOverlay.d.ts.map +1 -1
  26. package/dist/index.cjs +701 -927
  27. package/dist/index.mjs +116 -42
  28. package/dist/router/index.cjs +13 -202
  29. package/dist/router/nextAppRouterAdapter.cjs +11 -200
  30. package/dist/router/nextPagesRouterAdapter.cjs +10 -199
  31. package/dist/router/reactRouterAdapter.cjs +10 -199
  32. package/dist/router/tanstackRouterAdapter.cjs +22 -214
  33. package/package.json +1 -1
@@ -5,11 +5,82 @@ import {
5
5
  } from "../chunk-AJZMUYBN.mjs";
6
6
 
7
7
  // src/devtools/DevToolsProvider.tsx
8
- import { useCallback as useCallback8, useEffect as useEffect5, useState as useState8 } from "react";
8
+ import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef2, useState as useState11 } from "react";
9
9
  import { createPortal as createPortal3 } from "react-dom";
10
- import { AnimatePresence as AnimatePresence3, motion as motion6 } from "motion/react";
10
+ import { AnimatePresence as AnimatePresence7, motion as motion9 } from "motion/react";
11
+
12
+ // src/devtools/motion.ts
13
+ import { useEffect, useState } from "react";
14
+ var springs = {
15
+ snappy: {
16
+ type: "spring",
17
+ damping: 30,
18
+ stiffness: 500,
19
+ mass: 0.5
20
+ },
21
+ smooth: {
22
+ type: "spring",
23
+ damping: 30,
24
+ stiffness: 300,
25
+ mass: 0.8
26
+ },
27
+ bouncy: {
28
+ type: "spring",
29
+ damping: 15,
30
+ stiffness: 400,
31
+ mass: 0.5
32
+ }
33
+ };
34
+ var stagger = {
35
+ fast: {
36
+ staggerChildren: 0.03,
37
+ delayChildren: 0.05
38
+ },
39
+ default: {
40
+ staggerChildren: 0.05,
41
+ delayChildren: 0.1
42
+ }
43
+ };
44
+ var listItemVariants = {
45
+ hidden: {
46
+ opacity: 0,
47
+ y: 8,
48
+ scale: 0.98
49
+ },
50
+ visible: {
51
+ opacity: 1,
52
+ y: 0,
53
+ scale: 1
54
+ },
55
+ exit: {
56
+ opacity: 0,
57
+ scale: 0.95,
58
+ transition: { duration: 0.15 }
59
+ }
60
+ };
61
+ var listContainerVariants = {
62
+ hidden: { opacity: 0 },
63
+ visible: {
64
+ opacity: 1,
65
+ transition: stagger.fast
66
+ }
67
+ };
68
+ function useReducedMotion() {
69
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
70
+ useEffect(() => {
71
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
72
+ setPrefersReducedMotion(mediaQuery.matches);
73
+ const handler = (event) => {
74
+ setPrefersReducedMotion(event.matches);
75
+ };
76
+ mediaQuery.addEventListener("change", handler);
77
+ return () => mediaQuery.removeEventListener("change", handler);
78
+ }, []);
79
+ return prefersReducedMotion;
80
+ }
11
81
 
12
82
  // src/devtools/components/GrabberOverlay.tsx
83
+ import { useEffect as useEffect2, useState as useState2 } from "react";
13
84
  import { createPortal } from "react-dom";
14
85
  import { AnimatePresence, motion } from "motion/react";
15
86
 
@@ -125,6 +196,10 @@ var styles = {
125
196
  pointerEvents: "none",
126
197
  boxShadow: "0 0 0 4px hsl(217 91% 60% / 0.15), 0 4px 20px hsl(217 91% 60% / 0.2)"
127
198
  },
199
+ highlightPulse: {
200
+ boxShadow: "0 0 0 8px hsl(142 71% 55% / 0.3), 0 4px 20px hsl(142 71% 55% / 0.4)",
201
+ borderColor: "hsl(142 71% 55%)"
202
+ },
128
203
  label: {
129
204
  position: "absolute",
130
205
  bottom: "100%",
@@ -183,7 +258,6 @@ var styles = {
183
258
  position: "fixed",
184
259
  bottom: 20,
185
260
  left: "50%",
186
- transform: "translateX(-50%)",
187
261
  display: "flex",
188
262
  alignItems: "center",
189
263
  gap: 12,
@@ -227,7 +301,24 @@ var springTransition = {
227
301
  mass: 0.8
228
302
  };
229
303
  function GrabberOverlay(props) {
230
- const { isGrabbing, hoveredInfo, container } = props;
304
+ const { isGrabbing, hoveredInfo, container, onElementSelected } = props;
305
+ const reducedMotion = useReducedMotion();
306
+ const [showPulse, setShowPulse] = useState2(false);
307
+ useEffect2(() => {
308
+ if (onElementSelected) {
309
+ }
310
+ }, [onElementSelected]);
311
+ useEffect2(() => {
312
+ const handlePulse = () => {
313
+ if (reducedMotion) return;
314
+ setShowPulse(true);
315
+ setTimeout(() => setShowPulse(false), 300);
316
+ };
317
+ window.__devtools_pulse = handlePulse;
318
+ return () => {
319
+ delete window.__devtools_pulse;
320
+ };
321
+ }, [reducedMotion]);
231
322
  if (typeof window === "undefined") return null;
232
323
  const portalContainer = container ?? document.body;
233
324
  const labelStyle = {
@@ -243,12 +334,16 @@ function GrabberOverlay(props) {
243
334
  labelStyle.left = "auto";
244
335
  labelStyle.right = 0;
245
336
  }
337
+ const highlightStyle = {
338
+ ...styles.highlight,
339
+ ...showPulse && styles.highlightPulse
340
+ };
246
341
  return createPortal(
247
342
  /* @__PURE__ */ jsxs("div", { style: styles.root, "data-devtools-panel": "", children: [
248
343
  /* @__PURE__ */ jsx(AnimatePresence, { children: isGrabbing && hoveredInfo && /* @__PURE__ */ jsx(
249
344
  motion.div,
250
345
  {
251
- style: styles.highlight,
346
+ style: highlightStyle,
252
347
  initial: {
253
348
  top: hoveredInfo.rect.top,
254
349
  left: hoveredInfo.rect.left,
@@ -261,19 +356,20 @@ function GrabberOverlay(props) {
261
356
  left: hoveredInfo.rect.left,
262
357
  width: hoveredInfo.rect.width,
263
358
  height: hoveredInfo.rect.height,
264
- opacity: 1
359
+ opacity: 1,
360
+ scale: showPulse ? 1.02 : 1
265
361
  },
266
362
  exit: {
267
363
  opacity: 0
268
364
  },
269
- transition: springTransition,
365
+ transition: reducedMotion ? { duration: 0 } : springTransition,
270
366
  children: /* @__PURE__ */ jsxs(
271
367
  motion.div,
272
368
  {
273
369
  style: labelStyle,
274
- initial: { opacity: 0, y: 4 },
370
+ initial: reducedMotion ? {} : { opacity: 0, y: 4 },
275
371
  animate: { opacity: 1, y: 0 },
276
- transition: { delay: 0.03, duration: 0.12 },
372
+ transition: reducedMotion ? { duration: 0 } : { delay: 0.03, duration: 0.12 },
277
373
  children: [
278
374
  /* @__PURE__ */ jsxs("div", { style: styles.labelTop, children: [
279
375
  /* @__PURE__ */ jsxs("span", { style: styles.tagBadge, children: [
@@ -311,10 +407,10 @@ function GrabberOverlay(props) {
311
407
  motion.div,
312
408
  {
313
409
  style: styles.hint,
314
- initial: { opacity: 0, y: 10, scale: 0.95 },
315
- animate: { opacity: 1, y: 0, scale: 1 },
316
- exit: { opacity: 0, y: 10, scale: 0.95 },
317
- transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
410
+ initial: reducedMotion ? {} : { opacity: 0, y: 10, scale: 0.95, x: "-50%" },
411
+ animate: { opacity: 1, y: 0, scale: 1, x: "-50%" },
412
+ exit: reducedMotion ? {} : { opacity: 0, y: 10, scale: 0.95, x: "-50%" },
413
+ transition: reducedMotion ? { duration: 0 } : springs.smooth,
318
414
  children: [
319
415
  /* @__PURE__ */ jsxs("div", { style: styles.hintItem, children: [
320
416
  /* @__PURE__ */ jsx("span", { style: styles.kbd, children: "Click" }),
@@ -340,7 +436,8 @@ function GrabberOverlay(props) {
340
436
  }
341
437
 
342
438
  // src/devtools/components/StepList.tsx
343
- import { useCallback, useState as useState2 } from "react";
439
+ import { useCallback, useState as useState5 } from "react";
440
+ import { motion as motion4, AnimatePresence as AnimatePresence3 } from "motion/react";
344
441
  import {
345
442
  DndContext,
346
443
  DragOverlay,
@@ -357,8 +454,10 @@ import {
357
454
  } from "@dnd-kit/sortable";
358
455
 
359
456
  // src/devtools/components/StepItem.tsx
457
+ import { useState as useState3 } from "react";
360
458
  import { useSortable } from "@dnd-kit/sortable";
361
459
  import { CSS as CSS2 } from "@dnd-kit/utilities";
460
+ import { motion as motion2 } from "motion/react";
362
461
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
363
462
  var styles2 = {
364
463
  card: {
@@ -370,7 +469,12 @@ var styles2 = {
370
469
  border: "1px solid hsl(215 20% 22%)",
371
470
  fontSize: 12,
372
471
  fontFamily: "inherit",
373
- overflow: "hidden"
472
+ overflow: "hidden",
473
+ transition: "border-color 0.15s ease, box-shadow 0.15s ease"
474
+ },
475
+ cardHover: {
476
+ borderColor: "hsl(217 91% 55% / 0.4)",
477
+ boxShadow: "0 0 0 2px hsl(217 91% 55% / 0.1), 0 4px 12px rgba(0, 0, 0, 0.2)"
374
478
  },
375
479
  cardGhost: {
376
480
  opacity: 0.4,
@@ -509,6 +613,8 @@ var styles2 = {
509
613
  };
510
614
  function SortableStepItem(props) {
511
615
  const { step, index, onDelete, isBeingDragged = false } = props;
616
+ const [isHovered, setIsHovered] = useState3(false);
617
+ const reducedMotion = useReducedMotion();
512
618
  const {
513
619
  attributes,
514
620
  listeners,
@@ -530,86 +636,108 @@ function SortableStepItem(props) {
530
636
  };
531
637
  const cardStyle = {
532
638
  ...styles2.card,
639
+ ...isHovered && !isGhost && styles2.cardHover,
533
640
  ...isGhost && styles2.cardGhost
534
641
  };
535
642
  const handleStyle = {
536
643
  ...styles2.dragHandle
537
644
  };
538
- return /* @__PURE__ */ jsx2("div", { ref: setNodeRef, style: wrapperStyle, children: /* @__PURE__ */ jsxs2("div", { style: cardStyle, children: [
539
- /* @__PURE__ */ jsx2("div", { style: handleStyle, ...attributes, ...listeners, children: /* @__PURE__ */ jsxs2("svg", { width: "10", height: "16", viewBox: "0 0 10 16", fill: "currentColor", children: [
540
- /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "2", r: "1.5" }),
541
- /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "2", r: "1.5" }),
542
- /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "8", r: "1.5" }),
543
- /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "8", r: "1.5" }),
544
- /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "14", r: "1.5" }),
545
- /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "14", r: "1.5" })
546
- ] }) }),
547
- /* @__PURE__ */ jsxs2("div", { style: styles2.content, children: [
548
- /* @__PURE__ */ jsxs2("div", { style: styles2.header, children: [
549
- /* @__PURE__ */ jsx2("span", { style: styles2.order, children: index + 1 }),
550
- /* @__PURE__ */ jsxs2("span", { style: styles2.tagBadge, children: [
551
- "<",
552
- step.elementTag,
553
- ">"
554
- ] }),
555
- step.elementText && /* @__PURE__ */ jsx2("span", { style: styles2.text, children: step.elementText })
556
- ] }),
557
- /* @__PURE__ */ jsx2("div", { style: styles2.selector, children: step.selector }),
558
- step.source && /* @__PURE__ */ jsxs2("div", { style: styles2.sourceRow, children: [
559
- /* @__PURE__ */ jsx2(
560
- "svg",
561
- {
562
- width: "10",
563
- height: "10",
564
- viewBox: "0 0 16 16",
565
- fill: "hsl(142 71% 55%)",
566
- children: /* @__PURE__ */ jsx2("path", { d: "M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z" })
567
- }
568
- ),
569
- /* @__PURE__ */ jsx2(
570
- "a",
571
- {
572
- href: getVSCodeLink({ source: step.source }),
573
- style: styles2.sourceLink,
574
- title: "Open in VS Code",
575
- children: formatSourcePath({ source: step.source })
576
- }
577
- ),
578
- /* @__PURE__ */ jsx2(
579
- "button",
580
- {
581
- type: "button",
582
- style: styles2.copyButton,
583
- onClick: handleCopySource,
584
- title: "Copy path",
585
- children: /* @__PURE__ */ jsxs2(
645
+ return /* @__PURE__ */ jsx2(
646
+ "div",
647
+ {
648
+ ref: setNodeRef,
649
+ style: wrapperStyle,
650
+ onMouseEnter: () => setIsHovered(true),
651
+ onMouseLeave: () => setIsHovered(false),
652
+ children: /* @__PURE__ */ jsxs2("div", { style: cardStyle, children: [
653
+ /* @__PURE__ */ jsx2("div", { style: handleStyle, ...attributes, ...listeners, children: /* @__PURE__ */ jsxs2("svg", { width: "10", height: "16", viewBox: "0 0 10 16", fill: "currentColor", children: [
654
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "2", r: "1.5" }),
655
+ /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "2", r: "1.5" }),
656
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "8", r: "1.5" }),
657
+ /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "8", r: "1.5" }),
658
+ /* @__PURE__ */ jsx2("circle", { cx: "3", cy: "14", r: "1.5" }),
659
+ /* @__PURE__ */ jsx2("circle", { cx: "7", cy: "14", r: "1.5" })
660
+ ] }) }),
661
+ /* @__PURE__ */ jsxs2("div", { style: styles2.content, children: [
662
+ /* @__PURE__ */ jsxs2("div", { style: styles2.header, children: [
663
+ /* @__PURE__ */ jsx2(
664
+ motion2.span,
665
+ {
666
+ style: styles2.order,
667
+ initial: reducedMotion ? {} : { scale: 1.2 },
668
+ animate: { scale: 1 },
669
+ transition: reducedMotion ? { duration: 0 } : springs.bouncy,
670
+ children: index + 1
671
+ },
672
+ `order-${index}`
673
+ ),
674
+ /* @__PURE__ */ jsxs2("span", { style: styles2.tagBadge, children: [
675
+ "<",
676
+ step.elementTag,
677
+ ">"
678
+ ] }),
679
+ step.elementText && /* @__PURE__ */ jsx2("span", { style: styles2.text, children: step.elementText })
680
+ ] }),
681
+ /* @__PURE__ */ jsx2("div", { style: styles2.selector, children: step.selector }),
682
+ step.source && /* @__PURE__ */ jsxs2("div", { style: styles2.sourceRow, children: [
683
+ /* @__PURE__ */ jsx2(
586
684
  "svg",
587
685
  {
588
686
  width: "10",
589
687
  height: "10",
590
688
  viewBox: "0 0 16 16",
591
- fill: "currentColor",
592
- children: [
593
- /* @__PURE__ */ jsx2("path", { d: "M10 2H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zM4 1h6a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3z" }),
594
- /* @__PURE__ */ jsx2("path", { d: "M14 5a1 1 0 0 1 1 1v8a2 2 0 0 1-2 2H6a1 1 0 0 1 0-2h7V6a1 1 0 0 1 1-1z" })
595
- ]
689
+ fill: "hsl(142 71% 55%)",
690
+ children: /* @__PURE__ */ jsx2("path", { d: "M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z" })
691
+ }
692
+ ),
693
+ /* @__PURE__ */ jsx2(
694
+ "a",
695
+ {
696
+ href: getVSCodeLink({ source: step.source }),
697
+ style: styles2.sourceLink,
698
+ title: "Open in VS Code",
699
+ children: formatSourcePath({ source: step.source })
700
+ }
701
+ ),
702
+ /* @__PURE__ */ jsx2(
703
+ "button",
704
+ {
705
+ type: "button",
706
+ style: styles2.copyButton,
707
+ onClick: handleCopySource,
708
+ title: "Copy path",
709
+ children: /* @__PURE__ */ jsxs2(
710
+ "svg",
711
+ {
712
+ width: "10",
713
+ height: "10",
714
+ viewBox: "0 0 16 16",
715
+ fill: "currentColor",
716
+ children: [
717
+ /* @__PURE__ */ jsx2("path", { d: "M10 2H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zM4 1h6a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3z" }),
718
+ /* @__PURE__ */ jsx2("path", { d: "M14 5a1 1 0 0 1 1 1v8a2 2 0 0 1-2 2H6a1 1 0 0 1 0-2h7V6a1 1 0 0 1 1-1z" })
719
+ ]
720
+ }
721
+ )
596
722
  }
597
723
  )
724
+ ] })
725
+ ] }),
726
+ /* @__PURE__ */ jsx2(
727
+ motion2.button,
728
+ {
729
+ type: "button",
730
+ style: styles2.deleteButton,
731
+ onClick: onDelete,
732
+ title: "Delete step",
733
+ whileHover: reducedMotion ? {} : { scale: 1.1, color: "hsl(0 70% 60%)" },
734
+ whileTap: reducedMotion ? {} : { scale: 0.9 },
735
+ children: /* @__PURE__ */ jsx2("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: "M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" }) })
598
736
  }
599
737
  )
600
738
  ] })
601
- ] }),
602
- /* @__PURE__ */ jsx2(
603
- "button",
604
- {
605
- type: "button",
606
- style: styles2.deleteButton,
607
- onClick: onDelete,
608
- title: "Delete step",
609
- children: /* @__PURE__ */ jsx2("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: "M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" }) })
610
- }
611
- )
612
- ] }) });
739
+ }
740
+ );
613
741
  }
614
742
  function StepItemDragPreview(props) {
615
743
  const { step, index } = props;
@@ -662,8 +790,8 @@ function StepItemDragPreview(props) {
662
790
  }
663
791
 
664
792
  // src/devtools/components/Toolbar.tsx
665
- import { useState } from "react";
666
- import { motion as motion2 } from "motion/react";
793
+ import { useState as useState4 } from "react";
794
+ import { motion as motion3, AnimatePresence as AnimatePresence2 } from "motion/react";
667
795
  import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
668
796
  var styles3 = {
669
797
  toolbar: {
@@ -698,7 +826,8 @@ var styles3 = {
698
826
  backgroundColor: "rgba(59, 130, 246, 0.15)",
699
827
  borderColor: "rgba(59, 130, 246, 0.4)",
700
828
  color: "#60a5fa",
701
- boxShadow: "0 0 0 2px rgba(59, 130, 246, 0.1)"
829
+ boxShadow: "0 0 0 2px rgba(59, 130, 246, 0.1), 0 0 12px rgba(59, 130, 246, 0.2)",
830
+ animation: "grabPulse 2s ease-in-out infinite"
702
831
  },
703
832
  actionRow: {
704
833
  display: "flex",
@@ -755,11 +884,18 @@ var styles3 = {
755
884
  fontWeight: 600,
756
885
  borderRadius: 4,
757
886
  boxShadow: "0 2px 8px rgba(0, 0, 0, 0.3)"
758
- }
887
+ },
888
+ pulseKeyframes: `
889
+ @keyframes grabPulse {
890
+ 0%, 100% { box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1), 0 0 12px rgba(59, 130, 246, 0.2); }
891
+ 50% { box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15), 0 0 20px rgba(59, 130, 246, 0.3); }
892
+ }
893
+ `
759
894
  };
760
895
  function Toolbar(props) {
761
896
  const { mode, stepCount, onToggleGrab, onExport, onCopyForAI, onReset } = props;
762
- const [copied, setCopied] = useState(false);
897
+ const [copied, setCopied] = useState4(false);
898
+ const reducedMotion = useReducedMotion();
763
899
  const isGrabbing = mode === "grabbing";
764
900
  const hasSteps = stepCount > 0;
765
901
  const handleCopy = async () => {
@@ -785,14 +921,15 @@ function Toolbar(props) {
785
921
  ...hasSteps && styles3.actionButtonDanger
786
922
  };
787
923
  return /* @__PURE__ */ jsxs3("div", { style: styles3.toolbar, children: [
924
+ /* @__PURE__ */ jsx3("style", { children: styles3.pulseKeyframes }),
788
925
  /* @__PURE__ */ jsx3("div", { style: styles3.grabRow, children: /* @__PURE__ */ jsx3(
789
- motion2.button,
926
+ motion3.button,
790
927
  {
791
928
  type: "button",
792
929
  style: grabButtonStyle,
793
930
  onClick: onToggleGrab,
794
- whileHover: { scale: 1.01 },
795
- whileTap: { scale: 0.98 },
931
+ whileHover: reducedMotion ? {} : { scale: 1.01 },
932
+ whileTap: reducedMotion ? {} : { scale: 0.98 },
796
933
  children: isGrabbing ? /* @__PURE__ */ jsxs3(Fragment, { children: [
797
934
  /* @__PURE__ */ jsxs3(
798
935
  "svg",
@@ -876,14 +1013,14 @@ function Toolbar(props) {
876
1013
  ) }),
877
1014
  /* @__PURE__ */ jsxs3("div", { style: styles3.actionRow, children: [
878
1015
  /* @__PURE__ */ jsxs3(
879
- motion2.button,
1016
+ motion3.button,
880
1017
  {
881
1018
  type: "button",
882
1019
  style: exportButtonStyle,
883
1020
  onClick: onExport,
884
1021
  disabled: !hasSteps,
885
- whileHover: hasSteps ? { scale: 1.02 } : {},
886
- whileTap: hasSteps ? { scale: 0.98 } : {},
1022
+ whileHover: hasSteps && !reducedMotion ? { scale: 1.02 } : {},
1023
+ whileTap: hasSteps && !reducedMotion ? { scale: 0.98 } : {},
887
1024
  title: "Download JSON file",
888
1025
  children: [
889
1026
  /* @__PURE__ */ jsxs3("svg", { width: "11", height: "11", viewBox: "0 0 16 16", fill: "currentColor", children: [
@@ -895,14 +1032,14 @@ function Toolbar(props) {
895
1032
  }
896
1033
  ),
897
1034
  /* @__PURE__ */ jsxs3(
898
- motion2.button,
1035
+ motion3.button,
899
1036
  {
900
1037
  type: "button",
901
1038
  style: copyButtonStyle,
902
1039
  onClick: handleCopy,
903
1040
  disabled: !hasSteps,
904
- whileHover: hasSteps ? { scale: 1.02 } : {},
905
- whileTap: hasSteps ? { scale: 0.98 } : {},
1041
+ whileHover: hasSteps && !reducedMotion ? { scale: 1.02 } : {},
1042
+ whileTap: hasSteps && !reducedMotion ? { scale: 0.98 } : {},
906
1043
  title: "Copy JSON to clipboard",
907
1044
  children: [
908
1045
  /* @__PURE__ */ jsxs3("svg", { width: "11", height: "11", viewBox: "0 0 16 16", fill: "currentColor", children: [
@@ -910,28 +1047,29 @@ function Toolbar(props) {
910
1047
  /* @__PURE__ */ jsx3("path", { d: "M14 5a1 1 0 0 1 1 1v8a2 2 0 0 1-2 2H6a1 1 0 0 1 0-2h7V6a1 1 0 0 1 1-1z" })
911
1048
  ] }),
912
1049
  "Copy",
913
- copied && /* @__PURE__ */ jsx3(
914
- motion2.span,
1050
+ /* @__PURE__ */ jsx3(AnimatePresence2, { children: copied && /* @__PURE__ */ jsx3(
1051
+ motion3.span,
915
1052
  {
916
1053
  style: styles3.copiedBadge,
917
- initial: { opacity: 0, scale: 0.8, y: 4 },
1054
+ initial: reducedMotion ? {} : { opacity: 0, scale: 0.5, y: 4 },
918
1055
  animate: { opacity: 1, scale: 1, y: 0 },
919
- exit: { opacity: 0, scale: 0.8 },
1056
+ exit: reducedMotion ? {} : { opacity: 0, scale: 0.5, y: 4 },
1057
+ transition: reducedMotion ? { duration: 0 } : springs.bouncy,
920
1058
  children: "Copied!"
921
1059
  }
922
- )
1060
+ ) })
923
1061
  ]
924
1062
  }
925
1063
  ),
926
1064
  /* @__PURE__ */ jsxs3(
927
- motion2.button,
1065
+ motion3.button,
928
1066
  {
929
1067
  type: "button",
930
1068
  style: resetButtonStyle,
931
1069
  onClick: onReset,
932
1070
  disabled: !hasSteps,
933
- whileHover: hasSteps ? { scale: 1.02 } : {},
934
- whileTap: hasSteps ? { scale: 0.98 } : {},
1071
+ whileHover: hasSteps && !reducedMotion ? { scale: 1.02 } : {},
1072
+ whileTap: hasSteps && !reducedMotion ? { scale: 0.98 } : {},
935
1073
  title: "Clear all steps",
936
1074
  children: [
937
1075
  /* @__PURE__ */ jsxs3("svg", { width: "11", height: "11", viewBox: "0 0 16 16", fill: "currentColor", children: [
@@ -1012,7 +1150,8 @@ function StepList(props) {
1012
1150
  onClearAll,
1013
1151
  onExport
1014
1152
  } = props;
1015
- const [activeId, setActiveId] = useState2(null);
1153
+ const [activeId, setActiveId] = useState5(null);
1154
+ const reducedMotion = useReducedMotion();
1016
1155
  const activeStep = activeId ? steps.find((s) => s.id === activeId) : null;
1017
1156
  const activeIndex = activeId ? steps.findIndex((s) => s.id === activeId) : -1;
1018
1157
  const sensors = useSensors(
@@ -1079,26 +1218,37 @@ function StepList(props) {
1079
1218
  onReset: handleReset
1080
1219
  }
1081
1220
  ),
1082
- /* @__PURE__ */ jsx4("div", { style: styles4.scrollArea, children: steps.length === 0 ? /* @__PURE__ */ jsxs4("div", { style: styles4.empty, children: [
1083
- /* @__PURE__ */ jsx4("div", { style: styles4.emptyIcon, children: /* @__PURE__ */ jsx4(
1084
- "svg",
1085
- {
1086
- width: "20",
1087
- height: "20",
1088
- viewBox: "0 0 16 16",
1089
- fill: "hsl(215 20% 45%)",
1090
- children: /* @__PURE__ */ jsx4("path", { d: "M14 0a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12zM5.904 10.803L10 6.707v2.768a.5.5 0 0 0 1 0V5.5a.5.5 0 0 0-.5-.5H6.525a.5.5 0 1 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 .707.707z" })
1091
- }
1092
- ) }),
1093
- /* @__PURE__ */ jsxs4("div", { style: styles4.emptyText, children: [
1094
- /* @__PURE__ */ jsx4("div", { children: "No steps captured yet." }),
1095
- /* @__PURE__ */ jsxs4("div", { style: { marginTop: 6 }, children: [
1096
- "Press ",
1097
- /* @__PURE__ */ jsx4("span", { style: styles4.kbd, children: "Ctrl+Shift+G" }),
1098
- " to grab"
1099
- ] })
1100
- ] })
1101
- ] }) : /* @__PURE__ */ jsxs4(
1221
+ /* @__PURE__ */ jsx4("div", { style: styles4.scrollArea, children: /* @__PURE__ */ jsx4(AnimatePresence3, { mode: "wait", children: steps.length === 0 ? /* @__PURE__ */ jsxs4(
1222
+ motion4.div,
1223
+ {
1224
+ style: styles4.empty,
1225
+ initial: reducedMotion ? {} : { opacity: 0 },
1226
+ animate: { opacity: 1 },
1227
+ exit: reducedMotion ? {} : { opacity: 0 },
1228
+ transition: { duration: 0.2 },
1229
+ children: [
1230
+ /* @__PURE__ */ jsx4("div", { style: styles4.emptyIcon, children: /* @__PURE__ */ jsx4(
1231
+ "svg",
1232
+ {
1233
+ width: "20",
1234
+ height: "20",
1235
+ viewBox: "0 0 16 16",
1236
+ fill: "hsl(215 20% 45%)",
1237
+ children: /* @__PURE__ */ jsx4("path", { d: "M14 0a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12zM5.904 10.803L10 6.707v2.768a.5.5 0 0 0 1 0V5.5a.5.5 0 0 0-.5-.5H6.525a.5.5 0 1 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 .707.707z" })
1238
+ }
1239
+ ) }),
1240
+ /* @__PURE__ */ jsxs4("div", { style: styles4.emptyText, children: [
1241
+ /* @__PURE__ */ jsx4("div", { children: "No steps captured yet." }),
1242
+ /* @__PURE__ */ jsxs4("div", { style: { marginTop: 6 }, children: [
1243
+ "Press ",
1244
+ /* @__PURE__ */ jsx4("span", { style: styles4.kbd, children: "Ctrl+Shift+G" }),
1245
+ " to grab"
1246
+ ] })
1247
+ ] })
1248
+ ]
1249
+ },
1250
+ "empty-state"
1251
+ ) : /* @__PURE__ */ jsxs4(
1102
1252
  DndContext,
1103
1253
  {
1104
1254
  sensors,
@@ -1112,34 +1262,56 @@ function StepList(props) {
1112
1262
  {
1113
1263
  items: steps.map((s) => s.id),
1114
1264
  strategy: verticalListSortingStrategy,
1115
- children: /* @__PURE__ */ jsx4("div", { style: styles4.stepList, children: steps.map((step, index) => /* @__PURE__ */ jsx4(
1116
- SortableStepItem,
1265
+ children: /* @__PURE__ */ jsx4(
1266
+ motion4.div,
1117
1267
  {
1118
- step,
1119
- index,
1120
- onDelete: () => onDeleteStep({ id: step.id }),
1121
- isDragActive: activeId !== null,
1122
- isBeingDragged: step.id === activeId
1268
+ style: styles4.stepList,
1269
+ variants: reducedMotion ? void 0 : listContainerVariants,
1270
+ initial: "hidden",
1271
+ animate: "visible",
1272
+ children: /* @__PURE__ */ jsx4(AnimatePresence3, { mode: "popLayout", children: steps.map((step, index) => /* @__PURE__ */ jsx4(
1273
+ motion4.div,
1274
+ {
1275
+ variants: reducedMotion ? void 0 : listItemVariants,
1276
+ initial: "hidden",
1277
+ animate: "visible",
1278
+ exit: "exit",
1279
+ children: /* @__PURE__ */ jsx4(
1280
+ SortableStepItem,
1281
+ {
1282
+ step,
1283
+ index,
1284
+ onDelete: () => onDeleteStep({ id: step.id }),
1285
+ isDragActive: activeId !== null,
1286
+ isBeingDragged: step.id === activeId
1287
+ }
1288
+ )
1289
+ },
1290
+ step.id
1291
+ )) })
1123
1292
  },
1124
- step.id
1125
- )) })
1293
+ "step-list"
1294
+ )
1126
1295
  }
1127
1296
  ),
1128
1297
  /* @__PURE__ */ jsx4(DragOverlay, { dropAnimation: null, children: activeStep && /* @__PURE__ */ jsx4(StepItemDragPreview, { step: activeStep, index: activeIndex }) })
1129
1298
  ]
1130
1299
  }
1131
- ) })
1300
+ ) }) })
1132
1301
  ] });
1133
1302
  }
1134
1303
 
1135
1304
  // src/devtools/components/TabNav.tsx
1305
+ import { useEffect as useEffect3, useRef } from "react";
1306
+ import { motion as motion5, AnimatePresence as AnimatePresence4 } from "motion/react";
1136
1307
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1137
1308
  var styles5 = {
1138
1309
  container: {
1139
1310
  display: "flex",
1140
1311
  gap: 2,
1141
1312
  padding: "8px 10px 0",
1142
- borderBottom: "1px solid hsl(215 20% 20%)"
1313
+ borderBottom: "1px solid hsl(215 20% 20%)",
1314
+ position: "relative"
1143
1315
  },
1144
1316
  tab: {
1145
1317
  flex: 1,
@@ -1156,13 +1328,21 @@ var styles5 = {
1156
1328
  fontWeight: 500,
1157
1329
  fontFamily: "inherit",
1158
1330
  cursor: "pointer",
1159
- transition: "all 0.15s ease",
1331
+ transition: "color 0.15s ease",
1160
1332
  outline: "none",
1161
- marginBottom: -1
1333
+ marginBottom: -1,
1334
+ position: "relative",
1335
+ zIndex: 1
1162
1336
  },
1163
1337
  tabActive: {
1164
- color: "hsl(217 91% 70%)",
1165
- borderBottomColor: "hsl(217 91% 60%)"
1338
+ color: "hsl(217 91% 70%)"
1339
+ },
1340
+ indicator: {
1341
+ position: "absolute",
1342
+ bottom: -1,
1343
+ height: 2,
1344
+ backgroundColor: "hsl(217 91% 60%)",
1345
+ borderRadius: 1
1166
1346
  },
1167
1347
  badge: {
1168
1348
  display: "inline-flex",
@@ -1184,6 +1364,17 @@ var styles5 = {
1184
1364
  };
1185
1365
  function TabNav(props) {
1186
1366
  const { activeTab, onTabChange, stepCount, flowCount } = props;
1367
+ const reducedMotion = useReducedMotion();
1368
+ const prevStepCount = useRef(stepCount);
1369
+ const prevFlowCount = useRef(flowCount);
1370
+ const stepCountChanged = stepCount !== prevStepCount.current;
1371
+ const flowCountChanged = flowCount !== prevFlowCount.current;
1372
+ useEffect3(() => {
1373
+ prevStepCount.current = stepCount;
1374
+ }, [stepCount]);
1375
+ useEffect3(() => {
1376
+ prevFlowCount.current = flowCount;
1377
+ }, [flowCount]);
1187
1378
  const stepsTabStyle = {
1188
1379
  ...styles5.tab,
1189
1380
  ...activeTab === "steps" && styles5.tabActive
@@ -1210,7 +1401,18 @@ function TabNav(props) {
1210
1401
  children: [
1211
1402
  /* @__PURE__ */ jsx5("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx5("path", { d: "M14 0a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12zM5.904 10.803L10 6.707v2.768a.5.5 0 0 0 1 0V5.5a.5.5 0 0 0-.5-.5H6.525a.5.5 0 1 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 .707.707z" }) }),
1212
1403
  "Steps",
1213
- stepCount > 0 && /* @__PURE__ */ jsx5("span", { style: stepsBadgeStyle, children: stepCount })
1404
+ /* @__PURE__ */ jsx5(AnimatePresence4, { mode: "popLayout", children: stepCount > 0 && /* @__PURE__ */ jsx5(
1405
+ motion5.span,
1406
+ {
1407
+ style: stepsBadgeStyle,
1408
+ initial: stepCountChanged && !reducedMotion ? { scale: 1.3 } : { scale: 1 },
1409
+ animate: { scale: 1 },
1410
+ exit: { scale: 0.8, opacity: 0 },
1411
+ transition: reducedMotion ? { duration: 0 } : springs.bouncy,
1412
+ children: stepCount
1413
+ },
1414
+ `step-badge-${stepCount}`
1415
+ ) })
1214
1416
  ]
1215
1417
  }
1216
1418
  ),
@@ -1223,28 +1425,83 @@ function TabNav(props) {
1223
1425
  children: [
1224
1426
  /* @__PURE__ */ jsx5("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx5("path", { d: "M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H14a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 2 7h5.5V6A1.5 1.5 0 0 1 6 4.5v-1zm-3 8A1.5 1.5 0 0 1 4.5 10h1A1.5 1.5 0 0 1 7 11.5v1A1.5 1.5 0 0 1 5.5 14h-1A1.5 1.5 0 0 1 3 12.5v-1zm6 0a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1A1.5 1.5 0 0 1 9 12.5v-1z" }) }),
1225
1427
  "Flows",
1226
- flowCount > 0 && /* @__PURE__ */ jsx5("span", { style: flowsBadgeStyle, children: flowCount })
1428
+ /* @__PURE__ */ jsx5(AnimatePresence4, { mode: "popLayout", children: flowCount > 0 && /* @__PURE__ */ jsx5(
1429
+ motion5.span,
1430
+ {
1431
+ style: flowsBadgeStyle,
1432
+ initial: flowCountChanged && !reducedMotion ? { scale: 1.3 } : { scale: 1 },
1433
+ animate: { scale: 1 },
1434
+ exit: { scale: 0.8, opacity: 0 },
1435
+ transition: reducedMotion ? { duration: 0 } : springs.bouncy,
1436
+ children: flowCount
1437
+ },
1438
+ `flow-badge-${flowCount}`
1439
+ ) })
1227
1440
  ]
1228
1441
  }
1442
+ ),
1443
+ /* @__PURE__ */ jsx5(
1444
+ "div",
1445
+ {
1446
+ style: {
1447
+ ...styles5.indicator,
1448
+ left: activeTab === "steps" ? 10 : "50%",
1449
+ width: "calc(50% - 11px)",
1450
+ transition: reducedMotion ? "none" : "left 0.2s cubic-bezier(0.16, 1, 0.3, 1)"
1451
+ }
1452
+ }
1229
1453
  )
1230
1454
  ] });
1231
1455
  }
1232
1456
 
1233
1457
  // src/devtools/components/FlowsTab.tsx
1234
- import { useCallback as useCallback4, useState as useState6 } from "react";
1235
- import { motion as motion5 } from "motion/react";
1458
+ import { useCallback as useCallback4, useState as useState9 } from "react";
1459
+ import { motion as motion8 } from "motion/react";
1460
+
1461
+ // src/devtools/hooks/useFlowsData.ts
1462
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState6, useSyncExternalStore } from "react";
1463
+
1464
+ // src/devtools/globalBridge.ts
1465
+ var BRIDGE_KEY = "__FLOWSTERIX_DEVTOOLS_BRIDGE__";
1466
+ function getBridge() {
1467
+ if (typeof window === "undefined") {
1468
+ return { value: null, listeners: /* @__PURE__ */ new Set() };
1469
+ }
1470
+ const w = window;
1471
+ if (!w[BRIDGE_KEY]) {
1472
+ w[BRIDGE_KEY] = { value: null, listeners: /* @__PURE__ */ new Set() };
1473
+ }
1474
+ return w[BRIDGE_KEY];
1475
+ }
1476
+ function getDevToolsBridge() {
1477
+ return getBridge().value;
1478
+ }
1479
+ function subscribeDevToolsBridge(listener) {
1480
+ const bridge = getBridge();
1481
+ bridge.listeners.add(listener);
1482
+ return () => {
1483
+ bridge.listeners.delete(listener);
1484
+ };
1485
+ }
1236
1486
 
1237
1487
  // src/devtools/hooks/useFlowsData.ts
1238
- import { useCallback as useCallback2, useEffect, useState as useState3 } from "react";
1488
+ function useBridge() {
1489
+ return useSyncExternalStore(
1490
+ subscribeDevToolsBridge,
1491
+ getDevToolsBridge,
1492
+ () => null
1493
+ // Server snapshot
1494
+ );
1495
+ }
1239
1496
  function useFlowsData() {
1240
- const devtools = useDevToolsContext();
1241
- const [flowsData, setFlowsData] = useState3([]);
1497
+ const bridge = useBridge();
1498
+ const [flowsData, setFlowsData] = useState6([]);
1242
1499
  const loadFlowStates = useCallback2(async () => {
1243
- if (!devtools) {
1500
+ if (!bridge) {
1244
1501
  setFlowsData([]);
1245
1502
  return;
1246
1503
  }
1247
- const { flows, activeFlowId, state: activeState, getFlowState } = devtools;
1504
+ const { flows, activeFlowId, state: activeState, getFlowState } = bridge;
1248
1505
  const flowDataPromises = [];
1249
1506
  for (const [flowId, definition] of flows) {
1250
1507
  const isActive = flowId === activeFlowId;
@@ -1262,30 +1519,28 @@ function useFlowsData() {
1262
1519
  }
1263
1520
  const results = await Promise.all(flowDataPromises);
1264
1521
  setFlowsData(results);
1265
- }, [devtools]);
1266
- useEffect(() => {
1522
+ }, [bridge]);
1523
+ useEffect4(() => {
1267
1524
  void loadFlowStates();
1268
1525
  }, [loadFlowStates]);
1269
- useEffect(() => {
1270
- if (!devtools?.activeFlowId || !devtools?.state) return;
1271
- void loadFlowStates();
1272
- }, [devtools?.activeFlowId, devtools?.state, loadFlowStates]);
1273
1526
  const deleteFlow = useCallback2(
1274
1527
  async (flowId) => {
1275
- if (!devtools) return;
1276
- devtools.cancelFlow(flowId);
1277
- await devtools.deleteFlowStorage(flowId);
1528
+ if (!bridge) return;
1529
+ if (bridge.activeFlowId === flowId) {
1530
+ bridge.cancel();
1531
+ }
1532
+ await bridge.deleteFlowStorage(flowId);
1278
1533
  await loadFlowStates();
1279
1534
  },
1280
- [devtools, loadFlowStates]
1535
+ [bridge, loadFlowStates]
1281
1536
  );
1282
1537
  const updateFlow = useCallback2(
1283
- async (flowId, state) => {
1284
- if (!devtools) return;
1285
- await devtools.updateFlowStorage(flowId, state);
1538
+ async (flowId, newState) => {
1539
+ if (!bridge) return;
1540
+ await bridge.updateFlowStorage(flowId, newState);
1286
1541
  await loadFlowStates();
1287
1542
  },
1288
- [devtools, loadFlowStates]
1543
+ [bridge, loadFlowStates]
1289
1544
  );
1290
1545
  return {
1291
1546
  flows: flowsData,
@@ -1296,8 +1551,8 @@ function useFlowsData() {
1296
1551
  }
1297
1552
 
1298
1553
  // src/devtools/components/FlowItem.tsx
1299
- import { useState as useState4 } from "react";
1300
- import { motion as motion3 } from "motion/react";
1554
+ import { useState as useState7 } from "react";
1555
+ import { motion as motion6, AnimatePresence as AnimatePresence5 } from "motion/react";
1301
1556
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1302
1557
  var styles6 = {
1303
1558
  card: {
@@ -1309,7 +1564,12 @@ var styles6 = {
1309
1564
  borderRadius: 8,
1310
1565
  border: "1px solid hsl(215 20% 22%)",
1311
1566
  fontSize: 12,
1312
- fontFamily: "inherit"
1567
+ fontFamily: "inherit",
1568
+ transition: "border-color 0.15s ease, box-shadow 0.15s ease"
1569
+ },
1570
+ cardHover: {
1571
+ borderColor: "hsl(215 20% 28%)",
1572
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)"
1313
1573
  },
1314
1574
  cardActive: {
1315
1575
  borderColor: "hsl(217 91% 55% / 0.5)",
@@ -1429,7 +1689,9 @@ var statusStyles = {
1429
1689
  function FlowItem(props) {
1430
1690
  const { flow, onEdit, onDelete } = props;
1431
1691
  const { flowId, definition, state, isActive } = flow;
1432
- const [confirmDelete, setConfirmDelete] = useState4(false);
1692
+ const [confirmDelete, setConfirmDelete] = useState7(false);
1693
+ const [isHovered, setIsHovered] = useState7(false);
1694
+ const reducedMotion = useReducedMotion();
1433
1695
  const handleDelete = () => {
1434
1696
  if (confirmDelete) {
1435
1697
  onDelete();
@@ -1441,6 +1703,7 @@ function FlowItem(props) {
1441
1703
  };
1442
1704
  const cardStyle = {
1443
1705
  ...styles6.card,
1706
+ ...isHovered && styles6.cardHover,
1444
1707
  ...isActive && styles6.cardActive
1445
1708
  };
1446
1709
  const statusBadgeStyle = {
@@ -1452,84 +1715,117 @@ function FlowItem(props) {
1452
1715
  ...confirmDelete && styles6.actionButtonDanger
1453
1716
  };
1454
1717
  const stepInfo = state ? `Step ${state.stepIndex + 1}/${definition.steps.length}` : null;
1455
- return /* @__PURE__ */ jsxs6("div", { style: cardStyle, children: [
1456
- /* @__PURE__ */ jsxs6("div", { style: styles6.header, children: [
1457
- /* @__PURE__ */ jsxs6("div", { style: styles6.titleGroup, children: [
1458
- /* @__PURE__ */ jsx6("span", { style: styles6.flowId, children: flowId }),
1459
- isActive && /* @__PURE__ */ jsx6("span", { style: { ...styles6.statusBadge, ...styles6.activeBadge }, children: "Active" })
1460
- ] }),
1461
- /* @__PURE__ */ jsx6("span", { style: statusBadgeStyle, children: state?.status ?? "no state" })
1462
- ] }),
1463
- state ? /* @__PURE__ */ jsxs6("div", { style: styles6.infoRow, children: [
1464
- stepInfo && /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1465
- /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "Step:" }),
1466
- /* @__PURE__ */ jsx6("span", { style: styles6.value, children: stepInfo })
1467
- ] }),
1468
- /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1469
- /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "Version:" }),
1470
- /* @__PURE__ */ jsx6("span", { style: styles6.value, children: state.version })
1471
- ] }),
1472
- state.stepId && /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1473
- /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "ID:" }),
1474
- /* @__PURE__ */ jsx6("span", { style: styles6.value, children: state.stepId })
1475
- ] })
1476
- ] }) : /* @__PURE__ */ jsx6("div", { style: styles6.noState, children: "No stored state" }),
1477
- /* @__PURE__ */ jsxs6("div", { style: styles6.actions, children: [
1478
- /* @__PURE__ */ jsxs6(
1479
- motion3.button,
1480
- {
1481
- type: "button",
1482
- style: styles6.actionButton,
1483
- onClick: onEdit,
1484
- disabled: !state,
1485
- whileHover: state ? { scale: 1.02 } : {},
1486
- whileTap: state ? { scale: 0.98 } : {},
1487
- title: state ? "Edit flow state" : "No state to edit",
1488
- children: [
1489
- /* @__PURE__ */ jsx6("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx6("path", { d: "M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5L13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175l-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" }) }),
1490
- "Edit"
1491
- ]
1492
- }
1493
- ),
1494
- /* @__PURE__ */ jsxs6(
1495
- motion3.button,
1496
- {
1497
- type: "button",
1498
- style: deleteButtonStyle,
1499
- onClick: handleDelete,
1500
- disabled: !state,
1501
- whileHover: state ? { scale: 1.02 } : {},
1502
- whileTap: state ? { scale: 0.98 } : {},
1503
- title: confirmDelete ? "Click again to confirm deletion" : state ? "Delete flow state" : "No state to delete",
1504
- children: [
1505
- /* @__PURE__ */ jsxs6("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: [
1506
- /* @__PURE__ */ jsx6("path", { d: "M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z" }),
1507
- /* @__PURE__ */ jsx6(
1508
- "path",
1509
- {
1510
- fillRule: "evenodd",
1511
- d: "M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"
1512
- }
1513
- )
1514
- ] }),
1515
- confirmDelete ? "Confirm?" : "Delete"
1516
- ]
1517
- }
1518
- )
1519
- ] })
1520
- ] });
1718
+ const currentStatus = state?.status ?? "no state";
1719
+ return /* @__PURE__ */ jsxs6(
1720
+ "div",
1721
+ {
1722
+ style: cardStyle,
1723
+ onMouseEnter: () => setIsHovered(true),
1724
+ onMouseLeave: () => setIsHovered(false),
1725
+ children: [
1726
+ /* @__PURE__ */ jsxs6("div", { style: styles6.header, children: [
1727
+ /* @__PURE__ */ jsxs6("div", { style: styles6.titleGroup, children: [
1728
+ /* @__PURE__ */ jsx6("span", { style: styles6.flowId, children: flowId }),
1729
+ /* @__PURE__ */ jsx6(AnimatePresence5, { mode: "wait", children: isActive && /* @__PURE__ */ jsx6(
1730
+ motion6.span,
1731
+ {
1732
+ style: { ...styles6.statusBadge, ...styles6.activeBadge },
1733
+ initial: reducedMotion ? {} : { scale: 0.8, opacity: 0 },
1734
+ animate: { scale: 1, opacity: 1 },
1735
+ exit: reducedMotion ? {} : { scale: 0.8, opacity: 0 },
1736
+ transition: reducedMotion ? { duration: 0 } : springs.bouncy,
1737
+ children: "Active"
1738
+ },
1739
+ "active-badge"
1740
+ ) })
1741
+ ] }),
1742
+ /* @__PURE__ */ jsx6(AnimatePresence5, { mode: "wait", children: /* @__PURE__ */ jsx6(
1743
+ motion6.span,
1744
+ {
1745
+ style: statusBadgeStyle,
1746
+ initial: reducedMotion ? {} : { scale: 0.9, opacity: 0 },
1747
+ animate: { scale: 1, opacity: 1 },
1748
+ exit: reducedMotion ? {} : { scale: 0.9, opacity: 0 },
1749
+ transition: reducedMotion ? { duration: 0 } : { duration: 0.15 },
1750
+ children: currentStatus
1751
+ },
1752
+ currentStatus
1753
+ ) })
1754
+ ] }),
1755
+ state ? /* @__PURE__ */ jsxs6("div", { style: styles6.infoRow, children: [
1756
+ stepInfo && /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1757
+ /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "Step:" }),
1758
+ /* @__PURE__ */ jsx6("span", { style: styles6.value, children: stepInfo })
1759
+ ] }),
1760
+ /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1761
+ /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "Version:" }),
1762
+ /* @__PURE__ */ jsx6("span", { style: styles6.value, children: state.version })
1763
+ ] }),
1764
+ state.stepId && /* @__PURE__ */ jsxs6("div", { style: styles6.infoItem, children: [
1765
+ /* @__PURE__ */ jsx6("span", { style: styles6.label, children: "ID:" }),
1766
+ /* @__PURE__ */ jsx6("span", { style: styles6.value, children: state.stepId })
1767
+ ] })
1768
+ ] }) : /* @__PURE__ */ jsx6("div", { style: styles6.noState, children: "No stored state" }),
1769
+ /* @__PURE__ */ jsxs6("div", { style: styles6.actions, children: [
1770
+ /* @__PURE__ */ jsxs6(
1771
+ motion6.button,
1772
+ {
1773
+ type: "button",
1774
+ style: styles6.actionButton,
1775
+ onClick: onEdit,
1776
+ disabled: !state,
1777
+ whileHover: state && !reducedMotion ? { scale: 1.02 } : {},
1778
+ whileTap: state && !reducedMotion ? { scale: 0.98 } : {},
1779
+ title: state ? "Edit flow state" : "No state to edit",
1780
+ children: [
1781
+ /* @__PURE__ */ jsx6("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx6("path", { d: "M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5L13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175l-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" }) }),
1782
+ "Edit"
1783
+ ]
1784
+ }
1785
+ ),
1786
+ /* @__PURE__ */ jsxs6(
1787
+ motion6.button,
1788
+ {
1789
+ type: "button",
1790
+ style: deleteButtonStyle,
1791
+ onClick: handleDelete,
1792
+ disabled: !state,
1793
+ whileHover: state && !reducedMotion ? { scale: 1.02 } : {},
1794
+ whileTap: state && !reducedMotion ? { scale: 0.98 } : {},
1795
+ title: confirmDelete ? "Click again to confirm deletion" : state ? "Delete flow state" : "No state to delete",
1796
+ children: [
1797
+ /* @__PURE__ */ jsxs6("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: [
1798
+ /* @__PURE__ */ jsx6("path", { d: "M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z" }),
1799
+ /* @__PURE__ */ jsx6(
1800
+ "path",
1801
+ {
1802
+ fillRule: "evenodd",
1803
+ d: "M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"
1804
+ }
1805
+ )
1806
+ ] }),
1807
+ confirmDelete ? "Confirm?" : "Delete"
1808
+ ]
1809
+ }
1810
+ )
1811
+ ] })
1812
+ ]
1813
+ }
1814
+ );
1521
1815
  }
1522
1816
 
1523
1817
  // src/devtools/components/FlowEditModal.tsx
1524
- import { useCallback as useCallback3, useEffect as useEffect2, useState as useState5 } from "react";
1818
+ import { useCallback as useCallback3, useEffect as useEffect5, useState as useState8 } from "react";
1525
1819
  import { createPortal as createPortal2 } from "react-dom";
1526
- import { AnimatePresence as AnimatePresence2, motion as motion4 } from "motion/react";
1820
+ import { AnimatePresence as AnimatePresence6, motion as motion7 } from "motion/react";
1527
1821
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1528
1822
  var styles7 = {
1529
1823
  overlay: {
1530
1824
  position: "fixed",
1531
1825
  inset: 0,
1532
1826
  backgroundColor: "rgba(0, 0, 0, 0.6)",
1827
+ backdropFilter: "blur(4px)",
1828
+ WebkitBackdropFilter: "blur(4px)",
1533
1829
  display: "flex",
1534
1830
  alignItems: "center",
1535
1831
  justifyContent: "center",
@@ -1592,7 +1888,8 @@ var styles7 = {
1592
1888
  fontFamily: "ui-monospace, monospace",
1593
1889
  resize: "vertical",
1594
1890
  outline: "none",
1595
- lineHeight: 1.5
1891
+ lineHeight: 1.5,
1892
+ transition: "border-color 0.15s ease"
1596
1893
  },
1597
1894
  textareaError: {
1598
1895
  borderColor: "hsl(0 70% 50%)"
@@ -1644,14 +1941,21 @@ var styles7 = {
1644
1941
  };
1645
1942
  function FlowEditModal(props) {
1646
1943
  const { isOpen, flowId, initialState, onClose, onSave, container } = props;
1647
- const [jsonValue, setJsonValue] = useState5("");
1648
- const [error, setError] = useState5(null);
1649
- useEffect2(() => {
1944
+ const [jsonValue, setJsonValue] = useState8("");
1945
+ const [error, setError] = useState8(null);
1946
+ const [shake, setShake] = useState8(false);
1947
+ const reducedMotion = useReducedMotion();
1948
+ useEffect5(() => {
1650
1949
  if (isOpen && initialState) {
1651
1950
  setJsonValue(JSON.stringify(initialState, null, 2));
1652
1951
  setError(null);
1653
1952
  }
1654
1953
  }, [isOpen, initialState]);
1954
+ const triggerShake = useCallback3(() => {
1955
+ if (reducedMotion) return;
1956
+ setShake(true);
1957
+ setTimeout(() => setShake(false), 400);
1958
+ }, [reducedMotion]);
1655
1959
  const handleSave = useCallback3(() => {
1656
1960
  try {
1657
1961
  const parsed = JSON.parse(jsonValue);
@@ -1668,8 +1972,9 @@ function FlowEditModal(props) {
1668
1972
  onClose();
1669
1973
  } catch (err) {
1670
1974
  setError(err instanceof Error ? err.message : "Invalid JSON");
1975
+ triggerShake();
1671
1976
  }
1672
- }, [jsonValue, onSave, onClose]);
1977
+ }, [jsonValue, onSave, onClose, triggerShake]);
1673
1978
  const handleKeyDown = useCallback3(
1674
1979
  (e) => {
1675
1980
  if (e.key === "Escape") {
@@ -1694,26 +1999,31 @@ function FlowEditModal(props) {
1694
1999
  ...error && styles7.buttonDisabled
1695
2000
  };
1696
2001
  return createPortal2(
1697
- /* @__PURE__ */ jsx7(AnimatePresence2, { children: isOpen && /* @__PURE__ */ jsx7(
1698
- motion4.div,
2002
+ /* @__PURE__ */ jsx7(AnimatePresence6, { children: isOpen && /* @__PURE__ */ jsx7(
2003
+ motion7.div,
1699
2004
  {
1700
2005
  style: styles7.overlay,
1701
- initial: { opacity: 0 },
2006
+ initial: reducedMotion ? {} : { opacity: 0 },
1702
2007
  animate: { opacity: 1 },
1703
- exit: { opacity: 0 },
1704
- transition: { duration: 0.15 },
2008
+ exit: reducedMotion ? {} : { opacity: 0 },
2009
+ transition: reducedMotion ? { duration: 0 } : { duration: 0.15 },
1705
2010
  onClick: (e) => {
1706
2011
  if (e.target === e.currentTarget) onClose();
1707
2012
  },
1708
2013
  onKeyDown: handleKeyDown,
1709
2014
  children: /* @__PURE__ */ jsxs7(
1710
- motion4.div,
2015
+ motion7.div,
1711
2016
  {
1712
2017
  style: styles7.modal,
1713
- initial: { opacity: 0, scale: 0.95, y: 10 },
1714
- animate: { opacity: 1, scale: 1, y: 0 },
1715
- exit: { opacity: 0, scale: 0.95, y: 10 },
1716
- transition: { duration: 0.15, ease: [0.16, 1, 0.3, 1] },
2018
+ initial: reducedMotion ? {} : { opacity: 0, scale: 0.95, y: 10 },
2019
+ animate: {
2020
+ opacity: 1,
2021
+ scale: 1,
2022
+ y: 0,
2023
+ x: shake ? [0, -8, 8, -6, 6, -4, 4, 0] : 0
2024
+ },
2025
+ exit: reducedMotion ? {} : { opacity: 0, scale: 0.95, y: 10 },
2026
+ transition: reducedMotion ? { duration: 0 } : springs.smooth,
1717
2027
  onClick: (e) => e.stopPropagation(),
1718
2028
  children: [
1719
2029
  /* @__PURE__ */ jsxs7("div", { style: styles7.header, children: [
@@ -1722,12 +2032,14 @@ function FlowEditModal(props) {
1722
2032
  flowId
1723
2033
  ] }),
1724
2034
  /* @__PURE__ */ jsx7(
1725
- "button",
2035
+ motion7.button,
1726
2036
  {
1727
2037
  type: "button",
1728
2038
  style: styles7.closeButton,
1729
2039
  onClick: onClose,
1730
2040
  title: "Close",
2041
+ whileHover: reducedMotion ? {} : { scale: 1.1 },
2042
+ whileTap: reducedMotion ? {} : { scale: 0.9 },
1731
2043
  children: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx7("path", { d: "M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" }) })
1732
2044
  }
1733
2045
  )
@@ -1746,27 +2058,39 @@ function FlowEditModal(props) {
1746
2058
  autoFocus: true
1747
2059
  }
1748
2060
  ),
1749
- error && /* @__PURE__ */ jsx7("div", { style: styles7.error, children: error })
2061
+ /* @__PURE__ */ jsx7(AnimatePresence6, { children: error && /* @__PURE__ */ jsx7(
2062
+ motion7.div,
2063
+ {
2064
+ style: styles7.error,
2065
+ initial: reducedMotion ? {} : { opacity: 0, y: -4 },
2066
+ animate: { opacity: 1, y: 0 },
2067
+ exit: reducedMotion ? {} : { opacity: 0, y: -4 },
2068
+ transition: { duration: 0.15 },
2069
+ children: error
2070
+ }
2071
+ ) })
1750
2072
  ] }),
1751
2073
  /* @__PURE__ */ jsxs7("div", { style: styles7.footer, children: [
1752
2074
  /* @__PURE__ */ jsx7(
1753
- "button",
2075
+ motion7.button,
1754
2076
  {
1755
2077
  type: "button",
1756
2078
  style: styles7.button,
1757
2079
  onClick: onClose,
2080
+ whileHover: reducedMotion ? {} : { scale: 1.02 },
2081
+ whileTap: reducedMotion ? {} : { scale: 0.98 },
1758
2082
  children: "Cancel"
1759
2083
  }
1760
2084
  ),
1761
2085
  /* @__PURE__ */ jsx7(
1762
- motion4.button,
2086
+ motion7.button,
1763
2087
  {
1764
2088
  type: "button",
1765
2089
  style: saveButtonStyle,
1766
2090
  onClick: handleSave,
1767
2091
  disabled: !!error,
1768
- whileHover: !error ? { scale: 1.02 } : {},
1769
- whileTap: !error ? { scale: 0.98 } : {},
2092
+ whileHover: !error && !reducedMotion ? { scale: 1.02 } : {},
2093
+ whileTap: !error && !reducedMotion ? { scale: 0.98 } : {},
1770
2094
  children: "Save"
1771
2095
  }
1772
2096
  )
@@ -1854,7 +2178,7 @@ var styles8 = {
1854
2178
  function FlowsTab(props) {
1855
2179
  const { container } = props;
1856
2180
  const { flows, refreshFlows, deleteFlow, updateFlow } = useFlowsData();
1857
- const [editModal, setEditModal] = useState6({
2181
+ const [editModal, setEditModal] = useState9({
1858
2182
  isOpen: false,
1859
2183
  flowId: "",
1860
2184
  state: null
@@ -1909,7 +2233,7 @@ function FlowsTab(props) {
1909
2233
  " registered"
1910
2234
  ] }),
1911
2235
  /* @__PURE__ */ jsxs8(
1912
- motion5.button,
2236
+ motion8.button,
1913
2237
  {
1914
2238
  type: "button",
1915
2239
  style: styles8.refreshButton,
@@ -1957,7 +2281,7 @@ function FlowsTab(props) {
1957
2281
  }
1958
2282
 
1959
2283
  // src/devtools/hooks/useGrabMode.ts
1960
- import { useCallback as useCallback6, useEffect as useEffect3, useState as useState7 } from "react";
2284
+ import { useCallback as useCallback6, useEffect as useEffect6, useState as useState10 } from "react";
1961
2285
 
1962
2286
  // src/devtools/hooks/useElementInfo.ts
1963
2287
  import { useCallback as useCallback5 } from "react";
@@ -2094,8 +2418,8 @@ function isDevToolsElement(element) {
2094
2418
  return false;
2095
2419
  }
2096
2420
  function useGrabMode() {
2097
- const [mode, setMode] = useState7("idle");
2098
- const [hoveredElement, setHoveredElement] = useState7(null);
2421
+ const [mode, setMode] = useState10("idle");
2422
+ const [hoveredElement, setHoveredElement] = useState10(null);
2099
2423
  const { getElementInfo } = useElementInfo();
2100
2424
  const startGrabbing = useCallback6(() => {
2101
2425
  setMode("grabbing");
@@ -2113,7 +2437,7 @@ function useGrabMode() {
2113
2437
  if (!hoveredElement) return null;
2114
2438
  return hoveredElement.info;
2115
2439
  }, [hoveredElement]);
2116
- useEffect3(() => {
2440
+ useEffect6(() => {
2117
2441
  if (mode !== "grabbing") return;
2118
2442
  const handleMouseMove = (e) => {
2119
2443
  const target = document.elementFromPoint(e.clientX, e.clientY);
@@ -2137,7 +2461,7 @@ function useGrabMode() {
2137
2461
  document.addEventListener("mousemove", handleMouseMove, { passive: true });
2138
2462
  return () => document.removeEventListener("mousemove", handleMouseMove);
2139
2463
  }, [mode, getElementInfo]);
2140
- useEffect3(() => {
2464
+ useEffect6(() => {
2141
2465
  const handleKeyDown = (e) => {
2142
2466
  if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === "g") {
2143
2467
  e.preventDefault();
@@ -2164,7 +2488,7 @@ function useGrabMode() {
2164
2488
  }
2165
2489
 
2166
2490
  // src/devtools/hooks/useStepStore.ts
2167
- import { useCallback as useCallback7, useEffect as useEffect4, useSyncExternalStore } from "react";
2491
+ import { useCallback as useCallback7, useEffect as useEffect7, useSyncExternalStore as useSyncExternalStore2 } from "react";
2168
2492
 
2169
2493
  // src/devtools/utils/storage.ts
2170
2494
  var STORAGE_KEY = "flowsterix-devtools-steps";
@@ -2226,15 +2550,15 @@ function generateId() {
2226
2550
  return `step-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
2227
2551
  }
2228
2552
  function useStepStore() {
2229
- const steps = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2230
- useEffect4(() => {
2553
+ const steps = useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot);
2554
+ useEffect7(() => {
2231
2555
  const saved = loadSteps();
2232
2556
  if (saved.length > 0) {
2233
2557
  store.steps = saved;
2234
2558
  notifyListeners();
2235
2559
  }
2236
2560
  }, []);
2237
- useEffect4(() => {
2561
+ useEffect7(() => {
2238
2562
  saveSteps(steps);
2239
2563
  }, [steps]);
2240
2564
  const addStep = useCallback7((params) => {
@@ -2421,10 +2745,10 @@ var styles9 = {
2421
2745
  };
2422
2746
  function DevToolsProvider(props) {
2423
2747
  const { children, enabled = true, defaultTab = "steps" } = props;
2424
- const [mounted, setMounted] = useState8(false);
2425
- const [shadowRoot, setShadowRoot] = useState8(null);
2426
- const [activeTab, setActiveTab] = useState8(defaultTab);
2427
- useEffect5(() => {
2748
+ const [mounted, setMounted] = useState11(false);
2749
+ const [shadowRoot, setShadowRoot] = useState11(null);
2750
+ const [activeTab, setActiveTab] = useState11(defaultTab);
2751
+ useEffect8(() => {
2428
2752
  setMounted(true);
2429
2753
  const host = document.createElement("div");
2430
2754
  host.setAttribute("data-devtools-host", "");
@@ -2455,10 +2779,10 @@ function DevToolsProvider(props) {
2455
2779
  exportSteps
2456
2780
  } = useStepStore();
2457
2781
  const { flows } = useFlowsData();
2458
- const [collapsed, setCollapsed] = useState8(false);
2459
- const [position, setPosition] = useState8({ x: 16, y: 16 });
2460
- const [isPanelDragging, setIsPanelDragging] = useState8(false);
2461
- const dragStartRef = { current: null };
2782
+ const [collapsed, setCollapsed] = useState11(false);
2783
+ const [position, setPosition] = useState11({ x: 16, y: 16 });
2784
+ const [isPanelDragging, setIsPanelDragging] = useState11(false);
2785
+ const dragStartRef = useRef2(null);
2462
2786
  const handleClick = useCallback8(
2463
2787
  (e) => {
2464
2788
  if (mode !== "grabbing") return;
@@ -2479,12 +2803,12 @@ function DevToolsProvider(props) {
2479
2803
  },
2480
2804
  [mode, selectCurrent, addStep]
2481
2805
  );
2482
- useEffect5(() => {
2806
+ useEffect8(() => {
2483
2807
  if (mode !== "grabbing") return;
2484
2808
  document.addEventListener("click", handleClick, { capture: true });
2485
2809
  return () => document.removeEventListener("click", handleClick, { capture: true });
2486
2810
  }, [mode, handleClick]);
2487
- useEffect5(() => {
2811
+ useEffect8(() => {
2488
2812
  if (mode !== "grabbing") return;
2489
2813
  const preventDefault = (e) => {
2490
2814
  const target = e.target;
@@ -2496,7 +2820,7 @@ function DevToolsProvider(props) {
2496
2820
  document.removeEventListener("submit", preventDefault, { capture: true });
2497
2821
  };
2498
2822
  }, [mode]);
2499
- useEffect5(() => {
2823
+ useEffect8(() => {
2500
2824
  const handleKeyDown = (e) => {
2501
2825
  if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === "m") {
2502
2826
  e.preventDefault();
@@ -2564,7 +2888,7 @@ function DevToolsProvider(props) {
2564
2888
  ),
2565
2889
  createPortal3(
2566
2890
  /* @__PURE__ */ jsxs9(
2567
- motion6.div,
2891
+ motion9.div,
2568
2892
  {
2569
2893
  style: panelStyle,
2570
2894
  initial: { opacity: 0, x: 20, scale: 0.95 },
@@ -2614,14 +2938,14 @@ function DevToolsProvider(props) {
2614
2938
  ]
2615
2939
  }
2616
2940
  ),
2617
- /* @__PURE__ */ jsx9(AnimatePresence3, { initial: false, children: !collapsed && /* @__PURE__ */ jsxs9(
2618
- motion6.div,
2941
+ /* @__PURE__ */ jsx9(AnimatePresence7, { initial: false, children: !collapsed && /* @__PURE__ */ jsxs9(
2942
+ motion9.div,
2619
2943
  {
2620
- style: styles9.body,
2944
+ style: { ...styles9.body, overflow: "hidden" },
2621
2945
  initial: { height: 0, opacity: 0 },
2622
2946
  animate: { height: "auto", opacity: 1 },
2623
2947
  exit: { height: 0, opacity: 0 },
2624
- transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
2948
+ transition: springs.smooth,
2625
2949
  children: [
2626
2950
  /* @__PURE__ */ jsx9(
2627
2951
  TabNav,