react-grab 0.0.53 → 0.0.55

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-\\[11px\\]{font-size:11px}.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) => {
@@ -3322,7 +3373,7 @@ var cn = (...inputs) => {
3322
3373
  };
3323
3374
 
3324
3375
  // src/components/selection-box.tsx
3325
- var _tmpl$ = /* @__PURE__ */ template(`<div>`);
3376
+ var _tmpl$ = /* @__PURE__ */ template(`<div style=overflow:visible>`);
3326
3377
  var SelectionBox = (props) => {
3327
3378
  const [currentX, setCurrentX] = createSignal(props.bounds.x);
3328
3379
  const [currentY, setCurrentY] = createSignal(props.bounds.y);
@@ -3398,7 +3449,7 @@ var SelectionBox = (props) => {
3398
3449
  get children() {
3399
3450
  var _el$ = _tmpl$();
3400
3451
  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;
3452
+ 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
3453
  _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3403
3454
  _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3404
3455
  _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
@@ -3425,45 +3476,6 @@ var SelectionBox = (props) => {
3425
3476
  });
3426
3477
  };
3427
3478
 
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
3479
  // src/hooks/use-animated-lerp.ts
3468
3480
  var useAnimatedPosition = (options) => {
3469
3481
  const lerpFactor = options.lerpFactor ?? 0.3;
@@ -3510,187 +3522,8 @@ var useAnimatedPosition = (options) => {
3510
3522
  return { x: x3, y: y2 };
3511
3523
  };
3512
3524
 
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
3525
  // src/components/crosshair.tsx
3693
- var _tmpl$7 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3526
+ var _tmpl$2 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3694
3527
  var Crosshair = (props) => {
3695
3528
  let canvasRef;
3696
3529
  let context = null;
@@ -3750,7 +3583,7 @@ var Crosshair = (props) => {
3750
3583
  return props.visible !== false;
3751
3584
  },
3752
3585
  get children() {
3753
- var _el$ = _tmpl$7();
3586
+ var _el$ = _tmpl$2();
3754
3587
  var _ref$ = canvasRef;
3755
3588
  typeof _ref$ === "function" ? use(_ref$, _el$) : canvasRef = _el$;
3756
3589
  return _el$;
@@ -3758,96 +3591,697 @@ var Crosshair = (props) => {
3758
3591
  });
3759
3592
  };
3760
3593
 
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) => {
3594
+ // src/components/icon-checkmark.tsx
3595
+ 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>`);
3596
+ var IconCheckmark = (props) => {
3597
+ const size = () => props.size ?? 9;
3598
+ return (() => {
3599
+ var _el$ = _tmpl$3();
3600
+ createRenderEffect((_p$) => {
3601
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3602
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3603
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3604
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3605
+ return _p$;
3606
+ }, {
3607
+ e: void 0,
3608
+ t: void 0,
3609
+ a: void 0
3610
+ });
3611
+ return _el$;
3612
+ })();
3613
+ };
3614
+
3615
+ // src/components/icon-cursor-simple.tsx
3616
+ 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>`);
3617
+ var IconCursorSimple = (props) => {
3618
+ const size = () => props.size ?? 9;
3619
+ return (() => {
3620
+ var _el$ = _tmpl$4();
3621
+ createRenderEffect((_p$) => {
3622
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3623
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3624
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3625
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3626
+ return _p$;
3627
+ }, {
3628
+ e: void 0,
3629
+ t: void 0,
3630
+ a: void 0
3631
+ });
3632
+ return _el$;
3633
+ })();
3634
+ };
3635
+
3636
+ // src/components/icon-open.tsx
3637
+ 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">`);
3638
+ var IconOpen = (props) => {
3639
+ const size = () => props.size ?? 12;
3640
+ return (() => {
3641
+ var _el$ = _tmpl$5();
3642
+ createRenderEffect((_p$) => {
3643
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3644
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3645
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3646
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3647
+ return _p$;
3648
+ }, {
3649
+ e: void 0,
3650
+ t: void 0,
3651
+ a: void 0
3652
+ });
3653
+ return _el$;
3654
+ })();
3655
+ };
3656
+
3657
+ // src/components/icon-return-key.tsx
3658
+ 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">`);
3659
+ var IconReturnKey = (props) => {
3660
+ const size = () => props.size ?? 14;
3661
+ return (() => {
3662
+ var _el$ = _tmpl$6();
3663
+ createRenderEffect((_p$) => {
3664
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3665
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3666
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3667
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3668
+ return _p$;
3669
+ }, {
3670
+ e: void 0,
3671
+ t: void 0,
3672
+ a: void 0
3673
+ });
3674
+ return _el$;
3675
+ })();
3676
+ };
3677
+
3678
+ // src/components/icon-stop.tsx
3679
+ 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>`);
3680
+ var IconStop = (props) => {
3681
+ const size = () => props.size ?? 9;
3682
+ return (() => {
3683
+ var _el$ = _tmpl$7();
3684
+ createRenderEffect((_p$) => {
3685
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3686
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3687
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3688
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3689
+ return _p$;
3690
+ }, {
3691
+ e: void 0,
3692
+ t: void 0,
3693
+ a: void 0
3694
+ });
3695
+ return _el$;
3696
+ })();
3697
+ };
3698
+
3699
+ // src/components/selection-label.tsx
3700
+ 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>`);
3701
+ var _tmpl$22 = /* @__PURE__ */ template(`<span>`);
3702
+ var _tmpl$32 = /* @__PURE__ */ template(`<button>`);
3703
+ var _tmpl$42 = /* @__PURE__ */ template(`<div>`);
3704
+ 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]">`);
3705
+ 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">`);
3706
+ 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">`);
3707
+ var _tmpl$82 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px]">`);
3708
+ 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>`);
3709
+ var _tmpl$0 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px] react-grab-shimmer rounded-[3px]">`);
3710
+ var _tmpl$1 = /* @__PURE__ */ template(`<div class="shrink-0 flex items-center gap-1 w-full h-[14px]"><span class="text-label-muted text-[11px] leading-3.5 shrink-0 tracking-[-0.04em] font-medium w-fit h-fit">to change`);
3711
+ 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">`);
3712
+ var _tmpl$11 = /* @__PURE__ */ template(`<div class="shrink-0 flex justify-between items-start w-full min-h-[14px]"><textarea class="text-black text-[11px] 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]">`);
3713
+ 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">`);
3714
+ var ARROW_HEIGHT = 8;
3715
+ var LABEL_GAP = 4;
3716
+ var IDLE_TIMEOUT_MS = 150;
3717
+ var TagBadge = (props) => {
3718
+ const [isHovered, setIsHovered] = createSignal(false);
3719
+ const handleMouseEnter = () => {
3720
+ setIsHovered(true);
3721
+ props.onHoverChange?.(true);
3722
+ };
3723
+ const handleMouseLeave = () => {
3724
+ setIsHovered(false);
3725
+ props.onHoverChange?.(false);
3726
+ };
3727
+ return (() => {
3728
+ var _el$ = _tmpl$8(), _el$2 = _el$.firstChild;
3729
+ addEventListener(_el$, "click", props.onClick);
3730
+ _el$.addEventListener("mouseleave", handleMouseLeave);
3731
+ _el$.addEventListener("mouseenter", handleMouseEnter);
3732
+ insert(_el$2, () => props.tagName);
3733
+ insert(_el$, createComponent(Show, {
3734
+ get when() {
3735
+ return props.isClickable;
3736
+ },
3737
+ get children() {
3738
+ return createComponent(IconOpen, {
3739
+ size: 10,
3740
+ get ["class"]() {
3741
+ return cn("text-label-tag-border transition-all duration-100", isHovered() ? "opacity-100 scale-100" : "opacity-0 scale-75 -ml-[5px] w-0");
3742
+ }
3743
+ });
3744
+ }
3745
+ }), null);
3746
+ createRenderEffect((_p$) => {
3747
+ 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");
3748
+ _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3749
+ _v$2 !== _p$.t && className(_el$2, _p$.t = _v$2);
3750
+ return _p$;
3751
+ }, {
3752
+ e: void 0,
3753
+ t: void 0
3754
+ });
3755
+ return _el$;
3756
+ })();
3757
+ };
3758
+ var ActionPill = (props) => {
3759
+ 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");
3760
+ const content = [memo(() => props.icon), (() => {
3761
+ var _el$3 = _tmpl$22();
3762
+ insert(_el$3, () => props.label);
3763
+ createRenderEffect(() => className(_el$3, cn("text-black text-[12px] leading-4 font-medium tracking-[-0.04em]", props.shrink && "shrink-0 w-fit h-fit")));
3764
+ return _el$3;
3765
+ })()];
3766
+ return props.asButton ? (() => {
3767
+ var _el$4 = _tmpl$32();
3768
+ addEventListener(_el$4, "click", props.onClick);
3769
+ className(_el$4, baseClass);
3770
+ insert(_el$4, content);
3771
+ return _el$4;
3772
+ })() : (() => {
3773
+ var _el$5 = _tmpl$42();
3774
+ addEventListener(_el$5, "click", props.onClick);
3775
+ className(_el$5, baseClass);
3776
+ insert(_el$5, content);
3777
+ createRenderEffect(() => setAttribute(_el$5, "role", props.onClick ? "button" : void 0));
3778
+ return _el$5;
3779
+ })();
3780
+ };
3781
+ var SuccessPill = (props) => (() => {
3782
+ var _el$6 = _tmpl$52(), _el$7 = _el$6.firstChild;
3783
+ insert(_el$6, createComponent(IconCheckmark, {
3784
+ size: 9,
3785
+ "class": "text-label-success-text shrink-0"
3786
+ }), _el$7);
3787
+ insert(_el$7, () => props.hasAgent ? "Completed" : "Copied");
3788
+ return _el$6;
3789
+ })();
3790
+ var Arrow = (props) => (() => {
3791
+ var _el$8 = _tmpl$62();
3792
+ createRenderEffect((_$p) => style(_el$8, {
3793
+ left: `${props.leftPx}px`,
3794
+ ...props.position === "bottom" ? {
3795
+ top: "0",
3796
+ transform: "translateX(-50%) translateY(-100%)"
3797
+ } : {
3798
+ bottom: "0",
3799
+ transform: "translateX(-50%) translateY(100%)"
3800
+ },
3801
+ ...props.position === "bottom" ? {
3802
+ "border-bottom": "8px solid white"
3803
+ } : {
3804
+ "border-top": "8px solid white"
3805
+ }
3806
+ }, _$p));
3807
+ return _el$8;
3808
+ })();
3809
+ var ClickToCopyPill = (props) => createComponent(ActionPill, {
3810
+ get icon() {
3811
+ return createComponent(IconCursorSimple, {
3812
+ size: 9,
3813
+ "class": "text-black shrink-0"
3814
+ });
3815
+ },
3816
+ label: "Click to copy",
3817
+ get onClick() {
3818
+ return props.onClick;
3819
+ },
3820
+ get asButton() {
3821
+ return props.asButton;
3822
+ },
3823
+ get dimmed() {
3824
+ return props.dimmed;
3825
+ },
3826
+ get shrink() {
3827
+ return props.shrink;
3828
+ }
3829
+ });
3830
+ var BottomSection = (props) => (() => {
3831
+ var _el$9 = _tmpl$72();
3832
+ insert(_el$9, () => props.children);
3833
+ return _el$9;
3834
+ })();
3835
+ var SelectionLabel = (props) => {
3764
3836
  let containerRef;
3765
3837
  let inputRef;
3766
- const position = useAnimatedPosition({
3767
- x: () => props.x,
3768
- y: () => props.y,
3769
- lerpFactor: 0.3
3838
+ let isTagCurrentlyHovered = false;
3839
+ const [measuredWidth, setMeasuredWidth] = createSignal(0);
3840
+ const [measuredHeight, setMeasuredHeight] = createSignal(0);
3841
+ const [arrowPosition, setArrowPosition] = createSignal("bottom");
3842
+ const [viewportVersion, setViewportVersion] = createSignal(0);
3843
+ const [isIdle, setIsIdle] = createSignal(false);
3844
+ const isNotProcessing = () => props.status !== "copying" && props.status !== "copied" && props.status !== "fading";
3845
+ const measureContainer = () => {
3846
+ if (containerRef && !isTagCurrentlyHovered) {
3847
+ const rect = containerRef.getBoundingClientRect();
3848
+ setMeasuredWidth(rect.width);
3849
+ setMeasuredHeight(rect.height);
3850
+ }
3851
+ };
3852
+ const handleTagHoverChange = (hovered) => {
3853
+ isTagCurrentlyHovered = hovered;
3854
+ };
3855
+ const handleViewportChange = () => {
3856
+ setViewportVersion((version) => version + 1);
3857
+ };
3858
+ let idleTimeout;
3859
+ const resetIdleTimer = () => {
3860
+ setIsIdle(false);
3861
+ if (idleTimeout) {
3862
+ clearTimeout(idleTimeout);
3863
+ }
3864
+ idleTimeout = setTimeout(() => {
3865
+ setIsIdle(true);
3866
+ }, IDLE_TIMEOUT_MS);
3867
+ };
3868
+ const handleGlobalKeyDown = (event) => {
3869
+ if (event.code === "Enter" && isIdle() && !props.isInputExpanded && isNotProcessing()) {
3870
+ event.preventDefault();
3871
+ event.stopPropagation();
3872
+ props.onToggleExpand?.();
3873
+ }
3874
+ };
3875
+ onMount(() => {
3876
+ measureContainer();
3877
+ window.addEventListener("scroll", handleViewportChange, true);
3878
+ window.addEventListener("resize", handleViewportChange);
3879
+ window.addEventListener("mousemove", resetIdleTimer);
3880
+ window.addEventListener("keydown", handleGlobalKeyDown, {
3881
+ capture: true
3882
+ });
3883
+ resetIdleTimer();
3884
+ });
3885
+ onCleanup(() => {
3886
+ window.removeEventListener("scroll", handleViewportChange, true);
3887
+ window.removeEventListener("resize", handleViewportChange);
3888
+ window.removeEventListener("mousemove", resetIdleTimer);
3889
+ window.removeEventListener("keydown", handleGlobalKeyDown, {
3890
+ capture: true
3891
+ });
3892
+ if (idleTimeout) {
3893
+ clearTimeout(idleTimeout);
3894
+ }
3895
+ });
3896
+ createEffect(() => {
3897
+ if (props.visible) {
3898
+ requestAnimationFrame(measureContainer);
3899
+ }
3900
+ });
3901
+ createEffect(() => {
3902
+ void [props.status, props.isInputExpanded, props.inputValue, isIdle()];
3903
+ requestAnimationFrame(measureContainer);
3904
+ });
3905
+ createEffect(() => {
3906
+ if (props.isInputExpanded && inputRef) {
3907
+ setTimeout(() => {
3908
+ inputRef?.focus();
3909
+ }, 0);
3910
+ }
3770
3911
  });
3771
- const containerBoundingRect = () => containerRef?.getBoundingClientRect();
3772
3912
  const computedPosition = () => {
3773
- const boundingRect = containerBoundingRect();
3774
- if (!boundingRect) return {
3775
- left: position.x(),
3776
- top: position.y()
3777
- };
3913
+ viewportVersion();
3914
+ const bounds = props.selectionBounds;
3915
+ const labelWidth = measuredWidth();
3916
+ const labelHeight = measuredHeight();
3917
+ if (!bounds || labelWidth === 0 || labelHeight === 0) {
3918
+ return {
3919
+ left: -9999,
3920
+ top: -9999,
3921
+ arrowLeft: 0
3922
+ };
3923
+ }
3778
3924
  const viewportWidth = window.innerWidth;
3779
3925
  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
- }
3926
+ const selectionCenterX = bounds.x + bounds.width / 2;
3927
+ const selectionBottom = bounds.y + bounds.height;
3928
+ const selectionTop = bounds.y;
3929
+ let positionLeft = selectionCenterX - labelWidth / 2;
3930
+ let positionTop = selectionBottom + ARROW_HEIGHT + LABEL_GAP;
3931
+ if (positionLeft + labelWidth > viewportWidth - VIEWPORT_MARGIN_PX) {
3932
+ positionLeft = viewportWidth - labelWidth - VIEWPORT_MARGIN_PX;
3933
+ }
3934
+ if (positionLeft < VIEWPORT_MARGIN_PX) {
3935
+ positionLeft = VIEWPORT_MARGIN_PX;
3787
3936
  }
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;
3937
+ const totalHeightNeeded = labelHeight + ARROW_HEIGHT + LABEL_GAP;
3938
+ const fitsBelow = positionTop + labelHeight <= viewportHeight - VIEWPORT_MARGIN_PX;
3939
+ if (!fitsBelow) {
3940
+ positionTop = selectionTop - totalHeightNeeded;
3941
+ setArrowPosition("top");
3942
+ } else {
3943
+ setArrowPosition("bottom");
3944
+ }
3945
+ if (positionTop < VIEWPORT_MARGIN_PX) {
3946
+ positionTop = VIEWPORT_MARGIN_PX;
3947
+ }
3948
+ const arrowLeft = Math.max(12, Math.min(selectionCenterX - positionLeft, labelWidth - 12));
3949
+ return {
3950
+ left: positionLeft,
3951
+ top: positionTop,
3952
+ arrowLeft
3953
+ };
3792
3954
  };
3793
3955
  const handleKeyDown = (event) => {
3956
+ event.stopPropagation();
3794
3957
  if (event.code === "Enter" && !event.shiftKey) {
3795
3958
  event.preventDefault();
3796
- event.stopPropagation();
3797
- props.onSubmit();
3959
+ props.onSubmit?.();
3798
3960
  } else if (event.code === "Escape") {
3799
3961
  event.preventDefault();
3800
- event.stopPropagation();
3801
- props.onCancel();
3962
+ props.onCancel?.();
3802
3963
  }
3803
3964
  };
3804
3965
  const handleInput = (event) => {
3805
3966
  const target = event.target;
3806
- props.onInput(target.value);
3807
- autoResizeTextarea(target);
3808
- };
3809
- const autoResizeTextarea = (textarea) => {
3810
- textarea.style.height = "auto";
3811
- textarea.style.height = `${textarea.scrollHeight}px`;
3967
+ props.onInputChange?.(target.value);
3812
3968
  };
3813
- createEffect(() => {
3814
- if (props.visible && inputRef) {
3815
- inputRef.focus();
3816
- inputRef.style.height = "auto";
3817
- } else if (!props.visible && inputRef) {
3818
- inputRef.blur();
3969
+ const tagDisplay = () => props.tagName || "element";
3970
+ const handleTagClick = (event) => {
3971
+ event.stopPropagation();
3972
+ event.stopImmediatePropagation();
3973
+ if (props.filePath && props.onOpen) {
3974
+ props.onOpen();
3819
3975
  }
3820
- });
3821
- return (() => {
3822
- var _el$ = _tmpl$8(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
3823
- var _ref$ = containerRef;
3824
- typeof _ref$ === "function" ? use(_ref$, _el$) : containerRef = _el$;
3825
- _el$3.$$keydown = handleKeyDown;
3826
- _el$3.$$input = handleInput;
3827
- var _ref$2 = inputRef;
3828
- typeof _ref$2 === "function" ? use(_ref$2, _el$3) : inputRef = _el$3;
3829
- createRenderEffect((_p$) => {
3830
- 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";
3831
- _v$ !== _p$.e && setStyleProperty(_el$, "display", _p$.e = _v$);
3832
- _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3833
- _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
3834
- _v$4 !== _p$.o && setStyleProperty(_el$, "z-index", _p$.o = _v$4);
3835
- _v$5 !== _p$.i && setStyleProperty(_el$, "pointer-events", _p$.i = _v$5);
3836
- return _p$;
3837
- }, {
3838
- e: void 0,
3839
- t: void 0,
3840
- a: void 0,
3841
- o: void 0,
3842
- i: void 0
3843
- });
3844
- createRenderEffect(() => _el$3.value = props.value);
3845
- return _el$;
3846
- })();
3847
- };
3848
- delegateEvents(["input", "keydown"]);
3976
+ };
3977
+ const isTagClickable = () => Boolean(props.filePath && props.onOpen);
3978
+ const stopPropagation = (event) => {
3979
+ event.stopPropagation();
3980
+ event.stopImmediatePropagation();
3981
+ };
3982
+ const handleSubmit = () => props.onSubmit?.();
3983
+ return createComponent(Show, {
3984
+ get when() {
3985
+ return memo(() => props.visible !== false)() && props.selectionBounds;
3986
+ },
3987
+ get children() {
3988
+ var _el$0 = _tmpl$12(), _el$1 = _el$0.firstChild;
3989
+ _el$0.$$click = stopPropagation;
3990
+ _el$0.$$mousedown = stopPropagation;
3991
+ var _ref$ = containerRef;
3992
+ typeof _ref$ === "function" ? use(_ref$, _el$0) : containerRef = _el$0;
3993
+ insert(_el$0, createComponent(Arrow, {
3994
+ get position() {
3995
+ return arrowPosition();
3996
+ },
3997
+ get leftPx() {
3998
+ return computedPosition().arrowLeft;
3999
+ }
4000
+ }), _el$1);
4001
+ insert(_el$1, createComponent(Show, {
4002
+ get when() {
4003
+ return props.status === "copied" || props.status === "fading";
4004
+ },
4005
+ get children() {
4006
+ var _el$10 = _tmpl$82();
4007
+ insert(_el$10, createComponent(TagBadge, {
4008
+ get tagName() {
4009
+ return tagDisplay();
4010
+ },
4011
+ get isClickable() {
4012
+ return isTagClickable();
4013
+ },
4014
+ onClick: handleTagClick,
4015
+ onHoverChange: handleTagHoverChange
4016
+ }), null);
4017
+ insert(_el$10, createComponent(SuccessPill, {
4018
+ get hasAgent() {
4019
+ return props.hasAgent;
4020
+ }
4021
+ }), null);
4022
+ return _el$10;
4023
+ }
4024
+ }), null);
4025
+ insert(_el$1, createComponent(Show, {
4026
+ get when() {
4027
+ return props.status === "copying";
4028
+ },
4029
+ get children() {
4030
+ var _el$11 = _tmpl$0();
4031
+ insert(_el$11, createComponent(TagBadge, {
4032
+ get tagName() {
4033
+ return tagDisplay();
4034
+ },
4035
+ get isClickable() {
4036
+ return isTagClickable();
4037
+ },
4038
+ onClick: handleTagClick,
4039
+ onHoverChange: handleTagHoverChange,
4040
+ showMono: true
4041
+ }), null);
4042
+ insert(_el$11, createComponent(ActionPill, {
4043
+ get icon() {
4044
+ return createComponent(IconCursorSimple, {
4045
+ size: 9,
4046
+ "class": "text-black shrink-0"
4047
+ });
4048
+ },
4049
+ get label() {
4050
+ return props.statusText ?? "Grabbing\u2026";
4051
+ }
4052
+ }), null);
4053
+ insert(_el$11, createComponent(Show, {
4054
+ get when() {
4055
+ return memo(() => !!props.hasAgent)() && props.onAbort;
4056
+ },
4057
+ get children() {
4058
+ var _el$12 = _tmpl$9();
4059
+ _el$12.$$click = (event) => {
4060
+ event.preventDefault();
4061
+ event.stopPropagation();
4062
+ event.stopImmediatePropagation();
4063
+ props.onAbort?.();
4064
+ };
4065
+ _el$12.$$mousedown = (event) => {
4066
+ event.preventDefault();
4067
+ event.stopPropagation();
4068
+ event.stopImmediatePropagation();
4069
+ };
4070
+ insert(_el$12, createComponent(IconStop, {
4071
+ size: 8,
4072
+ "class": "text-white"
4073
+ }));
4074
+ return _el$12;
4075
+ }
4076
+ }), null);
4077
+ return _el$11;
4078
+ }
4079
+ }), null);
4080
+ insert(_el$1, createComponent(Show, {
4081
+ get when() {
4082
+ return memo(() => !!(isNotProcessing() && !isIdle()))() && !props.isInputExpanded;
4083
+ },
4084
+ get children() {
4085
+ var _el$13 = _tmpl$82();
4086
+ insert(_el$13, createComponent(TagBadge, {
4087
+ get tagName() {
4088
+ return tagDisplay();
4089
+ },
4090
+ get isClickable() {
4091
+ return isTagClickable();
4092
+ },
4093
+ onClick: handleTagClick,
4094
+ onHoverChange: handleTagHoverChange,
4095
+ showMono: true
4096
+ }), null);
4097
+ insert(_el$13, createComponent(ClickToCopyPill, {
4098
+ onClick: handleSubmit,
4099
+ asButton: true
4100
+ }), null);
4101
+ return _el$13;
4102
+ }
4103
+ }), null);
4104
+ insert(_el$1, createComponent(Show, {
4105
+ get when() {
4106
+ return memo(() => !!(isNotProcessing() && isIdle()))() && !props.isInputExpanded;
4107
+ },
4108
+ get children() {
4109
+ var _el$14 = _tmpl$10(), _el$15 = _el$14.firstChild;
4110
+ insert(_el$15, createComponent(TagBadge, {
4111
+ get tagName() {
4112
+ return tagDisplay();
4113
+ },
4114
+ get isClickable() {
4115
+ return isTagClickable();
4116
+ },
4117
+ onClick: handleTagClick,
4118
+ onHoverChange: handleTagHoverChange,
4119
+ showMono: true,
4120
+ shrink: true
4121
+ }), null);
4122
+ insert(_el$15, createComponent(ClickToCopyPill, {
4123
+ onClick: handleSubmit,
4124
+ shrink: true
4125
+ }), null);
4126
+ insert(_el$14, createComponent(BottomSection, {
4127
+ get children() {
4128
+ var _el$16 = _tmpl$1(), _el$17 = _el$16.firstChild;
4129
+ insert(_el$16, createComponent(IconReturnKey, {
4130
+ size: 10,
4131
+ "class": "shrink-0 text-black opacity-[0.65]"
4132
+ }), _el$17);
4133
+ return _el$16;
4134
+ }
4135
+ }), null);
4136
+ return _el$14;
4137
+ }
4138
+ }), null);
4139
+ insert(_el$1, createComponent(Show, {
4140
+ get when() {
4141
+ return memo(() => !!isNotProcessing())() && props.isInputExpanded;
4142
+ },
4143
+ get children() {
4144
+ var _el$18 = _tmpl$10(), _el$19 = _el$18.firstChild;
4145
+ insert(_el$19, createComponent(TagBadge, {
4146
+ get tagName() {
4147
+ return tagDisplay();
4148
+ },
4149
+ get isClickable() {
4150
+ return isTagClickable();
4151
+ },
4152
+ onClick: handleTagClick,
4153
+ onHoverChange: handleTagHoverChange,
4154
+ showMono: true,
4155
+ shrink: true
4156
+ }), null);
4157
+ insert(_el$19, createComponent(ClickToCopyPill, {
4158
+ onClick: handleSubmit,
4159
+ dimmed: true,
4160
+ shrink: true
4161
+ }), null);
4162
+ insert(_el$18, createComponent(BottomSection, {
4163
+ get children() {
4164
+ var _el$20 = _tmpl$11(), _el$21 = _el$20.firstChild, _el$22 = _el$21.nextSibling;
4165
+ _el$21.$$keydown = handleKeyDown;
4166
+ _el$21.$$input = handleInput;
4167
+ var _ref$2 = inputRef;
4168
+ typeof _ref$2 === "function" ? use(_ref$2, _el$21) : inputRef = _el$21;
4169
+ _el$22.$$click = handleSubmit;
4170
+ insert(_el$22, createComponent(IconReturnKey, {
4171
+ size: 10,
4172
+ "class": "shrink-0 text-black"
4173
+ }));
4174
+ createRenderEffect(() => _el$21.value = props.inputValue ?? "");
4175
+ return _el$20;
4176
+ }
4177
+ }), null);
4178
+ return _el$18;
4179
+ }
4180
+ }), null);
4181
+ createRenderEffect((_p$) => {
4182
+ 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" : isIdle() || props.isInputExpanded ? "0" : "4px";
4183
+ _v$3 !== _p$.e && setStyleProperty(_el$0, "top", _p$.e = _v$3);
4184
+ _v$4 !== _p$.t && setStyleProperty(_el$0, "left", _p$.t = _v$4);
4185
+ _v$5 !== _p$.a && setStyleProperty(_el$0, "pointer-events", _p$.a = _v$5);
4186
+ _v$6 !== _p$.o && setStyleProperty(_el$0, "opacity", _p$.o = _v$6);
4187
+ _v$7 !== _p$.i && setStyleProperty(_el$1, "padding", _p$.i = _v$7);
4188
+ return _p$;
4189
+ }, {
4190
+ e: void 0,
4191
+ t: void 0,
4192
+ a: void 0,
4193
+ o: void 0,
4194
+ i: void 0
4195
+ });
4196
+ return _el$0;
4197
+ }
4198
+ });
4199
+ };
4200
+ delegateEvents(["click", "mousedown", "input", "keydown"]);
4201
+
4202
+ // src/components/selection-cursor.tsx
4203
+ var _tmpl$13 = /* @__PURE__ */ template(`<div class="fixed z-2147483647"><button data-react-grab-selection-cursor>`);
4204
+ var SelectionCursor = (props) => {
4205
+ const [isHovered, setIsHovered] = createSignal(false);
4206
+ const [debouncedVisible, setDebouncedVisible] = createSignal(false);
4207
+ createEffect(() => {
4208
+ const isVisible = props.visible !== false;
4209
+ void [props.x, props.y];
4210
+ setDebouncedVisible(false);
4211
+ if (isVisible) {
4212
+ const timeout = setTimeout(() => setDebouncedVisible(true), SELECTION_CURSOR_SETTLE_DELAY_MS);
4213
+ onCleanup(() => clearTimeout(timeout));
4214
+ }
4215
+ });
4216
+ const handleClick = (event) => {
4217
+ event.preventDefault();
4218
+ event.stopPropagation();
4219
+ props.onClick?.();
4220
+ };
4221
+ return createComponent(Show, {
4222
+ get when() {
4223
+ return debouncedVisible();
4224
+ },
4225
+ get children() {
4226
+ return [createComponent(Show, {
4227
+ get when() {
4228
+ return memo(() => !!isHovered())() && props.elementBounds;
4229
+ },
4230
+ get children() {
4231
+ return createComponent(SelectionBox, {
4232
+ variant: "selection",
4233
+ get bounds() {
4234
+ return props.elementBounds;
4235
+ },
4236
+ visible: true
4237
+ });
4238
+ }
4239
+ }), (() => {
4240
+ var _el$ = _tmpl$13(), _el$2 = _el$.firstChild;
4241
+ _el$.addEventListener("mouseleave", () => setIsHovered(false));
4242
+ _el$.addEventListener("mouseenter", () => setIsHovered(true));
4243
+ _el$2.$$click = handleClick;
4244
+ createRenderEffect((_p$) => {
4245
+ 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");
4246
+ _v$ !== _p$.e && setStyleProperty(_el$, "left", _p$.e = _v$);
4247
+ _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
4248
+ _v$3 !== _p$.a && className(_el$2, _p$.a = _v$3);
4249
+ return _p$;
4250
+ }, {
4251
+ e: void 0,
4252
+ t: void 0,
4253
+ a: void 0
4254
+ });
4255
+ return _el$;
4256
+ })(), createComponent(Show, {
4257
+ get when() {
4258
+ return memo(() => !!isHovered())() && props.elementBounds;
4259
+ },
4260
+ get children() {
4261
+ return createComponent(SelectionLabel, {
4262
+ get tagName() {
4263
+ return props.tagName;
4264
+ },
4265
+ get selectionBounds() {
4266
+ return props.elementBounds;
4267
+ },
4268
+ visible: true,
4269
+ get onSubmit() {
4270
+ return props.onClick;
4271
+ }
4272
+ });
4273
+ }
4274
+ })];
4275
+ }
4276
+ });
4277
+ };
4278
+ delegateEvents(["click"]);
3849
4279
 
3850
4280
  // src/components/renderer.tsx
4281
+ var truncateStatus = (status, maxLength = 30) => {
4282
+ if (status.length <= maxLength) return status;
4283
+ return `${status.slice(0, maxLength)}\u2026`;
4284
+ };
3851
4285
  var ReactGrabRenderer = (props) => {
3852
4286
  return [createComponent(Show, {
3853
4287
  get when() {
@@ -3861,6 +4295,9 @@ var ReactGrabRenderer = (props) => {
3861
4295
  },
3862
4296
  get visible() {
3863
4297
  return props.selectionVisible;
4298
+ },
4299
+ get isFading() {
4300
+ return props.selectionLabelStatus === "fading";
3864
4301
  }
3865
4302
  });
3866
4303
  }
@@ -3907,86 +4344,141 @@ var ReactGrabRenderer = (props) => {
3907
4344
  return box.createdAt;
3908
4345
  }
3909
4346
  })
4347
+ }), createComponent(For, {
4348
+ get each() {
4349
+ return memo(() => !!props.agentSessions)() ? Array.from(props.agentSessions.values()) : [];
4350
+ },
4351
+ children: (session) => [createComponent(Show, {
4352
+ get when() {
4353
+ return session.selectionBounds;
4354
+ },
4355
+ get children() {
4356
+ return createComponent(SelectionBox, {
4357
+ variant: "processing",
4358
+ get bounds() {
4359
+ return session.selectionBounds;
4360
+ },
4361
+ visible: true
4362
+ });
4363
+ }
4364
+ }), createComponent(SelectionLabel, {
4365
+ get tagName() {
4366
+ return session.tagName;
4367
+ },
4368
+ get selectionBounds() {
4369
+ return session.selectionBounds;
4370
+ },
4371
+ visible: true,
4372
+ hasAgent: true,
4373
+ get status() {
4374
+ return session.isStreaming ? "copying" : "copied";
4375
+ },
4376
+ get statusText() {
4377
+ return truncateStatus(session.lastStatus || "Please wait\u2026");
4378
+ },
4379
+ onAbort: () => props.onAbortSession?.(session.id)
4380
+ })]
3910
4381
  }), createComponent(Show, {
3911
4382
  get when() {
3912
- return props.labelVariant !== "processing";
4383
+ return memo(() => !!props.selectionLabelVisible)() && props.selectionBounds;
3913
4384
  },
3914
4385
  get children() {
3915
- return createComponent(For, {
3916
- get each() {
3917
- return props.successLabels ?? [];
4386
+ return createComponent(SelectionLabel, {
4387
+ get tagName() {
4388
+ return props.selectionTagName;
3918
4389
  },
3919
- children: (label) => createComponent(Label, {
3920
- variant: "success",
3921
- get content() {
3922
- return memo(() => label.text);
3923
- },
3924
- get x() {
3925
- return props.mouseX ?? 0;
3926
- },
3927
- get y() {
3928
- return props.mouseY ?? 0;
4390
+ get selectionBounds() {
4391
+ return props.selectionBounds;
4392
+ },
4393
+ get visible() {
4394
+ return props.selectionLabelVisible;
4395
+ },
4396
+ get isInputExpanded() {
4397
+ return props.isInputExpanded;
4398
+ },
4399
+ get inputValue() {
4400
+ return props.inputValue;
4401
+ },
4402
+ get hasAgent() {
4403
+ return props.hasAgent;
4404
+ },
4405
+ get status() {
4406
+ return props.selectionLabelStatus;
4407
+ },
4408
+ get filePath() {
4409
+ return props.selectionFilePath;
4410
+ },
4411
+ get lineNumber() {
4412
+ return props.selectionLineNumber;
4413
+ },
4414
+ get onInputChange() {
4415
+ return props.onInputChange;
4416
+ },
4417
+ get onSubmit() {
4418
+ return props.onInputSubmit;
4419
+ },
4420
+ get onCancel() {
4421
+ return props.onInputCancel;
4422
+ },
4423
+ get onToggleExpand() {
4424
+ return props.onToggleExpand;
4425
+ },
4426
+ onOpen: () => {
4427
+ if (props.selectionFilePath) {
4428
+ const openFileUrl = buildOpenFileUrl(props.selectionFilePath, props.selectionLineNumber);
4429
+ window.open(openFileUrl, "_blank");
3929
4430
  }
3930
- })
4431
+ }
3931
4432
  });
3932
4433
  }
4434
+ }), createComponent(For, {
4435
+ get each() {
4436
+ return props.labelInstances ?? [];
4437
+ },
4438
+ children: (instance) => createComponent(SelectionLabel, {
4439
+ get tagName() {
4440
+ return instance.tagName;
4441
+ },
4442
+ get selectionBounds() {
4443
+ return instance.bounds;
4444
+ },
4445
+ visible: true,
4446
+ get status() {
4447
+ return instance.status;
4448
+ }
4449
+ })
3933
4450
  }), createComponent(Show, {
3934
4451
  get when() {
3935
- return memo(() => !!(props.labelVisible && props.labelVariant && props.labelContent !== void 0 && props.labelX !== void 0))() && props.labelY !== void 0;
4452
+ return memo(() => !!(props.nativeSelectionCursorVisible && props.nativeSelectionCursorX !== void 0))() && props.nativeSelectionCursorY !== void 0;
3936
4453
  },
3937
4454
  get children() {
3938
- return createComponent(Label, {
3939
- get variant() {
3940
- return props.labelVariant;
3941
- },
3942
- get content() {
3943
- return props.labelContent;
3944
- },
4455
+ return createComponent(SelectionCursor, {
3945
4456
  get x() {
3946
- return props.labelX;
4457
+ return props.nativeSelectionCursorX;
3947
4458
  },
3948
4459
  get y() {
3949
- return props.labelY;
4460
+ return props.nativeSelectionCursorY;
3950
4461
  },
3951
- get visible() {
3952
- return props.labelVisible;
4462
+ get tagName() {
4463
+ return props.nativeSelectionTagName;
4464
+ },
4465
+ get componentName() {
4466
+ return props.nativeSelectionComponentName;
3953
4467
  },
3954
- get zIndex() {
3955
- return props.labelZIndex;
4468
+ get elementBounds() {
4469
+ return props.nativeSelectionBounds;
3956
4470
  },
3957
- get progress() {
3958
- return props.progress;
4471
+ get visible() {
4472
+ return props.nativeSelectionCursorVisible;
4473
+ },
4474
+ get onClick() {
4475
+ return props.onNativeSelectionCopy;
3959
4476
  },
3960
- get showHint() {
3961
- return props.labelShowHint;
4477
+ get onEnter() {
4478
+ return props.onNativeSelectionEnter;
3962
4479
  }
3963
4480
  });
3964
4481
  }
3965
- }), createComponent(InputOverlay, {
3966
- get x() {
3967
- return props.inputX ?? 0;
3968
- },
3969
- get y() {
3970
- return props.inputY ?? 0;
3971
- },
3972
- get zIndex() {
3973
- return props.labelZIndex;
3974
- },
3975
- get value() {
3976
- return props.inputValue ?? "";
3977
- },
3978
- get visible() {
3979
- return props.inputVisible ?? false;
3980
- },
3981
- get onInput() {
3982
- return props.onInputChange;
3983
- },
3984
- get onSubmit() {
3985
- return props.onInputSubmit;
3986
- },
3987
- get onCancel() {
3988
- return props.onInputCancel;
3989
- }
3990
4482
  })];
3991
4483
  };
3992
4484
 
@@ -4931,20 +5423,55 @@ var getStack = async (element) => {
4931
5423
  return [];
4932
5424
  }
4933
5425
  };
4934
- var formatStack = (stack) => {
5426
+ var formatElementInfo = async (element) => {
5427
+ const html = getHTMLPreview(element);
5428
+ const stack = await getStack(element);
4935
5429
  const isNextProject = checkIsNextProject();
4936
- return stack.map(({ name, source }) => {
4937
- if (!source) return ` at ${name}`;
4938
- if (source.fileName.startsWith("about://React/Server")) {
4939
- return ` at ${name} (Server)`;
4940
- }
4941
- if (!je2(source.fileName)) return ` at ${name}`;
4942
- const framePart = ` at ${name} in ${Q(source.fileName)}`;
4943
- if (isNextProject) {
4944
- return `${framePart}:${source.lineNumber}:${source.columnNumber}`;
4945
- }
4946
- return framePart;
4947
- }).join("\n");
5430
+ let serverBoundary = null;
5431
+ let componentName = null;
5432
+ let fileName = null;
5433
+ let lineNumber = null;
5434
+ let columnNumber = null;
5435
+ for (const frame of stack) {
5436
+ if (!frame.source) continue;
5437
+ if (frame.source.fileName.startsWith("about://React/Server")) {
5438
+ if (!serverBoundary) serverBoundary = frame.name;
5439
+ continue;
5440
+ }
5441
+ if (je2(frame.source.fileName)) {
5442
+ if (!fileName) {
5443
+ fileName = Q(frame.source.fileName);
5444
+ lineNumber = frame.source.lineNumber ?? null;
5445
+ columnNumber = frame.source.columnNumber ?? null;
5446
+ }
5447
+ if (!componentName && checkIsSourceComponentName(frame.name)) {
5448
+ componentName = frame.name;
5449
+ }
5450
+ if (fileName && componentName) {
5451
+ break;
5452
+ }
5453
+ }
5454
+ }
5455
+ if (!componentName || !fileName) {
5456
+ return html;
5457
+ }
5458
+ let result = `${html}
5459
+ in ${componentName} at ${fileName}`;
5460
+ if (isNextProject && lineNumber && columnNumber) {
5461
+ result += `:${lineNumber}:${columnNumber}`;
5462
+ }
5463
+ if (serverBoundary) {
5464
+ result += ` (via Server: ${serverBoundary})`;
5465
+ }
5466
+ return result;
5467
+ };
5468
+ var getFileName = (stack) => {
5469
+ for (const frame of stack) {
5470
+ if (frame.source && je2(frame.source.fileName)) {
5471
+ return Q(frame.source.fileName);
5472
+ }
5473
+ }
5474
+ return null;
4948
5475
  };
4949
5476
  var getHTMLPreview = (element) => {
4950
5477
  const tagName = element.tagName.toLowerCase();
@@ -5238,6 +5765,106 @@ var createElementBounds = (element) => {
5238
5765
  };
5239
5766
  };
5240
5767
 
5768
+ // src/utils/is-c-like-key.ts
5769
+ var C_LIKE_CHARACTERS = /* @__PURE__ */ new Set([
5770
+ "c",
5771
+ "C",
5772
+ "\u0441",
5773
+ // Cyrillic small es
5774
+ "\u0421",
5775
+ // Cyrillic capital es
5776
+ "\u023C",
5777
+ // c with stroke
5778
+ "\u023B",
5779
+ // C with stroke
5780
+ "\u2184",
5781
+ // reversed c
5782
+ "\u2183",
5783
+ // reversed C
5784
+ "\u1D04",
5785
+ // modifier small c
5786
+ "\u1D9C",
5787
+ // modifier small c turned
5788
+ "\u2C7C",
5789
+ // latin small c with palatal hook
5790
+ "\u217D",
5791
+ // small roman numeral 100
5792
+ "\u216D",
5793
+ // capital roman numeral 100
5794
+ "\xE7",
5795
+ // c with cedilla
5796
+ "\xC7",
5797
+ // C with cedilla
5798
+ "\u0107",
5799
+ // c with acute
5800
+ "\u0106",
5801
+ // C with acute
5802
+ "\u010D",
5803
+ // c with caron
5804
+ "\u010C",
5805
+ // C with caron
5806
+ "\u0109",
5807
+ // c with circumflex
5808
+ "\u0108",
5809
+ // C with circumflex
5810
+ "\u010B",
5811
+ // c with dot above
5812
+ "\u010A"
5813
+ // C with dot above
5814
+ ]);
5815
+ var isCLikeKey = (key, code) => {
5816
+ if (code === "KeyC") return true;
5817
+ if (!key || key.length !== 1) return false;
5818
+ return C_LIKE_CHARACTERS.has(key);
5819
+ };
5820
+
5821
+ // src/utils/hotkey.ts
5822
+ var keyMatchesCode = (targetKey, code) => {
5823
+ const normalizedTarget = targetKey.toLowerCase();
5824
+ if (code.startsWith("Key")) {
5825
+ return code.slice(3).toLowerCase() === normalizedTarget;
5826
+ }
5827
+ if (code.startsWith("Digit")) {
5828
+ return code.slice(5) === normalizedTarget;
5829
+ }
5830
+ return false;
5831
+ };
5832
+ var isTargetKeyCombination = (event, options) => {
5833
+ if (options.activationShortcut) {
5834
+ return options.activationShortcut(event);
5835
+ }
5836
+ if (options.activationKey) {
5837
+ const { key, metaKey, ctrlKey, shiftKey, altKey } = options.activationKey;
5838
+ const isModifierOnly = !key;
5839
+ if (isModifierOnly) {
5840
+ if (!MODIFIER_KEYS.includes(event.key)) return false;
5841
+ const metaMatches = metaKey ? event.metaKey || event.key === "Meta" : true;
5842
+ const ctrlMatches = ctrlKey ? event.ctrlKey || event.key === "Control" : true;
5843
+ const shiftMatches = shiftKey ? event.shiftKey || event.key === "Shift" : true;
5844
+ const altMatches = altKey ? event.altKey || event.key === "Alt" : true;
5845
+ const allRequiredModifiersPressed = metaMatches && ctrlMatches && shiftMatches && altMatches;
5846
+ const requiredModifierCount = [metaKey, ctrlKey, shiftKey, altKey].filter(Boolean).length;
5847
+ const pressedModifierCount = [
5848
+ event.metaKey || event.key === "Meta",
5849
+ event.ctrlKey || event.key === "Control",
5850
+ event.shiftKey || event.key === "Shift",
5851
+ event.altKey || event.key === "Alt"
5852
+ ].filter(Boolean).length;
5853
+ return allRequiredModifiersPressed && pressedModifierCount >= requiredModifierCount;
5854
+ }
5855
+ const keyMatches = event.key.toLowerCase() === key.toLowerCase() || keyMatchesCode(key, event.code);
5856
+ const hasModifier = metaKey || ctrlKey || shiftKey || altKey;
5857
+ const modifiersMatch = hasModifier ? (metaKey ? event.metaKey : true) && (ctrlKey ? event.ctrlKey : true) && (shiftKey ? event.shiftKey : true) && (altKey ? event.altKey : true) : event.metaKey || event.ctrlKey;
5858
+ return keyMatches && modifiersMatch;
5859
+ }
5860
+ return (event.metaKey || event.ctrlKey) && isCLikeKey(event.key, event.code);
5861
+ };
5862
+
5863
+ // src/utils/is-event-from-overlay.ts
5864
+ var isEventFromOverlay = (event, attribute) => event.composedPath().some(
5865
+ (target) => target instanceof HTMLElement && target.hasAttribute(attribute)
5866
+ );
5867
+
5241
5868
  // src/theme.ts
5242
5869
  var DEFAULT_THEME = {
5243
5870
  enabled: true,
@@ -5350,16 +5977,307 @@ var deepMergeTheme = (baseTheme, partialTheme) => {
5350
5977
  };
5351
5978
  };
5352
5979
 
5980
+ // src/utils/agent-session.ts
5981
+ var STORAGE_KEY = "react-grab:agent-sessions";
5982
+ var generateSessionId = () => `session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
5983
+ var createSession = (context, position, selectionBounds, tagName) => ({
5984
+ id: generateSessionId(),
5985
+ context,
5986
+ lastStatus: "",
5987
+ isStreaming: true,
5988
+ createdAt: Date.now(),
5989
+ position,
5990
+ selectionBounds,
5991
+ tagName
5992
+ });
5993
+ var getStorage = (storage) => {
5994
+ if (!storage) return null;
5995
+ return storage;
5996
+ };
5997
+ var memorySessions = /* @__PURE__ */ new Map();
5998
+ var saveSessions = (sessions, storage) => {
5999
+ const resolvedStorage = getStorage(storage);
6000
+ if (!resolvedStorage) {
6001
+ memorySessions.clear();
6002
+ sessions.forEach((session, id) => memorySessions.set(id, session));
6003
+ return;
6004
+ }
6005
+ try {
6006
+ const sessionsObject = Object.fromEntries(sessions);
6007
+ resolvedStorage.setItem(STORAGE_KEY, JSON.stringify(sessionsObject));
6008
+ } catch {
6009
+ memorySessions.clear();
6010
+ sessions.forEach((session, id) => memorySessions.set(id, session));
6011
+ }
6012
+ };
6013
+ var saveSessionById = (session, storage) => {
6014
+ const sessions = loadSessions(storage);
6015
+ sessions.set(session.id, session);
6016
+ saveSessions(sessions, storage);
6017
+ };
6018
+ var loadSessions = (storage) => {
6019
+ const resolvedStorage = getStorage(storage);
6020
+ if (!resolvedStorage) {
6021
+ return new Map(memorySessions);
6022
+ }
6023
+ try {
6024
+ const data = resolvedStorage.getItem(STORAGE_KEY);
6025
+ if (!data) return /* @__PURE__ */ new Map();
6026
+ const sessionsObject = JSON.parse(data);
6027
+ return new Map(Object.entries(sessionsObject));
6028
+ } catch {
6029
+ return /* @__PURE__ */ new Map();
6030
+ }
6031
+ };
6032
+ var clearSessions = (storage) => {
6033
+ const resolvedStorage = getStorage(storage);
6034
+ if (!resolvedStorage) {
6035
+ memorySessions.clear();
6036
+ return;
6037
+ }
6038
+ try {
6039
+ resolvedStorage.removeItem(STORAGE_KEY);
6040
+ } catch {
6041
+ memorySessions.clear();
6042
+ }
6043
+ };
6044
+ var clearSessionById = (sessionId, storage) => {
6045
+ const sessions = loadSessions(storage);
6046
+ sessions.delete(sessionId);
6047
+ saveSessions(sessions, storage);
6048
+ };
6049
+ var updateSession = (session, updates, storage) => {
6050
+ const updatedSession = { ...session, ...updates };
6051
+ saveSessionById(updatedSession, storage);
6052
+ return updatedSession;
6053
+ };
6054
+
6055
+ // src/utils/generate-snippet.ts
6056
+ var generateSnippet = async (elements) => {
6057
+ const elementSnippetResults = await Promise.allSettled(
6058
+ elements.map((element) => formatElementInfo(element))
6059
+ );
6060
+ const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
6061
+ if (elementSnippets.length === 0) {
6062
+ return "";
6063
+ }
6064
+ return elementSnippets.join("\n\n");
6065
+ };
6066
+
6067
+ // src/agent.ts
6068
+ var createAgentManager = (agentOptions) => {
6069
+ const [sessions, setSessions] = createSignal(/* @__PURE__ */ new Map());
6070
+ const abortControllers = /* @__PURE__ */ new Map();
6071
+ const sessionElements = /* @__PURE__ */ new Map();
6072
+ const isProcessing = () => sessions().size > 0;
6073
+ const executeSessionStream = async (session, streamIterator) => {
6074
+ const storage = agentOptions?.storage;
6075
+ let didComplete = false;
6076
+ let wasAborted = false;
6077
+ let hadError = false;
6078
+ try {
6079
+ for await (const status of streamIterator) {
6080
+ const currentSessions = sessions();
6081
+ const currentSession = currentSessions.get(session.id);
6082
+ if (!currentSession) break;
6083
+ const updatedSession = updateSession(currentSession, { lastStatus: status }, storage);
6084
+ setSessions((prev) => new Map(prev).set(session.id, updatedSession));
6085
+ agentOptions?.onStatus?.(status, updatedSession);
6086
+ }
6087
+ didComplete = true;
6088
+ const finalSessions = sessions();
6089
+ const finalSession = finalSessions.get(session.id);
6090
+ if (finalSession) {
6091
+ const completedSession = updateSession(finalSession, { isStreaming: false }, storage);
6092
+ setSessions((prev) => new Map(prev).set(session.id, completedSession));
6093
+ agentOptions?.onComplete?.(completedSession);
6094
+ }
6095
+ } catch (error) {
6096
+ const currentSessions = sessions();
6097
+ const currentSession = currentSessions.get(session.id);
6098
+ if (error instanceof Error && error.name === "AbortError") {
6099
+ wasAborted = true;
6100
+ if (currentSession) {
6101
+ const element = sessionElements.get(session.id);
6102
+ agentOptions?.onAbort?.(currentSession, element);
6103
+ }
6104
+ } else {
6105
+ hadError = true;
6106
+ if (currentSession) {
6107
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
6108
+ const errorSession = updateSession(currentSession, {
6109
+ lastStatus: `Error: ${errorMessage}`,
6110
+ isStreaming: false
6111
+ }, storage);
6112
+ setSessions((prev) => new Map(prev).set(session.id, errorSession));
6113
+ if (error instanceof Error) {
6114
+ agentOptions?.onError?.(error, errorSession);
6115
+ }
6116
+ }
6117
+ }
6118
+ } finally {
6119
+ abortControllers.delete(session.id);
6120
+ const removeSession = () => {
6121
+ sessionElements.delete(session.id);
6122
+ clearSessionById(session.id, storage);
6123
+ setSessions((prev) => {
6124
+ const next = new Map(prev);
6125
+ next.delete(session.id);
6126
+ return next;
6127
+ });
6128
+ };
6129
+ if (wasAborted) {
6130
+ removeSession();
6131
+ } else if (didComplete || hadError) {
6132
+ setTimeout(removeSession, 1500);
6133
+ }
6134
+ }
6135
+ };
6136
+ const tryReacquireElement = (session) => {
6137
+ const { selectionBounds, tagName } = session;
6138
+ if (!selectionBounds) return void 0;
6139
+ const centerX = selectionBounds.x + selectionBounds.width / 2;
6140
+ const centerY = selectionBounds.y + selectionBounds.height / 2;
6141
+ const element = document.elementFromPoint(centerX, centerY);
6142
+ if (!element) return void 0;
6143
+ if (tagName && element.tagName.toLowerCase() !== tagName) {
6144
+ return void 0;
6145
+ }
6146
+ return element;
6147
+ };
6148
+ const tryResumeSessions = () => {
6149
+ const storage = agentOptions?.storage;
6150
+ const existingSessions = loadSessions(storage);
6151
+ const streamingSessions = Array.from(existingSessions.values()).filter(
6152
+ (session) => session.isStreaming
6153
+ );
6154
+ if (streamingSessions.length === 0) {
6155
+ clearSessions(storage);
6156
+ return;
6157
+ }
6158
+ if (!agentOptions?.provider?.supportsResume || !agentOptions.provider.resume) {
6159
+ clearSessions(storage);
6160
+ return;
6161
+ }
6162
+ const streamingSessionsMap = new Map(
6163
+ streamingSessions.map((session) => [session.id, session])
6164
+ );
6165
+ setSessions(streamingSessionsMap);
6166
+ saveSessions(streamingSessionsMap, storage);
6167
+ for (const existingSession of streamingSessions) {
6168
+ const reacquiredElement = tryReacquireElement(existingSession);
6169
+ if (reacquiredElement) {
6170
+ sessionElements.set(existingSession.id, reacquiredElement);
6171
+ }
6172
+ const sessionWithResumeStatus = {
6173
+ ...existingSession,
6174
+ lastStatus: existingSession.lastStatus || "Resuming...",
6175
+ position: existingSession.position ?? { x: window.innerWidth / 2, y: window.innerHeight / 2 }
6176
+ };
6177
+ setSessions((prev) => new Map(prev).set(existingSession.id, sessionWithResumeStatus));
6178
+ agentOptions?.onResume?.(sessionWithResumeStatus);
6179
+ const abortController = new AbortController();
6180
+ abortControllers.set(existingSession.id, abortController);
6181
+ const streamIterator = agentOptions.provider.resume(existingSession.id, abortController.signal);
6182
+ void executeSessionStream(existingSession, streamIterator);
6183
+ }
6184
+ };
6185
+ const startSession = async (params) => {
6186
+ const { element, prompt, position, selectionBounds } = params;
6187
+ const storage = agentOptions?.storage;
6188
+ if (!agentOptions?.provider) {
6189
+ return;
6190
+ }
6191
+ const elements = [element];
6192
+ const content = await generateSnippet(elements);
6193
+ const context = { content, prompt, options: agentOptions?.getOptions?.() };
6194
+ const tagName = (element.tagName || "").toLowerCase() || void 0;
6195
+ const session = createSession(context, position, selectionBounds, tagName);
6196
+ session.lastStatus = "Please wait\u2026";
6197
+ sessionElements.set(session.id, element);
6198
+ setSessions((prev) => new Map(prev).set(session.id, session));
6199
+ saveSessionById(session, storage);
6200
+ agentOptions.onStart?.(session);
6201
+ const abortController = new AbortController();
6202
+ abortControllers.set(session.id, abortController);
6203
+ const streamIterator = agentOptions.provider.send(context, abortController.signal);
6204
+ void executeSessionStream(session, streamIterator);
6205
+ };
6206
+ const abortSession = (sessionId) => {
6207
+ const controller = abortControllers.get(sessionId);
6208
+ if (controller) {
6209
+ controller.abort();
6210
+ }
6211
+ };
6212
+ const abortAllSessions = () => {
6213
+ abortControllers.forEach((controller) => controller.abort());
6214
+ abortControllers.clear();
6215
+ setSessions(/* @__PURE__ */ new Map());
6216
+ clearSessions(agentOptions?.storage);
6217
+ };
6218
+ const updateSessionBoundsOnViewportChange = () => {
6219
+ const currentSessions = sessions();
6220
+ if (currentSessions.size === 0) return;
6221
+ const updatedSessions = new Map(currentSessions);
6222
+ let didUpdate = false;
6223
+ for (const [sessionId, session] of currentSessions) {
6224
+ let element = sessionElements.get(sessionId);
6225
+ if (!element || !document.contains(element)) {
6226
+ const reacquiredElement = tryReacquireElement(session);
6227
+ if (reacquiredElement) {
6228
+ sessionElements.set(sessionId, reacquiredElement);
6229
+ element = reacquiredElement;
6230
+ }
6231
+ }
6232
+ if (element && document.contains(element)) {
6233
+ const newBounds = createElementBounds(element);
6234
+ if (newBounds) {
6235
+ updatedSessions.set(sessionId, { ...session, selectionBounds: newBounds });
6236
+ didUpdate = true;
6237
+ }
6238
+ }
6239
+ }
6240
+ if (didUpdate) {
6241
+ setSessions(updatedSessions);
6242
+ }
6243
+ };
6244
+ const getSessionElement = (sessionId) => {
6245
+ return sessionElements.get(sessionId);
6246
+ };
6247
+ return {
6248
+ sessions,
6249
+ isProcessing,
6250
+ tryResumeSessions,
6251
+ startSession,
6252
+ abortSession,
6253
+ abortAllSessions,
6254
+ updateSessionBoundsOnViewportChange,
6255
+ getSessionElement
6256
+ };
6257
+ };
6258
+
5353
6259
  // src/core.tsx
5354
- var _tmpl$9 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">1 element`);
6260
+ var _tmpl$14 = /* @__PURE__ */ template(`<span class="tabular-nums align-middle">`);
5355
6261
  var _tmpl$23 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">&lt;<!>>`);
5356
- var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums text-[10px] ml-1 align-middle"> in `);
6262
+ var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums ml-1 align-middle"> in `);
5357
6263
  var hasInited = false;
6264
+ var getScriptOptions = () => {
6265
+ if (typeof window === "undefined") return null;
6266
+ try {
6267
+ const dataOptions = document.currentScript?.getAttribute("data-options");
6268
+ if (!dataOptions) return null;
6269
+ return JSON.parse(dataOptions);
6270
+ } catch {
6271
+ return null;
6272
+ }
6273
+ };
5358
6274
  var init = (rawOptions) => {
6275
+ const scriptOptions = getScriptOptions();
5359
6276
  const options = {
5360
6277
  enabled: true,
5361
6278
  keyHoldDuration: 200,
5362
6279
  allowActivationInsideInput: true,
6280
+ ...scriptOptions,
5363
6281
  ...rawOptions
5364
6282
  };
5365
6283
  const initialTheme = mergeTheme(options.theme);
@@ -5379,6 +6297,7 @@ var init = (rawOptions) => {
5379
6297
  isActive: false,
5380
6298
  isDragging: false,
5381
6299
  isCopying: false,
6300
+ isInputMode: false,
5382
6301
  targetElement: null,
5383
6302
  dragBounds: null
5384
6303
  }),
@@ -5390,9 +6309,8 @@ var init = (rawOptions) => {
5390
6309
  hasInited = true;
5391
6310
  const logIntro = () => {
5392
6311
  try {
5393
- const version = "0.0.53";
5394
- 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>`;
5395
- const logoDataUri = `data:image/svg+xml;base64,${btoa(logoSvg)}`;
6312
+ const version = "0.0.55";
6313
+ const logoDataUri = `data:image/svg+xml;base64,${btoa(LOGO_SVG)}`;
5396
6314
  console.log(`%cReact Grab${version ? ` v${version}` : ""}%c
5397
6315
  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;`, "");
5398
6316
  if (navigator.onLine && version) {
@@ -5420,33 +6338,45 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5420
6338
  const [dragStartX, setDragStartX] = createSignal(OFFSCREEN_POSITION);
5421
6339
  const [dragStartY, setDragStartY] = createSignal(OFFSCREEN_POSITION);
5422
6340
  const [isCopying, setIsCopying] = createSignal(false);
6341
+ const [selectionLabelStatus, setSelectionLabelStatus] = createSignal("idle");
6342
+ const [labelInstances, setLabelInstances] = createSignal([]);
5423
6343
  const [lastGrabbedElement, setLastGrabbedElement] = createSignal(null);
5424
6344
  const [progressStartTime, setProgressStartTime] = createSignal(null);
5425
- const [progress, setProgress] = createSignal(0);
5426
6345
  const [grabbedBoxes, setGrabbedBoxes] = createSignal([]);
5427
6346
  const [successLabels, setSuccessLabels] = createSignal([]);
5428
6347
  const [isActivated, setIsActivated] = createSignal(false);
5429
6348
  const [isToggleMode, setIsToggleMode] = createSignal(false);
5430
- const [showProgressIndicator, setShowProgressIndicator] = createSignal(false);
5431
6349
  const [didJustDrag, setDidJustDrag] = createSignal(false);
5432
6350
  const [copyStartX, setCopyStartX] = createSignal(OFFSCREEN_POSITION);
5433
6351
  const [copyStartY, setCopyStartY] = createSignal(OFFSCREEN_POSITION);
5434
- const [mouseHasSettled, setMouseHasSettled] = createSignal(false);
5435
6352
  const [viewportVersion, setViewportVersion] = createSignal(0);
5436
6353
  const [isInputMode, setIsInputMode] = createSignal(false);
5437
6354
  const [inputText, setInputText] = createSignal("");
6355
+ const [isTouchMode, setIsTouchMode] = createSignal(false);
6356
+ const [selectionFilePath, setSelectionFilePath] = createSignal(void 0);
6357
+ const [selectionLineNumber, setSelectionLineNumber] = createSignal(void 0);
6358
+ const [isToggleFrozen, setIsToggleFrozen] = createSignal(false);
6359
+ const [isInputExpanded, setIsInputExpanded] = createSignal(false);
6360
+ const [frozenElement, setFrozenElement] = createSignal(null);
6361
+ const [nativeSelectionCursorX, setNativeSelectionCursorX] = createSignal(OFFSCREEN_POSITION);
6362
+ const [nativeSelectionCursorY, setNativeSelectionCursorY] = createSignal(OFFSCREEN_POSITION);
6363
+ const [hasNativeSelection, setHasNativeSelection] = createSignal(false);
6364
+ const [nativeSelectionElements, setNativeSelectionElements] = createSignal([]);
6365
+ const [nativeSelectionTagName, setNativeSelectionTagName] = createSignal(void 0);
6366
+ const [nativeSelectionComponentName, setNativeSelectionComponentName] = createSignal(void 0);
6367
+ const nativeSelectionBounds = createMemo(() => {
6368
+ viewportVersion();
6369
+ const elements = nativeSelectionElements();
6370
+ if (elements.length === 0 || !elements[0]) return void 0;
6371
+ return createElementBounds(elements[0]);
6372
+ });
5438
6373
  let holdTimerId = null;
6374
+ let activationTimestamp = null;
5439
6375
  let progressAnimationId = null;
5440
- let progressDelayTimerId = null;
5441
6376
  let keydownSpamTimerId = null;
5442
- let mouseSettleTimerId = null;
5443
6377
  let autoScrollAnimationId = null;
6378
+ let previouslyFocusedElement = null;
5444
6379
  const isRendererActive = createMemo(() => isActivated() && !isCopying());
5445
- const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
5446
- const isTargetKeyCombination = (event) => (
5447
- // NOTE: we use event.code instead of event.key for keyboard layout compatibility (e.g., AZERTY, QWERTZ)
5448
- (event.metaKey || event.ctrlKey) && event.code === "KeyC"
5449
- );
5450
6380
  const getAutoScrollDirection = (clientX, clientY) => {
5451
6381
  return {
5452
6382
  top: clientY < AUTO_SCROLL_EDGE_THRESHOLD_PX,
@@ -5466,51 +6396,83 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5466
6396
  };
5467
6397
  const currentBoxes = grabbedBoxes();
5468
6398
  setGrabbedBoxes([...currentBoxes, newBox]);
6399
+ options.onGrabbedBox?.(bounds, element);
5469
6400
  setTimeout(() => {
5470
6401
  setGrabbedBoxes((previousBoxes) => previousBoxes.filter((box) => box.id !== boxId));
5471
6402
  }, SUCCESS_LABEL_DURATION_MS);
5472
6403
  };
5473
- const showTemporarySuccessLabel = (text) => {
6404
+ const showTemporarySuccessLabel = (text, type) => {
5474
6405
  const labelId = `success-${Date.now()}-${Math.random()}`;
5475
6406
  setSuccessLabels((previousLabels) => [...previousLabels, {
5476
6407
  id: labelId,
5477
6408
  text
5478
6409
  }]);
6410
+ options.onSuccessLabel?.(text, type, {
6411
+ x: mouseX(),
6412
+ y: mouseY()
6413
+ });
5479
6414
  setTimeout(() => {
5480
6415
  setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
5481
6416
  }, SUCCESS_LABEL_DURATION_MS);
5482
6417
  };
5483
- const wrapInSelectedElementTags = (context) => `<selected_element>
5484
- ${context}
5485
- </selected_element>`;
5486
6418
  const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
5487
6419
  const extractElementTagNameForSuccess = (element) => {
5488
6420
  const tagName = extractElementTagName(element);
5489
6421
  return tagName ? `<${tagName}>` : "1 element";
5490
6422
  };
5491
6423
  const notifyElementsSelected = (elements) => {
5492
- try {
5493
- const elementsPayload = elements.map((element) => ({
5494
- tagName: extractElementTagName(element)
5495
- }));
5496
- window.dispatchEvent(new CustomEvent("react-grab:element-selected", {
5497
- detail: {
5498
- elements: elementsPayload
5499
- }
5500
- }));
5501
- } catch {
5502
- }
6424
+ const elementsPayload = elements.map((element) => ({
6425
+ tagName: extractElementTagName(element)
6426
+ }));
6427
+ window.dispatchEvent(new CustomEvent("react-grab:element-selected", {
6428
+ detail: {
6429
+ elements: elementsPayload
6430
+ }
6431
+ }));
5503
6432
  };
5504
- const executeCopyOperation = async (positionX, positionY, operation) => {
6433
+ const createLabelInstance = (bounds, tagName, status, element) => {
6434
+ const instanceId = `label-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6435
+ setLabelInstances((prev) => [...prev, {
6436
+ id: instanceId,
6437
+ bounds,
6438
+ tagName,
6439
+ status,
6440
+ createdAt: Date.now(),
6441
+ element
6442
+ }]);
6443
+ return instanceId;
6444
+ };
6445
+ const updateLabelInstance = (instanceId, status) => {
6446
+ setLabelInstances((prev) => prev.map((instance) => instance.id === instanceId ? {
6447
+ ...instance,
6448
+ status
6449
+ } : instance));
6450
+ };
6451
+ const removeLabelInstance = (instanceId) => {
6452
+ setLabelInstances((prev) => prev.filter((instance) => instance.id !== instanceId));
6453
+ };
6454
+ const executeCopyOperation = async (positionX, positionY, operation, bounds, tagName, element) => {
5505
6455
  setCopyStartX(positionX);
5506
6456
  setCopyStartY(positionY);
5507
6457
  setIsCopying(true);
5508
6458
  startProgressAnimation();
6459
+ const instanceId = bounds && tagName ? createLabelInstance(bounds, tagName, "copying", element) : null;
5509
6460
  await operation().finally(() => {
5510
6461
  setIsCopying(false);
5511
6462
  stopProgressAnimation();
6463
+ if (instanceId) {
6464
+ updateLabelInstance(instanceId, "copied");
6465
+ setTimeout(() => {
6466
+ updateLabelInstance(instanceId, "fading");
6467
+ setTimeout(() => {
6468
+ removeLabelInstance(instanceId);
6469
+ }, 350);
6470
+ }, COPIED_LABEL_DURATION_MS);
6471
+ }
5512
6472
  if (isToggleMode()) {
5513
- deactivateRenderer();
6473
+ setTimeout(() => {
6474
+ deactivateRenderer();
6475
+ }, COPIED_LABEL_DURATION_MS + 350);
5514
6476
  }
5515
6477
  });
5516
6478
  };
@@ -5526,35 +6488,40 @@ ${context}
5526
6488
  let didCopy = false;
5527
6489
  let copiedContent = "";
5528
6490
  const isReactProject = Ee();
5529
- try {
5530
- await options.onBeforeCopy?.(elements);
5531
- } catch {
5532
- }
5533
- try {
5534
- const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => {
5535
- const htmlPreview = getHTMLPreview(element);
5536
- if (!isReactProject) {
5537
- return `## HTML Frame:
5538
- ${htmlPreview}`;
6491
+ await options.onBeforeCopy?.(elements);
6492
+ if (options.copyFileOnly && isReactProject) {
6493
+ try {
6494
+ const firstElement = elements[0];
6495
+ if (firstElement) {
6496
+ const stack = await getStack(firstElement);
6497
+ const fileName = getFileName(stack);
6498
+ if (fileName) {
6499
+ copiedContent = `@${fileName}`;
6500
+ didCopy = await copyContent(copiedContent);
6501
+ if (didCopy) {
6502
+ options.onCopySuccess?.(elements, copiedContent);
6503
+ }
6504
+ }
5539
6505
  }
5540
- const stack = await getStack(element);
5541
- const formattedStack = formatStack(stack);
5542
- if (formattedStack) {
5543
- return `## HTML Frame:
5544
- ${htmlPreview}
5545
-
5546
- ## Code Location:
5547
- ${formattedStack}`;
6506
+ } catch (error) {
6507
+ options.onCopyError?.(error);
6508
+ }
6509
+ options.onAfterCopy?.(elements, didCopy);
6510
+ return didCopy;
6511
+ }
6512
+ try {
6513
+ const elementSnippetResults = await Promise.allSettled(elements.map((element) => formatElementInfo(element)));
6514
+ const elementSnippets = [];
6515
+ for (const result of elementSnippetResults) {
6516
+ if (result.status === "fulfilled" && result.value.trim()) {
6517
+ elementSnippets.push(result.value);
5548
6518
  }
5549
- return `## HTML Frame:
5550
- ${htmlPreview}`;
5551
- }));
5552
- const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
6519
+ }
5553
6520
  if (elementSnippets.length > 0) {
5554
- const wrappedSnippets = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
6521
+ const combinedSnippets = elementSnippets.join("\n\n");
5555
6522
  const plainTextContent = extraPrompt ? `${extraPrompt}
5556
6523
 
5557
- ${wrappedSnippets}` : wrappedSnippets;
6524
+ ${combinedSnippets}` : combinedSnippets;
5558
6525
  copiedContent = plainTextContent;
5559
6526
  didCopy = await copyContent(plainTextContent);
5560
6527
  }
@@ -5569,16 +6536,10 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5569
6536
  }
5570
6537
  }
5571
6538
  if (didCopy) {
5572
- try {
5573
- options.onCopySuccess?.(elements, copiedContent);
5574
- } catch {
5575
- }
6539
+ options.onCopySuccess?.(elements, copiedContent);
5576
6540
  }
5577
6541
  } catch (error) {
5578
- try {
5579
- options.onCopyError?.(error);
5580
- } catch {
5581
- }
6542
+ options.onCopyError?.(error);
5582
6543
  const plainTextContentOnly = createCombinedTextContent(elements);
5583
6544
  if (plainTextContentOnly.length > 0) {
5584
6545
  const contentWithPrompt = extraPrompt ? `${extraPrompt}
@@ -5588,34 +6549,26 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5588
6549
  didCopy = await copyContent(contentWithPrompt);
5589
6550
  }
5590
6551
  }
5591
- try {
5592
- options.onAfterCopy?.(elements, didCopy);
5593
- } catch {
5594
- }
6552
+ options.onAfterCopy?.(elements, didCopy);
5595
6553
  return didCopy;
5596
6554
  };
5597
6555
  const copySingleElementToClipboard = async (targetElement2, extraPrompt) => {
5598
- try {
5599
- options.onElementSelect?.(targetElement2);
5600
- } catch {
5601
- }
6556
+ const successLabelType = extraPrompt ? "input-submit" : "copy";
6557
+ options.onElementSelect?.(targetElement2);
5602
6558
  if (theme().grabbedBoxes.enabled) {
5603
6559
  showTemporaryGrabbedBox(createElementBounds(targetElement2), targetElement2);
5604
6560
  }
5605
6561
  await new Promise((resolve) => requestAnimationFrame(resolve));
5606
6562
  const didCopy = await tryCopyWithFallback([targetElement2], extraPrompt);
5607
6563
  if (didCopy && theme().successLabels.enabled) {
5608
- showTemporarySuccessLabel(extractElementTagNameForSuccess(targetElement2));
6564
+ showTemporarySuccessLabel(extractElementTagNameForSuccess(targetElement2), successLabelType);
5609
6565
  }
5610
6566
  notifyElementsSelected([targetElement2]);
5611
6567
  };
5612
6568
  const copyMultipleElementsToClipboard = async (targetElements) => {
5613
6569
  if (targetElements.length === 0) return;
5614
6570
  for (const element of targetElements) {
5615
- try {
5616
- options.onElementSelect?.(element);
5617
- } catch {
5618
- }
6571
+ options.onElementSelect?.(element);
5619
6572
  }
5620
6573
  if (theme().grabbedBoxes.enabled) {
5621
6574
  for (const element of targetElements) {
@@ -5625,7 +6578,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5625
6578
  await new Promise((resolve) => requestAnimationFrame(resolve));
5626
6579
  const didCopy = await tryCopyWithFallback(targetElements);
5627
6580
  if (didCopy && theme().successLabels.enabled) {
5628
- showTemporarySuccessLabel(`${targetElements.length} elements`);
6581
+ showTemporarySuccessLabel(`${targetElements.length} elements`, "copy");
5629
6582
  }
5630
6583
  notifyElementsSelected(targetElements);
5631
6584
  };
@@ -5633,6 +6586,12 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5633
6586
  if (!isRendererActive() || isDragging()) return null;
5634
6587
  return getElementAtPosition(mouseX(), mouseY());
5635
6588
  });
6589
+ createEffect(() => {
6590
+ const element = targetElement();
6591
+ if (element) {
6592
+ setFrozenElement(element);
6593
+ }
6594
+ });
5636
6595
  const selectionBounds = createMemo(() => {
5637
6596
  viewportVersion();
5638
6597
  const element = targetElement();
@@ -5689,7 +6648,14 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5689
6648
  });
5690
6649
  const labelContent = createMemo(() => {
5691
6650
  const element = targetElement();
5692
- if (!element) return _tmpl$9();
6651
+ const copying = isCopying();
6652
+ if (!element) {
6653
+ return (() => {
6654
+ var _el$ = _tmpl$14();
6655
+ insert(_el$, copying ? "Please wait\u2026" : "1 element");
6656
+ return _el$;
6657
+ })();
6658
+ }
5693
6659
  const tagName = extractElementTagName(element);
5694
6660
  const componentName = getNearestComponentName(element);
5695
6661
  if (tagName && componentName) {
@@ -5710,14 +6676,20 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5710
6676
  return _el$8;
5711
6677
  })();
5712
6678
  }
5713
- return _tmpl$9();
6679
+ return (() => {
6680
+ var _el$10 = _tmpl$14();
6681
+ insert(_el$10, copying ? "Please wait\u2026" : "1 element");
6682
+ return _el$10;
6683
+ })();
5714
6684
  });
5715
- const labelPosition = createMemo(() => isCopying() ? {
5716
- x: copyStartX(),
5717
- y: copyStartY()
5718
- } : {
5719
- x: mouseX(),
5720
- y: mouseY()
6685
+ const labelPosition = createMemo(() => {
6686
+ return isCopying() ? {
6687
+ x: copyStartX(),
6688
+ y: copyStartY()
6689
+ } : {
6690
+ x: mouseX(),
6691
+ y: mouseY()
6692
+ };
5721
6693
  });
5722
6694
  const progressPosition = createMemo(() => isCopying() ? {
5723
6695
  x: copyStartX(),
@@ -5731,12 +6703,29 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5731
6703
  setLastGrabbedElement(null);
5732
6704
  }
5733
6705
  if (currentElement) {
5734
- try {
5735
- options.onElementHover?.(currentElement);
5736
- } catch {
5737
- }
6706
+ options.onElementHover?.(currentElement);
5738
6707
  }
5739
6708
  }));
6709
+ createEffect(on(() => targetElement(), (element) => {
6710
+ const clearSource = () => {
6711
+ setSelectionFilePath(void 0);
6712
+ setSelectionLineNumber(void 0);
6713
+ };
6714
+ if (!element) {
6715
+ clearSource();
6716
+ return;
6717
+ }
6718
+ getStack(element).then((stack) => {
6719
+ for (const frame of stack) {
6720
+ if (frame.source && je2(frame.source.fileName)) {
6721
+ setSelectionFilePath(Q(frame.source.fileName));
6722
+ setSelectionLineNumber(frame.source.lineNumber);
6723
+ return;
6724
+ }
6725
+ }
6726
+ clearSource();
6727
+ }).catch(clearSource);
6728
+ }));
5740
6729
  createEffect(on(() => viewportVersion(), () => {
5741
6730
  const currentBoxes = grabbedBoxes();
5742
6731
  if (currentBoxes.length === 0) return;
@@ -5746,40 +6735,90 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5746
6735
  }));
5747
6736
  setGrabbedBoxes(updatedBoxes);
5748
6737
  }));
5749
- createEffect(on(() => [isActivated(), isDragging(), isCopying(), targetElement(), dragBounds()], ([active, dragging, copying, target, drag]) => {
5750
- try {
5751
- options.onStateChange?.({
5752
- isActive: active,
5753
- isDragging: dragging,
5754
- isCopying: copying,
5755
- targetElement: target,
5756
- dragBounds: drag ? {
5757
- x: drag.x,
5758
- y: drag.y,
5759
- width: drag.width,
5760
- height: drag.height
5761
- } : null
5762
- });
5763
- } catch {
6738
+ createEffect(on(() => viewportVersion(), () => agentManager.updateSessionBoundsOnViewportChange()));
6739
+ createEffect(on(() => [isActivated(), isDragging(), isCopying(), isInputMode(), targetElement(), dragBounds()], ([active, dragging, copying, inputMode, target, drag]) => {
6740
+ options.onStateChange?.({
6741
+ isActive: active,
6742
+ isDragging: dragging,
6743
+ isCopying: copying,
6744
+ isInputMode: inputMode,
6745
+ targetElement: target,
6746
+ dragBounds: drag ? {
6747
+ x: drag.x,
6748
+ y: drag.y,
6749
+ width: drag.width,
6750
+ height: drag.height
6751
+ } : null
6752
+ });
6753
+ }));
6754
+ createEffect(on(() => [isInputMode(), mouseX(), mouseY(), targetElement()], ([inputMode, x3, y2, target]) => {
6755
+ options.onInputModeChange?.(inputMode, {
6756
+ x: x3,
6757
+ y: y2,
6758
+ targetElement: target
6759
+ });
6760
+ }));
6761
+ createEffect(on(() => [selectionVisible(), selectionBounds(), targetElement()], ([visible, bounds, element]) => {
6762
+ options.onSelectionBox?.(Boolean(visible), bounds ?? null, element);
6763
+ }));
6764
+ createEffect(on(() => [dragVisible(), dragBounds()], ([visible, bounds]) => {
6765
+ options.onDragBox?.(Boolean(visible), bounds ?? null);
6766
+ }));
6767
+ createEffect(on(() => [crosshairVisible(), mouseX(), mouseY()], ([visible, x3, y2]) => {
6768
+ options.onCrosshair?.(Boolean(visible), {
6769
+ x: x3,
6770
+ y: y2
6771
+ });
6772
+ }));
6773
+ createEffect(on(() => [labelVisible(), labelVariant(), labelContent(), labelPosition()], ([visible, variant, content, position]) => {
6774
+ const contentString = typeof content === "string" ? content : "";
6775
+ options.onElementLabel?.(Boolean(visible), variant, {
6776
+ x: position.x,
6777
+ y: position.y,
6778
+ content: contentString
6779
+ });
6780
+ }));
6781
+ let cursorStyleElement = null;
6782
+ const setCursorOverride = (cursor) => {
6783
+ if (cursor) {
6784
+ if (!cursorStyleElement) {
6785
+ cursorStyleElement = document.createElement("style");
6786
+ cursorStyleElement.setAttribute("data-react-grab-cursor", "");
6787
+ document.head.appendChild(cursorStyleElement);
6788
+ }
6789
+ cursorStyleElement.textContent = `* { cursor: ${cursor} !important; }`;
6790
+ } else if (cursorStyleElement) {
6791
+ cursorStyleElement.remove();
6792
+ cursorStyleElement = null;
6793
+ }
6794
+ };
6795
+ createEffect(on(() => [isActivated(), isCopying(), isDragging(), isInputMode(), targetElement()], ([activated, copying, dragging, inputMode, target]) => {
6796
+ if (copying) {
6797
+ setCursorOverride("progress");
6798
+ } else if (inputMode) {
6799
+ setCursorOverride(null);
6800
+ } else if (activated && dragging) {
6801
+ setCursorOverride("crosshair");
6802
+ } else if (activated && target) {
6803
+ setCursorOverride("copy");
6804
+ } else if (activated) {
6805
+ setCursorOverride("crosshair");
6806
+ } else {
6807
+ setCursorOverride(null);
5764
6808
  }
5765
6809
  }));
5766
- const startProgressAnimation = () => {
6810
+ const startProgressAnimation = (duration) => {
5767
6811
  const startTime = Date.now();
6812
+ const animationDuration = options.keyHoldDuration;
5768
6813
  setProgressStartTime(startTime);
5769
- setShowProgressIndicator(false);
5770
- progressDelayTimerId = window.setTimeout(() => {
5771
- setShowProgressIndicator(true);
5772
- progressDelayTimerId = null;
5773
- }, PROGRESS_INDICATOR_DELAY_MS);
5774
6814
  const animateProgress = () => {
5775
6815
  const currentStartTime = progressStartTime();
5776
6816
  if (currentStartTime === null) return;
5777
6817
  const elapsedTime = Date.now() - currentStartTime;
5778
- const normalizedTime = elapsedTime / options.keyHoldDuration;
6818
+ const normalizedTime = elapsedTime / animationDuration;
5779
6819
  const easedProgress = 1 - Math.exp(-normalizedTime);
5780
6820
  const maxProgressBeforeCompletion = 0.95;
5781
6821
  const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
5782
- setProgress(currentProgress);
5783
6822
  if (currentProgress < 1) {
5784
6823
  progressAnimationId = requestAnimationFrame(animateProgress);
5785
6824
  }
@@ -5791,13 +6830,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5791
6830
  cancelAnimationFrame(progressAnimationId);
5792
6831
  progressAnimationId = null;
5793
6832
  }
5794
- if (progressDelayTimerId !== null) {
5795
- window.clearTimeout(progressDelayTimerId);
5796
- progressDelayTimerId = null;
5797
- }
5798
6833
  setProgressStartTime(null);
5799
- setProgress(1);
5800
- setShowProgressIndicator(false);
5801
6834
  };
5802
6835
  const startAutoScroll = () => {
5803
6836
  const scroll = () => {
@@ -5826,8 +6859,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5826
6859
  };
5827
6860
  const activateRenderer = () => {
5828
6861
  stopProgressAnimation();
6862
+ previouslyFocusedElement = document.activeElement;
6863
+ activationTimestamp = Date.now();
5829
6864
  setIsActivated(true);
5830
- document.body.style.cursor = "crosshair";
5831
6865
  options.onActivate?.();
5832
6866
  };
5833
6867
  const deactivateRenderer = () => {
@@ -5836,59 +6870,254 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5836
6870
  setIsActivated(false);
5837
6871
  setIsInputMode(false);
5838
6872
  setInputText("");
5839
- document.body.style.cursor = "";
6873
+ setIsToggleFrozen(false);
6874
+ setIsInputExpanded(false);
6875
+ setFrozenElement(null);
6876
+ setSelectionLabelStatus("idle");
5840
6877
  if (isDragging()) {
5841
6878
  setIsDragging(false);
5842
6879
  document.body.style.userSelect = "";
5843
6880
  }
5844
6881
  if (holdTimerId) window.clearTimeout(holdTimerId);
5845
6882
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
5846
- if (mouseSettleTimerId) {
5847
- window.clearTimeout(mouseSettleTimerId);
5848
- mouseSettleTimerId = null;
5849
- }
5850
- setMouseHasSettled(false);
5851
6883
  stopAutoScroll();
5852
6884
  stopProgressAnimation();
6885
+ activationTimestamp = null;
6886
+ if (previouslyFocusedElement instanceof HTMLElement && document.contains(previouslyFocusedElement)) {
6887
+ previouslyFocusedElement.focus();
6888
+ }
6889
+ previouslyFocusedElement = null;
5853
6890
  options.onDeactivate?.();
5854
6891
  };
6892
+ const agentOptions = options.agent ? {
6893
+ ...options.agent,
6894
+ onAbort: (session, element) => {
6895
+ options.agent?.onAbort?.(session, element);
6896
+ if (element && document.contains(element)) {
6897
+ const rect = element.getBoundingClientRect();
6898
+ const centerX = rect.left + rect.width / 2;
6899
+ const centerY = rect.top + rect.height / 2;
6900
+ setMouseX(centerX);
6901
+ setMouseY(centerY);
6902
+ setFrozenElement(element);
6903
+ setInputText(session.context.prompt);
6904
+ setIsInputExpanded(true);
6905
+ setIsInputMode(true);
6906
+ setIsToggleMode(true);
6907
+ setIsToggleFrozen(true);
6908
+ if (!isActivated()) {
6909
+ activateRenderer();
6910
+ }
6911
+ }
6912
+ }
6913
+ } : void 0;
6914
+ const agentManager = createAgentManager(agentOptions);
5855
6915
  const handleInputChange = (value) => {
5856
6916
  setInputText(value);
5857
6917
  };
5858
6918
  const handleInputSubmit = () => {
5859
- if (!isInputMode()) return;
5860
- const element = targetElement();
5861
- const prompt = inputText().trim();
5862
- const currentX = mouseX();
5863
- const currentY = mouseY();
6919
+ const element = frozenElement() || targetElement();
6920
+ const prompt = isInputMode() ? inputText().trim() : "";
6921
+ if (!element) {
6922
+ deactivateRenderer();
6923
+ return;
6924
+ }
6925
+ const elementRect = element.getBoundingClientRect();
6926
+ const computedStyle = window.getComputedStyle(element);
6927
+ const bounds = {
6928
+ x: elementRect.left,
6929
+ y: elementRect.top,
6930
+ width: elementRect.width,
6931
+ height: elementRect.height,
6932
+ borderRadius: computedStyle.borderRadius || "0px",
6933
+ transform: stripTranslateFromTransform(element)
6934
+ };
6935
+ const currentX = bounds.x + bounds.width / 2;
6936
+ const currentY = bounds.y + bounds.height / 2;
6937
+ setMouseX(currentX);
6938
+ setMouseY(currentY);
6939
+ if (options.agent?.provider && prompt) {
6940
+ const positionX = mouseX();
6941
+ const positionY = mouseY();
6942
+ setInputText("");
6943
+ setIsInputMode(false);
6944
+ deactivateRenderer();
6945
+ void agentManager.startSession({
6946
+ element,
6947
+ prompt,
6948
+ position: {
6949
+ x: positionX,
6950
+ y: positionY
6951
+ },
6952
+ selectionBounds: bounds
6953
+ });
6954
+ return;
6955
+ }
5864
6956
  setIsInputMode(false);
5865
6957
  setInputText("");
5866
- if (element) {
5867
- void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0)).then(() => {
5868
- deactivateRenderer();
5869
- });
5870
- } else {
6958
+ const tagName = extractElementTagName(element);
6959
+ void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0), bounds, tagName, element).then(() => {
5871
6960
  deactivateRenderer();
5872
- }
6961
+ });
5873
6962
  };
5874
6963
  const handleInputCancel = () => {
5875
6964
  if (!isInputMode()) return;
5876
6965
  deactivateRenderer();
5877
6966
  };
6967
+ const handleToggleExpand = () => {
6968
+ setIsToggleMode(true);
6969
+ setIsToggleFrozen(true);
6970
+ setIsInputExpanded(true);
6971
+ setIsInputMode(true);
6972
+ };
6973
+ const handleNativeSelectionCopy = async () => {
6974
+ const elements = nativeSelectionElements();
6975
+ if (elements.length === 0) return;
6976
+ const currentX = nativeSelectionCursorX();
6977
+ const currentY = nativeSelectionCursorY();
6978
+ const bounds = nativeSelectionBounds();
6979
+ const tagName = nativeSelectionTagName();
6980
+ setHasNativeSelection(false);
6981
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
6982
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
6983
+ setNativeSelectionElements([]);
6984
+ setNativeSelectionTagName(void 0);
6985
+ setNativeSelectionComponentName(void 0);
6986
+ window.getSelection()?.removeAllRanges();
6987
+ if (elements.length === 1) {
6988
+ await executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(elements[0]), bounds, tagName);
6989
+ } else {
6990
+ await executeCopyOperation(currentX, currentY, () => copyMultipleElementsToClipboard(elements), bounds, tagName);
6991
+ }
6992
+ };
6993
+ const handleNativeSelectionEnter = () => {
6994
+ const elements = nativeSelectionElements();
6995
+ if (elements.length === 0) return;
6996
+ const bounds = nativeSelectionBounds();
6997
+ const currentX = bounds ? bounds.x + bounds.width / 2 : nativeSelectionCursorX();
6998
+ const currentY = bounds ? bounds.y + bounds.height / 2 : nativeSelectionCursorY();
6999
+ setHasNativeSelection(false);
7000
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7001
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7002
+ setNativeSelectionElements([]);
7003
+ setNativeSelectionTagName(void 0);
7004
+ setNativeSelectionComponentName(void 0);
7005
+ window.getSelection()?.removeAllRanges();
7006
+ setMouseX(currentX);
7007
+ setMouseY(currentY);
7008
+ setIsToggleMode(true);
7009
+ setIsToggleFrozen(true);
7010
+ setIsInputExpanded(true);
7011
+ activateRenderer();
7012
+ setIsInputMode(true);
7013
+ };
7014
+ const handlePointerMove = (clientX, clientY) => {
7015
+ if (isInputMode() || isToggleFrozen()) return;
7016
+ setMouseX(clientX);
7017
+ setMouseY(clientY);
7018
+ if (isDragging()) {
7019
+ const direction = getAutoScrollDirection(clientX, clientY);
7020
+ const isNearEdge = direction.top || direction.bottom || direction.left || direction.right;
7021
+ if (isNearEdge && autoScrollAnimationId === null) {
7022
+ startAutoScroll();
7023
+ } else if (!isNearEdge && autoScrollAnimationId !== null) {
7024
+ stopAutoScroll();
7025
+ }
7026
+ }
7027
+ };
7028
+ const handlePointerDown = (clientX, clientY) => {
7029
+ if (!isRendererActive() || isCopying()) return false;
7030
+ setIsDragging(true);
7031
+ const startX = clientX + window.scrollX;
7032
+ const startY = clientY + window.scrollY;
7033
+ setDragStartX(startX);
7034
+ setDragStartY(startY);
7035
+ document.body.style.userSelect = "none";
7036
+ options.onDragStart?.(startX, startY);
7037
+ return true;
7038
+ };
7039
+ const handlePointerUp = (clientX, clientY) => {
7040
+ if (!isDragging()) return;
7041
+ const dragDistance = calculateDragDistance(clientX, clientY);
7042
+ const wasDragGesture = dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
7043
+ setIsDragging(false);
7044
+ stopAutoScroll();
7045
+ document.body.style.userSelect = "";
7046
+ if (wasDragGesture) {
7047
+ setDidJustDrag(true);
7048
+ const dragRect = calculateDragRectangle(clientX, clientY);
7049
+ const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
7050
+ const selectedElements = elements.length > 0 ? elements : getElementsInDragLoose(dragRect, isValidGrabbableElement);
7051
+ if (selectedElements.length > 0) {
7052
+ options.onDragEnd?.(selectedElements, dragRect);
7053
+ const firstElement = selectedElements[0];
7054
+ const firstElementRect = firstElement.getBoundingClientRect();
7055
+ const bounds = {
7056
+ x: firstElementRect.left,
7057
+ y: firstElementRect.top,
7058
+ width: firstElementRect.width,
7059
+ height: firstElementRect.height,
7060
+ borderRadius: "0px",
7061
+ transform: stripTranslateFromTransform(firstElement)
7062
+ };
7063
+ const tagName = extractElementTagName(firstElement);
7064
+ if (options.agent?.provider) {
7065
+ const centerX = bounds.x + bounds.width / 2;
7066
+ const centerY = bounds.y + bounds.height / 2;
7067
+ setMouseX(centerX);
7068
+ setMouseY(centerY);
7069
+ setFrozenElement(firstElement);
7070
+ setIsToggleMode(true);
7071
+ setIsToggleFrozen(true);
7072
+ setIsInputExpanded(true);
7073
+ setIsInputMode(true);
7074
+ } else {
7075
+ void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(selectedElements), bounds, tagName, firstElement);
7076
+ }
7077
+ }
7078
+ } else {
7079
+ const element = getElementAtPosition(clientX, clientY);
7080
+ if (!element) return;
7081
+ setLastGrabbedElement(element);
7082
+ const elementRect = element.getBoundingClientRect();
7083
+ const computedStyle = window.getComputedStyle(element);
7084
+ const bounds = {
7085
+ x: elementRect.left,
7086
+ y: elementRect.top,
7087
+ width: elementRect.width,
7088
+ height: elementRect.height,
7089
+ borderRadius: computedStyle.borderRadius || "0px",
7090
+ transform: stripTranslateFromTransform(element)
7091
+ };
7092
+ const tagName = extractElementTagName(element);
7093
+ void executeCopyOperation(clientX, clientY, () => copySingleElementToClipboard(element), bounds, tagName, element);
7094
+ }
7095
+ };
5878
7096
  const abortController = new AbortController();
5879
7097
  const eventListenerSignal = abortController.signal;
5880
7098
  window.addEventListener("keydown", (event) => {
5881
- if (event.code === "Escape" && isHoldingKeys()) {
5882
- if (isInputMode()) {
5883
- return;
7099
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
7100
+ if (event.key === "Escape" && agentManager.isProcessing()) {
7101
+ agentManager.abortAllSessions();
5884
7102
  }
5885
- deactivateRenderer();
5886
7103
  return;
5887
7104
  }
5888
- if (event.code === "Enter" && isHoldingKeys() && !isInputMode()) {
7105
+ if (event.key === "Escape") {
7106
+ if (agentManager.isProcessing()) {
7107
+ agentManager.abortAllSessions();
7108
+ return;
7109
+ }
7110
+ if (isHoldingKeys()) {
7111
+ deactivateRenderer();
7112
+ return;
7113
+ }
7114
+ }
7115
+ if (event.key === "Enter" && isHoldingKeys() && !isInputMode()) {
5889
7116
  event.preventDefault();
5890
7117
  event.stopPropagation();
5891
7118
  setIsToggleMode(true);
7119
+ setIsToggleFrozen(true);
7120
+ setIsInputExpanded(true);
5892
7121
  if (keydownSpamTimerId !== null) {
5893
7122
  window.clearTimeout(keydownSpamTimerId);
5894
7123
  keydownSpamTimerId = null;
@@ -5900,15 +7129,42 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5900
7129
  setIsInputMode(true);
5901
7130
  return;
5902
7131
  }
7132
+ if (event.key.toLowerCase() === "o" && !isInputMode()) {
7133
+ if (isActivated() && (event.metaKey || event.ctrlKey)) {
7134
+ const filePath = selectionFilePath();
7135
+ const lineNumber = selectionLineNumber();
7136
+ if (filePath) {
7137
+ event.preventDefault();
7138
+ event.stopPropagation();
7139
+ if (options.onOpenFile) {
7140
+ options.onOpenFile(filePath, lineNumber);
7141
+ } else {
7142
+ const url = buildOpenFileUrl(filePath, lineNumber);
7143
+ window.open(url, "_blank");
7144
+ }
7145
+ }
7146
+ return;
7147
+ }
7148
+ }
5903
7149
  if (!options.allowActivationInsideInput && isKeyboardEventTriggeredByInput(event)) {
5904
7150
  return;
5905
7151
  }
5906
- if (!isTargetKeyCombination(event)) return;
5907
- if (isActivated() || isHoldingKeys()) {
7152
+ if (!isTargetKeyCombination(event, options)) {
7153
+ if (isActivated() && !isToggleMode() && (event.metaKey || event.ctrlKey)) {
7154
+ if (!MODIFIER_KEYS.includes(event.key) && event.key !== "Enter") {
7155
+ deactivateRenderer();
7156
+ }
7157
+ }
7158
+ if (event.key !== "Enter") {
7159
+ return;
7160
+ }
7161
+ }
7162
+ if ((isActivated() || isHoldingKeys()) && !isInputMode()) {
5908
7163
  event.preventDefault();
5909
7164
  }
5910
7165
  if (isActivated()) {
5911
7166
  if (isToggleMode()) return;
7167
+ if (event.repeat) return;
5912
7168
  if (keydownSpamTimerId !== null) {
5913
7169
  window.clearTimeout(keydownSpamTimerId);
5914
7170
  }
@@ -5933,9 +7189,44 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5933
7189
  });
5934
7190
  window.addEventListener("keyup", (event) => {
5935
7191
  if (!isHoldingKeys() && !isActivated()) return;
5936
- const isReleasingModifier = !event.metaKey && !event.ctrlKey;
5937
- const isReleasingC = event.code === "KeyC";
5938
- if (isReleasingC || isReleasingModifier) {
7192
+ if (isInputMode()) return;
7193
+ const hasCustomShortcut = Boolean(options.activationShortcut || options.activationKey);
7194
+ const getRequiredModifiers = () => {
7195
+ if (options.activationKey) {
7196
+ const {
7197
+ metaKey,
7198
+ ctrlKey,
7199
+ shiftKey,
7200
+ altKey
7201
+ } = options.activationKey;
7202
+ return {
7203
+ metaKey: !!metaKey,
7204
+ ctrlKey: !!ctrlKey,
7205
+ shiftKey: !!shiftKey,
7206
+ altKey: !!altKey
7207
+ };
7208
+ }
7209
+ return {
7210
+ metaKey: true,
7211
+ ctrlKey: true,
7212
+ shiftKey: false,
7213
+ altKey: false
7214
+ };
7215
+ };
7216
+ const requiredModifiers = getRequiredModifiers();
7217
+ const isReleasingModifier = requiredModifiers.metaKey || requiredModifiers.ctrlKey ? !event.metaKey && !event.ctrlKey : requiredModifiers.shiftKey && !event.shiftKey || requiredModifiers.altKey && !event.altKey;
7218
+ 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);
7219
+ if (isActivated()) {
7220
+ if (isReleasingModifier) {
7221
+ if (isToggleMode()) return;
7222
+ deactivateRenderer();
7223
+ } else if (!hasCustomShortcut && isReleasingActivationKey && keydownSpamTimerId !== null) {
7224
+ window.clearTimeout(keydownSpamTimerId);
7225
+ keydownSpamTimerId = null;
7226
+ }
7227
+ return;
7228
+ }
7229
+ if (isReleasingActivationKey || isReleasingModifier) {
5939
7230
  if (isToggleMode()) return;
5940
7231
  deactivateRenderer();
5941
7232
  }
@@ -5944,91 +7235,72 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5944
7235
  capture: true
5945
7236
  });
5946
7237
  window.addEventListener("mousemove", (event) => {
5947
- if (isInputMode()) return;
5948
- setMouseX(event.clientX);
5949
- setMouseY(event.clientY);
5950
- if (mouseSettleTimerId !== null) {
5951
- window.clearTimeout(mouseSettleTimerId);
5952
- }
5953
- setMouseHasSettled(false);
5954
- mouseSettleTimerId = window.setTimeout(() => {
5955
- setMouseHasSettled(true);
5956
- mouseSettleTimerId = null;
5957
- }, 300);
5958
- if (isDragging()) {
5959
- const direction = getAutoScrollDirection(event.clientX, event.clientY);
5960
- const isNearEdge = direction.top || direction.bottom || direction.left || direction.right;
5961
- if (isNearEdge && autoScrollAnimationId === null) {
5962
- startAutoScroll();
5963
- } else if (!isNearEdge && autoScrollAnimationId !== null) {
5964
- stopAutoScroll();
5965
- }
5966
- }
7238
+ setIsTouchMode(false);
7239
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
7240
+ handlePointerMove(event.clientX, event.clientY);
5967
7241
  }, {
5968
7242
  signal: eventListenerSignal
5969
7243
  });
5970
7244
  window.addEventListener("mousedown", (event) => {
7245
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
5971
7246
  if (isInputMode()) {
5972
- const target = event.target;
5973
- const isClickingInput = target.closest("[data-react-grab-input]");
5974
- if (!isClickingInput) {
5975
- handleInputCancel();
5976
- }
7247
+ handleInputCancel();
5977
7248
  return;
5978
7249
  }
5979
- if (!isRendererActive() || isCopying()) return;
5980
- event.preventDefault();
5981
- setIsDragging(true);
5982
- const startX = event.clientX + window.scrollX;
5983
- const startY = event.clientY + window.scrollY;
5984
- setDragStartX(startX);
5985
- setDragStartY(startY);
5986
- document.body.style.userSelect = "none";
5987
- try {
5988
- options.onDragStart?.(startX, startY);
5989
- } catch {
7250
+ const didHandle = handlePointerDown(event.clientX, event.clientY);
7251
+ if (didHandle) {
7252
+ event.preventDefault();
5990
7253
  }
5991
7254
  }, {
5992
7255
  signal: eventListenerSignal,
5993
7256
  capture: true
5994
7257
  });
7258
+ window.addEventListener("pointerdown", (event) => {
7259
+ if (!isRendererActive() || isCopying() || isInputMode()) return;
7260
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
7261
+ event.stopPropagation();
7262
+ }, {
7263
+ signal: eventListenerSignal,
7264
+ capture: true
7265
+ });
5995
7266
  window.addEventListener("mouseup", (event) => {
5996
- if (!isDragging()) return;
5997
- const dragDistance = calculateDragDistance(event.clientX, event.clientY);
5998
- const wasDragGesture = dragDistance.x > DRAG_THRESHOLD_PX || dragDistance.y > DRAG_THRESHOLD_PX;
5999
- setIsDragging(false);
6000
- stopAutoScroll();
6001
- document.body.style.userSelect = "";
6002
- if (wasDragGesture) {
6003
- setDidJustDrag(true);
6004
- const dragRect = calculateDragRectangle(event.clientX, event.clientY);
6005
- const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
6006
- if (elements.length > 0) {
6007
- try {
6008
- options.onDragEnd?.(elements, dragRect);
6009
- } catch {
6010
- }
6011
- void executeCopyOperation(event.clientX, event.clientY, () => copyMultipleElementsToClipboard(elements));
6012
- } else {
6013
- const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
6014
- if (fallbackElements.length > 0) {
6015
- try {
6016
- options.onDragEnd?.(fallbackElements, dragRect);
6017
- } catch {
6018
- }
6019
- void executeCopyOperation(event.clientX, event.clientY, () => copyMultipleElementsToClipboard(fallbackElements));
6020
- }
6021
- }
6022
- } else {
6023
- const element = getElementAtPosition(event.clientX, event.clientY);
6024
- if (!element) return;
6025
- setLastGrabbedElement(element);
6026
- void executeCopyOperation(event.clientX, event.clientY, () => copySingleElementToClipboard(element));
7267
+ handlePointerUp(event.clientX, event.clientY);
7268
+ }, {
7269
+ signal: eventListenerSignal
7270
+ });
7271
+ window.addEventListener("touchmove", (event) => {
7272
+ if (event.touches.length === 0) return;
7273
+ setIsTouchMode(true);
7274
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
7275
+ handlePointerMove(event.touches[0].clientX, event.touches[0].clientY);
7276
+ }, {
7277
+ signal: eventListenerSignal,
7278
+ passive: true
7279
+ });
7280
+ window.addEventListener("touchstart", (event) => {
7281
+ if (event.touches.length === 0) return;
7282
+ setIsTouchMode(true);
7283
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
7284
+ if (isInputMode()) {
7285
+ handleInputCancel();
7286
+ return;
7287
+ }
7288
+ const didHandle = handlePointerDown(event.touches[0].clientX, event.touches[0].clientY);
7289
+ if (didHandle) {
7290
+ event.preventDefault();
6027
7291
  }
7292
+ }, {
7293
+ signal: eventListenerSignal,
7294
+ passive: false
7295
+ });
7296
+ window.addEventListener("touchend", (event) => {
7297
+ if (event.changedTouches.length === 0) return;
7298
+ handlePointerUp(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
6028
7299
  }, {
6029
7300
  signal: eventListenerSignal
6030
7301
  });
6031
7302
  window.addEventListener("click", (event) => {
7303
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6032
7304
  if (isRendererActive() || isCopying() || didJustDrag()) {
6033
7305
  event.preventDefault();
6034
7306
  event.stopPropagation();
@@ -6051,6 +7323,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6051
7323
  document.addEventListener("visibilitychange", () => {
6052
7324
  if (document.hidden) {
6053
7325
  setGrabbedBoxes([]);
7326
+ if (isActivated() && !isInputMode() && activationTimestamp !== null && Date.now() - activationTimestamp > BLUR_DEACTIVATION_THRESHOLD_MS) {
7327
+ deactivateRenderer();
7328
+ }
6054
7329
  }
6055
7330
  }, {
6056
7331
  signal: eventListenerSignal
@@ -6067,6 +7342,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6067
7342
  signal: eventListenerSignal
6068
7343
  });
6069
7344
  document.addEventListener("copy", (event) => {
7345
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
7346
+ return;
7347
+ }
6070
7348
  if (isRendererActive() || isCopying()) {
6071
7349
  event.preventDefault();
6072
7350
  }
@@ -6074,18 +7352,118 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6074
7352
  signal: eventListenerSignal,
6075
7353
  capture: true
6076
7354
  });
7355
+ let selectionDebounceTimerId = null;
7356
+ document.addEventListener("selectionchange", () => {
7357
+ if (isRendererActive()) return;
7358
+ if (selectionDebounceTimerId !== null) {
7359
+ window.clearTimeout(selectionDebounceTimerId);
7360
+ }
7361
+ setHasNativeSelection(false);
7362
+ const selection = window.getSelection();
7363
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
7364
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7365
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7366
+ setNativeSelectionElements([]);
7367
+ setNativeSelectionTagName(void 0);
7368
+ setNativeSelectionComponentName(void 0);
7369
+ return;
7370
+ }
7371
+ selectionDebounceTimerId = window.setTimeout(() => {
7372
+ selectionDebounceTimerId = null;
7373
+ const currentSelection = window.getSelection();
7374
+ if (!currentSelection || currentSelection.isCollapsed || currentSelection.rangeCount === 0) {
7375
+ return;
7376
+ }
7377
+ const range = currentSelection.getRangeAt(0);
7378
+ const rangeRect = range.getBoundingClientRect();
7379
+ if (rangeRect.width === 0 && rangeRect.height === 0) {
7380
+ return;
7381
+ }
7382
+ const isBackward = (() => {
7383
+ if (!currentSelection.anchorNode || !currentSelection.focusNode) return false;
7384
+ const position = currentSelection.anchorNode.compareDocumentPosition(currentSelection.focusNode);
7385
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return false;
7386
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return true;
7387
+ return currentSelection.anchorOffset > currentSelection.focusOffset;
7388
+ })();
7389
+ const clientRects = range.getClientRects();
7390
+ if (clientRects.length === 0) {
7391
+ return;
7392
+ }
7393
+ const cursorRect = isBackward ? clientRects[0] : clientRects[clientRects.length - 1];
7394
+ const cursorX = isBackward ? cursorRect.left : cursorRect.right;
7395
+ const cursorY = cursorRect.top + cursorRect.height / 2;
7396
+ if (isSelectionInsideEditableElement(cursorX, cursorY)) {
7397
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7398
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7399
+ setNativeSelectionElements([]);
7400
+ setNativeSelectionTagName(void 0);
7401
+ setNativeSelectionComponentName(void 0);
7402
+ return;
7403
+ }
7404
+ setNativeSelectionCursorX(cursorX);
7405
+ setNativeSelectionCursorY(cursorY);
7406
+ const container = range.commonAncestorContainer;
7407
+ const element = container.nodeType === Node.ELEMENT_NODE ? container : container.parentElement;
7408
+ if (element && isValidGrabbableElement(element)) {
7409
+ setNativeSelectionElements([element]);
7410
+ setNativeSelectionTagName(extractElementTagName(element) || void 0);
7411
+ setNativeSelectionComponentName(getNearestComponentName(element) || void 0);
7412
+ setHasNativeSelection(true);
7413
+ } else {
7414
+ setNativeSelectionElements([]);
7415
+ setNativeSelectionTagName(void 0);
7416
+ setNativeSelectionComponentName(void 0);
7417
+ }
7418
+ }, 150);
7419
+ }, {
7420
+ signal: eventListenerSignal
7421
+ });
6077
7422
  onCleanup(() => {
6078
7423
  abortController.abort();
6079
7424
  if (holdTimerId) window.clearTimeout(holdTimerId);
6080
7425
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
6081
- if (mouseSettleTimerId) window.clearTimeout(mouseSettleTimerId);
6082
7426
  stopAutoScroll();
6083
7427
  stopProgressAnimation();
6084
7428
  document.body.style.userSelect = "";
6085
- document.body.style.cursor = "";
7429
+ setCursorOverride(null);
6086
7430
  });
6087
7431
  const rendererRoot = mountRoot(styles_default);
6088
- const selectionVisible = createMemo(() => theme().selectionBox.enabled && isRendererActive() && !isDragging() && Boolean(targetElement()));
7432
+ const selectionVisible = createMemo(() => {
7433
+ if (!theme().selectionBox.enabled) return false;
7434
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7435
+ });
7436
+ const selectionTagName = createMemo(() => {
7437
+ const element = targetElement();
7438
+ if (!element) return void 0;
7439
+ return extractElementTagName(element) || void 0;
7440
+ });
7441
+ const selectionLabelVisible = createMemo(() => {
7442
+ if (!theme().elementLabel.enabled) return false;
7443
+ if (successLabels().length > 0) return false;
7444
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7445
+ });
7446
+ const computedLabelInstances = createMemo(() => {
7447
+ viewportVersion();
7448
+ return labelInstances().map((instance) => {
7449
+ if (!instance.element || !document.body.contains(instance.element)) {
7450
+ return instance;
7451
+ }
7452
+ const elementRect = instance.element.getBoundingClientRect();
7453
+ const computedStyle = window.getComputedStyle(instance.element);
7454
+ return {
7455
+ ...instance,
7456
+ bounds: {
7457
+ x: elementRect.left,
7458
+ y: elementRect.top,
7459
+ width: elementRect.width,
7460
+ height: elementRect.height,
7461
+ borderRadius: computedStyle.borderRadius || "0px",
7462
+ transform: stripTranslateFromTransform(instance.element)
7463
+ }
7464
+ };
7465
+ });
7466
+ });
6089
7467
  const dragVisible = createMemo(() => theme().dragBox.enabled && isRendererActive() && isDraggingBeyondThreshold());
6090
7468
  const labelVariant = createMemo(() => isCopying() ? "processing" : "hover");
6091
7469
  const labelVisible = createMemo(() => {
@@ -6095,11 +7473,8 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6095
7473
  if (successLabels().length > 0) return false;
6096
7474
  return isRendererActive() && !isDragging() && Boolean(targetElement());
6097
7475
  });
6098
- const progressVisible = createMemo(() => isCopying() && showProgressIndicator() && hasValidMousePosition());
6099
- const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging());
6100
- const inputVisible = createMemo(() => theme().inputOverlay.enabled && isInputMode());
7476
+ const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging() && !isTouchMode() && !isToggleFrozen());
6101
7477
  const shouldShowGrabbedBoxes = createMemo(() => theme().grabbedBoxes.enabled);
6102
- const shouldShowSuccessLabels = createMemo(() => theme().successLabels.enabled);
6103
7478
  createEffect(on(theme, (currentTheme) => {
6104
7479
  if (currentTheme.hue !== 0) {
6105
7480
  rendererRoot.style.filter = `hue-rotate(${currentTheme.hue}deg)`;
@@ -6115,43 +7490,34 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6115
7490
  get selectionBounds() {
6116
7491
  return selectionBounds();
6117
7492
  },
6118
- get dragVisible() {
6119
- return dragVisible();
7493
+ get selectionFilePath() {
7494
+ return selectionFilePath();
6120
7495
  },
6121
- get dragBounds() {
6122
- return dragBounds();
7496
+ get selectionLineNumber() {
7497
+ return selectionLineNumber();
6123
7498
  },
6124
- get grabbedBoxes() {
6125
- return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
7499
+ get selectionTagName() {
7500
+ return selectionTagName();
6126
7501
  },
6127
- get successLabels() {
6128
- return memo(() => !!shouldShowSuccessLabels())() ? successLabels() : [];
7502
+ get selectionLabelVisible() {
7503
+ return selectionLabelVisible();
6129
7504
  },
6130
- get labelVariant() {
6131
- return labelVariant();
7505
+ get selectionLabelStatus() {
7506
+ return selectionLabelStatus();
6132
7507
  },
6133
- get labelContent() {
6134
- return labelContent();
7508
+ get labelInstances() {
7509
+ return computedLabelInstances();
6135
7510
  },
6136
- get labelX() {
6137
- return labelPosition().x;
7511
+ get dragVisible() {
7512
+ return dragVisible();
6138
7513
  },
6139
- get labelY() {
6140
- return labelPosition().y;
7514
+ get dragBounds() {
7515
+ return dragBounds();
6141
7516
  },
6142
- get labelVisible() {
6143
- return labelVisible();
7517
+ get grabbedBoxes() {
7518
+ return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
6144
7519
  },
6145
7520
  labelZIndex: Z_INDEX_LABEL,
6146
- get labelShowHint() {
6147
- return mouseHasSettled();
6148
- },
6149
- get progressVisible() {
6150
- return progressVisible();
6151
- },
6152
- get progress() {
6153
- return progress();
6154
- },
6155
7521
  get mouseX() {
6156
7522
  return progressPosition().x;
6157
7523
  },
@@ -6161,44 +7527,64 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6161
7527
  get crosshairVisible() {
6162
7528
  return crosshairVisible();
6163
7529
  },
6164
- get inputVisible() {
6165
- return inputVisible();
7530
+ get inputValue() {
7531
+ return inputText();
6166
7532
  },
6167
- get inputX() {
6168
- return mouseX();
7533
+ get isInputExpanded() {
7534
+ return isInputExpanded();
6169
7535
  },
6170
- get inputY() {
6171
- return mouseY();
7536
+ get hasAgent() {
7537
+ return Boolean(options.agent?.provider);
6172
7538
  },
6173
- get inputValue() {
6174
- return inputText();
7539
+ get agentSessions() {
7540
+ return agentManager.sessions();
6175
7541
  },
7542
+ onAbortSession: (sessionId) => agentManager.abortSession(sessionId),
6176
7543
  onInputChange: handleInputChange,
6177
- onInputSubmit: handleInputSubmit,
7544
+ onInputSubmit: () => void handleInputSubmit(),
6178
7545
  onInputCancel: handleInputCancel,
7546
+ onToggleExpand: handleToggleExpand,
7547
+ get nativeSelectionCursorVisible() {
7548
+ return hasNativeSelection();
7549
+ },
7550
+ get nativeSelectionCursorX() {
7551
+ return nativeSelectionCursorX();
7552
+ },
7553
+ get nativeSelectionCursorY() {
7554
+ return nativeSelectionCursorY();
7555
+ },
7556
+ get nativeSelectionTagName() {
7557
+ return nativeSelectionTagName();
7558
+ },
7559
+ get nativeSelectionComponentName() {
7560
+ return nativeSelectionComponentName();
7561
+ },
7562
+ get nativeSelectionBounds() {
7563
+ return nativeSelectionBounds();
7564
+ },
7565
+ onNativeSelectionCopy: () => void handleNativeSelectionCopy(),
7566
+ onNativeSelectionEnter: handleNativeSelectionEnter,
6179
7567
  get theme() {
6180
7568
  return theme();
6181
7569
  }
6182
7570
  }), rendererRoot);
6183
7571
  }
7572
+ if (options.agent?.provider) {
7573
+ agentManager.tryResumeSessions();
7574
+ }
6184
7575
  const copyElementAPI = async (elements) => {
6185
7576
  const elementsArray = Array.isArray(elements) ? elements : [elements];
6186
7577
  if (elementsArray.length === 0) return false;
6187
- try {
6188
- await options.onBeforeCopy?.(elementsArray);
6189
- } catch {
6190
- }
7578
+ await options.onBeforeCopy?.(elementsArray);
6191
7579
  const didCopy = await tryCopyWithFallback(elementsArray);
6192
- try {
6193
- options.onAfterCopy?.(elementsArray, didCopy);
6194
- } catch {
6195
- }
7580
+ options.onAfterCopy?.(elementsArray, didCopy);
6196
7581
  return didCopy;
6197
7582
  };
6198
7583
  const getStateAPI = () => ({
6199
7584
  isActive: isActivated(),
6200
7585
  isDragging: isDragging(),
6201
7586
  isCopying: isCopying(),
7587
+ isInputMode: isInputMode(),
6202
7588
  targetElement: targetElement(),
6203
7589
  dragBounds: dragBounds() ? {
6204
7590
  x: dragBounds().x,
@@ -6210,6 +7596,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6210
7596
  return {
6211
7597
  activate: () => {
6212
7598
  if (!isActivated()) {
7599
+ setIsToggleMode(true);
6213
7600
  activateRenderer();
6214
7601
  }
6215
7602
  },
@@ -6222,11 +7609,15 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6222
7609
  if (isActivated()) {
6223
7610
  deactivateRenderer();
6224
7611
  } else {
7612
+ setIsToggleMode(true);
6225
7613
  activateRenderer();
6226
7614
  }
6227
7615
  },
6228
7616
  isActive: () => isActivated(),
6229
- dispose: dispose2,
7617
+ dispose: () => {
7618
+ hasInited = false;
7619
+ dispose2();
7620
+ },
6230
7621
  copyElement: copyElementAPI,
6231
7622
  getState: getStateAPI,
6232
7623
  updateTheme: (partialTheme) => {
@@ -6301,4 +7692,4 @@ bippy/dist/source.js:
6301
7692
  *)
6302
7693
  */
6303
7694
 
6304
- export { DEFAULT_THEME, Ee, formatStack, getHTMLPreview, getNearestComponentName, getStack, init };
7695
+ export { DEFAULT_THEME, Ee, formatElementInfo, generateSnippet, getFileName, getNearestComponentName, getStack, init };