react-grab 0.0.54 → 0.0.56

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.
@@ -550,12 +550,21 @@ function delegateEvents(eventNames, document2 = window.document) {
550
550
  }
551
551
  }
552
552
  function setAttribute(node, name, value) {
553
- node.removeAttribute(name);
553
+ if (value == null) node.removeAttribute(name);
554
+ else node.setAttribute(name, value);
554
555
  }
555
556
  function className(node, value) {
556
557
  if (value == null) node.removeAttribute("class");
557
558
  else node.className = value;
558
559
  }
560
+ function addEventListener(node, name, handler, delegate) {
561
+ {
562
+ if (Array.isArray(handler)) {
563
+ node[`$$${name}`] = handler[0];
564
+ node[`$$${name}Data`] = handler[1];
565
+ } else node[`$$${name}`] = handler;
566
+ }
567
+ }
559
568
  function style(node, value, prev) {
560
569
  if (!value) return prev ? setAttribute(node, "style") : value;
561
570
  const nodeStyle = node.style;
@@ -740,7 +749,7 @@ function cleanChildren(parent, current, marker, replacement) {
740
749
  }
741
750
 
742
751
  // dist/styles.css
743
- var styles_default = '/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--leading-tight:1.25;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-grab-pink:#b21c8e;--color-grab-pink-light:#fde7f7;--color-grab-pink-border:#f7c5ec;--color-grab-purple:#d239c0}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.top-0{top:calc(var(--spacing)*0)}.bottom-0{bottom:calc(var(--spacing)*0)}.left-0{left:calc(var(--spacing)*0)}.z-2147483645{z-index:2147483645}.z-2147483646{z-index:2147483646}.z-\\[2147483645\\]{z-index:2147483645}.mt-0\\.5{margin-top:calc(var(--spacing)*.5)}.mr-1{margin-right:calc(var(--spacing)*1)}.ml-1{margin-left:calc(var(--spacing)*1)}.box-border{box-sizing:border-box}.block{display:block}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.h-2{height:calc(var(--spacing)*2)}.min-h-\\[18px\\]{min-height:18px}.w-2{width:calc(var(--spacing)*2)}.w-\\[150px\\]{width:150px}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-crosshair{cursor:crosshair}.resize{resize:both}.resize-none{resize:none}.flex-col{flex-direction:column}.items-center{align-items:center}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-\\[3px\\]{border-radius:3px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-\\[1\\.5px\\]{border-style:var(--tw-border-style);border-width:1.5px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-solid{--tw-border-style:solid;border-style:solid}.border-grab-pink-border{border-color:var(--color-grab-pink-border)}.border-grab-purple{border-color:var(--color-grab-purple)}.border-grab-purple\\/40{border-color:#d239c066}@supports (color:color-mix(in lab, red, red)){.border-grab-purple\\/40{border-color:color-mix(in oklab,var(--color-grab-purple)40%,transparent)}}.border-grab-purple\\/50{border-color:#d239c080}@supports (color:color-mix(in lab, red, red)){.border-grab-purple\\/50{border-color:color-mix(in oklab,var(--color-grab-purple)50%,transparent)}}.border-t-transparent{border-top-color:#0000}.bg-grab-pink-light{background-color:var(--color-grab-pink-light)}.bg-grab-pink\\/20{background-color:#b21c8e33}@supports (color:color-mix(in lab, red, red)){.bg-grab-pink\\/20{background-color:color-mix(in oklab,var(--color-grab-pink)20%,transparent)}}.bg-grab-purple\\/5{background-color:#d239c00d}@supports (color:color-mix(in lab, red, red)){.bg-grab-purple\\/5{background-color:color-mix(in oklab,var(--color-grab-purple)5%,transparent)}}.bg-grab-purple\\/8{background-color:#d239c014}@supports (color:color-mix(in lab, red, red)){.bg-grab-purple\\/8{background-color:color-mix(in oklab,var(--color-grab-purple)8%,transparent)}}.bg-white{background-color:var(--color-white)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-\\[3px\\]{padding-inline:3px}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.text-center{text-align:center}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.text-grab-pink{color:var(--color-grab-pink)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.opacity-60{opacity:.6}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-\\[width\\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.will-change-\\[transform\\,width\\,height\\]{will-change:transform,width,height}.outline-none{--tw-outline-style:none;outline-style:none}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}';
752
+ var styles_default = '/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--font-weight-medium:500;--ease-out:cubic-bezier(0,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-grab-pink:#b21c8e;--color-grab-purple:#d239c0;--color-label-tag-border:#730079;--color-label-tag-text:#1e001f;--color-label-gray-border:#b0b0b0;--color-label-success-bg:#d9ffe4;--color-label-success-border:#00bb69;--color-label-success-text:#006e3b;--color-label-divider:#dedede;--color-label-muted:#767676}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.top-0{top:calc(var(--spacing)*0)}.left-0{left:calc(var(--spacing)*0)}.z-2147483645{z-index:2147483645}.z-2147483646{z-index:2147483646}.z-2147483647{z-index:2147483647}.z-\\[2147483645\\]{z-index:2147483645}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.mt-\\[2\\.5px\\]{margin-top:2.5px}.-ml-\\[5px\\]{margin-left:-5px}.ml-1{margin-left:calc(var(--spacing)*1)}.box-border{box-sizing:border-box}.flex{display:flex}.hidden{display:none}.h-0{height:calc(var(--spacing)*0)}.h-5{height:calc(var(--spacing)*5)}.h-5\\.5{height:calc(var(--spacing)*5.5)}.h-\\[14px\\]{height:14px}.h-\\[18px\\]{height:18px}.h-fit{height:fit-content}.min-h-\\[14px\\]{min-height:14px}.w-0{width:calc(var(--spacing)*0)}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-1{width:calc(var(--spacing)*1)}.w-\\[18px\\]{width:18px}.w-fit{width:fit-content}.w-full{width:100%}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-75{--tw-scale-x:75%;--tw-scale-y:75%;--tw-scale-z:75%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-crosshair{cursor:crosshair}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-\\[3px\\]{gap:3px}.gap-\\[5px\\]{gap:5px}.rounded-\\[1\\.5px\\]{border-radius:1.5px}.rounded-\\[3px\\]{border-radius:3px}.rounded-full{border-radius:3.40282e38px}.rounded-br-\\[3px\\]{border-bottom-right-radius:3px}.rounded-bl-\\[3px\\]{border-bottom-left-radius:3px}.border{border-style:var(--tw-border-style);border-width:1px}.border-\\[0\\.5px\\]{border-style:var(--tw-border-style);border-width:.5px}.border-t-\\[0\\.5px\\]{border-top-style:var(--tw-border-style);border-top-width:.5px}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.border-grab-purple{border-color:var(--color-grab-purple)}.border-grab-purple\\/40{border-color:#d239c066}@supports (color:color-mix(in lab, red, red)){.border-grab-purple\\/40{border-color:color-mix(in oklab,var(--color-grab-purple)40%,transparent)}}.border-grab-purple\\/50{border-color:#d239c080}@supports (color:color-mix(in lab, red, red)){.border-grab-purple\\/50{border-color:color-mix(in oklab,var(--color-grab-purple)50%,transparent)}}.border-label-gray-border{border-color:var(--color-label-gray-border)}.border-label-success-border{border-color:var(--color-label-success-border)}.border-label-tag-border{border-color:var(--color-label-tag-border)}.border-t-label-divider{border-top-color:var(--color-label-divider)}.bg-black{background-color:var(--color-black)}.bg-grab-pink{background-color:var(--color-grab-pink)}.bg-grab-purple\\/5{background-color:#d239c00d}@supports (color:color-mix(in lab, red, red)){.bg-grab-purple\\/5{background-color:color-mix(in oklab,var(--color-grab-purple)5%,transparent)}}.bg-grab-purple\\/8{background-color:#d239c014}@supports (color:color-mix(in lab, red, red)){.bg-grab-purple\\/8{background-color:color-mix(in oklab,var(--color-grab-purple)8%,transparent)}}.bg-label-success-bg{background-color:var(--color-label-success-bg)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.p-0{padding:calc(var(--spacing)*0)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-\\[5px\\]{padding-inline:5px}.py-\\[5px\\]{padding-block:5px}.py-px{padding-block:1px}.pt-1{padding-top:calc(var(--spacing)*1)}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-\\[12px\\]{font-size:12px}.leading-3\\.5{--tw-leading:calc(var(--spacing)*3.5);line-height:calc(var(--spacing)*3.5)}.leading-4{--tw-leading:calc(var(--spacing)*4);line-height:calc(var(--spacing)*4)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\\[-0\\.04em\\]{--tw-tracking:-.04em;letter-spacing:-.04em}.text-black{color:var(--color-black)}.text-label-muted{color:var(--color-label-muted)}.text-label-success-text{color:var(--color-label-success-text)}.text-label-tag-border{color:var(--color-label-tag-border)}.text-label-tag-text{color:var(--color-label-tag-text)}.text-white{color:var(--color-white)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-100{opacity:1}.opacity-\\[0\\.65\\]{opacity:.65}.brightness-125{--tw-brightness:brightness(125%);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[width\\,height\\]{transition-property:width,height;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.will-change-\\[transform\\,width\\,height\\]{will-change:transform,width,height}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\\:opacity-80:hover{opacity:.8}.hover\\:opacity-100:hover{opacity:1}}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.react-grab-shimmer{position:relative;overflow:hidden}.react-grab-shimmer:after{content:"";border-radius:inherit;pointer-events:none;background:linear-gradient(90deg,#0000 0%,#fff6 50%,#0000 100%) 0 0/200% 100%;animation:1.5s ease-in-out infinite shimmer;position:absolute;inset:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}';
744
753
 
745
754
  // src/utils/is-keyboard-event-triggered-by-input.ts
746
755
  var FORM_TAGS_AND_ROLES = [
@@ -791,6 +800,39 @@ var isKeyboardEventTriggeredByInput = (event) => {
791
800
  return isHotkeyEnabledOnTagName(event, FORM_TAGS_AND_ROLES);
792
801
  };
793
802
 
803
+ // src/utils/is-selection-inside-editable-element.ts
804
+ var isEditableElement = (element) => {
805
+ const tagName = element.tagName.toLowerCase();
806
+ if (tagName === "input" || tagName === "textarea") {
807
+ return true;
808
+ }
809
+ if (element instanceof HTMLElement && element.isContentEditable) {
810
+ return true;
811
+ }
812
+ return false;
813
+ };
814
+ var isSelectionInsideEditableElement = (cursorX, cursorY) => {
815
+ const activeElement = document.activeElement;
816
+ if (activeElement) {
817
+ let current = activeElement;
818
+ while (current) {
819
+ if (isEditableElement(current)) {
820
+ return true;
821
+ }
822
+ current = current.parentElement;
823
+ }
824
+ }
825
+ if (cursorX !== void 0 && cursorY !== void 0) {
826
+ const elementsAtPoint = document.elementsFromPoint(cursorX, cursorY);
827
+ for (const element of elementsAtPoint) {
828
+ if (isEditableElement(element)) {
829
+ return true;
830
+ }
831
+ }
832
+ }
833
+ return false;
834
+ };
835
+
794
836
  // src/utils/mount-root.ts
795
837
  var ATTRIBUTE_NAME = "data-react-grab";
796
838
  var mountRoot = (cssText) => {
@@ -823,18 +865,27 @@ var mountRoot = (cssText) => {
823
865
  return root;
824
866
  };
825
867
 
868
+ // src/utils/build-open-file-url.ts
869
+ var BASE_URL = "https://react-grab.com" ;
870
+ var buildOpenFileUrl = (filePath, lineNumber) => {
871
+ const lineParam = lineNumber ? `&line=${lineNumber}` : "";
872
+ return `${BASE_URL}/open-file?url=${encodeURIComponent(filePath)}${lineParam}`;
873
+ };
874
+
826
875
  // src/constants.ts
827
876
  var VIEWPORT_MARGIN_PX = 8;
828
- var INDICATOR_CLAMP_PADDING_PX = 4;
829
- var CURSOR_OFFSET_PX = 14;
830
877
  var OFFSCREEN_POSITION = -1e3;
831
878
  var SELECTION_LERP_FACTOR = 0.95;
832
879
  var SUCCESS_LABEL_DURATION_MS = 1700;
833
- var PROGRESS_INDICATOR_DELAY_MS = 150;
880
+ var COPIED_LABEL_DURATION_MS = 1500;
881
+ var SELECTION_CURSOR_SETTLE_DELAY_MS = 500;
882
+ var BLUR_DEACTIVATION_THRESHOLD_MS = 500;
834
883
  var DRAG_THRESHOLD_PX = 2;
835
884
  var AUTO_SCROLL_EDGE_THRESHOLD_PX = 25;
836
885
  var AUTO_SCROLL_SPEED_PX = 10;
837
886
  var Z_INDEX_LABEL = 2147483647;
887
+ var MODIFIER_KEYS = ["Meta", "Control", "Shift", "Alt"];
888
+ var LOGO_SVG = `<svg width="294" height="294" viewBox="0 0 294 294" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_0_3)"><mask id="mask0_0_3" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="294" height="294"><path d="M294 0H0V294H294V0Z" fill="white"/></mask><g mask="url(#mask0_0_3)"><path d="M144.599 47.4924C169.712 27.3959 194.548 20.0265 212.132 30.1797C227.847 39.2555 234.881 60.3243 231.926 89.516C231.677 92.0069 231.328 94.5423 230.94 97.1058L228.526 110.14C228.517 110.136 228.505 110.132 228.495 110.127C228.486 110.165 228.479 110.203 228.468 110.24L216.255 105.741C216.256 105.736 216.248 105.728 216.248 105.723C207.915 103.125 199.421 101.075 190.82 99.5888L190.696 99.5588L173.526 97.2648L173.511 97.2631C173.492 97.236 173.467 97.2176 173.447 97.1905C163.862 96.2064 154.233 95.7166 144.599 95.7223C134.943 95.7162 125.295 96.219 115.693 97.2286C110.075 105.033 104.859 113.118 100.063 121.453C95.2426 129.798 90.8624 138.391 86.939 147.193C90.8624 155.996 95.2426 164.588 100.063 172.933C104.866 181.302 110.099 189.417 115.741 197.245C115.749 197.245 115.758 197.246 115.766 197.247L115.752 197.27L115.745 197.283L115.754 197.296L126.501 211.013L126.574 211.089C132.136 217.767 138.126 224.075 144.507 229.974L144.609 230.082L154.572 238.287C154.539 238.319 154.506 238.35 154.472 238.38C154.485 238.392 154.499 238.402 154.513 238.412L143.846 247.482L143.827 247.497C126.56 261.128 109.472 268.745 94.8019 268.745C88.5916 268.837 82.4687 267.272 77.0657 264.208C61.3496 255.132 54.3164 234.062 57.2707 204.871C57.528 202.307 57.8806 199.694 58.2904 197.054C28.3363 185.327 9.52301 167.51 9.52301 147.193C9.52301 129.042 24.2476 112.396 50.9901 100.375C53.3443 99.3163 55.7938 98.3058 58.2904 97.3526C57.8806 94.7023 57.528 92.0803 57.2707 89.516C54.3164 60.3243 61.3496 39.2555 77.0657 30.1797C94.6494 20.0265 119.486 27.3959 144.599 47.4924ZM70.6423 201.315C70.423 202.955 70.2229 204.566 70.0704 206.168C67.6686 229.567 72.5478 246.628 83.3615 252.988L83.5176 253.062C95.0399 259.717 114.015 254.426 134.782 238.38C125.298 229.45 116.594 219.725 108.764 209.314C95.8516 207.742 83.0977 205.066 70.6423 201.315ZM80.3534 163.438C77.34 171.677 74.8666 180.104 72.9484 188.664C81.1787 191.224 89.5657 193.247 98.0572 194.724L98.4618 194.813C95.2115 189.865 92.0191 184.66 88.9311 179.378C85.8433 174.097 83.003 168.768 80.3534 163.438ZM60.759 110.203C59.234 110.839 57.7378 111.475 56.27 112.11C34.7788 121.806 22.3891 134.591 22.3891 147.193C22.3891 160.493 36.4657 174.297 60.7494 184.26C63.7439 171.581 67.8124 159.182 72.9104 147.193C67.822 135.23 63.7566 122.855 60.759 110.203ZM98.4137 99.6404C89.8078 101.145 81.3075 103.206 72.9676 105.809C74.854 114.203 77.2741 122.468 80.2132 130.554L80.3059 130.939C82.9938 125.6 85.8049 120.338 88.8834 115.008C91.9618 109.679 95.1544 104.569 98.4137 99.6404ZM94.9258 38.5215C90.9331 38.4284 86.9866 39.3955 83.4891 41.3243C72.6291 47.6015 67.6975 64.5954 70.0424 87.9446L70.0416 88.2194C70.194 89.8208 70.3941 91.4325 70.6134 93.0624C83.0737 89.3364 95.8263 86.6703 108.736 85.0924C116.57 74.6779 125.28 64.9532 134.773 56.0249C119.877 44.5087 105.895 38.5215 94.9258 38.5215ZM205.737 41.3148C202.268 39.398 198.355 38.4308 194.394 38.5099L194.29 38.512C183.321 38.512 169.34 44.4991 154.444 56.0153C163.93 64.9374 172.634 74.6557 180.462 85.064C193.375 86.6345 206.128 89.3102 218.584 93.0624C218.812 91.4325 219.003 89.8118 219.165 88.2098C221.548 64.7099 216.65 47.6164 205.737 41.3148ZM144.552 64.3097C138.104 70.2614 132.054 76.6306 126.443 83.3765C132.39 82.995 138.426 82.8046 144.552 82.8046C150.727 82.8046 156.778 83.0143 162.707 83.3765C157.08 76.6293 151.015 70.2596 144.552 64.3097Z" fill="white"/><path d="M144.598 47.4924C169.712 27.3959 194.547 20.0265 212.131 30.1797C227.847 39.2555 234.88 60.3243 231.926 89.516C231.677 92.0069 231.327 94.5423 230.941 97.1058L228.526 110.14L228.496 110.127C228.487 110.165 228.478 110.203 228.469 110.24L216.255 105.741L216.249 105.723C207.916 103.125 199.42 101.075 190.82 99.5888L190.696 99.5588L173.525 97.2648L173.511 97.263C173.492 97.236 173.468 97.2176 173.447 97.1905C163.863 96.2064 154.234 95.7166 144.598 95.7223C134.943 95.7162 125.295 96.219 115.693 97.2286C110.075 105.033 104.859 113.118 100.063 121.453C95.2426 129.798 90.8622 138.391 86.939 147.193C90.8622 155.996 95.2426 164.588 100.063 172.933C104.866 181.302 110.099 189.417 115.741 197.245L115.766 197.247L115.752 197.27L115.745 197.283L115.754 197.296L126.501 211.013L126.574 211.089C132.136 217.767 138.126 224.075 144.506 229.974L144.61 230.082L154.572 238.287C154.539 238.319 154.506 238.35 154.473 238.38L154.512 238.412L143.847 247.482L143.827 247.497C126.56 261.13 109.472 268.745 94.8018 268.745C88.5915 268.837 82.4687 267.272 77.0657 264.208C61.3496 255.132 54.3162 234.062 57.2707 204.871C57.528 202.307 57.8806 199.694 58.2904 197.054C28.3362 185.327 9.52298 167.51 9.52298 147.193C9.52298 129.042 24.2476 112.396 50.9901 100.375C53.3443 99.3163 55.7938 98.3058 58.2904 97.3526C57.8806 94.7023 57.528 92.0803 57.2707 89.516C54.3162 60.3243 61.3496 39.2555 77.0657 30.1797C94.6493 20.0265 119.486 27.3959 144.598 47.4924ZM70.6422 201.315C70.423 202.955 70.2229 204.566 70.0704 206.168C67.6686 229.567 72.5478 246.628 83.3615 252.988L83.5175 253.062C95.0399 259.717 114.015 254.426 134.782 238.38C125.298 229.45 116.594 219.725 108.764 209.314C95.8515 207.742 83.0977 205.066 70.6422 201.315ZM80.3534 163.438C77.34 171.677 74.8666 180.104 72.9484 188.664C81.1786 191.224 89.5657 193.247 98.0572 194.724L98.4618 194.813C95.2115 189.865 92.0191 184.66 88.931 179.378C85.8433 174.097 83.003 168.768 80.3534 163.438ZM60.7589 110.203C59.234 110.839 57.7378 111.475 56.2699 112.11C34.7788 121.806 22.3891 134.591 22.3891 147.193C22.3891 160.493 36.4657 174.297 60.7494 184.26C63.7439 171.581 67.8124 159.182 72.9103 147.193C67.822 135.23 63.7566 122.855 60.7589 110.203ZM98.4137 99.6404C89.8078 101.145 81.3075 103.206 72.9676 105.809C74.8539 114.203 77.2741 122.468 80.2132 130.554L80.3059 130.939C82.9938 125.6 85.8049 120.338 88.8834 115.008C91.9618 109.679 95.1544 104.569 98.4137 99.6404ZM94.9258 38.5215C90.9331 38.4284 86.9866 39.3955 83.4891 41.3243C72.629 47.6015 67.6975 64.5954 70.0424 87.9446L70.0415 88.2194C70.194 89.8208 70.3941 91.4325 70.6134 93.0624C83.0737 89.3364 95.8262 86.6703 108.736 85.0924C116.57 74.6779 125.28 64.9532 134.772 56.0249C119.877 44.5087 105.895 38.5215 94.9258 38.5215ZM205.737 41.3148C202.268 39.398 198.355 38.4308 194.394 38.5099L194.291 38.512C183.321 38.512 169.34 44.4991 154.443 56.0153C163.929 64.9374 172.634 74.6557 180.462 85.064C193.374 86.6345 206.129 89.3102 218.584 93.0624C218.813 91.4325 219.003 89.8118 219.166 88.2098C221.548 64.7099 216.65 47.6164 205.737 41.3148ZM144.551 64.3097C138.103 70.2614 132.055 76.6306 126.443 83.3765C132.389 82.995 138.427 82.8046 144.551 82.8046C150.727 82.8046 156.779 83.0143 162.707 83.3765C157.079 76.6293 151.015 70.2596 144.551 64.3097Z" fill="#FF40E0"/></g><mask id="mask1_0_3" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="102" y="84" width="161" height="162"><path d="M235.282 84.827L102.261 112.259L129.693 245.28L262.714 217.848L235.282 84.827Z" fill="white"/></mask><g mask="url(#mask1_0_3)"><path d="M136.863 129.916L213.258 141.224C220.669 142.322 222.495 152.179 215.967 155.856L187.592 171.843L184.135 204.227C183.339 211.678 173.564 213.901 169.624 207.526L129.021 141.831C125.503 136.14 130.245 128.936 136.863 129.916Z" fill="#FF40E0" stroke="#FF40E0" stroke-width="0.817337" stroke-linecap="round" stroke-linejoin="round"/></g></g><defs><clipPath id="clip0_0_3"><rect width="294" height="294" fill="white"/></clipPath></defs></svg>`;
838
889
 
839
890
  // src/utils/lerp.ts
840
891
  var lerp = (start, end, factor) => {
@@ -3317,12 +3368,10 @@ var getDefaultConfig = () => {
3317
3368
  var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
3318
3369
 
3319
3370
  // src/utils/cn.ts
3320
- var cn = (...inputs) => {
3321
- return twMerge(clsx(inputs));
3322
- };
3371
+ var cn = (...inputs) => twMerge(clsx(inputs));
3323
3372
 
3324
3373
  // src/components/selection-box.tsx
3325
- var _tmpl$ = /* @__PURE__ */ template(`<div>`);
3374
+ var _tmpl$ = /* @__PURE__ */ template(`<div style=overflow:visible>`);
3326
3375
  var SelectionBox = (props) => {
3327
3376
  const [currentX, setCurrentX] = createSignal(props.bounds.x);
3328
3377
  const [currentY, setCurrentY] = createSignal(props.bounds.y);
@@ -3398,7 +3447,7 @@ var SelectionBox = (props) => {
3398
3447
  get children() {
3399
3448
  var _el$ = _tmpl$();
3400
3449
  createRenderEffect((_p$) => {
3401
- var _v$ = cn("fixed box-border", props.variant === "drag" && "pointer-events-none", props.variant !== "drag" && "pointer-events-auto", props.variant === "grabbed" && "z-2147483645", props.variant !== "grabbed" && "z-2147483646", props.variant === "drag" && "border border-dashed border-grab-purple/40 bg-grab-purple/5 will-change-[transform,width,height] cursor-crosshair", props.variant === "selection" && "border border-dashed border-grab-purple/50 bg-grab-purple/8", props.variant === "grabbed" && "border border-solid border-grab-purple bg-grab-purple/8 transition-opacity duration-300 ease-out"), _v$2 = `${currentY()}px`, _v$3 = `${currentX()}px`, _v$4 = `${currentWidth()}px`, _v$5 = `${currentHeight()}px`, _v$6 = props.bounds.borderRadius, _v$7 = props.bounds.transform, _v$8 = opacity(), _v$9 = props.variant === "drag" ? "layout paint size" : void 0;
3450
+ var _v$ = cn("fixed box-border", props.variant === "drag" && "pointer-events-none", props.variant !== "drag" && "pointer-events-auto", props.variant === "grabbed" && "z-2147483645", props.variant !== "grabbed" && "z-2147483646", props.variant === "drag" && "border border-solid border-grab-purple/40 bg-grab-purple/5 will-change-[transform,width,height] cursor-crosshair", props.variant === "selection" && "border border-solid border-grab-purple/50 bg-grab-purple/8 transition-opacity duration-100 ease-out", props.variant === "grabbed" && "border border-solid border-grab-purple bg-grab-purple/8 transition-opacity duration-300 ease-out", props.variant === "processing" && "border border-solid border-grab-purple/50 bg-grab-purple/8"), _v$2 = `${currentY()}px`, _v$3 = `${currentX()}px`, _v$4 = `${currentWidth()}px`, _v$5 = `${currentHeight()}px`, _v$6 = props.bounds.borderRadius, _v$7 = props.bounds.transform, _v$8 = props.isFading ? 0 : opacity(), _v$9 = props.variant === "drag" ? "layout paint size" : void 0;
3402
3451
  _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3403
3452
  _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3404
3453
  _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
@@ -3425,45 +3474,6 @@ var SelectionBox = (props) => {
3425
3474
  });
3426
3475
  };
3427
3476
 
3428
- // src/components/spinner.tsx
3429
- var _tmpl$2 = /* @__PURE__ */ template(`<span class="inline-block w-2 h-2 border-[1.5px] border-grab-dark-pink border-t-transparent rounded-full mr-1 align-middle">`);
3430
- var Spinner = (props) => {
3431
- let spinnerRef;
3432
- onMount(() => {
3433
- if (spinnerRef) {
3434
- spinnerRef.animate([{
3435
- transform: "rotate(0deg)"
3436
- }, {
3437
- transform: "rotate(360deg)"
3438
- }], {
3439
- duration: 600,
3440
- easing: "linear",
3441
- iterations: Infinity
3442
- });
3443
- }
3444
- });
3445
- return (() => {
3446
- var _el$ = _tmpl$2();
3447
- var _ref$ = spinnerRef;
3448
- typeof _ref$ === "function" ? use(_ref$, _el$) : spinnerRef = _el$;
3449
- createRenderEffect((_$p) => style(_el$, props.style, _$p));
3450
- return _el$;
3451
- })();
3452
- };
3453
-
3454
- // src/utils/get-clamped-element-position.ts
3455
- var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elementHeight) => {
3456
- const viewportWidth = window.innerWidth;
3457
- const viewportHeight = window.innerHeight;
3458
- const minLeft = VIEWPORT_MARGIN_PX;
3459
- const minTop = VIEWPORT_MARGIN_PX;
3460
- const maxLeft = viewportWidth - elementWidth - VIEWPORT_MARGIN_PX;
3461
- const maxTop = viewportHeight - elementHeight - VIEWPORT_MARGIN_PX;
3462
- const clampedLeft = Math.max(minLeft, Math.min(positionLeft, maxLeft));
3463
- const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
3464
- return { left: clampedLeft, top: clampedTop };
3465
- };
3466
-
3467
3477
  // src/hooks/use-animated-lerp.ts
3468
3478
  var useAnimatedPosition = (options) => {
3469
3479
  const lerpFactor = options.lerpFactor ?? 0.3;
@@ -3510,187 +3520,8 @@ var useAnimatedPosition = (options) => {
3510
3520
  return { x: x3, y: y2 };
3511
3521
  };
3512
3522
 
3513
- // src/hooks/use-fade-in-out.ts
3514
- var useFadeInOut = (options) => {
3515
- const [opacity, setOpacity] = createSignal(0);
3516
- createEffect(
3517
- on(
3518
- () => options.visible,
3519
- (isVisible) => {
3520
- if (isVisible !== false) {
3521
- requestAnimationFrame(() => {
3522
- setOpacity(1);
3523
- });
3524
- } else {
3525
- setOpacity(0);
3526
- return;
3527
- }
3528
- if (options.autoFadeOutAfter !== void 0) {
3529
- const fadeOutTimer = setTimeout(() => {
3530
- setOpacity(0);
3531
- }, options.autoFadeOutAfter);
3532
- onCleanup(() => clearTimeout(fadeOutTimer));
3533
- }
3534
- }
3535
- )
3536
- );
3537
- return opacity;
3538
- };
3539
-
3540
- // src/utils/get-cursor-quadrants.ts
3541
- var getCursorQuadrants = (cursorX, cursorY, elementWidth, elementHeight, offset) => {
3542
- return [
3543
- {
3544
- left: Math.round(cursorX) + offset,
3545
- top: Math.round(cursorY) + offset
3546
- },
3547
- {
3548
- left: Math.round(cursorX) - elementWidth - offset,
3549
- top: Math.round(cursorY) + offset
3550
- },
3551
- {
3552
- left: Math.round(cursorX) + offset,
3553
- top: Math.round(cursorY) - elementHeight - offset
3554
- },
3555
- {
3556
- left: Math.round(cursorX) - elementWidth - offset,
3557
- top: Math.round(cursorY) - elementHeight - offset
3558
- }
3559
- ];
3560
- };
3561
-
3562
- // src/components/label.tsx
3563
- var _tmpl$3 = /* @__PURE__ */ template(`<div class="absolute top-0 left-0 bottom-0 bg-grab-pink/20 rounded-[3px] transition-[width] duration-100 ease-out pointer-events-none">`);
3564
- var _tmpl$22 = /* @__PURE__ */ template(`<span class="inline-block mr-1 font-semibold">\u2713`);
3565
- var _tmpl$32 = /* @__PURE__ */ template(`<div class=mr-1>Copied`);
3566
- var _tmpl$4 = /* @__PURE__ */ template(`<div class=ml-1>to clipboard`);
3567
- var _tmpl$5 = /* @__PURE__ */ template(`<div class="text-[9px] opacity-60 text-center mt-0.5">Click or drag to select`);
3568
- var _tmpl$6 = /* @__PURE__ */ template(`<div class="fixed bg-grab-pink-light text-grab-pink border border-grab-pink-border rounded text-[11px] font-medium font-sans pointer-events-none transition-opacity duration-200 ease-in-out overflow-hidden"style="max-width:calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)))"><div class="relative py-0.5 px-1.5 flex flex-col"><div class="flex items-center text-ellipsis whitespace-nowrap">`);
3569
- var Label = (props) => {
3570
- let labelRef;
3571
- const position = useAnimatedPosition({
3572
- x: () => props.x,
3573
- y: () => props.y,
3574
- lerpFactor: 0.3
3575
- });
3576
- const opacity = useFadeInOut({
3577
- visible: props.visible,
3578
- autoFadeOutAfter: props.variant === "success" ? SUCCESS_LABEL_DURATION_MS : void 0
3579
- });
3580
- const labelBoundingRect = () => labelRef?.getBoundingClientRect();
3581
- const computedPosition = () => {
3582
- const boundingRect = labelBoundingRect();
3583
- if (!boundingRect) return {
3584
- left: position.x(),
3585
- top: position.y()
3586
- };
3587
- const viewportWidth = window.innerWidth;
3588
- const viewportHeight = window.innerHeight;
3589
- const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
3590
- for (const position2 of quadrants) {
3591
- const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
3592
- const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
3593
- if (fitsHorizontally && fitsVertically) {
3594
- return position2;
3595
- }
3596
- }
3597
- const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
3598
- fallback.left += INDICATOR_CLAMP_PADDING_PX;
3599
- fallback.top += INDICATOR_CLAMP_PADDING_PX;
3600
- return fallback;
3601
- };
3602
- return createComponent(Show, {
3603
- get when() {
3604
- return props.visible !== false;
3605
- },
3606
- get children() {
3607
- var _el$ = _tmpl$6(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild;
3608
- var _ref$ = labelRef;
3609
- typeof _ref$ === "function" ? use(_ref$, _el$) : labelRef = _el$;
3610
- insert(_el$, createComponent(Show, {
3611
- get when() {
3612
- return memo(() => props.variant === "processing")() && props.progress !== void 0;
3613
- },
3614
- get children() {
3615
- var _el$2 = _tmpl$3();
3616
- createRenderEffect((_$p) => setStyleProperty(_el$2, "width", `${Math.min(100, Math.max(0, (props.progress ?? 0) * 100))}%`));
3617
- return _el$2;
3618
- }
3619
- }), _el$3);
3620
- insert(_el$4, createComponent(Show, {
3621
- get when() {
3622
- return props.variant === "processing";
3623
- },
3624
- get children() {
3625
- return createComponent(Spinner, {});
3626
- }
3627
- }), null);
3628
- insert(_el$4, createComponent(Show, {
3629
- get when() {
3630
- return props.variant === "success";
3631
- },
3632
- get children() {
3633
- return _tmpl$22();
3634
- }
3635
- }), null);
3636
- insert(_el$4, createComponent(Show, {
3637
- get when() {
3638
- return props.variant === "success";
3639
- },
3640
- get children() {
3641
- return _tmpl$32();
3642
- }
3643
- }), null);
3644
- insert(_el$4, createComponent(Show, {
3645
- get when() {
3646
- return props.variant === "processing";
3647
- },
3648
- children: "Please wait\u2026"
3649
- }), null);
3650
- insert(_el$4, createComponent(Show, {
3651
- get when() {
3652
- return props.variant !== "processing";
3653
- },
3654
- get children() {
3655
- return props.content;
3656
- }
3657
- }), null);
3658
- insert(_el$4, createComponent(Show, {
3659
- get when() {
3660
- return props.variant === "success";
3661
- },
3662
- get children() {
3663
- return _tmpl$4();
3664
- }
3665
- }), null);
3666
- insert(_el$3, createComponent(Show, {
3667
- get when() {
3668
- return memo(() => props.variant === "hover")() && props.showHint;
3669
- },
3670
- get children() {
3671
- return _tmpl$5();
3672
- }
3673
- }), null);
3674
- createRenderEffect((_p$) => {
3675
- var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
3676
- _v$ !== _p$.e && setStyleProperty(_el$, "top", _p$.e = _v$);
3677
- _v$2 !== _p$.t && setStyleProperty(_el$, "left", _p$.t = _v$2);
3678
- _v$3 !== _p$.a && setStyleProperty(_el$, "z-index", _p$.a = _v$3);
3679
- _v$4 !== _p$.o && setStyleProperty(_el$, "opacity", _p$.o = _v$4);
3680
- return _p$;
3681
- }, {
3682
- e: void 0,
3683
- t: void 0,
3684
- a: void 0,
3685
- o: void 0
3686
- });
3687
- return _el$;
3688
- }
3689
- });
3690
- };
3691
-
3692
3523
  // src/components/crosshair.tsx
3693
- var _tmpl$7 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3524
+ var _tmpl$2 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3694
3525
  var Crosshair = (props) => {
3695
3526
  let canvasRef;
3696
3527
  let context = null;
@@ -3750,7 +3581,7 @@ var Crosshair = (props) => {
3750
3581
  return props.visible !== false;
3751
3582
  },
3752
3583
  get children() {
3753
- var _el$ = _tmpl$7();
3584
+ var _el$ = _tmpl$2();
3754
3585
  var _ref$ = canvasRef;
3755
3586
  typeof _ref$ === "function" ? use(_ref$, _el$) : canvasRef = _el$;
3756
3587
  return _el$;
@@ -3758,106 +3589,658 @@ var Crosshair = (props) => {
3758
3589
  });
3759
3590
  };
3760
3591
 
3761
- // src/components/input-overlay.tsx
3762
- var _tmpl$8 = /* @__PURE__ */ template(`<div data-react-grab-input class="fixed bg-grab-pink-light text-grab-pink border border-grab-pink-border rounded text-[11px] font-medium font-sans overflow-hidden"style="max-width:calc(100vw - (16px + env(safe-area-inset-left) + env(safe-area-inset-right)))"><div class="relative p-0.5 px-[3px] flex flex-col gap-0.5"><textarea placeholder="Make a change"rows=1 class="w-[150px] px-1 py-0.5 bg-white text-grab-pink border border-grab-pink-border rounded-[3px] text-[11px] leading-tight font-sans outline-none resize-none min-h-[18px] overflow-hidden"></textarea><div class="text-[9px] opacity-60 text-center">Enter \u23CE submit &middot; Esc cancel`);
3763
- var InputOverlay = (props) => {
3592
+ // src/components/icon-checkmark.tsx
3593
+ var _tmpl$3 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 9 9"fill=none><path d="M1 4.5L3.5 7L8 1.5"stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round>`);
3594
+ var IconCheckmark = (props) => {
3595
+ const size = () => props.size ?? 9;
3596
+ return (() => {
3597
+ var _el$ = _tmpl$3();
3598
+ createRenderEffect((_p$) => {
3599
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3600
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3601
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3602
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3603
+ return _p$;
3604
+ }, {
3605
+ e: void 0,
3606
+ t: void 0,
3607
+ a: void 0
3608
+ });
3609
+ return _el$;
3610
+ })();
3611
+ };
3612
+
3613
+ // src/components/icon-cursor-simple.tsx
3614
+ var _tmpl$4 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 12 12"fill=none><path fill-rule=evenodd clip-rule=evenodd d="M0.675576 0.0318497C0.491988 -0.0369956 0.285105 0.0078173 0.146461 0.146461C0.0078173 0.285105 -0.0369956 0.491988 0.0318497 0.675576L4.15685 11.6756C4.2337 11.8805 4.43492 12.0117 4.65345 11.9992C4.87197 11.9868 5.057 11.8336 5.11009 11.6213L6.41232 6.41232L11.6213 5.11009C11.8336 5.057 11.9868 4.87197 11.9992 4.65345C12.0117 4.43492 11.8805 4.2337 11.6756 4.15685L0.675576 0.0318497Z"fill=currentColor>`);
3615
+ var IconCursorSimple = (props) => {
3616
+ const size = () => props.size ?? 9;
3617
+ return (() => {
3618
+ var _el$ = _tmpl$4();
3619
+ createRenderEffect((_p$) => {
3620
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3621
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3622
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3623
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3624
+ return _p$;
3625
+ }, {
3626
+ e: void 0,
3627
+ t: void 0,
3628
+ a: void 0
3629
+ });
3630
+ return _el$;
3631
+ })();
3632
+ };
3633
+
3634
+ // src/components/icon-open.tsx
3635
+ var _tmpl$5 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2><path d="M12 6H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6"></path><path d="M11 13l9-9"></path><path d="M15 4h5v5">`);
3636
+ var IconOpen = (props) => {
3637
+ const size = () => props.size ?? 12;
3638
+ return (() => {
3639
+ var _el$ = _tmpl$5();
3640
+ createRenderEffect((_p$) => {
3641
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3642
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3643
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3644
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3645
+ return _p$;
3646
+ }, {
3647
+ e: void 0,
3648
+ t: void 0,
3649
+ a: void 0
3650
+ });
3651
+ return _el$;
3652
+ })();
3653
+ };
3654
+
3655
+ // src/components/icon-return-key.tsx
3656
+ var _tmpl$6 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 12 12"><g fill=none stroke-linecap=round stroke-linejoin=round stroke-width=1 stroke=currentColor><path d=m1.25,6.75h8.5c.5523,0,1-.4477,1-1v-2.5c0-.5523-.4477-1-1-1h-1.75></path><polyline points="3.75 4 1 6.75 3.75 9.5">`);
3657
+ var IconReturnKey = (props) => {
3658
+ const size = () => props.size ?? 14;
3659
+ return (() => {
3660
+ var _el$ = _tmpl$6();
3661
+ createRenderEffect((_p$) => {
3662
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3663
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3664
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3665
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3666
+ return _p$;
3667
+ }, {
3668
+ e: void 0,
3669
+ t: void 0,
3670
+ a: void 0
3671
+ });
3672
+ return _el$;
3673
+ })();
3674
+ };
3675
+
3676
+ // src/components/icon-stop.tsx
3677
+ var _tmpl$7 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 9 9"fill=none><rect x=1 y=1 width=7 height=7 rx=1 fill=currentColor>`);
3678
+ var IconStop = (props) => {
3679
+ const size = () => props.size ?? 9;
3680
+ return (() => {
3681
+ var _el$ = _tmpl$7();
3682
+ createRenderEffect((_p$) => {
3683
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3684
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3685
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3686
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3687
+ return _p$;
3688
+ }, {
3689
+ e: void 0,
3690
+ t: void 0,
3691
+ a: void 0
3692
+ });
3693
+ return _el$;
3694
+ })();
3695
+ };
3696
+
3697
+ // src/components/selection-label.tsx
3698
+ var _tmpl$8 = /* @__PURE__ */ template(`<div style="background-image:linear-gradient(in oklab 180deg, oklab(88.7% 0.086 -0.058) 0%, oklab(83.2% 0.132 -0.089) 100%)"><span>`);
3699
+ var _tmpl$22 = /* @__PURE__ */ template(`<span>`);
3700
+ var _tmpl$32 = /* @__PURE__ */ template(`<button>`);
3701
+ var _tmpl$42 = /* @__PURE__ */ template(`<div>`);
3702
+ var _tmpl$52 = /* @__PURE__ */ template(`<div class="flex items-center h-[18px] rounded-[1.5px] gap-[3px] px-[5px] py-px bg-label-success-bg border-[0.5px] border-solid border-label-success-border"><span class="text-label-success-text text-[12px] leading-4 font-medium tracking-[-0.04em]">`);
3703
+ var _tmpl$62 = /* @__PURE__ */ template(`<div class="absolute w-0 h-0"style="border-left:8px solid transparent;border-right:8px solid transparent;z-index:1">`);
3704
+ var _tmpl$72 = /* @__PURE__ */ template(`<div class="shrink-0 flex flex-col items-start px-2 py-[5px] w-full h-fit rounded-bl-[3px] rounded-br-[3px] border-t-[0.5px] border-t-solid border-t-label-divider">`);
3705
+ var _tmpl$82 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px]">`);
3706
+ var _tmpl$9 = /* @__PURE__ */ template(`<button class="flex items-center justify-center w-[18px] h-[18px] rounded-full cursor-pointer bg-black border-none transition-opacity hover:opacity-80"title=Stop>`);
3707
+ var _tmpl$0 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px] react-grab-shimmer rounded-[3px]">`);
3708
+ var _tmpl$1 = /* @__PURE__ */ template(`<div class="shrink-0 flex items-center gap-1 w-full h-[14px]"><span class="text-label-muted text-[12px] leading-3.5 shrink-0 tracking-[-0.04em] font-medium w-fit h-fit">to change`);
3709
+ var _tmpl$10 = /* @__PURE__ */ template(`<div class="shrink-0 flex flex-col justify-center items-start gap-1 w-fit h-fit"><div class="shrink-0 flex items-center gap-[3px] pt-1 w-fit h-fit px-1">`);
3710
+ var _tmpl$11 = /* @__PURE__ */ template(`<div class="shrink-0 flex justify-between items-start w-full min-h-[14px]"><textarea class="text-black text-[12px] leading-3.5 tracking-[-0.04em] font-medium bg-transparent border-none outline-none resize-none flex-1 p-0 m-0"placeholder="type to modify..."rows=1 style=field-sizing:content;min-height:14px></textarea><button class="shrink-0 flex items-center gap-1 w-fit h-fit cursor-pointer bg-transparent border-none p-0 ml-1 mt-[2.5px]">`);
3711
+ var _tmpl$12 = /* @__PURE__ */ template(`<div data-react-grab-ignore-events class="fixed font-sans antialiased transition-opacity duration-300 ease-out"style=z-index:2147483647><div class="relative flex items-center gap-[5px] bg-white rounded-[3px]"style="box-shadow:#00000033 0px 2px 3px">`);
3712
+ var ARROW_HEIGHT = 8;
3713
+ var LABEL_GAP = 4;
3714
+ var TagBadge = (props) => {
3715
+ const [isHovered, setIsHovered] = createSignal(false);
3716
+ const handleMouseEnter = () => {
3717
+ setIsHovered(true);
3718
+ props.onHoverChange?.(true);
3719
+ };
3720
+ const handleMouseLeave = () => {
3721
+ setIsHovered(false);
3722
+ props.onHoverChange?.(false);
3723
+ };
3724
+ return (() => {
3725
+ var _el$ = _tmpl$8(), _el$2 = _el$.firstChild;
3726
+ addEventListener(_el$, "click", props.onClick);
3727
+ _el$.addEventListener("mouseleave", handleMouseLeave);
3728
+ _el$.addEventListener("mouseenter", handleMouseEnter);
3729
+ insert(_el$2, () => props.tagName);
3730
+ insert(_el$, createComponent(Show, {
3731
+ get when() {
3732
+ return props.isClickable;
3733
+ },
3734
+ get children() {
3735
+ return createComponent(IconOpen, {
3736
+ size: 10,
3737
+ get ["class"]() {
3738
+ return cn("text-label-tag-border transition-all duration-100", isHovered() ? "opacity-100 scale-100" : "opacity-0 scale-75 -ml-[5px] w-0");
3739
+ }
3740
+ });
3741
+ }
3742
+ }), null);
3743
+ createRenderEffect((_p$) => {
3744
+ var _v$ = cn("flex items-center px-1 py-px h-[18px] rounded-[1.5px] gap-[5px] border-[0.5px] border-solid border-label-tag-border", props.shrink && "shrink-0 w-fit", props.isClickable && "cursor-pointer"), _v$2 = cn("text-label-tag-text text-[12px] leading-4 font-medium tracking-[-0.04em]", props.showMono && "font-mono", props.shrink && "shrink-0 w-fit h-fit");
3745
+ _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3746
+ _v$2 !== _p$.t && className(_el$2, _p$.t = _v$2);
3747
+ return _p$;
3748
+ }, {
3749
+ e: void 0,
3750
+ t: void 0
3751
+ });
3752
+ return _el$;
3753
+ })();
3754
+ };
3755
+ var ActionPill = (props) => {
3756
+ const baseClass = cn("flex items-center h-[18px] rounded-[1.5px] gap-[3px] px-[5px] py-px border-[0.5px] border-solid border-label-gray-border", props.shrink && "shrink-0 w-fit", props.asButton && "cursor-pointer bg-transparent", props.dimmed && "opacity-50 hover:opacity-100 transition-opacity");
3757
+ const content = [memo(() => props.icon), (() => {
3758
+ var _el$3 = _tmpl$22();
3759
+ insert(_el$3, () => props.label);
3760
+ createRenderEffect(() => className(_el$3, cn("text-black text-[12px] leading-4 font-medium tracking-[-0.04em]", props.shrink && "shrink-0 w-fit h-fit")));
3761
+ return _el$3;
3762
+ })()];
3763
+ return props.asButton ? (() => {
3764
+ var _el$4 = _tmpl$32();
3765
+ addEventListener(_el$4, "click", props.onClick);
3766
+ className(_el$4, baseClass);
3767
+ insert(_el$4, content);
3768
+ return _el$4;
3769
+ })() : (() => {
3770
+ var _el$5 = _tmpl$42();
3771
+ addEventListener(_el$5, "click", props.onClick);
3772
+ className(_el$5, baseClass);
3773
+ insert(_el$5, content);
3774
+ createRenderEffect(() => setAttribute(_el$5, "role", props.onClick ? "button" : void 0));
3775
+ return _el$5;
3776
+ })();
3777
+ };
3778
+ var SuccessPill = (props) => (() => {
3779
+ var _el$6 = _tmpl$52(), _el$7 = _el$6.firstChild;
3780
+ insert(_el$6, createComponent(IconCheckmark, {
3781
+ size: 9,
3782
+ "class": "text-label-success-text shrink-0"
3783
+ }), _el$7);
3784
+ insert(_el$7, () => props.hasAgent ? "Completed" : "Copied");
3785
+ return _el$6;
3786
+ })();
3787
+ var Arrow = (props) => (() => {
3788
+ var _el$8 = _tmpl$62();
3789
+ createRenderEffect((_$p) => style(_el$8, {
3790
+ left: `${props.leftPx}px`,
3791
+ ...props.position === "bottom" ? {
3792
+ top: "0",
3793
+ transform: "translateX(-50%) translateY(-100%)"
3794
+ } : {
3795
+ bottom: "0",
3796
+ transform: "translateX(-50%) translateY(100%)"
3797
+ },
3798
+ ...props.position === "bottom" ? {
3799
+ "border-bottom": "8px solid white"
3800
+ } : {
3801
+ "border-top": "8px solid white"
3802
+ }
3803
+ }, _$p));
3804
+ return _el$8;
3805
+ })();
3806
+ var ClickToCopyPill = (props) => createComponent(ActionPill, {
3807
+ get icon() {
3808
+ return createComponent(IconCursorSimple, {
3809
+ size: 9,
3810
+ "class": "text-black shrink-0"
3811
+ });
3812
+ },
3813
+ label: "Click to copy",
3814
+ get onClick() {
3815
+ return props.onClick;
3816
+ },
3817
+ get asButton() {
3818
+ return props.asButton;
3819
+ },
3820
+ get dimmed() {
3821
+ return props.dimmed;
3822
+ },
3823
+ get shrink() {
3824
+ return props.shrink;
3825
+ }
3826
+ });
3827
+ var BottomSection = (props) => (() => {
3828
+ var _el$9 = _tmpl$72();
3829
+ insert(_el$9, () => props.children);
3830
+ return _el$9;
3831
+ })();
3832
+ var SelectionLabel = (props) => {
3764
3833
  let containerRef;
3765
3834
  let inputRef;
3766
- const position = useAnimatedPosition({
3767
- x: () => props.x,
3768
- y: () => props.y,
3769
- lerpFactor: 0.3
3835
+ let isTagCurrentlyHovered = false;
3836
+ const [measuredWidth, setMeasuredWidth] = createSignal(0);
3837
+ const [measuredHeight, setMeasuredHeight] = createSignal(0);
3838
+ const [arrowPosition, setArrowPosition] = createSignal("bottom");
3839
+ const [viewportVersion, setViewportVersion] = createSignal(0);
3840
+ const isNotProcessing = () => props.status !== "copying" && props.status !== "copied" && props.status !== "fading";
3841
+ const measureContainer = () => {
3842
+ if (containerRef && !isTagCurrentlyHovered) {
3843
+ const rect = containerRef.getBoundingClientRect();
3844
+ setMeasuredWidth(rect.width);
3845
+ setMeasuredHeight(rect.height);
3846
+ }
3847
+ };
3848
+ const handleTagHoverChange = (hovered) => {
3849
+ isTagCurrentlyHovered = hovered;
3850
+ };
3851
+ const handleViewportChange = () => {
3852
+ setViewportVersion((version) => version + 1);
3853
+ };
3854
+ onMount(() => {
3855
+ measureContainer();
3856
+ window.addEventListener("scroll", handleViewportChange, true);
3857
+ window.addEventListener("resize", handleViewportChange);
3858
+ });
3859
+ onCleanup(() => {
3860
+ window.removeEventListener("scroll", handleViewportChange, true);
3861
+ window.removeEventListener("resize", handleViewportChange);
3862
+ });
3863
+ createEffect(() => {
3864
+ if (props.visible) {
3865
+ requestAnimationFrame(measureContainer);
3866
+ }
3867
+ });
3868
+ createEffect(() => {
3869
+ void [props.status, props.isInputExpanded, props.inputValue];
3870
+ requestAnimationFrame(measureContainer);
3871
+ });
3872
+ createEffect(() => {
3873
+ if (props.isInputExpanded && inputRef) {
3874
+ setTimeout(() => {
3875
+ inputRef?.focus();
3876
+ }, 0);
3877
+ }
3770
3878
  });
3771
- const containerBoundingRect = () => containerRef?.getBoundingClientRect();
3772
3879
  const computedPosition = () => {
3773
- const boundingRect = containerBoundingRect();
3774
- if (!boundingRect) return {
3775
- left: position.x(),
3776
- top: position.y()
3777
- };
3880
+ viewportVersion();
3881
+ const bounds = props.selectionBounds;
3882
+ const labelWidth = measuredWidth();
3883
+ const labelHeight = measuredHeight();
3884
+ if (!bounds || labelWidth === 0 || labelHeight === 0) {
3885
+ return {
3886
+ left: -9999,
3887
+ top: -9999,
3888
+ arrowLeft: 0
3889
+ };
3890
+ }
3778
3891
  const viewportWidth = window.innerWidth;
3779
3892
  const viewportHeight = window.innerHeight;
3780
- const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
3781
- for (const position2 of quadrants) {
3782
- const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
3783
- const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
3784
- if (fitsHorizontally && fitsVertically) {
3785
- return position2;
3786
- }
3893
+ const selectionCenterX = bounds.x + bounds.width / 2;
3894
+ const selectionBottom = bounds.y + bounds.height;
3895
+ const selectionTop = bounds.y;
3896
+ let positionLeft = selectionCenterX - labelWidth / 2;
3897
+ let positionTop = selectionBottom + ARROW_HEIGHT + LABEL_GAP;
3898
+ if (positionLeft + labelWidth > viewportWidth - VIEWPORT_MARGIN_PX) {
3899
+ positionLeft = viewportWidth - labelWidth - VIEWPORT_MARGIN_PX;
3900
+ }
3901
+ if (positionLeft < VIEWPORT_MARGIN_PX) {
3902
+ positionLeft = VIEWPORT_MARGIN_PX;
3903
+ }
3904
+ const totalHeightNeeded = labelHeight + ARROW_HEIGHT + LABEL_GAP;
3905
+ const fitsBelow = positionTop + labelHeight <= viewportHeight - VIEWPORT_MARGIN_PX;
3906
+ if (!fitsBelow) {
3907
+ positionTop = selectionTop - totalHeightNeeded;
3908
+ setArrowPosition("top");
3909
+ } else {
3910
+ setArrowPosition("bottom");
3787
3911
  }
3788
- const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
3789
- fallback.left += INDICATOR_CLAMP_PADDING_PX;
3790
- fallback.top += INDICATOR_CLAMP_PADDING_PX;
3791
- return fallback;
3912
+ if (positionTop < VIEWPORT_MARGIN_PX) {
3913
+ positionTop = VIEWPORT_MARGIN_PX;
3914
+ }
3915
+ const arrowLeft = Math.max(12, Math.min(selectionCenterX - positionLeft, labelWidth - 12));
3916
+ return {
3917
+ left: positionLeft,
3918
+ top: positionTop,
3919
+ arrowLeft
3920
+ };
3792
3921
  };
3793
3922
  const handleKeyDown = (event) => {
3923
+ event.stopPropagation();
3794
3924
  if (event.code === "Enter" && !event.shiftKey) {
3795
3925
  event.preventDefault();
3796
- event.stopPropagation();
3797
- props.onSubmit();
3926
+ props.onSubmit?.();
3798
3927
  } else if (event.code === "Escape") {
3799
3928
  event.preventDefault();
3800
- event.stopPropagation();
3801
- props.onCancel();
3929
+ props.onCancel?.();
3802
3930
  }
3803
3931
  };
3804
3932
  const handleInput = (event) => {
3805
3933
  const target = event.target;
3806
- props.onInput(target.value);
3807
- target.style.height = "auto";
3808
- target.style.height = `${target.scrollHeight}px`;
3934
+ props.onInputChange?.(target.value);
3809
3935
  };
3810
- createEffect(() => {
3811
- if (props.visible && inputRef) {
3812
- inputRef.focus();
3813
- inputRef.style.height = "auto";
3814
- } else if (!props.visible && inputRef) {
3815
- inputRef.blur();
3936
+ const tagDisplay = () => props.tagName || "element";
3937
+ const handleTagClick = (event) => {
3938
+ event.stopPropagation();
3939
+ event.stopImmediatePropagation();
3940
+ if (props.filePath && props.onOpen) {
3941
+ props.onOpen();
3816
3942
  }
3817
- });
3818
- return (() => {
3819
- var _el$ = _tmpl$8(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
3820
- var _ref$ = containerRef;
3821
- typeof _ref$ === "function" ? use(_ref$, _el$) : containerRef = _el$;
3822
- _el$3.$$keydown = handleKeyDown;
3823
- _el$3.$$input = handleInput;
3824
- var _ref$2 = inputRef;
3825
- typeof _ref$2 === "function" ? use(_ref$2, _el$3) : inputRef = _el$3;
3826
- createRenderEffect((_p$) => {
3827
- var _v$ = props.visible ? "block" : "none", _v$2 = `${computedPosition().top}px`, _v$3 = `${computedPosition().left}px`, _v$4 = props.zIndex?.toString() ?? "2147483647", _v$5 = props.visible ? "auto" : "none";
3828
- _v$ !== _p$.e && setStyleProperty(_el$, "display", _p$.e = _v$);
3829
- _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3830
- _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
3831
- _v$4 !== _p$.o && setStyleProperty(_el$, "z-index", _p$.o = _v$4);
3832
- _v$5 !== _p$.i && setStyleProperty(_el$, "pointer-events", _p$.i = _v$5);
3833
- return _p$;
3834
- }, {
3835
- e: void 0,
3836
- t: void 0,
3837
- a: void 0,
3838
- o: void 0,
3839
- i: void 0
3840
- });
3841
- createRenderEffect(() => _el$3.value = props.value);
3842
- return _el$;
3843
- })();
3844
- };
3845
- delegateEvents(["input", "keydown"]);
3846
-
3847
- // src/components/renderer.tsx
3848
- var ReactGrabRenderer = (props) => {
3849
- return [createComponent(Show, {
3943
+ };
3944
+ const isTagClickable = () => Boolean(props.filePath && props.onOpen);
3945
+ const stopPropagation = (event) => {
3946
+ event.stopPropagation();
3947
+ event.stopImmediatePropagation();
3948
+ };
3949
+ const handleSubmit = () => props.onSubmit?.();
3950
+ return createComponent(Show, {
3850
3951
  get when() {
3851
- return memo(() => !!props.selectionVisible)() && props.selectionBounds;
3952
+ return memo(() => props.visible !== false)() && props.selectionBounds;
3852
3953
  },
3853
3954
  get children() {
3854
- return createComponent(SelectionBox, {
3855
- variant: "selection",
3856
- get bounds() {
3955
+ var _el$0 = _tmpl$12(), _el$1 = _el$0.firstChild;
3956
+ _el$0.$$click = stopPropagation;
3957
+ _el$0.$$mousedown = stopPropagation;
3958
+ var _ref$ = containerRef;
3959
+ typeof _ref$ === "function" ? use(_ref$, _el$0) : containerRef = _el$0;
3960
+ insert(_el$0, createComponent(Arrow, {
3961
+ get position() {
3962
+ return arrowPosition();
3963
+ },
3964
+ get leftPx() {
3965
+ return computedPosition().arrowLeft;
3966
+ }
3967
+ }), _el$1);
3968
+ insert(_el$1, createComponent(Show, {
3969
+ get when() {
3970
+ return props.status === "copied" || props.status === "fading";
3971
+ },
3972
+ get children() {
3973
+ var _el$10 = _tmpl$82();
3974
+ insert(_el$10, createComponent(TagBadge, {
3975
+ get tagName() {
3976
+ return tagDisplay();
3977
+ },
3978
+ get isClickable() {
3979
+ return isTagClickable();
3980
+ },
3981
+ onClick: handleTagClick,
3982
+ onHoverChange: handleTagHoverChange
3983
+ }), null);
3984
+ insert(_el$10, createComponent(SuccessPill, {
3985
+ get hasAgent() {
3986
+ return props.hasAgent;
3987
+ }
3988
+ }), null);
3989
+ return _el$10;
3990
+ }
3991
+ }), null);
3992
+ insert(_el$1, createComponent(Show, {
3993
+ get when() {
3994
+ return props.status === "copying";
3995
+ },
3996
+ get children() {
3997
+ var _el$11 = _tmpl$0();
3998
+ insert(_el$11, createComponent(TagBadge, {
3999
+ get tagName() {
4000
+ return tagDisplay();
4001
+ },
4002
+ get isClickable() {
4003
+ return isTagClickable();
4004
+ },
4005
+ onClick: handleTagClick,
4006
+ onHoverChange: handleTagHoverChange,
4007
+ showMono: true
4008
+ }), null);
4009
+ insert(_el$11, createComponent(ActionPill, {
4010
+ get icon() {
4011
+ return createComponent(IconCursorSimple, {
4012
+ size: 9,
4013
+ "class": "text-black shrink-0"
4014
+ });
4015
+ },
4016
+ get label() {
4017
+ return props.statusText ?? "Grabbing\u2026";
4018
+ }
4019
+ }), null);
4020
+ insert(_el$11, createComponent(Show, {
4021
+ get when() {
4022
+ return memo(() => !!props.hasAgent)() && props.onAbort;
4023
+ },
4024
+ get children() {
4025
+ var _el$12 = _tmpl$9();
4026
+ _el$12.$$click = (event) => {
4027
+ event.preventDefault();
4028
+ event.stopPropagation();
4029
+ event.stopImmediatePropagation();
4030
+ props.onAbort?.();
4031
+ };
4032
+ _el$12.$$mousedown = (event) => {
4033
+ event.preventDefault();
4034
+ event.stopPropagation();
4035
+ event.stopImmediatePropagation();
4036
+ };
4037
+ insert(_el$12, createComponent(IconStop, {
4038
+ size: 8,
4039
+ "class": "text-white"
4040
+ }));
4041
+ return _el$12;
4042
+ }
4043
+ }), null);
4044
+ return _el$11;
4045
+ }
4046
+ }), null);
4047
+ insert(_el$1, createComponent(Show, {
4048
+ get when() {
4049
+ return memo(() => !!isNotProcessing())() && !props.isInputExpanded;
4050
+ },
4051
+ get children() {
4052
+ var _el$13 = _tmpl$10(), _el$14 = _el$13.firstChild;
4053
+ insert(_el$14, createComponent(TagBadge, {
4054
+ get tagName() {
4055
+ return tagDisplay();
4056
+ },
4057
+ get isClickable() {
4058
+ return isTagClickable();
4059
+ },
4060
+ onClick: handleTagClick,
4061
+ onHoverChange: handleTagHoverChange,
4062
+ showMono: true,
4063
+ shrink: true
4064
+ }), null);
4065
+ insert(_el$14, createComponent(ClickToCopyPill, {
4066
+ onClick: handleSubmit,
4067
+ shrink: true
4068
+ }), null);
4069
+ insert(_el$13, createComponent(BottomSection, {
4070
+ get children() {
4071
+ var _el$15 = _tmpl$1(), _el$16 = _el$15.firstChild;
4072
+ insert(_el$15, createComponent(IconReturnKey, {
4073
+ size: 12,
4074
+ "class": "shrink-0 text-black opacity-[0.65]"
4075
+ }), _el$16);
4076
+ return _el$15;
4077
+ }
4078
+ }), null);
4079
+ return _el$13;
4080
+ }
4081
+ }), null);
4082
+ insert(_el$1, createComponent(Show, {
4083
+ get when() {
4084
+ return memo(() => !!isNotProcessing())() && props.isInputExpanded;
4085
+ },
4086
+ get children() {
4087
+ var _el$17 = _tmpl$10(), _el$18 = _el$17.firstChild;
4088
+ insert(_el$18, createComponent(TagBadge, {
4089
+ get tagName() {
4090
+ return tagDisplay();
4091
+ },
4092
+ get isClickable() {
4093
+ return isTagClickable();
4094
+ },
4095
+ onClick: handleTagClick,
4096
+ onHoverChange: handleTagHoverChange,
4097
+ showMono: true,
4098
+ shrink: true
4099
+ }), null);
4100
+ insert(_el$18, createComponent(ClickToCopyPill, {
4101
+ onClick: handleSubmit,
4102
+ dimmed: true,
4103
+ shrink: true
4104
+ }), null);
4105
+ insert(_el$17, createComponent(BottomSection, {
4106
+ get children() {
4107
+ var _el$19 = _tmpl$11(), _el$20 = _el$19.firstChild, _el$21 = _el$20.nextSibling;
4108
+ _el$20.$$keydown = handleKeyDown;
4109
+ _el$20.$$input = handleInput;
4110
+ var _ref$2 = inputRef;
4111
+ typeof _ref$2 === "function" ? use(_ref$2, _el$20) : inputRef = _el$20;
4112
+ _el$21.$$click = handleSubmit;
4113
+ insert(_el$21, createComponent(IconReturnKey, {
4114
+ size: 12,
4115
+ "class": "shrink-0 text-black"
4116
+ }));
4117
+ createRenderEffect(() => _el$20.value = props.inputValue ?? "");
4118
+ return _el$19;
4119
+ }
4120
+ }), null);
4121
+ return _el$17;
4122
+ }
4123
+ }), null);
4124
+ createRenderEffect((_p$) => {
4125
+ var _v$3 = `${computedPosition().top}px`, _v$4 = `${computedPosition().left}px`, _v$5 = props.visible ? "auto" : "none", _v$6 = props.status === "fading" ? 0 : 1, _v$7 = !isNotProcessing() ? "4px" : "0";
4126
+ _v$3 !== _p$.e && setStyleProperty(_el$0, "top", _p$.e = _v$3);
4127
+ _v$4 !== _p$.t && setStyleProperty(_el$0, "left", _p$.t = _v$4);
4128
+ _v$5 !== _p$.a && setStyleProperty(_el$0, "pointer-events", _p$.a = _v$5);
4129
+ _v$6 !== _p$.o && setStyleProperty(_el$0, "opacity", _p$.o = _v$6);
4130
+ _v$7 !== _p$.i && setStyleProperty(_el$1, "padding", _p$.i = _v$7);
4131
+ return _p$;
4132
+ }, {
4133
+ e: void 0,
4134
+ t: void 0,
4135
+ a: void 0,
4136
+ o: void 0,
4137
+ i: void 0
4138
+ });
4139
+ return _el$0;
4140
+ }
4141
+ });
4142
+ };
4143
+ delegateEvents(["click", "mousedown", "input", "keydown"]);
4144
+
4145
+ // src/components/selection-cursor.tsx
4146
+ var _tmpl$13 = /* @__PURE__ */ template(`<div class="fixed z-2147483647"><button data-react-grab-selection-cursor>`);
4147
+ var SelectionCursor = (props) => {
4148
+ const [isHovered, setIsHovered] = createSignal(false);
4149
+ const [debouncedVisible, setDebouncedVisible] = createSignal(false);
4150
+ createEffect(() => {
4151
+ const isVisible = props.visible !== false;
4152
+ void [props.x, props.y];
4153
+ setDebouncedVisible(false);
4154
+ if (isVisible) {
4155
+ const timeout = setTimeout(() => setDebouncedVisible(true), SELECTION_CURSOR_SETTLE_DELAY_MS);
4156
+ onCleanup(() => clearTimeout(timeout));
4157
+ }
4158
+ });
4159
+ const handleClick = (event) => {
4160
+ event.preventDefault();
4161
+ event.stopPropagation();
4162
+ props.onClick?.();
4163
+ };
4164
+ return createComponent(Show, {
4165
+ get when() {
4166
+ return debouncedVisible();
4167
+ },
4168
+ get children() {
4169
+ return [createComponent(Show, {
4170
+ get when() {
4171
+ return memo(() => !!isHovered())() && props.elementBounds;
4172
+ },
4173
+ get children() {
4174
+ return createComponent(SelectionBox, {
4175
+ variant: "selection",
4176
+ get bounds() {
4177
+ return props.elementBounds;
4178
+ },
4179
+ visible: true
4180
+ });
4181
+ }
4182
+ }), (() => {
4183
+ var _el$ = _tmpl$13(), _el$2 = _el$.firstChild;
4184
+ _el$.addEventListener("mouseleave", () => setIsHovered(false));
4185
+ _el$.addEventListener("mouseenter", () => setIsHovered(true));
4186
+ _el$2.$$click = handleClick;
4187
+ createRenderEffect((_p$) => {
4188
+ var _v$ = `${props.x}px`, _v$2 = `${props.y}px`, _v$3 = cn("absolute left-0 top-0 -translate-x-1/2 -translate-y-1/2 bg-grab-pink cursor-pointer rounded-full transition-[width,height] duration-150", isHovered() ? "w-1 h-5.5 brightness-125" : "w-0.5 h-5 animate-pulse");
4189
+ _v$ !== _p$.e && setStyleProperty(_el$, "left", _p$.e = _v$);
4190
+ _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
4191
+ _v$3 !== _p$.a && className(_el$2, _p$.a = _v$3);
4192
+ return _p$;
4193
+ }, {
4194
+ e: void 0,
4195
+ t: void 0,
4196
+ a: void 0
4197
+ });
4198
+ return _el$;
4199
+ })(), createComponent(Show, {
4200
+ get when() {
4201
+ return memo(() => !!isHovered())() && props.elementBounds;
4202
+ },
4203
+ get children() {
4204
+ return createComponent(SelectionLabel, {
4205
+ get tagName() {
4206
+ return props.tagName;
4207
+ },
4208
+ get selectionBounds() {
4209
+ return props.elementBounds;
4210
+ },
4211
+ visible: true,
4212
+ get onSubmit() {
4213
+ return props.onClick;
4214
+ }
4215
+ });
4216
+ }
4217
+ })];
4218
+ }
4219
+ });
4220
+ };
4221
+ delegateEvents(["click"]);
4222
+
4223
+ // src/components/renderer.tsx
4224
+ var truncateStatus = (status, maxLength = 30) => {
4225
+ if (status.length <= maxLength) return status;
4226
+ return `${status.slice(0, maxLength)}\u2026`;
4227
+ };
4228
+ var ReactGrabRenderer = (props) => {
4229
+ return [createComponent(Show, {
4230
+ get when() {
4231
+ return memo(() => !!props.selectionVisible)() && props.selectionBounds;
4232
+ },
4233
+ get children() {
4234
+ return createComponent(SelectionBox, {
4235
+ variant: "selection",
4236
+ get bounds() {
3857
4237
  return props.selectionBounds;
3858
4238
  },
3859
4239
  get visible() {
3860
4240
  return props.selectionVisible;
4241
+ },
4242
+ get isFading() {
4243
+ return props.selectionLabelStatus === "fading";
3861
4244
  }
3862
4245
  });
3863
4246
  }
@@ -3904,86 +4287,141 @@ var ReactGrabRenderer = (props) => {
3904
4287
  return box.createdAt;
3905
4288
  }
3906
4289
  })
4290
+ }), createComponent(For, {
4291
+ get each() {
4292
+ return memo(() => !!props.agentSessions)() ? Array.from(props.agentSessions.values()) : [];
4293
+ },
4294
+ children: (session) => [createComponent(Show, {
4295
+ get when() {
4296
+ return session.selectionBounds;
4297
+ },
4298
+ get children() {
4299
+ return createComponent(SelectionBox, {
4300
+ variant: "processing",
4301
+ get bounds() {
4302
+ return session.selectionBounds;
4303
+ },
4304
+ visible: true
4305
+ });
4306
+ }
4307
+ }), createComponent(SelectionLabel, {
4308
+ get tagName() {
4309
+ return session.tagName;
4310
+ },
4311
+ get selectionBounds() {
4312
+ return session.selectionBounds;
4313
+ },
4314
+ visible: true,
4315
+ hasAgent: true,
4316
+ get status() {
4317
+ return session.isStreaming ? "copying" : "copied";
4318
+ },
4319
+ get statusText() {
4320
+ return truncateStatus(session.lastStatus || "Please wait\u2026");
4321
+ },
4322
+ onAbort: () => props.onAbortSession?.(session.id)
4323
+ })]
3907
4324
  }), createComponent(Show, {
3908
4325
  get when() {
3909
- return props.labelVariant !== "processing";
4326
+ return memo(() => !!props.selectionLabelVisible)() && props.selectionBounds;
3910
4327
  },
3911
4328
  get children() {
3912
- return createComponent(For, {
3913
- get each() {
3914
- return props.successLabels ?? [];
4329
+ return createComponent(SelectionLabel, {
4330
+ get tagName() {
4331
+ return props.selectionTagName;
3915
4332
  },
3916
- children: (label) => createComponent(Label, {
3917
- variant: "success",
3918
- get content() {
3919
- return memo(() => label.text);
3920
- },
3921
- get x() {
3922
- return props.mouseX ?? 0;
3923
- },
3924
- get y() {
3925
- return props.mouseY ?? 0;
4333
+ get selectionBounds() {
4334
+ return props.selectionBounds;
4335
+ },
4336
+ get visible() {
4337
+ return props.selectionLabelVisible;
4338
+ },
4339
+ get isInputExpanded() {
4340
+ return props.isInputExpanded;
4341
+ },
4342
+ get inputValue() {
4343
+ return props.inputValue;
4344
+ },
4345
+ get hasAgent() {
4346
+ return props.hasAgent;
4347
+ },
4348
+ get status() {
4349
+ return props.selectionLabelStatus;
4350
+ },
4351
+ get filePath() {
4352
+ return props.selectionFilePath;
4353
+ },
4354
+ get lineNumber() {
4355
+ return props.selectionLineNumber;
4356
+ },
4357
+ get onInputChange() {
4358
+ return props.onInputChange;
4359
+ },
4360
+ get onSubmit() {
4361
+ return props.onInputSubmit;
4362
+ },
4363
+ get onCancel() {
4364
+ return props.onInputCancel;
4365
+ },
4366
+ get onToggleExpand() {
4367
+ return props.onToggleExpand;
4368
+ },
4369
+ onOpen: () => {
4370
+ if (props.selectionFilePath) {
4371
+ const openFileUrl = buildOpenFileUrl(props.selectionFilePath, props.selectionLineNumber);
4372
+ window.open(openFileUrl, "_blank");
3926
4373
  }
3927
- })
4374
+ }
3928
4375
  });
3929
4376
  }
4377
+ }), createComponent(For, {
4378
+ get each() {
4379
+ return props.labelInstances ?? [];
4380
+ },
4381
+ children: (instance) => createComponent(SelectionLabel, {
4382
+ get tagName() {
4383
+ return instance.tagName;
4384
+ },
4385
+ get selectionBounds() {
4386
+ return instance.bounds;
4387
+ },
4388
+ visible: true,
4389
+ get status() {
4390
+ return instance.status;
4391
+ }
4392
+ })
3930
4393
  }), createComponent(Show, {
3931
4394
  get when() {
3932
- return memo(() => !!(props.labelVisible && props.labelVariant && props.labelContent !== void 0 && props.labelX !== void 0))() && props.labelY !== void 0;
4395
+ return memo(() => !!(props.nativeSelectionCursorVisible && props.nativeSelectionCursorX !== void 0))() && props.nativeSelectionCursorY !== void 0;
3933
4396
  },
3934
4397
  get children() {
3935
- return createComponent(Label, {
3936
- get variant() {
3937
- return props.labelVariant;
3938
- },
3939
- get content() {
3940
- return props.labelContent;
3941
- },
4398
+ return createComponent(SelectionCursor, {
3942
4399
  get x() {
3943
- return props.labelX;
4400
+ return props.nativeSelectionCursorX;
3944
4401
  },
3945
4402
  get y() {
3946
- return props.labelY;
4403
+ return props.nativeSelectionCursorY;
3947
4404
  },
3948
- get visible() {
3949
- return props.labelVisible;
4405
+ get tagName() {
4406
+ return props.nativeSelectionTagName;
4407
+ },
4408
+ get componentName() {
4409
+ return props.nativeSelectionComponentName;
3950
4410
  },
3951
- get zIndex() {
3952
- return props.labelZIndex;
4411
+ get elementBounds() {
4412
+ return props.nativeSelectionBounds;
3953
4413
  },
3954
- get progress() {
3955
- return props.progress;
4414
+ get visible() {
4415
+ return props.nativeSelectionCursorVisible;
4416
+ },
4417
+ get onClick() {
4418
+ return props.onNativeSelectionCopy;
3956
4419
  },
3957
- get showHint() {
3958
- return props.labelShowHint;
4420
+ get onEnter() {
4421
+ return props.onNativeSelectionEnter;
3959
4422
  }
3960
4423
  });
3961
4424
  }
3962
- }), createComponent(InputOverlay, {
3963
- get x() {
3964
- return props.inputX ?? 0;
3965
- },
3966
- get y() {
3967
- return props.inputY ?? 0;
3968
- },
3969
- get zIndex() {
3970
- return props.labelZIndex;
3971
- },
3972
- get value() {
3973
- return props.inputValue ?? "";
3974
- },
3975
- get visible() {
3976
- return props.inputVisible ?? false;
3977
- },
3978
- get onInput() {
3979
- return props.onInputChange;
3980
- },
3981
- get onSubmit() {
3982
- return props.onInputSubmit;
3983
- },
3984
- get onCancel() {
3985
- return props.onInputCancel;
3986
- }
3987
4425
  })];
3988
4426
  };
3989
4427
 
@@ -4827,7 +5265,7 @@ var je2 = (e2) => {
4827
5265
  var isCapitalized = (value) => value.length > 0 && /^[A-Z]/.test(value);
4828
5266
 
4829
5267
  // src/instrumentation.ts
4830
- var NEXT_INTERNAL_COMPONENT_NAMES = [
5268
+ var NEXT_INTERNAL_COMPONENT_NAMES = /* @__PURE__ */ new Set([
4831
5269
  "InnerLayoutRouter",
4832
5270
  "RedirectErrorBoundary",
4833
5271
  "RedirectBoundary",
@@ -4841,28 +5279,23 @@ var NEXT_INTERNAL_COMPONENT_NAMES = [
4841
5279
  "OuterLayoutRouter",
4842
5280
  "body",
4843
5281
  "html",
4844
- "RedirectErrorBoundary",
4845
- "RedirectBoundary",
4846
- "HTTPAccessFallbackErrorBoundary",
4847
- "HTTPAccessFallbackBoundary",
4848
5282
  "DevRootHTTPAccessFallbackBoundary",
4849
5283
  "AppDevOverlayErrorBoundary",
4850
5284
  "AppDevOverlay",
4851
5285
  "HotReload",
4852
5286
  "Router",
4853
5287
  "ErrorBoundaryHandler",
4854
- "ErrorBoundary",
4855
5288
  "AppRouter",
4856
5289
  "ServerRoot",
4857
5290
  "SegmentStateProvider",
4858
5291
  "RootErrorBoundary"
4859
- ];
5292
+ ]);
4860
5293
  var checkIsNextProject = () => {
4861
5294
  return Boolean(document.getElementById("__NEXT_DATA__"));
4862
5295
  };
4863
5296
  var checkIsInternalComponentName = (name) => {
4864
5297
  if (name.startsWith("_")) return true;
4865
- if (NEXT_INTERNAL_COMPONENT_NAMES.includes(name)) return true;
5298
+ if (NEXT_INTERNAL_COMPONENT_NAMES.has(name)) return true;
4866
5299
  return false;
4867
5300
  };
4868
5301
  var checkIsSourceComponentName = (name) => {
@@ -4928,20 +5361,47 @@ var getStack = async (element) => {
4928
5361
  return [];
4929
5362
  }
4930
5363
  };
4931
- var formatStack = (stack) => {
5364
+ var formatElementInfo = async (element) => {
5365
+ const html = getHTMLPreview(element);
5366
+ const stack = await getStack(element);
4932
5367
  const isNextProject = checkIsNextProject();
4933
- return stack.map(({ name, source }) => {
4934
- if (!source) return ` at ${name}`;
4935
- if (source.fileName.startsWith("about://React/Server")) {
4936
- return ` at ${name} (Server)`;
4937
- }
4938
- if (!je2(source.fileName)) return ` at ${name}`;
4939
- const framePart = ` at ${name} in ${Q(source.fileName)}`;
4940
- if (isNextProject) {
4941
- return `${framePart}:${source.lineNumber}:${source.columnNumber}`;
4942
- }
4943
- return framePart;
4944
- }).join("\n");
5368
+ let serverBoundary = null;
5369
+ let componentName = null;
5370
+ let fileName = null;
5371
+ let lineNumber = null;
5372
+ let columnNumber = null;
5373
+ for (const frame of stack) {
5374
+ if (!frame.source) continue;
5375
+ if (frame.source.fileName.startsWith("about://React/Server")) {
5376
+ if (!serverBoundary) serverBoundary = frame.name;
5377
+ continue;
5378
+ }
5379
+ if (je2(frame.source.fileName)) {
5380
+ if (!fileName) {
5381
+ fileName = Q(frame.source.fileName);
5382
+ lineNumber = frame.source.lineNumber ?? null;
5383
+ columnNumber = frame.source.columnNumber ?? null;
5384
+ }
5385
+ if (!componentName && checkIsSourceComponentName(frame.name)) {
5386
+ componentName = frame.name;
5387
+ }
5388
+ if (fileName && componentName) {
5389
+ break;
5390
+ }
5391
+ }
5392
+ }
5393
+ if (!componentName || !fileName) {
5394
+ return html;
5395
+ }
5396
+ let result = `${html}
5397
+ in ${componentName} at ${fileName}`;
5398
+ if (isNextProject && lineNumber && columnNumber) {
5399
+ result += `:${lineNumber}:${columnNumber}`;
5400
+ }
5401
+ if (serverBoundary) {
5402
+ result += ` (via Server: ${serverBoundary})`;
5403
+ }
5404
+ return result;
4945
5405
  };
4946
5406
  var getFileName = (stack) => {
4947
5407
  for (const frame of stack) {
@@ -5296,6 +5756,53 @@ var isCLikeKey = (key, code) => {
5296
5756
  return C_LIKE_CHARACTERS.has(key);
5297
5757
  };
5298
5758
 
5759
+ // src/utils/hotkey.ts
5760
+ var keyMatchesCode = (targetKey, code) => {
5761
+ const normalizedTarget = targetKey.toLowerCase();
5762
+ if (code.startsWith("Key")) {
5763
+ return code.slice(3).toLowerCase() === normalizedTarget;
5764
+ }
5765
+ if (code.startsWith("Digit")) {
5766
+ return code.slice(5) === normalizedTarget;
5767
+ }
5768
+ return false;
5769
+ };
5770
+ var isTargetKeyCombination = (event, options) => {
5771
+ if (options.activationShortcut) {
5772
+ return options.activationShortcut(event);
5773
+ }
5774
+ if (options.activationKey) {
5775
+ const { key, metaKey, ctrlKey, shiftKey, altKey } = options.activationKey;
5776
+ const isModifierOnly = !key;
5777
+ if (isModifierOnly) {
5778
+ if (!MODIFIER_KEYS.includes(event.key)) return false;
5779
+ const metaMatches = metaKey ? event.metaKey || event.key === "Meta" : true;
5780
+ const ctrlMatches = ctrlKey ? event.ctrlKey || event.key === "Control" : true;
5781
+ const shiftMatches = shiftKey ? event.shiftKey || event.key === "Shift" : true;
5782
+ const altMatches = altKey ? event.altKey || event.key === "Alt" : true;
5783
+ const allRequiredModifiersPressed = metaMatches && ctrlMatches && shiftMatches && altMatches;
5784
+ const requiredModifierCount = [metaKey, ctrlKey, shiftKey, altKey].filter(Boolean).length;
5785
+ const pressedModifierCount = [
5786
+ event.metaKey || event.key === "Meta",
5787
+ event.ctrlKey || event.key === "Control",
5788
+ event.shiftKey || event.key === "Shift",
5789
+ event.altKey || event.key === "Alt"
5790
+ ].filter(Boolean).length;
5791
+ return allRequiredModifiersPressed && pressedModifierCount >= requiredModifierCount;
5792
+ }
5793
+ const keyMatches = event.key.toLowerCase() === key.toLowerCase() || keyMatchesCode(key, event.code);
5794
+ const hasModifier = metaKey || ctrlKey || shiftKey || altKey;
5795
+ const modifiersMatch = hasModifier ? (metaKey ? event.metaKey : true) && (ctrlKey ? event.ctrlKey : true) && (shiftKey ? event.shiftKey : true) && (altKey ? event.altKey : true) : event.metaKey || event.ctrlKey;
5796
+ return keyMatches && modifiersMatch;
5797
+ }
5798
+ return (event.metaKey || event.ctrlKey) && isCLikeKey(event.key, event.code);
5799
+ };
5800
+
5801
+ // src/utils/is-event-from-overlay.ts
5802
+ var isEventFromOverlay = (event, attribute) => event.composedPath().some(
5803
+ (target) => target instanceof HTMLElement && target.hasAttribute(attribute)
5804
+ );
5805
+
5299
5806
  // src/theme.ts
5300
5807
  var DEFAULT_THEME = {
5301
5808
  enabled: true,
@@ -5332,86 +5839,327 @@ var DEFAULT_THEME = {
5332
5839
  enabled: true
5333
5840
  }
5334
5841
  };
5335
- var mergeTheme = (userTheme) => {
5336
- if (!userTheme) return DEFAULT_THEME;
5337
- return {
5338
- enabled: userTheme.enabled ?? DEFAULT_THEME.enabled,
5339
- hue: userTheme.hue ?? DEFAULT_THEME.hue,
5340
- selectionBox: {
5341
- enabled: userTheme.selectionBox?.enabled ?? DEFAULT_THEME.selectionBox.enabled,
5342
- color: userTheme.selectionBox?.color ?? DEFAULT_THEME.selectionBox.color,
5343
- borderRadius: userTheme.selectionBox?.borderRadius ?? DEFAULT_THEME.selectionBox.borderRadius
5344
- },
5345
- dragBox: {
5346
- enabled: userTheme.dragBox?.enabled ?? DEFAULT_THEME.dragBox.enabled,
5347
- color: userTheme.dragBox?.color ?? DEFAULT_THEME.dragBox.color
5348
- },
5349
- grabbedBoxes: {
5350
- enabled: userTheme.grabbedBoxes?.enabled ?? DEFAULT_THEME.grabbedBoxes.enabled,
5351
- color: userTheme.grabbedBoxes?.color ?? DEFAULT_THEME.grabbedBoxes.color
5352
- },
5353
- elementLabel: {
5354
- enabled: userTheme.elementLabel?.enabled ?? DEFAULT_THEME.elementLabel.enabled,
5355
- backgroundColor: userTheme.elementLabel?.backgroundColor ?? DEFAULT_THEME.elementLabel.backgroundColor,
5356
- textColor: userTheme.elementLabel?.textColor ?? DEFAULT_THEME.elementLabel.textColor,
5357
- borderColor: userTheme.elementLabel?.borderColor ?? DEFAULT_THEME.elementLabel.borderColor,
5358
- padding: userTheme.elementLabel?.padding ?? DEFAULT_THEME.elementLabel.padding,
5359
- cursorOffset: userTheme.elementLabel?.cursorOffset ?? DEFAULT_THEME.elementLabel.cursorOffset
5360
- },
5361
- successLabels: {
5362
- enabled: userTheme.successLabels?.enabled ?? DEFAULT_THEME.successLabels.enabled
5363
- },
5364
- crosshair: {
5365
- enabled: userTheme.crosshair?.enabled ?? DEFAULT_THEME.crosshair.enabled,
5366
- color: userTheme.crosshair?.color ?? DEFAULT_THEME.crosshair.color
5367
- },
5368
- inputOverlay: {
5369
- enabled: userTheme.inputOverlay?.enabled ?? DEFAULT_THEME.inputOverlay.enabled
5842
+ var mergeThemeWithBase = (baseTheme, partialTheme) => ({
5843
+ enabled: partialTheme.enabled ?? baseTheme.enabled,
5844
+ hue: partialTheme.hue ?? baseTheme.hue,
5845
+ selectionBox: {
5846
+ enabled: partialTheme.selectionBox?.enabled ?? baseTheme.selectionBox.enabled,
5847
+ color: partialTheme.selectionBox?.color ?? baseTheme.selectionBox.color,
5848
+ borderRadius: partialTheme.selectionBox?.borderRadius ?? baseTheme.selectionBox.borderRadius
5849
+ },
5850
+ dragBox: {
5851
+ enabled: partialTheme.dragBox?.enabled ?? baseTheme.dragBox.enabled,
5852
+ color: partialTheme.dragBox?.color ?? baseTheme.dragBox.color
5853
+ },
5854
+ grabbedBoxes: {
5855
+ enabled: partialTheme.grabbedBoxes?.enabled ?? baseTheme.grabbedBoxes.enabled,
5856
+ color: partialTheme.grabbedBoxes?.color ?? baseTheme.grabbedBoxes.color
5857
+ },
5858
+ elementLabel: {
5859
+ enabled: partialTheme.elementLabel?.enabled ?? baseTheme.elementLabel.enabled,
5860
+ backgroundColor: partialTheme.elementLabel?.backgroundColor ?? baseTheme.elementLabel.backgroundColor,
5861
+ textColor: partialTheme.elementLabel?.textColor ?? baseTheme.elementLabel.textColor,
5862
+ borderColor: partialTheme.elementLabel?.borderColor ?? baseTheme.elementLabel.borderColor,
5863
+ padding: partialTheme.elementLabel?.padding ?? baseTheme.elementLabel.padding,
5864
+ cursorOffset: partialTheme.elementLabel?.cursorOffset ?? baseTheme.elementLabel.cursorOffset
5865
+ },
5866
+ successLabels: {
5867
+ enabled: partialTheme.successLabels?.enabled ?? baseTheme.successLabels.enabled
5868
+ },
5869
+ crosshair: {
5870
+ enabled: partialTheme.crosshair?.enabled ?? baseTheme.crosshair.enabled,
5871
+ color: partialTheme.crosshair?.color ?? baseTheme.crosshair.color
5872
+ },
5873
+ inputOverlay: {
5874
+ enabled: partialTheme.inputOverlay?.enabled ?? baseTheme.inputOverlay.enabled
5875
+ }
5876
+ });
5877
+ var mergeTheme = (userTheme) => userTheme ? mergeThemeWithBase(DEFAULT_THEME, userTheme) : DEFAULT_THEME;
5878
+ var deepMergeTheme = mergeThemeWithBase;
5879
+
5880
+ // src/utils/agent-session.ts
5881
+ var STORAGE_KEY = "react-grab:agent-sessions";
5882
+ var generateSessionId = () => `session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
5883
+ var createSession = (context, position, selectionBounds, tagName) => ({
5884
+ id: generateSessionId(),
5885
+ context,
5886
+ lastStatus: "",
5887
+ isStreaming: true,
5888
+ createdAt: Date.now(),
5889
+ position,
5890
+ selectionBounds,
5891
+ tagName
5892
+ });
5893
+ var getStorage = (storage) => {
5894
+ if (!storage) return null;
5895
+ return storage;
5896
+ };
5897
+ var memorySessions = /* @__PURE__ */ new Map();
5898
+ var saveSessions = (sessions, storage) => {
5899
+ const resolvedStorage = getStorage(storage);
5900
+ if (!resolvedStorage) {
5901
+ memorySessions.clear();
5902
+ sessions.forEach((session, id) => memorySessions.set(id, session));
5903
+ return;
5904
+ }
5905
+ try {
5906
+ const sessionsObject = Object.fromEntries(sessions);
5907
+ resolvedStorage.setItem(STORAGE_KEY, JSON.stringify(sessionsObject));
5908
+ } catch {
5909
+ memorySessions.clear();
5910
+ sessions.forEach((session, id) => memorySessions.set(id, session));
5911
+ }
5912
+ };
5913
+ var saveSessionById = (session, storage) => {
5914
+ const sessions = loadSessions(storage);
5915
+ sessions.set(session.id, session);
5916
+ saveSessions(sessions, storage);
5917
+ };
5918
+ var loadSessions = (storage) => {
5919
+ const resolvedStorage = getStorage(storage);
5920
+ if (!resolvedStorage) {
5921
+ return new Map(memorySessions);
5922
+ }
5923
+ try {
5924
+ const data = resolvedStorage.getItem(STORAGE_KEY);
5925
+ if (!data) return /* @__PURE__ */ new Map();
5926
+ const sessionsObject = JSON.parse(data);
5927
+ return new Map(Object.entries(sessionsObject));
5928
+ } catch {
5929
+ return /* @__PURE__ */ new Map();
5930
+ }
5931
+ };
5932
+ var clearSessions = (storage) => {
5933
+ const resolvedStorage = getStorage(storage);
5934
+ if (!resolvedStorage) {
5935
+ memorySessions.clear();
5936
+ return;
5937
+ }
5938
+ try {
5939
+ resolvedStorage.removeItem(STORAGE_KEY);
5940
+ } catch {
5941
+ memorySessions.clear();
5942
+ }
5943
+ };
5944
+ var clearSessionById = (sessionId, storage) => {
5945
+ const sessions = loadSessions(storage);
5946
+ sessions.delete(sessionId);
5947
+ saveSessions(sessions, storage);
5948
+ };
5949
+ var updateSession = (session, updates, storage) => {
5950
+ const updatedSession = { ...session, ...updates };
5951
+ saveSessionById(updatedSession, storage);
5952
+ return updatedSession;
5953
+ };
5954
+
5955
+ // src/utils/generate-snippet.ts
5956
+ var generateSnippet = async (elements) => {
5957
+ const elementSnippetResults = await Promise.allSettled(
5958
+ elements.map((element) => formatElementInfo(element))
5959
+ );
5960
+ const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
5961
+ if (elementSnippets.length === 0) {
5962
+ return "";
5963
+ }
5964
+ return elementSnippets.join("\n\n");
5965
+ };
5966
+
5967
+ // src/agent.ts
5968
+ var createAgentManager = (agentOptions) => {
5969
+ const [sessions, setSessions] = createSignal(/* @__PURE__ */ new Map());
5970
+ const abortControllers = /* @__PURE__ */ new Map();
5971
+ const sessionElements = /* @__PURE__ */ new Map();
5972
+ const isProcessing = () => sessions().size > 0;
5973
+ const executeSessionStream = async (session, streamIterator) => {
5974
+ const storage = agentOptions?.storage;
5975
+ let didComplete = false;
5976
+ let wasAborted = false;
5977
+ let hadError = false;
5978
+ try {
5979
+ for await (const status of streamIterator) {
5980
+ const currentSessions = sessions();
5981
+ const currentSession = currentSessions.get(session.id);
5982
+ if (!currentSession) break;
5983
+ const updatedSession = updateSession(currentSession, { lastStatus: status }, storage);
5984
+ setSessions((prev) => new Map(prev).set(session.id, updatedSession));
5985
+ agentOptions?.onStatus?.(status, updatedSession);
5986
+ }
5987
+ didComplete = true;
5988
+ const finalSessions = sessions();
5989
+ const finalSession = finalSessions.get(session.id);
5990
+ if (finalSession) {
5991
+ const completedSession = updateSession(finalSession, { isStreaming: false }, storage);
5992
+ setSessions((prev) => new Map(prev).set(session.id, completedSession));
5993
+ agentOptions?.onComplete?.(completedSession);
5994
+ }
5995
+ } catch (error) {
5996
+ const currentSessions = sessions();
5997
+ const currentSession = currentSessions.get(session.id);
5998
+ if (error instanceof Error && error.name === "AbortError") {
5999
+ wasAborted = true;
6000
+ if (currentSession) {
6001
+ const element = sessionElements.get(session.id);
6002
+ agentOptions?.onAbort?.(currentSession, element);
6003
+ }
6004
+ } else {
6005
+ hadError = true;
6006
+ if (currentSession) {
6007
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
6008
+ const errorSession = updateSession(currentSession, {
6009
+ lastStatus: `Error: ${errorMessage}`,
6010
+ isStreaming: false
6011
+ }, storage);
6012
+ setSessions((prev) => new Map(prev).set(session.id, errorSession));
6013
+ if (error instanceof Error) {
6014
+ agentOptions?.onError?.(error, errorSession);
6015
+ }
6016
+ }
6017
+ }
6018
+ } finally {
6019
+ abortControllers.delete(session.id);
6020
+ const removeSession = () => {
6021
+ sessionElements.delete(session.id);
6022
+ clearSessionById(session.id, storage);
6023
+ setSessions((prev) => {
6024
+ const next = new Map(prev);
6025
+ next.delete(session.id);
6026
+ return next;
6027
+ });
6028
+ };
6029
+ if (wasAborted) {
6030
+ removeSession();
6031
+ } else if (didComplete || hadError) {
6032
+ setTimeout(removeSession, 1500);
6033
+ }
5370
6034
  }
5371
6035
  };
5372
- };
5373
- var deepMergeTheme = (baseTheme, partialTheme) => {
5374
- return {
5375
- enabled: partialTheme.enabled ?? baseTheme.enabled,
5376
- hue: partialTheme.hue ?? baseTheme.hue,
5377
- selectionBox: {
5378
- enabled: partialTheme.selectionBox?.enabled ?? baseTheme.selectionBox.enabled,
5379
- color: partialTheme.selectionBox?.color ?? baseTheme.selectionBox.color,
5380
- borderRadius: partialTheme.selectionBox?.borderRadius ?? baseTheme.selectionBox.borderRadius
5381
- },
5382
- dragBox: {
5383
- enabled: partialTheme.dragBox?.enabled ?? baseTheme.dragBox.enabled,
5384
- color: partialTheme.dragBox?.color ?? baseTheme.dragBox.color
5385
- },
5386
- grabbedBoxes: {
5387
- enabled: partialTheme.grabbedBoxes?.enabled ?? baseTheme.grabbedBoxes.enabled,
5388
- color: partialTheme.grabbedBoxes?.color ?? baseTheme.grabbedBoxes.color
5389
- },
5390
- elementLabel: {
5391
- enabled: partialTheme.elementLabel?.enabled ?? baseTheme.elementLabel.enabled,
5392
- backgroundColor: partialTheme.elementLabel?.backgroundColor ?? baseTheme.elementLabel.backgroundColor,
5393
- textColor: partialTheme.elementLabel?.textColor ?? baseTheme.elementLabel.textColor,
5394
- borderColor: partialTheme.elementLabel?.borderColor ?? baseTheme.elementLabel.borderColor,
5395
- padding: partialTheme.elementLabel?.padding ?? baseTheme.elementLabel.padding,
5396
- cursorOffset: partialTheme.elementLabel?.cursorOffset ?? baseTheme.elementLabel.cursorOffset
5397
- },
5398
- successLabels: {
5399
- enabled: partialTheme.successLabels?.enabled ?? baseTheme.successLabels.enabled
5400
- },
5401
- crosshair: {
5402
- enabled: partialTheme.crosshair?.enabled ?? baseTheme.crosshair.enabled,
5403
- color: partialTheme.crosshair?.color ?? baseTheme.crosshair.color
5404
- },
5405
- inputOverlay: {
5406
- enabled: partialTheme.inputOverlay?.enabled ?? baseTheme.inputOverlay.enabled
6036
+ const tryReacquireElement = (session) => {
6037
+ const { selectionBounds, tagName } = session;
6038
+ if (!selectionBounds) return void 0;
6039
+ const centerX = selectionBounds.x + selectionBounds.width / 2;
6040
+ const centerY = selectionBounds.y + selectionBounds.height / 2;
6041
+ const element = document.elementFromPoint(centerX, centerY);
6042
+ if (!element) return void 0;
6043
+ if (tagName && element.tagName.toLowerCase() !== tagName) {
6044
+ return void 0;
6045
+ }
6046
+ return element;
6047
+ };
6048
+ const tryResumeSessions = () => {
6049
+ const storage = agentOptions?.storage;
6050
+ const existingSessions = loadSessions(storage);
6051
+ const streamingSessions = Array.from(existingSessions.values()).filter(
6052
+ (session) => session.isStreaming
6053
+ );
6054
+ if (streamingSessions.length === 0) {
6055
+ clearSessions(storage);
6056
+ return;
6057
+ }
6058
+ if (!agentOptions?.provider?.supportsResume || !agentOptions.provider.resume) {
6059
+ clearSessions(storage);
6060
+ return;
6061
+ }
6062
+ const streamingSessionsMap = new Map(
6063
+ streamingSessions.map((session) => [session.id, session])
6064
+ );
6065
+ setSessions(streamingSessionsMap);
6066
+ saveSessions(streamingSessionsMap, storage);
6067
+ for (const existingSession of streamingSessions) {
6068
+ const reacquiredElement = tryReacquireElement(existingSession);
6069
+ if (reacquiredElement) {
6070
+ sessionElements.set(existingSession.id, reacquiredElement);
6071
+ }
6072
+ const sessionWithResumeStatus = {
6073
+ ...existingSession,
6074
+ lastStatus: existingSession.lastStatus || "Resuming...",
6075
+ position: existingSession.position ?? { x: window.innerWidth / 2, y: window.innerHeight / 2 }
6076
+ };
6077
+ setSessions((prev) => new Map(prev).set(existingSession.id, sessionWithResumeStatus));
6078
+ agentOptions?.onResume?.(sessionWithResumeStatus);
6079
+ const abortController = new AbortController();
6080
+ abortControllers.set(existingSession.id, abortController);
6081
+ const streamIterator = agentOptions.provider.resume(existingSession.id, abortController.signal);
6082
+ void executeSessionStream(existingSession, streamIterator);
6083
+ }
6084
+ };
6085
+ const startSession = async (params) => {
6086
+ const { element, prompt, position, selectionBounds } = params;
6087
+ const storage = agentOptions?.storage;
6088
+ if (!agentOptions?.provider) {
6089
+ return;
6090
+ }
6091
+ const elements = [element];
6092
+ const content = await generateSnippet(elements);
6093
+ const context = { content, prompt, options: agentOptions?.getOptions?.() };
6094
+ const tagName = (element.tagName || "").toLowerCase() || void 0;
6095
+ const session = createSession(context, position, selectionBounds, tagName);
6096
+ session.lastStatus = "Please wait\u2026";
6097
+ sessionElements.set(session.id, element);
6098
+ setSessions((prev) => new Map(prev).set(session.id, session));
6099
+ saveSessionById(session, storage);
6100
+ agentOptions.onStart?.(session);
6101
+ const abortController = new AbortController();
6102
+ abortControllers.set(session.id, abortController);
6103
+ const streamIterator = agentOptions.provider.send(context, abortController.signal);
6104
+ void executeSessionStream(session, streamIterator);
6105
+ };
6106
+ const abortSession = (sessionId) => {
6107
+ const controller = abortControllers.get(sessionId);
6108
+ if (controller) {
6109
+ controller.abort();
5407
6110
  }
5408
6111
  };
6112
+ const abortAllSessions = () => {
6113
+ abortControllers.forEach((controller) => controller.abort());
6114
+ abortControllers.clear();
6115
+ setSessions(/* @__PURE__ */ new Map());
6116
+ clearSessions(agentOptions?.storage);
6117
+ };
6118
+ const updateSessionBoundsOnViewportChange = () => {
6119
+ const currentSessions = sessions();
6120
+ if (currentSessions.size === 0) return;
6121
+ const updatedSessions = new Map(currentSessions);
6122
+ let didUpdate = false;
6123
+ for (const [sessionId, session] of currentSessions) {
6124
+ let element = sessionElements.get(sessionId);
6125
+ if (!element || !document.contains(element)) {
6126
+ const reacquiredElement = tryReacquireElement(session);
6127
+ if (reacquiredElement) {
6128
+ sessionElements.set(sessionId, reacquiredElement);
6129
+ element = reacquiredElement;
6130
+ }
6131
+ }
6132
+ if (element && document.contains(element)) {
6133
+ const newBounds = createElementBounds(element);
6134
+ if (newBounds) {
6135
+ updatedSessions.set(sessionId, { ...session, selectionBounds: newBounds });
6136
+ didUpdate = true;
6137
+ }
6138
+ }
6139
+ }
6140
+ if (didUpdate) {
6141
+ setSessions(updatedSessions);
6142
+ }
6143
+ };
6144
+ const getSessionElement = (sessionId) => {
6145
+ return sessionElements.get(sessionId);
6146
+ };
6147
+ return {
6148
+ sessions,
6149
+ isProcessing,
6150
+ tryResumeSessions,
6151
+ startSession,
6152
+ abortSession,
6153
+ abortAllSessions,
6154
+ updateSessionBoundsOnViewportChange,
6155
+ getSessionElement
6156
+ };
5409
6157
  };
5410
6158
 
5411
6159
  // src/core.tsx
5412
- var _tmpl$9 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">1 element`);
6160
+ var _tmpl$14 = /* @__PURE__ */ template(`<span class="tabular-nums align-middle">`);
5413
6161
  var _tmpl$23 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">&lt;<!>>`);
5414
- var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums text-[10px] ml-1 align-middle"> in `);
6162
+ var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums ml-1 align-middle"> in `);
5415
6163
  var hasInited = false;
5416
6164
  var getScriptOptions = () => {
5417
6165
  if (typeof window === "undefined") return null;
@@ -5461,9 +6209,8 @@ var init = (rawOptions) => {
5461
6209
  hasInited = true;
5462
6210
  const logIntro = () => {
5463
6211
  try {
5464
- const version = "0.0.54";
5465
- const logoSvg = `<svg width="294" height="294" viewBox="0 0 294 294" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_0_3)"><mask id="mask0_0_3" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="294" height="294"><path d="M294 0H0V294H294V0Z" fill="white"/></mask><g mask="url(#mask0_0_3)"><path d="M144.599 47.4924C169.712 27.3959 194.548 20.0265 212.132 30.1797C227.847 39.2555 234.881 60.3243 231.926 89.516C231.677 92.0069 231.328 94.5423 230.94 97.1058L228.526 110.14C228.517 110.136 228.505 110.132 228.495 110.127C228.486 110.165 228.479 110.203 228.468 110.24L216.255 105.741C216.256 105.736 216.248 105.728 216.248 105.723C207.915 103.125 199.421 101.075 190.82 99.5888L190.696 99.5588L173.526 97.2648L173.511 97.2631C173.492 97.236 173.467 97.2176 173.447 97.1905C163.862 96.2064 154.233 95.7166 144.599 95.7223C134.943 95.7162 125.295 96.219 115.693 97.2286C110.075 105.033 104.859 113.118 100.063 121.453C95.2426 129.798 90.8624 138.391 86.939 147.193C90.8624 155.996 95.2426 164.588 100.063 172.933C104.866 181.302 110.099 189.417 115.741 197.245C115.749 197.245 115.758 197.246 115.766 197.247L115.752 197.27L115.745 197.283L115.754 197.296L126.501 211.013L126.574 211.089C132.136 217.767 138.126 224.075 144.507 229.974L144.609 230.082L154.572 238.287C154.539 238.319 154.506 238.35 154.472 238.38C154.485 238.392 154.499 238.402 154.513 238.412L143.846 247.482L143.827 247.497C126.56 261.128 109.472 268.745 94.8019 268.745C88.5916 268.837 82.4687 267.272 77.0657 264.208C61.3496 255.132 54.3164 234.062 57.2707 204.871C57.528 202.307 57.8806 199.694 58.2904 197.054C28.3363 185.327 9.52301 167.51 9.52301 147.193C9.52301 129.042 24.2476 112.396 50.9901 100.375C53.3443 99.3163 55.7938 98.3058 58.2904 97.3526C57.8806 94.7023 57.528 92.0803 57.2707 89.516C54.3164 60.3243 61.3496 39.2555 77.0657 30.1797C94.6494 20.0265 119.486 27.3959 144.599 47.4924ZM70.6423 201.315C70.423 202.955 70.2229 204.566 70.0704 206.168C67.6686 229.567 72.5478 246.628 83.3615 252.988L83.5176 253.062C95.0399 259.717 114.015 254.426 134.782 238.38C125.298 229.45 116.594 219.725 108.764 209.314C95.8516 207.742 83.0977 205.066 70.6423 201.315ZM80.3534 163.438C77.34 171.677 74.8666 180.104 72.9484 188.664C81.1787 191.224 89.5657 193.247 98.0572 194.724L98.4618 194.813C95.2115 189.865 92.0191 184.66 88.9311 179.378C85.8433 174.097 83.003 168.768 80.3534 163.438ZM60.759 110.203C59.234 110.839 57.7378 111.475 56.27 112.11C34.7788 121.806 22.3891 134.591 22.3891 147.193C22.3891 160.493 36.4657 174.297 60.7494 184.26C63.7439 171.581 67.8124 159.182 72.9104 147.193C67.822 135.23 63.7566 122.855 60.759 110.203ZM98.4137 99.6404C89.8078 101.145 81.3075 103.206 72.9676 105.809C74.854 114.203 77.2741 122.468 80.2132 130.554L80.3059 130.939C82.9938 125.6 85.8049 120.338 88.8834 115.008C91.9618 109.679 95.1544 104.569 98.4137 99.6404ZM94.9258 38.5215C90.9331 38.4284 86.9866 39.3955 83.4891 41.3243C72.6291 47.6015 67.6975 64.5954 70.0424 87.9446L70.0416 88.2194C70.194 89.8208 70.3941 91.4325 70.6134 93.0624C83.0737 89.3364 95.8263 86.6703 108.736 85.0924C116.57 74.6779 125.28 64.9532 134.773 56.0249C119.877 44.5087 105.895 38.5215 94.9258 38.5215ZM205.737 41.3148C202.268 39.398 198.355 38.4308 194.394 38.5099L194.29 38.512C183.321 38.512 169.34 44.4991 154.444 56.0153C163.93 64.9374 172.634 74.6557 180.462 85.064C193.375 86.6345 206.128 89.3102 218.584 93.0624C218.812 91.4325 219.003 89.8118 219.165 88.2098C221.548 64.7099 216.65 47.6164 205.737 41.3148ZM144.552 64.3097C138.104 70.2614 132.054 76.6306 126.443 83.3765C132.39 82.995 138.426 82.8046 144.552 82.8046C150.727 82.8046 156.778 83.0143 162.707 83.3765C157.08 76.6293 151.015 70.2596 144.552 64.3097Z" fill="white"/><path d="M144.598 47.4924C169.712 27.3959 194.547 20.0265 212.131 30.1797C227.847 39.2555 234.88 60.3243 231.926 89.516C231.677 92.0069 231.327 94.5423 230.941 97.1058L228.526 110.14L228.496 110.127C228.487 110.165 228.478 110.203 228.469 110.24L216.255 105.741L216.249 105.723C207.916 103.125 199.42 101.075 190.82 99.5888L190.696 99.5588L173.525 97.2648L173.511 97.263C173.492 97.236 173.468 97.2176 173.447 97.1905C163.863 96.2064 154.234 95.7166 144.598 95.7223C134.943 95.7162 125.295 96.219 115.693 97.2286C110.075 105.033 104.859 113.118 100.063 121.453C95.2426 129.798 90.8622 138.391 86.939 147.193C90.8622 155.996 95.2426 164.588 100.063 172.933C104.866 181.302 110.099 189.417 115.741 197.245L115.766 197.247L115.752 197.27L115.745 197.283L115.754 197.296L126.501 211.013L126.574 211.089C132.136 217.767 138.126 224.075 144.506 229.974L144.61 230.082L154.572 238.287C154.539 238.319 154.506 238.35 154.473 238.38L154.512 238.412L143.847 247.482L143.827 247.497C126.56 261.13 109.472 268.745 94.8018 268.745C88.5915 268.837 82.4687 267.272 77.0657 264.208C61.3496 255.132 54.3162 234.062 57.2707 204.871C57.528 202.307 57.8806 199.694 58.2904 197.054C28.3362 185.327 9.52298 167.51 9.52298 147.193C9.52298 129.042 24.2476 112.396 50.9901 100.375C53.3443 99.3163 55.7938 98.3058 58.2904 97.3526C57.8806 94.7023 57.528 92.0803 57.2707 89.516C54.3162 60.3243 61.3496 39.2555 77.0657 30.1797C94.6493 20.0265 119.486 27.3959 144.598 47.4924ZM70.6422 201.315C70.423 202.955 70.2229 204.566 70.0704 206.168C67.6686 229.567 72.5478 246.628 83.3615 252.988L83.5175 253.062C95.0399 259.717 114.015 254.426 134.782 238.38C125.298 229.45 116.594 219.725 108.764 209.314C95.8515 207.742 83.0977 205.066 70.6422 201.315ZM80.3534 163.438C77.34 171.677 74.8666 180.104 72.9484 188.664C81.1786 191.224 89.5657 193.247 98.0572 194.724L98.4618 194.813C95.2115 189.865 92.0191 184.66 88.931 179.378C85.8433 174.097 83.003 168.768 80.3534 163.438ZM60.7589 110.203C59.234 110.839 57.7378 111.475 56.2699 112.11C34.7788 121.806 22.3891 134.591 22.3891 147.193C22.3891 160.493 36.4657 174.297 60.7494 184.26C63.7439 171.581 67.8124 159.182 72.9103 147.193C67.822 135.23 63.7566 122.855 60.7589 110.203ZM98.4137 99.6404C89.8078 101.145 81.3075 103.206 72.9676 105.809C74.8539 114.203 77.2741 122.468 80.2132 130.554L80.3059 130.939C82.9938 125.6 85.8049 120.338 88.8834 115.008C91.9618 109.679 95.1544 104.569 98.4137 99.6404ZM94.9258 38.5215C90.9331 38.4284 86.9866 39.3955 83.4891 41.3243C72.629 47.6015 67.6975 64.5954 70.0424 87.9446L70.0415 88.2194C70.194 89.8208 70.3941 91.4325 70.6134 93.0624C83.0737 89.3364 95.8262 86.6703 108.736 85.0924C116.57 74.6779 125.28 64.9532 134.772 56.0249C119.877 44.5087 105.895 38.5215 94.9258 38.5215ZM205.737 41.3148C202.268 39.398 198.355 38.4308 194.394 38.5099L194.291 38.512C183.321 38.512 169.34 44.4991 154.443 56.0153C163.929 64.9374 172.634 74.6557 180.462 85.064C193.374 86.6345 206.129 89.3102 218.584 93.0624C218.813 91.4325 219.003 89.8118 219.166 88.2098C221.548 64.7099 216.65 47.6164 205.737 41.3148ZM144.551 64.3097C138.103 70.2614 132.055 76.6306 126.443 83.3765C132.389 82.995 138.427 82.8046 144.551 82.8046C150.727 82.8046 156.779 83.0143 162.707 83.3765C157.079 76.6293 151.015 70.2596 144.551 64.3097Z" fill="#FF40E0"/></g><mask id="mask1_0_3" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="102" y="84" width="161" height="162"><path d="M235.282 84.827L102.261 112.259L129.693 245.28L262.714 217.848L235.282 84.827Z" fill="white"/></mask><g mask="url(#mask1_0_3)"><path d="M136.863 129.916L213.258 141.224C220.669 142.322 222.495 152.179 215.967 155.856L187.592 171.843L184.135 204.227C183.339 211.678 173.564 213.901 169.624 207.526L129.021 141.831C125.503 136.14 130.245 128.936 136.863 129.916Z" fill="#FF40E0" stroke="#FF40E0" stroke-width="0.817337" stroke-linecap="round" stroke-linejoin="round"/></g></g><defs><clipPath id="clip0_0_3"><rect width="294" height="294" fill="white"/></clipPath></defs></svg>`;
5466
- const logoDataUri = `data:image/svg+xml;base64,${btoa(logoSvg)}`;
6212
+ const version = "0.0.56";
6213
+ const logoDataUri = `data:image/svg+xml;base64,${btoa(LOGO_SVG)}`;
5467
6214
  console.log(`%cReact Grab${version ? ` v${version}` : ""}%c
5468
6215
  https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid #d75fcb; padding: 4px 4px 4px 24px; border-radius: 4px; background-image: url("${logoDataUri}"); background-size: 16px 16px; background-repeat: no-repeat; background-position: 4px center; display: inline-block; margin-bottom: 4px;`, "");
5469
6216
  if (navigator.onLine && version) {
@@ -5481,9 +6228,7 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5481
6228
  } catch {
5482
6229
  }
5483
6230
  };
5484
- if (options.log !== false) {
5485
- logIntro();
5486
- }
6231
+ logIntro();
5487
6232
  return createRoot((dispose2) => {
5488
6233
  const [theme, setTheme] = createSignal(initialTheme);
5489
6234
  const [isHoldingKeys, setIsHoldingKeys] = createSignal(false);
@@ -5493,32 +6238,85 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5493
6238
  const [dragStartX, setDragStartX] = createSignal(OFFSCREEN_POSITION);
5494
6239
  const [dragStartY, setDragStartY] = createSignal(OFFSCREEN_POSITION);
5495
6240
  const [isCopying, setIsCopying] = createSignal(false);
6241
+ const [selectionLabelStatus, setSelectionLabelStatus] = createSignal("idle");
6242
+ const [labelInstances, setLabelInstances] = createSignal([]);
5496
6243
  const [lastGrabbedElement, setLastGrabbedElement] = createSignal(null);
5497
6244
  const [progressStartTime, setProgressStartTime] = createSignal(null);
5498
- const [progress, setProgress] = createSignal(0);
5499
6245
  const [grabbedBoxes, setGrabbedBoxes] = createSignal([]);
5500
6246
  const [successLabels, setSuccessLabels] = createSignal([]);
5501
6247
  const [isActivated, setIsActivated] = createSignal(false);
5502
6248
  const [isToggleMode, setIsToggleMode] = createSignal(false);
5503
- const [showProgressIndicator, setShowProgressIndicator] = createSignal(false);
5504
6249
  const [didJustDrag, setDidJustDrag] = createSignal(false);
5505
6250
  const [copyStartX, setCopyStartX] = createSignal(OFFSCREEN_POSITION);
5506
6251
  const [copyStartY, setCopyStartY] = createSignal(OFFSCREEN_POSITION);
5507
- const [mouseHasSettled, setMouseHasSettled] = createSignal(false);
5508
6252
  const [viewportVersion, setViewportVersion] = createSignal(0);
5509
6253
  const [isInputMode, setIsInputMode] = createSignal(false);
5510
6254
  const [inputText, setInputText] = createSignal("");
5511
6255
  const [isTouchMode, setIsTouchMode] = createSignal(false);
6256
+ const [selectionFilePath, setSelectionFilePath] = createSignal(void 0);
6257
+ const [selectionLineNumber, setSelectionLineNumber] = createSignal(void 0);
6258
+ const [isToggleFrozen, setIsToggleFrozen] = createSignal(false);
6259
+ const [isInputExpanded, setIsInputExpanded] = createSignal(false);
6260
+ const [frozenElement, setFrozenElement] = createSignal(null);
6261
+ const [nativeSelectionCursorX, setNativeSelectionCursorX] = createSignal(OFFSCREEN_POSITION);
6262
+ const [nativeSelectionCursorY, setNativeSelectionCursorY] = createSignal(OFFSCREEN_POSITION);
6263
+ const [hasNativeSelection, setHasNativeSelection] = createSignal(false);
6264
+ const [nativeSelectionElements, setNativeSelectionElements] = createSignal([]);
6265
+ const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
6266
+ const nativeSelectionTagName = createMemo(() => {
6267
+ const elements = nativeSelectionElements();
6268
+ if (elements.length === 0 || !elements[0]) return void 0;
6269
+ return extractElementTagName(elements[0]) || void 0;
6270
+ });
6271
+ const nativeSelectionComponentName = createMemo(() => {
6272
+ const elements = nativeSelectionElements();
6273
+ if (elements.length === 0 || !elements[0]) return void 0;
6274
+ return getNearestComponentName(elements[0]) || void 0;
6275
+ });
6276
+ const clearNativeSelectionState = () => {
6277
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
6278
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
6279
+ setNativeSelectionElements([]);
6280
+ };
6281
+ const recalculateNativeSelectionCursor = () => {
6282
+ const currentSelection = window.getSelection();
6283
+ if (!currentSelection || currentSelection.isCollapsed || currentSelection.rangeCount === 0) {
6284
+ return;
6285
+ }
6286
+ const range = currentSelection.getRangeAt(0);
6287
+ const clientRects = range.getClientRects();
6288
+ if (clientRects.length === 0) return;
6289
+ const isBackward = (() => {
6290
+ if (!currentSelection.anchorNode || !currentSelection.focusNode) return false;
6291
+ const position = currentSelection.anchorNode.compareDocumentPosition(currentSelection.focusNode);
6292
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return false;
6293
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return true;
6294
+ return currentSelection.anchorOffset > currentSelection.focusOffset;
6295
+ })();
6296
+ const cursorRect = isBackward ? clientRects[0] : clientRects[clientRects.length - 1];
6297
+ const cursorX = isBackward ? cursorRect.left : cursorRect.right;
6298
+ const cursorY = cursorRect.top + cursorRect.height / 2;
6299
+ setNativeSelectionCursorX(cursorX);
6300
+ setNativeSelectionCursorY(cursorY);
6301
+ };
6302
+ createEffect(on(() => viewportVersion(), () => {
6303
+ if (hasNativeSelection()) {
6304
+ recalculateNativeSelectionCursor();
6305
+ }
6306
+ }));
6307
+ const nativeSelectionBounds = createMemo(() => {
6308
+ viewportVersion();
6309
+ const elements = nativeSelectionElements();
6310
+ if (elements.length === 0 || !elements[0]) return void 0;
6311
+ return createElementBounds(elements[0]);
6312
+ });
5512
6313
  let holdTimerId = null;
6314
+ let activationTimestamp = null;
5513
6315
  let progressAnimationId = null;
5514
- let progressDelayTimerId = null;
5515
6316
  let keydownSpamTimerId = null;
5516
- let mouseSettleTimerId = null;
5517
6317
  let autoScrollAnimationId = null;
5518
6318
  let previouslyFocusedElement = null;
5519
6319
  const isRendererActive = createMemo(() => isActivated() && !isCopying());
5520
- const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
5521
- const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && isCLikeKey(event.key, event.code);
5522
6320
  const getAutoScrollDirection = (clientX, clientY) => {
5523
6321
  return {
5524
6322
  top: clientY < AUTO_SCROLL_EDGE_THRESHOLD_PX,
@@ -5557,10 +6355,6 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5557
6355
  setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
5558
6356
  }, SUCCESS_LABEL_DURATION_MS);
5559
6357
  };
5560
- const wrapInSelectedElementTags = (context) => `<selected_element>
5561
- ${context}
5562
- </selected_element>`;
5563
- const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
5564
6358
  const extractElementTagNameForSuccess = (element) => {
5565
6359
  const tagName = extractElementTagName(element);
5566
6360
  return tagName ? `<${tagName}>` : "1 element";
@@ -5575,16 +6369,49 @@ ${context}
5575
6369
  }
5576
6370
  }));
5577
6371
  };
5578
- const executeCopyOperation = async (positionX, positionY, operation) => {
6372
+ const createLabelInstance = (bounds, tagName, status, element) => {
6373
+ const instanceId = `label-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6374
+ setLabelInstances((prev) => [...prev, {
6375
+ id: instanceId,
6376
+ bounds,
6377
+ tagName,
6378
+ status,
6379
+ createdAt: Date.now(),
6380
+ element
6381
+ }]);
6382
+ return instanceId;
6383
+ };
6384
+ const updateLabelInstance = (instanceId, status) => {
6385
+ setLabelInstances((prev) => prev.map((instance) => instance.id === instanceId ? {
6386
+ ...instance,
6387
+ status
6388
+ } : instance));
6389
+ };
6390
+ const removeLabelInstance = (instanceId) => {
6391
+ setLabelInstances((prev) => prev.filter((instance) => instance.id !== instanceId));
6392
+ };
6393
+ const executeCopyOperation = async (positionX, positionY, operation, bounds, tagName, element) => {
5579
6394
  setCopyStartX(positionX);
5580
6395
  setCopyStartY(positionY);
5581
6396
  setIsCopying(true);
5582
6397
  startProgressAnimation();
6398
+ const instanceId = bounds && tagName ? createLabelInstance(bounds, tagName, "copying", element) : null;
5583
6399
  await operation().finally(() => {
5584
6400
  setIsCopying(false);
5585
6401
  stopProgressAnimation();
6402
+ if (instanceId) {
6403
+ updateLabelInstance(instanceId, "copied");
6404
+ setTimeout(() => {
6405
+ updateLabelInstance(instanceId, "fading");
6406
+ setTimeout(() => {
6407
+ removeLabelInstance(instanceId);
6408
+ }, 350);
6409
+ }, COPIED_LABEL_DURATION_MS);
6410
+ }
5586
6411
  if (isToggleMode()) {
5587
- deactivateRenderer();
6412
+ setTimeout(() => {
6413
+ deactivateRenderer();
6414
+ }, COPIED_LABEL_DURATION_MS + 350);
5588
6415
  }
5589
6416
  });
5590
6417
  };
@@ -5599,53 +6426,20 @@ ${context}
5599
6426
  const tryCopyWithFallback = async (elements, extraPrompt) => {
5600
6427
  let didCopy = false;
5601
6428
  let copiedContent = "";
5602
- const isReactProject = Ee();
5603
6429
  await options.onBeforeCopy?.(elements);
5604
- if (options.copyFileOnly && isReactProject) {
5605
- try {
5606
- const firstElement = elements[0];
5607
- if (firstElement) {
5608
- const stack = await getStack(firstElement);
5609
- const fileName = getFileName(stack);
5610
- if (fileName) {
5611
- copiedContent = `@${fileName}`;
5612
- didCopy = await copyContent(copiedContent);
5613
- if (didCopy) {
5614
- options.onCopySuccess?.(elements, copiedContent);
5615
- }
5616
- }
5617
- }
5618
- } catch (error) {
5619
- options.onCopyError?.(error);
5620
- }
5621
- options.onAfterCopy?.(elements, didCopy);
5622
- return didCopy;
5623
- }
5624
6430
  try {
5625
- const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => {
5626
- const htmlPreview = getHTMLPreview(element);
5627
- if (!isReactProject) {
5628
- return `## HTML Frame:
5629
- ${htmlPreview}`;
5630
- }
5631
- const stack = await getStack(element);
5632
- const formattedStack = formatStack(stack);
5633
- if (formattedStack) {
5634
- return `## HTML Frame:
5635
- ${htmlPreview}
5636
-
5637
- ## Code Location:
5638
- ${formattedStack}`;
6431
+ const elementSnippetResults = await Promise.allSettled(elements.map((element) => formatElementInfo(element)));
6432
+ const elementSnippets = [];
6433
+ for (const result of elementSnippetResults) {
6434
+ if (result.status === "fulfilled" && result.value.trim()) {
6435
+ elementSnippets.push(result.value);
5639
6436
  }
5640
- return `## HTML Frame:
5641
- ${htmlPreview}`;
5642
- }));
5643
- const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
6437
+ }
5644
6438
  if (elementSnippets.length > 0) {
5645
- const wrappedSnippets = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
6439
+ const combinedSnippets = elementSnippets.join("\n\n");
5646
6440
  const plainTextContent = extraPrompt ? `${extraPrompt}
5647
6441
 
5648
- ${wrappedSnippets}` : wrappedSnippets;
6442
+ ${combinedSnippets}` : combinedSnippets;
5649
6443
  copiedContent = plainTextContent;
5650
6444
  didCopy = await copyContent(plainTextContent);
5651
6445
  }
@@ -5710,20 +6504,17 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5710
6504
  if (!isRendererActive() || isDragging()) return null;
5711
6505
  return getElementAtPosition(mouseX(), mouseY());
5712
6506
  });
6507
+ createEffect(() => {
6508
+ const element = targetElement();
6509
+ if (element) {
6510
+ setFrozenElement(element);
6511
+ }
6512
+ });
5713
6513
  const selectionBounds = createMemo(() => {
5714
6514
  viewportVersion();
5715
6515
  const element = targetElement();
5716
6516
  if (!element) return void 0;
5717
- const elementBounds = element.getBoundingClientRect();
5718
- const computedStyle = window.getComputedStyle(element);
5719
- return {
5720
- borderRadius: computedStyle.borderRadius || "0px",
5721
- height: elementBounds.height,
5722
- transform: stripTranslateFromTransform(element),
5723
- width: elementBounds.width,
5724
- x: elementBounds.left,
5725
- y: elementBounds.top
5726
- };
6517
+ return createElementBounds(element);
5727
6518
  });
5728
6519
  const calculateDragDistance = (endX, endY) => {
5729
6520
  const endPageX = endX + window.scrollX;
@@ -5766,7 +6557,14 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5766
6557
  });
5767
6558
  const labelContent = createMemo(() => {
5768
6559
  const element = targetElement();
5769
- if (!element) return _tmpl$9();
6560
+ const copying = isCopying();
6561
+ if (!element) {
6562
+ return (() => {
6563
+ var _el$ = _tmpl$14();
6564
+ insert(_el$, copying ? "Please wait\u2026" : "1 element");
6565
+ return _el$;
6566
+ })();
6567
+ }
5770
6568
  const tagName = extractElementTagName(element);
5771
6569
  const componentName = getNearestComponentName(element);
5772
6570
  if (tagName && componentName) {
@@ -5787,16 +6585,13 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5787
6585
  return _el$8;
5788
6586
  })();
5789
6587
  }
5790
- return _tmpl$9();
6588
+ return (() => {
6589
+ var _el$10 = _tmpl$14();
6590
+ insert(_el$10, copying ? "Please wait\u2026" : "1 element");
6591
+ return _el$10;
6592
+ })();
5791
6593
  });
5792
- const labelPosition = createMemo(() => isCopying() ? {
5793
- x: copyStartX(),
5794
- y: copyStartY()
5795
- } : {
5796
- x: mouseX(),
5797
- y: mouseY()
5798
- });
5799
- const progressPosition = createMemo(() => isCopying() ? {
6594
+ const cursorPosition = createMemo(() => isCopying() ? {
5800
6595
  x: copyStartX(),
5801
6596
  y: copyStartY()
5802
6597
  } : {
@@ -5811,6 +6606,26 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5811
6606
  options.onElementHover?.(currentElement);
5812
6607
  }
5813
6608
  }));
6609
+ createEffect(on(() => targetElement(), (element) => {
6610
+ const clearSource = () => {
6611
+ setSelectionFilePath(void 0);
6612
+ setSelectionLineNumber(void 0);
6613
+ };
6614
+ if (!element) {
6615
+ clearSource();
6616
+ return;
6617
+ }
6618
+ getStack(element).then((stack) => {
6619
+ for (const frame of stack) {
6620
+ if (frame.source && je2(frame.source.fileName)) {
6621
+ setSelectionFilePath(Q(frame.source.fileName));
6622
+ setSelectionLineNumber(frame.source.lineNumber);
6623
+ return;
6624
+ }
6625
+ }
6626
+ clearSource();
6627
+ }).catch(clearSource);
6628
+ }));
5814
6629
  createEffect(on(() => viewportVersion(), () => {
5815
6630
  const currentBoxes = grabbedBoxes();
5816
6631
  if (currentBoxes.length === 0) return;
@@ -5820,6 +6635,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5820
6635
  }));
5821
6636
  setGrabbedBoxes(updatedBoxes);
5822
6637
  }));
6638
+ createEffect(on(() => viewportVersion(), () => agentManager.updateSessionBoundsOnViewportChange()));
5823
6639
  createEffect(on(() => [isActivated(), isDragging(), isCopying(), isInputMode(), targetElement(), dragBounds()], ([active, dragging, copying, inputMode, target, drag]) => {
5824
6640
  options.onStateChange?.({
5825
6641
  isActive: active,
@@ -5854,7 +6670,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5854
6670
  y: y2
5855
6671
  });
5856
6672
  }));
5857
- createEffect(on(() => [labelVisible(), labelVariant(), labelContent(), labelPosition()], ([visible, variant, content, position]) => {
6673
+ createEffect(on(() => [labelVisible(), labelVariant(), labelContent(), cursorPosition()], ([visible, variant, content, position]) => {
5858
6674
  const contentString = typeof content === "string" ? content : "";
5859
6675
  options.onElementLabel?.(Boolean(visible), variant, {
5860
6676
  x: position.x,
@@ -5862,23 +6678,47 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5862
6678
  content: contentString
5863
6679
  });
5864
6680
  }));
5865
- const startProgressAnimation = () => {
6681
+ let cursorStyleElement = null;
6682
+ const setCursorOverride = (cursor) => {
6683
+ if (cursor) {
6684
+ if (!cursorStyleElement) {
6685
+ cursorStyleElement = document.createElement("style");
6686
+ cursorStyleElement.setAttribute("data-react-grab-cursor", "");
6687
+ document.head.appendChild(cursorStyleElement);
6688
+ }
6689
+ cursorStyleElement.textContent = `* { cursor: ${cursor} !important; }`;
6690
+ } else if (cursorStyleElement) {
6691
+ cursorStyleElement.remove();
6692
+ cursorStyleElement = null;
6693
+ }
6694
+ };
6695
+ createEffect(on(() => [isActivated(), isCopying(), isDragging(), isInputMode(), targetElement()], ([activated, copying, dragging, inputMode, target]) => {
6696
+ if (copying) {
6697
+ setCursorOverride("progress");
6698
+ } else if (inputMode) {
6699
+ setCursorOverride(null);
6700
+ } else if (activated && dragging) {
6701
+ setCursorOverride("crosshair");
6702
+ } else if (activated && target) {
6703
+ setCursorOverride("copy");
6704
+ } else if (activated) {
6705
+ setCursorOverride("crosshair");
6706
+ } else {
6707
+ setCursorOverride(null);
6708
+ }
6709
+ }));
6710
+ const startProgressAnimation = (duration) => {
5866
6711
  const startTime = Date.now();
6712
+ const animationDuration = options.keyHoldDuration;
5867
6713
  setProgressStartTime(startTime);
5868
- setShowProgressIndicator(false);
5869
- progressDelayTimerId = window.setTimeout(() => {
5870
- setShowProgressIndicator(true);
5871
- progressDelayTimerId = null;
5872
- }, PROGRESS_INDICATOR_DELAY_MS);
5873
6714
  const animateProgress = () => {
5874
6715
  const currentStartTime = progressStartTime();
5875
6716
  if (currentStartTime === null) return;
5876
6717
  const elapsedTime = Date.now() - currentStartTime;
5877
- const normalizedTime = elapsedTime / options.keyHoldDuration;
6718
+ const normalizedTime = elapsedTime / animationDuration;
5878
6719
  const easedProgress = 1 - Math.exp(-normalizedTime);
5879
6720
  const maxProgressBeforeCompletion = 0.95;
5880
6721
  const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
5881
- setProgress(currentProgress);
5882
6722
  if (currentProgress < 1) {
5883
6723
  progressAnimationId = requestAnimationFrame(animateProgress);
5884
6724
  }
@@ -5890,13 +6730,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5890
6730
  cancelAnimationFrame(progressAnimationId);
5891
6731
  progressAnimationId = null;
5892
6732
  }
5893
- if (progressDelayTimerId !== null) {
5894
- window.clearTimeout(progressDelayTimerId);
5895
- progressDelayTimerId = null;
5896
- }
5897
6733
  setProgressStartTime(null);
5898
- setProgress(1);
5899
- setShowProgressIndicator(false);
5900
6734
  };
5901
6735
  const startAutoScroll = () => {
5902
6736
  const scroll = () => {
@@ -5926,8 +6760,8 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5926
6760
  const activateRenderer = () => {
5927
6761
  stopProgressAnimation();
5928
6762
  previouslyFocusedElement = document.activeElement;
6763
+ activationTimestamp = Date.now();
5929
6764
  setIsActivated(true);
5930
- document.body.style.cursor = "crosshair";
5931
6765
  options.onActivate?.();
5932
6766
  };
5933
6767
  const deactivateRenderer = () => {
@@ -5936,61 +6770,130 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5936
6770
  setIsActivated(false);
5937
6771
  setIsInputMode(false);
5938
6772
  setInputText("");
5939
- document.body.style.cursor = "";
6773
+ setIsToggleFrozen(false);
6774
+ setIsInputExpanded(false);
6775
+ setFrozenElement(null);
6776
+ setSelectionLabelStatus("idle");
5940
6777
  if (isDragging()) {
5941
6778
  setIsDragging(false);
5942
6779
  document.body.style.userSelect = "";
5943
6780
  }
5944
6781
  if (holdTimerId) window.clearTimeout(holdTimerId);
5945
6782
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
5946
- if (mouseSettleTimerId) {
5947
- window.clearTimeout(mouseSettleTimerId);
5948
- mouseSettleTimerId = null;
5949
- }
5950
- setMouseHasSettled(false);
5951
6783
  stopAutoScroll();
5952
6784
  stopProgressAnimation();
6785
+ activationTimestamp = null;
5953
6786
  if (previouslyFocusedElement instanceof HTMLElement && document.contains(previouslyFocusedElement)) {
5954
6787
  previouslyFocusedElement.focus();
5955
6788
  }
5956
6789
  previouslyFocusedElement = null;
5957
6790
  options.onDeactivate?.();
5958
6791
  };
6792
+ const agentOptions = options.agent ? {
6793
+ ...options.agent,
6794
+ onAbort: (session, element) => {
6795
+ options.agent?.onAbort?.(session, element);
6796
+ if (element && document.contains(element)) {
6797
+ const rect = element.getBoundingClientRect();
6798
+ const centerX = rect.left + rect.width / 2;
6799
+ const centerY = rect.top + rect.height / 2;
6800
+ setMouseX(centerX);
6801
+ setMouseY(centerY);
6802
+ setFrozenElement(element);
6803
+ setInputText(session.context.prompt);
6804
+ setIsInputExpanded(true);
6805
+ setIsInputMode(true);
6806
+ setIsToggleMode(true);
6807
+ setIsToggleFrozen(true);
6808
+ if (!isActivated()) {
6809
+ activateRenderer();
6810
+ }
6811
+ }
6812
+ }
6813
+ } : void 0;
6814
+ const agentManager = createAgentManager(agentOptions);
5959
6815
  const handleInputChange = (value) => {
5960
6816
  setInputText(value);
5961
6817
  };
5962
6818
  const handleInputSubmit = () => {
5963
- if (!isInputMode()) return;
5964
- const element = targetElement();
5965
- const prompt = inputText().trim();
5966
- const currentX = mouseX();
5967
- const currentY = mouseY();
6819
+ const element = frozenElement() || targetElement();
6820
+ const prompt = isInputMode() ? inputText().trim() : "";
6821
+ if (!element) {
6822
+ deactivateRenderer();
6823
+ return;
6824
+ }
6825
+ const bounds = createElementBounds(element);
6826
+ const currentX = bounds.x + bounds.width / 2;
6827
+ const currentY = bounds.y + bounds.height / 2;
6828
+ setMouseX(currentX);
6829
+ setMouseY(currentY);
6830
+ if (options.agent?.provider && prompt) {
6831
+ deactivateRenderer();
6832
+ void agentManager.startSession({
6833
+ element,
6834
+ prompt,
6835
+ position: {
6836
+ x: currentX,
6837
+ y: currentY
6838
+ },
6839
+ selectionBounds: bounds
6840
+ });
6841
+ return;
6842
+ }
5968
6843
  setIsInputMode(false);
5969
6844
  setInputText("");
5970
- if (element) {
5971
- void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0)).then(() => {
5972
- deactivateRenderer();
5973
- });
5974
- } else {
6845
+ const tagName = extractElementTagName(element);
6846
+ void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0), bounds, tagName, element).then(() => {
5975
6847
  deactivateRenderer();
5976
- }
6848
+ });
5977
6849
  };
5978
6850
  const handleInputCancel = () => {
5979
6851
  if (!isInputMode()) return;
5980
6852
  deactivateRenderer();
5981
6853
  };
6854
+ const handleToggleExpand = () => {
6855
+ setIsToggleMode(true);
6856
+ setIsToggleFrozen(true);
6857
+ setIsInputExpanded(true);
6858
+ setIsInputMode(true);
6859
+ };
6860
+ const handleNativeSelectionCopy = async () => {
6861
+ const elements = nativeSelectionElements();
6862
+ if (elements.length === 0) return;
6863
+ const currentX = nativeSelectionCursorX();
6864
+ const currentY = nativeSelectionCursorY();
6865
+ const bounds = nativeSelectionBounds();
6866
+ const tagName = nativeSelectionTagName();
6867
+ setHasNativeSelection(false);
6868
+ clearNativeSelectionState();
6869
+ window.getSelection()?.removeAllRanges();
6870
+ if (elements.length === 1) {
6871
+ await executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(elements[0]), bounds, tagName);
6872
+ } else {
6873
+ await executeCopyOperation(currentX, currentY, () => copyMultipleElementsToClipboard(elements), bounds, tagName);
6874
+ }
6875
+ };
6876
+ const handleNativeSelectionEnter = () => {
6877
+ const elements = nativeSelectionElements();
6878
+ if (elements.length === 0) return;
6879
+ const bounds = nativeSelectionBounds();
6880
+ const currentX = bounds ? bounds.x + bounds.width / 2 : nativeSelectionCursorX();
6881
+ const currentY = bounds ? bounds.y + bounds.height / 2 : nativeSelectionCursorY();
6882
+ setHasNativeSelection(false);
6883
+ clearNativeSelectionState();
6884
+ window.getSelection()?.removeAllRanges();
6885
+ setMouseX(currentX);
6886
+ setMouseY(currentY);
6887
+ setIsToggleMode(true);
6888
+ setIsToggleFrozen(true);
6889
+ setIsInputExpanded(true);
6890
+ activateRenderer();
6891
+ setIsInputMode(true);
6892
+ };
5982
6893
  const handlePointerMove = (clientX, clientY) => {
5983
- if (isInputMode()) return;
6894
+ if (isInputMode() || isToggleFrozen()) return;
5984
6895
  setMouseX(clientX);
5985
6896
  setMouseY(clientY);
5986
- if (mouseSettleTimerId !== null) {
5987
- window.clearTimeout(mouseSettleTimerId);
5988
- }
5989
- setMouseHasSettled(false);
5990
- mouseSettleTimerId = window.setTimeout(() => {
5991
- setMouseHasSettled(true);
5992
- mouseSettleTimerId = null;
5993
- }, 300);
5994
6897
  if (isDragging()) {
5995
6898
  const direction = getAutoScrollDirection(clientX, clientY);
5996
6899
  const isNearEdge = direction.top || direction.bottom || direction.left || direction.right;
@@ -6023,37 +6926,68 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6023
6926
  setDidJustDrag(true);
6024
6927
  const dragRect = calculateDragRectangle(clientX, clientY);
6025
6928
  const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
6026
- if (elements.length > 0) {
6027
- options.onDragEnd?.(elements, dragRect);
6028
- void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(elements));
6029
- } else {
6030
- const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
6031
- if (fallbackElements.length > 0) {
6032
- options.onDragEnd?.(fallbackElements, dragRect);
6033
- void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(fallbackElements));
6929
+ const selectedElements = elements.length > 0 ? elements : getElementsInDragLoose(dragRect, isValidGrabbableElement);
6930
+ if (selectedElements.length > 0) {
6931
+ options.onDragEnd?.(selectedElements, dragRect);
6932
+ const firstElement = selectedElements[0];
6933
+ const firstElementRect = firstElement.getBoundingClientRect();
6934
+ const bounds = {
6935
+ x: firstElementRect.left,
6936
+ y: firstElementRect.top,
6937
+ width: firstElementRect.width,
6938
+ height: firstElementRect.height,
6939
+ borderRadius: "0px",
6940
+ transform: stripTranslateFromTransform(firstElement)
6941
+ };
6942
+ const tagName = extractElementTagName(firstElement);
6943
+ if (options.agent?.provider) {
6944
+ const centerX = bounds.x + bounds.width / 2;
6945
+ const centerY = bounds.y + bounds.height / 2;
6946
+ setMouseX(centerX);
6947
+ setMouseY(centerY);
6948
+ setFrozenElement(firstElement);
6949
+ setIsToggleMode(true);
6950
+ setIsToggleFrozen(true);
6951
+ setIsInputExpanded(true);
6952
+ setIsInputMode(true);
6953
+ } else {
6954
+ void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(selectedElements), bounds, tagName, firstElement);
6034
6955
  }
6035
6956
  }
6036
6957
  } else {
6037
6958
  const element = getElementAtPosition(clientX, clientY);
6038
6959
  if (!element) return;
6039
6960
  setLastGrabbedElement(element);
6040
- void executeCopyOperation(clientX, clientY, () => copySingleElementToClipboard(element));
6961
+ const bounds = createElementBounds(element);
6962
+ const tagName = extractElementTagName(element);
6963
+ void executeCopyOperation(clientX, clientY, () => copySingleElementToClipboard(element), bounds, tagName, element);
6041
6964
  }
6042
6965
  };
6043
6966
  const abortController = new AbortController();
6044
6967
  const eventListenerSignal = abortController.signal;
6045
6968
  window.addEventListener("keydown", (event) => {
6046
- if (event.key === "Escape" && isHoldingKeys()) {
6047
- if (isInputMode()) {
6048
- return;
6969
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
6970
+ if (event.key === "Escape" && agentManager.isProcessing()) {
6971
+ agentManager.abortAllSessions();
6049
6972
  }
6050
- deactivateRenderer();
6051
6973
  return;
6052
6974
  }
6975
+ if (event.key === "Escape") {
6976
+ if (agentManager.isProcessing()) {
6977
+ agentManager.abortAllSessions();
6978
+ return;
6979
+ }
6980
+ if (isHoldingKeys()) {
6981
+ deactivateRenderer();
6982
+ return;
6983
+ }
6984
+ }
6053
6985
  if (event.key === "Enter" && isHoldingKeys() && !isInputMode()) {
6054
6986
  event.preventDefault();
6055
6987
  event.stopPropagation();
6056
6988
  setIsToggleMode(true);
6989
+ setIsToggleFrozen(true);
6990
+ setIsInputExpanded(true);
6057
6991
  if (keydownSpamTimerId !== null) {
6058
6992
  window.clearTimeout(keydownSpamTimerId);
6059
6993
  keydownSpamTimerId = null;
@@ -6065,15 +6999,42 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6065
6999
  setIsInputMode(true);
6066
7000
  return;
6067
7001
  }
7002
+ if (event.key.toLowerCase() === "o" && !isInputMode()) {
7003
+ if (isActivated() && (event.metaKey || event.ctrlKey)) {
7004
+ const filePath = selectionFilePath();
7005
+ const lineNumber = selectionLineNumber();
7006
+ if (filePath) {
7007
+ event.preventDefault();
7008
+ event.stopPropagation();
7009
+ if (options.onOpenFile) {
7010
+ options.onOpenFile(filePath, lineNumber);
7011
+ } else {
7012
+ const url = buildOpenFileUrl(filePath, lineNumber);
7013
+ window.open(url, "_blank");
7014
+ }
7015
+ }
7016
+ return;
7017
+ }
7018
+ }
6068
7019
  if (!options.allowActivationInsideInput && isKeyboardEventTriggeredByInput(event)) {
6069
7020
  return;
6070
7021
  }
6071
- if (!isTargetKeyCombination(event)) return;
6072
- if (isActivated() || isHoldingKeys()) {
7022
+ if (!isTargetKeyCombination(event, options)) {
7023
+ if (isActivated() && !isToggleMode() && (event.metaKey || event.ctrlKey)) {
7024
+ if (!MODIFIER_KEYS.includes(event.key) && event.key !== "Enter") {
7025
+ deactivateRenderer();
7026
+ }
7027
+ }
7028
+ if (event.key !== "Enter") {
7029
+ return;
7030
+ }
7031
+ }
7032
+ if ((isActivated() || isHoldingKeys()) && !isInputMode()) {
6073
7033
  event.preventDefault();
6074
7034
  }
6075
7035
  if (isActivated()) {
6076
7036
  if (isToggleMode()) return;
7037
+ if (event.repeat) return;
6077
7038
  if (keydownSpamTimerId !== null) {
6078
7039
  window.clearTimeout(keydownSpamTimerId);
6079
7040
  }
@@ -6098,9 +7059,44 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6098
7059
  });
6099
7060
  window.addEventListener("keyup", (event) => {
6100
7061
  if (!isHoldingKeys() && !isActivated()) return;
6101
- const isReleasingModifier = !event.metaKey && !event.ctrlKey;
6102
- const isReleasingC = isCLikeKey(event.key, event.code);
6103
- if (isReleasingC || isReleasingModifier) {
7062
+ if (isInputMode()) return;
7063
+ const hasCustomShortcut = Boolean(options.activationShortcut || options.activationKey);
7064
+ const getRequiredModifiers = () => {
7065
+ if (options.activationKey) {
7066
+ const {
7067
+ metaKey,
7068
+ ctrlKey,
7069
+ shiftKey,
7070
+ altKey
7071
+ } = options.activationKey;
7072
+ return {
7073
+ metaKey: !!metaKey,
7074
+ ctrlKey: !!ctrlKey,
7075
+ shiftKey: !!shiftKey,
7076
+ altKey: !!altKey
7077
+ };
7078
+ }
7079
+ return {
7080
+ metaKey: true,
7081
+ ctrlKey: true,
7082
+ shiftKey: false,
7083
+ altKey: false
7084
+ };
7085
+ };
7086
+ const requiredModifiers = getRequiredModifiers();
7087
+ const isReleasingModifier = requiredModifiers.metaKey || requiredModifiers.ctrlKey ? !event.metaKey && !event.ctrlKey : requiredModifiers.shiftKey && !event.shiftKey || requiredModifiers.altKey && !event.altKey;
7088
+ const isReleasingActivationKey = options.activationShortcut ? !options.activationShortcut(event) : options.activationKey ? options.activationKey.key ? event.key.toLowerCase() === options.activationKey.key.toLowerCase() || keyMatchesCode(options.activationKey.key, event.code) : false : isCLikeKey(event.key, event.code);
7089
+ if (isActivated()) {
7090
+ if (isReleasingModifier) {
7091
+ if (isToggleMode()) return;
7092
+ deactivateRenderer();
7093
+ } else if (!hasCustomShortcut && isReleasingActivationKey && keydownSpamTimerId !== null) {
7094
+ window.clearTimeout(keydownSpamTimerId);
7095
+ keydownSpamTimerId = null;
7096
+ }
7097
+ return;
7098
+ }
7099
+ if (isReleasingActivationKey || isReleasingModifier) {
6104
7100
  if (isToggleMode()) return;
6105
7101
  deactivateRenderer();
6106
7102
  }
@@ -6110,17 +7106,15 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6110
7106
  });
6111
7107
  window.addEventListener("mousemove", (event) => {
6112
7108
  setIsTouchMode(false);
7109
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6113
7110
  handlePointerMove(event.clientX, event.clientY);
6114
7111
  }, {
6115
7112
  signal: eventListenerSignal
6116
7113
  });
6117
7114
  window.addEventListener("mousedown", (event) => {
7115
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6118
7116
  if (isInputMode()) {
6119
- const target = event.target;
6120
- const isClickingInput = target.closest("[data-react-grab-input]");
6121
- if (!isClickingInput) {
6122
- handleInputCancel();
6123
- }
7117
+ handleInputCancel();
6124
7118
  return;
6125
7119
  }
6126
7120
  const didHandle = handlePointerDown(event.clientX, event.clientY);
@@ -6133,6 +7127,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6133
7127
  });
6134
7128
  window.addEventListener("pointerdown", (event) => {
6135
7129
  if (!isRendererActive() || isCopying() || isInputMode()) return;
7130
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6136
7131
  event.stopPropagation();
6137
7132
  }, {
6138
7133
  signal: eventListenerSignal,
@@ -6146,6 +7141,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6146
7141
  window.addEventListener("touchmove", (event) => {
6147
7142
  if (event.touches.length === 0) return;
6148
7143
  setIsTouchMode(true);
7144
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6149
7145
  handlePointerMove(event.touches[0].clientX, event.touches[0].clientY);
6150
7146
  }, {
6151
7147
  signal: eventListenerSignal,
@@ -6154,12 +7150,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6154
7150
  window.addEventListener("touchstart", (event) => {
6155
7151
  if (event.touches.length === 0) return;
6156
7152
  setIsTouchMode(true);
7153
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6157
7154
  if (isInputMode()) {
6158
- const target = event.target;
6159
- const isClickingInput = target.closest("[data-react-grab-input]");
6160
- if (!isClickingInput) {
6161
- handleInputCancel();
6162
- }
7155
+ handleInputCancel();
6163
7156
  return;
6164
7157
  }
6165
7158
  const didHandle = handlePointerDown(event.touches[0].clientX, event.touches[0].clientY);
@@ -6177,6 +7170,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6177
7170
  signal: eventListenerSignal
6178
7171
  });
6179
7172
  window.addEventListener("click", (event) => {
7173
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6180
7174
  if (isRendererActive() || isCopying() || didJustDrag()) {
6181
7175
  event.preventDefault();
6182
7176
  event.stopPropagation();
@@ -6199,6 +7193,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6199
7193
  document.addEventListener("visibilitychange", () => {
6200
7194
  if (document.hidden) {
6201
7195
  setGrabbedBoxes([]);
7196
+ if (isActivated() && !isInputMode() && activationTimestamp !== null && Date.now() - activationTimestamp > BLUR_DEACTIVATION_THRESHOLD_MS) {
7197
+ deactivateRenderer();
7198
+ }
6202
7199
  }
6203
7200
  }, {
6204
7201
  signal: eventListenerSignal
@@ -6215,6 +7212,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6215
7212
  signal: eventListenerSignal
6216
7213
  });
6217
7214
  document.addEventListener("copy", (event) => {
7215
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
7216
+ return;
7217
+ }
6218
7218
  if (isRendererActive() || isCopying()) {
6219
7219
  event.preventDefault();
6220
7220
  }
@@ -6222,18 +7222,97 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6222
7222
  signal: eventListenerSignal,
6223
7223
  capture: true
6224
7224
  });
7225
+ let selectionDebounceTimerId = null;
7226
+ document.addEventListener("selectionchange", () => {
7227
+ if (isRendererActive()) return;
7228
+ if (selectionDebounceTimerId !== null) {
7229
+ window.clearTimeout(selectionDebounceTimerId);
7230
+ }
7231
+ setHasNativeSelection(false);
7232
+ const selection = window.getSelection();
7233
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
7234
+ clearNativeSelectionState();
7235
+ return;
7236
+ }
7237
+ selectionDebounceTimerId = window.setTimeout(() => {
7238
+ selectionDebounceTimerId = null;
7239
+ const currentSelection = window.getSelection();
7240
+ if (!currentSelection || currentSelection.isCollapsed || currentSelection.rangeCount === 0) {
7241
+ return;
7242
+ }
7243
+ const range = currentSelection.getRangeAt(0);
7244
+ const rangeRect = range.getBoundingClientRect();
7245
+ if (rangeRect.width === 0 && rangeRect.height === 0) {
7246
+ return;
7247
+ }
7248
+ const isBackward = (() => {
7249
+ if (!currentSelection.anchorNode || !currentSelection.focusNode) return false;
7250
+ const position = currentSelection.anchorNode.compareDocumentPosition(currentSelection.focusNode);
7251
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return false;
7252
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return true;
7253
+ return currentSelection.anchorOffset > currentSelection.focusOffset;
7254
+ })();
7255
+ const clientRects = range.getClientRects();
7256
+ if (clientRects.length === 0) {
7257
+ return;
7258
+ }
7259
+ const cursorRect = isBackward ? clientRects[0] : clientRects[clientRects.length - 1];
7260
+ const cursorX = isBackward ? cursorRect.left : cursorRect.right;
7261
+ const cursorY = cursorRect.top + cursorRect.height / 2;
7262
+ if (isSelectionInsideEditableElement(cursorX, cursorY)) {
7263
+ clearNativeSelectionState();
7264
+ return;
7265
+ }
7266
+ setNativeSelectionCursorX(cursorX);
7267
+ setNativeSelectionCursorY(cursorY);
7268
+ const container = range.commonAncestorContainer;
7269
+ const element = container.nodeType === Node.ELEMENT_NODE ? container : container.parentElement;
7270
+ if (element && isValidGrabbableElement(element)) {
7271
+ setNativeSelectionElements([element]);
7272
+ setHasNativeSelection(true);
7273
+ } else {
7274
+ setNativeSelectionElements([]);
7275
+ }
7276
+ }, 150);
7277
+ }, {
7278
+ signal: eventListenerSignal
7279
+ });
6225
7280
  onCleanup(() => {
6226
7281
  abortController.abort();
6227
7282
  if (holdTimerId) window.clearTimeout(holdTimerId);
6228
7283
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
6229
- if (mouseSettleTimerId) window.clearTimeout(mouseSettleTimerId);
6230
7284
  stopAutoScroll();
6231
7285
  stopProgressAnimation();
6232
7286
  document.body.style.userSelect = "";
6233
- document.body.style.cursor = "";
7287
+ setCursorOverride(null);
6234
7288
  });
6235
7289
  const rendererRoot = mountRoot(styles_default);
6236
- const selectionVisible = createMemo(() => theme().selectionBox.enabled && isRendererActive() && !isDragging() && Boolean(targetElement()));
7290
+ const selectionVisible = createMemo(() => {
7291
+ if (!theme().selectionBox.enabled) return false;
7292
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7293
+ });
7294
+ const selectionTagName = createMemo(() => {
7295
+ const element = targetElement();
7296
+ if (!element) return void 0;
7297
+ return extractElementTagName(element) || void 0;
7298
+ });
7299
+ const selectionLabelVisible = createMemo(() => {
7300
+ if (!theme().elementLabel.enabled) return false;
7301
+ if (successLabels().length > 0) return false;
7302
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7303
+ });
7304
+ const computedLabelInstances = createMemo(() => {
7305
+ viewportVersion();
7306
+ return labelInstances().map((instance) => {
7307
+ if (!instance.element || !document.body.contains(instance.element)) {
7308
+ return instance;
7309
+ }
7310
+ return {
7311
+ ...instance,
7312
+ bounds: createElementBounds(instance.element)
7313
+ };
7314
+ });
7315
+ });
6237
7316
  const dragVisible = createMemo(() => theme().dragBox.enabled && isRendererActive() && isDraggingBeyondThreshold());
6238
7317
  const labelVariant = createMemo(() => isCopying() ? "processing" : "hover");
6239
7318
  const labelVisible = createMemo(() => {
@@ -6243,11 +7322,8 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6243
7322
  if (successLabels().length > 0) return false;
6244
7323
  return isRendererActive() && !isDragging() && Boolean(targetElement());
6245
7324
  });
6246
- const progressVisible = createMemo(() => isCopying() && showProgressIndicator() && hasValidMousePosition());
6247
- const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging() && !isTouchMode());
6248
- const inputVisible = createMemo(() => theme().inputOverlay.enabled && isInputMode());
7325
+ const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging() && !isTouchMode() && !isToggleFrozen());
6249
7326
  const shouldShowGrabbedBoxes = createMemo(() => theme().grabbedBoxes.enabled);
6250
- const shouldShowSuccessLabels = createMemo(() => theme().successLabels.enabled);
6251
7327
  createEffect(on(theme, (currentTheme) => {
6252
7328
  if (currentTheme.hue !== 0) {
6253
7329
  rendererRoot.style.filter = `hue-rotate(${currentTheme.hue}deg)`;
@@ -6263,72 +7339,88 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6263
7339
  get selectionBounds() {
6264
7340
  return selectionBounds();
6265
7341
  },
6266
- get dragVisible() {
6267
- return dragVisible();
7342
+ get selectionFilePath() {
7343
+ return selectionFilePath();
6268
7344
  },
6269
- get dragBounds() {
6270
- return dragBounds();
7345
+ get selectionLineNumber() {
7346
+ return selectionLineNumber();
6271
7347
  },
6272
- get grabbedBoxes() {
6273
- return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
7348
+ get selectionTagName() {
7349
+ return selectionTagName();
6274
7350
  },
6275
- get successLabels() {
6276
- return memo(() => !!shouldShowSuccessLabels())() ? successLabels() : [];
7351
+ get selectionLabelVisible() {
7352
+ return selectionLabelVisible();
6277
7353
  },
6278
- get labelVariant() {
6279
- return labelVariant();
7354
+ get selectionLabelStatus() {
7355
+ return selectionLabelStatus();
6280
7356
  },
6281
- get labelContent() {
6282
- return labelContent();
7357
+ get labelInstances() {
7358
+ return computedLabelInstances();
6283
7359
  },
6284
- get labelX() {
6285
- return labelPosition().x;
7360
+ get dragVisible() {
7361
+ return dragVisible();
6286
7362
  },
6287
- get labelY() {
6288
- return labelPosition().y;
7363
+ get dragBounds() {
7364
+ return dragBounds();
6289
7365
  },
6290
- get labelVisible() {
6291
- return labelVisible();
7366
+ get grabbedBoxes() {
7367
+ return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
6292
7368
  },
6293
7369
  labelZIndex: Z_INDEX_LABEL,
6294
- get labelShowHint() {
6295
- return mouseHasSettled();
6296
- },
6297
- get progressVisible() {
6298
- return progressVisible();
6299
- },
6300
- get progress() {
6301
- return progress();
6302
- },
6303
7370
  get mouseX() {
6304
- return progressPosition().x;
7371
+ return cursorPosition().x;
6305
7372
  },
6306
7373
  get mouseY() {
6307
- return progressPosition().y;
7374
+ return cursorPosition().y;
6308
7375
  },
6309
7376
  get crosshairVisible() {
6310
7377
  return crosshairVisible();
6311
7378
  },
6312
- get inputVisible() {
6313
- return inputVisible();
7379
+ get inputValue() {
7380
+ return inputText();
6314
7381
  },
6315
- get inputX() {
6316
- return mouseX();
7382
+ get isInputExpanded() {
7383
+ return isInputExpanded();
6317
7384
  },
6318
- get inputY() {
6319
- return mouseY();
7385
+ get hasAgent() {
7386
+ return Boolean(options.agent?.provider);
6320
7387
  },
6321
- get inputValue() {
6322
- return inputText();
7388
+ get agentSessions() {
7389
+ return agentManager.sessions();
6323
7390
  },
7391
+ onAbortSession: (sessionId) => agentManager.abortSession(sessionId),
6324
7392
  onInputChange: handleInputChange,
6325
- onInputSubmit: handleInputSubmit,
7393
+ onInputSubmit: () => void handleInputSubmit(),
6326
7394
  onInputCancel: handleInputCancel,
7395
+ onToggleExpand: handleToggleExpand,
7396
+ get nativeSelectionCursorVisible() {
7397
+ return hasNativeSelection();
7398
+ },
7399
+ get nativeSelectionCursorX() {
7400
+ return nativeSelectionCursorX();
7401
+ },
7402
+ get nativeSelectionCursorY() {
7403
+ return nativeSelectionCursorY();
7404
+ },
7405
+ get nativeSelectionTagName() {
7406
+ return nativeSelectionTagName();
7407
+ },
7408
+ get nativeSelectionComponentName() {
7409
+ return nativeSelectionComponentName();
7410
+ },
7411
+ get nativeSelectionBounds() {
7412
+ return nativeSelectionBounds();
7413
+ },
7414
+ onNativeSelectionCopy: () => void handleNativeSelectionCopy(),
7415
+ onNativeSelectionEnter: handleNativeSelectionEnter,
6327
7416
  get theme() {
6328
7417
  return theme();
6329
7418
  }
6330
7419
  }), rendererRoot);
6331
7420
  }
7421
+ if (options.agent?.provider) {
7422
+ agentManager.tryResumeSessions();
7423
+ }
6332
7424
  const copyElementAPI = async (elements) => {
6333
7425
  const elementsArray = Array.isArray(elements) ? elements : [elements];
6334
7426
  if (elementsArray.length === 0) return false;
@@ -6353,6 +7445,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6353
7445
  return {
6354
7446
  activate: () => {
6355
7447
  if (!isActivated()) {
7448
+ setIsToggleMode(true);
6356
7449
  activateRenderer();
6357
7450
  }
6358
7451
  },
@@ -6365,11 +7458,15 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6365
7458
  if (isActivated()) {
6366
7459
  deactivateRenderer();
6367
7460
  } else {
7461
+ setIsToggleMode(true);
6368
7462
  activateRenderer();
6369
7463
  }
6370
7464
  },
6371
7465
  isActive: () => isActivated(),
6372
- dispose: dispose2,
7466
+ dispose: () => {
7467
+ hasInited = false;
7468
+ dispose2();
7469
+ },
6373
7470
  copyElement: copyElementAPI,
6374
7471
  getState: getStateAPI,
6375
7472
  updateTheme: (partialTheme) => {
@@ -6444,4 +7541,4 @@ bippy/dist/source.js:
6444
7541
  *)
6445
7542
  */
6446
7543
 
6447
- export { DEFAULT_THEME, Ee, formatStack, getFileName, getHTMLPreview, getNearestComponentName, getStack, init };
7544
+ export { DEFAULT_THEME, Ee, formatElementInfo, generateSnippet, getFileName, getNearestComponentName, getStack, init };