react-grab 0.0.54 → 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.
@@ -552,12 +552,21 @@ function delegateEvents(eventNames, document2 = window.document) {
552
552
  }
553
553
  }
554
554
  function setAttribute(node, name, value) {
555
- node.removeAttribute(name);
555
+ if (value == null) node.removeAttribute(name);
556
+ else node.setAttribute(name, value);
556
557
  }
557
558
  function className(node, value) {
558
559
  if (value == null) node.removeAttribute("class");
559
560
  else node.className = value;
560
561
  }
562
+ function addEventListener(node, name, handler, delegate) {
563
+ {
564
+ if (Array.isArray(handler)) {
565
+ node[`$$${name}`] = handler[0];
566
+ node[`$$${name}Data`] = handler[1];
567
+ } else node[`$$${name}`] = handler;
568
+ }
569
+ }
561
570
  function style(node, value, prev) {
562
571
  if (!value) return prev ? setAttribute(node, "style") : value;
563
572
  const nodeStyle = node.style;
@@ -742,7 +751,7 @@ function cleanChildren(parent, current, marker, replacement) {
742
751
  }
743
752
 
744
753
  // dist/styles.css
745
- 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}';
754
+ 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}}';
746
755
 
747
756
  // src/utils/is-keyboard-event-triggered-by-input.ts
748
757
  var FORM_TAGS_AND_ROLES = [
@@ -793,6 +802,39 @@ var isKeyboardEventTriggeredByInput = (event) => {
793
802
  return isHotkeyEnabledOnTagName(event, FORM_TAGS_AND_ROLES);
794
803
  };
795
804
 
805
+ // src/utils/is-selection-inside-editable-element.ts
806
+ var isEditableElement = (element) => {
807
+ const tagName = element.tagName.toLowerCase();
808
+ if (tagName === "input" || tagName === "textarea") {
809
+ return true;
810
+ }
811
+ if (element instanceof HTMLElement && element.isContentEditable) {
812
+ return true;
813
+ }
814
+ return false;
815
+ };
816
+ var isSelectionInsideEditableElement = (cursorX, cursorY) => {
817
+ const activeElement = document.activeElement;
818
+ if (activeElement) {
819
+ let current = activeElement;
820
+ while (current) {
821
+ if (isEditableElement(current)) {
822
+ return true;
823
+ }
824
+ current = current.parentElement;
825
+ }
826
+ }
827
+ if (cursorX !== void 0 && cursorY !== void 0) {
828
+ const elementsAtPoint = document.elementsFromPoint(cursorX, cursorY);
829
+ for (const element of elementsAtPoint) {
830
+ if (isEditableElement(element)) {
831
+ return true;
832
+ }
833
+ }
834
+ }
835
+ return false;
836
+ };
837
+
796
838
  // src/utils/mount-root.ts
797
839
  var ATTRIBUTE_NAME = "data-react-grab";
798
840
  var mountRoot = (cssText) => {
@@ -825,18 +867,27 @@ var mountRoot = (cssText) => {
825
867
  return root;
826
868
  };
827
869
 
870
+ // src/utils/build-open-file-url.ts
871
+ var BASE_URL = "https://react-grab.com" ;
872
+ var buildOpenFileUrl = (filePath, lineNumber) => {
873
+ const lineParam = lineNumber ? `&line=${lineNumber}` : "";
874
+ return `${BASE_URL}/open-file?url=${encodeURIComponent(filePath)}${lineParam}`;
875
+ };
876
+
828
877
  // src/constants.ts
829
878
  var VIEWPORT_MARGIN_PX = 8;
830
- var INDICATOR_CLAMP_PADDING_PX = 4;
831
- var CURSOR_OFFSET_PX = 14;
832
879
  var OFFSCREEN_POSITION = -1e3;
833
880
  var SELECTION_LERP_FACTOR = 0.95;
834
881
  var SUCCESS_LABEL_DURATION_MS = 1700;
835
- var PROGRESS_INDICATOR_DELAY_MS = 150;
882
+ var COPIED_LABEL_DURATION_MS = 1500;
883
+ var SELECTION_CURSOR_SETTLE_DELAY_MS = 500;
884
+ var BLUR_DEACTIVATION_THRESHOLD_MS = 500;
836
885
  var DRAG_THRESHOLD_PX = 2;
837
886
  var AUTO_SCROLL_EDGE_THRESHOLD_PX = 25;
838
887
  var AUTO_SCROLL_SPEED_PX = 10;
839
888
  var Z_INDEX_LABEL = 2147483647;
889
+ var MODIFIER_KEYS = ["Meta", "Control", "Shift", "Alt"];
890
+ 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>`;
840
891
 
841
892
  // src/utils/lerp.ts
842
893
  var lerp = (start, end, factor) => {
@@ -3324,7 +3375,7 @@ var cn = (...inputs) => {
3324
3375
  };
3325
3376
 
3326
3377
  // src/components/selection-box.tsx
3327
- var _tmpl$ = /* @__PURE__ */ template(`<div>`);
3378
+ var _tmpl$ = /* @__PURE__ */ template(`<div style=overflow:visible>`);
3328
3379
  var SelectionBox = (props) => {
3329
3380
  const [currentX, setCurrentX] = createSignal(props.bounds.x);
3330
3381
  const [currentY, setCurrentY] = createSignal(props.bounds.y);
@@ -3400,7 +3451,7 @@ var SelectionBox = (props) => {
3400
3451
  get children() {
3401
3452
  var _el$ = _tmpl$();
3402
3453
  createRenderEffect((_p$) => {
3403
- 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;
3454
+ 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;
3404
3455
  _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3405
3456
  _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3406
3457
  _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
@@ -3427,45 +3478,6 @@ var SelectionBox = (props) => {
3427
3478
  });
3428
3479
  };
3429
3480
 
3430
- // src/components/spinner.tsx
3431
- 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">`);
3432
- var Spinner = (props) => {
3433
- let spinnerRef;
3434
- onMount(() => {
3435
- if (spinnerRef) {
3436
- spinnerRef.animate([{
3437
- transform: "rotate(0deg)"
3438
- }, {
3439
- transform: "rotate(360deg)"
3440
- }], {
3441
- duration: 600,
3442
- easing: "linear",
3443
- iterations: Infinity
3444
- });
3445
- }
3446
- });
3447
- return (() => {
3448
- var _el$ = _tmpl$2();
3449
- var _ref$ = spinnerRef;
3450
- typeof _ref$ === "function" ? use(_ref$, _el$) : spinnerRef = _el$;
3451
- createRenderEffect((_$p) => style(_el$, props.style, _$p));
3452
- return _el$;
3453
- })();
3454
- };
3455
-
3456
- // src/utils/get-clamped-element-position.ts
3457
- var getClampedElementPosition = (positionLeft, positionTop, elementWidth, elementHeight) => {
3458
- const viewportWidth = window.innerWidth;
3459
- const viewportHeight = window.innerHeight;
3460
- const minLeft = VIEWPORT_MARGIN_PX;
3461
- const minTop = VIEWPORT_MARGIN_PX;
3462
- const maxLeft = viewportWidth - elementWidth - VIEWPORT_MARGIN_PX;
3463
- const maxTop = viewportHeight - elementHeight - VIEWPORT_MARGIN_PX;
3464
- const clampedLeft = Math.max(minLeft, Math.min(positionLeft, maxLeft));
3465
- const clampedTop = Math.max(minTop, Math.min(positionTop, maxTop));
3466
- return { left: clampedLeft, top: clampedTop };
3467
- };
3468
-
3469
3481
  // src/hooks/use-animated-lerp.ts
3470
3482
  var useAnimatedPosition = (options) => {
3471
3483
  const lerpFactor = options.lerpFactor ?? 0.3;
@@ -3512,187 +3524,8 @@ var useAnimatedPosition = (options) => {
3512
3524
  return { x: x3, y: y2 };
3513
3525
  };
3514
3526
 
3515
- // src/hooks/use-fade-in-out.ts
3516
- var useFadeInOut = (options) => {
3517
- const [opacity, setOpacity] = createSignal(0);
3518
- createEffect(
3519
- on(
3520
- () => options.visible,
3521
- (isVisible) => {
3522
- if (isVisible !== false) {
3523
- requestAnimationFrame(() => {
3524
- setOpacity(1);
3525
- });
3526
- } else {
3527
- setOpacity(0);
3528
- return;
3529
- }
3530
- if (options.autoFadeOutAfter !== void 0) {
3531
- const fadeOutTimer = setTimeout(() => {
3532
- setOpacity(0);
3533
- }, options.autoFadeOutAfter);
3534
- onCleanup(() => clearTimeout(fadeOutTimer));
3535
- }
3536
- }
3537
- )
3538
- );
3539
- return opacity;
3540
- };
3541
-
3542
- // src/utils/get-cursor-quadrants.ts
3543
- var getCursorQuadrants = (cursorX, cursorY, elementWidth, elementHeight, offset) => {
3544
- return [
3545
- {
3546
- left: Math.round(cursorX) + offset,
3547
- top: Math.round(cursorY) + offset
3548
- },
3549
- {
3550
- left: Math.round(cursorX) - elementWidth - offset,
3551
- top: Math.round(cursorY) + offset
3552
- },
3553
- {
3554
- left: Math.round(cursorX) + offset,
3555
- top: Math.round(cursorY) - elementHeight - offset
3556
- },
3557
- {
3558
- left: Math.round(cursorX) - elementWidth - offset,
3559
- top: Math.round(cursorY) - elementHeight - offset
3560
- }
3561
- ];
3562
- };
3563
-
3564
- // src/components/label.tsx
3565
- 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">`);
3566
- var _tmpl$22 = /* @__PURE__ */ template(`<span class="inline-block mr-1 font-semibold">\u2713`);
3567
- var _tmpl$32 = /* @__PURE__ */ template(`<div class=mr-1>Copied`);
3568
- var _tmpl$4 = /* @__PURE__ */ template(`<div class=ml-1>to clipboard`);
3569
- var _tmpl$5 = /* @__PURE__ */ template(`<div class="text-[9px] opacity-60 text-center mt-0.5">Click or drag to select`);
3570
- 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">`);
3571
- var Label = (props) => {
3572
- let labelRef;
3573
- const position = useAnimatedPosition({
3574
- x: () => props.x,
3575
- y: () => props.y,
3576
- lerpFactor: 0.3
3577
- });
3578
- const opacity = useFadeInOut({
3579
- visible: props.visible,
3580
- autoFadeOutAfter: props.variant === "success" ? SUCCESS_LABEL_DURATION_MS : void 0
3581
- });
3582
- const labelBoundingRect = () => labelRef?.getBoundingClientRect();
3583
- const computedPosition = () => {
3584
- const boundingRect = labelBoundingRect();
3585
- if (!boundingRect) return {
3586
- left: position.x(),
3587
- top: position.y()
3588
- };
3589
- const viewportWidth = window.innerWidth;
3590
- const viewportHeight = window.innerHeight;
3591
- const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
3592
- for (const position2 of quadrants) {
3593
- const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
3594
- const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
3595
- if (fitsHorizontally && fitsVertically) {
3596
- return position2;
3597
- }
3598
- }
3599
- const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
3600
- fallback.left += INDICATOR_CLAMP_PADDING_PX;
3601
- fallback.top += INDICATOR_CLAMP_PADDING_PX;
3602
- return fallback;
3603
- };
3604
- return createComponent(Show, {
3605
- get when() {
3606
- return props.visible !== false;
3607
- },
3608
- get children() {
3609
- var _el$ = _tmpl$6(), _el$3 = _el$.firstChild, _el$4 = _el$3.firstChild;
3610
- var _ref$ = labelRef;
3611
- typeof _ref$ === "function" ? use(_ref$, _el$) : labelRef = _el$;
3612
- insert(_el$, createComponent(Show, {
3613
- get when() {
3614
- return memo(() => props.variant === "processing")() && props.progress !== void 0;
3615
- },
3616
- get children() {
3617
- var _el$2 = _tmpl$3();
3618
- createRenderEffect((_$p) => setStyleProperty(_el$2, "width", `${Math.min(100, Math.max(0, (props.progress ?? 0) * 100))}%`));
3619
- return _el$2;
3620
- }
3621
- }), _el$3);
3622
- insert(_el$4, createComponent(Show, {
3623
- get when() {
3624
- return props.variant === "processing";
3625
- },
3626
- get children() {
3627
- return createComponent(Spinner, {});
3628
- }
3629
- }), null);
3630
- insert(_el$4, createComponent(Show, {
3631
- get when() {
3632
- return props.variant === "success";
3633
- },
3634
- get children() {
3635
- return _tmpl$22();
3636
- }
3637
- }), null);
3638
- insert(_el$4, createComponent(Show, {
3639
- get when() {
3640
- return props.variant === "success";
3641
- },
3642
- get children() {
3643
- return _tmpl$32();
3644
- }
3645
- }), null);
3646
- insert(_el$4, createComponent(Show, {
3647
- get when() {
3648
- return props.variant === "processing";
3649
- },
3650
- children: "Please wait\u2026"
3651
- }), null);
3652
- insert(_el$4, createComponent(Show, {
3653
- get when() {
3654
- return props.variant !== "processing";
3655
- },
3656
- get children() {
3657
- return props.content;
3658
- }
3659
- }), null);
3660
- insert(_el$4, createComponent(Show, {
3661
- get when() {
3662
- return props.variant === "success";
3663
- },
3664
- get children() {
3665
- return _tmpl$4();
3666
- }
3667
- }), null);
3668
- insert(_el$3, createComponent(Show, {
3669
- get when() {
3670
- return memo(() => props.variant === "hover")() && props.showHint;
3671
- },
3672
- get children() {
3673
- return _tmpl$5();
3674
- }
3675
- }), null);
3676
- createRenderEffect((_p$) => {
3677
- var _v$ = `${computedPosition().top}px`, _v$2 = `${computedPosition().left}px`, _v$3 = props.zIndex?.toString() ?? "2147483647", _v$4 = opacity();
3678
- _v$ !== _p$.e && setStyleProperty(_el$, "top", _p$.e = _v$);
3679
- _v$2 !== _p$.t && setStyleProperty(_el$, "left", _p$.t = _v$2);
3680
- _v$3 !== _p$.a && setStyleProperty(_el$, "z-index", _p$.a = _v$3);
3681
- _v$4 !== _p$.o && setStyleProperty(_el$, "opacity", _p$.o = _v$4);
3682
- return _p$;
3683
- }, {
3684
- e: void 0,
3685
- t: void 0,
3686
- a: void 0,
3687
- o: void 0
3688
- });
3689
- return _el$;
3690
- }
3691
- });
3692
- };
3693
-
3694
3527
  // src/components/crosshair.tsx
3695
- var _tmpl$7 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3528
+ var _tmpl$2 = /* @__PURE__ */ template(`<canvas class="fixed top-0 left-0 pointer-events-none z-[2147483645]">`);
3696
3529
  var Crosshair = (props) => {
3697
3530
  let canvasRef;
3698
3531
  let context = null;
@@ -3752,7 +3585,7 @@ var Crosshair = (props) => {
3752
3585
  return props.visible !== false;
3753
3586
  },
3754
3587
  get children() {
3755
- var _el$ = _tmpl$7();
3588
+ var _el$ = _tmpl$2();
3756
3589
  var _ref$ = canvasRef;
3757
3590
  typeof _ref$ === "function" ? use(_ref$, _el$) : canvasRef = _el$;
3758
3591
  return _el$;
@@ -3760,93 +3593,697 @@ var Crosshair = (props) => {
3760
3593
  });
3761
3594
  };
3762
3595
 
3763
- // src/components/input-overlay.tsx
3764
- 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`);
3765
- var InputOverlay = (props) => {
3596
+ // src/components/icon-checkmark.tsx
3597
+ 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>`);
3598
+ var IconCheckmark = (props) => {
3599
+ const size = () => props.size ?? 9;
3600
+ return (() => {
3601
+ var _el$ = _tmpl$3();
3602
+ createRenderEffect((_p$) => {
3603
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3604
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3605
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3606
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3607
+ return _p$;
3608
+ }, {
3609
+ e: void 0,
3610
+ t: void 0,
3611
+ a: void 0
3612
+ });
3613
+ return _el$;
3614
+ })();
3615
+ };
3616
+
3617
+ // src/components/icon-cursor-simple.tsx
3618
+ 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>`);
3619
+ var IconCursorSimple = (props) => {
3620
+ const size = () => props.size ?? 9;
3621
+ return (() => {
3622
+ var _el$ = _tmpl$4();
3623
+ createRenderEffect((_p$) => {
3624
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3625
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3626
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3627
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3628
+ return _p$;
3629
+ }, {
3630
+ e: void 0,
3631
+ t: void 0,
3632
+ a: void 0
3633
+ });
3634
+ return _el$;
3635
+ })();
3636
+ };
3637
+
3638
+ // src/components/icon-open.tsx
3639
+ 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">`);
3640
+ var IconOpen = (props) => {
3641
+ const size = () => props.size ?? 12;
3642
+ return (() => {
3643
+ var _el$ = _tmpl$5();
3644
+ createRenderEffect((_p$) => {
3645
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3646
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3647
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3648
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3649
+ return _p$;
3650
+ }, {
3651
+ e: void 0,
3652
+ t: void 0,
3653
+ a: void 0
3654
+ });
3655
+ return _el$;
3656
+ })();
3657
+ };
3658
+
3659
+ // src/components/icon-return-key.tsx
3660
+ 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">`);
3661
+ var IconReturnKey = (props) => {
3662
+ const size = () => props.size ?? 14;
3663
+ return (() => {
3664
+ var _el$ = _tmpl$6();
3665
+ createRenderEffect((_p$) => {
3666
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3667
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3668
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3669
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3670
+ return _p$;
3671
+ }, {
3672
+ e: void 0,
3673
+ t: void 0,
3674
+ a: void 0
3675
+ });
3676
+ return _el$;
3677
+ })();
3678
+ };
3679
+
3680
+ // src/components/icon-stop.tsx
3681
+ 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>`);
3682
+ var IconStop = (props) => {
3683
+ const size = () => props.size ?? 9;
3684
+ return (() => {
3685
+ var _el$ = _tmpl$7();
3686
+ createRenderEffect((_p$) => {
3687
+ var _v$ = size(), _v$2 = size(), _v$3 = props.class;
3688
+ _v$ !== _p$.e && setAttribute(_el$, "width", _p$.e = _v$);
3689
+ _v$2 !== _p$.t && setAttribute(_el$, "height", _p$.t = _v$2);
3690
+ _v$3 !== _p$.a && setAttribute(_el$, "class", _p$.a = _v$3);
3691
+ return _p$;
3692
+ }, {
3693
+ e: void 0,
3694
+ t: void 0,
3695
+ a: void 0
3696
+ });
3697
+ return _el$;
3698
+ })();
3699
+ };
3700
+
3701
+ // src/components/selection-label.tsx
3702
+ 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>`);
3703
+ var _tmpl$22 = /* @__PURE__ */ template(`<span>`);
3704
+ var _tmpl$32 = /* @__PURE__ */ template(`<button>`);
3705
+ var _tmpl$42 = /* @__PURE__ */ template(`<div>`);
3706
+ 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]">`);
3707
+ 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">`);
3708
+ 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">`);
3709
+ var _tmpl$82 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px]">`);
3710
+ 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>`);
3711
+ var _tmpl$0 = /* @__PURE__ */ template(`<div class="flex items-center gap-[3px] react-grab-shimmer rounded-[3px]">`);
3712
+ 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`);
3713
+ 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">`);
3714
+ 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]">`);
3715
+ 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">`);
3716
+ var ARROW_HEIGHT = 8;
3717
+ var LABEL_GAP = 4;
3718
+ var IDLE_TIMEOUT_MS = 150;
3719
+ var TagBadge = (props) => {
3720
+ const [isHovered, setIsHovered] = createSignal(false);
3721
+ const handleMouseEnter = () => {
3722
+ setIsHovered(true);
3723
+ props.onHoverChange?.(true);
3724
+ };
3725
+ const handleMouseLeave = () => {
3726
+ setIsHovered(false);
3727
+ props.onHoverChange?.(false);
3728
+ };
3729
+ return (() => {
3730
+ var _el$ = _tmpl$8(), _el$2 = _el$.firstChild;
3731
+ addEventListener(_el$, "click", props.onClick);
3732
+ _el$.addEventListener("mouseleave", handleMouseLeave);
3733
+ _el$.addEventListener("mouseenter", handleMouseEnter);
3734
+ insert(_el$2, () => props.tagName);
3735
+ insert(_el$, createComponent(Show, {
3736
+ get when() {
3737
+ return props.isClickable;
3738
+ },
3739
+ get children() {
3740
+ return createComponent(IconOpen, {
3741
+ size: 10,
3742
+ get ["class"]() {
3743
+ return cn("text-label-tag-border transition-all duration-100", isHovered() ? "opacity-100 scale-100" : "opacity-0 scale-75 -ml-[5px] w-0");
3744
+ }
3745
+ });
3746
+ }
3747
+ }), null);
3748
+ createRenderEffect((_p$) => {
3749
+ 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");
3750
+ _v$ !== _p$.e && className(_el$, _p$.e = _v$);
3751
+ _v$2 !== _p$.t && className(_el$2, _p$.t = _v$2);
3752
+ return _p$;
3753
+ }, {
3754
+ e: void 0,
3755
+ t: void 0
3756
+ });
3757
+ return _el$;
3758
+ })();
3759
+ };
3760
+ var ActionPill = (props) => {
3761
+ 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");
3762
+ const content = [memo(() => props.icon), (() => {
3763
+ var _el$3 = _tmpl$22();
3764
+ insert(_el$3, () => props.label);
3765
+ createRenderEffect(() => className(_el$3, cn("text-black text-[12px] leading-4 font-medium tracking-[-0.04em]", props.shrink && "shrink-0 w-fit h-fit")));
3766
+ return _el$3;
3767
+ })()];
3768
+ return props.asButton ? (() => {
3769
+ var _el$4 = _tmpl$32();
3770
+ addEventListener(_el$4, "click", props.onClick);
3771
+ className(_el$4, baseClass);
3772
+ insert(_el$4, content);
3773
+ return _el$4;
3774
+ })() : (() => {
3775
+ var _el$5 = _tmpl$42();
3776
+ addEventListener(_el$5, "click", props.onClick);
3777
+ className(_el$5, baseClass);
3778
+ insert(_el$5, content);
3779
+ createRenderEffect(() => setAttribute(_el$5, "role", props.onClick ? "button" : void 0));
3780
+ return _el$5;
3781
+ })();
3782
+ };
3783
+ var SuccessPill = (props) => (() => {
3784
+ var _el$6 = _tmpl$52(), _el$7 = _el$6.firstChild;
3785
+ insert(_el$6, createComponent(IconCheckmark, {
3786
+ size: 9,
3787
+ "class": "text-label-success-text shrink-0"
3788
+ }), _el$7);
3789
+ insert(_el$7, () => props.hasAgent ? "Completed" : "Copied");
3790
+ return _el$6;
3791
+ })();
3792
+ var Arrow = (props) => (() => {
3793
+ var _el$8 = _tmpl$62();
3794
+ createRenderEffect((_$p) => style(_el$8, {
3795
+ left: `${props.leftPx}px`,
3796
+ ...props.position === "bottom" ? {
3797
+ top: "0",
3798
+ transform: "translateX(-50%) translateY(-100%)"
3799
+ } : {
3800
+ bottom: "0",
3801
+ transform: "translateX(-50%) translateY(100%)"
3802
+ },
3803
+ ...props.position === "bottom" ? {
3804
+ "border-bottom": "8px solid white"
3805
+ } : {
3806
+ "border-top": "8px solid white"
3807
+ }
3808
+ }, _$p));
3809
+ return _el$8;
3810
+ })();
3811
+ var ClickToCopyPill = (props) => createComponent(ActionPill, {
3812
+ get icon() {
3813
+ return createComponent(IconCursorSimple, {
3814
+ size: 9,
3815
+ "class": "text-black shrink-0"
3816
+ });
3817
+ },
3818
+ label: "Click to copy",
3819
+ get onClick() {
3820
+ return props.onClick;
3821
+ },
3822
+ get asButton() {
3823
+ return props.asButton;
3824
+ },
3825
+ get dimmed() {
3826
+ return props.dimmed;
3827
+ },
3828
+ get shrink() {
3829
+ return props.shrink;
3830
+ }
3831
+ });
3832
+ var BottomSection = (props) => (() => {
3833
+ var _el$9 = _tmpl$72();
3834
+ insert(_el$9, () => props.children);
3835
+ return _el$9;
3836
+ })();
3837
+ var SelectionLabel = (props) => {
3766
3838
  let containerRef;
3767
3839
  let inputRef;
3768
- const position = useAnimatedPosition({
3769
- x: () => props.x,
3770
- y: () => props.y,
3771
- lerpFactor: 0.3
3840
+ let isTagCurrentlyHovered = false;
3841
+ const [measuredWidth, setMeasuredWidth] = createSignal(0);
3842
+ const [measuredHeight, setMeasuredHeight] = createSignal(0);
3843
+ const [arrowPosition, setArrowPosition] = createSignal("bottom");
3844
+ const [viewportVersion, setViewportVersion] = createSignal(0);
3845
+ const [isIdle, setIsIdle] = createSignal(false);
3846
+ const isNotProcessing = () => props.status !== "copying" && props.status !== "copied" && props.status !== "fading";
3847
+ const measureContainer = () => {
3848
+ if (containerRef && !isTagCurrentlyHovered) {
3849
+ const rect = containerRef.getBoundingClientRect();
3850
+ setMeasuredWidth(rect.width);
3851
+ setMeasuredHeight(rect.height);
3852
+ }
3853
+ };
3854
+ const handleTagHoverChange = (hovered) => {
3855
+ isTagCurrentlyHovered = hovered;
3856
+ };
3857
+ const handleViewportChange = () => {
3858
+ setViewportVersion((version) => version + 1);
3859
+ };
3860
+ let idleTimeout;
3861
+ const resetIdleTimer = () => {
3862
+ setIsIdle(false);
3863
+ if (idleTimeout) {
3864
+ clearTimeout(idleTimeout);
3865
+ }
3866
+ idleTimeout = setTimeout(() => {
3867
+ setIsIdle(true);
3868
+ }, IDLE_TIMEOUT_MS);
3869
+ };
3870
+ const handleGlobalKeyDown = (event) => {
3871
+ if (event.code === "Enter" && isIdle() && !props.isInputExpanded && isNotProcessing()) {
3872
+ event.preventDefault();
3873
+ event.stopPropagation();
3874
+ props.onToggleExpand?.();
3875
+ }
3876
+ };
3877
+ onMount(() => {
3878
+ measureContainer();
3879
+ window.addEventListener("scroll", handleViewportChange, true);
3880
+ window.addEventListener("resize", handleViewportChange);
3881
+ window.addEventListener("mousemove", resetIdleTimer);
3882
+ window.addEventListener("keydown", handleGlobalKeyDown, {
3883
+ capture: true
3884
+ });
3885
+ resetIdleTimer();
3886
+ });
3887
+ onCleanup(() => {
3888
+ window.removeEventListener("scroll", handleViewportChange, true);
3889
+ window.removeEventListener("resize", handleViewportChange);
3890
+ window.removeEventListener("mousemove", resetIdleTimer);
3891
+ window.removeEventListener("keydown", handleGlobalKeyDown, {
3892
+ capture: true
3893
+ });
3894
+ if (idleTimeout) {
3895
+ clearTimeout(idleTimeout);
3896
+ }
3897
+ });
3898
+ createEffect(() => {
3899
+ if (props.visible) {
3900
+ requestAnimationFrame(measureContainer);
3901
+ }
3902
+ });
3903
+ createEffect(() => {
3904
+ void [props.status, props.isInputExpanded, props.inputValue, isIdle()];
3905
+ requestAnimationFrame(measureContainer);
3906
+ });
3907
+ createEffect(() => {
3908
+ if (props.isInputExpanded && inputRef) {
3909
+ setTimeout(() => {
3910
+ inputRef?.focus();
3911
+ }, 0);
3912
+ }
3772
3913
  });
3773
- const containerBoundingRect = () => containerRef?.getBoundingClientRect();
3774
3914
  const computedPosition = () => {
3775
- const boundingRect = containerBoundingRect();
3776
- if (!boundingRect) return {
3777
- left: position.x(),
3778
- top: position.y()
3779
- };
3915
+ viewportVersion();
3916
+ const bounds = props.selectionBounds;
3917
+ const labelWidth = measuredWidth();
3918
+ const labelHeight = measuredHeight();
3919
+ if (!bounds || labelWidth === 0 || labelHeight === 0) {
3920
+ return {
3921
+ left: -9999,
3922
+ top: -9999,
3923
+ arrowLeft: 0
3924
+ };
3925
+ }
3780
3926
  const viewportWidth = window.innerWidth;
3781
3927
  const viewportHeight = window.innerHeight;
3782
- const quadrants = getCursorQuadrants(position.x(), position.y(), boundingRect.width, boundingRect.height, CURSOR_OFFSET_PX);
3783
- for (const position2 of quadrants) {
3784
- const fitsHorizontally = position2.left >= VIEWPORT_MARGIN_PX && position2.left + boundingRect.width <= viewportWidth - VIEWPORT_MARGIN_PX;
3785
- const fitsVertically = position2.top >= VIEWPORT_MARGIN_PX && position2.top + boundingRect.height <= viewportHeight - VIEWPORT_MARGIN_PX;
3786
- if (fitsHorizontally && fitsVertically) {
3787
- return position2;
3788
- }
3928
+ const selectionCenterX = bounds.x + bounds.width / 2;
3929
+ const selectionBottom = bounds.y + bounds.height;
3930
+ const selectionTop = bounds.y;
3931
+ let positionLeft = selectionCenterX - labelWidth / 2;
3932
+ let positionTop = selectionBottom + ARROW_HEIGHT + LABEL_GAP;
3933
+ if (positionLeft + labelWidth > viewportWidth - VIEWPORT_MARGIN_PX) {
3934
+ positionLeft = viewportWidth - labelWidth - VIEWPORT_MARGIN_PX;
3935
+ }
3936
+ if (positionLeft < VIEWPORT_MARGIN_PX) {
3937
+ positionLeft = VIEWPORT_MARGIN_PX;
3789
3938
  }
3790
- const fallback = getClampedElementPosition(quadrants[0].left, quadrants[0].top, boundingRect.width, boundingRect.height);
3791
- fallback.left += INDICATOR_CLAMP_PADDING_PX;
3792
- fallback.top += INDICATOR_CLAMP_PADDING_PX;
3793
- return fallback;
3939
+ const totalHeightNeeded = labelHeight + ARROW_HEIGHT + LABEL_GAP;
3940
+ const fitsBelow = positionTop + labelHeight <= viewportHeight - VIEWPORT_MARGIN_PX;
3941
+ if (!fitsBelow) {
3942
+ positionTop = selectionTop - totalHeightNeeded;
3943
+ setArrowPosition("top");
3944
+ } else {
3945
+ setArrowPosition("bottom");
3946
+ }
3947
+ if (positionTop < VIEWPORT_MARGIN_PX) {
3948
+ positionTop = VIEWPORT_MARGIN_PX;
3949
+ }
3950
+ const arrowLeft = Math.max(12, Math.min(selectionCenterX - positionLeft, labelWidth - 12));
3951
+ return {
3952
+ left: positionLeft,
3953
+ top: positionTop,
3954
+ arrowLeft
3955
+ };
3794
3956
  };
3795
3957
  const handleKeyDown = (event) => {
3958
+ event.stopPropagation();
3796
3959
  if (event.code === "Enter" && !event.shiftKey) {
3797
3960
  event.preventDefault();
3798
- event.stopPropagation();
3799
- props.onSubmit();
3961
+ props.onSubmit?.();
3800
3962
  } else if (event.code === "Escape") {
3801
3963
  event.preventDefault();
3802
- event.stopPropagation();
3803
- props.onCancel();
3964
+ props.onCancel?.();
3804
3965
  }
3805
3966
  };
3806
3967
  const handleInput = (event) => {
3807
3968
  const target = event.target;
3808
- props.onInput(target.value);
3809
- target.style.height = "auto";
3810
- target.style.height = `${target.scrollHeight}px`;
3969
+ props.onInputChange?.(target.value);
3811
3970
  };
3812
- createEffect(() => {
3813
- if (props.visible && inputRef) {
3814
- inputRef.focus();
3815
- inputRef.style.height = "auto";
3816
- } else if (!props.visible && inputRef) {
3817
- inputRef.blur();
3971
+ const tagDisplay = () => props.tagName || "element";
3972
+ const handleTagClick = (event) => {
3973
+ event.stopPropagation();
3974
+ event.stopImmediatePropagation();
3975
+ if (props.filePath && props.onOpen) {
3976
+ props.onOpen();
3818
3977
  }
3819
- });
3820
- return (() => {
3821
- var _el$ = _tmpl$8(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild;
3822
- var _ref$ = containerRef;
3823
- typeof _ref$ === "function" ? use(_ref$, _el$) : containerRef = _el$;
3824
- _el$3.$$keydown = handleKeyDown;
3825
- _el$3.$$input = handleInput;
3826
- var _ref$2 = inputRef;
3827
- typeof _ref$2 === "function" ? use(_ref$2, _el$3) : inputRef = _el$3;
3828
- createRenderEffect((_p$) => {
3829
- 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";
3830
- _v$ !== _p$.e && setStyleProperty(_el$, "display", _p$.e = _v$);
3831
- _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
3832
- _v$3 !== _p$.a && setStyleProperty(_el$, "left", _p$.a = _v$3);
3833
- _v$4 !== _p$.o && setStyleProperty(_el$, "z-index", _p$.o = _v$4);
3834
- _v$5 !== _p$.i && setStyleProperty(_el$, "pointer-events", _p$.i = _v$5);
3835
- return _p$;
3836
- }, {
3837
- e: void 0,
3838
- t: void 0,
3839
- a: void 0,
3840
- o: void 0,
3841
- i: void 0
3842
- });
3843
- createRenderEffect(() => _el$3.value = props.value);
3844
- return _el$;
3845
- })();
3846
- };
3847
- delegateEvents(["input", "keydown"]);
3848
-
3978
+ };
3979
+ const isTagClickable = () => Boolean(props.filePath && props.onOpen);
3980
+ const stopPropagation = (event) => {
3981
+ event.stopPropagation();
3982
+ event.stopImmediatePropagation();
3983
+ };
3984
+ const handleSubmit = () => props.onSubmit?.();
3985
+ return createComponent(Show, {
3986
+ get when() {
3987
+ return memo(() => props.visible !== false)() && props.selectionBounds;
3988
+ },
3989
+ get children() {
3990
+ var _el$0 = _tmpl$12(), _el$1 = _el$0.firstChild;
3991
+ _el$0.$$click = stopPropagation;
3992
+ _el$0.$$mousedown = stopPropagation;
3993
+ var _ref$ = containerRef;
3994
+ typeof _ref$ === "function" ? use(_ref$, _el$0) : containerRef = _el$0;
3995
+ insert(_el$0, createComponent(Arrow, {
3996
+ get position() {
3997
+ return arrowPosition();
3998
+ },
3999
+ get leftPx() {
4000
+ return computedPosition().arrowLeft;
4001
+ }
4002
+ }), _el$1);
4003
+ insert(_el$1, createComponent(Show, {
4004
+ get when() {
4005
+ return props.status === "copied" || props.status === "fading";
4006
+ },
4007
+ get children() {
4008
+ var _el$10 = _tmpl$82();
4009
+ insert(_el$10, createComponent(TagBadge, {
4010
+ get tagName() {
4011
+ return tagDisplay();
4012
+ },
4013
+ get isClickable() {
4014
+ return isTagClickable();
4015
+ },
4016
+ onClick: handleTagClick,
4017
+ onHoverChange: handleTagHoverChange
4018
+ }), null);
4019
+ insert(_el$10, createComponent(SuccessPill, {
4020
+ get hasAgent() {
4021
+ return props.hasAgent;
4022
+ }
4023
+ }), null);
4024
+ return _el$10;
4025
+ }
4026
+ }), null);
4027
+ insert(_el$1, createComponent(Show, {
4028
+ get when() {
4029
+ return props.status === "copying";
4030
+ },
4031
+ get children() {
4032
+ var _el$11 = _tmpl$0();
4033
+ insert(_el$11, createComponent(TagBadge, {
4034
+ get tagName() {
4035
+ return tagDisplay();
4036
+ },
4037
+ get isClickable() {
4038
+ return isTagClickable();
4039
+ },
4040
+ onClick: handleTagClick,
4041
+ onHoverChange: handleTagHoverChange,
4042
+ showMono: true
4043
+ }), null);
4044
+ insert(_el$11, createComponent(ActionPill, {
4045
+ get icon() {
4046
+ return createComponent(IconCursorSimple, {
4047
+ size: 9,
4048
+ "class": "text-black shrink-0"
4049
+ });
4050
+ },
4051
+ get label() {
4052
+ return props.statusText ?? "Grabbing\u2026";
4053
+ }
4054
+ }), null);
4055
+ insert(_el$11, createComponent(Show, {
4056
+ get when() {
4057
+ return memo(() => !!props.hasAgent)() && props.onAbort;
4058
+ },
4059
+ get children() {
4060
+ var _el$12 = _tmpl$9();
4061
+ _el$12.$$click = (event) => {
4062
+ event.preventDefault();
4063
+ event.stopPropagation();
4064
+ event.stopImmediatePropagation();
4065
+ props.onAbort?.();
4066
+ };
4067
+ _el$12.$$mousedown = (event) => {
4068
+ event.preventDefault();
4069
+ event.stopPropagation();
4070
+ event.stopImmediatePropagation();
4071
+ };
4072
+ insert(_el$12, createComponent(IconStop, {
4073
+ size: 8,
4074
+ "class": "text-white"
4075
+ }));
4076
+ return _el$12;
4077
+ }
4078
+ }), null);
4079
+ return _el$11;
4080
+ }
4081
+ }), null);
4082
+ insert(_el$1, createComponent(Show, {
4083
+ get when() {
4084
+ return memo(() => !!(isNotProcessing() && !isIdle()))() && !props.isInputExpanded;
4085
+ },
4086
+ get children() {
4087
+ var _el$13 = _tmpl$82();
4088
+ insert(_el$13, createComponent(TagBadge, {
4089
+ get tagName() {
4090
+ return tagDisplay();
4091
+ },
4092
+ get isClickable() {
4093
+ return isTagClickable();
4094
+ },
4095
+ onClick: handleTagClick,
4096
+ onHoverChange: handleTagHoverChange,
4097
+ showMono: true
4098
+ }), null);
4099
+ insert(_el$13, createComponent(ClickToCopyPill, {
4100
+ onClick: handleSubmit,
4101
+ asButton: true
4102
+ }), null);
4103
+ return _el$13;
4104
+ }
4105
+ }), null);
4106
+ insert(_el$1, createComponent(Show, {
4107
+ get when() {
4108
+ return memo(() => !!(isNotProcessing() && isIdle()))() && !props.isInputExpanded;
4109
+ },
4110
+ get children() {
4111
+ var _el$14 = _tmpl$10(), _el$15 = _el$14.firstChild;
4112
+ insert(_el$15, createComponent(TagBadge, {
4113
+ get tagName() {
4114
+ return tagDisplay();
4115
+ },
4116
+ get isClickable() {
4117
+ return isTagClickable();
4118
+ },
4119
+ onClick: handleTagClick,
4120
+ onHoverChange: handleTagHoverChange,
4121
+ showMono: true,
4122
+ shrink: true
4123
+ }), null);
4124
+ insert(_el$15, createComponent(ClickToCopyPill, {
4125
+ onClick: handleSubmit,
4126
+ shrink: true
4127
+ }), null);
4128
+ insert(_el$14, createComponent(BottomSection, {
4129
+ get children() {
4130
+ var _el$16 = _tmpl$1(), _el$17 = _el$16.firstChild;
4131
+ insert(_el$16, createComponent(IconReturnKey, {
4132
+ size: 10,
4133
+ "class": "shrink-0 text-black opacity-[0.65]"
4134
+ }), _el$17);
4135
+ return _el$16;
4136
+ }
4137
+ }), null);
4138
+ return _el$14;
4139
+ }
4140
+ }), null);
4141
+ insert(_el$1, createComponent(Show, {
4142
+ get when() {
4143
+ return memo(() => !!isNotProcessing())() && props.isInputExpanded;
4144
+ },
4145
+ get children() {
4146
+ var _el$18 = _tmpl$10(), _el$19 = _el$18.firstChild;
4147
+ insert(_el$19, createComponent(TagBadge, {
4148
+ get tagName() {
4149
+ return tagDisplay();
4150
+ },
4151
+ get isClickable() {
4152
+ return isTagClickable();
4153
+ },
4154
+ onClick: handleTagClick,
4155
+ onHoverChange: handleTagHoverChange,
4156
+ showMono: true,
4157
+ shrink: true
4158
+ }), null);
4159
+ insert(_el$19, createComponent(ClickToCopyPill, {
4160
+ onClick: handleSubmit,
4161
+ dimmed: true,
4162
+ shrink: true
4163
+ }), null);
4164
+ insert(_el$18, createComponent(BottomSection, {
4165
+ get children() {
4166
+ var _el$20 = _tmpl$11(), _el$21 = _el$20.firstChild, _el$22 = _el$21.nextSibling;
4167
+ _el$21.$$keydown = handleKeyDown;
4168
+ _el$21.$$input = handleInput;
4169
+ var _ref$2 = inputRef;
4170
+ typeof _ref$2 === "function" ? use(_ref$2, _el$21) : inputRef = _el$21;
4171
+ _el$22.$$click = handleSubmit;
4172
+ insert(_el$22, createComponent(IconReturnKey, {
4173
+ size: 10,
4174
+ "class": "shrink-0 text-black"
4175
+ }));
4176
+ createRenderEffect(() => _el$21.value = props.inputValue ?? "");
4177
+ return _el$20;
4178
+ }
4179
+ }), null);
4180
+ return _el$18;
4181
+ }
4182
+ }), null);
4183
+ createRenderEffect((_p$) => {
4184
+ 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";
4185
+ _v$3 !== _p$.e && setStyleProperty(_el$0, "top", _p$.e = _v$3);
4186
+ _v$4 !== _p$.t && setStyleProperty(_el$0, "left", _p$.t = _v$4);
4187
+ _v$5 !== _p$.a && setStyleProperty(_el$0, "pointer-events", _p$.a = _v$5);
4188
+ _v$6 !== _p$.o && setStyleProperty(_el$0, "opacity", _p$.o = _v$6);
4189
+ _v$7 !== _p$.i && setStyleProperty(_el$1, "padding", _p$.i = _v$7);
4190
+ return _p$;
4191
+ }, {
4192
+ e: void 0,
4193
+ t: void 0,
4194
+ a: void 0,
4195
+ o: void 0,
4196
+ i: void 0
4197
+ });
4198
+ return _el$0;
4199
+ }
4200
+ });
4201
+ };
4202
+ delegateEvents(["click", "mousedown", "input", "keydown"]);
4203
+
4204
+ // src/components/selection-cursor.tsx
4205
+ var _tmpl$13 = /* @__PURE__ */ template(`<div class="fixed z-2147483647"><button data-react-grab-selection-cursor>`);
4206
+ var SelectionCursor = (props) => {
4207
+ const [isHovered, setIsHovered] = createSignal(false);
4208
+ const [debouncedVisible, setDebouncedVisible] = createSignal(false);
4209
+ createEffect(() => {
4210
+ const isVisible = props.visible !== false;
4211
+ void [props.x, props.y];
4212
+ setDebouncedVisible(false);
4213
+ if (isVisible) {
4214
+ const timeout = setTimeout(() => setDebouncedVisible(true), SELECTION_CURSOR_SETTLE_DELAY_MS);
4215
+ onCleanup(() => clearTimeout(timeout));
4216
+ }
4217
+ });
4218
+ const handleClick = (event) => {
4219
+ event.preventDefault();
4220
+ event.stopPropagation();
4221
+ props.onClick?.();
4222
+ };
4223
+ return createComponent(Show, {
4224
+ get when() {
4225
+ return debouncedVisible();
4226
+ },
4227
+ get children() {
4228
+ return [createComponent(Show, {
4229
+ get when() {
4230
+ return memo(() => !!isHovered())() && props.elementBounds;
4231
+ },
4232
+ get children() {
4233
+ return createComponent(SelectionBox, {
4234
+ variant: "selection",
4235
+ get bounds() {
4236
+ return props.elementBounds;
4237
+ },
4238
+ visible: true
4239
+ });
4240
+ }
4241
+ }), (() => {
4242
+ var _el$ = _tmpl$13(), _el$2 = _el$.firstChild;
4243
+ _el$.addEventListener("mouseleave", () => setIsHovered(false));
4244
+ _el$.addEventListener("mouseenter", () => setIsHovered(true));
4245
+ _el$2.$$click = handleClick;
4246
+ createRenderEffect((_p$) => {
4247
+ 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");
4248
+ _v$ !== _p$.e && setStyleProperty(_el$, "left", _p$.e = _v$);
4249
+ _v$2 !== _p$.t && setStyleProperty(_el$, "top", _p$.t = _v$2);
4250
+ _v$3 !== _p$.a && className(_el$2, _p$.a = _v$3);
4251
+ return _p$;
4252
+ }, {
4253
+ e: void 0,
4254
+ t: void 0,
4255
+ a: void 0
4256
+ });
4257
+ return _el$;
4258
+ })(), createComponent(Show, {
4259
+ get when() {
4260
+ return memo(() => !!isHovered())() && props.elementBounds;
4261
+ },
4262
+ get children() {
4263
+ return createComponent(SelectionLabel, {
4264
+ get tagName() {
4265
+ return props.tagName;
4266
+ },
4267
+ get selectionBounds() {
4268
+ return props.elementBounds;
4269
+ },
4270
+ visible: true,
4271
+ get onSubmit() {
4272
+ return props.onClick;
4273
+ }
4274
+ });
4275
+ }
4276
+ })];
4277
+ }
4278
+ });
4279
+ };
4280
+ delegateEvents(["click"]);
4281
+
3849
4282
  // src/components/renderer.tsx
4283
+ var truncateStatus = (status, maxLength = 30) => {
4284
+ if (status.length <= maxLength) return status;
4285
+ return `${status.slice(0, maxLength)}\u2026`;
4286
+ };
3850
4287
  var ReactGrabRenderer = (props) => {
3851
4288
  return [createComponent(Show, {
3852
4289
  get when() {
@@ -3860,6 +4297,9 @@ var ReactGrabRenderer = (props) => {
3860
4297
  },
3861
4298
  get visible() {
3862
4299
  return props.selectionVisible;
4300
+ },
4301
+ get isFading() {
4302
+ return props.selectionLabelStatus === "fading";
3863
4303
  }
3864
4304
  });
3865
4305
  }
@@ -3906,86 +4346,141 @@ var ReactGrabRenderer = (props) => {
3906
4346
  return box.createdAt;
3907
4347
  }
3908
4348
  })
4349
+ }), createComponent(For, {
4350
+ get each() {
4351
+ return memo(() => !!props.agentSessions)() ? Array.from(props.agentSessions.values()) : [];
4352
+ },
4353
+ children: (session) => [createComponent(Show, {
4354
+ get when() {
4355
+ return session.selectionBounds;
4356
+ },
4357
+ get children() {
4358
+ return createComponent(SelectionBox, {
4359
+ variant: "processing",
4360
+ get bounds() {
4361
+ return session.selectionBounds;
4362
+ },
4363
+ visible: true
4364
+ });
4365
+ }
4366
+ }), createComponent(SelectionLabel, {
4367
+ get tagName() {
4368
+ return session.tagName;
4369
+ },
4370
+ get selectionBounds() {
4371
+ return session.selectionBounds;
4372
+ },
4373
+ visible: true,
4374
+ hasAgent: true,
4375
+ get status() {
4376
+ return session.isStreaming ? "copying" : "copied";
4377
+ },
4378
+ get statusText() {
4379
+ return truncateStatus(session.lastStatus || "Please wait\u2026");
4380
+ },
4381
+ onAbort: () => props.onAbortSession?.(session.id)
4382
+ })]
3909
4383
  }), createComponent(Show, {
3910
4384
  get when() {
3911
- return props.labelVariant !== "processing";
4385
+ return memo(() => !!props.selectionLabelVisible)() && props.selectionBounds;
3912
4386
  },
3913
4387
  get children() {
3914
- return createComponent(For, {
3915
- get each() {
3916
- return props.successLabels ?? [];
4388
+ return createComponent(SelectionLabel, {
4389
+ get tagName() {
4390
+ return props.selectionTagName;
3917
4391
  },
3918
- children: (label) => createComponent(Label, {
3919
- variant: "success",
3920
- get content() {
3921
- return memo(() => label.text);
3922
- },
3923
- get x() {
3924
- return props.mouseX ?? 0;
3925
- },
3926
- get y() {
3927
- return props.mouseY ?? 0;
4392
+ get selectionBounds() {
4393
+ return props.selectionBounds;
4394
+ },
4395
+ get visible() {
4396
+ return props.selectionLabelVisible;
4397
+ },
4398
+ get isInputExpanded() {
4399
+ return props.isInputExpanded;
4400
+ },
4401
+ get inputValue() {
4402
+ return props.inputValue;
4403
+ },
4404
+ get hasAgent() {
4405
+ return props.hasAgent;
4406
+ },
4407
+ get status() {
4408
+ return props.selectionLabelStatus;
4409
+ },
4410
+ get filePath() {
4411
+ return props.selectionFilePath;
4412
+ },
4413
+ get lineNumber() {
4414
+ return props.selectionLineNumber;
4415
+ },
4416
+ get onInputChange() {
4417
+ return props.onInputChange;
4418
+ },
4419
+ get onSubmit() {
4420
+ return props.onInputSubmit;
4421
+ },
4422
+ get onCancel() {
4423
+ return props.onInputCancel;
4424
+ },
4425
+ get onToggleExpand() {
4426
+ return props.onToggleExpand;
4427
+ },
4428
+ onOpen: () => {
4429
+ if (props.selectionFilePath) {
4430
+ const openFileUrl = buildOpenFileUrl(props.selectionFilePath, props.selectionLineNumber);
4431
+ window.open(openFileUrl, "_blank");
3928
4432
  }
3929
- })
4433
+ }
3930
4434
  });
3931
4435
  }
4436
+ }), createComponent(For, {
4437
+ get each() {
4438
+ return props.labelInstances ?? [];
4439
+ },
4440
+ children: (instance) => createComponent(SelectionLabel, {
4441
+ get tagName() {
4442
+ return instance.tagName;
4443
+ },
4444
+ get selectionBounds() {
4445
+ return instance.bounds;
4446
+ },
4447
+ visible: true,
4448
+ get status() {
4449
+ return instance.status;
4450
+ }
4451
+ })
3932
4452
  }), createComponent(Show, {
3933
4453
  get when() {
3934
- return memo(() => !!(props.labelVisible && props.labelVariant && props.labelContent !== void 0 && props.labelX !== void 0))() && props.labelY !== void 0;
4454
+ return memo(() => !!(props.nativeSelectionCursorVisible && props.nativeSelectionCursorX !== void 0))() && props.nativeSelectionCursorY !== void 0;
3935
4455
  },
3936
4456
  get children() {
3937
- return createComponent(Label, {
3938
- get variant() {
3939
- return props.labelVariant;
3940
- },
3941
- get content() {
3942
- return props.labelContent;
3943
- },
4457
+ return createComponent(SelectionCursor, {
3944
4458
  get x() {
3945
- return props.labelX;
4459
+ return props.nativeSelectionCursorX;
3946
4460
  },
3947
4461
  get y() {
3948
- return props.labelY;
4462
+ return props.nativeSelectionCursorY;
3949
4463
  },
3950
- get visible() {
3951
- return props.labelVisible;
4464
+ get tagName() {
4465
+ return props.nativeSelectionTagName;
4466
+ },
4467
+ get componentName() {
4468
+ return props.nativeSelectionComponentName;
3952
4469
  },
3953
- get zIndex() {
3954
- return props.labelZIndex;
4470
+ get elementBounds() {
4471
+ return props.nativeSelectionBounds;
3955
4472
  },
3956
- get progress() {
3957
- return props.progress;
4473
+ get visible() {
4474
+ return props.nativeSelectionCursorVisible;
4475
+ },
4476
+ get onClick() {
4477
+ return props.onNativeSelectionCopy;
3958
4478
  },
3959
- get showHint() {
3960
- return props.labelShowHint;
4479
+ get onEnter() {
4480
+ return props.onNativeSelectionEnter;
3961
4481
  }
3962
4482
  });
3963
4483
  }
3964
- }), createComponent(InputOverlay, {
3965
- get x() {
3966
- return props.inputX ?? 0;
3967
- },
3968
- get y() {
3969
- return props.inputY ?? 0;
3970
- },
3971
- get zIndex() {
3972
- return props.labelZIndex;
3973
- },
3974
- get value() {
3975
- return props.inputValue ?? "";
3976
- },
3977
- get visible() {
3978
- return props.inputVisible ?? false;
3979
- },
3980
- get onInput() {
3981
- return props.onInputChange;
3982
- },
3983
- get onSubmit() {
3984
- return props.onInputSubmit;
3985
- },
3986
- get onCancel() {
3987
- return props.onInputCancel;
3988
- }
3989
4484
  })];
3990
4485
  };
3991
4486
 
@@ -4930,20 +5425,47 @@ var getStack = async (element) => {
4930
5425
  return [];
4931
5426
  }
4932
5427
  };
4933
- var formatStack = (stack) => {
5428
+ var formatElementInfo = async (element) => {
5429
+ const html = getHTMLPreview(element);
5430
+ const stack = await getStack(element);
4934
5431
  const isNextProject = checkIsNextProject();
4935
- return stack.map(({ name, source }) => {
4936
- if (!source) return ` at ${name}`;
4937
- if (source.fileName.startsWith("about://React/Server")) {
4938
- return ` at ${name} (Server)`;
4939
- }
4940
- if (!je2(source.fileName)) return ` at ${name}`;
4941
- const framePart = ` at ${name} in ${Q(source.fileName)}`;
4942
- if (isNextProject) {
4943
- return `${framePart}:${source.lineNumber}:${source.columnNumber}`;
4944
- }
4945
- return framePart;
4946
- }).join("\n");
5432
+ let serverBoundary = null;
5433
+ let componentName = null;
5434
+ let fileName = null;
5435
+ let lineNumber = null;
5436
+ let columnNumber = null;
5437
+ for (const frame of stack) {
5438
+ if (!frame.source) continue;
5439
+ if (frame.source.fileName.startsWith("about://React/Server")) {
5440
+ if (!serverBoundary) serverBoundary = frame.name;
5441
+ continue;
5442
+ }
5443
+ if (je2(frame.source.fileName)) {
5444
+ if (!fileName) {
5445
+ fileName = Q(frame.source.fileName);
5446
+ lineNumber = frame.source.lineNumber ?? null;
5447
+ columnNumber = frame.source.columnNumber ?? null;
5448
+ }
5449
+ if (!componentName && checkIsSourceComponentName(frame.name)) {
5450
+ componentName = frame.name;
5451
+ }
5452
+ if (fileName && componentName) {
5453
+ break;
5454
+ }
5455
+ }
5456
+ }
5457
+ if (!componentName || !fileName) {
5458
+ return html;
5459
+ }
5460
+ let result = `${html}
5461
+ in ${componentName} at ${fileName}`;
5462
+ if (isNextProject && lineNumber && columnNumber) {
5463
+ result += `:${lineNumber}:${columnNumber}`;
5464
+ }
5465
+ if (serverBoundary) {
5466
+ result += ` (via Server: ${serverBoundary})`;
5467
+ }
5468
+ return result;
4947
5469
  };
4948
5470
  var getFileName = (stack) => {
4949
5471
  for (const frame of stack) {
@@ -5298,6 +5820,53 @@ var isCLikeKey = (key, code) => {
5298
5820
  return C_LIKE_CHARACTERS.has(key);
5299
5821
  };
5300
5822
 
5823
+ // src/utils/hotkey.ts
5824
+ var keyMatchesCode = (targetKey, code) => {
5825
+ const normalizedTarget = targetKey.toLowerCase();
5826
+ if (code.startsWith("Key")) {
5827
+ return code.slice(3).toLowerCase() === normalizedTarget;
5828
+ }
5829
+ if (code.startsWith("Digit")) {
5830
+ return code.slice(5) === normalizedTarget;
5831
+ }
5832
+ return false;
5833
+ };
5834
+ var isTargetKeyCombination = (event, options) => {
5835
+ if (options.activationShortcut) {
5836
+ return options.activationShortcut(event);
5837
+ }
5838
+ if (options.activationKey) {
5839
+ const { key, metaKey, ctrlKey, shiftKey, altKey } = options.activationKey;
5840
+ const isModifierOnly = !key;
5841
+ if (isModifierOnly) {
5842
+ if (!MODIFIER_KEYS.includes(event.key)) return false;
5843
+ const metaMatches = metaKey ? event.metaKey || event.key === "Meta" : true;
5844
+ const ctrlMatches = ctrlKey ? event.ctrlKey || event.key === "Control" : true;
5845
+ const shiftMatches = shiftKey ? event.shiftKey || event.key === "Shift" : true;
5846
+ const altMatches = altKey ? event.altKey || event.key === "Alt" : true;
5847
+ const allRequiredModifiersPressed = metaMatches && ctrlMatches && shiftMatches && altMatches;
5848
+ const requiredModifierCount = [metaKey, ctrlKey, shiftKey, altKey].filter(Boolean).length;
5849
+ const pressedModifierCount = [
5850
+ event.metaKey || event.key === "Meta",
5851
+ event.ctrlKey || event.key === "Control",
5852
+ event.shiftKey || event.key === "Shift",
5853
+ event.altKey || event.key === "Alt"
5854
+ ].filter(Boolean).length;
5855
+ return allRequiredModifiersPressed && pressedModifierCount >= requiredModifierCount;
5856
+ }
5857
+ const keyMatches = event.key.toLowerCase() === key.toLowerCase() || keyMatchesCode(key, event.code);
5858
+ const hasModifier = metaKey || ctrlKey || shiftKey || altKey;
5859
+ const modifiersMatch = hasModifier ? (metaKey ? event.metaKey : true) && (ctrlKey ? event.ctrlKey : true) && (shiftKey ? event.shiftKey : true) && (altKey ? event.altKey : true) : event.metaKey || event.ctrlKey;
5860
+ return keyMatches && modifiersMatch;
5861
+ }
5862
+ return (event.metaKey || event.ctrlKey) && isCLikeKey(event.key, event.code);
5863
+ };
5864
+
5865
+ // src/utils/is-event-from-overlay.ts
5866
+ var isEventFromOverlay = (event, attribute) => event.composedPath().some(
5867
+ (target) => target instanceof HTMLElement && target.hasAttribute(attribute)
5868
+ );
5869
+
5301
5870
  // src/theme.ts
5302
5871
  var DEFAULT_THEME = {
5303
5872
  enabled: true,
@@ -5410,10 +5979,289 @@ var deepMergeTheme = (baseTheme, partialTheme) => {
5410
5979
  };
5411
5980
  };
5412
5981
 
5982
+ // src/utils/agent-session.ts
5983
+ var STORAGE_KEY = "react-grab:agent-sessions";
5984
+ var generateSessionId = () => `session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
5985
+ var createSession = (context, position, selectionBounds, tagName) => ({
5986
+ id: generateSessionId(),
5987
+ context,
5988
+ lastStatus: "",
5989
+ isStreaming: true,
5990
+ createdAt: Date.now(),
5991
+ position,
5992
+ selectionBounds,
5993
+ tagName
5994
+ });
5995
+ var getStorage = (storage) => {
5996
+ if (!storage) return null;
5997
+ return storage;
5998
+ };
5999
+ var memorySessions = /* @__PURE__ */ new Map();
6000
+ var saveSessions = (sessions, storage) => {
6001
+ const resolvedStorage = getStorage(storage);
6002
+ if (!resolvedStorage) {
6003
+ memorySessions.clear();
6004
+ sessions.forEach((session, id) => memorySessions.set(id, session));
6005
+ return;
6006
+ }
6007
+ try {
6008
+ const sessionsObject = Object.fromEntries(sessions);
6009
+ resolvedStorage.setItem(STORAGE_KEY, JSON.stringify(sessionsObject));
6010
+ } catch {
6011
+ memorySessions.clear();
6012
+ sessions.forEach((session, id) => memorySessions.set(id, session));
6013
+ }
6014
+ };
6015
+ var saveSessionById = (session, storage) => {
6016
+ const sessions = loadSessions(storage);
6017
+ sessions.set(session.id, session);
6018
+ saveSessions(sessions, storage);
6019
+ };
6020
+ var loadSessions = (storage) => {
6021
+ const resolvedStorage = getStorage(storage);
6022
+ if (!resolvedStorage) {
6023
+ return new Map(memorySessions);
6024
+ }
6025
+ try {
6026
+ const data = resolvedStorage.getItem(STORAGE_KEY);
6027
+ if (!data) return /* @__PURE__ */ new Map();
6028
+ const sessionsObject = JSON.parse(data);
6029
+ return new Map(Object.entries(sessionsObject));
6030
+ } catch {
6031
+ return /* @__PURE__ */ new Map();
6032
+ }
6033
+ };
6034
+ var clearSessions = (storage) => {
6035
+ const resolvedStorage = getStorage(storage);
6036
+ if (!resolvedStorage) {
6037
+ memorySessions.clear();
6038
+ return;
6039
+ }
6040
+ try {
6041
+ resolvedStorage.removeItem(STORAGE_KEY);
6042
+ } catch {
6043
+ memorySessions.clear();
6044
+ }
6045
+ };
6046
+ var clearSessionById = (sessionId, storage) => {
6047
+ const sessions = loadSessions(storage);
6048
+ sessions.delete(sessionId);
6049
+ saveSessions(sessions, storage);
6050
+ };
6051
+ var updateSession = (session, updates, storage) => {
6052
+ const updatedSession = { ...session, ...updates };
6053
+ saveSessionById(updatedSession, storage);
6054
+ return updatedSession;
6055
+ };
6056
+
6057
+ // src/utils/generate-snippet.ts
6058
+ var generateSnippet = async (elements) => {
6059
+ const elementSnippetResults = await Promise.allSettled(
6060
+ elements.map((element) => formatElementInfo(element))
6061
+ );
6062
+ const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
6063
+ if (elementSnippets.length === 0) {
6064
+ return "";
6065
+ }
6066
+ return elementSnippets.join("\n\n");
6067
+ };
6068
+
6069
+ // src/agent.ts
6070
+ var createAgentManager = (agentOptions) => {
6071
+ const [sessions, setSessions] = createSignal(/* @__PURE__ */ new Map());
6072
+ const abortControllers = /* @__PURE__ */ new Map();
6073
+ const sessionElements = /* @__PURE__ */ new Map();
6074
+ const isProcessing = () => sessions().size > 0;
6075
+ const executeSessionStream = async (session, streamIterator) => {
6076
+ const storage = agentOptions?.storage;
6077
+ let didComplete = false;
6078
+ let wasAborted = false;
6079
+ let hadError = false;
6080
+ try {
6081
+ for await (const status of streamIterator) {
6082
+ const currentSessions = sessions();
6083
+ const currentSession = currentSessions.get(session.id);
6084
+ if (!currentSession) break;
6085
+ const updatedSession = updateSession(currentSession, { lastStatus: status }, storage);
6086
+ setSessions((prev) => new Map(prev).set(session.id, updatedSession));
6087
+ agentOptions?.onStatus?.(status, updatedSession);
6088
+ }
6089
+ didComplete = true;
6090
+ const finalSessions = sessions();
6091
+ const finalSession = finalSessions.get(session.id);
6092
+ if (finalSession) {
6093
+ const completedSession = updateSession(finalSession, { isStreaming: false }, storage);
6094
+ setSessions((prev) => new Map(prev).set(session.id, completedSession));
6095
+ agentOptions?.onComplete?.(completedSession);
6096
+ }
6097
+ } catch (error) {
6098
+ const currentSessions = sessions();
6099
+ const currentSession = currentSessions.get(session.id);
6100
+ if (error instanceof Error && error.name === "AbortError") {
6101
+ wasAborted = true;
6102
+ if (currentSession) {
6103
+ const element = sessionElements.get(session.id);
6104
+ agentOptions?.onAbort?.(currentSession, element);
6105
+ }
6106
+ } else {
6107
+ hadError = true;
6108
+ if (currentSession) {
6109
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
6110
+ const errorSession = updateSession(currentSession, {
6111
+ lastStatus: `Error: ${errorMessage}`,
6112
+ isStreaming: false
6113
+ }, storage);
6114
+ setSessions((prev) => new Map(prev).set(session.id, errorSession));
6115
+ if (error instanceof Error) {
6116
+ agentOptions?.onError?.(error, errorSession);
6117
+ }
6118
+ }
6119
+ }
6120
+ } finally {
6121
+ abortControllers.delete(session.id);
6122
+ const removeSession = () => {
6123
+ sessionElements.delete(session.id);
6124
+ clearSessionById(session.id, storage);
6125
+ setSessions((prev) => {
6126
+ const next = new Map(prev);
6127
+ next.delete(session.id);
6128
+ return next;
6129
+ });
6130
+ };
6131
+ if (wasAborted) {
6132
+ removeSession();
6133
+ } else if (didComplete || hadError) {
6134
+ setTimeout(removeSession, 1500);
6135
+ }
6136
+ }
6137
+ };
6138
+ const tryReacquireElement = (session) => {
6139
+ const { selectionBounds, tagName } = session;
6140
+ if (!selectionBounds) return void 0;
6141
+ const centerX = selectionBounds.x + selectionBounds.width / 2;
6142
+ const centerY = selectionBounds.y + selectionBounds.height / 2;
6143
+ const element = document.elementFromPoint(centerX, centerY);
6144
+ if (!element) return void 0;
6145
+ if (tagName && element.tagName.toLowerCase() !== tagName) {
6146
+ return void 0;
6147
+ }
6148
+ return element;
6149
+ };
6150
+ const tryResumeSessions = () => {
6151
+ const storage = agentOptions?.storage;
6152
+ const existingSessions = loadSessions(storage);
6153
+ const streamingSessions = Array.from(existingSessions.values()).filter(
6154
+ (session) => session.isStreaming
6155
+ );
6156
+ if (streamingSessions.length === 0) {
6157
+ clearSessions(storage);
6158
+ return;
6159
+ }
6160
+ if (!agentOptions?.provider?.supportsResume || !agentOptions.provider.resume) {
6161
+ clearSessions(storage);
6162
+ return;
6163
+ }
6164
+ const streamingSessionsMap = new Map(
6165
+ streamingSessions.map((session) => [session.id, session])
6166
+ );
6167
+ setSessions(streamingSessionsMap);
6168
+ saveSessions(streamingSessionsMap, storage);
6169
+ for (const existingSession of streamingSessions) {
6170
+ const reacquiredElement = tryReacquireElement(existingSession);
6171
+ if (reacquiredElement) {
6172
+ sessionElements.set(existingSession.id, reacquiredElement);
6173
+ }
6174
+ const sessionWithResumeStatus = {
6175
+ ...existingSession,
6176
+ lastStatus: existingSession.lastStatus || "Resuming...",
6177
+ position: existingSession.position ?? { x: window.innerWidth / 2, y: window.innerHeight / 2 }
6178
+ };
6179
+ setSessions((prev) => new Map(prev).set(existingSession.id, sessionWithResumeStatus));
6180
+ agentOptions?.onResume?.(sessionWithResumeStatus);
6181
+ const abortController = new AbortController();
6182
+ abortControllers.set(existingSession.id, abortController);
6183
+ const streamIterator = agentOptions.provider.resume(existingSession.id, abortController.signal);
6184
+ void executeSessionStream(existingSession, streamIterator);
6185
+ }
6186
+ };
6187
+ const startSession = async (params) => {
6188
+ const { element, prompt, position, selectionBounds } = params;
6189
+ const storage = agentOptions?.storage;
6190
+ if (!agentOptions?.provider) {
6191
+ return;
6192
+ }
6193
+ const elements = [element];
6194
+ const content = await generateSnippet(elements);
6195
+ const context = { content, prompt, options: agentOptions?.getOptions?.() };
6196
+ const tagName = (element.tagName || "").toLowerCase() || void 0;
6197
+ const session = createSession(context, position, selectionBounds, tagName);
6198
+ session.lastStatus = "Please wait\u2026";
6199
+ sessionElements.set(session.id, element);
6200
+ setSessions((prev) => new Map(prev).set(session.id, session));
6201
+ saveSessionById(session, storage);
6202
+ agentOptions.onStart?.(session);
6203
+ const abortController = new AbortController();
6204
+ abortControllers.set(session.id, abortController);
6205
+ const streamIterator = agentOptions.provider.send(context, abortController.signal);
6206
+ void executeSessionStream(session, streamIterator);
6207
+ };
6208
+ const abortSession = (sessionId) => {
6209
+ const controller = abortControllers.get(sessionId);
6210
+ if (controller) {
6211
+ controller.abort();
6212
+ }
6213
+ };
6214
+ const abortAllSessions = () => {
6215
+ abortControllers.forEach((controller) => controller.abort());
6216
+ abortControllers.clear();
6217
+ setSessions(/* @__PURE__ */ new Map());
6218
+ clearSessions(agentOptions?.storage);
6219
+ };
6220
+ const updateSessionBoundsOnViewportChange = () => {
6221
+ const currentSessions = sessions();
6222
+ if (currentSessions.size === 0) return;
6223
+ const updatedSessions = new Map(currentSessions);
6224
+ let didUpdate = false;
6225
+ for (const [sessionId, session] of currentSessions) {
6226
+ let element = sessionElements.get(sessionId);
6227
+ if (!element || !document.contains(element)) {
6228
+ const reacquiredElement = tryReacquireElement(session);
6229
+ if (reacquiredElement) {
6230
+ sessionElements.set(sessionId, reacquiredElement);
6231
+ element = reacquiredElement;
6232
+ }
6233
+ }
6234
+ if (element && document.contains(element)) {
6235
+ const newBounds = createElementBounds(element);
6236
+ if (newBounds) {
6237
+ updatedSessions.set(sessionId, { ...session, selectionBounds: newBounds });
6238
+ didUpdate = true;
6239
+ }
6240
+ }
6241
+ }
6242
+ if (didUpdate) {
6243
+ setSessions(updatedSessions);
6244
+ }
6245
+ };
6246
+ const getSessionElement = (sessionId) => {
6247
+ return sessionElements.get(sessionId);
6248
+ };
6249
+ return {
6250
+ sessions,
6251
+ isProcessing,
6252
+ tryResumeSessions,
6253
+ startSession,
6254
+ abortSession,
6255
+ abortAllSessions,
6256
+ updateSessionBoundsOnViewportChange,
6257
+ getSessionElement
6258
+ };
6259
+ };
6260
+
5413
6261
  // src/core.tsx
5414
- var _tmpl$9 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">1 element`);
6262
+ var _tmpl$14 = /* @__PURE__ */ template(`<span class="tabular-nums align-middle">`);
5415
6263
  var _tmpl$23 = /* @__PURE__ */ template(`<span class="font-mono tabular-nums align-middle">&lt;<!>>`);
5416
- var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums text-[10px] ml-1 align-middle"> in `);
6264
+ var _tmpl$33 = /* @__PURE__ */ template(`<span class="tabular-nums ml-1 align-middle"> in `);
5417
6265
  var hasInited = false;
5418
6266
  var getScriptOptions = () => {
5419
6267
  if (typeof window === "undefined") return null;
@@ -5463,9 +6311,8 @@ var init = (rawOptions) => {
5463
6311
  hasInited = true;
5464
6312
  const logIntro = () => {
5465
6313
  try {
5466
- const version = "0.0.54";
5467
- 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>`;
5468
- const logoDataUri = `data:image/svg+xml;base64,${btoa(logoSvg)}`;
6314
+ const version = "0.0.55";
6315
+ const logoDataUri = `data:image/svg+xml;base64,${btoa(LOGO_SVG)}`;
5469
6316
  console.log(`%cReact Grab${version ? ` v${version}` : ""}%c
5470
6317
  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;`, "");
5471
6318
  if (navigator.onLine && version) {
@@ -5483,9 +6330,7 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5483
6330
  } catch {
5484
6331
  }
5485
6332
  };
5486
- if (options.log !== false) {
5487
- logIntro();
5488
- }
6333
+ logIntro();
5489
6334
  return createRoot((dispose2) => {
5490
6335
  const [theme, setTheme] = createSignal(initialTheme);
5491
6336
  const [isHoldingKeys, setIsHoldingKeys] = createSignal(false);
@@ -5495,32 +6340,45 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5495
6340
  const [dragStartX, setDragStartX] = createSignal(OFFSCREEN_POSITION);
5496
6341
  const [dragStartY, setDragStartY] = createSignal(OFFSCREEN_POSITION);
5497
6342
  const [isCopying, setIsCopying] = createSignal(false);
6343
+ const [selectionLabelStatus, setSelectionLabelStatus] = createSignal("idle");
6344
+ const [labelInstances, setLabelInstances] = createSignal([]);
5498
6345
  const [lastGrabbedElement, setLastGrabbedElement] = createSignal(null);
5499
6346
  const [progressStartTime, setProgressStartTime] = createSignal(null);
5500
- const [progress, setProgress] = createSignal(0);
5501
6347
  const [grabbedBoxes, setGrabbedBoxes] = createSignal([]);
5502
6348
  const [successLabels, setSuccessLabels] = createSignal([]);
5503
6349
  const [isActivated, setIsActivated] = createSignal(false);
5504
6350
  const [isToggleMode, setIsToggleMode] = createSignal(false);
5505
- const [showProgressIndicator, setShowProgressIndicator] = createSignal(false);
5506
6351
  const [didJustDrag, setDidJustDrag] = createSignal(false);
5507
6352
  const [copyStartX, setCopyStartX] = createSignal(OFFSCREEN_POSITION);
5508
6353
  const [copyStartY, setCopyStartY] = createSignal(OFFSCREEN_POSITION);
5509
- const [mouseHasSettled, setMouseHasSettled] = createSignal(false);
5510
6354
  const [viewportVersion, setViewportVersion] = createSignal(0);
5511
6355
  const [isInputMode, setIsInputMode] = createSignal(false);
5512
6356
  const [inputText, setInputText] = createSignal("");
5513
6357
  const [isTouchMode, setIsTouchMode] = createSignal(false);
6358
+ const [selectionFilePath, setSelectionFilePath] = createSignal(void 0);
6359
+ const [selectionLineNumber, setSelectionLineNumber] = createSignal(void 0);
6360
+ const [isToggleFrozen, setIsToggleFrozen] = createSignal(false);
6361
+ const [isInputExpanded, setIsInputExpanded] = createSignal(false);
6362
+ const [frozenElement, setFrozenElement] = createSignal(null);
6363
+ const [nativeSelectionCursorX, setNativeSelectionCursorX] = createSignal(OFFSCREEN_POSITION);
6364
+ const [nativeSelectionCursorY, setNativeSelectionCursorY] = createSignal(OFFSCREEN_POSITION);
6365
+ const [hasNativeSelection, setHasNativeSelection] = createSignal(false);
6366
+ const [nativeSelectionElements, setNativeSelectionElements] = createSignal([]);
6367
+ const [nativeSelectionTagName, setNativeSelectionTagName] = createSignal(void 0);
6368
+ const [nativeSelectionComponentName, setNativeSelectionComponentName] = createSignal(void 0);
6369
+ const nativeSelectionBounds = createMemo(() => {
6370
+ viewportVersion();
6371
+ const elements = nativeSelectionElements();
6372
+ if (elements.length === 0 || !elements[0]) return void 0;
6373
+ return createElementBounds(elements[0]);
6374
+ });
5514
6375
  let holdTimerId = null;
6376
+ let activationTimestamp = null;
5515
6377
  let progressAnimationId = null;
5516
- let progressDelayTimerId = null;
5517
6378
  let keydownSpamTimerId = null;
5518
- let mouseSettleTimerId = null;
5519
6379
  let autoScrollAnimationId = null;
5520
6380
  let previouslyFocusedElement = null;
5521
6381
  const isRendererActive = createMemo(() => isActivated() && !isCopying());
5522
- const hasValidMousePosition = createMemo(() => mouseX() > OFFSCREEN_POSITION && mouseY() > OFFSCREEN_POSITION);
5523
- const isTargetKeyCombination = (event) => (event.metaKey || event.ctrlKey) && isCLikeKey(event.key, event.code);
5524
6382
  const getAutoScrollDirection = (clientX, clientY) => {
5525
6383
  return {
5526
6384
  top: clientY < AUTO_SCROLL_EDGE_THRESHOLD_PX,
@@ -5559,9 +6417,6 @@ https://react-grab.com`, `background: #330039; color: #ffffff; border: 1px solid
5559
6417
  setSuccessLabels((previousLabels) => previousLabels.filter((label) => label.id !== labelId));
5560
6418
  }, SUCCESS_LABEL_DURATION_MS);
5561
6419
  };
5562
- const wrapInSelectedElementTags = (context) => `<selected_element>
5563
- ${context}
5564
- </selected_element>`;
5565
6420
  const extractElementTagName = (element) => (element.tagName || "").toLowerCase();
5566
6421
  const extractElementTagNameForSuccess = (element) => {
5567
6422
  const tagName = extractElementTagName(element);
@@ -5577,16 +6432,49 @@ ${context}
5577
6432
  }
5578
6433
  }));
5579
6434
  };
5580
- const executeCopyOperation = async (positionX, positionY, operation) => {
6435
+ const createLabelInstance = (bounds, tagName, status, element) => {
6436
+ const instanceId = `label-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6437
+ setLabelInstances((prev) => [...prev, {
6438
+ id: instanceId,
6439
+ bounds,
6440
+ tagName,
6441
+ status,
6442
+ createdAt: Date.now(),
6443
+ element
6444
+ }]);
6445
+ return instanceId;
6446
+ };
6447
+ const updateLabelInstance = (instanceId, status) => {
6448
+ setLabelInstances((prev) => prev.map((instance) => instance.id === instanceId ? {
6449
+ ...instance,
6450
+ status
6451
+ } : instance));
6452
+ };
6453
+ const removeLabelInstance = (instanceId) => {
6454
+ setLabelInstances((prev) => prev.filter((instance) => instance.id !== instanceId));
6455
+ };
6456
+ const executeCopyOperation = async (positionX, positionY, operation, bounds, tagName, element) => {
5581
6457
  setCopyStartX(positionX);
5582
6458
  setCopyStartY(positionY);
5583
6459
  setIsCopying(true);
5584
6460
  startProgressAnimation();
6461
+ const instanceId = bounds && tagName ? createLabelInstance(bounds, tagName, "copying", element) : null;
5585
6462
  await operation().finally(() => {
5586
6463
  setIsCopying(false);
5587
6464
  stopProgressAnimation();
6465
+ if (instanceId) {
6466
+ updateLabelInstance(instanceId, "copied");
6467
+ setTimeout(() => {
6468
+ updateLabelInstance(instanceId, "fading");
6469
+ setTimeout(() => {
6470
+ removeLabelInstance(instanceId);
6471
+ }, 350);
6472
+ }, COPIED_LABEL_DURATION_MS);
6473
+ }
5588
6474
  if (isToggleMode()) {
5589
- deactivateRenderer();
6475
+ setTimeout(() => {
6476
+ deactivateRenderer();
6477
+ }, COPIED_LABEL_DURATION_MS + 350);
5590
6478
  }
5591
6479
  });
5592
6480
  };
@@ -5624,30 +6512,18 @@ ${context}
5624
6512
  return didCopy;
5625
6513
  }
5626
6514
  try {
5627
- const elementSnippetResults = await Promise.allSettled(elements.map(async (element) => {
5628
- const htmlPreview = getHTMLPreview(element);
5629
- if (!isReactProject) {
5630
- return `## HTML Frame:
5631
- ${htmlPreview}`;
5632
- }
5633
- const stack = await getStack(element);
5634
- const formattedStack = formatStack(stack);
5635
- if (formattedStack) {
5636
- return `## HTML Frame:
5637
- ${htmlPreview}
5638
-
5639
- ## Code Location:
5640
- ${formattedStack}`;
6515
+ const elementSnippetResults = await Promise.allSettled(elements.map((element) => formatElementInfo(element)));
6516
+ const elementSnippets = [];
6517
+ for (const result of elementSnippetResults) {
6518
+ if (result.status === "fulfilled" && result.value.trim()) {
6519
+ elementSnippets.push(result.value);
5641
6520
  }
5642
- return `## HTML Frame:
5643
- ${htmlPreview}`;
5644
- }));
5645
- const elementSnippets = elementSnippetResults.map((result) => result.status === "fulfilled" ? result.value : "").filter((snippet) => snippet.trim());
6521
+ }
5646
6522
  if (elementSnippets.length > 0) {
5647
- const wrappedSnippets = elementSnippets.map((snippet) => wrapInSelectedElementTags(snippet)).join("\n\n");
6523
+ const combinedSnippets = elementSnippets.join("\n\n");
5648
6524
  const plainTextContent = extraPrompt ? `${extraPrompt}
5649
6525
 
5650
- ${wrappedSnippets}` : wrappedSnippets;
6526
+ ${combinedSnippets}` : combinedSnippets;
5651
6527
  copiedContent = plainTextContent;
5652
6528
  didCopy = await copyContent(plainTextContent);
5653
6529
  }
@@ -5712,6 +6588,12 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5712
6588
  if (!isRendererActive() || isDragging()) return null;
5713
6589
  return getElementAtPosition(mouseX(), mouseY());
5714
6590
  });
6591
+ createEffect(() => {
6592
+ const element = targetElement();
6593
+ if (element) {
6594
+ setFrozenElement(element);
6595
+ }
6596
+ });
5715
6597
  const selectionBounds = createMemo(() => {
5716
6598
  viewportVersion();
5717
6599
  const element = targetElement();
@@ -5768,7 +6650,14 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5768
6650
  });
5769
6651
  const labelContent = createMemo(() => {
5770
6652
  const element = targetElement();
5771
- if (!element) return _tmpl$9();
6653
+ const copying = isCopying();
6654
+ if (!element) {
6655
+ return (() => {
6656
+ var _el$ = _tmpl$14();
6657
+ insert(_el$, copying ? "Please wait\u2026" : "1 element");
6658
+ return _el$;
6659
+ })();
6660
+ }
5772
6661
  const tagName = extractElementTagName(element);
5773
6662
  const componentName = getNearestComponentName(element);
5774
6663
  if (tagName && componentName) {
@@ -5789,14 +6678,20 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5789
6678
  return _el$8;
5790
6679
  })();
5791
6680
  }
5792
- return _tmpl$9();
6681
+ return (() => {
6682
+ var _el$10 = _tmpl$14();
6683
+ insert(_el$10, copying ? "Please wait\u2026" : "1 element");
6684
+ return _el$10;
6685
+ })();
5793
6686
  });
5794
- const labelPosition = createMemo(() => isCopying() ? {
5795
- x: copyStartX(),
5796
- y: copyStartY()
5797
- } : {
5798
- x: mouseX(),
5799
- y: mouseY()
6687
+ const labelPosition = createMemo(() => {
6688
+ return isCopying() ? {
6689
+ x: copyStartX(),
6690
+ y: copyStartY()
6691
+ } : {
6692
+ x: mouseX(),
6693
+ y: mouseY()
6694
+ };
5800
6695
  });
5801
6696
  const progressPosition = createMemo(() => isCopying() ? {
5802
6697
  x: copyStartX(),
@@ -5813,6 +6708,26 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5813
6708
  options.onElementHover?.(currentElement);
5814
6709
  }
5815
6710
  }));
6711
+ createEffect(on(() => targetElement(), (element) => {
6712
+ const clearSource = () => {
6713
+ setSelectionFilePath(void 0);
6714
+ setSelectionLineNumber(void 0);
6715
+ };
6716
+ if (!element) {
6717
+ clearSource();
6718
+ return;
6719
+ }
6720
+ getStack(element).then((stack) => {
6721
+ for (const frame of stack) {
6722
+ if (frame.source && je2(frame.source.fileName)) {
6723
+ setSelectionFilePath(Q(frame.source.fileName));
6724
+ setSelectionLineNumber(frame.source.lineNumber);
6725
+ return;
6726
+ }
6727
+ }
6728
+ clearSource();
6729
+ }).catch(clearSource);
6730
+ }));
5816
6731
  createEffect(on(() => viewportVersion(), () => {
5817
6732
  const currentBoxes = grabbedBoxes();
5818
6733
  if (currentBoxes.length === 0) return;
@@ -5822,6 +6737,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5822
6737
  }));
5823
6738
  setGrabbedBoxes(updatedBoxes);
5824
6739
  }));
6740
+ createEffect(on(() => viewportVersion(), () => agentManager.updateSessionBoundsOnViewportChange()));
5825
6741
  createEffect(on(() => [isActivated(), isDragging(), isCopying(), isInputMode(), targetElement(), dragBounds()], ([active, dragging, copying, inputMode, target, drag]) => {
5826
6742
  options.onStateChange?.({
5827
6743
  isActive: active,
@@ -5864,23 +6780,47 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5864
6780
  content: contentString
5865
6781
  });
5866
6782
  }));
5867
- const startProgressAnimation = () => {
6783
+ let cursorStyleElement = null;
6784
+ const setCursorOverride = (cursor) => {
6785
+ if (cursor) {
6786
+ if (!cursorStyleElement) {
6787
+ cursorStyleElement = document.createElement("style");
6788
+ cursorStyleElement.setAttribute("data-react-grab-cursor", "");
6789
+ document.head.appendChild(cursorStyleElement);
6790
+ }
6791
+ cursorStyleElement.textContent = `* { cursor: ${cursor} !important; }`;
6792
+ } else if (cursorStyleElement) {
6793
+ cursorStyleElement.remove();
6794
+ cursorStyleElement = null;
6795
+ }
6796
+ };
6797
+ createEffect(on(() => [isActivated(), isCopying(), isDragging(), isInputMode(), targetElement()], ([activated, copying, dragging, inputMode, target]) => {
6798
+ if (copying) {
6799
+ setCursorOverride("progress");
6800
+ } else if (inputMode) {
6801
+ setCursorOverride(null);
6802
+ } else if (activated && dragging) {
6803
+ setCursorOverride("crosshair");
6804
+ } else if (activated && target) {
6805
+ setCursorOverride("copy");
6806
+ } else if (activated) {
6807
+ setCursorOverride("crosshair");
6808
+ } else {
6809
+ setCursorOverride(null);
6810
+ }
6811
+ }));
6812
+ const startProgressAnimation = (duration) => {
5868
6813
  const startTime = Date.now();
6814
+ const animationDuration = options.keyHoldDuration;
5869
6815
  setProgressStartTime(startTime);
5870
- setShowProgressIndicator(false);
5871
- progressDelayTimerId = window.setTimeout(() => {
5872
- setShowProgressIndicator(true);
5873
- progressDelayTimerId = null;
5874
- }, PROGRESS_INDICATOR_DELAY_MS);
5875
6816
  const animateProgress = () => {
5876
6817
  const currentStartTime = progressStartTime();
5877
6818
  if (currentStartTime === null) return;
5878
6819
  const elapsedTime = Date.now() - currentStartTime;
5879
- const normalizedTime = elapsedTime / options.keyHoldDuration;
6820
+ const normalizedTime = elapsedTime / animationDuration;
5880
6821
  const easedProgress = 1 - Math.exp(-normalizedTime);
5881
6822
  const maxProgressBeforeCompletion = 0.95;
5882
6823
  const currentProgress = isCopying() ? Math.min(easedProgress, maxProgressBeforeCompletion) : 1;
5883
- setProgress(currentProgress);
5884
6824
  if (currentProgress < 1) {
5885
6825
  progressAnimationId = requestAnimationFrame(animateProgress);
5886
6826
  }
@@ -5892,13 +6832,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5892
6832
  cancelAnimationFrame(progressAnimationId);
5893
6833
  progressAnimationId = null;
5894
6834
  }
5895
- if (progressDelayTimerId !== null) {
5896
- window.clearTimeout(progressDelayTimerId);
5897
- progressDelayTimerId = null;
5898
- }
5899
6835
  setProgressStartTime(null);
5900
- setProgress(1);
5901
- setShowProgressIndicator(false);
5902
6836
  };
5903
6837
  const startAutoScroll = () => {
5904
6838
  const scroll = () => {
@@ -5928,8 +6862,8 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5928
6862
  const activateRenderer = () => {
5929
6863
  stopProgressAnimation();
5930
6864
  previouslyFocusedElement = document.activeElement;
6865
+ activationTimestamp = Date.now();
5931
6866
  setIsActivated(true);
5932
- document.body.style.cursor = "crosshair";
5933
6867
  options.onActivate?.();
5934
6868
  };
5935
6869
  const deactivateRenderer = () => {
@@ -5938,61 +6872,151 @@ ${plainTextContentOnly}` : plainTextContentOnly;
5938
6872
  setIsActivated(false);
5939
6873
  setIsInputMode(false);
5940
6874
  setInputText("");
5941
- document.body.style.cursor = "";
6875
+ setIsToggleFrozen(false);
6876
+ setIsInputExpanded(false);
6877
+ setFrozenElement(null);
6878
+ setSelectionLabelStatus("idle");
5942
6879
  if (isDragging()) {
5943
6880
  setIsDragging(false);
5944
6881
  document.body.style.userSelect = "";
5945
6882
  }
5946
6883
  if (holdTimerId) window.clearTimeout(holdTimerId);
5947
6884
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
5948
- if (mouseSettleTimerId) {
5949
- window.clearTimeout(mouseSettleTimerId);
5950
- mouseSettleTimerId = null;
5951
- }
5952
- setMouseHasSettled(false);
5953
6885
  stopAutoScroll();
5954
6886
  stopProgressAnimation();
6887
+ activationTimestamp = null;
5955
6888
  if (previouslyFocusedElement instanceof HTMLElement && document.contains(previouslyFocusedElement)) {
5956
6889
  previouslyFocusedElement.focus();
5957
6890
  }
5958
6891
  previouslyFocusedElement = null;
5959
6892
  options.onDeactivate?.();
5960
6893
  };
6894
+ const agentOptions = options.agent ? {
6895
+ ...options.agent,
6896
+ onAbort: (session, element) => {
6897
+ options.agent?.onAbort?.(session, element);
6898
+ if (element && document.contains(element)) {
6899
+ const rect = element.getBoundingClientRect();
6900
+ const centerX = rect.left + rect.width / 2;
6901
+ const centerY = rect.top + rect.height / 2;
6902
+ setMouseX(centerX);
6903
+ setMouseY(centerY);
6904
+ setFrozenElement(element);
6905
+ setInputText(session.context.prompt);
6906
+ setIsInputExpanded(true);
6907
+ setIsInputMode(true);
6908
+ setIsToggleMode(true);
6909
+ setIsToggleFrozen(true);
6910
+ if (!isActivated()) {
6911
+ activateRenderer();
6912
+ }
6913
+ }
6914
+ }
6915
+ } : void 0;
6916
+ const agentManager = createAgentManager(agentOptions);
5961
6917
  const handleInputChange = (value) => {
5962
6918
  setInputText(value);
5963
6919
  };
5964
6920
  const handleInputSubmit = () => {
5965
- if (!isInputMode()) return;
5966
- const element = targetElement();
5967
- const prompt = inputText().trim();
5968
- const currentX = mouseX();
5969
- const currentY = mouseY();
6921
+ const element = frozenElement() || targetElement();
6922
+ const prompt = isInputMode() ? inputText().trim() : "";
6923
+ if (!element) {
6924
+ deactivateRenderer();
6925
+ return;
6926
+ }
6927
+ const elementRect = element.getBoundingClientRect();
6928
+ const computedStyle = window.getComputedStyle(element);
6929
+ const bounds = {
6930
+ x: elementRect.left,
6931
+ y: elementRect.top,
6932
+ width: elementRect.width,
6933
+ height: elementRect.height,
6934
+ borderRadius: computedStyle.borderRadius || "0px",
6935
+ transform: stripTranslateFromTransform(element)
6936
+ };
6937
+ const currentX = bounds.x + bounds.width / 2;
6938
+ const currentY = bounds.y + bounds.height / 2;
6939
+ setMouseX(currentX);
6940
+ setMouseY(currentY);
6941
+ if (options.agent?.provider && prompt) {
6942
+ const positionX = mouseX();
6943
+ const positionY = mouseY();
6944
+ setInputText("");
6945
+ setIsInputMode(false);
6946
+ deactivateRenderer();
6947
+ void agentManager.startSession({
6948
+ element,
6949
+ prompt,
6950
+ position: {
6951
+ x: positionX,
6952
+ y: positionY
6953
+ },
6954
+ selectionBounds: bounds
6955
+ });
6956
+ return;
6957
+ }
5970
6958
  setIsInputMode(false);
5971
6959
  setInputText("");
5972
- if (element) {
5973
- void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0)).then(() => {
5974
- deactivateRenderer();
5975
- });
5976
- } else {
6960
+ const tagName = extractElementTagName(element);
6961
+ void executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(element, prompt || void 0), bounds, tagName, element).then(() => {
5977
6962
  deactivateRenderer();
5978
- }
6963
+ });
5979
6964
  };
5980
6965
  const handleInputCancel = () => {
5981
6966
  if (!isInputMode()) return;
5982
6967
  deactivateRenderer();
5983
6968
  };
6969
+ const handleToggleExpand = () => {
6970
+ setIsToggleMode(true);
6971
+ setIsToggleFrozen(true);
6972
+ setIsInputExpanded(true);
6973
+ setIsInputMode(true);
6974
+ };
6975
+ const handleNativeSelectionCopy = async () => {
6976
+ const elements = nativeSelectionElements();
6977
+ if (elements.length === 0) return;
6978
+ const currentX = nativeSelectionCursorX();
6979
+ const currentY = nativeSelectionCursorY();
6980
+ const bounds = nativeSelectionBounds();
6981
+ const tagName = nativeSelectionTagName();
6982
+ setHasNativeSelection(false);
6983
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
6984
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
6985
+ setNativeSelectionElements([]);
6986
+ setNativeSelectionTagName(void 0);
6987
+ setNativeSelectionComponentName(void 0);
6988
+ window.getSelection()?.removeAllRanges();
6989
+ if (elements.length === 1) {
6990
+ await executeCopyOperation(currentX, currentY, () => copySingleElementToClipboard(elements[0]), bounds, tagName);
6991
+ } else {
6992
+ await executeCopyOperation(currentX, currentY, () => copyMultipleElementsToClipboard(elements), bounds, tagName);
6993
+ }
6994
+ };
6995
+ const handleNativeSelectionEnter = () => {
6996
+ const elements = nativeSelectionElements();
6997
+ if (elements.length === 0) return;
6998
+ const bounds = nativeSelectionBounds();
6999
+ const currentX = bounds ? bounds.x + bounds.width / 2 : nativeSelectionCursorX();
7000
+ const currentY = bounds ? bounds.y + bounds.height / 2 : nativeSelectionCursorY();
7001
+ setHasNativeSelection(false);
7002
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7003
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7004
+ setNativeSelectionElements([]);
7005
+ setNativeSelectionTagName(void 0);
7006
+ setNativeSelectionComponentName(void 0);
7007
+ window.getSelection()?.removeAllRanges();
7008
+ setMouseX(currentX);
7009
+ setMouseY(currentY);
7010
+ setIsToggleMode(true);
7011
+ setIsToggleFrozen(true);
7012
+ setIsInputExpanded(true);
7013
+ activateRenderer();
7014
+ setIsInputMode(true);
7015
+ };
5984
7016
  const handlePointerMove = (clientX, clientY) => {
5985
- if (isInputMode()) return;
7017
+ if (isInputMode() || isToggleFrozen()) return;
5986
7018
  setMouseX(clientX);
5987
7019
  setMouseY(clientY);
5988
- if (mouseSettleTimerId !== null) {
5989
- window.clearTimeout(mouseSettleTimerId);
5990
- }
5991
- setMouseHasSettled(false);
5992
- mouseSettleTimerId = window.setTimeout(() => {
5993
- setMouseHasSettled(true);
5994
- mouseSettleTimerId = null;
5995
- }, 300);
5996
7020
  if (isDragging()) {
5997
7021
  const direction = getAutoScrollDirection(clientX, clientY);
5998
7022
  const isNearEdge = direction.top || direction.bottom || direction.left || direction.right;
@@ -6025,37 +7049,77 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6025
7049
  setDidJustDrag(true);
6026
7050
  const dragRect = calculateDragRectangle(clientX, clientY);
6027
7051
  const elements = getElementsInDrag(dragRect, isValidGrabbableElement);
6028
- if (elements.length > 0) {
6029
- options.onDragEnd?.(elements, dragRect);
6030
- void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(elements));
6031
- } else {
6032
- const fallbackElements = getElementsInDragLoose(dragRect, isValidGrabbableElement);
6033
- if (fallbackElements.length > 0) {
6034
- options.onDragEnd?.(fallbackElements, dragRect);
6035
- void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(fallbackElements));
7052
+ const selectedElements = elements.length > 0 ? elements : getElementsInDragLoose(dragRect, isValidGrabbableElement);
7053
+ if (selectedElements.length > 0) {
7054
+ options.onDragEnd?.(selectedElements, dragRect);
7055
+ const firstElement = selectedElements[0];
7056
+ const firstElementRect = firstElement.getBoundingClientRect();
7057
+ const bounds = {
7058
+ x: firstElementRect.left,
7059
+ y: firstElementRect.top,
7060
+ width: firstElementRect.width,
7061
+ height: firstElementRect.height,
7062
+ borderRadius: "0px",
7063
+ transform: stripTranslateFromTransform(firstElement)
7064
+ };
7065
+ const tagName = extractElementTagName(firstElement);
7066
+ if (options.agent?.provider) {
7067
+ const centerX = bounds.x + bounds.width / 2;
7068
+ const centerY = bounds.y + bounds.height / 2;
7069
+ setMouseX(centerX);
7070
+ setMouseY(centerY);
7071
+ setFrozenElement(firstElement);
7072
+ setIsToggleMode(true);
7073
+ setIsToggleFrozen(true);
7074
+ setIsInputExpanded(true);
7075
+ setIsInputMode(true);
7076
+ } else {
7077
+ void executeCopyOperation(clientX, clientY, () => copyMultipleElementsToClipboard(selectedElements), bounds, tagName, firstElement);
6036
7078
  }
6037
7079
  }
6038
7080
  } else {
6039
7081
  const element = getElementAtPosition(clientX, clientY);
6040
7082
  if (!element) return;
6041
7083
  setLastGrabbedElement(element);
6042
- void executeCopyOperation(clientX, clientY, () => copySingleElementToClipboard(element));
7084
+ const elementRect = element.getBoundingClientRect();
7085
+ const computedStyle = window.getComputedStyle(element);
7086
+ const bounds = {
7087
+ x: elementRect.left,
7088
+ y: elementRect.top,
7089
+ width: elementRect.width,
7090
+ height: elementRect.height,
7091
+ borderRadius: computedStyle.borderRadius || "0px",
7092
+ transform: stripTranslateFromTransform(element)
7093
+ };
7094
+ const tagName = extractElementTagName(element);
7095
+ void executeCopyOperation(clientX, clientY, () => copySingleElementToClipboard(element), bounds, tagName, element);
6043
7096
  }
6044
7097
  };
6045
7098
  const abortController = new AbortController();
6046
7099
  const eventListenerSignal = abortController.signal;
6047
7100
  window.addEventListener("keydown", (event) => {
6048
- if (event.key === "Escape" && isHoldingKeys()) {
6049
- if (isInputMode()) {
6050
- return;
7101
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
7102
+ if (event.key === "Escape" && agentManager.isProcessing()) {
7103
+ agentManager.abortAllSessions();
6051
7104
  }
6052
- deactivateRenderer();
6053
7105
  return;
6054
7106
  }
7107
+ if (event.key === "Escape") {
7108
+ if (agentManager.isProcessing()) {
7109
+ agentManager.abortAllSessions();
7110
+ return;
7111
+ }
7112
+ if (isHoldingKeys()) {
7113
+ deactivateRenderer();
7114
+ return;
7115
+ }
7116
+ }
6055
7117
  if (event.key === "Enter" && isHoldingKeys() && !isInputMode()) {
6056
7118
  event.preventDefault();
6057
7119
  event.stopPropagation();
6058
7120
  setIsToggleMode(true);
7121
+ setIsToggleFrozen(true);
7122
+ setIsInputExpanded(true);
6059
7123
  if (keydownSpamTimerId !== null) {
6060
7124
  window.clearTimeout(keydownSpamTimerId);
6061
7125
  keydownSpamTimerId = null;
@@ -6067,15 +7131,42 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6067
7131
  setIsInputMode(true);
6068
7132
  return;
6069
7133
  }
7134
+ if (event.key.toLowerCase() === "o" && !isInputMode()) {
7135
+ if (isActivated() && (event.metaKey || event.ctrlKey)) {
7136
+ const filePath = selectionFilePath();
7137
+ const lineNumber = selectionLineNumber();
7138
+ if (filePath) {
7139
+ event.preventDefault();
7140
+ event.stopPropagation();
7141
+ if (options.onOpenFile) {
7142
+ options.onOpenFile(filePath, lineNumber);
7143
+ } else {
7144
+ const url = buildOpenFileUrl(filePath, lineNumber);
7145
+ window.open(url, "_blank");
7146
+ }
7147
+ }
7148
+ return;
7149
+ }
7150
+ }
6070
7151
  if (!options.allowActivationInsideInput && isKeyboardEventTriggeredByInput(event)) {
6071
7152
  return;
6072
7153
  }
6073
- if (!isTargetKeyCombination(event)) return;
6074
- if (isActivated() || isHoldingKeys()) {
7154
+ if (!isTargetKeyCombination(event, options)) {
7155
+ if (isActivated() && !isToggleMode() && (event.metaKey || event.ctrlKey)) {
7156
+ if (!MODIFIER_KEYS.includes(event.key) && event.key !== "Enter") {
7157
+ deactivateRenderer();
7158
+ }
7159
+ }
7160
+ if (event.key !== "Enter") {
7161
+ return;
7162
+ }
7163
+ }
7164
+ if ((isActivated() || isHoldingKeys()) && !isInputMode()) {
6075
7165
  event.preventDefault();
6076
7166
  }
6077
7167
  if (isActivated()) {
6078
7168
  if (isToggleMode()) return;
7169
+ if (event.repeat) return;
6079
7170
  if (keydownSpamTimerId !== null) {
6080
7171
  window.clearTimeout(keydownSpamTimerId);
6081
7172
  }
@@ -6100,9 +7191,44 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6100
7191
  });
6101
7192
  window.addEventListener("keyup", (event) => {
6102
7193
  if (!isHoldingKeys() && !isActivated()) return;
6103
- const isReleasingModifier = !event.metaKey && !event.ctrlKey;
6104
- const isReleasingC = isCLikeKey(event.key, event.code);
6105
- if (isReleasingC || isReleasingModifier) {
7194
+ if (isInputMode()) return;
7195
+ const hasCustomShortcut = Boolean(options.activationShortcut || options.activationKey);
7196
+ const getRequiredModifiers = () => {
7197
+ if (options.activationKey) {
7198
+ const {
7199
+ metaKey,
7200
+ ctrlKey,
7201
+ shiftKey,
7202
+ altKey
7203
+ } = options.activationKey;
7204
+ return {
7205
+ metaKey: !!metaKey,
7206
+ ctrlKey: !!ctrlKey,
7207
+ shiftKey: !!shiftKey,
7208
+ altKey: !!altKey
7209
+ };
7210
+ }
7211
+ return {
7212
+ metaKey: true,
7213
+ ctrlKey: true,
7214
+ shiftKey: false,
7215
+ altKey: false
7216
+ };
7217
+ };
7218
+ const requiredModifiers = getRequiredModifiers();
7219
+ const isReleasingModifier = requiredModifiers.metaKey || requiredModifiers.ctrlKey ? !event.metaKey && !event.ctrlKey : requiredModifiers.shiftKey && !event.shiftKey || requiredModifiers.altKey && !event.altKey;
7220
+ 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);
7221
+ if (isActivated()) {
7222
+ if (isReleasingModifier) {
7223
+ if (isToggleMode()) return;
7224
+ deactivateRenderer();
7225
+ } else if (!hasCustomShortcut && isReleasingActivationKey && keydownSpamTimerId !== null) {
7226
+ window.clearTimeout(keydownSpamTimerId);
7227
+ keydownSpamTimerId = null;
7228
+ }
7229
+ return;
7230
+ }
7231
+ if (isReleasingActivationKey || isReleasingModifier) {
6106
7232
  if (isToggleMode()) return;
6107
7233
  deactivateRenderer();
6108
7234
  }
@@ -6112,17 +7238,15 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6112
7238
  });
6113
7239
  window.addEventListener("mousemove", (event) => {
6114
7240
  setIsTouchMode(false);
7241
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6115
7242
  handlePointerMove(event.clientX, event.clientY);
6116
7243
  }, {
6117
7244
  signal: eventListenerSignal
6118
7245
  });
6119
7246
  window.addEventListener("mousedown", (event) => {
7247
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6120
7248
  if (isInputMode()) {
6121
- const target = event.target;
6122
- const isClickingInput = target.closest("[data-react-grab-input]");
6123
- if (!isClickingInput) {
6124
- handleInputCancel();
6125
- }
7249
+ handleInputCancel();
6126
7250
  return;
6127
7251
  }
6128
7252
  const didHandle = handlePointerDown(event.clientX, event.clientY);
@@ -6135,6 +7259,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6135
7259
  });
6136
7260
  window.addEventListener("pointerdown", (event) => {
6137
7261
  if (!isRendererActive() || isCopying() || isInputMode()) return;
7262
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6138
7263
  event.stopPropagation();
6139
7264
  }, {
6140
7265
  signal: eventListenerSignal,
@@ -6148,6 +7273,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6148
7273
  window.addEventListener("touchmove", (event) => {
6149
7274
  if (event.touches.length === 0) return;
6150
7275
  setIsTouchMode(true);
7276
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6151
7277
  handlePointerMove(event.touches[0].clientX, event.touches[0].clientY);
6152
7278
  }, {
6153
7279
  signal: eventListenerSignal,
@@ -6156,12 +7282,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6156
7282
  window.addEventListener("touchstart", (event) => {
6157
7283
  if (event.touches.length === 0) return;
6158
7284
  setIsTouchMode(true);
7285
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6159
7286
  if (isInputMode()) {
6160
- const target = event.target;
6161
- const isClickingInput = target.closest("[data-react-grab-input]");
6162
- if (!isClickingInput) {
6163
- handleInputCancel();
6164
- }
7287
+ handleInputCancel();
6165
7288
  return;
6166
7289
  }
6167
7290
  const didHandle = handlePointerDown(event.touches[0].clientX, event.touches[0].clientY);
@@ -6179,6 +7302,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6179
7302
  signal: eventListenerSignal
6180
7303
  });
6181
7304
  window.addEventListener("click", (event) => {
7305
+ if (isEventFromOverlay(event, "data-react-grab-ignore-events")) return;
6182
7306
  if (isRendererActive() || isCopying() || didJustDrag()) {
6183
7307
  event.preventDefault();
6184
7308
  event.stopPropagation();
@@ -6201,6 +7325,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6201
7325
  document.addEventListener("visibilitychange", () => {
6202
7326
  if (document.hidden) {
6203
7327
  setGrabbedBoxes([]);
7328
+ if (isActivated() && !isInputMode() && activationTimestamp !== null && Date.now() - activationTimestamp > BLUR_DEACTIVATION_THRESHOLD_MS) {
7329
+ deactivateRenderer();
7330
+ }
6204
7331
  }
6205
7332
  }, {
6206
7333
  signal: eventListenerSignal
@@ -6217,6 +7344,9 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6217
7344
  signal: eventListenerSignal
6218
7345
  });
6219
7346
  document.addEventListener("copy", (event) => {
7347
+ if (isInputMode() || isEventFromOverlay(event, "data-react-grab-ignore-events")) {
7348
+ return;
7349
+ }
6220
7350
  if (isRendererActive() || isCopying()) {
6221
7351
  event.preventDefault();
6222
7352
  }
@@ -6224,18 +7354,118 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6224
7354
  signal: eventListenerSignal,
6225
7355
  capture: true
6226
7356
  });
7357
+ let selectionDebounceTimerId = null;
7358
+ document.addEventListener("selectionchange", () => {
7359
+ if (isRendererActive()) return;
7360
+ if (selectionDebounceTimerId !== null) {
7361
+ window.clearTimeout(selectionDebounceTimerId);
7362
+ }
7363
+ setHasNativeSelection(false);
7364
+ const selection = window.getSelection();
7365
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
7366
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7367
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7368
+ setNativeSelectionElements([]);
7369
+ setNativeSelectionTagName(void 0);
7370
+ setNativeSelectionComponentName(void 0);
7371
+ return;
7372
+ }
7373
+ selectionDebounceTimerId = window.setTimeout(() => {
7374
+ selectionDebounceTimerId = null;
7375
+ const currentSelection = window.getSelection();
7376
+ if (!currentSelection || currentSelection.isCollapsed || currentSelection.rangeCount === 0) {
7377
+ return;
7378
+ }
7379
+ const range = currentSelection.getRangeAt(0);
7380
+ const rangeRect = range.getBoundingClientRect();
7381
+ if (rangeRect.width === 0 && rangeRect.height === 0) {
7382
+ return;
7383
+ }
7384
+ const isBackward = (() => {
7385
+ if (!currentSelection.anchorNode || !currentSelection.focusNode) return false;
7386
+ const position = currentSelection.anchorNode.compareDocumentPosition(currentSelection.focusNode);
7387
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) return false;
7388
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) return true;
7389
+ return currentSelection.anchorOffset > currentSelection.focusOffset;
7390
+ })();
7391
+ const clientRects = range.getClientRects();
7392
+ if (clientRects.length === 0) {
7393
+ return;
7394
+ }
7395
+ const cursorRect = isBackward ? clientRects[0] : clientRects[clientRects.length - 1];
7396
+ const cursorX = isBackward ? cursorRect.left : cursorRect.right;
7397
+ const cursorY = cursorRect.top + cursorRect.height / 2;
7398
+ if (isSelectionInsideEditableElement(cursorX, cursorY)) {
7399
+ setNativeSelectionCursorX(OFFSCREEN_POSITION);
7400
+ setNativeSelectionCursorY(OFFSCREEN_POSITION);
7401
+ setNativeSelectionElements([]);
7402
+ setNativeSelectionTagName(void 0);
7403
+ setNativeSelectionComponentName(void 0);
7404
+ return;
7405
+ }
7406
+ setNativeSelectionCursorX(cursorX);
7407
+ setNativeSelectionCursorY(cursorY);
7408
+ const container = range.commonAncestorContainer;
7409
+ const element = container.nodeType === Node.ELEMENT_NODE ? container : container.parentElement;
7410
+ if (element && isValidGrabbableElement(element)) {
7411
+ setNativeSelectionElements([element]);
7412
+ setNativeSelectionTagName(extractElementTagName(element) || void 0);
7413
+ setNativeSelectionComponentName(getNearestComponentName(element) || void 0);
7414
+ setHasNativeSelection(true);
7415
+ } else {
7416
+ setNativeSelectionElements([]);
7417
+ setNativeSelectionTagName(void 0);
7418
+ setNativeSelectionComponentName(void 0);
7419
+ }
7420
+ }, 150);
7421
+ }, {
7422
+ signal: eventListenerSignal
7423
+ });
6227
7424
  onCleanup(() => {
6228
7425
  abortController.abort();
6229
7426
  if (holdTimerId) window.clearTimeout(holdTimerId);
6230
7427
  if (keydownSpamTimerId) window.clearTimeout(keydownSpamTimerId);
6231
- if (mouseSettleTimerId) window.clearTimeout(mouseSettleTimerId);
6232
7428
  stopAutoScroll();
6233
7429
  stopProgressAnimation();
6234
7430
  document.body.style.userSelect = "";
6235
- document.body.style.cursor = "";
7431
+ setCursorOverride(null);
6236
7432
  });
6237
7433
  const rendererRoot = mountRoot(styles_default);
6238
- const selectionVisible = createMemo(() => theme().selectionBox.enabled && isRendererActive() && !isDragging() && Boolean(targetElement()));
7434
+ const selectionVisible = createMemo(() => {
7435
+ if (!theme().selectionBox.enabled) return false;
7436
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7437
+ });
7438
+ const selectionTagName = createMemo(() => {
7439
+ const element = targetElement();
7440
+ if (!element) return void 0;
7441
+ return extractElementTagName(element) || void 0;
7442
+ });
7443
+ const selectionLabelVisible = createMemo(() => {
7444
+ if (!theme().elementLabel.enabled) return false;
7445
+ if (successLabels().length > 0) return false;
7446
+ return isRendererActive() && !isDragging() && Boolean(targetElement());
7447
+ });
7448
+ const computedLabelInstances = createMemo(() => {
7449
+ viewportVersion();
7450
+ return labelInstances().map((instance) => {
7451
+ if (!instance.element || !document.body.contains(instance.element)) {
7452
+ return instance;
7453
+ }
7454
+ const elementRect = instance.element.getBoundingClientRect();
7455
+ const computedStyle = window.getComputedStyle(instance.element);
7456
+ return {
7457
+ ...instance,
7458
+ bounds: {
7459
+ x: elementRect.left,
7460
+ y: elementRect.top,
7461
+ width: elementRect.width,
7462
+ height: elementRect.height,
7463
+ borderRadius: computedStyle.borderRadius || "0px",
7464
+ transform: stripTranslateFromTransform(instance.element)
7465
+ }
7466
+ };
7467
+ });
7468
+ });
6239
7469
  const dragVisible = createMemo(() => theme().dragBox.enabled && isRendererActive() && isDraggingBeyondThreshold());
6240
7470
  const labelVariant = createMemo(() => isCopying() ? "processing" : "hover");
6241
7471
  const labelVisible = createMemo(() => {
@@ -6245,11 +7475,8 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6245
7475
  if (successLabels().length > 0) return false;
6246
7476
  return isRendererActive() && !isDragging() && Boolean(targetElement());
6247
7477
  });
6248
- const progressVisible = createMemo(() => isCopying() && showProgressIndicator() && hasValidMousePosition());
6249
- const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging() && !isTouchMode());
6250
- const inputVisible = createMemo(() => theme().inputOverlay.enabled && isInputMode());
7478
+ const crosshairVisible = createMemo(() => theme().crosshair.enabled && isRendererActive() && !isDragging() && !isTouchMode() && !isToggleFrozen());
6251
7479
  const shouldShowGrabbedBoxes = createMemo(() => theme().grabbedBoxes.enabled);
6252
- const shouldShowSuccessLabels = createMemo(() => theme().successLabels.enabled);
6253
7480
  createEffect(on(theme, (currentTheme) => {
6254
7481
  if (currentTheme.hue !== 0) {
6255
7482
  rendererRoot.style.filter = `hue-rotate(${currentTheme.hue}deg)`;
@@ -6265,43 +7492,34 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6265
7492
  get selectionBounds() {
6266
7493
  return selectionBounds();
6267
7494
  },
6268
- get dragVisible() {
6269
- return dragVisible();
7495
+ get selectionFilePath() {
7496
+ return selectionFilePath();
6270
7497
  },
6271
- get dragBounds() {
6272
- return dragBounds();
7498
+ get selectionLineNumber() {
7499
+ return selectionLineNumber();
6273
7500
  },
6274
- get grabbedBoxes() {
6275
- return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
7501
+ get selectionTagName() {
7502
+ return selectionTagName();
6276
7503
  },
6277
- get successLabels() {
6278
- return memo(() => !!shouldShowSuccessLabels())() ? successLabels() : [];
7504
+ get selectionLabelVisible() {
7505
+ return selectionLabelVisible();
6279
7506
  },
6280
- get labelVariant() {
6281
- return labelVariant();
7507
+ get selectionLabelStatus() {
7508
+ return selectionLabelStatus();
6282
7509
  },
6283
- get labelContent() {
6284
- return labelContent();
7510
+ get labelInstances() {
7511
+ return computedLabelInstances();
6285
7512
  },
6286
- get labelX() {
6287
- return labelPosition().x;
7513
+ get dragVisible() {
7514
+ return dragVisible();
6288
7515
  },
6289
- get labelY() {
6290
- return labelPosition().y;
7516
+ get dragBounds() {
7517
+ return dragBounds();
6291
7518
  },
6292
- get labelVisible() {
6293
- return labelVisible();
7519
+ get grabbedBoxes() {
7520
+ return memo(() => !!shouldShowGrabbedBoxes())() ? grabbedBoxes() : [];
6294
7521
  },
6295
7522
  labelZIndex: Z_INDEX_LABEL,
6296
- get labelShowHint() {
6297
- return mouseHasSettled();
6298
- },
6299
- get progressVisible() {
6300
- return progressVisible();
6301
- },
6302
- get progress() {
6303
- return progress();
6304
- },
6305
7523
  get mouseX() {
6306
7524
  return progressPosition().x;
6307
7525
  },
@@ -6311,26 +7529,51 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6311
7529
  get crosshairVisible() {
6312
7530
  return crosshairVisible();
6313
7531
  },
6314
- get inputVisible() {
6315
- return inputVisible();
7532
+ get inputValue() {
7533
+ return inputText();
6316
7534
  },
6317
- get inputX() {
6318
- return mouseX();
7535
+ get isInputExpanded() {
7536
+ return isInputExpanded();
6319
7537
  },
6320
- get inputY() {
6321
- return mouseY();
7538
+ get hasAgent() {
7539
+ return Boolean(options.agent?.provider);
6322
7540
  },
6323
- get inputValue() {
6324
- return inputText();
7541
+ get agentSessions() {
7542
+ return agentManager.sessions();
6325
7543
  },
7544
+ onAbortSession: (sessionId) => agentManager.abortSession(sessionId),
6326
7545
  onInputChange: handleInputChange,
6327
- onInputSubmit: handleInputSubmit,
7546
+ onInputSubmit: () => void handleInputSubmit(),
6328
7547
  onInputCancel: handleInputCancel,
7548
+ onToggleExpand: handleToggleExpand,
7549
+ get nativeSelectionCursorVisible() {
7550
+ return hasNativeSelection();
7551
+ },
7552
+ get nativeSelectionCursorX() {
7553
+ return nativeSelectionCursorX();
7554
+ },
7555
+ get nativeSelectionCursorY() {
7556
+ return nativeSelectionCursorY();
7557
+ },
7558
+ get nativeSelectionTagName() {
7559
+ return nativeSelectionTagName();
7560
+ },
7561
+ get nativeSelectionComponentName() {
7562
+ return nativeSelectionComponentName();
7563
+ },
7564
+ get nativeSelectionBounds() {
7565
+ return nativeSelectionBounds();
7566
+ },
7567
+ onNativeSelectionCopy: () => void handleNativeSelectionCopy(),
7568
+ onNativeSelectionEnter: handleNativeSelectionEnter,
6329
7569
  get theme() {
6330
7570
  return theme();
6331
7571
  }
6332
7572
  }), rendererRoot);
6333
7573
  }
7574
+ if (options.agent?.provider) {
7575
+ agentManager.tryResumeSessions();
7576
+ }
6334
7577
  const copyElementAPI = async (elements) => {
6335
7578
  const elementsArray = Array.isArray(elements) ? elements : [elements];
6336
7579
  if (elementsArray.length === 0) return false;
@@ -6355,6 +7598,7 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6355
7598
  return {
6356
7599
  activate: () => {
6357
7600
  if (!isActivated()) {
7601
+ setIsToggleMode(true);
6358
7602
  activateRenderer();
6359
7603
  }
6360
7604
  },
@@ -6367,11 +7611,15 @@ ${plainTextContentOnly}` : plainTextContentOnly;
6367
7611
  if (isActivated()) {
6368
7612
  deactivateRenderer();
6369
7613
  } else {
7614
+ setIsToggleMode(true);
6370
7615
  activateRenderer();
6371
7616
  }
6372
7617
  },
6373
7618
  isActive: () => isActivated(),
6374
- dispose: dispose2,
7619
+ dispose: () => {
7620
+ hasInited = false;
7621
+ dispose2();
7622
+ },
6375
7623
  copyElement: copyElementAPI,
6376
7624
  getState: getStateAPI,
6377
7625
  updateTheme: (partialTheme) => {
@@ -6448,9 +7696,9 @@ bippy/dist/source.js:
6448
7696
 
6449
7697
  exports.DEFAULT_THEME = DEFAULT_THEME;
6450
7698
  exports.Ee = Ee;
6451
- exports.formatStack = formatStack;
7699
+ exports.formatElementInfo = formatElementInfo;
7700
+ exports.generateSnippet = generateSnippet;
6452
7701
  exports.getFileName = getFileName;
6453
- exports.getHTMLPreview = getHTMLPreview;
6454
7702
  exports.getNearestComponentName = getNearestComponentName;
6455
7703
  exports.getStack = getStack;
6456
7704
  exports.init = init;