@nice-code/action 0.2.13 → 0.2.14

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.
@@ -128,8 +128,7 @@ class ActionDevtoolsCore {
128
128
  }
129
129
  }
130
130
  // src/devtools/browser/NiceActionDevtools.tsx
131
- import { useVirtualizer } from "@tanstack/react-virtual";
132
- import { useCallback, useEffect as useEffect2, useLayoutEffect, useMemo as useMemo2, useRef as useRef2, useState as useState6 } from "react";
131
+ import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState6 } from "react";
133
132
 
134
133
  // src/devtools/browser/components/ActionDetailPanel.tsx
135
134
  import { useMemo, useState as useState5 } from "react";
@@ -196,6 +195,7 @@ function DomainHierarchyTooltip({
196
195
  }, undefined, false, undefined, this);
197
196
  }
198
197
  function DomainChip({
198
+ subtle = false,
199
199
  domain,
200
200
  allDomains,
201
201
  size
@@ -216,10 +216,10 @@ function DomainChip({
216
216
  display: "flex",
217
217
  alignItems: "center",
218
218
  gap: "0.4em",
219
- color: "#818cf8",
219
+ color: subtle ? "#4b5563" : "#818cf8",
220
220
  fontSize,
221
221
  background: "#0f172a",
222
- border: "1px solid #312e81",
222
+ border: !subtle ? "1px solid #312e81" : "1px solid transparent",
223
223
  padding,
224
224
  borderRadius: "0.6rem",
225
225
  flexShrink: 0,
@@ -435,59 +435,9 @@ function CallStackSection({
435
435
  }, undefined, true, undefined, this);
436
436
  }
437
437
 
438
- // src/devtools/browser/components/Chip.tsx
439
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
440
- function Chip({
441
- color,
442
- borderColor,
443
- fontSize = "8px",
444
- padding = "1px 4px",
445
- children,
446
- style
447
- }) {
448
- return /* @__PURE__ */ jsxDEV5("span", {
449
- style: {
450
- color,
451
- fontSize,
452
- background: "#0f172a",
453
- border: `1px solid ${borderColor}`,
454
- padding,
455
- borderRadius: "3px",
456
- flexShrink: 0,
457
- whiteSpace: "nowrap",
458
- ...style
459
- },
460
- children
461
- }, undefined, false, undefined, this);
462
- }
463
-
464
- // src/devtools/browser/components/ChildDispatchChips.tsx
465
- import { jsxDEV as jsxDEV6, Fragment as Fragment2 } from "react/jsx-dev-runtime";
466
- function ChildDispatchChips({
467
- labels,
468
- size = "sm"
469
- }) {
470
- if (labels == null || labels.length === 0)
471
- return null;
472
- const fontSize = size === "md" ? "9px" : "8px";
473
- const padding = size === "md" ? "1px 4px" : "1px 3px";
474
- return /* @__PURE__ */ jsxDEV6(Fragment2, {
475
- children: labels.map((label) => /* @__PURE__ */ jsxDEV6(Chip, {
476
- color: "#c084fc",
477
- borderColor: "#581c87",
478
- fontSize,
479
- padding,
480
- children: [
481
- "↳ ",
482
- label
483
- ]
484
- }, label, true, undefined, this))
485
- }, undefined, false, undefined, this);
486
- }
487
-
488
438
  // src/devtools/browser/components/DetailSection.tsx
489
439
  import { useState as useState2 } from "react";
490
- import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
440
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
491
441
  var COMPACT_CHAR_LIMIT = 120;
492
442
  function DetailSection({
493
443
  label,
@@ -499,9 +449,9 @@ function DetailSection({
499
449
  const compactJson = safeStringify(value, 0);
500
450
  const canExpand = fullJson !== compactJson || compactJson.length > COMPACT_CHAR_LIMIT;
501
451
  const compactDisplay = compactJson.length > COMPACT_CHAR_LIMIT ? `${compactJson.slice(0, COMPACT_CHAR_LIMIT)}…` : compactJson;
502
- return /* @__PURE__ */ jsxDEV7("div", {
452
+ return /* @__PURE__ */ jsxDEV5("div", {
503
453
  children: [
504
- /* @__PURE__ */ jsxDEV7("div", {
454
+ /* @__PURE__ */ jsxDEV5("div", {
505
455
  style: {
506
456
  display: "flex",
507
457
  alignItems: "center",
@@ -509,7 +459,7 @@ function DetailSection({
509
459
  marginBottom: "3px"
510
460
  },
511
461
  children: [
512
- /* @__PURE__ */ jsxDEV7("div", {
462
+ /* @__PURE__ */ jsxDEV5("div", {
513
463
  style: {
514
464
  color,
515
465
  fontSize: "10px",
@@ -518,13 +468,13 @@ function DetailSection({
518
468
  },
519
469
  children: label
520
470
  }, undefined, false, undefined, this),
521
- canExpand && /* @__PURE__ */ jsxDEV7("span", {
471
+ canExpand && /* @__PURE__ */ jsxDEV5("span", {
522
472
  style: { color: "#334155", fontSize: "11px" },
523
473
  children: expanded ? "▾" : "▸"
524
474
  }, undefined, false, undefined, this)
525
475
  ]
526
476
  }, undefined, true, undefined, this),
527
- expanded ? /* @__PURE__ */ jsxDEV7("div", {
477
+ expanded ? /* @__PURE__ */ jsxDEV5("div", {
528
478
  onClick: canExpand ? () => setExpanded(false) : undefined,
529
479
  style: {
530
480
  margin: 0,
@@ -540,7 +490,7 @@ function DetailSection({
540
490
  cursor: canExpand ? "pointer" : "default"
541
491
  },
542
492
  children: fullJson
543
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("div", {
493
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5("div", {
544
494
  onClick: canExpand ? () => setExpanded(true) : undefined,
545
495
  style: {
546
496
  padding: "5px 8px",
@@ -560,31 +510,64 @@ function DetailSection({
560
510
  }, undefined, true, undefined, this);
561
511
  }
562
512
 
513
+ // src/devtools/core/devtools_colors.ts
514
+ var DEVTOOL_COLOR_HANDLER_LOCAL_TEXT = "#34bb89";
515
+ var DEVTOOL_COLOR_HANDLER_LOCAL_BORDER = "#144427";
516
+ var DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT = "#cfa12a";
517
+ var DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER = "#723917";
518
+
519
+ // src/devtools/browser/components/Chip.tsx
520
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
521
+ function Chip({
522
+ color,
523
+ borderColor,
524
+ fontSize = "8px",
525
+ padding = "1px 4px",
526
+ children,
527
+ style
528
+ }) {
529
+ return /* @__PURE__ */ jsxDEV6("span", {
530
+ style: {
531
+ color,
532
+ fontSize,
533
+ background: "#0f172a",
534
+ border: `1px solid ${borderColor}`,
535
+ padding,
536
+ borderRadius: "3px",
537
+ flexShrink: 0,
538
+ whiteSpace: "nowrap",
539
+ ...style
540
+ },
541
+ children
542
+ }, undefined, false, undefined, this);
543
+ }
544
+
563
545
  // src/devtools/browser/components/HandlerChips.tsx
564
- import { jsxDEV as jsxDEV8, Fragment as Fragment3 } from "react/jsx-dev-runtime";
546
+ import { jsxDEV as jsxDEV7, Fragment as Fragment2 } from "react/jsx-dev-runtime";
565
547
  function getExternalLabel(hop) {
566
548
  if (hop.handlerType !== "external")
567
549
  return null;
568
550
  return hop.handlerClient != null ? `${hop.transport ?? "ext"} → ${hop.handlerClient.envId}` : `→ ${hop.transport ?? "ext"}`;
569
551
  }
570
- function HandlerChips({ entry, size, alwaysShowLocal = false }) {
552
+ function HandlerChips({ entry, size }) {
571
553
  const firstHop = entry.meta.routing[0];
572
554
  const localEnvId = firstHop != null ? firstHop.runtime.envId : null;
573
555
  const externalLabel = firstHop != null ? getExternalLabel(firstHop) : null;
574
- const fontSize = size === "md" ? "9px" : "8px";
556
+ const fontSize = size === "md" ? "1em" : "0.8em";
575
557
  const padding = size === "md" ? "1px 5px" : "1px 4px";
576
- return /* @__PURE__ */ jsxDEV8(Fragment3, {
558
+ const firstHopIsLocal = firstHop != null && firstHop.handlerType === "local";
559
+ return /* @__PURE__ */ jsxDEV7(Fragment2, {
577
560
  children: [
578
- localEnvId != null && (alwaysShowLocal || externalLabel == null) && /* @__PURE__ */ jsxDEV8(Chip, {
579
- color: "#34d399",
580
- borderColor: "#14532d",
561
+ localEnvId != null && (firstHopIsLocal || externalLabel == null) && /* @__PURE__ */ jsxDEV7(Chip, {
562
+ color: DEVTOOL_COLOR_HANDLER_LOCAL_TEXT,
563
+ borderColor: DEVTOOL_COLOR_HANDLER_LOCAL_BORDER,
581
564
  fontSize,
582
565
  padding,
583
- children: localEnvId
566
+ children: "local"
584
567
  }, undefined, false, undefined, this),
585
- externalLabel != null && /* @__PURE__ */ jsxDEV8(Chip, {
586
- color: "#fbbf24",
587
- borderColor: "#78350f",
568
+ externalLabel != null && /* @__PURE__ */ jsxDEV7(Chip, {
569
+ color: DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT,
570
+ borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
588
571
  fontSize,
589
572
  padding,
590
573
  children: externalLabel
@@ -595,19 +578,19 @@ function HandlerChips({ entry, size, alwaysShowLocal = false }) {
595
578
 
596
579
  // src/devtools/browser/components/MetaSection.tsx
597
580
  import { useState as useState3 } from "react";
598
- import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
581
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
599
582
  function MetaChip({ label, value }) {
600
- return /* @__PURE__ */ jsxDEV9("span", {
583
+ return /* @__PURE__ */ jsxDEV8("span", {
601
584
  style: { whiteSpace: "nowrap" },
602
585
  children: [
603
- /* @__PURE__ */ jsxDEV9("span", {
586
+ /* @__PURE__ */ jsxDEV8("span", {
604
587
  style: { color: "#475569" },
605
588
  children: [
606
589
  label,
607
590
  " "
608
591
  ]
609
592
  }, undefined, true, undefined, this),
610
- /* @__PURE__ */ jsxDEV9("span", {
593
+ /* @__PURE__ */ jsxDEV8("span", {
611
594
  style: { color: "#cbd5e1" },
612
595
  children: value
613
596
  }, undefined, false, undefined, this)
@@ -623,9 +606,9 @@ function MetaSection({ entry }) {
623
606
  ...meta.originClient.perId != null ? [{ label: "perId", value: meta.originClient.perId }] : [],
624
607
  ...meta.originClient.insId != null ? [{ label: "insId", value: meta.originClient.insId }] : []
625
608
  ];
626
- return /* @__PURE__ */ jsxDEV9("div", {
609
+ return /* @__PURE__ */ jsxDEV8("div", {
627
610
  children: [
628
- /* @__PURE__ */ jsxDEV9("div", {
611
+ /* @__PURE__ */ jsxDEV8("div", {
629
612
  style: {
630
613
  display: "flex",
631
614
  alignItems: "center",
@@ -633,7 +616,7 @@ function MetaSection({ entry }) {
633
616
  marginBottom: "3px"
634
617
  },
635
618
  children: [
636
- /* @__PURE__ */ jsxDEV9("div", {
619
+ /* @__PURE__ */ jsxDEV8("div", {
637
620
  style: {
638
621
  color: "#60a5fa",
639
622
  fontSize: "10px",
@@ -642,16 +625,16 @@ function MetaSection({ entry }) {
642
625
  },
643
626
  children: "Meta"
644
627
  }, undefined, false, undefined, this),
645
- /* @__PURE__ */ jsxDEV9("span", {
628
+ /* @__PURE__ */ jsxDEV8("span", {
646
629
  style: { color: "#334155", fontSize: "11px" },
647
630
  children: expanded ? "▾" : "▸"
648
631
  }, undefined, false, undefined, this)
649
632
  ]
650
633
  }, undefined, true, undefined, this),
651
- expanded ? /* @__PURE__ */ jsxDEV9("div", {
634
+ expanded ? /* @__PURE__ */ jsxDEV8("div", {
652
635
  onClick: () => setExpanded(false),
653
636
  style: { background: "#1e293b", borderRadius: "4px", overflow: "hidden", cursor: "pointer" },
654
- children: expandedRows.map(({ label, value }, i) => /* @__PURE__ */ jsxDEV9("div", {
637
+ children: expandedRows.map(({ label, value }, i) => /* @__PURE__ */ jsxDEV8("div", {
655
638
  style: {
656
639
  display: "grid",
657
640
  gridTemplateColumns: "52px 1fr",
@@ -661,17 +644,17 @@ function MetaSection({ entry }) {
661
644
  alignItems: "start"
662
645
  },
663
646
  children: [
664
- /* @__PURE__ */ jsxDEV9("span", {
647
+ /* @__PURE__ */ jsxDEV8("span", {
665
648
  style: { textAlign: "left", color: "#475569", fontSize: "10px", paddingTop: "1px" },
666
649
  children: label
667
650
  }, undefined, false, undefined, this),
668
- /* @__PURE__ */ jsxDEV9("span", {
651
+ /* @__PURE__ */ jsxDEV8("span", {
669
652
  style: { textAlign: "left", color: "#cbd5e1", fontSize: "11px", wordBreak: "break-all" },
670
653
  children: value
671
654
  }, undefined, false, undefined, this)
672
655
  ]
673
656
  }, label, true, undefined, this))
674
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("div", {
657
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("div", {
675
658
  onClick: () => setExpanded(true),
676
659
  style: {
677
660
  background: "#1e293b",
@@ -685,19 +668,19 @@ function MetaSection({ entry }) {
685
668
  cursor: "pointer"
686
669
  },
687
670
  children: [
688
- /* @__PURE__ */ jsxDEV9(MetaChip, {
671
+ /* @__PURE__ */ jsxDEV8(MetaChip, {
689
672
  label: "cuid",
690
673
  value: `…${cuid.slice(-8)}`
691
674
  }, undefined, false, undefined, this),
692
- /* @__PURE__ */ jsxDEV9(MetaChip, {
675
+ /* @__PURE__ */ jsxDEV8(MetaChip, {
693
676
  label: "origin",
694
677
  value: meta.originClient.envId
695
678
  }, undefined, false, undefined, this),
696
- meta.originClient.perId != null && /* @__PURE__ */ jsxDEV9(MetaChip, {
679
+ meta.originClient.perId != null && /* @__PURE__ */ jsxDEV8(MetaChip, {
697
680
  label: "perId",
698
681
  value: meta.originClient.perId.length > 10 ? `${meta.originClient.perId.slice(0, 10)}…` : meta.originClient.perId
699
682
  }, undefined, false, undefined, this),
700
- meta.originClient.insId != null && /* @__PURE__ */ jsxDEV9(MetaChip, {
683
+ meta.originClient.insId != null && /* @__PURE__ */ jsxDEV8(MetaChip, {
701
684
  label: "insId",
702
685
  value: meta.originClient.insId.length > 10 ? `${meta.originClient.insId.slice(0, 10)}…` : meta.originClient.insId
703
686
  }, undefined, false, undefined, this)
@@ -708,7 +691,7 @@ function MetaSection({ entry }) {
708
691
  }
709
692
 
710
693
  // src/devtools/browser/components/RoutingSection.tsx
711
- import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
694
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
712
695
  function RoutingSection({
713
696
  entry,
714
697
  minHopCount = 0
@@ -718,12 +701,12 @@ function RoutingSection({
718
701
  const phantomCount = Math.max(0, minHopCount - hopCount);
719
702
  if (hopCount === 0 && phantomCount === 0)
720
703
  return null;
721
- return /* @__PURE__ */ jsxDEV10("div", {
704
+ return /* @__PURE__ */ jsxDEV9("div", {
722
705
  children: [
723
- /* @__PURE__ */ jsxDEV10(SectionLabel, {
706
+ /* @__PURE__ */ jsxDEV9(SectionLabel, {
724
707
  label: hopCount > 0 ? `Routing · ${hopCount} hop${hopCount !== 1 ? "s" : ""}` : "Routing"
725
708
  }, undefined, false, undefined, this),
726
- /* @__PURE__ */ jsxDEV10("div", {
709
+ /* @__PURE__ */ jsxDEV9("div", {
727
710
  style: { display: "flex", flexDirection: "column", gap: "2px" },
728
711
  children: [
729
712
  meta.routing.map((hop, i) => {
@@ -732,7 +715,7 @@ function RoutingSection({
732
715
  const badgeColor = isLocal ? "#34d399" : "#fbbf24";
733
716
  const badgeText = isLocal ? "● exec" : `→ ${hop.transport ?? "ext"}`;
734
717
  const runtimeTitle = [hop.runtime.perId, hop.runtime.insId].filter(Boolean).join(" · ") || undefined;
735
- return /* @__PURE__ */ jsxDEV10("div", {
718
+ return /* @__PURE__ */ jsxDEV9("div", {
736
719
  style: {
737
720
  background: "#1e293b",
738
721
  borderRadius: "4px",
@@ -745,14 +728,14 @@ function RoutingSection({
745
728
  padding: "4px 8px"
746
729
  },
747
730
  children: [
748
- /* @__PURE__ */ jsxDEV10("span", {
731
+ /* @__PURE__ */ jsxDEV9("span", {
749
732
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
750
733
  children: [
751
- /* @__PURE__ */ jsxDEV10("span", {
734
+ /* @__PURE__ */ jsxDEV9("span", {
752
735
  style: { color: "#334155", fontSize: "10px", width: "16px", textAlign: "right" },
753
736
  children: i + 1
754
737
  }, undefined, false, undefined, this),
755
- /* @__PURE__ */ jsxDEV10("span", {
738
+ /* @__PURE__ */ jsxDEV9("span", {
756
739
  title: runtimeTitle,
757
740
  style: {
758
741
  color: "#94a3b8",
@@ -766,11 +749,11 @@ function RoutingSection({
766
749
  }, undefined, false, undefined, this)
767
750
  ]
768
751
  }, undefined, true, undefined, this),
769
- /* @__PURE__ */ jsxDEV10("span", {
752
+ /* @__PURE__ */ jsxDEV9("span", {
770
753
  style: { color: badgeColor, fontSize: "10px", whiteSpace: "nowrap" },
771
754
  children: badgeText
772
755
  }, undefined, false, undefined, this),
773
- /* @__PURE__ */ jsxDEV10("span", {
756
+ /* @__PURE__ */ jsxDEV9("span", {
774
757
  style: {
775
758
  display: "flex",
776
759
  alignItems: "center",
@@ -779,7 +762,7 @@ function RoutingSection({
779
762
  overflow: "hidden"
780
763
  },
781
764
  children: [
782
- /* @__PURE__ */ jsxDEV10("span", {
765
+ /* @__PURE__ */ jsxDEV9("span", {
783
766
  style: {
784
767
  color: "#475569",
785
768
  fontSize: "10px",
@@ -789,7 +772,7 @@ function RoutingSection({
789
772
  },
790
773
  children: hop.handlerClient != null ? `↳ ${hop.handlerClient.envId}` : ""
791
774
  }, undefined, false, undefined, this),
792
- /* @__PURE__ */ jsxDEV10("span", {
775
+ /* @__PURE__ */ jsxDEV9("span", {
793
776
  style: { color: "#334155", fontSize: "10px", flexShrink: 0, marginLeft: "auto" },
794
777
  children: [
795
778
  "+",
@@ -802,7 +785,7 @@ function RoutingSection({
802
785
  ]
803
786
  }, `${hop.time}-${hop.runtime.envId}`, true, undefined, this);
804
787
  }),
805
- Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxDEV10("div", {
788
+ Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxDEV9("div", {
806
789
  "aria-hidden": "true",
807
790
  style: {
808
791
  visibility: "hidden",
@@ -815,24 +798,24 @@ function RoutingSection({
815
798
  padding: "4px 8px"
816
799
  },
817
800
  children: [
818
- /* @__PURE__ */ jsxDEV10("span", {
801
+ /* @__PURE__ */ jsxDEV9("span", {
819
802
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
820
803
  children: [
821
- /* @__PURE__ */ jsxDEV10("span", {
804
+ /* @__PURE__ */ jsxDEV9("span", {
822
805
  style: { fontSize: "10px", width: "16px" },
823
806
  children: "0"
824
807
  }, undefined, false, undefined, this),
825
- /* @__PURE__ */ jsxDEV10("span", {
808
+ /* @__PURE__ */ jsxDEV9("span", {
826
809
  style: { fontSize: "11px" },
827
810
  children: "placeholder"
828
811
  }, undefined, false, undefined, this)
829
812
  ]
830
813
  }, undefined, true, undefined, this),
831
- /* @__PURE__ */ jsxDEV10("span", {
814
+ /* @__PURE__ */ jsxDEV9("span", {
832
815
  style: { fontSize: "10px" },
833
816
  children: "placeholder"
834
817
  }, undefined, false, undefined, this),
835
- /* @__PURE__ */ jsxDEV10("span", {}, undefined, false, undefined, this)
818
+ /* @__PURE__ */ jsxDEV9("span", {}, undefined, false, undefined, this)
836
819
  ]
837
820
  }, key, true, undefined, this))
838
821
  ]
@@ -843,7 +826,7 @@ function RoutingSection({
843
826
 
844
827
  // src/devtools/browser/components/StackTraceSection.tsx
845
828
  import { useState as useState4 } from "react";
846
- import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
829
+ import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
847
830
  var INTERNAL_PATTERNS = [
848
831
  "/nice-action/",
849
832
  "@nice-code/action",
@@ -902,9 +885,9 @@ function StackTraceSection({
902
885
  const displayFrames = showAll ? allFrames : userFrames;
903
886
  if (allFrames.length === 0)
904
887
  return null;
905
- return /* @__PURE__ */ jsxDEV11("div", {
888
+ return /* @__PURE__ */ jsxDEV10("div", {
906
889
  children: [
907
- /* @__PURE__ */ jsxDEV11("div", {
890
+ /* @__PURE__ */ jsxDEV10("div", {
908
891
  style: {
909
892
  display: "flex",
910
893
  alignItems: "center",
@@ -912,17 +895,17 @@ function StackTraceSection({
912
895
  marginBottom: "3px"
913
896
  },
914
897
  children: [
915
- /* @__PURE__ */ jsxDEV11(SectionLabel, {
898
+ /* @__PURE__ */ jsxDEV10(SectionLabel, {
916
899
  label,
917
900
  color
918
901
  }, undefined, false, undefined, this),
919
- hasInternalFrames && /* @__PURE__ */ jsxDEV11("span", {
902
+ hasInternalFrames && /* @__PURE__ */ jsxDEV10("span", {
920
903
  style: { color: "#475569", fontSize: "9px" },
921
904
  children: !showAll ? "user only" : `all (${allFrames.length})`
922
905
  }, undefined, false, undefined, this)
923
906
  ]
924
907
  }, undefined, true, undefined, this),
925
- /* @__PURE__ */ jsxDEV11("div", {
908
+ /* @__PURE__ */ jsxDEV10("div", {
926
909
  onClick: () => setShowAll((s) => !s),
927
910
  style: {
928
911
  background: "#040a13",
@@ -931,7 +914,7 @@ function StackTraceSection({
931
914
  overflow: "hidden",
932
915
  cursor: "pointer"
933
916
  },
934
- children: displayFrames.length === 0 ? /* @__PURE__ */ jsxDEV11("div", {
917
+ children: displayFrames.length === 0 ? /* @__PURE__ */ jsxDEV10("div", {
935
918
  style: { padding: "6px 10px", color: "#64748b", fontSize: "10px", fontStyle: "italic" },
936
919
  children: "no user frames captured"
937
920
  }, undefined, false, undefined, this) : displayFrames.map((frame, idx) => {
@@ -941,7 +924,7 @@ function StackTraceSection({
941
924
  const bareFilename = slashIdx >= 0 ? displayFile.slice(slashIdx + 1) : displayFile;
942
925
  const titleStr = frame.file != null ? frame.file : frame.raw;
943
926
  const isUser = !frame.isInternal;
944
- return /* @__PURE__ */ jsxDEV11("div", {
927
+ return /* @__PURE__ */ jsxDEV10("div", {
945
928
  title: titleStr,
946
929
  style: {
947
930
  display: "flex",
@@ -951,7 +934,7 @@ function StackTraceSection({
951
934
  borderBottom: idx < displayFrames.length - 1 ? "1px solid #0f172a" : undefined
952
935
  },
953
936
  children: [
954
- /* @__PURE__ */ jsxDEV11("span", {
937
+ /* @__PURE__ */ jsxDEV10("span", {
955
938
  style: {
956
939
  color: isUser ? "#64748b" : "#2d3f53",
957
940
  fontSize: "10px",
@@ -962,12 +945,12 @@ function StackTraceSection({
962
945
  },
963
946
  children: idx + 1
964
947
  }, undefined, false, undefined, this),
965
- /* @__PURE__ */ jsxDEV11("div", {
948
+ /* @__PURE__ */ jsxDEV10("div", {
966
949
  style: { display: "flex", flexDirection: "column", gap: "0.15em", lineHeight: 1.2 },
967
950
  children: [
968
- /* @__PURE__ */ jsxDEV11("div", {
951
+ /* @__PURE__ */ jsxDEV10("div", {
969
952
  style: { display: "flex", alignItems: "center" },
970
- children: /* @__PURE__ */ jsxDEV11("span", {
953
+ children: /* @__PURE__ */ jsxDEV10("span", {
971
954
  style: {
972
955
  color: isUser ? "#e2e8f0" : "#50698b",
973
956
  fontSize: "12px",
@@ -979,10 +962,10 @@ function StackTraceSection({
979
962
  children: frame.fn ?? "(anonymous)"
980
963
  }, undefined, false, undefined, this)
981
964
  }, undefined, false, undefined, this),
982
- /* @__PURE__ */ jsxDEV11("div", {
965
+ /* @__PURE__ */ jsxDEV10("div", {
983
966
  style: { display: "flex", alignItems: "baseline", overflow: "hidden" },
984
967
  children: [
985
- folderPrefix !== "" && /* @__PURE__ */ jsxDEV11("span", {
968
+ folderPrefix !== "" && /* @__PURE__ */ jsxDEV10("span", {
986
969
  style: {
987
970
  color: isUser ? "#596b83" : "#2d3f53",
988
971
  fontSize: "10px",
@@ -994,7 +977,7 @@ function StackTraceSection({
994
977
  },
995
978
  children: folderPrefix
996
979
  }, undefined, false, undefined, this),
997
- /* @__PURE__ */ jsxDEV11("span", {
980
+ /* @__PURE__ */ jsxDEV10("span", {
998
981
  style: {
999
982
  color: isUser ? "#8a9ebb" : "#425979",
1000
983
  fontSize: "10px",
@@ -1016,7 +999,7 @@ function StackTraceSection({
1016
999
  }
1017
1000
 
1018
1001
  // src/devtools/browser/components/ActionDetailPanel.tsx
1019
- import { jsxDEV as jsxDEV12, Fragment as Fragment4 } from "react/jsx-dev-runtime";
1002
+ import { jsxDEV as jsxDEV11, Fragment as Fragment3 } from "react/jsx-dev-runtime";
1020
1003
  function DetailHeader({
1021
1004
  entry,
1022
1005
  isActive,
@@ -1026,7 +1009,7 @@ function DetailHeader({
1026
1009
  const color = STATUS_COLOR[entry.status];
1027
1010
  const symbol = STATUS_SYMBOL[entry.status];
1028
1011
  const timestamp = formatTimestamp(entry.startTime);
1029
- return /* @__PURE__ */ jsxDEV12("div", {
1012
+ return /* @__PURE__ */ jsxDEV11("div", {
1030
1013
  onClick: !isActive ? onClick : undefined,
1031
1014
  style: {
1032
1015
  padding: "10px 12px",
@@ -1040,7 +1023,7 @@ function DetailHeader({
1040
1023
  cursor: isActive ? "default" : "pointer"
1041
1024
  },
1042
1025
  children: [
1043
- /* @__PURE__ */ jsxDEV12("span", {
1026
+ /* @__PURE__ */ jsxDEV11("span", {
1044
1027
  style: {
1045
1028
  color,
1046
1029
  fontSize: "15px",
@@ -1050,16 +1033,20 @@ function DetailHeader({
1050
1033
  },
1051
1034
  children: symbol
1052
1035
  }, undefined, false, undefined, this),
1053
- /* @__PURE__ */ jsxDEV12("div", {
1054
- style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "5px" },
1036
+ /* @__PURE__ */ jsxDEV11("div", {
1037
+ style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "0.5em" },
1055
1038
  children: [
1056
- /* @__PURE__ */ jsxDEV12("div", {
1057
- style: { display: "flex", alignItems: "center", minWidth: 0, gap: "0.5em" },
1039
+ /* @__PURE__ */ jsxDEV11("div", {
1040
+ style: { display: "flex", alignItems: "center", minWidth: 0, gap: "0.4em" },
1058
1041
  children: [
1059
- /* @__PURE__ */ jsxDEV12("span", {
1042
+ /* @__PURE__ */ jsxDEV11("span", {
1043
+ style: { fontSize: "1.2em" },
1044
+ children: "⚡"
1045
+ }, undefined, false, undefined, this),
1046
+ /* @__PURE__ */ jsxDEV11("span", {
1060
1047
  style: {
1061
1048
  color: "#f1f5f9",
1062
- fontSize: "13px",
1049
+ fontSize: "1.2em",
1063
1050
  fontWeight: "600",
1064
1051
  overflow: "hidden",
1065
1052
  textOverflow: "ellipsis",
@@ -1069,14 +1056,14 @@ function DetailHeader({
1069
1056
  },
1070
1057
  children: entry.actionId
1071
1058
  }, undefined, false, undefined, this),
1072
- /* @__PURE__ */ jsxDEV12(DomainChip, {
1059
+ /* @__PURE__ */ jsxDEV11(DomainChip, {
1073
1060
  domain: entry.domain,
1074
1061
  allDomains: entry.allDomains,
1075
1062
  size: "md"
1076
1063
  }, undefined, false, undefined, this)
1077
1064
  ]
1078
1065
  }, undefined, true, undefined, this),
1079
- /* @__PURE__ */ jsxDEV12("div", {
1066
+ /* @__PURE__ */ jsxDEV11("div", {
1080
1067
  style: {
1081
1068
  display: "flex",
1082
1069
  alignItems: "center",
@@ -1084,7 +1071,7 @@ function DetailHeader({
1084
1071
  gap: "8px"
1085
1072
  },
1086
1073
  children: [
1087
- /* @__PURE__ */ jsxDEV12("div", {
1074
+ /* @__PURE__ */ jsxDEV11("div", {
1088
1075
  style: {
1089
1076
  display: "flex",
1090
1077
  alignItems: "center",
@@ -1092,28 +1079,21 @@ function DetailHeader({
1092
1079
  minWidth: 0,
1093
1080
  overflow: "hidden"
1094
1081
  },
1095
- children: [
1096
- /* @__PURE__ */ jsxDEV12(HandlerChips, {
1097
- entry,
1098
- size: "md",
1099
- alwaysShowLocal: true
1100
- }, undefined, false, undefined, this),
1101
- /* @__PURE__ */ jsxDEV12(ChildDispatchChips, {
1102
- labels: childExternalLabels,
1103
- size: "md"
1104
- }, undefined, false, undefined, this)
1105
- ]
1106
- }, undefined, true, undefined, this),
1107
- /* @__PURE__ */ jsxDEV12("div", {
1082
+ children: /* @__PURE__ */ jsxDEV11(HandlerChips, {
1083
+ entry,
1084
+ size: "md"
1085
+ }, undefined, false, undefined, this)
1086
+ }, undefined, false, undefined, this),
1087
+ /* @__PURE__ */ jsxDEV11("div", {
1108
1088
  style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0 },
1109
1089
  children: [
1110
- /* @__PURE__ */ jsxDEV12("span", {
1090
+ /* @__PURE__ */ jsxDEV11("span", {
1111
1091
  style: { color: "#334155", fontSize: "10px", letterSpacing: "0.02em" },
1112
1092
  children: timestamp
1113
1093
  }, undefined, false, undefined, this),
1114
- /* @__PURE__ */ jsxDEV12("span", {
1094
+ /* @__PURE__ */ jsxDEV11("span", {
1115
1095
  style: { color, fontSize: "12px", fontWeight: "500" },
1116
- children: /* @__PURE__ */ jsxDEV12(DurationDisplay, {
1096
+ children: /* @__PURE__ */ jsxDEV11(DurationDisplay, {
1117
1097
  entry
1118
1098
  }, undefined, false, undefined, this)
1119
1099
  }, undefined, false, undefined, this)
@@ -1153,7 +1133,7 @@ function ActionDetailPanel({
1153
1133
  const handleFocusChild = (cuid) => {
1154
1134
  setFocusedChildCuid((prev) => prev === cuid ? null : cuid);
1155
1135
  };
1156
- return /* @__PURE__ */ jsxDEV12("div", {
1136
+ return /* @__PURE__ */ jsxDEV11("div", {
1157
1137
  style: {
1158
1138
  flex: 1,
1159
1139
  display: "flex",
@@ -1163,13 +1143,13 @@ function ActionDetailPanel({
1163
1143
  background: "#0f172a"
1164
1144
  },
1165
1145
  children: [
1166
- /* @__PURE__ */ jsxDEV12(DetailHeader, {
1146
+ /* @__PURE__ */ jsxDEV11(DetailHeader, {
1167
1147
  entry,
1168
1148
  isActive: focusedChildCuid === null,
1169
1149
  onClick: () => setFocusedChildCuid(null),
1170
1150
  childExternalLabels
1171
1151
  }, undefined, false, undefined, this),
1172
- /* @__PURE__ */ jsxDEV12("div", {
1152
+ /* @__PURE__ */ jsxDEV11("div", {
1173
1153
  style: {
1174
1154
  flex: 1,
1175
1155
  overflowY: "auto",
@@ -1180,63 +1160,63 @@ function ActionDetailPanel({
1180
1160
  gap: "8px"
1181
1161
  },
1182
1162
  children: [
1183
- /* @__PURE__ */ jsxDEV12(CallStackSection, {
1163
+ /* @__PURE__ */ jsxDEV11(CallStackSection, {
1184
1164
  parent,
1185
1165
  childEntries,
1186
1166
  focusedChildCuid,
1187
1167
  onFocusChild: handleFocusChild,
1188
1168
  onSelectParent: onSelectEntry
1189
1169
  }, undefined, false, undefined, this),
1190
- /* @__PURE__ */ jsxDEV12(MetaSection, {
1170
+ /* @__PURE__ */ jsxDEV11(MetaSection, {
1191
1171
  entry: focusedEntry
1192
1172
  }, undefined, false, undefined, this),
1193
- /* @__PURE__ */ jsxDEV12(RoutingSection, {
1173
+ /* @__PURE__ */ jsxDEV11(RoutingSection, {
1194
1174
  entry: focusedEntry,
1195
1175
  minHopCount: maxRoutingHops
1196
1176
  }, undefined, false, undefined, this),
1197
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
1177
+ /* @__PURE__ */ jsxDEV11(StackTraceSection, {
1198
1178
  label: "Dispatch Site",
1199
1179
  stack: focusedEntry.callSite,
1200
1180
  color: "#94a3b8"
1201
1181
  }, undefined, false, undefined, this),
1202
- /* @__PURE__ */ jsxDEV12(DetailSection, {
1182
+ /* @__PURE__ */ jsxDEV11(DetailSection, {
1203
1183
  label: "Input",
1204
1184
  value: focusedEntry.input
1205
1185
  }, undefined, false, undefined, this),
1206
- focusedEntry.status === "success" && /* @__PURE__ */ jsxDEV12(DetailSection, {
1186
+ focusedEntry.status === "success" && /* @__PURE__ */ jsxDEV11(DetailSection, {
1207
1187
  label: "Output",
1208
1188
  value: focusedEntry.output,
1209
1189
  color: "#4ade80"
1210
1190
  }, undefined, false, undefined, this),
1211
- focusedEntry.status === "failed" && /* @__PURE__ */ jsxDEV12(Fragment4, {
1191
+ focusedEntry.status === "failed" && /* @__PURE__ */ jsxDEV11(Fragment3, {
1212
1192
  children: [
1213
- /* @__PURE__ */ jsxDEV12(DetailSection, {
1193
+ /* @__PURE__ */ jsxDEV11(DetailSection, {
1214
1194
  label: "Error",
1215
1195
  value: focusedEntry.error,
1216
1196
  color: "#f87171"
1217
1197
  }, undefined, false, undefined, this),
1218
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
1198
+ /* @__PURE__ */ jsxDEV11(StackTraceSection, {
1219
1199
  label: "Error Stack",
1220
1200
  stack: focusedEntry.errorStack,
1221
1201
  color: "#f87171"
1222
1202
  }, undefined, false, undefined, this)
1223
1203
  ]
1224
1204
  }, undefined, true, undefined, this),
1225
- focusedEntry.status === "aborted" && /* @__PURE__ */ jsxDEV12(Fragment4, {
1205
+ focusedEntry.status === "aborted" && /* @__PURE__ */ jsxDEV11(Fragment3, {
1226
1206
  children: [
1227
- focusedEntry.abortReason != null && /* @__PURE__ */ jsxDEV12(DetailSection, {
1207
+ focusedEntry.abortReason != null && /* @__PURE__ */ jsxDEV11(DetailSection, {
1228
1208
  label: "Abort Reason",
1229
1209
  value: focusedEntry.abortReason,
1230
1210
  color: "#9ca3af"
1231
1211
  }, undefined, false, undefined, this),
1232
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
1212
+ /* @__PURE__ */ jsxDEV11(StackTraceSection, {
1233
1213
  label: "Abort Stack",
1234
1214
  stack: focusedEntry.errorStack,
1235
1215
  color: "#9ca3af"
1236
1216
  }, undefined, false, undefined, this)
1237
1217
  ]
1238
1218
  }, undefined, true, undefined, this),
1239
- focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsxDEV12(DetailSection, {
1219
+ focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsxDEV11(DetailSection, {
1240
1220
  label: `Progress (${focusedEntry.progressUpdates.length})`,
1241
1221
  value: focusedEntry.progressUpdates
1242
1222
  }, undefined, false, undefined, this)
@@ -1246,6 +1226,30 @@ function ActionDetailPanel({
1246
1226
  }, undefined, true, undefined, this);
1247
1227
  }
1248
1228
 
1229
+ // src/devtools/browser/components/ChildDispatchChips.tsx
1230
+ import { jsxDEV as jsxDEV12, Fragment as Fragment4 } from "react/jsx-dev-runtime";
1231
+ function ChildDispatchChips({
1232
+ labels,
1233
+ size = "sm"
1234
+ }) {
1235
+ if (labels == null || labels.length === 0)
1236
+ return null;
1237
+ const fontSize = size === "md" ? "1em" : "0.8em";
1238
+ const padding = size === "md" ? "1px 4px" : "1px 3px";
1239
+ return /* @__PURE__ */ jsxDEV12(Fragment4, {
1240
+ children: labels.map((label) => /* @__PURE__ */ jsxDEV12(Chip, {
1241
+ color: DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT,
1242
+ borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
1243
+ fontSize,
1244
+ padding,
1245
+ children: [
1246
+ "↳ ",
1247
+ label
1248
+ ]
1249
+ }, label, true, undefined, this))
1250
+ }, undefined, false, undefined, this);
1251
+ }
1252
+
1249
1253
  // src/devtools/browser/components/ActionEntryRow.tsx
1250
1254
  import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
1251
1255
  function ActionEntryRow({
@@ -1280,6 +1284,12 @@ function ActionEntryRow({
1280
1284
  style: { color: "#334155", fontSize: "10px", flexShrink: 0 },
1281
1285
  children: symbol
1282
1286
  }, undefined, false, undefined, this),
1287
+ /* @__PURE__ */ jsxDEV13(DomainChip, {
1288
+ subtle: true,
1289
+ domain: entry.domain,
1290
+ allDomains: entry.allDomains,
1291
+ size: "sm"
1292
+ }, undefined, false, undefined, this),
1283
1293
  /* @__PURE__ */ jsxDEV13("span", {
1284
1294
  children: [
1285
1295
  /* @__PURE__ */ jsxDEV13("span", {
@@ -1300,11 +1310,6 @@ function ActionEntryRow({
1300
1310
  }, undefined, false, undefined, this)
1301
1311
  ]
1302
1312
  }, undefined, true, undefined, this),
1303
- /* @__PURE__ */ jsxDEV13(DomainChip, {
1304
- domain: entry.domain,
1305
- allDomains: entry.allDomains,
1306
- size: "sm"
1307
- }, undefined, false, undefined, this),
1308
1313
  /* @__PURE__ */ jsxDEV13("span", {
1309
1314
  style: { color: "#334155", fontSize: "11px", flexShrink: 0 },
1310
1315
  children: /* @__PURE__ */ jsxDEV13(DurationDisplay, {
@@ -1368,9 +1373,18 @@ function ActionEntryRow({
1368
1373
  alignItems: "center",
1369
1374
  minWidth: 0,
1370
1375
  overflow: "hidden",
1371
- gap: "0.5em"
1376
+ gap: "0.3em"
1372
1377
  },
1373
1378
  children: [
1379
+ /* @__PURE__ */ jsxDEV13(DomainChip, {
1380
+ domain: entry.domain,
1381
+ allDomains: entry.allDomains,
1382
+ size: "md"
1383
+ }, undefined, false, undefined, this),
1384
+ /* @__PURE__ */ jsxDEV13("span", {
1385
+ style: { color: isSelected ? "#818cf8" : "#3730a3", fontSize: "1em" },
1386
+ children: "⚡"
1387
+ }, undefined, false, undefined, this),
1374
1388
  /* @__PURE__ */ jsxDEV13("span", {
1375
1389
  style: {
1376
1390
  color: "#cbd5e1",
@@ -1382,11 +1396,6 @@ function ActionEntryRow({
1382
1396
  minWidth: "24px"
1383
1397
  },
1384
1398
  children: entry.actionId
1385
- }, undefined, false, undefined, this),
1386
- /* @__PURE__ */ jsxDEV13(DomainChip, {
1387
- domain: entry.domain,
1388
- allDomains: entry.allDomains,
1389
- size: "md"
1390
1399
  }, undefined, false, undefined, this)
1391
1400
  ]
1392
1401
  }, undefined, true, undefined, this),
@@ -1427,7 +1436,7 @@ function ActionEntryRow({
1427
1436
  fontSize: "9px",
1428
1437
  padding: "1px 5px",
1429
1438
  children: [
1430
- "×",
1439
+ "x",
1431
1440
  groupCount
1432
1441
  ]
1433
1442
  }, undefined, true, undefined, this),
@@ -1611,14 +1620,18 @@ if (typeof document !== "undefined" && !document.getElementById("__nice-action-d
1611
1620
  0%, 100% { opacity: 1; }
1612
1621
  50% { opacity: 0.35; }
1613
1622
  }
1623
+ @keyframes __nice-action-shine {
1624
+ 0% { transform: translateX(-100%); opacity: 0; }
1625
+ 15% { opacity: 1; }
1626
+ 85% { opacity: 1; }
1627
+ 100% { transform: translateX(200%); opacity: 0; }
1628
+ }
1614
1629
  `;
1615
1630
  document.head?.appendChild(style);
1616
1631
  }
1617
1632
  var PREFS_KEY = "__nice-action-devtools-prefs";
1618
1633
  var DOCKED_HEIGHT_DEFAULT = 320;
1619
1634
  var DOCKED_WIDTH_DEFAULT = 420;
1620
- var ROW_HEIGHT = 50;
1621
- var SUB_ROW_HEIGHT = 30;
1622
1635
  function readPrefs(defaultPosition, initialOpen) {
1623
1636
  const fallback = {
1624
1637
  position: defaultPosition,
@@ -1692,7 +1705,7 @@ function NiceActionDevtools_Panel({
1692
1705
  useEffect2(() => core.subscribe(setEntries), [core]);
1693
1706
  const groups = useMemo2(() => {
1694
1707
  const byCuid = new Map(entries.map((e) => [e.cuid, e]));
1695
- const roots = entries.filter((e) => e.parentCuid == null || !byCuid.has(e.parentCuid));
1708
+ const roots = entries.filter((e) => e.status !== "running" && (e.parentCuid == null || !byCuid.has(e.parentCuid)));
1696
1709
  return groupEntries(roots);
1697
1710
  }, [entries]);
1698
1711
  const childExternalLabelsMap = useMemo2(() => {
@@ -1714,19 +1727,20 @@ function NiceActionDevtools_Panel({
1714
1727
  }, [entries]);
1715
1728
  const handleGroupRowClick = (group) => {
1716
1729
  const repCuid = group.representative.cuid;
1717
- const isExpanded = expandedGroupCuids.has(repCuid);
1718
- const isSelected = selectedCuid === repCuid;
1719
- if (group.rest.length === 0) {
1720
- setSelectedCuid(isSelected ? null : repCuid);
1721
- setExpandedGroupCuids(new Set);
1722
- } else if (isSelected && isExpanded) {
1723
- setSelectedCuid(null);
1724
- setExpandedGroupCuids(new Set);
1725
- } else {
1730
+ const allInGroup = [group.representative, ...group.rest];
1731
+ const selectedInGroup = allInGroup.find((e) => e.cuid === selectedCuid) ?? null;
1732
+ setExpandedGroupCuids(new Set);
1733
+ if (selectedInGroup != null && selectedCuid !== repCuid) {
1726
1734
  setSelectedCuid(repCuid);
1727
- setExpandedGroupCuids(new Set([repCuid]));
1735
+ } else {
1736
+ setSelectedCuid(selectedCuid === repCuid ? null : repCuid);
1728
1737
  }
1729
1738
  };
1739
+ const handleExpandGroup = (group) => {
1740
+ const oldestCuid = (group.rest[group.rest.length - 1] ?? group.representative).cuid;
1741
+ setSelectedCuid(null);
1742
+ setExpandedGroupCuids(new Set([oldestCuid]));
1743
+ };
1730
1744
  const setPrefs = (update) => {
1731
1745
  setPrefsRaw((prev) => {
1732
1746
  const next = { ...prev, ...update };
@@ -1863,7 +1877,11 @@ function NiceActionDevtools_Panel({
1863
1877
  selectedCuid,
1864
1878
  expandedGroupCuids,
1865
1879
  onGroupClick: handleGroupRowClick,
1866
- onSubClick: (cuid, isSelected) => setSelectedCuid(isSelected ? null : cuid),
1880
+ onSubClick: (cuid, isSelected) => {
1881
+ setSelectedCuid(isSelected ? null : cuid);
1882
+ setExpandedGroupCuids(new Set);
1883
+ },
1884
+ onExpandGroup: handleExpandGroup,
1867
1885
  childExternalLabelsMap
1868
1886
  };
1869
1887
  return /* @__PURE__ */ jsxDEV15(DomainTooltipCtx.Provider, {
@@ -1893,7 +1911,7 @@ function NiceActionDevtools_Panel({
1893
1911
  isHorizDock ? /* @__PURE__ */ jsxDEV15("div", {
1894
1912
  style: { flex: 1, display: "flex", overflow: "hidden" },
1895
1913
  children: [
1896
- /* @__PURE__ */ jsxDEV15(VirtualActionList, {
1914
+ /* @__PURE__ */ jsxDEV15(ActionList, {
1897
1915
  ...virtualListProps,
1898
1916
  style: {
1899
1917
  width: "340px",
@@ -1922,7 +1940,7 @@ function NiceActionDevtools_Panel({
1922
1940
  ]
1923
1941
  }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV15(Fragment5, {
1924
1942
  children: [
1925
- /* @__PURE__ */ jsxDEV15(VirtualActionList, {
1943
+ /* @__PURE__ */ jsxDEV15(ActionList, {
1926
1944
  ...virtualListProps,
1927
1945
  style: {
1928
1946
  overflowY: "auto",
@@ -1952,53 +1970,56 @@ function NiceActionDevtools_Panel({
1952
1970
  }, undefined, true, undefined, this)
1953
1971
  }, undefined, false, undefined, this);
1954
1972
  }
1955
- function VirtualActionList({
1973
+ function getFlatItemKey(item) {
1974
+ const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
1975
+ if (item.type === "group")
1976
+ return `g:${oldestCuid}`;
1977
+ if (item.type === "sub")
1978
+ return `s:${item.entry.cuid}`;
1979
+ return `c:${item.position}:${oldestCuid}`;
1980
+ }
1981
+ function ActionList({
1956
1982
  groups,
1957
1983
  selectedCuid,
1958
1984
  expandedGroupCuids,
1959
1985
  onGroupClick,
1960
1986
  onSubClick,
1987
+ onExpandGroup,
1961
1988
  childExternalLabelsMap,
1962
1989
  style
1963
1990
  }) {
1964
- const outerRef = useRef2(null);
1991
+ const containerRef = useRef2(null);
1965
1992
  const latestTime = groups[0]?.representative.startTime;
1966
1993
  const flatItems = useMemo2(() => {
1967
1994
  const result = [];
1968
1995
  for (let gi = 0;gi < groups.length; gi++) {
1969
1996
  const group = groups[gi];
1970
1997
  const repCuid = group.representative.cuid;
1971
- const isExpanded = expandedGroupCuids.has(repCuid) || group.rest.some((e) => e.cuid === selectedCuid);
1998
+ const allInGroup = [group.representative, ...group.rest];
1999
+ const selectedIdx = allInGroup.findIndex((e) => e.cuid === selectedCuid);
1972
2000
  result.push({ type: "group", group, groupIndex: gi });
1973
- if (isExpanded) {
1974
- for (const entry of group.rest) {
1975
- result.push({ type: "sub", entry, group });
2001
+ const oldestCuid = (group.rest[group.rest.length - 1] ?? group.representative).cuid;
2002
+ if (selectedIdx > 0) {
2003
+ const aboveCount = selectedIdx;
2004
+ const belowCount = allInGroup.length - selectedIdx - 1;
2005
+ if (aboveCount > 0)
2006
+ result.push({ type: "group-count", count: aboveCount, position: "above", group });
2007
+ result.push({ type: "sub", entry: allInGroup[selectedIdx], group });
2008
+ if (belowCount > 0)
2009
+ result.push({ type: "group-count", count: belowCount, position: "below", group });
2010
+ } else if (selectedIdx === 0 && group.rest.length > 0) {
2011
+ result.push({ type: "group-count", count: group.rest.length, position: "below", group });
2012
+ } else {
2013
+ const isExpanded = expandedGroupCuids.has(repCuid) || expandedGroupCuids.has(oldestCuid);
2014
+ if (isExpanded) {
2015
+ for (const entry of group.rest) {
2016
+ result.push({ type: "sub", entry, group });
2017
+ }
1976
2018
  }
1977
2019
  }
1978
2020
  }
1979
2021
  return result;
1980
2022
  }, [groups, expandedGroupCuids, selectedCuid]);
1981
- const flatItemsRef = useRef2(flatItems);
1982
- flatItemsRef.current = flatItems;
1983
- const virtualizer = useVirtualizer({
1984
- count: flatItems.length,
1985
- getScrollElement: () => outerRef.current,
1986
- estimateSize: (i) => flatItemsRef.current[i]?.type === "sub" ? SUB_ROW_HEIGHT : ROW_HEIGHT,
1987
- overscan: 5,
1988
- measureElement: (el) => el.getBoundingClientRect().height
1989
- });
1990
- const prevGroupLenRef = useRef2(groups.length);
1991
- useLayoutEffect(() => {
1992
- const el = outerRef.current;
1993
- if (el == null)
1994
- return;
1995
- const prev = prevGroupLenRef.current;
1996
- prevGroupLenRef.current = groups.length;
1997
- const added = groups.length - prev;
1998
- if (added > 0 && el.scrollTop > 10) {
1999
- el.scrollTop += added * ROW_HEIGHT;
2000
- }
2001
- }, [groups]);
2002
2023
  const prevSelectedRef = useRef2(selectedCuid);
2003
2024
  useEffect2(() => {
2004
2025
  if (selectedCuid === prevSelectedRef.current)
@@ -2006,10 +2027,8 @@ function VirtualActionList({
2006
2027
  prevSelectedRef.current = selectedCuid;
2007
2028
  if (selectedCuid == null)
2008
2029
  return;
2009
- const idx = flatItemsRef.current.findIndex((item) => item.type === "group" && (item.group.representative.cuid === selectedCuid || item.group.rest.some((e) => e.cuid === selectedCuid)) || item.type === "sub" && item.entry.cuid === selectedCuid);
2010
- if (idx >= 0)
2011
- virtualizer.scrollToIndex(idx, { align: "auto" });
2012
- }, [selectedCuid, virtualizer]);
2030
+ containerRef.current?.querySelector(`[data-cuid="${selectedCuid}"]`)?.scrollIntoView({ block: "nearest" });
2031
+ }, [selectedCuid]);
2013
2032
  if (groups.length === 0) {
2014
2033
  return /* @__PURE__ */ jsxDEV15("div", {
2015
2034
  style,
@@ -2019,28 +2038,25 @@ function VirtualActionList({
2019
2038
  }, undefined, false, undefined, this)
2020
2039
  }, undefined, false, undefined, this);
2021
2040
  }
2022
- const virtualItems = virtualizer.getVirtualItems();
2023
2041
  return /* @__PURE__ */ jsxDEV15("div", {
2024
- ref: outerRef,
2042
+ ref: containerRef,
2025
2043
  style,
2026
- children: /* @__PURE__ */ jsxDEV15("div", {
2027
- style: { height: `${virtualizer.getTotalSize()}px`, position: "relative" },
2028
- children: virtualItems.map((vi) => {
2029
- const item = flatItems[vi.index];
2030
- if (item == null)
2031
- return null;
2032
- return /* @__PURE__ */ jsxDEV15("div", {
2033
- "data-index": vi.index,
2034
- ref: virtualizer.measureElement,
2035
- style: {
2036
- position: "absolute",
2037
- top: 0,
2038
- left: 0,
2039
- width: "100%",
2040
- transform: `translateY(${vi.start}px)`,
2041
- borderBottom: "1px solid #101109"
2042
- },
2043
- children: item.type === "group" ? /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
2044
+ children: flatItems.map((item) => {
2045
+ const key = getFlatItemKey(item);
2046
+ return /* @__PURE__ */ jsxDEV15("div", {
2047
+ "data-cuid": item.type === "group" ? item.group.representative.cuid : item.type === "sub" ? item.entry.cuid : undefined,
2048
+ style: { borderBottom: "1px solid #101109", position: "relative", overflow: "hidden" },
2049
+ children: [
2050
+ item.type === "group" && /* @__PURE__ */ jsxDEV15("div", {
2051
+ style: {
2052
+ position: "absolute",
2053
+ inset: 0,
2054
+ pointerEvents: "none",
2055
+ background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
2056
+ animation: "__nice-action-shine 0.65s ease-out forwards"
2057
+ }
2058
+ }, item.group.representative.cuid, false, undefined, this),
2059
+ item.type === "group" ? /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
2044
2060
  entry: item.group.representative,
2045
2061
  isSelected: selectedCuid === item.group.representative.cuid,
2046
2062
  groupCount: item.group.rest.length > 0 ? item.group.rest.length + 1 : undefined,
@@ -2048,7 +2064,34 @@ function VirtualActionList({
2048
2064
  latestTime,
2049
2065
  childExternalLabels: childExternalLabelsMap.get(item.group.representative.cuid),
2050
2066
  onClick: () => onGroupClick(item.group)
2051
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
2067
+ }, undefined, false, undefined, this) : item.type === "group-count" ? /* @__PURE__ */ jsxDEV15("div", {
2068
+ onClick: () => onExpandGroup(item.group),
2069
+ style: {
2070
+ padding: "2px 28px",
2071
+ fontSize: "10px",
2072
+ color: "#475569",
2073
+ display: "flex",
2074
+ alignItems: "center",
2075
+ gap: "5px",
2076
+ background: "#0a1120",
2077
+ cursor: "pointer",
2078
+ userSelect: "none"
2079
+ },
2080
+ children: [
2081
+ /* @__PURE__ */ jsxDEV15("span", {
2082
+ style: { opacity: 0.6 },
2083
+ children: item.position === "above" ? "↑" : "↓"
2084
+ }, undefined, false, undefined, this),
2085
+ /* @__PURE__ */ jsxDEV15("span", {
2086
+ children: [
2087
+ item.count,
2088
+ " ",
2089
+ item.position === "above" ? "newer" : "older",
2090
+ " — click to browse"
2091
+ ]
2092
+ }, undefined, true, undefined, this)
2093
+ ]
2094
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
2052
2095
  entry: item.entry,
2053
2096
  isSelected: selectedCuid === item.entry.cuid,
2054
2097
  isSubEntry: true,
@@ -2056,9 +2099,9 @@ function VirtualActionList({
2056
2099
  latestTime,
2057
2100
  onClick: () => onSubClick(item.entry.cuid, selectedCuid === item.entry.cuid)
2058
2101
  }, undefined, false, undefined, this)
2059
- }, vi.key, false, undefined, this);
2060
- })
2061
- }, undefined, false, undefined, this)
2102
+ ]
2103
+ }, key, true, undefined, this);
2104
+ })
2062
2105
  }, undefined, false, undefined, this);
2063
2106
  }
2064
2107
  export {
@@ -7,7 +7,8 @@ export declare function DomainHierarchyTooltip({ allDomains, anchor, }: {
7
7
  allDomains: string[];
8
8
  anchor: DOMRect;
9
9
  }): import("react/jsx-runtime").JSX.Element;
10
- export declare function DomainChip({ domain, allDomains, size, }: {
10
+ export declare function DomainChip({ subtle, domain, allDomains, size, }: {
11
+ subtle?: boolean;
11
12
  domain: string;
12
13
  allDomains?: string[];
13
14
  size: "sm" | "md";
@@ -3,8 +3,6 @@ export declare function getExternalLabel(hop: IDevtoolsRouteItem): string | null
3
3
  interface IHandlerChipsProps {
4
4
  entry: IDevtoolsActionEntry;
5
5
  size: "sm" | "md";
6
- /** Show the local runtime chip even when an external chip is also present */
7
- alwaysShowLocal?: boolean;
8
6
  }
9
- export declare function HandlerChips({ entry, size, alwaysShowLocal }: IHandlerChipsProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function HandlerChips({ entry, size }: IHandlerChipsProps): import("react/jsx-runtime").JSX.Element;
10
8
  export {};
@@ -0,0 +1,4 @@
1
+ export declare const DEVTOOL_COLOR_HANDLER_LOCAL_TEXT = "#34bb89";
2
+ export declare const DEVTOOL_COLOR_HANDLER_LOCAL_BORDER = "#144427";
3
+ export declare const DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT = "#cfa12a";
4
+ export declare const DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER = "#723917";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice-code/action",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,8 +44,8 @@
44
44
  "build-types": "tsc --project tsconfig.build.json"
45
45
  },
46
46
  "dependencies": {
47
- "@nice-code/common-errors": "0.2.13",
48
- "@nice-code/error": "0.2.13",
47
+ "@nice-code/common-errors": "0.2.14",
48
+ "@nice-code/error": "0.2.14",
49
49
  "@standard-schema/spec": "^1.1.0",
50
50
  "@tanstack/react-virtual": "^3.13.26",
51
51
  "http-status-codes": "^2.3.0",