@bitovi/vybit 0.12.0 → 0.13.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.
@@ -44,11 +44,6 @@
44
44
  function sendTo(role, data) {
45
45
  send({ ...data, to: role });
46
46
  }
47
- window.addEventListener("message", (event) => {
48
- if (event.data?.type === "STORYBOOK_STORY_RENDERED") {
49
- send({ type: "RESET_SELECTION" });
50
- }
51
- });
52
47
 
53
48
  // overlay/src/context.ts
54
49
  function buildContext(target, oldClass, newClass, originalClassMap) {
@@ -686,6 +681,73 @@ ${pad}</${tag}>`;
686
681
  }
687
682
  .msg-send svg { width: 12px; height: 12px; }
688
683
 
684
+ /* \u2500\u2500 Mic button (voice messages) \u2500\u2500 */
685
+ .mic-btn {
686
+ width: 24px;
687
+ height: 24px;
688
+ border-radius: 5px;
689
+ border: none;
690
+ background: transparent;
691
+ color: #888;
692
+ display: flex;
693
+ align-items: center;
694
+ justify-content: center;
695
+ cursor: pointer;
696
+ flex-shrink: 0;
697
+ transition: all 120ms ease-out;
698
+ padding: 0;
699
+ }
700
+ .mic-btn:hover { color: #e5e5e5; background: rgba(255,255,255,0.06); }
701
+ .mic-btn svg { width: 13px; height: 13px; }
702
+ .mic-btn.listening {
703
+ background: #F5532D;
704
+ color: white;
705
+ animation: mic-pulse 1.5s ease-in-out infinite;
706
+ }
707
+ .mic-btn.error { color: #F5532D; }
708
+ @keyframes mic-pulse {
709
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(245, 83, 45, 0.4); }
710
+ 50% { box-shadow: 0 0 0 4px rgba(245, 83, 45, 0); }
711
+ }
712
+ /* \u2500\u2500 Mic-blocked banner \u2500\u2500 */
713
+ .mic-banner {
714
+ position: fixed;
715
+ top: 0;
716
+ left: 0;
717
+ right: 0;
718
+ z-index: 9999999;
719
+ display: flex;
720
+ align-items: center;
721
+ justify-content: center;
722
+ gap: 12px;
723
+ padding: 10px 16px;
724
+ background: #F5532D;
725
+ color: white;
726
+ font-family: 'Inter', system-ui, sans-serif;
727
+ font-size: 13px;
728
+ font-weight: 500;
729
+ box-shadow: 0 2px 12px rgba(0,0,0,0.3);
730
+ opacity: 0;
731
+ transform: translateY(-100%);
732
+ transition: opacity 0.25s ease-out, transform 0.25s ease-out;
733
+ }
734
+ .mic-banner.visible {
735
+ opacity: 1;
736
+ transform: translateY(0);
737
+ }
738
+ .mic-banner-dismiss {
739
+ background: none;
740
+ border: none;
741
+ color: white;
742
+ font-size: 18px;
743
+ cursor: pointer;
744
+ padding: 0 4px;
745
+ line-height: 1;
746
+ opacity: 0.8;
747
+ flex-shrink: 0;
748
+ }
749
+ .mic-banner-dismiss:hover { opacity: 1; }
750
+
689
751
  /* \u2500\u2500 Text editing action bar \u2500\u2500 */
690
752
  .text-action-bar {
691
753
  position: fixed;
@@ -1524,6 +1586,9 @@ ${pad}</${tag}>`;
1524
1586
  bottom: "top",
1525
1587
  top: "bottom"
1526
1588
  };
1589
+ function clamp(start, value, end) {
1590
+ return max(start, min(value, end));
1591
+ }
1527
1592
  function evaluate(value, param) {
1528
1593
  return typeof value === "function" ? value(param) : value;
1529
1594
  }
@@ -2011,6 +2076,79 @@ ${pad}</${tag}>`;
2011
2076
  }
2012
2077
  };
2013
2078
  };
2079
+ var shift = function(options) {
2080
+ if (options === void 0) {
2081
+ options = {};
2082
+ }
2083
+ return {
2084
+ name: "shift",
2085
+ options,
2086
+ async fn(state2) {
2087
+ const {
2088
+ x,
2089
+ y,
2090
+ placement,
2091
+ platform: platform2
2092
+ } = state2;
2093
+ const {
2094
+ mainAxis: checkMainAxis = true,
2095
+ crossAxis: checkCrossAxis = false,
2096
+ limiter = {
2097
+ fn: (_ref) => {
2098
+ let {
2099
+ x: x2,
2100
+ y: y2
2101
+ } = _ref;
2102
+ return {
2103
+ x: x2,
2104
+ y: y2
2105
+ };
2106
+ }
2107
+ },
2108
+ ...detectOverflowOptions
2109
+ } = evaluate(options, state2);
2110
+ const coords = {
2111
+ x,
2112
+ y
2113
+ };
2114
+ const overflow = await platform2.detectOverflow(state2, detectOverflowOptions);
2115
+ const crossAxis = getSideAxis(getSide(placement));
2116
+ const mainAxis = getOppositeAxis(crossAxis);
2117
+ let mainAxisCoord = coords[mainAxis];
2118
+ let crossAxisCoord = coords[crossAxis];
2119
+ if (checkMainAxis) {
2120
+ const minSide = mainAxis === "y" ? "top" : "left";
2121
+ const maxSide = mainAxis === "y" ? "bottom" : "right";
2122
+ const min2 = mainAxisCoord + overflow[minSide];
2123
+ const max2 = mainAxisCoord - overflow[maxSide];
2124
+ mainAxisCoord = clamp(min2, mainAxisCoord, max2);
2125
+ }
2126
+ if (checkCrossAxis) {
2127
+ const minSide = crossAxis === "y" ? "top" : "left";
2128
+ const maxSide = crossAxis === "y" ? "bottom" : "right";
2129
+ const min2 = crossAxisCoord + overflow[minSide];
2130
+ const max2 = crossAxisCoord - overflow[maxSide];
2131
+ crossAxisCoord = clamp(min2, crossAxisCoord, max2);
2132
+ }
2133
+ const limitedCoords = limiter.fn({
2134
+ ...state2,
2135
+ [mainAxis]: mainAxisCoord,
2136
+ [crossAxis]: crossAxisCoord
2137
+ });
2138
+ return {
2139
+ ...limitedCoords,
2140
+ data: {
2141
+ x: limitedCoords.x - x,
2142
+ y: limitedCoords.y - y,
2143
+ enabled: {
2144
+ [mainAxis]: checkMainAxis,
2145
+ [crossAxis]: checkCrossAxis
2146
+ }
2147
+ }
2148
+ };
2149
+ }
2150
+ };
2151
+ };
2014
2152
 
2015
2153
  // node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
2016
2154
  function hasWindow() {
@@ -2761,6 +2899,7 @@ ${pad}</${tag}>`;
2761
2899
  };
2762
2900
  }
2763
2901
  var offset2 = offset;
2902
+ var shift2 = shift;
2764
2903
  var flip2 = flip;
2765
2904
  var computePosition2 = (reference, floating, options) => {
2766
2905
  const cache2 = /* @__PURE__ */ new Map();
@@ -3239,6 +3378,117 @@ ${pad}</${tag}>`;
3239
3378
  }
3240
3379
  };
3241
3380
 
3381
+ // overlay/src/angular-detect.ts
3382
+ function getNgApi() {
3383
+ const ng = window.ng;
3384
+ if (ng?.getComponent && ng?.getOwningComponent) return ng;
3385
+ return null;
3386
+ }
3387
+ function isAngularElement(el) {
3388
+ if ("__ngContext__" in el) return true;
3389
+ return Array.from(el.attributes).some(
3390
+ (a) => a.name.startsWith("_nghost-") || a.name.startsWith("_ngcontent-")
3391
+ );
3392
+ }
3393
+ function findAngularComponentBoundary(el) {
3394
+ const ng = getNgApi();
3395
+ if (ng) {
3396
+ const component = ng.getComponent(el) ?? ng.getOwningComponent(el);
3397
+ if (component) {
3398
+ const raw = component.constructor?.name || "Unknown";
3399
+ const name = raw.replace(/^_+/, "");
3400
+ return {
3401
+ componentType: component.constructor,
3402
+ componentName: name,
3403
+ componentFiber: component
3404
+ // reuse field for the component instance
3405
+ };
3406
+ }
3407
+ }
3408
+ const hostAttr = findAttrStartingWith(el, "_nghost-");
3409
+ if (hostAttr) {
3410
+ return {
3411
+ componentType: el.tagName.toLowerCase(),
3412
+ componentName: formatTagAsComponentName(el.tagName),
3413
+ componentFiber: el
3414
+ };
3415
+ }
3416
+ const contentAttr = findAttrStartingWith(el, "_ngcontent-");
3417
+ if (contentAttr) {
3418
+ const suffix = contentAttr.name.replace("_ngcontent-", "");
3419
+ const host = el.closest(`[_nghost-${suffix}]`);
3420
+ if (host) {
3421
+ return {
3422
+ componentType: host.tagName.toLowerCase(),
3423
+ componentName: formatTagAsComponentName(host.tagName),
3424
+ componentFiber: host
3425
+ };
3426
+ }
3427
+ }
3428
+ return null;
3429
+ }
3430
+ function findAllAngularInstances(tagOrType) {
3431
+ const ng = getNgApi();
3432
+ if (ng && typeof tagOrType === "function") {
3433
+ const sampleEl = document.querySelector(tagOrType.\u0275cmp?.selectors?.[0]?.[0] ?? "");
3434
+ if (!sampleEl) {
3435
+ return findAllAngularInstancesByClass(ng, tagOrType);
3436
+ }
3437
+ return Array.from(document.querySelectorAll(sampleEl.tagName.toLowerCase()));
3438
+ }
3439
+ if (typeof tagOrType === "string") {
3440
+ return Array.from(document.querySelectorAll(tagOrType));
3441
+ }
3442
+ return [];
3443
+ }
3444
+ function findAllAngularInstancesByClass(ng, componentClass) {
3445
+ const results = [];
3446
+ const allCustomElements = document.querySelectorAll("*");
3447
+ for (const el of allCustomElements) {
3448
+ const comp = ng.getComponent(el);
3449
+ if (comp instanceof componentClass) {
3450
+ results.push(el);
3451
+ }
3452
+ }
3453
+ return results;
3454
+ }
3455
+ function collectAngularComponentDOMNodes(hostEl, tagName) {
3456
+ const hostAttr = findAttrStartingWith(hostEl, "_nghost-");
3457
+ if (!hostAttr) {
3458
+ return Array.from(hostEl.querySelectorAll(tagName.toLowerCase()));
3459
+ }
3460
+ const suffix = hostAttr.name.replace("_nghost-", "");
3461
+ return Array.from(
3462
+ document.querySelectorAll(
3463
+ `${tagName.toLowerCase()}[_ngcontent-${suffix}]`
3464
+ )
3465
+ );
3466
+ }
3467
+ function findAttrStartingWith(el, prefix) {
3468
+ return Array.from(el.attributes).find((a) => a.name.startsWith(prefix)) ?? null;
3469
+ }
3470
+ function formatTagAsComponentName(tagName) {
3471
+ const lower = tagName.toLowerCase();
3472
+ const stripped = lower.replace(/^app-/, "");
3473
+ const pascal = stripped.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
3474
+ return pascal + "Component";
3475
+ }
3476
+
3477
+ // overlay/src/framework-detect.ts
3478
+ var cachedFramework = null;
3479
+ function detectComponent(el) {
3480
+ const fiber = getFiber(el);
3481
+ if (fiber) {
3482
+ cachedFramework = "react";
3483
+ return findComponentBoundary(fiber);
3484
+ }
3485
+ if (isAngularElement(el)) {
3486
+ cachedFramework = "angular";
3487
+ return findAngularComponentBoundary(el);
3488
+ }
3489
+ return null;
3490
+ }
3491
+
3242
3492
  // overlay/src/design-canvas/vb-design-canvas.ts
3243
3493
  var VbDesignCanvas = class extends HTMLElement {
3244
3494
  static observedAttributes = ["src", "width", "height", "min-height"];
@@ -3286,6 +3536,7 @@ ${pad}</${tag}>`;
3286
3536
  this.iframe.allow = "microphone";
3287
3537
  this.iframe.style.cssText = css(DESIGN_CANVAS_IFRAME);
3288
3538
  this.iframe.addEventListener("load", () => {
3539
+ console.log("[tw-debug] vb-design-canvas iframe load event fired, src=", this.iframe.src);
3289
3540
  this.dispatchEvent(new CustomEvent("vb-canvas-ready", {
3290
3541
  bubbles: true,
3291
3542
  detail: { iframe: this.iframe }
@@ -3338,7 +3589,9 @@ ${pad}</${tag}>`;
3338
3589
  /** Sync observed attributes to internal DOM. */
3339
3590
  syncAttributes() {
3340
3591
  const src = this.getAttribute("src");
3592
+ console.log("[tw-debug] vb-design-canvas syncAttributes, src=", src, "current iframe.src=", this.iframe.src);
3341
3593
  if (src && this.iframe.src !== src) {
3594
+ console.log("[tw-debug] vb-design-canvas setting iframe.src =", src);
3342
3595
  this.iframe.src = src;
3343
3596
  }
3344
3597
  const w = this.getAttribute("width");
@@ -3379,6 +3632,7 @@ ${pad}</${tag}>`;
3379
3632
  var TEXT_SVG = `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M14.895,2.553l-1-2c-.169-.339-.516-.553-.895-.553H3c-.379,0-.725,.214-.895,.553L1.105,2.553c-.247,.494-.047,1.095,.447,1.342,.496,.248,1.095,.046,1.342-.447l.724-1.447h3.382V14h-2c-.552,0-1,.448-1,1s.448,1,1,1h6c.552,0,1-.448,1-1s-.448-1-1-1h-2V2h3.382l.724,1.447c.175,.351,.528,.553,.896,.553,.15,0,.303-.034,.446-.105,.494-.247,.694-.848,.447-1.342Z"/></svg>`;
3380
3633
  var REPLACE_SVG = `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M6,15H1a1,1,0,0,1-1-1V2A1,1,0,0,1,1,1H6A1,1,0,0,1,7,2V14A1,1,0,0,1,6,15Z"/><rect x="9" y="6" width="2" height="4"/><path d="M14,13H11V12H9v2a1,1,0,0,0,1,1h5a1,1,0,0,0,1-1V12H14Z"/><path d="M15,1H10A1,1,0,0,0,9,2V4h2V3h3V4h2V2A1,1,0,0,0,15,1Z"/><rect x="14" y="6" width="2" height="4"/></svg>`;
3381
3634
  var SEND_SVG = `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M15.7,7.3l-14-7C1.4,0.1,1.1,0.1,0.8,0.3C0.6,0.4,0.5,0.7,0.5,1l1.8,6H9v2H2.3L0.5,15c-0.1,0.3,0,0.6,0.2,0.7C0.8,15.9,1,16,1.1,16c0.1,0,0.3,0,0.4-0.1l14-7C15.8,8.7,16,8.4,16,8S15.8,7.3,15.7,7.3z"/></svg>`;
3635
+ var MIC_SVG = `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 1a4 4 0 0 1 4 4v7a4 4 0 0 1-8 0V5a4 4 0 0 1 4-4zm-1.5 4v7a1.5 1.5 0 0 0 3 0V5a1.5 1.5 0 0 0-3 0zM6 11a1 1 0 0 1 1 1 5 5 0 0 0 10 0 1 1 0 1 1 2 0 7 7 0 0 1-6 6.93V21h2a1 1 0 1 1 0 2H9a1 1 0 1 1 0-2h2v-2.07A7 7 0 0 1 5 12a1 1 0 0 1 1-1z"/></svg>`;
3382
3636
  var VYBIT_LOGO_SVG = `<svg width="26" height="27" viewBox="0 0 210 221" fill="none" xmlns="http://www.w3.org/2000/svg">
3383
3637
  <path class="eb-fill" d="M141.54 137.71L103.87 140.38C102.98 140.44 102.2 140.97 101.8 141.77C101.41 142.57 101.47 143.51 101.96 144.25C102.27 144.72 109.46 155.39 121.96 155.39C122.3 155.39 122.65 155.39 123 155.37C138.61 154.64 143.83 141.66 144.05 141.11C144.36 140.31 144.24 139.41 143.73 138.72C143.22 138.03 142.4 137.65 141.54 137.71Z"/>
3384
3638
  <path class="eb-eye-l eb-fill" d="M80.6401 93.03C76.7801 93.22 73.8 96.5 73.99 100.36L74.7501 115.96C74.9401 119.85 78.2701 122.84 82.1501 122.61C85.9801 122.38 88.9101 119.11 88.7301 115.28L87.9701 99.68C87.7801 95.82 84.5001 92.84 80.6401 93.03Z"/>
@@ -3422,13 +3676,23 @@ ${pad}</${tag}>`;
3422
3676
  function findExactMatches(clickedEl, shadowHost) {
3423
3677
  const classes = parseClassList(typeof clickedEl.className === "string" ? clickedEl.className : "");
3424
3678
  const tag = clickedEl.tagName;
3425
- const fiber = getFiber(clickedEl);
3426
- const boundary = fiber ? findComponentBoundary(fiber) : null;
3679
+ const boundary = detectComponent(clickedEl);
3427
3680
  const componentName = boundary?.componentName ?? null;
3681
+ const fiber = getFiber(clickedEl);
3682
+ const reactBoundary = fiber ? findComponentBoundary(fiber) : null;
3428
3683
  let exactMatches;
3429
- if (boundary) {
3430
- const rootFiber = getRootFiberFrom(boundary.componentFiber) ?? getRootFiber();
3431
- const allNodes = rootFiber ? collectComponentDOMNodes(rootFiber, boundary.componentType, tag) : [];
3684
+ if (reactBoundary) {
3685
+ const rootFiber = getRootFiberFrom(reactBoundary.componentFiber) ?? getRootFiber();
3686
+ const allNodes = rootFiber ? collectComponentDOMNodes(rootFiber, reactBoundary.componentType, tag) : [];
3687
+ exactMatches = allNodes.filter(
3688
+ (n) => n.tagName === tag && n.className === clickedEl.className
3689
+ );
3690
+ } else if (boundary && isAngularElement(clickedEl)) {
3691
+ const instances = findAllAngularInstances(boundary.componentType);
3692
+ const allNodes = [];
3693
+ for (const host of instances) {
3694
+ allNodes.push(...collectAngularComponentDOMNodes(host, tag));
3695
+ }
3432
3696
  exactMatches = allNodes.filter(
3433
3697
  (n) => n.tagName === tag && n.className === clickedEl.className
3434
3698
  );
@@ -3464,14 +3728,23 @@ ${pad}</${tag}>`;
3464
3728
  const tag = clickedEl.tagName;
3465
3729
  const refSet = new Set(classes);
3466
3730
  if (classes.length === 0) return [];
3731
+ const boundary = detectComponent(clickedEl);
3467
3732
  const fiber = getFiber(clickedEl);
3468
- const boundary = fiber ? findComponentBoundary(fiber) : null;
3733
+ const reactBoundary = fiber ? findComponentBoundary(fiber) : null;
3469
3734
  let candidates;
3470
- if (boundary) {
3471
- const rootFiber = getRootFiberFrom(boundary.componentFiber) ?? getRootFiber();
3472
- candidates = rootFiber ? collectComponentDOMNodes(rootFiber, boundary.componentType, tag) : [];
3735
+ if (reactBoundary) {
3736
+ const rootFiber = getRootFiberFrom(reactBoundary.componentFiber) ?? getRootFiber();
3737
+ candidates = rootFiber ? collectComponentDOMNodes(rootFiber, reactBoundary.componentType, tag) : [];
3473
3738
  candidates = candidates.filter((n) => !exactMatchSet.has(n));
3474
- console.log("[grouping] React path \u2014 component:", boundary.componentName, "tag:", tag, "candidates:", candidates.length, candidates.map((n) => n.className.split(" ")[0]));
3739
+ console.log("[grouping] React path \u2014 component:", reactBoundary.componentName, "tag:", tag, "candidates:", candidates.length, candidates.map((n) => n.className.split(" ")[0]));
3740
+ } else if (boundary && isAngularElement(clickedEl)) {
3741
+ const instances = findAllAngularInstances(boundary.componentType);
3742
+ const allNodes = [];
3743
+ for (const host of instances) {
3744
+ allNodes.push(...collectAngularComponentDOMNodes(host, tag));
3745
+ }
3746
+ candidates = allNodes.filter((n) => !exactMatchSet.has(n));
3747
+ console.log("[grouping] Angular path \u2014 component:", boundary.componentName, "tag:", tag, "candidates:", candidates.length);
3475
3748
  } else {
3476
3749
  const seen = new Set(exactMatchSet);
3477
3750
  candidates = [];
@@ -3544,21 +3817,42 @@ ${pad}</${tag}>`;
3544
3817
  }
3545
3818
  function findSamePathElements(clickedEl) {
3546
3819
  const fiber = getFiber(clickedEl);
3547
- if (!fiber) return null;
3548
- const boundary = findComponentBoundary(fiber);
3549
- if (!boundary) return null;
3550
- const { label, path } = buildPathLabel(fiber, boundary);
3551
- const rootFiber = getRootFiberFrom(boundary.componentFiber) ?? getRootFiber();
3552
- if (!rootFiber) return null;
3553
- const instances = findAllInstances(rootFiber, boundary.componentType);
3554
- const elements = [];
3555
- for (const inst of instances) {
3556
- const node = resolvePathToDOM(inst, path);
3557
- if (node && !elements.includes(node)) {
3558
- elements.push(node);
3820
+ if (fiber) {
3821
+ const boundary = findComponentBoundary(fiber);
3822
+ if (!boundary) return null;
3823
+ const { label, path } = buildPathLabel(fiber, boundary);
3824
+ const rootFiber = getRootFiberFrom(boundary.componentFiber) ?? getRootFiber();
3825
+ if (!rootFiber) return null;
3826
+ const instances = findAllInstances(rootFiber, boundary.componentType);
3827
+ const elements = [];
3828
+ for (const inst of instances) {
3829
+ const node = resolvePathToDOM(inst, path);
3830
+ if (node && !elements.includes(node)) {
3831
+ elements.push(node);
3832
+ }
3833
+ }
3834
+ return elements.length > 0 ? { elements, label } : null;
3835
+ }
3836
+ if (isAngularElement(clickedEl)) {
3837
+ const boundary = detectComponent(clickedEl);
3838
+ if (!boundary) return null;
3839
+ const instances = findAllAngularInstances(boundary.componentType);
3840
+ if (instances.length < 2) return null;
3841
+ const tag = clickedEl.tagName;
3842
+ const elements = [];
3843
+ for (const host of instances) {
3844
+ const nodes = collectAngularComponentDOMNodes(host, tag);
3845
+ const match = nodes.find(
3846
+ (n) => n.tagName === clickedEl.tagName && n.className === clickedEl.className
3847
+ );
3848
+ if (match && !elements.includes(match)) {
3849
+ elements.push(match);
3850
+ }
3559
3851
  }
3852
+ const label = `${boundary.componentName} > ${tag.toLowerCase()}`;
3853
+ return elements.length > 0 ? { elements, label } : null;
3560
3854
  }
3561
- return elements.length > 0 ? { elements, label } : null;
3855
+ return null;
3562
3856
  }
3563
3857
 
3564
3858
  // overlay/src/patcher.ts
@@ -3811,13 +4105,52 @@ ${pad}</${tag}>`;
3811
4105
  clearHoverPreview();
3812
4106
  return;
3813
4107
  }
3814
- const fiber = getFiber(target);
3815
- const boundary = fiber ? findComponentBoundary(fiber) : null;
4108
+ const boundary = detectComponent(target);
3816
4109
  const label = boundary?.componentName ?? target.tagName.toLowerCase();
3817
4110
  showHoverPreview(target, label);
3818
4111
  }
3819
4112
 
3820
4113
  // overlay/src/element-toolbar.ts
4114
+ var SpeechRecognitionAPI = typeof window !== "undefined" ? window.SpeechRecognition ?? window.webkitSpeechRecognition ?? null : null;
4115
+ var activeBanner = null;
4116
+ var bannerTimeout = null;
4117
+ function showMicBanner(message) {
4118
+ if (activeBanner) {
4119
+ activeBanner.remove();
4120
+ activeBanner = null;
4121
+ }
4122
+ if (bannerTimeout) {
4123
+ clearTimeout(bannerTimeout);
4124
+ bannerTimeout = null;
4125
+ }
4126
+ const banner = document.createElement("div");
4127
+ banner.className = "mic-banner";
4128
+ const text = document.createElement("span");
4129
+ text.textContent = message;
4130
+ banner.appendChild(text);
4131
+ const dismiss = document.createElement("button");
4132
+ dismiss.className = "mic-banner-dismiss";
4133
+ dismiss.textContent = "\xD7";
4134
+ dismiss.addEventListener("click", () => {
4135
+ banner.classList.remove("visible");
4136
+ setTimeout(() => banner.remove(), 250);
4137
+ activeBanner = null;
4138
+ if (bannerTimeout) {
4139
+ clearTimeout(bannerTimeout);
4140
+ bannerTimeout = null;
4141
+ }
4142
+ });
4143
+ banner.appendChild(dismiss);
4144
+ state.shadowRoot.appendChild(banner);
4145
+ activeBanner = banner;
4146
+ requestAnimationFrame(() => banner.classList.add("visible"));
4147
+ bannerTimeout = setTimeout(() => {
4148
+ banner.classList.remove("visible");
4149
+ setTimeout(() => banner.remove(), 250);
4150
+ activeBanner = null;
4151
+ bannerTimeout = null;
4152
+ }, 8e3);
4153
+ }
3821
4154
  var setSelectMode;
3822
4155
  var showToast;
3823
4156
  var onBrowseLocked;
@@ -3830,10 +4163,11 @@ ${pad}</${tag}>`;
3830
4163
  rebuildSelectionFromSources = deps2.rebuildSelectionFromSources;
3831
4164
  setAddMode = deps2.setAddMode;
3832
4165
  }
3833
- async function positionWithFlip(anchor, floating, placement = "top-start") {
4166
+ async function positionWithFlip(anchor, floating, placement = "top-start", options) {
4167
+ const middleware = options?.disableFlip ? [offset2(6)] : [offset2(6), flip2()];
3834
4168
  const { x, y, placement: resolved } = await computePosition2(anchor, floating, {
3835
4169
  placement,
3836
- middleware: [offset2(6), flip2()]
4170
+ middleware
3837
4171
  });
3838
4172
  floating.style.left = `${x}px`;
3839
4173
  floating.style.top = `${y}px`;
@@ -3844,9 +4178,9 @@ ${pad}</${tag}>`;
3844
4178
  if (!msgRow) return;
3845
4179
  const msgPlacement = await positionWithFlip(targetEl, msgRow, "bottom-start");
3846
4180
  if (toolbarPlacement === "bottom-start" && msgPlacement === "bottom-start") {
3847
- await positionWithFlip(toolbar, msgRow, "bottom-start");
4181
+ await positionWithFlip(toolbar, msgRow, "bottom-start", { disableFlip: true });
3848
4182
  } else if (toolbarPlacement === "top-start" && msgPlacement === "top-start") {
3849
- await positionWithFlip(toolbar, msgRow, "top-start");
4183
+ await positionWithFlip(toolbar, msgRow, "top-start", { disableFlip: true });
3850
4184
  }
3851
4185
  }
3852
4186
  function showDrawButton(targetEl) {
@@ -3878,10 +4212,8 @@ ${pad}</${tag}>`;
3878
4212
  state.cachedExactMatches = null;
3879
4213
  state.manuallyAddedNodes = /* @__PURE__ */ new Set();
3880
4214
  state.addMode = false;
3881
- state.currentMode = "select";
3882
- state.currentTab = resolveTab();
3883
- sendTo("panel", { type: "MODE_CHANGED", mode: "select" });
3884
- setSelectMode(true);
4215
+ setSelectMode(false);
4216
+ sendTo("panel", { type: "MODE_CHANGED", mode: null });
3885
4217
  });
3886
4218
  selectGroup.appendChild(selectBtn);
3887
4219
  const innerSep = document.createElement("div");
@@ -3950,6 +4282,7 @@ ${pad}</${tag}>`;
3950
4282
  clearLockedInsert();
3951
4283
  revertPreview();
3952
4284
  clearHighlights();
4285
+ setSelectMode(false);
3953
4286
  state.currentEquivalentNodes = [];
3954
4287
  state.currentTargetEl = null;
3955
4288
  state.currentBoundary = null;
@@ -3957,6 +4290,10 @@ ${pad}</${tag}>`;
3957
4290
  state.cachedExactMatches = null;
3958
4291
  state.manuallyAddedNodes = /* @__PURE__ */ new Set();
3959
4292
  state.addMode = false;
4293
+ if (state.currentMode === "insert") {
4294
+ sendTo("panel", { type: "MODE_CHANGED", mode: null });
4295
+ return;
4296
+ }
3960
4297
  state.currentMode = "insert";
3961
4298
  if (state.tabPreference === "design") state.tabPreference = "component";
3962
4299
  state.currentTab = resolveTab();
@@ -4008,20 +4345,79 @@ ${pad}</${tag}>`;
4008
4345
  placeBtn.innerHTML = `Place`;
4009
4346
  toolbar.appendChild(placeBtn);
4010
4347
  }
4348
+ let msgRow;
4349
+ msgRow = createMsgRow(state.currentBoundary, () => positionBothMenus(targetEl, toolbar, msgRow));
4350
+ state.shadowRoot.appendChild(msgRow);
4351
+ state.msgRowEl = msgRow;
4352
+ positionBothMenus(targetEl, toolbar, msgRow);
4353
+ }
4354
+ function getCanvasMessageText() {
4355
+ const textarea = canvasMsgRow?.querySelector("textarea");
4356
+ return textarea?.value.trim() ?? "";
4357
+ }
4358
+ function createMsgRow(boundary, onReposition, options) {
4359
+ const showSendButton = options?.showSendButton ?? true;
4011
4360
  const msgRow = document.createElement("div");
4012
4361
  msgRow.className = "msg-row";
4013
4362
  msgRow.style.left = "0px";
4014
4363
  msgRow.style.top = "0px";
4015
- state.shadowRoot.appendChild(msgRow);
4016
- state.msgRowEl = msgRow;
4017
4364
  const msgInput = document.createElement("textarea");
4018
4365
  msgInput.rows = 1;
4019
4366
  msgInput.placeholder = "add your message";
4020
4367
  msgRow.appendChild(msgInput);
4021
- const msgSendBtn = document.createElement("button");
4022
- msgSendBtn.className = "msg-send";
4023
- msgSendBtn.innerHTML = SEND_SVG;
4024
- msgRow.appendChild(msgSendBtn);
4368
+ let recognition = null;
4369
+ let micBtn = null;
4370
+ if (SpeechRecognitionAPI) {
4371
+ micBtn = document.createElement("button");
4372
+ micBtn.className = "mic-btn";
4373
+ micBtn.title = "Record voice message";
4374
+ micBtn.innerHTML = MIC_SVG;
4375
+ msgRow.appendChild(micBtn);
4376
+ micBtn.addEventListener("click", (e) => {
4377
+ e.stopPropagation();
4378
+ if (recognition) {
4379
+ recognition.stop();
4380
+ return;
4381
+ }
4382
+ const baseText = msgInput.value;
4383
+ recognition = new SpeechRecognitionAPI();
4384
+ recognition.continuous = false;
4385
+ recognition.interimResults = true;
4386
+ recognition.lang = navigator.language || "en-US";
4387
+ recognition.onresult = (event) => {
4388
+ let transcript = "";
4389
+ for (let i = 0; i < event.results.length; i++) {
4390
+ transcript += event.results[i][0].transcript;
4391
+ }
4392
+ const separator = baseText && !baseText.endsWith("\n") ? "\n" : "";
4393
+ msgInput.value = baseText + separator + transcript;
4394
+ msgInput.style.height = "auto";
4395
+ msgInput.style.height = msgInput.scrollHeight + "px";
4396
+ onReposition();
4397
+ };
4398
+ recognition.onend = () => {
4399
+ micBtn.classList.remove("listening");
4400
+ recognition = null;
4401
+ };
4402
+ recognition.onerror = (event) => {
4403
+ micBtn.classList.remove("listening");
4404
+ if (event.error === "not-allowed" || event.error === "service-not-allowed") {
4405
+ micBtn.classList.add("error");
4406
+ showMicBanner("Microphone blocked \u2014 allow access in your browser's address bar");
4407
+ }
4408
+ recognition = null;
4409
+ };
4410
+ micBtn.classList.remove("error");
4411
+ micBtn.classList.add("listening");
4412
+ recognition.start();
4413
+ });
4414
+ }
4415
+ const msgSendBtn = showSendButton ? document.createElement("button") : null;
4416
+ if (msgSendBtn) {
4417
+ msgSendBtn.className = "msg-send";
4418
+ msgSendBtn.innerHTML = SEND_SVG;
4419
+ msgRow.appendChild(msgSendBtn);
4420
+ }
4025
4421
  function sendMessage() {
4026
4422
  const text = msgInput.value.trim();
4027
4423
  if (!text) return;
@@ -4030,15 +4426,15 @@ ${pad}</${tag}>`;
4030
4426
  type: "MESSAGE_STAGE",
4031
4427
  id,
4032
4428
  message: text,
4033
- elementKey: state.currentBoundary?.componentName ?? "",
4034
- component: state.currentBoundary ? { name: state.currentBoundary.componentName } : void 0
4429
+ elementKey: boundary?.componentName ?? "",
4430
+ component: boundary ? { name: boundary.componentName } : void 0
4035
4431
  });
4036
4432
  msgInput.value = "";
4037
4433
  msgInput.style.height = "auto";
4038
- positionBothMenus(targetEl, toolbar, msgRow);
4434
+ onReposition();
4039
4435
  showToast("Message staged");
4040
4436
  }
4041
- msgSendBtn.addEventListener("click", (e) => {
4437
+ msgSendBtn?.addEventListener("click", (e) => {
4042
4438
  e.stopPropagation();
4043
4439
  sendMessage();
4044
4440
  });
@@ -4054,10 +4450,45 @@ ${pad}</${tag}>`;
4054
4450
  msgInput.addEventListener("input", () => {
4055
4451
  msgInput.style.height = "auto";
4056
4452
  msgInput.style.height = msgInput.scrollHeight + "px";
4057
- positionBothMenus(targetEl, toolbar, msgRow);
4453
+ onReposition();
4058
4454
  });
4059
4455
  msgRow.addEventListener("click", (e) => e.stopPropagation());
4060
- positionBothMenus(targetEl, toolbar, msgRow);
4456
+ return msgRow;
4457
+ }
4458
+ var canvasMsgRow = null;
4459
+ var canvasMsgRowObserver = null;
4460
+ function showCanvasMessageRow(canvasWrapper, boundary, shadowRoot) {
4461
+ hideCanvasMessageRow();
4462
+ const msgRow = createMsgRow(boundary, () => positionCanvasMsgRow(canvasWrapper, msgRow), { showSendButton: false });
4463
+ msgRow.setAttribute("data-canvas-anchor", "true");
4464
+ shadowRoot.appendChild(msgRow);
4465
+ canvasMsgRow = msgRow;
4466
+ positionCanvasMsgRow(canvasWrapper, msgRow);
4467
+ canvasMsgRowObserver = new ResizeObserver(() => {
4468
+ positionCanvasMsgRow(canvasWrapper, msgRow);
4469
+ });
4470
+ canvasMsgRowObserver.observe(canvasWrapper);
4471
+ }
4472
+ function hideCanvasMessageRow() {
4473
+ canvasMsgRowObserver?.disconnect();
4474
+ canvasMsgRowObserver = null;
4475
+ canvasMsgRow?.remove();
4476
+ canvasMsgRow = null;
4477
+ }
4478
+ function positionCanvasMsgRow(canvasWrapper, msgRow) {
4479
+ computePosition2(canvasWrapper, msgRow, {
4480
+ placement: "bottom-start",
4481
+ middleware: [
4482
+ shift2({ padding: 8 }),
4483
+ flip2()
4484
+ ]
4485
+ }).then(({ x, y }) => {
4486
+ Object.assign(msgRow.style, {
4487
+ position: "fixed",
4488
+ left: `${x}px`,
4489
+ top: `${y}px`
4490
+ });
4491
+ });
4061
4492
  }
4062
4493
  function showGroupPicker(anchorBtn, onClose, onCountChange) {
4063
4494
  if (state.pickerCloseHandler) {
@@ -5151,6 +5582,7 @@ ${pad}</${tag}>`;
5151
5582
  showToastFn = deps2.showToast;
5152
5583
  }
5153
5584
  function injectDesignCanvas(insertMode) {
5585
+ console.log("[tw-debug] injectDesignCanvas called, insertMode=", insertMode, "currentTargetEl=", state.currentTargetEl, "currentBoundary=", state.currentBoundary);
5154
5586
  if (!state.currentTargetEl || !state.currentBoundary) {
5155
5587
  showToastFn("Select an element first");
5156
5588
  return;
@@ -5158,7 +5590,9 @@ ${pad}</${tag}>`;
5158
5590
  clearHighlights();
5159
5591
  const targetEl = state.currentTargetEl;
5160
5592
  const canvas = document.createElement("vb-design-canvas");
5161
- canvas.setAttribute("src", `${serverOrigin}/panel/?mode=design`);
5593
+ const canvasSrc = `${serverOrigin}/panel/?mode=design`;
5594
+ console.log("[tw-debug] creating vb-design-canvas, src=", canvasSrc, "targetEl=", targetEl, "insertMode=", insertMode);
5595
+ canvas.setAttribute("src", canvasSrc);
5162
5596
  const wrapper = canvas.getWrapper();
5163
5597
  let replacedNodes = null;
5164
5598
  let replacedParent = null;
@@ -5193,7 +5627,10 @@ ${pad}</${tag}>`;
5193
5627
  parent: replacedParent,
5194
5628
  anchor: replacedAnchor
5195
5629
  });
5630
+ requestAnimationFrame(() => showCanvasMessageRow(canvas.getWrapper(), state.currentBoundary, state.shadowRoot));
5631
+ console.log("[tw-debug] canvas inserted into DOM, listening for vb-canvas-ready...");
5196
5632
  canvas.addEventListener("vb-canvas-ready", () => {
5633
+ console.log("[tw-debug] vb-canvas-ready fired!");
5197
5634
  const contextMsg = {
5198
5635
  type: "ELEMENT_CONTEXT",
5199
5636
  componentName: state.currentBoundary?.componentName ?? "",
@@ -5276,6 +5713,7 @@ ${pad}</${tag}>`;
5276
5713
  parent.insertBefore(canvas, marker);
5277
5714
  marker.remove();
5278
5715
  state.designCanvasWrappers.push({ wrapper: canvas, replacedNodes, parent, anchor: canvas.nextSibling });
5716
+ requestAnimationFrame(() => showCanvasMessageRow(canvas.getWrapper(), state.currentBoundary, state.shadowRoot));
5279
5717
  canvas.addEventListener("vb-canvas-ready", () => {
5280
5718
  const contextMsg = {
5281
5719
  type: "ELEMENT_CONTEXT",
@@ -5299,6 +5737,12 @@ ${pad}</${tag}>`;
5299
5737
  setTimeout(trySend, 200);
5300
5738
  });
5301
5739
  }
5740
+ function removeAllDesignCanvases() {
5741
+ for (const entry of state.designCanvasWrappers) {
5742
+ entry.wrapper.remove();
5743
+ }
5744
+ state.designCanvasWrappers.length = 0;
5745
+ }
5302
5746
  function handleDesignSubmitted(msg) {
5303
5747
  const lastEntry = state.designCanvasWrappers[state.designCanvasWrappers.length - 1];
5304
5748
  const last = lastEntry?.wrapper;
@@ -5315,6 +5759,11 @@ ${pad}</${tag}>`;
5315
5759
  last.appendChild(img);
5316
5760
  }
5317
5761
  }
5762
+ const messageText = getCanvasMessageText();
5763
+ if (messageText && msg.patchId) {
5764
+ send({ type: "CANVAS_MESSAGE_ATTACH", patchId: msg.patchId, message: messageText });
5765
+ }
5766
+ hideCanvasMessageRow();
5318
5767
  }
5319
5768
  function handleDesignClose() {
5320
5769
  const last = state.designCanvasWrappers.pop();
@@ -5326,6 +5775,7 @@ ${pad}</${tag}>`;
5326
5775
  }
5327
5776
  last.wrapper.remove();
5328
5777
  }
5778
+ hideCanvasMessageRow();
5329
5779
  }
5330
5780
 
5331
5781
  // overlay/src/recording/console-interceptor/console-interceptor.ts
@@ -6825,8 +7275,7 @@ ${pad}</${tag}>`;
6825
7275
  function onBrowseLocked2(target) {
6826
7276
  state.currentTargetEl = target;
6827
7277
  state.currentEquivalentNodes = [target];
6828
- const fiber = getFiber(target);
6829
- const boundary = fiber ? findComponentBoundary(fiber) : null;
7278
+ const boundary = detectComponent(target);
6830
7279
  state.currentBoundary = boundary ? { componentName: boundary.componentName } : { componentName: target.tagName.toLowerCase() };
6831
7280
  state.cachedNearGroups = null;
6832
7281
  showDrawButton(target);
@@ -7088,6 +7537,24 @@ ${pad}</${tag}>`;
7088
7537
  setTimeout(() => toast.remove(), 200);
7089
7538
  }, duration);
7090
7539
  }
7540
+ function resetOnNavigation() {
7541
+ if (isTextEditing()) endTextEdit(false);
7542
+ revertPreview();
7543
+ clearHighlights();
7544
+ cancelInsert();
7545
+ clearLockedInsert();
7546
+ removeAllDesignCanvases();
7547
+ state.currentEquivalentNodes = [];
7548
+ state.currentTargetEl = null;
7549
+ state.currentBoundary = null;
7550
+ state.cachedNearGroups = null;
7551
+ state.cachedExactMatches = null;
7552
+ state.manuallyAddedNodes = /* @__PURE__ */ new Set();
7553
+ state.addMode = false;
7554
+ setSelectMode2(false);
7555
+ sendTo("panel", { type: "RESET_SELECTION" });
7556
+ sendTo("panel", { type: "COMPONENT_DISARMED" });
7557
+ }
7091
7558
  function getDefaultContainer() {
7092
7559
  try {
7093
7560
  const stored = localStorage.getItem("tw-panel-container");
@@ -7099,6 +7566,8 @@ ${pad}</${tag}>`;
7099
7566
  return "popover";
7100
7567
  }
7101
7568
  function init() {
7569
+ const params = new URLSearchParams(location.search);
7570
+ if (params.get("viewMode") === "story" || params.get("vybit-ghost") === "1") return;
7102
7571
  state.shadowHost = document.createElement("div");
7103
7572
  state.shadowHost.id = "tw-visual-editor-host";
7104
7573
  state.shadowHost.style.cssText = css(SHADOW_HOST);
@@ -7125,6 +7594,16 @@ ${pad}</${tag}>`;
7125
7594
  btn.style.display = "none";
7126
7595
  }
7127
7596
  state.shadowRoot.appendChild(btn);
7597
+ createNavigationInterceptor(() => {
7598
+ if (state.active) resetOnNavigation();
7599
+ });
7600
+ window.addEventListener("message", (event) => {
7601
+ if (event.data?.type === "STORYBOOK_STORY_RENDERED") {
7602
+ if (state.active) {
7603
+ resetOnNavigation();
7604
+ }
7605
+ }
7606
+ });
7128
7607
  document.addEventListener("keydown", (e) => {
7129
7608
  if (e.key === "Escape") {
7130
7609
  if (state.addMode) {
@@ -7141,11 +7620,14 @@ ${pad}</${tag}>`;
7141
7620
  state.cachedExactMatches = null;
7142
7621
  state.manuallyAddedNodes = /* @__PURE__ */ new Set();
7143
7622
  state.addMode = false;
7144
- sendTo("panel", { type: "RESET_SELECTION" });
7145
7623
  if (state.currentMode === "select") {
7146
7624
  setSelectMode2(true);
7625
+ sendTo("panel", { type: "DESELECT_ELEMENT" });
7147
7626
  } else if (state.currentMode === "insert") {
7627
+ sendTo("panel", { type: "DESELECT_ELEMENT" });
7148
7628
  startBrowse(state.shadowHost, onBrowseLocked2);
7629
+ } else {
7630
+ sendTo("panel", { type: "RESET_SELECTION" });
7149
7631
  }
7150
7632
  } else if (state.selectModeOn) {
7151
7633
  setSelectMode2(false);
@@ -7162,6 +7644,8 @@ ${pad}</${tag}>`;
7162
7644
  onMessage((msg) => {
7163
7645
  if (msg.type === "TOGGLE_SELECT_MODE") {
7164
7646
  if (msg.active) {
7647
+ state.active = true;
7648
+ sessionStorage.setItem(PANEL_OPEN_KEY, "1");
7165
7649
  setSelectMode2(true);
7166
7650
  if (!insideStorybook) {
7167
7651
  const panelUrl = `${SERVER_ORIGIN}/panel`;
@@ -7171,6 +7655,10 @@ ${pad}</${tag}>`;
7171
7655
  setSelectMode2(false);
7172
7656
  }
7173
7657
  } else if (msg.type === "MODE_CHANGED") {
7658
+ if (msg.mode) {
7659
+ state.active = true;
7660
+ sessionStorage.setItem(PANEL_OPEN_KEY, "1");
7661
+ }
7174
7662
  revertPreview();
7175
7663
  clearHighlights();
7176
7664
  cancelInsert();
@@ -7181,6 +7669,7 @@ ${pad}</${tag}>`;
7181
7669
  state.cachedNearGroups = null;
7182
7670
  state.currentMode = msg.mode;
7183
7671
  if (msg.mode === "insert") {
7672
+ setSelectMode2(false);
7184
7673
  if (state.tabPreference === "design") state.tabPreference = "component";
7185
7674
  state.currentTab = resolveTab();
7186
7675
  startBrowse(state.shadowHost, onBrowseLocked2);
@@ -7295,22 +7784,36 @@ ${pad}</${tag}>`;
7295
7784
  }
7296
7785
  } else {
7297
7786
  const locked2 = getLockedInsert();
7787
+ console.log("[tw-debug] INSERT_DESIGN_CANVAS else branch, locked=", locked2, "currentTargetEl=", state.currentTargetEl);
7298
7788
  if (locked2) {
7299
7789
  state.currentTargetEl = locked2.target;
7300
- const fiber = getFiber(locked2.target);
7301
- const boundary = fiber ? findComponentBoundary(fiber) : null;
7790
+ const boundary = detectComponent(locked2.target);
7302
7791
  state.currentBoundary = boundary ? { componentName: boundary.componentName } : { componentName: locked2.target.tagName.toLowerCase() };
7303
7792
  state.currentEquivalentNodes = [locked2.target];
7304
7793
  clearLockedInsert();
7794
+ console.log("[tw-debug] locked path \u2014 calling injectDesignCanvas, position=", locked2.position, "boundary=", state.currentBoundary);
7305
7795
  injectDesignCanvas(locked2.position);
7306
7796
  } else {
7797
+ console.log("[tw-debug] arming generic insert...");
7307
7798
  armGenericInsert("Place: Canvas", state.shadowHost, (target, position) => {
7308
- state.currentTargetEl = target;
7309
- const fiber = getFiber(target);
7310
- const boundary = fiber ? findComponentBoundary(fiber) : null;
7311
- state.currentBoundary = boundary ? { componentName: boundary.componentName } : { componentName: target.tagName.toLowerCase() };
7312
- state.currentEquivalentNodes = [target];
7313
- injectDesignCanvas(position);
7799
+ console.log("[tw-debug] armGenericInsert callback fired, target=", target, "position=", position);
7800
+ try {
7801
+ console.log("[tw-debug] step 1: setting currentTargetEl");
7802
+ state.currentTargetEl = target;
7803
+ console.log("[tw-debug] step 2: calling detectComponent");
7804
+ const boundary = detectComponent(target);
7805
+ console.log("[tw-debug] step 3: boundary=", boundary);
7806
+ state.currentBoundary = boundary ? { componentName: boundary.componentName } : { componentName: target.tagName.toLowerCase() };
7807
+ state.currentEquivalentNodes = [target];
7808
+ console.log("[tw-debug] step 4: state set, currentBoundary=", state.currentBoundary, "\u2014 calling injectDesignCanvas");
7809
+ injectDesignCanvas(position);
7810
+ console.log("[tw-debug] injectDesignCanvas returned OK");
7811
+ } catch (err) {
7812
+ console.error("[tw-debug] CALLBACK THREW (this is the real error):", err);
7813
+ if (err instanceof Error) {
7814
+ console.error("[tw-debug] message:", err.message, "stack:", err.stack);
7815
+ }
7816
+ }
7314
7817
  });
7315
7818
  }
7316
7819
  }
@@ -7439,8 +7942,7 @@ ${pad}</${tag}>`;
7439
7942
  if (!target || target === state.shadowHost || e.composedPath().some((el) => el === state.shadowHost)) {
7440
7943
  return;
7441
7944
  }
7442
- const fiber = getFiber(target);
7443
- const boundary = fiber ? findComponentBoundary(fiber) : null;
7945
+ const boundary = detectComponent(target);
7444
7946
  const selectorPath = buildSelectorPath2(target);
7445
7947
  const rect = target.getBoundingClientRect();
7446
7948
  const element = {