made-refine 0.2.1-beta.2 → 0.2.3

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.
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  "use client";
2
2
 
3
3
  // src/provider.tsx
4
- import * as React7 from "react";
4
+ import * as React8 from "react";
5
5
 
6
6
  // src/portal-container.tsx
7
7
  import * as React from "react";
8
8
 
9
9
  // dist/styles.css
10
- var styles_default = '/*! tailwindcss v4.1.18 | 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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--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-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@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-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--leading-relaxed:1.625;--radius-sm:calc(.5rem - 4px);--radius-md:calc(.5rem - 2px);--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-xl:24px;--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-border:#e6e6e6;--color-ring:#262626;--color-background:#fff;--color-foreground:#171717;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary-foreground:#171717;--color-destructive:#ef4444;--color-destructive-foreground:#fafafa;--color-muted:#f2f2f2;--color-muted-foreground:#737373;--color-popover-foreground:#171717}}@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}:root,:host{color-scheme:light;color:var(--color-foreground)}@media (prefers-color-scheme:dark){:root,:host(:not([data-theme])),:host([data-theme=system]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}}:host([data-theme=dark]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:var(--color-background);--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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;border-color:var(--color-border)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-1\\/2{top:50%}.left-1\\.5{left:calc(var(--spacing)*1.5)}.left-1\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.z-\\[99990\\]{z-index:99990}.z-\\[99991\\]{z-index:99991}.z-\\[99998\\]{z-index:99998}.z-\\[99999\\]{z-index:99999}.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-4{margin:calc(var(--spacing)*4)}.mx-0\\.5{margin-inline:calc(var(--spacing)*.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.my-0\\.5{margin-block:calc(var(--spacing)*.5)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2\\.5{margin-top:calc(var(--spacing)*2.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0{margin-left:calc(var(--spacing)*0)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.size-1{width:calc(var(--spacing)*1);height:calc(var(--spacing)*1)}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-full{width:100%;height:100%}.h-0\\.5{height:calc(var(--spacing)*.5)}.h-2{height:calc(var(--spacing)*2)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-\\[150px\\]{height:150px}.h-auto{height:auto}.h-fit{height:fit-content}.h-full{height:100%}.max-h-0{max-height:calc(var(--spacing)*0)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\\[220px\\]{max-height:220px}.max-h-\\[240px\\]{max-height:240px}.min-h-\\[18px\\]{min-height:18px}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-14{width:calc(var(--spacing)*14)}.w-\\[1\\.5px\\]{width:1.5px}.w-\\[60px\\]{width:60px}.w-\\[68px\\]{width:68px}.w-\\[200px\\]{width:200px}.w-\\[260px\\]{width:260px}.w-\\[280px\\]{width:280px}.w-\\[340px\\]{width:340px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-0{max-width:calc(var(--spacing)*0)}.max-w-\\[200px\\]{max-width:200px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\\[20px\\]{min-width:20px}.min-w-\\[100px\\]{min-width:100px}.min-w-\\[120px\\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-\\(--transform-origin\\){transform-origin:var(--transform-origin)}.-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)}.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-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.\\[appearance\\:textfield\\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-evenly{justify-content:space-evenly}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-\\[2px\\]{gap:2px}.gap-\\[4px\\]{gap:4px}:where(.space-y-1\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\\[8px\\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-tl{border-top-left-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.\\[border-top-style\\:solid\\]{border-top-style:solid}.\\[border-right-style\\:dashed\\]{border-right-style:dashed}.\\[border-bottom-style\\:dashed\\]{border-bottom-style:dashed}.\\[border-bottom-style\\:dotted\\]{border-bottom-style:dotted}.\\[border-bottom-style\\:solid\\]{border-bottom-style:solid}.\\[border-left-style\\:double\\]{border-left-style:double}.\\[border-left-style\\:solid\\]{border-left-style:solid}.border-border{border-color:var(--color-border)}.border-border\\/30{border-color:#e6e6e64d}@supports (color:color-mix(in lab, red, red)){.border-border\\/30{border-color:color-mix(in oklab,var(--color-border)30%,transparent)}}.border-border\\/50{border-color:#e6e6e680}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--color-border)50%,transparent)}}.border-foreground\\/10{border-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/10{border-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-\\[canvas\\]{background-color:canvas}.bg-background{background-color:var(--color-background)}.bg-background\\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab, red, red)){.bg-background\\/85{background-color:color-mix(in oklab,var(--color-background)85%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--color-border)}.bg-destructive{background-color:var(--color-destructive)}.bg-foreground{background-color:var(--color-foreground)}.bg-foreground\\/25{background-color:#17171740}@supports (color:color-mix(in lab, red, red)){.bg-foreground\\/25{background-color:color-mix(in oklab,var(--color-foreground)25%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\\/30{background-color:#7373734d}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/30{background-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-transparent{background-color:#0000}.fill-border{fill:var(--color-border)}.p-0{padding:calc(var(--spacing)*0)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-3\\.5{padding-block:calc(var(--spacing)*3.5)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-1\\.5{padding-top:calc(var(--spacing)*1.5)}.pt-2\\.5{padding-top:calc(var(--spacing)*2.5)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pt-\\[13px\\]{padding-top:13px}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-1\\.5{padding-right:calc(var(--spacing)*1.5)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-1\\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[7px\\]{font-size:7px}.text-\\[10px\\]{font-size:10px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-extralight{--tw-font-weight:var(--font-weight-extralight);font-weight:var(--font-weight-extralight)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.font-thin{--tw-font-weight:var(--font-weight-thin);font-weight:var(--font-weight-thin)}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--color-background)}.text-blue-500{color:var(--color-blue-500)}.text-destructive-foreground{color:var(--color-destructive-foreground)}.text-foreground{color:var(--color-foreground)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-popover-foreground{color:var(--color-popover-foreground)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.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,)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xs{--tw-shadow:0 1px var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.3\\)\\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_4px_6px_-1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[inset_0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:inset 0 0 0 1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-white{--tw-ring-color:var(--color-white)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.outline-foreground\\/10{outline-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.outline-foreground\\/10{outline-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.outline-gray-200{outline-color:var(--color-gray-200)}.outline-red-500\\/70{outline-color:#fb2c36b3}@supports (color:color-mix(in lab, red, red)){.outline-red-500\\/70{outline-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.blur{--tw-blur:blur(8px);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,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.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-\\[max-width\\,max-height\\,margin\\,opacity\\]{transition-property:max-width,max-height,margin,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[opacity\\,background-color\\,color\\]{transition-property:opacity,background-color,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[transform\\,scale\\,opacity\\]{transition-property:transform,scale,opacity;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-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.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)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-dashed{--tw-outline-style:dashed;outline-style:dashed}.outline-dotted{--tw-outline-style:dotted;outline-style:dotted}.outline-double{--tw-outline-style:double;outline-style:double}.outline-none{--tw-outline-style:none;outline-style:none}.outline-solid{--tw-outline-style:solid;outline-style:solid}.select-none{-webkit-user-select:none;user-select:none}.\\[-ms-overflow-style\\:none\\]{-ms-overflow-style:none}.\\[scrollbar-width\\:none\\]{scrollbar-width:none}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}@media (hover:hover){.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\\/pin\\:inline:is(:where(.group\\/pin):hover *){display:inline}}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--color-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.placeholder\\:text-red-400::placeholder{color:var(--color-red-400)}.focus-within\\:ring-1:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--color-ring)}.focus-within\\:outline-none:focus-within{--tw-outline-style:none;outline-style:none}.focus-within\\:ring-inset:focus-within{--tw-ring-inset:inset}@media (hover:hover){.hover\\:scale-\\[1\\.67\\]:hover{scale:1.67}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive\\/90:hover{background-color:#ef4444e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--color-destructive)90%,transparent)}}.hover\\:bg-foreground\\/80:hover{background-color:#171717cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-foreground\\/80:hover{background-color:color-mix(in oklab,var(--color-foreground)80%,transparent)}}.hover\\:bg-muted:hover{background-color:var(--color-muted)}.hover\\:bg-muted-foreground\\/10:hover{background-color:#7373731a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/10:hover{background-color:color-mix(in oklab,var(--color-muted-foreground)10%,transparent)}}.hover\\:bg-muted\\/50:hover{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/50:hover{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\\:text-foreground:hover{color:var(--color-foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\:cursor-grabbing:active{cursor:grabbing}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.disabled\\:opacity-60:disabled{opacity:.6}.data-ending-style\\:scale-90[data-ending-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-ending-style\\:opacity-0[data-ending-style]{opacity:0}.data-instant\\:transition-none[data-instant]{transition-property:none}.data-starting-style\\:scale-90[data-starting-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-starting-style\\:opacity-0[data-starting-style]{opacity:0}.data-\\[highlighted\\]\\:bg-muted[data-highlighted]{background-color:var(--color-muted)}.data-\\[highlighted\\]\\:text-foreground[data-highlighted]{color:var(--color-foreground)}@media (prefers-color-scheme:dark){.dark\\:shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\\:-outline-offset-1{outline-offset:calc(1px*-1)}.dark\\:outline-gray-300{outline-color:var(--color-gray-300)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\:\\:-webkit-inner-spin-button\\]\\:appearance-none::-webkit-inner-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-outer-spin-button\\]\\:appearance-none::-webkit-outer-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-scrollbar\\]\\:hidden::-webkit-scrollbar{display:none}}.lucide{stroke-width:1px}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,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-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-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@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-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@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-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@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}@keyframes pulse{50%{opacity:.5}}';
10
+ var styles_default = '/*! tailwindcss v4.1.18 | 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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--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-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@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-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--leading-relaxed:1.625;--radius-sm:calc(.5rem - 4px);--radius-md:calc(.5rem - 2px);--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-xl:24px;--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-border:#e6e6e6;--color-ring:#262626;--color-background:#fff;--color-foreground:#171717;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary-foreground:#171717;--color-destructive:#ef4444;--color-destructive-foreground:#fafafa;--color-muted:#f2f2f2;--color-muted-foreground:#737373;--color-popover-foreground:#171717}}@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}:root,:host{color-scheme:light;color:var(--color-foreground)}@media (prefers-color-scheme:dark){:root,:host(:not([data-theme])),:host([data-theme=system]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}}:host([data-theme=dark]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:var(--color-background);--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--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;border-color:var(--color-border)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-1\\/2{top:50%}.left-1\\.5{left:calc(var(--spacing)*1.5)}.left-1\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.z-\\[99990\\]{z-index:99990}.z-\\[99991\\]{z-index:99991}.z-\\[99998\\]{z-index:99998}.z-\\[99999\\]{z-index:99999}.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-4{margin:calc(var(--spacing)*4)}.mx-0\\.5{margin-inline:calc(var(--spacing)*.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.my-0\\.5{margin-block:calc(var(--spacing)*.5)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2\\.5{margin-top:calc(var(--spacing)*2.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0{margin-left:calc(var(--spacing)*0)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.size-1{width:calc(var(--spacing)*1);height:calc(var(--spacing)*1)}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-full{width:100%;height:100%}.h-0\\.5{height:calc(var(--spacing)*.5)}.h-2{height:calc(var(--spacing)*2)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-\\[150px\\]{height:150px}.h-auto{height:auto}.h-fit{height:fit-content}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\\[240px\\]{max-height:240px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\\[18px\\]{min-height:18px}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-14{width:calc(var(--spacing)*14)}.w-\\[1\\.5px\\]{width:1.5px}.w-\\[30px\\]{width:30px}.w-\\[60px\\]{width:60px}.w-\\[68px\\]{width:68px}.w-\\[180px\\]{width:180px}.w-\\[200px\\]{width:200px}.w-\\[260px\\]{width:260px}.w-\\[280px\\]{width:280px}.w-\\[300px\\]{width:300px}.w-\\[340px\\]{width:340px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\\[18px\\]{min-width:18px}.min-w-\\[20px\\]{min-width:20px}.min-w-\\[100px\\]{min-width:100px}.min-w-\\[120px\\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-\\(--transform-origin\\){transform-origin:var(--transform-origin)}.-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)}.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-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.\\[appearance\\:textfield\\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\\[0fr\\]{grid-template-columns:0fr}.grid-cols-\\[1fr\\]{grid-template-columns:1fr}.grid-rows-\\[0fr\\]{grid-template-rows:0fr}.grid-rows-\\[1fr\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-evenly{justify-content:space-evenly}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-\\[2px\\]{gap:2px}.gap-\\[4px\\]{gap:4px}:where(.space-y-1\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\\[6px\\]{border-radius:6px}.rounded-\\[8px\\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-tl{border-top-left-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.\\[border-top-style\\:solid\\]{border-top-style:solid}.\\[border-right-style\\:dashed\\]{border-right-style:dashed}.\\[border-bottom-style\\:dashed\\]{border-bottom-style:dashed}.\\[border-bottom-style\\:dotted\\]{border-bottom-style:dotted}.\\[border-bottom-style\\:solid\\]{border-bottom-style:solid}.\\[border-left-style\\:double\\]{border-left-style:double}.\\[border-left-style\\:solid\\]{border-left-style:solid}.border-border{border-color:var(--color-border)}.border-border\\/30{border-color:#e6e6e64d}@supports (color:color-mix(in lab, red, red)){.border-border\\/30{border-color:color-mix(in oklab,var(--color-border)30%,transparent)}}.border-border\\/50{border-color:#e6e6e680}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--color-border)50%,transparent)}}.border-foreground\\/10{border-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/10{border-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-\\[canvas\\]{background-color:canvas}.bg-background{background-color:var(--color-background)}.bg-background\\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab, red, red)){.bg-background\\/85{background-color:color-mix(in oklab,var(--color-background)85%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--color-border)}.bg-destructive{background-color:var(--color-destructive)}.bg-foreground{background-color:var(--color-foreground)}.bg-foreground\\/25{background-color:#17171740}@supports (color:color-mix(in lab, red, red)){.bg-foreground\\/25{background-color:color-mix(in oklab,var(--color-foreground)25%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\\/30{background-color:#7373734d}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/30{background-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-transparent{background-color:#0000}.fill-border{fill:var(--color-border)}.p-0{padding:calc(var(--spacing)*0)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-3\\.5{padding-block:calc(var(--spacing)*3.5)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2\\.5{padding-top:calc(var(--spacing)*2.5)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pt-\\[13px\\]{padding-top:13px}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-1\\.5{padding-right:calc(var(--spacing)*1.5)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-1\\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[7px\\]{font-size:7px}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-extralight{--tw-font-weight:var(--font-weight-extralight);font-weight:var(--font-weight-extralight)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.font-thin{--tw-font-weight:var(--font-weight-thin);font-weight:var(--font-weight-thin)}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--color-background)}.text-blue-500{color:var(--color-blue-500)}.text-destructive-foreground{color:var(--color-destructive-foreground)}.text-foreground{color:var(--color-foreground)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-popover-foreground{color:var(--color-popover-foreground)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.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,)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xs{--tw-shadow:0 1px var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.3\\)\\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_4px_6px_-1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[inset_0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:inset 0 0 0 1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-white{--tw-ring-color:var(--color-white)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.outline-border{outline-color:var(--color-border)}.outline-foreground\\/10{outline-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.outline-foreground\\/10{outline-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.outline-red-500\\/70{outline-color:#fb2c36b3}@supports (color:color-mix(in lab, red, red)){.outline-red-500\\/70{outline-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.blur{--tw-blur:blur(8px);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,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.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-\\[color\\,background-color\\]{transition-property:color,background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[opacity\\,background-color\\,color\\]{transition-property:opacity,background-color,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[transform\\,scale\\,opacity\\]{transition-property:transform,scale,opacity;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-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.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)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-dashed{--tw-outline-style:dashed;outline-style:dashed}.outline-dotted{--tw-outline-style:dotted;outline-style:dotted}.outline-double{--tw-outline-style:double;outline-style:double}.outline-none{--tw-outline-style:none;outline-style:none}.outline-solid{--tw-outline-style:solid;outline-style:solid}.select-none{-webkit-user-select:none;user-select:none}.\\[-ms-overflow-style\\:none\\]{-ms-overflow-style:none}.\\[scrollbar-width\\:none\\]{scrollbar-width:none}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}@media (hover:hover){.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\\/pin\\:inline:is(:where(.group\\/pin):hover *){display:inline}}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--color-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.placeholder\\:text-red-400::placeholder{color:var(--color-red-400)}.focus-within\\:ring-1:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--color-ring)}.focus-within\\:outline-none:focus-within{--tw-outline-style:none;outline-style:none}.focus-within\\:ring-inset:focus-within{--tw-ring-inset:inset}@media (hover:hover){.hover\\:scale-\\[1\\.67\\]:hover{scale:1.67}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive\\/90:hover{background-color:#ef4444e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--color-destructive)90%,transparent)}}.hover\\:bg-foreground\\/80:hover{background-color:#171717cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-foreground\\/80:hover{background-color:color-mix(in oklab,var(--color-foreground)80%,transparent)}}.hover\\:bg-muted:hover{background-color:var(--color-muted)}.hover\\:bg-muted-foreground\\/10:hover{background-color:#7373731a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/10:hover{background-color:color-mix(in oklab,var(--color-muted-foreground)10%,transparent)}}.hover\\:bg-muted\\/50:hover{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/50:hover{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.hover\\:bg-muted\\/80:hover{background-color:#f2f2f2cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/80:hover{background-color:color-mix(in oklab,var(--color-muted)80%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\\:text-foreground:hover{color:var(--color-foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\:cursor-grabbing:active{cursor:grabbing}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.disabled\\:opacity-60:disabled{opacity:.6}.data-ending-style\\:scale-90[data-ending-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-ending-style\\:opacity-0[data-ending-style]{opacity:0}.data-instant\\:transition-none[data-instant]{transition-property:none}.data-starting-style\\:scale-90[data-starting-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-starting-style\\:opacity-0[data-starting-style]{opacity:0}.data-\\[highlighted\\]\\:bg-muted[data-highlighted]{background-color:var(--color-muted)}.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.data-\\[highlighted\\]\\:text-foreground[data-highlighted]{color:var(--color-foreground)}@media (prefers-color-scheme:dark){.dark\\:shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\\:-outline-offset-1{outline-offset:calc(1px*-1)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\:\\:-webkit-inner-spin-button\\]\\:appearance-none::-webkit-inner-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-outer-spin-button\\]\\:appearance-none::-webkit-outer-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-scrollbar\\]\\:hidden::-webkit-scrollbar{display:none}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none;animation:none}}.lucide{stroke-width:1px}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,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-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-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@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-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@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-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@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}@keyframes pulse{50%{opacity:.5}}';
11
11
 
12
12
  // src/portal-container.tsx
13
13
  import { jsx } from "react/jsx-runtime";
@@ -36,7 +36,7 @@ function PortalContainerProvider({ children }) {
36
36
  const root = document.createElement("div");
37
37
  root.setAttribute("data-direct-edit-root", "");
38
38
  shadow.appendChild(root);
39
- document.body.appendChild(host);
39
+ document.documentElement.appendChild(host);
40
40
  setContainer(root);
41
41
  return () => {
42
42
  host.remove();
@@ -78,6 +78,13 @@ function clamp(value, min, max) {
78
78
  if (max < min) return min;
79
79
  return Math.max(min, Math.min(max, value));
80
80
  }
81
+ function isInputFocused() {
82
+ let active = document.activeElement;
83
+ while (active?.shadowRoot?.activeElement) {
84
+ active = active.shadowRoot.activeElement;
85
+ }
86
+ return active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
87
+ }
81
88
  function getComputedStyles(element) {
82
89
  const computed = window.getComputedStyle(element);
83
90
  return {
@@ -2734,6 +2741,7 @@ function useSessionManager({
2734
2741
  borderStyleControlPreference: prev.borderStyleControlPreference,
2735
2742
  comments: prev.comments,
2736
2743
  activeCommentId: prev.activeCommentId,
2744
+ canvas: prev.canvas,
2737
2745
  textEditingElement: null
2738
2746
  }));
2739
2747
  }, [pushUndo, saveCurrentToSession]);
@@ -2868,6 +2876,7 @@ function useSessionManager({
2868
2876
  borderStyleControlPreference: prev.borderStyleControlPreference,
2869
2877
  comments: prev.comments,
2870
2878
  activeCommentId: prev.activeCommentId,
2879
+ canvas: prev.canvas,
2871
2880
  textEditingElement: null
2872
2881
  }));
2873
2882
  } else {
@@ -3066,6 +3075,7 @@ function useSessionManager({
3066
3075
  borderStyleControlPreference: prev.borderStyleControlPreference,
3067
3076
  comments: prev.comments,
3068
3077
  activeCommentId: prev.activeCommentId,
3078
+ canvas: prev.canvas,
3069
3079
  textEditingElement: null
3070
3080
  }));
3071
3081
  },
@@ -3279,8 +3289,8 @@ function useTextAndComments({
3279
3289
  const locator = getElementLocator(element);
3280
3290
  const rect = element.getBoundingClientRect();
3281
3291
  const relativePosition = {
3282
- x: clickPosition.x - rect.left,
3283
- y: clickPosition.y - rect.top
3292
+ x: rect.width > 0 ? (clickPosition.x - rect.left) / rect.width : 0,
3293
+ y: rect.height > 0 ? (clickPosition.y - rect.top) / rect.height : 0
3284
3294
  };
3285
3295
  const id = `comment-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
3286
3296
  const comment = {
@@ -3293,11 +3303,14 @@ function useTextAndComments({
3293
3303
  createdAt: Date.now(),
3294
3304
  replies: []
3295
3305
  };
3296
- setState((prev) => ({
3297
- ...prev,
3298
- comments: [...prev.comments, comment],
3299
- activeCommentId: id
3300
- }));
3306
+ setState((prev) => {
3307
+ const filtered = prev.activeCommentId ? prev.comments.filter((c) => c.id !== prev.activeCommentId || c.text.trim().length > 0) : prev.comments;
3308
+ return {
3309
+ ...prev,
3310
+ comments: [...filtered, comment],
3311
+ activeCommentId: id
3312
+ };
3313
+ });
3301
3314
  }, []);
3302
3315
  const updateCommentText = React4.useCallback((id, text) => {
3303
3316
  setState((prev) => ({
@@ -3720,11 +3733,11 @@ async function sendCommentToAgent(comment) {
3720
3733
 
3721
3734
  // src/use-agent-comms.ts
3722
3735
  function useAgentComms({ stateRef, sessionEditsRef, getSessionItems }) {
3723
- const canSendEditToAgent = React5.useCallback((snapshot) => {
3736
+ const canSendEditToAgent = React5.useCallback((snapshot2) => {
3724
3737
  const current = stateRef.current;
3725
- const selectedElement = snapshot?.selectedElement ?? current.selectedElement;
3726
- const elementInfo = snapshot?.elementInfo ?? current.elementInfo;
3727
- const pendingStyles = snapshot?.pendingStyles ?? current.pendingStyles;
3738
+ const selectedElement = snapshot2?.selectedElement ?? current.selectedElement;
3739
+ const elementInfo = snapshot2?.elementInfo ?? current.elementInfo;
3740
+ const pendingStyles = snapshot2?.pendingStyles ?? current.pendingStyles;
3728
3741
  if (!selectedElement || !elementInfo) return false;
3729
3742
  const sessionEdit = sessionEditsRef.current.get(selectedElement);
3730
3743
  const hasPendingStyles = Object.keys(pendingStyles).length > 0;
@@ -3847,7 +3860,11 @@ function useKeyboardShortcuts({
3847
3860
  commitTextEditing,
3848
3861
  startTextEditing,
3849
3862
  closePanel,
3850
- setState
3863
+ setState,
3864
+ toggleCanvas,
3865
+ setCanvasZoom,
3866
+ fitCanvasToViewport,
3867
+ zoomCanvasTo100
3851
3868
  }) {
3852
3869
  React6.useEffect(() => {
3853
3870
  function handleToggle(e) {
@@ -3869,15 +3886,13 @@ function useKeyboardShortcuts({
3869
3886
  return;
3870
3887
  }
3871
3888
  if (e.key === "C" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive) {
3872
- const active = document.activeElement;
3873
- const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
3874
- if (!isInput) {
3889
+ if (!isInputFocused()) {
3875
3890
  e.preventDefault();
3876
3891
  setState((prev) => {
3877
3892
  let comments = prev.comments;
3878
3893
  if (prev.activeCommentId) {
3879
- const active2 = comments.find((c) => c.id === prev.activeCommentId);
3880
- if (active2 && active2.text === "") {
3894
+ const active = comments.find((c) => c.id === prev.activeCommentId);
3895
+ if (active && active.text === "") {
3881
3896
  comments = comments.filter((c) => c.id !== prev.activeCommentId);
3882
3897
  }
3883
3898
  }
@@ -3891,19 +3906,44 @@ function useKeyboardShortcuts({
3891
3906
  return;
3892
3907
  }
3893
3908
  }
3909
+ if (e.key === "Z" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive) {
3910
+ if (!isInputFocused()) {
3911
+ e.preventDefault();
3912
+ toggleCanvas();
3913
+ return;
3914
+ }
3915
+ }
3916
+ if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey && s.canvas?.active) {
3917
+ if (e.code === "Digit0" || e.key === "0") {
3918
+ e.preventDefault();
3919
+ fitCanvasToViewport();
3920
+ return;
3921
+ }
3922
+ if (e.code === "Digit1" || e.key === "1") {
3923
+ e.preventDefault();
3924
+ zoomCanvasTo100();
3925
+ return;
3926
+ }
3927
+ if (e.code === "Equal" || e.key === "=") {
3928
+ e.preventDefault();
3929
+ setCanvasZoom(Math.min(5, (s.canvas?.zoom ?? 1) * 1.1));
3930
+ return;
3931
+ }
3932
+ if (e.code === "Minus" || e.key === "-") {
3933
+ e.preventDefault();
3934
+ setCanvasZoom(Math.max(0.1, (s.canvas?.zoom ?? 1) / 1.1));
3935
+ return;
3936
+ }
3937
+ }
3894
3938
  if (e.key === "A" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive && s.selectedElement) {
3895
- const active = document.activeElement;
3896
- const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
3897
- if (!isInput) {
3939
+ if (!isInputFocused()) {
3898
3940
  e.preventDefault();
3899
3941
  toggleFlexLayout();
3900
3942
  return;
3901
3943
  }
3902
3944
  }
3903
3945
  if (e.key === "Enter" && s.editModeActive && !s.textEditingElement && s.selectedElement) {
3904
- const active = document.activeElement;
3905
- const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
3906
- if (!isInput && isTextElement(s.selectedElement)) {
3946
+ if (!isInputFocused() && isTextElement(s.selectedElement)) {
3907
3947
  e.preventDefault();
3908
3948
  startTextEditing(s.selectedElement);
3909
3949
  return;
@@ -3934,22 +3974,339 @@ function useKeyboardShortcuts({
3934
3974
  }
3935
3975
  window.addEventListener("keydown", handleKeyDown);
3936
3976
  return () => window.removeEventListener("keydown", handleKeyDown);
3937
- }, [closePanel, toggleEditMode, toggleFlexLayout, undo, commitTextEditing, startTextEditing]);
3977
+ }, [closePanel, toggleEditMode, toggleFlexLayout, undo, commitTextEditing, startTextEditing, toggleCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100]);
3978
+ }
3979
+
3980
+ // src/use-canvas.ts
3981
+ import * as React7 from "react";
3982
+
3983
+ // src/canvas-store.ts
3984
+ import { useSyncExternalStore } from "react";
3985
+ var DEFAULT = { active: false, zoom: 1, panX: 0, panY: 0 };
3986
+ var snapshot = DEFAULT;
3987
+ var listeners = /* @__PURE__ */ new Set();
3988
+ var ownerCount = 0;
3989
+ var bodyOffset = { x: 0, y: 0 };
3990
+ function getBodyOffset() {
3991
+ return bodyOffset;
3992
+ }
3993
+ function setBodyOffset(o) {
3994
+ bodyOffset = o;
3995
+ }
3996
+ function getCanvasSnapshot() {
3997
+ return snapshot;
3998
+ }
3999
+ function setCanvasSnapshot(next) {
4000
+ snapshot = next;
4001
+ listeners.forEach((cb) => cb());
4002
+ }
4003
+ function registerCanvasStoreOwner() {
4004
+ ownerCount += 1;
4005
+ if (ownerCount > 1 && (typeof process === "undefined" || process.env.NODE_ENV !== "test")) {
4006
+ console.warn("[made-refine] multiple DirectEditProvider instances share canvas-store globals");
4007
+ }
4008
+ return () => {
4009
+ ownerCount = Math.max(0, ownerCount - 1);
4010
+ };
4011
+ }
4012
+ function subscribe(cb) {
4013
+ listeners.add(cb);
4014
+ return () => {
4015
+ listeners.delete(cb);
4016
+ };
4017
+ }
4018
+ function useCanvasSnapshot() {
4019
+ return useSyncExternalStore(subscribe, getCanvasSnapshot, () => DEFAULT);
4020
+ }
4021
+
4022
+ // src/use-canvas.ts
4023
+ var MIN_ZOOM = 0.1;
4024
+ var MAX_ZOOM = 5;
4025
+ var ZOOM_SENSITIVITY = 0.0145;
4026
+ var LINE_HEIGHT_PX = 40;
4027
+ var PAGE_HEIGHT_PX = 800;
4028
+ function normalizeWheelDelta(e) {
4029
+ let { deltaX, deltaY } = e;
4030
+ if (e.deltaMode === 1) {
4031
+ deltaX *= LINE_HEIGHT_PX;
4032
+ deltaY *= LINE_HEIGHT_PX;
4033
+ } else if (e.deltaMode === 2) {
4034
+ deltaX *= PAGE_HEIGHT_PX;
4035
+ deltaY *= PAGE_HEIGHT_PX;
4036
+ }
4037
+ return { deltaX, deltaY };
4038
+ }
4039
+ var PAN_MARGIN = 0.1;
4040
+ function clampPan(zoom, panX, panY, bodyW, bodyH) {
4041
+ const vw = window.innerWidth;
4042
+ const vh = window.innerHeight;
4043
+ const minPanX = PAN_MARGIN * vw / zoom - bodyW;
4044
+ const maxPanX = (1 - PAN_MARGIN) * vw / zoom;
4045
+ const minPanY = PAN_MARGIN * vh / zoom - bodyH;
4046
+ const maxPanY = (1 - PAN_MARGIN) * vh / zoom;
4047
+ return {
4048
+ panX: Math.max(minPanX, Math.min(maxPanX, panX)),
4049
+ panY: Math.max(minPanY, Math.min(maxPanY, panY))
4050
+ };
4051
+ }
4052
+ function useCanvas({ stateRef, setState }) {
4053
+ React7.useEffect(() => registerCanvasStoreOwner(), []);
4054
+ const canvasRef = React7.useRef({ active: false, zoom: 1, panX: 0, panY: 0 });
4055
+ const savedScrollRef = React7.useRef({ x: 0, y: 0 });
4056
+ const savedBodyOverflowRef = React7.useRef("");
4057
+ const savedHtmlOverflowRef = React7.useRef("");
4058
+ const savedHtmlBgColorRef = React7.useRef("");
4059
+ const savedBodyDimensionsRef = React7.useRef({ width: 0, height: 0 });
4060
+ const rafIdRef = React7.useRef(null);
4061
+ const rafPendingRef = React7.useRef(false);
4062
+ const spaceHeldRef = React7.useRef(false);
4063
+ const isDraggingRef = React7.useRef(false);
4064
+ const dragStartRef = React7.useRef({ x: 0, y: 0, panX: 0, panY: 0 });
4065
+ const applyTransform = React7.useCallback((zoom, panX, panY) => {
4066
+ document.body.style.transformOrigin = "0 0";
4067
+ document.body.style.transform = `scale(${zoom}) translate(${panX}px, ${panY}px)`;
4068
+ }, []);
4069
+ const dispatchCanvasChange = React7.useCallback(() => {
4070
+ window.dispatchEvent(new Event("direct-edit-canvas-change"));
4071
+ }, []);
4072
+ const readBodyOffset = React7.useCallback(() => {
4073
+ const bodyStyle = getComputedStyle(document.body);
4074
+ return {
4075
+ x: parseFloat(bodyStyle.marginLeft) || 0,
4076
+ y: parseFloat(bodyStyle.marginTop) || 0
4077
+ };
4078
+ }, []);
4079
+ const updateBodyOffset = React7.useCallback(() => {
4080
+ const next = readBodyOffset();
4081
+ const prev = getBodyOffset();
4082
+ if (prev.x === next.x && prev.y === next.y) return false;
4083
+ setBodyOffset(next);
4084
+ return true;
4085
+ }, [readBodyOffset]);
4086
+ const cancelPendingRaf = React7.useCallback(() => {
4087
+ if (rafIdRef.current !== null) {
4088
+ cancelAnimationFrame(rafIdRef.current);
4089
+ rafIdRef.current = null;
4090
+ rafPendingRef.current = false;
4091
+ }
4092
+ }, []);
4093
+ const updateCanvas = React7.useCallback((zoom, panX, panY) => {
4094
+ const dims = savedBodyDimensionsRef.current;
4095
+ const bodyW = dims.width || window.innerWidth;
4096
+ const bodyH = dims.height || window.innerHeight;
4097
+ const clamped = clampPan(zoom, panX, panY, bodyW, bodyH);
4098
+ canvasRef.current = { ...canvasRef.current, zoom, panX: clamped.panX, panY: clamped.panY };
4099
+ setCanvasSnapshot(canvasRef.current);
4100
+ applyTransform(zoom, clamped.panX, clamped.panY);
4101
+ dispatchCanvasChange();
4102
+ if (!rafPendingRef.current) {
4103
+ rafPendingRef.current = true;
4104
+ rafIdRef.current = requestAnimationFrame(() => {
4105
+ rafPendingRef.current = false;
4106
+ rafIdRef.current = null;
4107
+ const s = canvasRef.current;
4108
+ setState((prev) => ({
4109
+ ...prev,
4110
+ canvas: { active: s.active, zoom: s.zoom, panX: s.panX, panY: s.panY }
4111
+ }));
4112
+ });
4113
+ }
4114
+ }, [applyTransform, dispatchCanvasChange, setState]);
4115
+ const enterCanvas = React7.useCallback(() => {
4116
+ const scrollX = window.scrollX;
4117
+ const scrollY = window.scrollY;
4118
+ savedScrollRef.current = { x: scrollX, y: scrollY };
4119
+ savedBodyOverflowRef.current = document.body.style.overflow;
4120
+ savedHtmlOverflowRef.current = document.documentElement.style.overflow;
4121
+ savedHtmlBgColorRef.current = document.documentElement.style.backgroundColor;
4122
+ savedBodyDimensionsRef.current = {
4123
+ width: document.body.scrollWidth,
4124
+ height: document.body.scrollHeight
4125
+ };
4126
+ const existingTransform = document.body.style.transform;
4127
+ if (existingTransform && existingTransform !== "none" && existingTransform !== "") {
4128
+ console.warn("[made-refine] canvas mode: overriding existing body transform:", existingTransform);
4129
+ }
4130
+ window.scrollTo(0, 0);
4131
+ updateBodyOffset();
4132
+ document.body.style.overflow = "hidden";
4133
+ document.documentElement.style.overflow = "hidden";
4134
+ document.documentElement.style.backgroundColor = "#F5F5F5";
4135
+ const initialPanX = -scrollX;
4136
+ const initialPanY = -scrollY;
4137
+ applyTransform(1, initialPanX, initialPanY);
4138
+ canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
4139
+ setCanvasSnapshot(canvasRef.current);
4140
+ setState((prev) => ({
4141
+ ...prev,
4142
+ canvas: { active: true, zoom: 1, panX: initialPanX, panY: initialPanY }
4143
+ }));
4144
+ dispatchCanvasChange();
4145
+ }, [applyTransform, dispatchCanvasChange, setState, updateBodyOffset]);
4146
+ const exitCanvas = React7.useCallback(() => {
4147
+ cancelPendingRaf();
4148
+ document.body.style.transform = "";
4149
+ document.body.style.transformOrigin = "";
4150
+ document.body.style.overflow = savedBodyOverflowRef.current;
4151
+ document.documentElement.style.overflow = savedHtmlOverflowRef.current;
4152
+ document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
4153
+ document.body.style.cursor = "";
4154
+ window.scrollTo(savedScrollRef.current.x, savedScrollRef.current.y);
4155
+ setBodyOffset({ x: 0, y: 0 });
4156
+ canvasRef.current = { active: false, zoom: 1, panX: 0, panY: 0 };
4157
+ setCanvasSnapshot(canvasRef.current);
4158
+ setState((prev) => ({
4159
+ ...prev,
4160
+ canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
4161
+ }));
4162
+ dispatchCanvasChange();
4163
+ }, [cancelPendingRaf, dispatchCanvasChange, setState]);
4164
+ const toggleCanvas = React7.useCallback(() => {
4165
+ if (canvasRef.current.active) {
4166
+ exitCanvas();
4167
+ } else {
4168
+ enterCanvas();
4169
+ }
4170
+ }, [enterCanvas, exitCanvas]);
4171
+ const setCanvasZoom = React7.useCallback((zoom) => {
4172
+ const c = canvasRef.current;
4173
+ if (!c.active) return;
4174
+ const clampedZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
4175
+ updateCanvas(clampedZoom, c.panX, c.panY);
4176
+ }, [updateCanvas]);
4177
+ const fitCanvasToViewport = React7.useCallback(() => {
4178
+ const c = canvasRef.current;
4179
+ if (!c.active) return;
4180
+ const bodyWidth = savedBodyDimensionsRef.current.width || window.innerWidth;
4181
+ const bodyHeight = savedBodyDimensionsRef.current.height || window.innerHeight;
4182
+ const scaleX = window.innerWidth / bodyWidth;
4183
+ const scaleY = window.innerHeight / bodyHeight;
4184
+ const zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, Math.min(scaleX, scaleY) * 0.9));
4185
+ const panX = (window.innerWidth / zoom - bodyWidth) / 2;
4186
+ const panY = (window.innerHeight / zoom - bodyHeight) / 2;
4187
+ updateCanvas(zoom, panX, panY);
4188
+ }, [updateCanvas]);
4189
+ const zoomCanvasTo100 = React7.useCallback(() => {
4190
+ const c = canvasRef.current;
4191
+ if (!c.active) return;
4192
+ updateCanvas(1, 0, 0);
4193
+ }, [updateCanvas]);
4194
+ React7.useEffect(() => {
4195
+ function handleWheel(e) {
4196
+ const c = canvasRef.current;
4197
+ if (!c.active) return;
4198
+ e.preventDefault();
4199
+ const { deltaX, deltaY } = normalizeWheelDelta(e);
4200
+ if (e.ctrlKey || e.metaKey) {
4201
+ const zoomFactor = Math.exp(-deltaY * ZOOM_SENSITIVITY);
4202
+ const oldZoom = c.zoom;
4203
+ const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * zoomFactor));
4204
+ const cx = e.clientX;
4205
+ const cy = e.clientY;
4206
+ const bo = getBodyOffset();
4207
+ const newPanX = c.panX + (cx - bo.x) * (1 / newZoom - 1 / oldZoom);
4208
+ const newPanY = c.panY + (cy - bo.y) * (1 / newZoom - 1 / oldZoom);
4209
+ updateCanvas(newZoom, newPanX, newPanY);
4210
+ } else {
4211
+ const newPanX = c.panX - deltaX / c.zoom;
4212
+ const newPanY = c.panY - deltaY / c.zoom;
4213
+ updateCanvas(c.zoom, newPanX, newPanY);
4214
+ }
4215
+ }
4216
+ window.addEventListener("wheel", handleWheel, { passive: false });
4217
+ return () => window.removeEventListener("wheel", handleWheel);
4218
+ }, [updateCanvas]);
4219
+ React7.useEffect(() => {
4220
+ function handleResize() {
4221
+ if (!canvasRef.current.active) return;
4222
+ if (updateBodyOffset()) {
4223
+ dispatchCanvasChange();
4224
+ }
4225
+ }
4226
+ window.addEventListener("resize", handleResize);
4227
+ return () => window.removeEventListener("resize", handleResize);
4228
+ }, [dispatchCanvasChange, updateBodyOffset]);
4229
+ React7.useEffect(() => {
4230
+ function handleKeyDown(e) {
4231
+ if (e.code !== "Space" || e.repeat) return;
4232
+ if (!canvasRef.current.active) return;
4233
+ if (isInputFocused()) return;
4234
+ spaceHeldRef.current = true;
4235
+ if (!isDraggingRef.current) {
4236
+ document.body.style.cursor = "grab";
4237
+ }
4238
+ e.preventDefault();
4239
+ }
4240
+ function handleKeyUp(e) {
4241
+ if (e.code !== "Space") return;
4242
+ if (!canvasRef.current.active) return;
4243
+ spaceHeldRef.current = false;
4244
+ if (!isDraggingRef.current) {
4245
+ document.body.style.cursor = "";
4246
+ }
4247
+ }
4248
+ window.addEventListener("keydown", handleKeyDown, true);
4249
+ window.addEventListener("keyup", handleKeyUp, true);
4250
+ return () => {
4251
+ window.removeEventListener("keydown", handleKeyDown, true);
4252
+ window.removeEventListener("keyup", handleKeyUp, true);
4253
+ };
4254
+ }, []);
4255
+ React7.useEffect(() => {
4256
+ function handlePointerDown(e) {
4257
+ const c = canvasRef.current;
4258
+ if (!c.active) return;
4259
+ const isMiddleMouse = e.button === 1;
4260
+ const isSpaceDrag = spaceHeldRef.current && e.button === 0;
4261
+ if (!isMiddleMouse && !isSpaceDrag) return;
4262
+ e.preventDefault();
4263
+ isDraggingRef.current = true;
4264
+ dragStartRef.current = { x: e.clientX, y: e.clientY, panX: c.panX, panY: c.panY };
4265
+ document.body.style.cursor = "grabbing";
4266
+ const dragAbort = new AbortController();
4267
+ const opts = { signal: dragAbort.signal };
4268
+ function endDrag() {
4269
+ isDraggingRef.current = false;
4270
+ document.body.style.cursor = spaceHeldRef.current ? "grab" : "";
4271
+ dragAbort.abort();
4272
+ }
4273
+ window.addEventListener("pointermove", (moveE) => {
4274
+ const current = canvasRef.current;
4275
+ const dx = (moveE.clientX - dragStartRef.current.x) / current.zoom;
4276
+ const dy = (moveE.clientY - dragStartRef.current.y) / current.zoom;
4277
+ updateCanvas(current.zoom, dragStartRef.current.panX + dx, dragStartRef.current.panY + dy);
4278
+ }, opts);
4279
+ window.addEventListener("pointerup", endDrag, opts);
4280
+ window.addEventListener("pointercancel", endDrag, opts);
4281
+ window.addEventListener("blur", endDrag, opts);
4282
+ }
4283
+ window.addEventListener("pointerdown", handlePointerDown, true);
4284
+ return () => window.removeEventListener("pointerdown", handlePointerDown, true);
4285
+ }, [updateCanvas]);
4286
+ React7.useEffect(() => {
4287
+ return () => {
4288
+ cancelPendingRaf();
4289
+ if (canvasRef.current.active) {
4290
+ exitCanvas();
4291
+ }
4292
+ };
4293
+ }, [cancelPendingRaf, exitCanvas]);
4294
+ return { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 };
3938
4295
  }
3939
4296
 
3940
4297
  // src/provider.tsx
3941
4298
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
3942
- var DirectEditStateContext = React7.createContext(null);
3943
- var DirectEditActionsContext = React7.createContext(null);
4299
+ var DirectEditStateContext = React8.createContext(null);
4300
+ var DirectEditActionsContext = React8.createContext(null);
3944
4301
  function useDirectEditState() {
3945
- const context = React7.useContext(DirectEditStateContext);
4302
+ const context = React8.useContext(DirectEditStateContext);
3946
4303
  if (!context) {
3947
4304
  throw new Error("useDirectEditState must be used within a DirectEditProvider");
3948
4305
  }
3949
4306
  return context;
3950
4307
  }
3951
4308
  function useDirectEditActions() {
3952
- const context = React7.useContext(DirectEditActionsContext);
4309
+ const context = React8.useContext(DirectEditActionsContext);
3953
4310
  if (!context) {
3954
4311
  throw new Error("useDirectEditActions must be used within a DirectEditProvider");
3955
4312
  }
@@ -3958,11 +4315,34 @@ function useDirectEditActions() {
3958
4315
  function useDirectEdit() {
3959
4316
  const state = useDirectEditState();
3960
4317
  const actions = useDirectEditActions();
3961
- return React7.useMemo(() => ({ ...state, ...actions }), [state, actions]);
4318
+ return React8.useMemo(() => ({ ...state, ...actions }), [state, actions]);
3962
4319
  }
3963
4320
  var BORDER_STYLE_CONTROL_PREFERENCE_KEY = "direct-edit-border-style-control";
4321
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? React8.useEffect : React8.useLayoutEffect;
4322
+ function getInitialTheme() {
4323
+ if (typeof window === "undefined") return "system";
4324
+ try {
4325
+ const theme = localStorage.getItem("direct-edit-theme");
4326
+ if (theme === "light" || theme === "dark" || theme === "system") {
4327
+ return theme;
4328
+ }
4329
+ } catch {
4330
+ }
4331
+ return "system";
4332
+ }
4333
+ function getInitialBorderStyleControlPreference() {
4334
+ if (typeof window === "undefined") return "icon";
4335
+ try {
4336
+ const borderPref = localStorage.getItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY);
4337
+ if (borderPref === "label" || borderPref === "icon") {
4338
+ return borderPref;
4339
+ }
4340
+ } catch {
4341
+ }
4342
+ return "icon";
4343
+ }
3964
4344
  function DirectEditProvider({ children }) {
3965
- const [state, setState] = React7.useState({
4345
+ const [state, setState] = React8.useState(() => ({
3966
4346
  isOpen: false,
3967
4347
  selectedElement: null,
3968
4348
  elementInfo: null,
@@ -3978,38 +4358,22 @@ function DirectEditProvider({ children }) {
3978
4358
  pendingStyles: {},
3979
4359
  editModeActive: false,
3980
4360
  activeTool: "select",
3981
- theme: "system",
3982
- borderStyleControlPreference: "icon",
4361
+ theme: getInitialTheme(),
4362
+ borderStyleControlPreference: getInitialBorderStyleControlPreference(),
3983
4363
  comments: [],
3984
4364
  activeCommentId: null,
3985
- textEditingElement: null
3986
- });
3987
- React7.useEffect(() => {
3988
- try {
3989
- const updates = {};
3990
- const theme = localStorage.getItem("direct-edit-theme");
3991
- if (theme === "light" || theme === "dark" || theme === "system") {
3992
- updates.theme = theme;
3993
- }
3994
- const borderPref = localStorage.getItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY);
3995
- if (borderPref === "label" || borderPref === "icon") {
3996
- updates.borderStyleControlPreference = borderPref;
3997
- }
3998
- if (Object.keys(updates).length > 0) {
3999
- setState((prev) => ({ ...prev, ...updates }));
4000
- }
4001
- } catch {
4002
- }
4003
- }, []);
4004
- const undoStackRef = React7.useRef([]);
4005
- const sessionEditsRef = React7.useRef(/* @__PURE__ */ new Map());
4006
- const removedSessionEditsRef = React7.useRef(/* @__PURE__ */ new WeakSet());
4007
- const [sessionEditCount, setSessionEditCount] = React7.useState(0);
4008
- const stateRef = React7.useRef(state);
4009
- React7.useEffect(() => {
4365
+ textEditingElement: null,
4366
+ canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
4367
+ }));
4368
+ const undoStackRef = React8.useRef([]);
4369
+ const sessionEditsRef = React8.useRef(/* @__PURE__ */ new Map());
4370
+ const removedSessionEditsRef = React8.useRef(/* @__PURE__ */ new WeakSet());
4371
+ const [sessionEditCount, setSessionEditCount] = React8.useState(0);
4372
+ const stateRef = React8.useRef(state);
4373
+ React8.useEffect(() => {
4010
4374
  stateRef.current = state;
4011
4375
  });
4012
- const pushUndo = React7.useCallback((entry) => {
4376
+ const pushUndo = React8.useCallback((entry) => {
4013
4377
  undoStackRef.current.push(entry);
4014
4378
  if (undoStackRef.current.length > 500) {
4015
4379
  undoStackRef.current = undoStackRef.current.slice(-500);
@@ -4054,13 +4418,13 @@ function DirectEditProvider({ children }) {
4054
4418
  setState,
4055
4419
  setSessionEditCount
4056
4420
  });
4057
- React7.useEffect(() => {
4421
+ React8.useEffect(() => {
4058
4422
  if (!state.selectedElement) return;
4059
4423
  saveCurrentToSession();
4060
4424
  }, [state.selectedElement, state.pendingStyles, saveCurrentToSession]);
4061
4425
  const {
4062
4426
  finalizeTextEditing,
4063
- toggleEditMode,
4427
+ toggleEditMode: toggleEditModeBase,
4064
4428
  startTextEditing,
4065
4429
  commitTextEditing,
4066
4430
  addComment,
@@ -4077,10 +4441,32 @@ function DirectEditProvider({ children }) {
4077
4441
  syncSessionItemCount,
4078
4442
  setState
4079
4443
  });
4080
- React7.useEffect(() => {
4444
+ const { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 } = useCanvas({
4445
+ stateRef,
4446
+ setState
4447
+ });
4448
+ const closePanel = React8.useCallback(() => {
4449
+ setState((prev) => ({
4450
+ ...prev,
4451
+ isOpen: false
4452
+ }));
4453
+ }, []);
4454
+ const toggleEditMode = React8.useCallback(() => {
4455
+ const wasActive = stateRef.current.editModeActive;
4456
+ toggleEditModeBase();
4457
+ if (wasActive && stateRef.current.canvas?.active) {
4458
+ exitCanvas();
4459
+ } else if (!wasActive) {
4460
+ enterCanvas();
4461
+ }
4462
+ if (wasActive) {
4463
+ closePanel();
4464
+ }
4465
+ }, [toggleEditModeBase, stateRef, exitCanvas, enterCanvas, closePanel]);
4466
+ React8.useEffect(() => {
4081
4467
  syncSessionItemCount(state.comments);
4082
4468
  }, [state.comments, syncSessionItemCount]);
4083
- React7.useEffect(() => {
4469
+ React8.useEffect(() => {
4084
4470
  const editingElement = state.textEditingElement;
4085
4471
  if (!editingElement) return;
4086
4472
  const activeEditingElement = editingElement;
@@ -4105,27 +4491,21 @@ function DirectEditProvider({ children }) {
4105
4491
  sendCommentToAgent: sendCommentToAgent2,
4106
4492
  sendAllSessionItemsToAgent
4107
4493
  } = useAgentComms({ stateRef, sessionEditsRef, getSessionItems });
4108
- const closePanel = React7.useCallback(() => {
4109
- setState((prev) => ({
4110
- ...prev,
4111
- isOpen: false
4112
- }));
4113
- }, []);
4114
- const setActiveTool = React7.useCallback((tool) => {
4494
+ const setActiveTool = React8.useCallback((tool) => {
4115
4495
  setState((prev) => ({
4116
4496
  ...prev,
4117
4497
  activeTool: tool,
4118
4498
  activeCommentId: null
4119
4499
  }));
4120
4500
  }, []);
4121
- const setTheme = React7.useCallback((theme) => {
4501
+ const setTheme = React8.useCallback((theme) => {
4122
4502
  setState((prev) => ({ ...prev, theme }));
4123
4503
  try {
4124
4504
  localStorage.setItem("direct-edit-theme", theme);
4125
4505
  } catch {
4126
4506
  }
4127
4507
  }, []);
4128
- const setBorderStyleControlPreference = React7.useCallback((preference) => {
4508
+ const setBorderStyleControlPreference = React8.useCallback((preference) => {
4129
4509
  setState((prev) => ({ ...prev, borderStyleControlPreference: preference }));
4130
4510
  try {
4131
4511
  localStorage.setItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY, preference);
@@ -4140,13 +4520,17 @@ function DirectEditProvider({ children }) {
4140
4520
  commitTextEditing,
4141
4521
  startTextEditing,
4142
4522
  closePanel,
4143
- setState
4523
+ setState,
4524
+ toggleCanvas,
4525
+ setCanvasZoom,
4526
+ fitCanvasToViewport,
4527
+ zoomCanvasTo100
4144
4528
  });
4145
- const stateContextValue = React7.useMemo(() => ({
4529
+ const stateContextValue = React8.useMemo(() => ({
4146
4530
  ...state,
4147
4531
  sessionEditCount
4148
4532
  }), [state, sessionEditCount]);
4149
- const actionsContextValue = React7.useMemo(() => ({
4533
+ const actionsContextValue = React8.useMemo(() => ({
4150
4534
  selectElement,
4151
4535
  selectParent,
4152
4536
  selectChild,
@@ -4185,7 +4569,11 @@ function DirectEditProvider({ children }) {
4185
4569
  clearSessionEdits,
4186
4570
  removeSessionEdit,
4187
4571
  startTextEditing,
4188
- commitTextEditing
4572
+ commitTextEditing,
4573
+ toggleCanvas,
4574
+ setCanvasZoom,
4575
+ fitCanvasToViewport,
4576
+ zoomCanvasTo100
4189
4577
  }), [
4190
4578
  selectElement,
4191
4579
  selectParent,
@@ -4225,7 +4613,11 @@ function DirectEditProvider({ children }) {
4225
4613
  clearSessionEdits,
4226
4614
  removeSessionEdit,
4227
4615
  startTextEditing,
4228
- commitTextEditing
4616
+ commitTextEditing,
4617
+ toggleCanvas,
4618
+ setCanvasZoom,
4619
+ fitCanvasToViewport,
4620
+ zoomCanvasTo100
4229
4621
  ]);
4230
4622
  return /* @__PURE__ */ jsx2(PortalContainerProvider, { children: /* @__PURE__ */ jsx2(DirectEditStateContext.Provider, { value: stateContextValue, children: /* @__PURE__ */ jsxs(DirectEditActionsContext.Provider, { value: actionsContextValue, children: [
4231
4623
  /* @__PURE__ */ jsx2(ThemeApplier, {}),
@@ -4235,7 +4627,7 @@ function DirectEditProvider({ children }) {
4235
4627
  function ThemeApplier() {
4236
4628
  const { theme } = useDirectEditState();
4237
4629
  const container = usePortalContainer();
4238
- React7.useEffect(() => {
4630
+ useIsomorphicLayoutEffect(() => {
4239
4631
  if (!container) return;
4240
4632
  const host = container.getRootNode().host;
4241
4633
  if (theme === "system") {
@@ -4248,11 +4640,11 @@ function ThemeApplier() {
4248
4640
  }
4249
4641
 
4250
4642
  // src/panel.tsx
4251
- import * as React28 from "react";
4643
+ import * as React29 from "react";
4252
4644
  import { createPortal } from "react-dom";
4253
4645
 
4254
4646
  // src/ui/tooltip.tsx
4255
- import * as React8 from "react";
4647
+ import * as React9 from "react";
4256
4648
  import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
4257
4649
 
4258
4650
  // src/cn.ts
@@ -4273,14 +4665,14 @@ var TooltipProvider = ({
4273
4665
  }) => /* @__PURE__ */ jsx3(TooltipPrimitive.Provider, { delay: delay ?? delayDuration, closeDelay, ...props, children });
4274
4666
  var Tooltip = TooltipPrimitive.Root;
4275
4667
  var TooltipTrigger = TooltipPrimitive.Trigger;
4276
- var TooltipContent = React8.forwardRef(({ className, side, align, sideOffset = 8, ...props }, ref) => {
4668
+ var TooltipContent = React9.forwardRef(({ className, side, align, sideOffset = 8, ...props }, ref) => {
4277
4669
  const container = usePortalContainer();
4278
4670
  return /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { container, children: /* @__PURE__ */ jsx3(TooltipPrimitive.Positioner, { side, align, sideOffset, className: "fixed z-[99999]", children: /* @__PURE__ */ jsx3(
4279
4671
  TooltipPrimitive.Popup,
4280
4672
  {
4281
4673
  ref,
4282
4674
  className: cn(
4283
- "rounded-md bg-[canvas] px-2 py-1 text-xs origin-(--transform-origin) shadow-xs outline-1 outline-gray-200 transition-[transform,scale,opacity] data-starting-style:scale-90 data-starting-style:opacity-0 data-ending-style:scale-90 data-ending-style:opacity-0 data-instant:transition-none dark:shadow-none dark:outline-gray-300 dark:-outline-offset-1",
4675
+ "rounded-md bg-[canvas] px-2 py-1 text-xs origin-(--transform-origin) shadow-xs outline-1 outline-border transition-[transform,scale,opacity] data-starting-style:scale-90 data-starting-style:opacity-0 data-ending-style:scale-90 data-ending-style:opacity-0 data-instant:transition-none dark:shadow-none dark:-outline-offset-1",
4284
4676
  className
4285
4677
  ),
4286
4678
  ...props
@@ -4291,23 +4683,23 @@ TooltipContent.displayName = "TooltipContent";
4291
4683
  var createTooltipHandle = TooltipPrimitive.createHandle;
4292
4684
 
4293
4685
  // src/use-measurement.ts
4294
- import * as React9 from "react";
4686
+ import * as React10 from "react";
4295
4687
  var INITIAL_STATE = {
4296
4688
  hoveredElement: null,
4297
4689
  measurements: []
4298
4690
  };
4299
4691
  function useMeasurement(selectedElement) {
4300
- const [altHeld, setAltHeld] = React9.useState(false);
4301
- const [state, setState] = React9.useState(INITIAL_STATE);
4302
- const [mousePosition, setMousePosition] = React9.useState(null);
4303
- const rafRef = React9.useRef(null);
4304
- const mousePositionRef = React9.useRef(null);
4305
- const getElementBelow = React9.useCallback((x, y) => {
4692
+ const [altHeld, setAltHeld] = React10.useState(false);
4693
+ const [state, setState] = React10.useState(INITIAL_STATE);
4694
+ const [mousePosition, setMousePosition] = React10.useState(null);
4695
+ const rafRef = React10.useRef(null);
4696
+ const mousePositionRef = React10.useRef(null);
4697
+ const getElementBelow = React10.useCallback((x, y) => {
4306
4698
  const element = elementFromPointWithoutOverlays(x, y);
4307
4699
  if (element?.closest("[data-direct-edit-host]")) return null;
4308
4700
  return element;
4309
4701
  }, []);
4310
- React9.useEffect(() => {
4702
+ React10.useEffect(() => {
4311
4703
  function handleKeyDown(e) {
4312
4704
  if (e.key === "Alt") {
4313
4705
  e.preventDefault();
@@ -4338,7 +4730,7 @@ function useMeasurement(selectedElement) {
4338
4730
  document.removeEventListener("visibilitychange", handleVisibilityChange);
4339
4731
  };
4340
4732
  }, []);
4341
- React9.useEffect(() => {
4733
+ React10.useEffect(() => {
4342
4734
  if (!altHeld || !selectedElement) {
4343
4735
  setState(INITIAL_STATE);
4344
4736
  return;
@@ -4397,7 +4789,7 @@ function useMeasurement(selectedElement) {
4397
4789
  }
4398
4790
 
4399
4791
  // src/measurement-overlay.tsx
4400
- import * as React10 from "react";
4792
+ import * as React11 from "react";
4401
4793
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
4402
4794
  var TOMATO = "#E54D2E";
4403
4795
  var BLUE = "#0D99FF";
@@ -4474,16 +4866,18 @@ function MeasurementOverlay({
4474
4866
  hoveredElement,
4475
4867
  measurements
4476
4868
  }) {
4477
- const [, forceUpdate] = React10.useReducer((x) => x + 1, 0);
4478
- React10.useEffect(() => {
4869
+ const [, forceUpdate] = React11.useReducer((x) => x + 1, 0);
4870
+ React11.useEffect(() => {
4479
4871
  function handleUpdate() {
4480
4872
  requestAnimationFrame(forceUpdate);
4481
4873
  }
4482
4874
  window.addEventListener("scroll", handleUpdate, true);
4483
4875
  window.addEventListener("resize", handleUpdate);
4876
+ window.addEventListener("direct-edit-canvas-change", handleUpdate);
4484
4877
  return () => {
4485
4878
  window.removeEventListener("scroll", handleUpdate, true);
4486
4879
  window.removeEventListener("resize", handleUpdate);
4880
+ window.removeEventListener("direct-edit-canvas-change", handleUpdate);
4487
4881
  };
4488
4882
  }, [selectedElement]);
4489
4883
  return /* @__PURE__ */ jsxs2(
@@ -4508,7 +4902,7 @@ function MeasurementOverlay({
4508
4902
  }
4509
4903
 
4510
4904
  // src/use-move.ts
4511
- import * as React11 from "react";
4905
+ import * as React12 from "react";
4512
4906
  var INITIAL_DRAG_STATE = {
4513
4907
  isDragging: false,
4514
4908
  draggedElement: null,
@@ -4519,19 +4913,19 @@ var INITIAL_DRAG_STATE = {
4519
4913
  dragOffset: { x: 0, y: 0 }
4520
4914
  };
4521
4915
  function useMove({ onMoveComplete }) {
4522
- const [dragState, setDragState] = React11.useState(INITIAL_DRAG_STATE);
4523
- const [dropTarget, setDropTarget] = React11.useState(null);
4524
- const [dropIndicator, setDropIndicator] = React11.useState(null);
4525
- const dragStateRef = React11.useRef(dragState);
4526
- const dropTargetRef = React11.useRef(dropTarget);
4527
- const onMoveCompleteRef = React11.useRef(onMoveComplete);
4528
- const dragOptionsRef = React11.useRef({});
4529
- React11.useEffect(() => {
4916
+ const [dragState, setDragState] = React12.useState(INITIAL_DRAG_STATE);
4917
+ const [dropTarget, setDropTarget] = React12.useState(null);
4918
+ const [dropIndicator, setDropIndicator] = React12.useState(null);
4919
+ const dragStateRef = React12.useRef(dragState);
4920
+ const dropTargetRef = React12.useRef(dropTarget);
4921
+ const onMoveCompleteRef = React12.useRef(onMoveComplete);
4922
+ const dragOptionsRef = React12.useRef({});
4923
+ React12.useEffect(() => {
4530
4924
  dragStateRef.current = dragState;
4531
4925
  dropTargetRef.current = dropTarget;
4532
4926
  onMoveCompleteRef.current = onMoveComplete;
4533
4927
  });
4534
- const cancelDrag = React11.useCallback(() => {
4928
+ const cancelDrag = React12.useCallback(() => {
4535
4929
  const current = dragStateRef.current;
4536
4930
  if (current.draggedElement) {
4537
4931
  current.draggedElement.style.opacity = "";
@@ -4541,7 +4935,7 @@ function useMove({ onMoveComplete }) {
4541
4935
  setDropTarget(null);
4542
4936
  setDropIndicator(null);
4543
4937
  }, []);
4544
- const completeDrag = React11.useCallback(() => {
4938
+ const completeDrag = React12.useCallback(() => {
4545
4939
  const current = dragStateRef.current;
4546
4940
  const target = dropTargetRef.current;
4547
4941
  const { draggedElement, originalParent, originalPreviousSibling, originalNextSibling } = current;
@@ -4575,7 +4969,7 @@ function useMove({ onMoveComplete }) {
4575
4969
  onMoveCompleteRef.current(draggedElement, moveInfo);
4576
4970
  }
4577
4971
  }, [cancelDrag]);
4578
- const startDrag = React11.useCallback(
4972
+ const startDrag = React12.useCallback(
4579
4973
  (e, element, options) => {
4580
4974
  const rect = element.getBoundingClientRect();
4581
4975
  const parent = element.parentElement;
@@ -4595,7 +4989,7 @@ function useMove({ onMoveComplete }) {
4595
4989
  },
4596
4990
  []
4597
4991
  );
4598
- React11.useEffect(() => {
4992
+ React12.useEffect(() => {
4599
4993
  if (!dragState.isDragging) return;
4600
4994
  function handlePointerMove(e) {
4601
4995
  const current = dragStateRef.current;
@@ -4663,7 +5057,46 @@ function useMove({ onMoveComplete }) {
4663
5057
  }
4664
5058
 
4665
5059
  // src/use-guidelines.ts
4666
- import * as React12 from "react";
5060
+ import * as React13 from "react";
5061
+
5062
+ // src/utils/snap-targets.ts
5063
+ var SNAP_THRESHOLD_PX = 6;
5064
+ function collectSnapTargets(orientation) {
5065
+ const edges = [];
5066
+ const elements = document.body.querySelectorAll("*");
5067
+ const viewportW = window.innerWidth;
5068
+ const viewportH = window.innerHeight;
5069
+ for (let i = 0; i < elements.length; i++) {
5070
+ const el = elements[i];
5071
+ if (el === document.body || el === document.documentElement) continue;
5072
+ if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) continue;
5073
+ if (el.offsetParent === null && el !== document.body) continue;
5074
+ const rect = el.getBoundingClientRect();
5075
+ if (rect.width < 4 || rect.height < 4) continue;
5076
+ if (rect.right < -200 || rect.bottom < -200 || rect.left > viewportW + 200 || rect.top > viewportH + 200) continue;
5077
+ if (orientation === "horizontal") {
5078
+ edges.push(rect.top, rect.bottom);
5079
+ } else {
5080
+ edges.push(rect.left, rect.right);
5081
+ }
5082
+ if (edges.length >= 2e3) break;
5083
+ }
5084
+ return edges;
5085
+ }
5086
+ function findSnap(viewportPos, snapEdges, threshold) {
5087
+ let best = null;
5088
+ let bestDist = threshold + 1;
5089
+ for (let i = 0; i < snapEdges.length; i++) {
5090
+ const dist = Math.abs(snapEdges[i] - viewportPos);
5091
+ if (dist < bestDist) {
5092
+ bestDist = dist;
5093
+ best = snapEdges[i];
5094
+ }
5095
+ }
5096
+ return bestDist <= threshold ? best : null;
5097
+ }
5098
+
5099
+ // src/use-guidelines.ts
4667
5100
  var STORAGE_KEY = "direct-edit-guidelines";
4668
5101
  function isGuidelineOrientation(value) {
4669
5102
  return value === "horizontal" || value === "vertical";
@@ -4700,6 +5133,7 @@ function generateId() {
4700
5133
  return `gl-${Date.now()}-${idCounter++}`;
4701
5134
  }
4702
5135
  var RULER_SIZE = 20;
5136
+ var SNAP_VELOCITY_THRESHOLD = 3;
4703
5137
  function viewportToCssCoord(hostElement, value, axis) {
4704
5138
  if (!hostElement) return value;
4705
5139
  const rect = hostElement.getBoundingClientRect();
@@ -4709,68 +5143,108 @@ function viewportToCssCoord(hostElement, value, axis) {
4709
5143
  if (size === 0) return value;
4710
5144
  return (value - origin) * (cssSize / size);
4711
5145
  }
4712
- function useGuidelines(enabled, hostElement) {
4713
- const [guidelines, setGuidelines] = React12.useState([]);
4714
- const [hydrated, setHydrated] = React12.useState(false);
4715
- const [activeGuidelineId, setActiveGuidelineId] = React12.useState(null);
4716
- const [dragPosition, setDragPosition] = React12.useState(null);
4717
- const [isCreating, setIsCreating] = React12.useState(false);
4718
- const [scrollOffset, setScrollOffset] = React12.useState({ x: 0, y: 0 });
4719
- const hostRef = React12.useRef(hostElement ?? null);
5146
+ function useGuidelines(enabled, hostElement, canvas) {
5147
+ const [guidelines, setGuidelines] = React13.useState([]);
5148
+ const [hydrated, setHydrated] = React13.useState(false);
5149
+ const [activeGuidelineId, setActiveGuidelineId] = React13.useState(null);
5150
+ const [dragPosition, setDragPosition] = React13.useState(null);
5151
+ const [isCreating, setIsCreating] = React13.useState(false);
5152
+ const [scrollOffset, setScrollOffset] = React13.useState({ x: 0, y: 0 });
5153
+ const hostRef = React13.useRef(hostElement ?? null);
4720
5154
  hostRef.current = hostElement ?? null;
4721
- const [dragging, setDragging] = React12.useState(false);
4722
- const guidelinesRef = React12.useRef(guidelines);
5155
+ const canvasRef = React13.useRef(canvas);
5156
+ canvasRef.current = canvas;
5157
+ const [dragging, setDragging] = React13.useState(false);
5158
+ const guidelinesRef = React13.useRef(guidelines);
4723
5159
  guidelinesRef.current = guidelines;
4724
- const dragInfoRef = React12.useRef(null);
4725
- React12.useEffect(() => {
5160
+ const dragInfoRef = React13.useRef(null);
5161
+ const snapTargetsRef = React13.useRef([]);
5162
+ const isSnappedRef = React13.useRef(false);
5163
+ const [isSnapped, setIsSnapped] = React13.useState(false);
5164
+ React13.useEffect(() => {
4726
5165
  setGuidelines(loadGuidelines());
4727
5166
  setHydrated(true);
4728
5167
  }, []);
4729
- React12.useEffect(() => {
5168
+ React13.useEffect(() => {
4730
5169
  if (!hydrated) return;
4731
5170
  saveGuidelines(guidelines);
4732
5171
  }, [guidelines, hydrated]);
4733
- React12.useEffect(() => {
5172
+ React13.useEffect(() => {
4734
5173
  if (!enabled) return;
4735
5174
  function update() {
4736
- setScrollOffset({ x: window.scrollX, y: window.scrollY });
5175
+ setScrollOffset((prev) => {
5176
+ const x = window.scrollX;
5177
+ const y = window.scrollY;
5178
+ return prev.x === x && prev.y === y ? prev : { x, y };
5179
+ });
4737
5180
  }
4738
5181
  update();
4739
5182
  window.addEventListener("scroll", update, true);
4740
5183
  window.addEventListener("resize", update);
5184
+ window.addEventListener("direct-edit-canvas-change", update);
4741
5185
  return () => {
4742
5186
  window.removeEventListener("scroll", update, true);
4743
5187
  window.removeEventListener("resize", update);
5188
+ window.removeEventListener("direct-edit-canvas-change", update);
4744
5189
  };
4745
5190
  }, [enabled]);
4746
- const endDrag = React12.useCallback(() => {
5191
+ const endDrag = React13.useCallback(() => {
4747
5192
  const wasCreating = dragInfoRef.current?.isCreating ?? false;
4748
5193
  dragInfoRef.current = null;
5194
+ snapTargetsRef.current = [];
5195
+ isSnappedRef.current = false;
5196
+ setIsSnapped(false);
4749
5197
  setDragging(false);
4750
5198
  setActiveGuidelineId(null);
4751
5199
  setDragPosition(null);
4752
5200
  if (wasCreating) setIsCreating(false);
4753
5201
  }, []);
4754
- React12.useEffect(() => {
5202
+ React13.useEffect(() => {
4755
5203
  if (!dragging) return;
4756
5204
  const info = dragInfoRef.current;
4757
5205
  if (!info) return;
4758
5206
  const { guidelineId, orientation } = info;
4759
5207
  const axis = orientation === "horizontal" ? "y" : "x";
4760
- function pointerToPos(e) {
4761
- const raw = orientation === "horizontal" ? e.clientY : e.clientX;
4762
- return viewportToCssCoord(hostRef.current, raw, axis);
4763
- }
5208
+ let lastPos = NaN;
5209
+ let lastTime = 0;
4764
5210
  function onPointerMove(e) {
4765
- const pos = pointerToPos(e);
5211
+ const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
5212
+ const now = performance.now();
5213
+ const dt = now - lastTime;
5214
+ const velocity = dt > 0 && !Number.isNaN(lastPos) ? Math.abs(rawViewportPos - lastPos) / dt : 0;
5215
+ lastPos = rawViewportPos;
5216
+ lastTime = now;
5217
+ let effectiveViewportPos = rawViewportPos;
5218
+ let snapped = false;
5219
+ if (velocity < SNAP_VELOCITY_THRESHOLD) {
5220
+ const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
5221
+ if (snapResult !== null) {
5222
+ effectiveViewportPos = snapResult;
5223
+ snapped = true;
5224
+ }
5225
+ }
5226
+ isSnappedRef.current = snapped;
5227
+ setIsSnapped(snapped);
5228
+ const pos = viewportToCssCoord(hostRef.current, effectiveViewportPos, axis);
4766
5229
  setDragPosition(pos);
4767
- const currentScroll = orientation === "horizontal" ? window.scrollY : window.scrollX;
5230
+ const c = canvasRef.current;
5231
+ let storedPosition;
5232
+ if (c?.active) {
5233
+ const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
5234
+ const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
5235
+ storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
5236
+ } else {
5237
+ const currentScroll = orientation === "horizontal" ? window.scrollY : window.scrollX;
5238
+ storedPosition = pos + currentScroll;
5239
+ }
4768
5240
  setGuidelines(
4769
- (prev) => prev.map((g) => g.id === guidelineId ? { ...g, position: pos + currentScroll } : g)
5241
+ (prev) => prev.map((g) => g.id === guidelineId ? { ...g, position: storedPosition } : g)
4770
5242
  );
4771
5243
  }
4772
5244
  function onPointerUp(e) {
4773
- const pos = pointerToPos(e);
5245
+ const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
5246
+ const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
5247
+ const pos = viewportToCssCoord(hostRef.current, snapResult ?? rawViewportPos, axis);
4774
5248
  if (pos <= RULER_SIZE) {
4775
5249
  setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
4776
5250
  }
@@ -4783,22 +5257,32 @@ function useGuidelines(enabled, hostElement) {
4783
5257
  window.removeEventListener("pointerup", onPointerUp);
4784
5258
  };
4785
5259
  }, [dragging, endDrag]);
4786
- React12.useEffect(() => {
5260
+ React13.useEffect(() => {
4787
5261
  if (!enabled && dragging) {
4788
5262
  endDrag();
4789
5263
  }
4790
5264
  }, [enabled, dragging, endDrag]);
4791
- const activeGuideline = React12.useMemo(
5265
+ const activeGuideline = React13.useMemo(
4792
5266
  () => guidelines.find((g) => g.id === activeGuidelineId) ?? null,
4793
5267
  [guidelines, activeGuidelineId]
4794
5268
  );
4795
- const startCreate = React12.useCallback(
5269
+ const startCreate = React13.useCallback(
4796
5270
  (orientation, viewportPosition) => {
4797
5271
  const axis = orientation === "horizontal" ? "y" : "x";
4798
5272
  const pos = viewportToCssCoord(hostRef.current, viewportPosition, axis);
4799
- const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
4800
5273
  const id = generateId();
4801
- const newGuideline = { id, orientation, position: pos + scrollPos };
5274
+ const c = canvasRef.current;
5275
+ let storedPosition;
5276
+ if (c?.active) {
5277
+ const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
5278
+ const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
5279
+ storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
5280
+ } else {
5281
+ const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
5282
+ storedPosition = pos + scrollPos;
5283
+ }
5284
+ const newGuideline = { id, orientation, position: storedPosition };
5285
+ snapTargetsRef.current = collectSnapTargets(orientation);
4802
5286
  setGuidelines((prev) => [...prev, newGuideline]);
4803
5287
  setActiveGuidelineId(id);
4804
5288
  setDragPosition(pos);
@@ -4808,19 +5292,29 @@ function useGuidelines(enabled, hostElement) {
4808
5292
  },
4809
5293
  []
4810
5294
  );
4811
- const startDrag = React12.useCallback((guidelineId) => {
5295
+ const startDrag = React13.useCallback((guidelineId) => {
4812
5296
  const guideline = guidelinesRef.current.find((g) => g.id === guidelineId);
4813
5297
  if (!guideline) return;
4814
- const scrollPos = guideline.orientation === "horizontal" ? window.scrollY : window.scrollX;
5298
+ snapTargetsRef.current = collectSnapTargets(guideline.orientation);
5299
+ const c = canvasRef.current;
5300
+ let viewportPos;
5301
+ if (c?.active) {
5302
+ const pan = guideline.orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
5303
+ const bo = guideline.orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
5304
+ viewportPos = bo + (guideline.position - bo + pan) * (c.zoom || 1);
5305
+ } else {
5306
+ const scrollPos = guideline.orientation === "horizontal" ? window.scrollY : window.scrollX;
5307
+ viewportPos = guideline.position - scrollPos;
5308
+ }
4815
5309
  setActiveGuidelineId(guidelineId);
4816
- setDragPosition(guideline.position - scrollPos);
5310
+ setDragPosition(viewportPos);
4817
5311
  dragInfoRef.current = { guidelineId, orientation: guideline.orientation, isCreating: false };
4818
5312
  setDragging(true);
4819
5313
  }, []);
4820
- const deleteGuideline = React12.useCallback((guidelineId) => {
5314
+ const deleteGuideline = React13.useCallback((guidelineId) => {
4821
5315
  setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
4822
5316
  }, []);
4823
- const clearAll = React12.useCallback(() => {
5317
+ const clearAll = React13.useCallback(() => {
4824
5318
  setGuidelines([]);
4825
5319
  }, []);
4826
5320
  return {
@@ -4828,6 +5322,7 @@ function useGuidelines(enabled, hostElement) {
4828
5322
  activeGuideline,
4829
5323
  dragPosition,
4830
5324
  isCreating,
5325
+ isSnapped,
4831
5326
  scrollOffset,
4832
5327
  startCreate,
4833
5328
  startDrag,
@@ -4882,10 +5377,8 @@ function InteractionOverlay({
4882
5377
  if (activeTool === "comment") {
4883
5378
  if (hasPendingCommentDraft()) return;
4884
5379
  const elementUnder2 = elementFromPointWithoutOverlays(e.clientX, e.clientY);
4885
- if (elementUnder2 && elementUnder2 !== document.body && elementUnder2 !== document.documentElement) {
4886
- const resolved = resolveElementTarget(elementUnder2, selectedElement);
4887
- onAddComment(resolved, { x: e.clientX, y: e.clientY });
4888
- }
5380
+ const target = elementUnder2 && elementUnder2 !== document.body && elementUnder2 !== document.documentElement ? resolveElementTarget(elementUnder2, selectedElement) : document.body;
5381
+ onAddComment(target, { x: e.clientX, y: e.clientY });
4889
5382
  return;
4890
5383
  }
4891
5384
  if (activeCommentId) {
@@ -4903,39 +5396,41 @@ function InteractionOverlay({
4903
5396
  hoverHighlight && (() => {
4904
5397
  const cr = hoverHighlight.flexContainer.getBoundingClientRect();
4905
5398
  return /* @__PURE__ */ jsxs3(
4906
- "svg",
5399
+ "div",
4907
5400
  {
4908
5401
  "data-direct-edit": "hover-highlight",
4909
5402
  className: "pointer-events-none fixed inset-0 z-[99991]",
4910
- width: "100%",
4911
- height: "100%",
4912
- style: { width: "100vw", height: "100vh" },
4913
5403
  children: [
4914
5404
  /* @__PURE__ */ jsx5(
4915
- "rect",
5405
+ "div",
4916
5406
  {
4917
- x: cr.left,
4918
- y: cr.top,
4919
- width: cr.width,
4920
- height: cr.height,
4921
- fill: "transparent",
4922
- stroke: "#3b82f6",
4923
- strokeWidth: 1
5407
+ style: {
5408
+ position: "absolute",
5409
+ left: cr.left,
5410
+ top: cr.top,
5411
+ width: cr.width,
5412
+ height: cr.height,
5413
+ border: "1px solid #3b82f6",
5414
+ borderRadius: "0px",
5415
+ boxSizing: "border-box"
5416
+ }
4924
5417
  }
4925
5418
  ),
4926
5419
  hoverHighlight.children.map((child) => {
4927
5420
  const r = child.getBoundingClientRect();
4928
5421
  return /* @__PURE__ */ jsx5(
4929
- "rect",
5422
+ "div",
4930
5423
  {
4931
- x: r.left,
4932
- y: r.top,
4933
- width: r.width,
4934
- height: r.height,
4935
- fill: "transparent",
4936
- stroke: "#3b82f6",
4937
- strokeWidth: 1,
4938
- strokeDasharray: "4 2"
5424
+ style: {
5425
+ position: "absolute",
5426
+ left: r.left,
5427
+ top: r.top,
5428
+ width: r.width,
5429
+ height: r.height,
5430
+ border: "1px dashed #3b82f6",
5431
+ borderRadius: "0px",
5432
+ boxSizing: "border-box"
5433
+ }
4939
5434
  },
4940
5435
  `${r.left}-${r.top}-${r.width}-${r.height}`
4941
5436
  );
@@ -4981,7 +5476,7 @@ function MoveOverlay({ dropIndicator }) {
4981
5476
  }
4982
5477
 
4983
5478
  // src/selection-overlay.tsx
4984
- import * as React13 from "react";
5479
+ import * as React14 from "react";
4985
5480
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
4986
5481
  var BLUE3 = "#0D99FF";
4987
5482
  var MAGENTA = "#E11BB6";
@@ -4995,23 +5490,25 @@ function SelectionOverlay({
4995
5490
  ghostPosition,
4996
5491
  onMoveStart,
4997
5492
  showMoveHandle = false,
5493
+ activeTool = "select",
4998
5494
  isTextEditing,
4999
5495
  onDoubleClick,
5000
5496
  onHoverElement,
5001
5497
  onClickThrough
5002
5498
  }) {
5003
5499
  const rectElement = isDragging && draggedElement ? draggedElement : selectedElement;
5004
- const [rect, setRect] = React13.useState(() => rectElement.getBoundingClientRect());
5005
- const [moveHandleRects, setMoveHandleRects] = React13.useState([]);
5006
- const cleanupRef = React13.useRef(null);
5007
- const clickThroughTimerRef = React13.useRef(null);
5008
- React13.useEffect(() => {
5500
+ const [rect, setRect] = React14.useState(() => rectElement.getBoundingClientRect());
5501
+ const [moveHandleRects, setMoveHandleRects] = React14.useState([]);
5502
+ const cleanupRef = React14.useRef(null);
5503
+ const clickThroughTimerRef = React14.useRef(null);
5504
+ React14.useEffect(() => {
5009
5505
  function updateRect() {
5010
5506
  setRect(rectElement.getBoundingClientRect());
5011
5507
  }
5012
5508
  updateRect();
5013
5509
  window.addEventListener("scroll", updateRect, true);
5014
5510
  window.addEventListener("resize", updateRect);
5511
+ window.addEventListener("direct-edit-canvas-change", updateRect);
5015
5512
  const observer = new MutationObserver(updateRect);
5016
5513
  observer.observe(rectElement, {
5017
5514
  attributes: true,
@@ -5021,10 +5518,11 @@ function SelectionOverlay({
5021
5518
  return () => {
5022
5519
  window.removeEventListener("scroll", updateRect, true);
5023
5520
  window.removeEventListener("resize", updateRect);
5521
+ window.removeEventListener("direct-edit-canvas-change", updateRect);
5024
5522
  observer.disconnect();
5025
5523
  };
5026
5524
  }, [rectElement]);
5027
- React13.useEffect(() => {
5525
+ React14.useEffect(() => {
5028
5526
  return () => {
5029
5527
  cleanupRef.current?.();
5030
5528
  if (clickThroughTimerRef.current) clearTimeout(clickThroughTimerRef.current);
@@ -5085,7 +5583,7 @@ function SelectionOverlay({
5085
5583
  const handleMouseLeave = () => {
5086
5584
  onHoverElement?.(null);
5087
5585
  };
5088
- const getMoveHandleTargets = React13.useCallback(() => {
5586
+ const getMoveHandleTargets = React14.useCallback(() => {
5089
5587
  if (!showMoveHandle) return [];
5090
5588
  const selectedDisplay = window.getComputedStyle(selectedElement).display;
5091
5589
  const selectedIsFlexContainer = selectedDisplay === "flex" || selectedDisplay === "inline-flex";
@@ -5110,7 +5608,7 @@ function SelectionOverlay({
5110
5608
  }
5111
5609
  return [target];
5112
5610
  }, [selectedElement, showMoveHandle]);
5113
- React13.useEffect(() => {
5611
+ React14.useEffect(() => {
5114
5612
  if (!showMoveHandle || isDragging || isTextEditing) {
5115
5613
  setMoveHandleRects([]);
5116
5614
  return;
@@ -5150,30 +5648,22 @@ function SelectionOverlay({
5150
5648
  const displayX = isDragging && ghostPosition ? ghostPosition.x : rect.left;
5151
5649
  const displayY = isDragging && ghostPosition ? ghostPosition.y : rect.top;
5152
5650
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
5153
- /* @__PURE__ */ jsx7(
5154
- "svg",
5651
+ !isTextEditing && /* @__PURE__ */ jsx7(
5652
+ "div",
5155
5653
  {
5156
5654
  "data-direct-edit": "selection-overlay",
5157
5655
  style: {
5158
5656
  position: "fixed",
5159
- inset: 0,
5160
- width: "100vw",
5161
- height: "100vh",
5657
+ left: displayX,
5658
+ top: displayY,
5659
+ width: rect.width,
5660
+ height: rect.height,
5162
5661
  pointerEvents: "none",
5163
- zIndex: 99996
5164
- },
5165
- children: !isTextEditing && /* @__PURE__ */ jsx7(
5166
- "rect",
5167
- {
5168
- x: displayX,
5169
- y: displayY,
5170
- width: rect.width,
5171
- height: rect.height,
5172
- fill: "transparent",
5173
- stroke: BLUE3,
5174
- strokeWidth: 1
5175
- }
5176
- )
5662
+ zIndex: 99996,
5663
+ border: `1px solid ${BLUE3}`,
5664
+ borderRadius: "0px",
5665
+ boxSizing: "border-box"
5666
+ }
5177
5667
  }
5178
5668
  ),
5179
5669
  !isDragging && !isTextEditing && /* @__PURE__ */ jsx7(
@@ -5188,7 +5678,7 @@ function SelectionOverlay({
5188
5678
  height: rect.height,
5189
5679
  zIndex: 99996,
5190
5680
  cursor: "default",
5191
- pointerEvents: "auto"
5681
+ pointerEvents: activeTool === "comment" ? "none" : "auto"
5192
5682
  },
5193
5683
  onPointerDown: handlePointerDown,
5194
5684
  onDoubleClick: handleDoubleClick,
@@ -5230,7 +5720,7 @@ function SelectionOverlay({
5230
5720
  }
5231
5721
 
5232
5722
  // src/comment-overlay.tsx
5233
- import * as React14 from "react";
5723
+ import * as React15 from "react";
5234
5724
  import { ChevronLeft, Check, Copy, Trash2, ArrowUp, Send, X } from "lucide-react";
5235
5725
  import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
5236
5726
  function formatRelativeTime(timestamp) {
@@ -5270,7 +5760,8 @@ function CommentOverlay({
5270
5760
  onDelete,
5271
5761
  onExport,
5272
5762
  onSendToAgent,
5273
- attentionRequest = null
5763
+ attentionRequest = null,
5764
+ draftRef
5274
5765
  }) {
5275
5766
  if (comments.length === 0) return null;
5276
5767
  return /* @__PURE__ */ jsx8(Fragment3, { children: comments.map((comment, index) => /* @__PURE__ */ jsx8(
@@ -5286,7 +5777,8 @@ function CommentOverlay({
5286
5777
  onDelete: () => onDelete(comment.id),
5287
5778
  onExport: onExport ? () => onExport(comment.id) : void 0,
5288
5779
  onSendToAgent: () => onSendToAgent(comment.id),
5289
- attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0
5780
+ attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0,
5781
+ draftRef: activeCommentId === comment.id ? draftRef : void 0
5290
5782
  },
5291
5783
  comment.id
5292
5784
  )) });
@@ -5302,31 +5794,34 @@ function CommentPin({
5302
5794
  onDelete,
5303
5795
  onExport,
5304
5796
  onSendToAgent,
5305
- attentionNonce
5797
+ attentionNonce,
5798
+ draftRef
5306
5799
  }) {
5307
- const [position, setPosition] = React14.useState(comment.clickPosition);
5308
- const [elementRect, setElementRect] = React14.useState(null);
5309
- const [flipHorizontal, setFlipHorizontal] = React14.useState(false);
5310
- const [flipVertical, setFlipVertical] = React14.useState(false);
5311
- React14.useEffect(() => {
5800
+ const [position, setPosition] = React15.useState(comment.clickPosition);
5801
+ const [elementRect, setElementRect] = React15.useState(null);
5802
+ const [flipHorizontal, setFlipHorizontal] = React15.useState(false);
5803
+ const [flipVertical, setFlipVertical] = React15.useState(false);
5804
+ React15.useEffect(() => {
5312
5805
  function updatePosition() {
5313
5806
  if (!comment.element.isConnected) return;
5314
5807
  const rect = comment.element.getBoundingClientRect();
5315
5808
  setPosition({
5316
- x: rect.left + comment.relativePosition.x,
5317
- y: rect.top + comment.relativePosition.y
5809
+ x: rect.left + comment.relativePosition.x * rect.width,
5810
+ y: rect.top + comment.relativePosition.y * rect.height
5318
5811
  });
5319
5812
  setElementRect(rect);
5320
5813
  }
5321
5814
  updatePosition();
5322
5815
  window.addEventListener("scroll", updatePosition, true);
5323
5816
  window.addEventListener("resize", updatePosition);
5817
+ window.addEventListener("direct-edit-canvas-change", updatePosition);
5324
5818
  return () => {
5325
5819
  window.removeEventListener("scroll", updatePosition, true);
5326
5820
  window.removeEventListener("resize", updatePosition);
5821
+ window.removeEventListener("direct-edit-canvas-change", updatePosition);
5327
5822
  };
5328
5823
  }, [comment.element, comment.relativePosition]);
5329
- React14.useEffect(() => {
5824
+ React15.useEffect(() => {
5330
5825
  if (isActive) {
5331
5826
  const hasText = comment.text !== "";
5332
5827
  const cardWidth = hasText ? 280 : 220;
@@ -5392,7 +5887,8 @@ function CommentPin({
5392
5887
  onUpdateText(text);
5393
5888
  },
5394
5889
  onCancel: onClose,
5395
- attentionNonce
5890
+ attentionNonce,
5891
+ draftRef
5396
5892
  }
5397
5893
  ) : /* @__PURE__ */ jsx8(
5398
5894
  CommentThread,
@@ -5419,16 +5915,17 @@ function NewCommentInput({
5419
5915
  flipVertical,
5420
5916
  onSubmit,
5421
5917
  onCancel,
5422
- attentionNonce
5918
+ attentionNonce,
5919
+ draftRef
5423
5920
  }) {
5424
- const [text, setText] = React14.useState("");
5425
- const [showError, setShowError] = React14.useState(false);
5426
- const inputRef = React14.useRef(null);
5427
- const cardRef = React14.useRef(null);
5428
- React14.useEffect(() => {
5921
+ const [text, setText] = React15.useState("");
5922
+ const [showError, setShowError] = React15.useState(false);
5923
+ const inputRef = React15.useRef(null);
5924
+ const cardRef = React15.useRef(null);
5925
+ React15.useEffect(() => {
5429
5926
  inputRef.current?.focus();
5430
5927
  }, []);
5431
- React14.useEffect(() => {
5928
+ React15.useEffect(() => {
5432
5929
  if (attentionNonce <= 0) return;
5433
5930
  setShowError(true);
5434
5931
  cardRef.current?.animate?.(
@@ -5475,7 +5972,10 @@ function NewCommentInput({
5475
5972
  ),
5476
5973
  placeholder: "Add a comment...",
5477
5974
  value: text,
5478
- onChange: (e) => setText(e.target.value),
5975
+ onChange: (e) => {
5976
+ setText(e.target.value);
5977
+ if (draftRef) draftRef.current = e.target.value;
5978
+ },
5479
5979
  onKeyDown: (e) => {
5480
5980
  e.stopPropagation();
5481
5981
  if (e.key === "Enter" && text.trim()) {
@@ -5517,15 +6017,15 @@ function CommentThread({
5517
6017
  onExport,
5518
6018
  onSendToAgent
5519
6019
  }) {
5520
- const [replyText, setReplyText] = React14.useState("");
5521
- const [copied, setCopied] = React14.useState(false);
5522
- const [sendStatus, setSendStatus] = React14.useState("idle");
5523
- const inputRef = React14.useRef(null);
5524
- const copyTimerRef = React14.useRef(null);
5525
- React14.useEffect(() => {
6020
+ const [replyText, setReplyText] = React15.useState("");
6021
+ const [copied, setCopied] = React15.useState(false);
6022
+ const [sendStatus, setSendStatus] = React15.useState("idle");
6023
+ const inputRef = React15.useRef(null);
6024
+ const copyTimerRef = React15.useRef(null);
6025
+ React15.useEffect(() => {
5526
6026
  inputRef.current?.focus();
5527
6027
  }, []);
5528
- React14.useEffect(() => {
6028
+ React15.useEffect(() => {
5529
6029
  return () => {
5530
6030
  if (copyTimerRef.current) {
5531
6031
  window.clearTimeout(copyTimerRef.current);
@@ -5713,12 +6213,12 @@ function CommentThread({
5713
6213
  }
5714
6214
 
5715
6215
  // src/panel/shared.tsx
5716
- import * as React16 from "react";
6216
+ import * as React17 from "react";
5717
6217
 
5718
6218
  // src/ui/input.tsx
5719
- import * as React15 from "react";
6219
+ import * as React16 from "react";
5720
6220
  import { jsx as jsx9 } from "react/jsx-runtime";
5721
- var Input = React15.forwardRef(
6221
+ var Input = React16.forwardRef(
5722
6222
  ({ className, type, ...props }, ref) => {
5723
6223
  return /* @__PURE__ */ jsx9(
5724
6224
  "input",
@@ -5740,8 +6240,8 @@ Input.displayName = "Input";
5740
6240
  import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
5741
6241
  var selectOnFocus = (e) => e.target.select();
5742
6242
  function NumberInput({ value: propValue, onValueChange, ...props }) {
5743
- const [localValue, setLocalValue] = React16.useState(propValue === null ? "" : String(propValue));
5744
- React16.useEffect(() => {
6243
+ const [localValue, setLocalValue] = React17.useState(propValue === null ? "" : String(propValue));
6244
+ React17.useEffect(() => {
5745
6245
  setLocalValue(propValue === null ? "" : String(propValue));
5746
6246
  }, [propValue]);
5747
6247
  return /* @__PURE__ */ jsx10(
@@ -5788,9 +6288,9 @@ var SECTION_LABELS = {
5788
6288
  text: "Text"
5789
6289
  };
5790
6290
  function useSectionNav(sectionRefs) {
5791
- const scrollRef = React16.useRef(null);
5792
- const [activeSection, setActiveSection] = React16.useState("layout");
5793
- React16.useEffect(() => {
6291
+ const scrollRef = React17.useRef(null);
6292
+ const [activeSection, setActiveSection] = React17.useState("layout");
6293
+ React17.useEffect(() => {
5794
6294
  const scrollEl = scrollRef.current;
5795
6295
  if (!scrollEl) return;
5796
6296
  const handleScroll = () => {
@@ -5851,10 +6351,10 @@ function SectionNav({
5851
6351
  }
5852
6352
 
5853
6353
  // src/panel/border-radius-inputs.tsx
5854
- import * as React19 from "react";
6354
+ import * as React20 from "react";
5855
6355
 
5856
6356
  // src/ui/button.tsx
5857
- import * as React17 from "react";
6357
+ import * as React18 from "react";
5858
6358
  import { jsx as jsx11 } from "react/jsx-runtime";
5859
6359
  var buttonVariants = {
5860
6360
  base: "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
@@ -5873,7 +6373,7 @@ var buttonVariants = {
5873
6373
  icon: "h-10 w-10"
5874
6374
  }
5875
6375
  };
5876
- var Button = React17.forwardRef(
6376
+ var Button = React18.forwardRef(
5877
6377
  ({ className, variant = "default", size = "default", ...props }, ref) => {
5878
6378
  return /* @__PURE__ */ jsx11(
5879
6379
  "button",
@@ -5893,10 +6393,10 @@ var Button = React17.forwardRef(
5893
6393
  Button.displayName = "Button";
5894
6394
 
5895
6395
  // src/ui/slider.tsx
5896
- import * as React18 from "react";
6396
+ import * as React19 from "react";
5897
6397
  import { Slider as SliderPrimitive } from "@base-ui/react/slider";
5898
6398
  import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
5899
- var Slider = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
6399
+ var Slider = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
5900
6400
  SliderPrimitive.Root,
5901
6401
  {
5902
6402
  ref,
@@ -5934,7 +6434,7 @@ function RadiusCornerIcon({ corner, className }) {
5934
6434
  return /* @__PURE__ */ jsx13("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: cn("size-3", className), children: /* @__PURE__ */ jsx13("path", { d: paths[corner] }) });
5935
6435
  }
5936
6436
  function BorderRadiusInputs({ values, onChange }) {
5937
- const [individual, setIndividual] = React19.useState(false);
6437
+ const [individual, setIndividual] = React20.useState(false);
5938
6438
  const handleChange = (corners, numericValue) => {
5939
6439
  const newValue = {
5940
6440
  numericValue,
@@ -6067,7 +6567,7 @@ function BorderRadiusInputs({ values, onChange }) {
6067
6567
  }
6068
6568
 
6069
6569
  // src/panel/border-section.tsx
6070
- import * as React22 from "react";
6570
+ import * as React23 from "react";
6071
6571
 
6072
6572
  // src/ui/select.tsx
6073
6573
  import { Select as SelectPrimitive } from "@base-ui/react/select";
@@ -6132,21 +6632,21 @@ function SimpleSelect({
6132
6632
  }
6133
6633
 
6134
6634
  // src/ui/color-picker.tsx
6135
- import * as React20 from "react";
6635
+ import * as React21 from "react";
6136
6636
  import { Popover } from "@base-ui/react/popover";
6137
6637
  import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
6138
6638
  function ColorPickerPortal(props) {
6139
6639
  const container = usePortalContainer();
6140
6640
  return /* @__PURE__ */ jsx16(Popover.Portal, { container, ...props });
6141
6641
  }
6142
- var ColorPickerGroupContext = React20.createContext(null);
6642
+ var ColorPickerGroupContext = React21.createContext(null);
6143
6643
  function ColorPickerGroup({ children }) {
6144
- const [activePickerId, setActivePickerId] = React20.useState(null);
6644
+ const [activePickerId, setActivePickerId] = React21.useState(null);
6145
6645
  return /* @__PURE__ */ jsx16(ColorPickerGroupContext.Provider, { value: { activePickerId, setActivePickerId }, children });
6146
6646
  }
6147
6647
  function useDrag(onMove) {
6148
- const ref = React20.useRef(null);
6149
- const handlePointerEvent = React20.useCallback(
6648
+ const ref = React21.useRef(null);
6649
+ const handlePointerEvent = React21.useCallback(
6150
6650
  (e) => {
6151
6651
  const el = ref.current;
6152
6652
  if (!el) return;
@@ -6157,7 +6657,7 @@ function useDrag(onMove) {
6157
6657
  },
6158
6658
  [onMove]
6159
6659
  );
6160
- const onPointerDown = React20.useCallback(
6660
+ const onPointerDown = React21.useCallback(
6161
6661
  (e) => {
6162
6662
  e.preventDefault();
6163
6663
  ref.current?.setPointerCapture(e.pointerId);
@@ -6165,7 +6665,7 @@ function useDrag(onMove) {
6165
6665
  },
6166
6666
  [handlePointerEvent]
6167
6667
  );
6168
- const onPointerMove = React20.useCallback(
6668
+ const onPointerMove = React21.useCallback(
6169
6669
  (e) => {
6170
6670
  if (e.buttons === 0) return;
6171
6671
  handlePointerEvent(e);
@@ -6235,8 +6735,8 @@ function NumericInput({
6235
6735
  max,
6236
6736
  onChange
6237
6737
  }) {
6238
- const [local, setLocal] = React20.useState(Math.round(value).toString());
6239
- React20.useEffect(() => {
6738
+ const [local, setLocal] = React21.useState(Math.round(value).toString());
6739
+ React21.useEffect(() => {
6240
6740
  setLocal(Math.round(value).toString());
6241
6741
  }, [value]);
6242
6742
  return /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
@@ -6258,13 +6758,13 @@ function NumericInput({
6258
6758
  ] });
6259
6759
  }
6260
6760
  function ColorPickerPopover({ id, value, onChange, children }) {
6261
- const group = React20.useContext(ColorPickerGroupContext);
6761
+ const group = React21.useContext(ColorPickerGroupContext);
6262
6762
  const rgb = hexToRgb(value.hex);
6263
6763
  const initialHsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
6264
- const [hsv, setHsv] = React20.useState({ h: initialHsv.h, s: initialHsv.s, v: initialHsv.v });
6265
- const [alpha, setAlpha] = React20.useState(value.alpha);
6266
- const lastSyncedHex = React20.useRef(value.hex);
6267
- React20.useEffect(() => {
6764
+ const [hsv, setHsv] = React21.useState({ h: initialHsv.h, s: initialHsv.s, v: initialHsv.v });
6765
+ const [alpha, setAlpha] = React21.useState(value.alpha);
6766
+ const lastSyncedHex = React21.useRef(value.hex);
6767
+ React21.useEffect(() => {
6268
6768
  if (value.hex !== lastSyncedHex.current) {
6269
6769
  const newRgb = hexToRgb(value.hex);
6270
6770
  const newHsv = rgbToHsv(newRgb.r, newRgb.g, newRgb.b);
@@ -6277,7 +6777,7 @@ function ColorPickerPopover({ id, value, onChange, children }) {
6277
6777
  }
6278
6778
  setAlpha(value.alpha);
6279
6779
  }, [value.hex, value.alpha]);
6280
- const emitChange = React20.useCallback(
6780
+ const emitChange = React21.useCallback(
6281
6781
  (h, s, v, a) => {
6282
6782
  const newRgb = hsvToRgb(h, s, v);
6283
6783
  const hex = rgbToHex(newRgb.r, newRgb.g, newRgb.b);
@@ -6358,11 +6858,11 @@ function ColorPickerPopover({ id, value, onChange, children }) {
6358
6858
  const handleOpenChange = isControlled ? (open) => {
6359
6859
  group.setActivePickerId(open ? id : null);
6360
6860
  } : void 0;
6361
- const popupRef = React20.useRef(null);
6362
- const triggerRef = React20.useRef(null);
6363
- const onCloseRef = React20.useRef();
6861
+ const popupRef = React21.useRef(null);
6862
+ const triggerRef = React21.useRef(null);
6863
+ const onCloseRef = React21.useRef();
6364
6864
  onCloseRef.current = () => group?.setActivePickerId(null);
6365
- React20.useEffect(() => {
6865
+ React21.useEffect(() => {
6366
6866
  if (!isOpen) return;
6367
6867
  function handlePointerDown(e) {
6368
6868
  const path = e.composedPath();
@@ -6432,8 +6932,8 @@ function ColorPickerPopover({ id, value, onChange, children }) {
6432
6932
  ] });
6433
6933
  }
6434
6934
  function HexInput({ value, onChange }) {
6435
- const [local, setLocal] = React20.useState(value);
6436
- React20.useEffect(() => {
6935
+ const [local, setLocal] = React21.useState(value);
6936
+ React21.useEffect(() => {
6437
6937
  setLocal(value);
6438
6938
  }, [value]);
6439
6939
  return /* @__PURE__ */ jsx16(
@@ -6452,8 +6952,8 @@ function HexInput({ value, onChange }) {
6452
6952
  );
6453
6953
  }
6454
6954
  function AlphaInput({ value, onChange }) {
6455
- const [local, setLocal] = React20.useState(value.toString());
6456
- React20.useEffect(() => {
6955
+ const [local, setLocal] = React21.useState(value.toString());
6956
+ React21.useEffect(() => {
6457
6957
  setLocal(value.toString());
6458
6958
  }, [value]);
6459
6959
  return /* @__PURE__ */ jsx16(
@@ -6473,7 +6973,7 @@ function AlphaInput({ value, onChange }) {
6473
6973
  }
6474
6974
 
6475
6975
  // src/panel/fill-section.tsx
6476
- import * as React21 from "react";
6976
+ import * as React22 from "react";
6477
6977
  import {
6478
6978
  Paintbrush,
6479
6979
  Square,
@@ -6482,9 +6982,9 @@ import {
6482
6982
  } from "lucide-react";
6483
6983
  import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
6484
6984
  function ColorInput({ id, label, icon, value, onChange }) {
6485
- const [hexInput, setHexInput] = React21.useState(value.hex);
6486
- const [alphaInput, setAlphaInput] = React21.useState(value.alpha.toString());
6487
- React21.useEffect(() => {
6985
+ const [hexInput, setHexInput] = React22.useState(value.hex);
6986
+ const [alphaInput, setAlphaInput] = React22.useState(value.alpha.toString());
6987
+ React22.useEffect(() => {
6488
6988
  setHexInput(value.hex);
6489
6989
  setAlphaInput(value.alpha.toString());
6490
6990
  }, [value.hex, value.alpha]);
@@ -6683,7 +7183,7 @@ function BorderSideIcon({ side, className }) {
6683
7183
  ] });
6684
7184
  }
6685
7185
  function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, borderPosition, borderStyleControlPreference, onPositionChange, outlineStyle, outlineWidth }) {
6686
- const [selectedSide, setSelectedSide] = React22.useState("All");
7186
+ const [selectedSide, setSelectedSide] = React23.useState("All");
6687
7187
  const isOutline = borderPosition === "outline";
6688
7188
  const activeSides = selectedSide === "All" || selectedSide === "Custom" ? BORDER_SIDES : [selectedSide];
6689
7189
  const stylesMatch = activeSides.every(
@@ -6795,7 +7295,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
6795
7295
  onValueChange: (val) => handleStyleChange(val),
6796
7296
  options: BORDER_STYLE_OPTIONS,
6797
7297
  popupMinWidth: "120px",
6798
- children: borderStyleControlPreference === "icon" ? /* @__PURE__ */ jsx18(Tip, { label: `Border style: ${currentStyleLabel}`, children: /* @__PURE__ */ jsx18(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0 bg-muted px-2 text-xs hover:bg-muted-foreground/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: /* @__PURE__ */ jsx18(Settings2, { className: "size-3.5 text-muted-foreground" }) }) }) : /* @__PURE__ */ jsxs12(SelectTrigger, { className: "flex h-7 flex-1 items-center justify-between rounded-md border-0 bg-muted px-2 text-xs hover:bg-muted-foreground/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: [
7298
+ children: borderStyleControlPreference === "icon" ? /* @__PURE__ */ jsx18(Tip, { label: `Border style: ${currentStyleLabel}`, children: /* @__PURE__ */ jsx18(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0 px-2 text-xs text-muted-foreground hover:bg-muted-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: /* @__PURE__ */ jsx18(Settings2, { className: "size-3.5" }) }) }) : /* @__PURE__ */ jsxs12(SelectTrigger, { className: "flex h-7 flex-1 items-center justify-between rounded-md border-0 bg-muted px-2 text-xs hover:bg-muted-foreground/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: [
6799
7299
  /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1.5", children: [
6800
7300
  /* @__PURE__ */ jsx18(Square2, { className: "size-3.5 text-muted-foreground" }),
6801
7301
  /* @__PURE__ */ jsx18("span", { children: currentStyleLabel })
@@ -6811,7 +7311,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
6811
7311
  onValueChange: (val) => handleSideChange(val),
6812
7312
  options: BORDER_SIDE_OPTIONS.map((side) => ({ value: side, label: side })),
6813
7313
  popupMinWidth: "90px",
6814
- children: /* @__PURE__ */ jsx18(Tip, { label: `Sides: ${selectedSide}`, children: /* @__PURE__ */ jsx18(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0 bg-muted px-2 text-xs hover:bg-muted-foreground/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: selectedSide === "Custom" ? /* @__PURE__ */ jsx18(Grid2x22, { className: "size-3.5 text-muted-foreground", strokeWidth: 1 }) : selectedSide === "All" ? /* @__PURE__ */ jsx18(Square2, { className: "size-3.5 text-muted-foreground" }) : /* @__PURE__ */ jsx18(BorderSideIcon, { side: selectedSide, className: "text-muted-foreground" }) }) })
7314
+ children: /* @__PURE__ */ jsx18(Tip, { label: `Sides: ${selectedSide}`, children: /* @__PURE__ */ jsx18(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0 px-2 text-xs text-muted-foreground hover:bg-muted-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", children: selectedSide === "Custom" ? /* @__PURE__ */ jsx18(Grid2x22, { className: "size-3.5 text-muted-foreground", strokeWidth: 1 }) : selectedSide === "All" ? /* @__PURE__ */ jsx18(Square2, { className: "size-3.5 text-muted-foreground" }) : /* @__PURE__ */ jsx18(BorderSideIcon, { side: selectedSide, className: "text-muted-foreground" }) }) })
6815
7315
  }
6816
7316
  )
6817
7317
  ] }),
@@ -6831,23 +7331,27 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
6831
7331
  )
6832
7332
  ] }) }, side);
6833
7333
  }) }),
6834
- activeColor && activeColorChange && /* @__PURE__ */ jsx18(
6835
- ColorInput,
6836
- {
6837
- id: isOutline ? "outline-color" : "border-color",
6838
- label: isOutline ? "Outline" : "Border",
6839
- icon: isOutline ? /* @__PURE__ */ jsx18(Focus2, { className: "size-3.5" }) : /* @__PURE__ */ jsx18(Square2, { className: "size-3.5" }),
6840
- value: activeColor,
6841
- onChange: activeColorChange
6842
- }
6843
- )
7334
+ activeColor && activeColorChange && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5", children: [
7335
+ /* @__PURE__ */ jsx18("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx18(
7336
+ ColorInput,
7337
+ {
7338
+ id: isOutline ? "outline-color" : "border-color",
7339
+ label: isOutline ? "Outline" : "Border",
7340
+ icon: isOutline ? /* @__PURE__ */ jsx18(Focus2, { className: "size-3.5" }) : /* @__PURE__ */ jsx18(Square2, { className: "size-3.5" }),
7341
+ value: activeColor,
7342
+ onChange: activeColorChange
7343
+ }
7344
+ ) }),
7345
+ borderStyleControlPreference === "icon" && /* @__PURE__ */ jsx18("div", { className: "w-[30px] shrink-0" }),
7346
+ !isOutline && /* @__PURE__ */ jsx18("div", { className: "w-[30px] shrink-0" })
7347
+ ] })
6844
7348
  ] });
6845
7349
  }
6846
7350
  function BorderSection({ border, borderColor, outlineColor, borderStyleControlPreference, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, pendingStyles }) {
6847
7351
  const hasOutlinePending = Boolean(
6848
7352
  pendingStyles?.["outline-style"] || pendingStyles?.["outline-width"]
6849
7353
  );
6850
- const [borderPosition, setBorderPosition] = React22.useState(
7354
+ const [borderPosition, setBorderPosition] = React23.useState(
6851
7355
  hasOutlinePending ? "outline" : "border"
6852
7356
  );
6853
7357
  const isOutline = borderPosition === "outline";
@@ -6953,7 +7457,7 @@ function BorderSection({ border, borderColor, outlineColor, borderStyleControlPr
6953
7457
  }
6954
7458
 
6955
7459
  // src/panel/shadow-section.tsx
6956
- import * as React23 from "react";
7460
+ import * as React24 from "react";
6957
7461
 
6958
7462
  // src/shadow-utils.ts
6959
7463
  var TAILWIND_SHADOW_PRESETS = [
@@ -7093,9 +7597,9 @@ function ShadowLayerEditor({
7093
7597
  onChange,
7094
7598
  onRemoveLayer
7095
7599
  }) {
7096
- const [hexInput, setHexInput] = React23.useState(layer.color.hex);
7097
- const [alphaInput, setAlphaInput] = React23.useState(String(layer.color.alpha));
7098
- React23.useEffect(() => {
7600
+ const [hexInput, setHexInput] = React24.useState(layer.color.hex);
7601
+ const [alphaInput, setAlphaInput] = React24.useState(String(layer.color.alpha));
7602
+ React24.useEffect(() => {
7099
7603
  setHexInput(layer.color.hex);
7100
7604
  setAlphaInput(String(layer.color.alpha));
7101
7605
  }, [layer.color.hex, layer.color.alpha]);
@@ -7186,10 +7690,10 @@ function ShadowLayerEditor({
7186
7690
  }
7187
7691
  function ShadowSection({ boxShadow, onSetCSS, pendingStyles }) {
7188
7692
  const effectiveShadow = (pendingStyles?.["box-shadow"] ?? boxShadow ?? "none").trim();
7189
- const parsedLayers = React23.useMemo(() => parseShadowLayers(effectiveShadow), [effectiveShadow]);
7190
- const [layers, setLayers] = React23.useState(parsedLayers);
7693
+ const parsedLayers = React24.useMemo(() => parseShadowLayers(effectiveShadow), [effectiveShadow]);
7694
+ const [layers, setLayers] = React24.useState(parsedLayers);
7191
7695
  const hasShadow = layers.length > 0;
7192
- React23.useEffect(() => {
7696
+ React24.useEffect(() => {
7193
7697
  setLayers(parsedLayers);
7194
7698
  }, [parsedLayers]);
7195
7699
  const commitLayers = (nextLayers) => {
@@ -7493,7 +7997,7 @@ function PanelHeader({
7493
7997
  }
7494
7998
 
7495
7999
  // src/panel/panel-footer.tsx
7496
- import * as React24 from "react";
8000
+ import * as React25 from "react";
7497
8001
  import { X as X3, Copy as Copy2, Check as Check3, Send as Send2 } from "lucide-react";
7498
8002
  import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
7499
8003
  var panelBarBaseClass2 = "flex h-11 shrink-0 items-center border-border/50 bg-background pl-3 pr-2";
@@ -7507,9 +8011,9 @@ function PanelFooter({
7507
8011
  onPointerUp,
7508
8012
  onPointerCancel
7509
8013
  }) {
7510
- const [copied, setCopied] = React24.useState(false);
7511
- const [copyError, setCopyError] = React24.useState(false);
7512
- const [sendStatus, setSendStatus] = React24.useState("idle");
8014
+ const [copied, setCopied] = React25.useState(false);
8015
+ const [copyError, setCopyError] = React25.useState(false);
8016
+ const [sendStatus, setSendStatus] = React25.useState("idle");
7513
8017
  const handleCopy = async () => {
7514
8018
  const success = await onExportEdits();
7515
8019
  if (success) {
@@ -7577,7 +8081,7 @@ function PanelFooter({
7577
8081
  }
7578
8082
 
7579
8083
  // src/panel/spacing-inputs.tsx
7580
- import * as React25 from "react";
8084
+ import * as React26 from "react";
7581
8085
  import {
7582
8086
  ArrowRight,
7583
8087
  ArrowDown,
@@ -7590,7 +8094,7 @@ import {
7590
8094
  } from "lucide-react";
7591
8095
  import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
7592
8096
  function SpacingInputs({ prefix, values, onChange }) {
7593
- const [individual, setIndividual] = React25.useState(false);
8097
+ const [individual, setIndividual] = React26.useState(false);
7594
8098
  const allowNegative = prefix === "margin";
7595
8099
  const handleChange = (sides, numericValue) => {
7596
8100
  const clamped = allowNegative ? numericValue : Math.max(0, numericValue);
@@ -7708,7 +8212,7 @@ function SpacingInputs({ prefix, values, onChange }) {
7708
8212
  }
7709
8213
 
7710
8214
  // src/panel/sizing-inputs.tsx
7711
- import * as React26 from "react";
8215
+ import * as React27 from "react";
7712
8216
  import {
7713
8217
  Check as Check4,
7714
8218
  ChevronsUpDown,
@@ -7729,8 +8233,8 @@ var DISTRIBUTE_LABELS = {
7729
8233
  "space-evenly": "Evenly"
7730
8234
  };
7731
8235
  function SizingFixedInput({ value, onValueChange }) {
7732
- const [localValue, setLocalValue] = React26.useState(String(value));
7733
- React26.useEffect(() => {
8236
+ const [localValue, setLocalValue] = React27.useState(String(value));
8237
+ React27.useEffect(() => {
7734
8238
  setLocalValue(String(value));
7735
8239
  }, [value]);
7736
8240
  return /* @__PURE__ */ jsx24(
@@ -7791,9 +8295,9 @@ function SizingDropdown({ label, value, onChange }) {
7791
8295
  }
7792
8296
  function SizingInputs({ width, height, onWidthChange, onHeightChange }) {
7793
8297
  const { selectedElement } = useDirectEditState();
7794
- const [locked, setLocked] = React26.useState(false);
7795
- const ratioRef = React26.useRef(1);
7796
- React26.useEffect(() => {
8298
+ const [locked, setLocked] = React27.useState(false);
8299
+ const ratioRef = React27.useRef(1);
8300
+ React27.useEffect(() => {
7797
8301
  setLocked(false);
7798
8302
  }, [selectedElement]);
7799
8303
  const canLock = width.mode === "fixed" && height.mode === "fixed" && height.value.numericValue > 0 && width.value.numericValue > 0;
@@ -8057,7 +8561,7 @@ function LayoutSection({
8057
8561
  }
8058
8562
 
8059
8563
  // src/use-panel-position.ts
8060
- import * as React27 from "react";
8564
+ import * as React28 from "react";
8061
8565
  var PANEL_WIDTH = 300;
8062
8566
  var PANEL_HEIGHT = 420;
8063
8567
  var STORAGE_KEY2 = "direct-edit-panel-position";
@@ -8139,14 +8643,14 @@ function getInitialPosition() {
8139
8643
  });
8140
8644
  }
8141
8645
  function usePanelPosition() {
8142
- const [position, setPosition] = React27.useState(getInitialPosition);
8143
- const [isDragging, setIsDragging] = React27.useState(false);
8144
- const [isSnapping, setIsSnapping] = React27.useState(false);
8145
- const [dragOffset, setDragOffset] = React27.useState({ x: 0, y: 0 });
8146
- const snapTimerRef = React27.useRef(null);
8147
- const panelRef = React27.useRef(null);
8148
- const positionRef = React27.useRef(position);
8149
- React27.useEffect(() => {
8646
+ const [position, setPosition] = React28.useState(getInitialPosition);
8647
+ const [isDragging, setIsDragging] = React28.useState(false);
8648
+ const [isSnapping, setIsSnapping] = React28.useState(false);
8649
+ const [dragOffset, setDragOffset] = React28.useState({ x: 0, y: 0 });
8650
+ const snapTimerRef = React28.useRef(null);
8651
+ const panelRef = React28.useRef(null);
8652
+ const positionRef = React28.useRef(position);
8653
+ React28.useEffect(() => {
8150
8654
  positionRef.current = position;
8151
8655
  }, [position]);
8152
8656
  const handlePointerDown = (e) => {
@@ -8202,7 +8706,7 @@ function usePanelPosition() {
8202
8706
  } catch {
8203
8707
  }
8204
8708
  };
8205
- React27.useEffect(() => {
8709
+ React28.useEffect(() => {
8206
8710
  function handleResize() {
8207
8711
  setPosition((prev) => {
8208
8712
  const next = snapToEdge(prev);
@@ -8213,7 +8717,7 @@ function usePanelPosition() {
8213
8717
  window.addEventListener("resize", handleResize);
8214
8718
  return () => window.removeEventListener("resize", handleResize);
8215
8719
  }, []);
8216
- React27.useEffect(() => {
8720
+ React28.useEffect(() => {
8217
8721
  return () => {
8218
8722
  if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
8219
8723
  };
@@ -8274,12 +8778,12 @@ function DirectEditPanelInner({
8274
8778
  const canTriggerSend = canSendToAgent || hasPendingChanges;
8275
8779
  const isDraggable = onHeaderPointerDown !== void 0;
8276
8780
  const sectionRefs = {
8277
- layout: React28.useRef(null),
8278
- radius: React28.useRef(null),
8279
- border: React28.useRef(null),
8280
- shadow: React28.useRef(null),
8281
- colors: React28.useRef(null),
8282
- text: React28.useRef(null)
8781
+ layout: React29.useRef(null),
8782
+ radius: React29.useRef(null),
8783
+ border: React29.useRef(null),
8784
+ shadow: React29.useRef(null),
8785
+ colors: React29.useRef(null),
8786
+ text: React29.useRef(null)
8283
8787
  };
8284
8788
  const { scrollRef, activeSection } = useSectionNav(sectionRefs);
8285
8789
  return /* @__PURE__ */ jsx27(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs21(
@@ -8322,7 +8826,7 @@ function DirectEditPanelInner({
8322
8826
  sectionRefs
8323
8827
  }
8324
8828
  ),
8325
- /* @__PURE__ */ jsxs21("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, children: [
8829
+ /* @__PURE__ */ jsxs21("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, onWheelCapture: (e) => e.stopPropagation(), children: [
8326
8830
  /* @__PURE__ */ jsx27(
8327
8831
  LayoutSection,
8328
8832
  {
@@ -8477,8 +8981,12 @@ function DirectEditPanelContent() {
8477
8981
  handlePointerUp,
8478
8982
  handlePointerCancel
8479
8983
  } = usePanelPosition();
8480
- const [hoverHighlight, setHoverHighlight] = React28.useState(null);
8481
- const [commentInputAttention, setCommentInputAttention] = React28.useState(null);
8984
+ const [hoverHighlight, setHoverHighlight] = React29.useState(null);
8985
+ const [commentInputAttention, setCommentInputAttention] = React29.useState(null);
8986
+ const commentDraftRef = React29.useRef("");
8987
+ React29.useEffect(() => {
8988
+ commentDraftRef.current = "";
8989
+ }, [activeCommentId]);
8482
8990
  const { isActive: measurementActive, hoveredElement, measurements, mousePosition } = useMeasurement(
8483
8991
  isOpen ? selectedElement : null
8484
8992
  );
@@ -8489,21 +8997,29 @@ function DirectEditPanelContent() {
8489
8997
  } = useMove({
8490
8998
  onMoveComplete: handleMoveComplete
8491
8999
  });
8492
- const triggerCommentInputAttention = React28.useCallback((commentId) => {
9000
+ const triggerCommentInputAttention = React29.useCallback((commentId) => {
8493
9001
  setCommentInputAttention((prev) => prev?.commentId === commentId ? { commentId, nonce: prev.nonce + 1 } : { commentId, nonce: 1 });
8494
9002
  }, []);
8495
- const hasPendingCommentDraft = React28.useCallback((nextCommentId = null) => {
9003
+ const hasPendingCommentDraft = React29.useCallback((nextCommentId = null) => {
8496
9004
  if (!activeCommentId) return false;
8497
9005
  if (nextCommentId && nextCommentId === activeCommentId) return false;
8498
9006
  const active = comments.find((comment) => comment.id === activeCommentId);
8499
- if (!active || active.text.trim().length > 0) return false;
9007
+ if (!active) return false;
9008
+ const hasUnsentDraft = active.text.trim().length === 0 && commentDraftRef.current.trim().length > 0;
9009
+ if (!hasUnsentDraft) return false;
8500
9010
  triggerCommentInputAttention(active.id);
8501
9011
  return true;
8502
9012
  }, [activeCommentId, comments, triggerCommentInputAttention]);
8503
- const handleSetActiveComment = React28.useCallback((id) => {
8504
- if (id && hasPendingCommentDraft(id)) return;
9013
+ const handleSetActiveComment = React29.useCallback((id) => {
9014
+ if (hasPendingCommentDraft(id)) return;
9015
+ if (activeCommentId && activeCommentId !== id) {
9016
+ const active = comments.find((comment) => comment.id === activeCommentId);
9017
+ if (active && active.text.trim().length === 0) {
9018
+ deleteComment(active.id);
9019
+ }
9020
+ }
8505
9021
  setActiveCommentId(id);
8506
- }, [hasPendingCommentDraft, setActiveCommentId]);
9022
+ }, [activeCommentId, comments, hasPendingCommentDraft, deleteComment, setActiveCommentId]);
8507
9023
  const overlay = editModeActive && container ? createPortal(
8508
9024
  /* @__PURE__ */ jsx27(
8509
9025
  InteractionOverlay,
@@ -8516,7 +9032,7 @@ function DirectEditPanelContent() {
8516
9032
  onSelectElement: selectElement,
8517
9033
  onStartTextEditing: startTextEditing,
8518
9034
  onAddComment: addComment,
8519
- onSetActiveCommentId: setActiveCommentId,
9035
+ onSetActiveCommentId: handleSetActiveComment,
8520
9036
  onSetHoverHighlight: setHoverHighlight,
8521
9037
  hasPendingCommentDraft
8522
9038
  }
@@ -8535,7 +9051,8 @@ function DirectEditPanelContent() {
8535
9051
  onDelete: deleteComment,
8536
9052
  onExport: exportComment,
8537
9053
  onSendToAgent: sendCommentToAgent2,
8538
- attentionRequest: commentInputAttention
9054
+ attentionRequest: commentInputAttention,
9055
+ draftRef: commentDraftRef
8539
9056
  }
8540
9057
  ),
8541
9058
  container
@@ -8577,6 +9094,7 @@ function DirectEditPanelContent() {
8577
9094
  ghostPosition: dragState.ghostPosition,
8578
9095
  onMoveStart: handleMoveStart,
8579
9096
  showMoveHandle,
9097
+ activeTool,
8580
9098
  isTextEditing: Boolean(textEditingElement),
8581
9099
  onDoubleClick: (clientX, clientY) => {
8582
9100
  if (!selectedElement) return;
@@ -8682,8 +9200,8 @@ function DirectEditPanelContent() {
8682
9200
  );
8683
9201
  }
8684
9202
  function DirectEditPanel() {
8685
- const [mounted, setMounted] = React28.useState(false);
8686
- React28.useEffect(() => {
9203
+ const [mounted, setMounted] = React29.useState(false);
9204
+ React29.useEffect(() => {
8687
9205
  setMounted(true);
8688
9206
  }, []);
8689
9207
  if (!mounted) {
@@ -8693,26 +9211,59 @@ function DirectEditPanel() {
8693
9211
  }
8694
9212
 
8695
9213
  // src/toolbar.tsx
8696
- import * as React34 from "react";
9214
+ import * as React36 from "react";
8697
9215
  import { createPortal as createPortal3 } from "react-dom";
8698
9216
 
8699
9217
  // src/rulers-overlay.tsx
8700
- import * as React29 from "react";
9218
+ import * as React30 from "react";
8701
9219
  import { createPortal as createPortal2 } from "react-dom";
8702
9220
  import { Fragment as Fragment6, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
8703
9221
  var RULER_SIZE2 = 20;
8704
9222
  var GUIDELINE_COLOR = "#FF6B6B";
9223
+ var SNAPPED_COLOR = "#0D99FF";
8705
9224
  var HIT_ZONE = 9;
9225
+ function computeCanvasRulerScrollOffset(pan, zoom, bodyOffset2) {
9226
+ if (zoom === 0) return -pan;
9227
+ return bodyOffset2 * (1 - 1 / zoom) - pan;
9228
+ }
9229
+ function computeTickIntervals(zoom) {
9230
+ const MIN_LABEL_SPACING_PX = 80;
9231
+ const rawInterval = MIN_LABEL_SPACING_PX / zoom;
9232
+ const magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval)));
9233
+ const residual = rawInterval / magnitude;
9234
+ let nice;
9235
+ if (residual <= 1) nice = 1;
9236
+ else if (residual <= 2) nice = 2;
9237
+ else if (residual <= 2.5) nice = 2.5;
9238
+ else if (residual <= 5) nice = 5;
9239
+ else nice = 10;
9240
+ const major = nice * magnitude;
9241
+ const stepsPerMajor = 10;
9242
+ const minor = major / stepsPerMajor;
9243
+ return { major, minor, stepsPerMajor };
9244
+ }
9245
+ function getColorSchemeQuery() {
9246
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
9247
+ return null;
9248
+ }
9249
+ return window.matchMedia("(prefers-color-scheme: dark)");
9250
+ }
8706
9251
  function subscribeColorScheme(cb) {
8707
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
8708
- mq.addEventListener("change", cb);
8709
- return () => mq.removeEventListener("change", cb);
9252
+ const mq = getColorSchemeQuery();
9253
+ if (!mq) return () => {
9254
+ };
9255
+ if (typeof mq.addEventListener === "function") {
9256
+ mq.addEventListener("change", cb);
9257
+ return () => mq.removeEventListener("change", cb);
9258
+ }
9259
+ mq.addListener(cb);
9260
+ return () => mq.removeListener(cb);
8710
9261
  }
8711
9262
  function getColorScheme() {
8712
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
9263
+ return getColorSchemeQuery()?.matches ?? false;
8713
9264
  }
8714
9265
  function useSystemDark() {
8715
- return React29.useSyncExternalStore(subscribeColorScheme, getColorScheme, () => false);
9266
+ return React30.useSyncExternalStore(subscribeColorScheme, getColorScheme, () => false);
8716
9267
  }
8717
9268
  var rulerFont = {
8718
9269
  fontFamily: "system-ui, -apple-system, sans-serif",
@@ -8721,13 +9272,14 @@ var rulerFont = {
8721
9272
  };
8722
9273
  function HorizontalRuler({
8723
9274
  scrollOffset,
9275
+ zoom = 1,
8724
9276
  onPointerDown
8725
9277
  }) {
8726
- const canvasRef = React29.useRef(null);
9278
+ const canvasRef = React30.useRef(null);
8727
9279
  const viewportWidth = useViewportWidth();
8728
9280
  const { theme } = useDirectEditState();
8729
9281
  const systemDark = useSystemDark();
8730
- React29.useEffect(() => {
9282
+ React30.useEffect(() => {
8731
9283
  const canvas = canvasRef.current;
8732
9284
  if (!canvas) return;
8733
9285
  const dpr = window.devicePixelRatio || 1;
@@ -8745,12 +9297,16 @@ function HorizontalRuler({
8745
9297
  const computed = getComputedStyle(canvas);
8746
9298
  const tick = computed.getPropertyValue("color");
8747
9299
  const label = tick;
8748
- const startPx = Math.floor(scrollOffset.x / 10) * 10;
8749
- const endPx = scrollOffset.x + width;
8750
- for (let px = startPx; px <= endPx; px += 10) {
8751
- const x = px - scrollOffset.x;
8752
- const isMajor = px % 100 === 0;
8753
- const isMid = px % 50 === 0;
9300
+ const { minor, stepsPerMajor } = computeTickIntervals(zoom);
9301
+ const midIdx = stepsPerMajor / 2;
9302
+ const visibleContentWidth = width / zoom;
9303
+ const startIdx = Math.floor(scrollOffset.x / minor);
9304
+ const endIdx = Math.ceil((scrollOffset.x + visibleContentWidth) / minor);
9305
+ for (let i = startIdx; i <= endIdx; i++) {
9306
+ const px = i * minor;
9307
+ const x = (px - scrollOffset.x) * zoom;
9308
+ const isMajor = i % stepsPerMajor === 0;
9309
+ const isMid = !isMajor && i % midIdx === 0;
8754
9310
  ctx.beginPath();
8755
9311
  ctx.moveTo(x, height);
8756
9312
  ctx.lineTo(x, height - (isMajor ? 10 : isMid ? 7 : 4));
@@ -8758,15 +9314,15 @@ function HorizontalRuler({
8758
9314
  ctx.globalAlpha = 0.6;
8759
9315
  ctx.lineWidth = 1;
8760
9316
  ctx.stroke();
8761
- if (isMajor && px !== 0) {
9317
+ if (isMajor) {
8762
9318
  ctx.globalAlpha = 1;
8763
9319
  ctx.fillStyle = label;
8764
9320
  ctx.font = "9px system-ui, -apple-system, sans-serif";
8765
9321
  ctx.textAlign = "center";
8766
- ctx.fillText(String(px), x, 9);
9322
+ ctx.fillText(String(Math.round(px)), x, 9);
8767
9323
  }
8768
9324
  }
8769
- }, [scrollOffset.x, viewportWidth, theme, systemDark]);
9325
+ }, [scrollOffset.x, viewportWidth, zoom, theme, systemDark]);
8770
9326
  return /* @__PURE__ */ jsx28(
8771
9327
  "div",
8772
9328
  {
@@ -8792,13 +9348,14 @@ function HorizontalRuler({
8792
9348
  }
8793
9349
  function VerticalRuler({
8794
9350
  scrollOffset,
9351
+ zoom = 1,
8795
9352
  onPointerDown
8796
9353
  }) {
8797
- const canvasRef = React29.useRef(null);
9354
+ const canvasRef = React30.useRef(null);
8798
9355
  const viewportHeight = useViewportHeight();
8799
9356
  const { theme } = useDirectEditState();
8800
9357
  const systemDark = useSystemDark();
8801
- React29.useEffect(() => {
9358
+ React30.useEffect(() => {
8802
9359
  const canvas = canvasRef.current;
8803
9360
  if (!canvas) return;
8804
9361
  const dpr = window.devicePixelRatio || 1;
@@ -8816,12 +9373,16 @@ function VerticalRuler({
8816
9373
  const computed = getComputedStyle(canvas);
8817
9374
  const tick = computed.getPropertyValue("color");
8818
9375
  const label = tick;
8819
- const startPx = Math.floor(scrollOffset.y / 10) * 10;
8820
- const endPx = scrollOffset.y + height;
8821
- for (let px = startPx; px <= endPx; px += 10) {
8822
- const y = px - scrollOffset.y;
8823
- const isMajor = px % 100 === 0;
8824
- const isMid = px % 50 === 0;
9376
+ const { minor, stepsPerMajor } = computeTickIntervals(zoom);
9377
+ const midIdx = stepsPerMajor / 2;
9378
+ const visibleContentHeight = height / zoom;
9379
+ const startIdx = Math.floor(scrollOffset.y / minor);
9380
+ const endIdx = Math.ceil((scrollOffset.y + visibleContentHeight) / minor);
9381
+ for (let i = startIdx; i <= endIdx; i++) {
9382
+ const px = i * minor;
9383
+ const y = (px - scrollOffset.y) * zoom;
9384
+ const isMajor = i % stepsPerMajor === 0;
9385
+ const isMid = !isMajor && i % midIdx === 0;
8825
9386
  ctx.beginPath();
8826
9387
  ctx.moveTo(width, y);
8827
9388
  ctx.lineTo(width - (isMajor ? 10 : isMid ? 7 : 4), y);
@@ -8829,7 +9390,7 @@ function VerticalRuler({
8829
9390
  ctx.globalAlpha = 0.6;
8830
9391
  ctx.lineWidth = 1;
8831
9392
  ctx.stroke();
8832
- if (isMajor && px !== 0) {
9393
+ if (isMajor) {
8833
9394
  ctx.save();
8834
9395
  ctx.globalAlpha = 1;
8835
9396
  ctx.fillStyle = label;
@@ -8837,11 +9398,11 @@ function VerticalRuler({
8837
9398
  ctx.textAlign = "center";
8838
9399
  ctx.translate(9, y);
8839
9400
  ctx.rotate(-Math.PI / 2);
8840
- ctx.fillText(String(px), 0, 0);
9401
+ ctx.fillText(String(Math.round(px)), 0, 0);
8841
9402
  ctx.restore();
8842
9403
  }
8843
9404
  }
8844
- }, [scrollOffset.y, viewportHeight, theme, systemDark]);
9405
+ }, [scrollOffset.y, viewportHeight, zoom, theme, systemDark]);
8845
9406
  return /* @__PURE__ */ jsx28(
8846
9407
  "div",
8847
9408
  {
@@ -8885,17 +9446,26 @@ function CornerSquare() {
8885
9446
  }
8886
9447
  );
8887
9448
  }
9449
+ function computeGuidelineViewportPos(position, orientation) {
9450
+ const snap = getCanvasSnapshot();
9451
+ const zoom = snap.active ? snap.zoom : 1;
9452
+ const pan = orientation === "horizontal" ? snap.active ? snap.panY : -window.scrollY : snap.active ? snap.panX : -window.scrollX;
9453
+ if (snap.active) {
9454
+ const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
9455
+ return bo + (position - bo + pan) * zoom;
9456
+ }
9457
+ return (position + pan) * zoom;
9458
+ }
8888
9459
  function GuidelineLine({
8889
9460
  guideline,
8890
- scrollOffset,
8891
9461
  isActive,
9462
+ isSnapped,
8892
9463
  dragPosition,
8893
9464
  onStartDrag,
8894
9465
  onDelete
8895
9466
  }) {
8896
9467
  const isHorizontal = guideline.orientation === "horizontal";
8897
- const scrollPos = isHorizontal ? scrollOffset.y : scrollOffset.x;
8898
- const viewportPos = guideline.position - scrollPos;
9468
+ const lineColor = isActive && isSnapped ? SNAPPED_COLOR : GUIDELINE_COLOR;
8899
9469
  const handlePointerDown = (e) => {
8900
9470
  e.preventDefault();
8901
9471
  e.stopPropagation();
@@ -8906,119 +9476,137 @@ function GuidelineLine({
8906
9476
  e.stopPropagation();
8907
9477
  onDelete(guideline.id);
8908
9478
  };
8909
- const displayPos = isActive && dragPosition !== null ? dragPosition : viewportPos;
9479
+ const isDragging = isActive && dragPosition !== null;
9480
+ const viewportPos = isDragging ? dragPosition : computeGuidelineViewportPos(guideline.position, guideline.orientation);
9481
+ const translate = isHorizontal ? `translateY(${viewportPos}px)` : `translateX(${viewportPos}px)`;
8910
9482
  if (isHorizontal) {
8911
- return /* @__PURE__ */ jsxs22(Fragment6, { children: [
8912
- /* @__PURE__ */ jsx28(
8913
- "div",
8914
- {
8915
- "data-direct-edit": "guideline",
8916
- style: {
8917
- position: "fixed",
8918
- top: displayPos,
8919
- left: 0,
8920
- right: 0,
8921
- height: 1,
8922
- background: GUIDELINE_COLOR,
8923
- zIndex: 99993,
8924
- pointerEvents: "none"
8925
- }
8926
- }
8927
- ),
8928
- /* @__PURE__ */ jsx28(
8929
- "div",
8930
- {
8931
- style: {
8932
- position: "fixed",
8933
- top: displayPos - Math.floor(HIT_ZONE / 2),
8934
- left: RULER_SIZE2,
8935
- right: 0,
8936
- height: HIT_ZONE,
8937
- zIndex: 99993,
8938
- cursor: "ns-resize",
8939
- pointerEvents: "auto"
8940
- },
8941
- onPointerDown: handlePointerDown,
8942
- onDoubleClick: handleDoubleClick
8943
- }
8944
- ),
8945
- isActive && /* @__PURE__ */ jsx28(
8946
- "div",
8947
- {
8948
- style: {
8949
- position: "fixed",
8950
- top: displayPos + 4,
8951
- left: RULER_SIZE2 + 4,
8952
- background: GUIDELINE_COLOR,
8953
- color: "#fff",
8954
- padding: "1px 4px",
8955
- borderRadius: 2,
8956
- zIndex: 99995,
8957
- pointerEvents: "none",
8958
- ...rulerFont
8959
- },
8960
- children: Math.round(guideline.position)
8961
- }
8962
- )
8963
- ] });
8964
- }
8965
- return /* @__PURE__ */ jsxs22(Fragment6, { children: [
8966
- /* @__PURE__ */ jsx28(
9483
+ return /* @__PURE__ */ jsxs22(
8967
9484
  "div",
8968
9485
  {
8969
- "data-direct-edit": "guideline",
9486
+ "data-gl-pos": guideline.position,
9487
+ "data-gl-orient": "h",
9488
+ ...isDragging ? { "data-gl-dragging": "" } : {},
8970
9489
  style: {
8971
9490
  position: "fixed",
8972
- left: displayPos,
8973
9491
  top: 0,
8974
- bottom: 0,
8975
- width: 1,
8976
- background: GUIDELINE_COLOR,
9492
+ left: 0,
9493
+ right: 0,
9494
+ height: 0,
9495
+ transform: translate,
8977
9496
  zIndex: 99993,
8978
9497
  pointerEvents: "none"
8979
- }
8980
- }
8981
- ),
8982
- /* @__PURE__ */ jsx28(
8983
- "div",
8984
- {
8985
- style: {
8986
- position: "fixed",
8987
- left: displayPos - Math.floor(HIT_ZONE / 2),
8988
- top: RULER_SIZE2,
8989
- bottom: 0,
8990
- width: HIT_ZONE,
8991
- zIndex: 99993,
8992
- cursor: "ew-resize",
8993
- pointerEvents: "auto"
8994
9498
  },
8995
- onPointerDown: handlePointerDown,
8996
- onDoubleClick: handleDoubleClick
8997
- }
8998
- ),
8999
- isActive && /* @__PURE__ */ jsx28(
9000
- "div",
9001
- {
9002
- style: {
9003
- position: "fixed",
9004
- left: displayPos + 4,
9005
- top: RULER_SIZE2 + 4,
9006
- background: GUIDELINE_COLOR,
9007
- color: "#fff",
9008
- padding: "1px 4px",
9009
- borderRadius: 2,
9010
- zIndex: 99995,
9011
- pointerEvents: "none",
9012
- ...rulerFont
9013
- },
9014
- children: Math.round(guideline.position)
9499
+ children: [
9500
+ /* @__PURE__ */ jsx28(
9501
+ "div",
9502
+ {
9503
+ "data-direct-edit": "guideline",
9504
+ style: { position: "absolute", top: 0, left: 0, right: 0, height: 1, background: lineColor }
9505
+ }
9506
+ ),
9507
+ /* @__PURE__ */ jsx28(
9508
+ "div",
9509
+ {
9510
+ style: {
9511
+ position: "absolute",
9512
+ top: -Math.floor(HIT_ZONE / 2),
9513
+ left: RULER_SIZE2,
9514
+ right: 0,
9515
+ height: HIT_ZONE,
9516
+ cursor: "ns-resize",
9517
+ pointerEvents: "auto"
9518
+ },
9519
+ onPointerDown: handlePointerDown,
9520
+ onDoubleClick: handleDoubleClick
9521
+ }
9522
+ ),
9523
+ isActive && /* @__PURE__ */ jsx28(
9524
+ "div",
9525
+ {
9526
+ style: {
9527
+ position: "absolute",
9528
+ top: 4,
9529
+ left: RULER_SIZE2 + 4,
9530
+ background: lineColor,
9531
+ color: "#fff",
9532
+ padding: "1px 4px",
9533
+ borderRadius: 2,
9534
+ zIndex: 99995,
9535
+ pointerEvents: "none",
9536
+ ...rulerFont
9537
+ },
9538
+ children: Math.round(guideline.position)
9539
+ }
9540
+ )
9541
+ ]
9015
9542
  }
9016
- )
9017
- ] });
9543
+ );
9544
+ }
9545
+ return /* @__PURE__ */ jsxs22(
9546
+ "div",
9547
+ {
9548
+ "data-gl-pos": guideline.position,
9549
+ "data-gl-orient": "v",
9550
+ ...isDragging ? { "data-gl-dragging": "" } : {},
9551
+ style: {
9552
+ position: "fixed",
9553
+ top: 0,
9554
+ left: 0,
9555
+ bottom: 0,
9556
+ width: 0,
9557
+ transform: translate,
9558
+ zIndex: 99993,
9559
+ pointerEvents: "none"
9560
+ },
9561
+ children: [
9562
+ /* @__PURE__ */ jsx28(
9563
+ "div",
9564
+ {
9565
+ "data-direct-edit": "guideline",
9566
+ style: { position: "absolute", left: 0, top: 0, bottom: 0, width: 1, background: lineColor }
9567
+ }
9568
+ ),
9569
+ /* @__PURE__ */ jsx28(
9570
+ "div",
9571
+ {
9572
+ style: {
9573
+ position: "absolute",
9574
+ left: -Math.floor(HIT_ZONE / 2),
9575
+ top: RULER_SIZE2,
9576
+ bottom: 0,
9577
+ width: HIT_ZONE,
9578
+ cursor: "ew-resize",
9579
+ pointerEvents: "auto"
9580
+ },
9581
+ onPointerDown: handlePointerDown,
9582
+ onDoubleClick: handleDoubleClick
9583
+ }
9584
+ ),
9585
+ isActive && /* @__PURE__ */ jsx28(
9586
+ "div",
9587
+ {
9588
+ style: {
9589
+ position: "absolute",
9590
+ left: 4,
9591
+ top: RULER_SIZE2 + 4,
9592
+ background: lineColor,
9593
+ color: "#fff",
9594
+ padding: "1px 4px",
9595
+ borderRadius: 2,
9596
+ zIndex: 99995,
9597
+ pointerEvents: "none",
9598
+ ...rulerFont
9599
+ },
9600
+ children: Math.round(guideline.position)
9601
+ }
9602
+ )
9603
+ ]
9604
+ }
9605
+ );
9018
9606
  }
9019
9607
  function useViewportWidth() {
9020
- const [width, setWidth] = React29.useState(0);
9021
- React29.useEffect(() => {
9608
+ const [width, setWidth] = React30.useState(0);
9609
+ React30.useEffect(() => {
9022
9610
  setWidth(window.innerWidth);
9023
9611
  const onResize = () => setWidth(window.innerWidth);
9024
9612
  window.addEventListener("resize", onResize);
@@ -9027,8 +9615,8 @@ function useViewportWidth() {
9027
9615
  return width;
9028
9616
  }
9029
9617
  function useViewportHeight() {
9030
- const [height, setHeight] = React29.useState(0);
9031
- React29.useEffect(() => {
9618
+ const [height, setHeight] = React30.useState(0);
9619
+ React30.useEffect(() => {
9032
9620
  setHeight(window.innerHeight);
9033
9621
  const onResize = () => setHeight(window.innerHeight);
9034
9622
  window.addEventListener("resize", onResize);
@@ -9038,7 +9626,8 @@ function useViewportHeight() {
9038
9626
  }
9039
9627
  function RulersOverlay({ enabled }) {
9040
9628
  const container = usePortalContainer();
9041
- const hostElement = React29.useMemo(() => {
9629
+ const canvas = useCanvasSnapshot();
9630
+ const hostElement = React30.useMemo(() => {
9042
9631
  if (!container) return null;
9043
9632
  const root = container.getRootNode();
9044
9633
  if (root instanceof ShadowRoot) return root.host;
@@ -9048,12 +9637,51 @@ function RulersOverlay({ enabled }) {
9048
9637
  guidelines,
9049
9638
  activeGuideline,
9050
9639
  dragPosition,
9640
+ isSnapped,
9051
9641
  scrollOffset,
9052
9642
  startCreate,
9053
9643
  startDrag,
9054
9644
  deleteGuideline
9055
- } = useGuidelines(enabled, hostElement);
9645
+ } = useGuidelines(enabled, hostElement, canvas);
9646
+ React30.useLayoutEffect(() => {
9647
+ if (!container || !enabled) return;
9648
+ const el = container;
9649
+ function updateGuidelinePositions() {
9650
+ const snap = getCanvasSnapshot();
9651
+ const zoom2 = snap.active ? snap.zoom : 1;
9652
+ const panX = snap.active ? snap.panX : -window.scrollX;
9653
+ const panY = snap.active ? snap.panY : -window.scrollY;
9654
+ const bo = getBodyOffset();
9655
+ el.querySelectorAll("[data-gl-pos]").forEach((node) => {
9656
+ if (node.hasAttribute("data-gl-dragging")) return;
9657
+ const pos = Number(node.dataset.glPos);
9658
+ const orient = node.dataset.glOrient;
9659
+ let vp;
9660
+ if (snap.active) {
9661
+ vp = orient === "h" ? bo.y + (pos - bo.y + panY) * zoom2 : bo.x + (pos - bo.x + panX) * zoom2;
9662
+ } else {
9663
+ vp = orient === "h" ? (pos + panY) * zoom2 : (pos + panX) * zoom2;
9664
+ }
9665
+ node.style.transform = orient === "h" ? `translateY(${vp}px)` : `translateX(${vp}px)`;
9666
+ });
9667
+ }
9668
+ updateGuidelinePositions();
9669
+ window.addEventListener("direct-edit-canvas-change", updateGuidelinePositions);
9670
+ window.addEventListener("scroll", updateGuidelinePositions, true);
9671
+ return () => {
9672
+ window.removeEventListener("direct-edit-canvas-change", updateGuidelinePositions);
9673
+ window.removeEventListener("scroll", updateGuidelinePositions, true);
9674
+ };
9675
+ }, [container, enabled]);
9056
9676
  if (!enabled || !container) return null;
9677
+ const zoom = canvas?.active ? canvas.zoom || 1 : 1;
9678
+ const effectiveScrollOffset = canvas?.active ? (() => {
9679
+ const bo = getBodyOffset();
9680
+ return {
9681
+ x: computeCanvasRulerScrollOffset(canvas.panX || 0, zoom, bo.x),
9682
+ y: computeCanvasRulerScrollOffset(canvas.panY || 0, zoom, bo.y)
9683
+ };
9684
+ })() : scrollOffset;
9057
9685
  const handleHorizontalPointerDown = (e) => {
9058
9686
  e.preventDefault();
9059
9687
  startCreate("horizontal", e.clientY);
@@ -9065,14 +9693,14 @@ function RulersOverlay({ enabled }) {
9065
9693
  return createPortal2(
9066
9694
  /* @__PURE__ */ jsxs22(Fragment6, { children: [
9067
9695
  /* @__PURE__ */ jsx28(CornerSquare, {}),
9068
- /* @__PURE__ */ jsx28(HorizontalRuler, { scrollOffset, onPointerDown: handleHorizontalPointerDown }),
9069
- /* @__PURE__ */ jsx28(VerticalRuler, { scrollOffset, onPointerDown: handleVerticalPointerDown }),
9696
+ /* @__PURE__ */ jsx28(HorizontalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleHorizontalPointerDown }),
9697
+ /* @__PURE__ */ jsx28(VerticalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleVerticalPointerDown }),
9070
9698
  guidelines.map((g) => /* @__PURE__ */ jsx28(
9071
9699
  GuidelineLine,
9072
9700
  {
9073
9701
  guideline: g,
9074
- scrollOffset,
9075
9702
  isActive: activeGuideline?.id === g.id,
9703
+ isSnapped: activeGuideline?.id === g.id ? isSnapped : false,
9076
9704
  dragPosition: activeGuideline?.id === g.id ? dragPosition : null,
9077
9705
  onStartDrag: startDrag,
9078
9706
  onDelete: deleteGuideline
@@ -9120,12 +9748,12 @@ function subscribeRulersVisible(listener) {
9120
9748
  };
9121
9749
  }
9122
9750
  function useRulersVisible() {
9123
- const visible = React29.useSyncExternalStore(
9751
+ const visible = React30.useSyncExternalStore(
9124
9752
  subscribeRulersVisible,
9125
9753
  () => rulersVisibleSnapshot,
9126
9754
  () => true
9127
9755
  );
9128
- const toggle = React29.useCallback(() => {
9756
+ const toggle = React30.useCallback(() => {
9129
9757
  setRulersVisible(!rulersVisibleSnapshot);
9130
9758
  }, []);
9131
9759
  return [visible, toggle];
@@ -9133,7 +9761,7 @@ function useRulersVisible() {
9133
9761
  function Rulers() {
9134
9762
  const { editModeActive } = useDirectEditState();
9135
9763
  const [rulersVisible, toggleRulers] = useRulersVisible();
9136
- React29.useEffect(() => {
9764
+ React30.useEffect(() => {
9137
9765
  if (!editModeActive) return;
9138
9766
  function handleKeyDown(e) {
9139
9767
  if (e.shiftKey && e.key === "R" && !e.metaKey && !e.ctrlKey && !e.altKey) {
@@ -9151,7 +9779,7 @@ function Rulers() {
9151
9779
  }
9152
9780
 
9153
9781
  // src/use-toolbar-dock.ts
9154
- import * as React30 from "react";
9782
+ import * as React31 from "react";
9155
9783
  var STORAGE_KEY3 = "direct-edit-toolbar-dock";
9156
9784
  var EDGE_MARGIN = 8;
9157
9785
  var DRAG_THRESHOLD2 = 3;
@@ -9175,21 +9803,25 @@ function getToolbarBounds(width, height) {
9175
9803
  const maxY = availableY <= 0 ? 0 : Math.max(minY, availableY - EDGE_MARGIN);
9176
9804
  return { minX, maxX, minY, maxY };
9177
9805
  }
9178
- function getDockedPosition(edge, width, height, currentX, currentY) {
9806
+ function getDockedPosition(edge, width, height) {
9179
9807
  const { minX, maxX, minY, maxY } = getToolbarBounds(width, height);
9180
- const freeX = currentX !== void 0 ? clamp(currentX, minX, maxX) : clamp((window.innerWidth - width) / 2, minX, maxX);
9181
- const freeY = currentY !== void 0 ? clamp(currentY, minY, maxY) : clamp((window.innerHeight - height) / 2, minY, maxY);
9808
+ const centerX = clamp((window.innerWidth - width) / 2, minX, maxX);
9809
+ const centerY = clamp((window.innerHeight - height) / 2, minY, maxY);
9182
9810
  switch (edge) {
9183
9811
  case "bottom":
9184
- return { x: freeX, y: maxY };
9812
+ return { x: centerX, y: maxY };
9185
9813
  case "top":
9186
- return { x: freeX, y: minY };
9814
+ return { x: centerX, y: minY };
9187
9815
  case "left":
9188
- return { x: minX, y: freeY };
9816
+ return { x: minX, y: centerY };
9189
9817
  case "right":
9190
- return { x: maxX, y: freeY };
9818
+ return { x: maxX, y: centerY };
9191
9819
  }
9192
9820
  }
9821
+ function getInitialDockedPosition(edge) {
9822
+ if (typeof window === "undefined") return { x: 0, y: 0 };
9823
+ return getDockedPosition(edge, 0, 0);
9824
+ }
9193
9825
  function getNearestEdge(centerX, centerY) {
9194
9826
  const vw = window.innerWidth;
9195
9827
  const vh = window.innerHeight;
@@ -9210,53 +9842,65 @@ function getNearestEdge(centerX, centerY) {
9210
9842
  return nearest;
9211
9843
  }
9212
9844
  function useToolbarDock(toolbarRef) {
9213
- const [dockedEdge, setDockedEdge] = React30.useState(getInitialEdge);
9214
- const [phase, setPhase] = React30.useState("docked");
9215
- const [dragPosition, setDragPosition] = React30.useState(null);
9216
- const dragOffsetRef = React30.useRef({ x: 0, y: 0 });
9217
- const dockedPosRef = React30.useRef({ x: 0, y: 0 });
9218
- const pointerStartRef = React30.useRef({ x: 0, y: 0 });
9219
- const pendingDragRef = React30.useRef(false);
9220
- const capturedElementRef = React30.useRef(null);
9221
- const snapTimerRef = React30.useRef(null);
9222
- const getDockedPos = React30.useCallback(() => {
9845
+ const [dockedEdge, setDockedEdge] = React31.useState(getInitialEdge);
9846
+ const [phase, setPhase] = React31.useState("docked");
9847
+ const [dragPosition, setDragPosition] = React31.useState(null);
9848
+ const dragOffsetRef = React31.useRef({ x: 0, y: 0 });
9849
+ const pointerStartRef = React31.useRef({ x: 0, y: 0 });
9850
+ const pendingDragRef = React31.useRef(false);
9851
+ const capturedElementRef = React31.useRef(null);
9852
+ const snapTimerRef = React31.useRef(null);
9853
+ const transitionTimerRef = React31.useRef(null);
9854
+ const transitioningRef = React31.useRef(false);
9855
+ const recalcRef = React31.useRef(null);
9856
+ const getDockedPos = React31.useCallback(() => {
9223
9857
  const el = toolbarRef.current;
9224
9858
  if (!el) return { x: 0, y: 0 };
9225
9859
  const rect = el.getBoundingClientRect();
9226
9860
  return getDockedPosition(dockedEdge, rect.width, rect.height);
9227
9861
  }, [dockedEdge, toolbarRef]);
9228
- const [dockedPos, setDockedPos] = React30.useState({ x: 0, y: 0 });
9229
- const [ready, setReady] = React30.useState(false);
9230
- React30.useEffect(() => {
9862
+ const [dockedPos, setDockedPos] = React31.useState(() => getInitialDockedPosition(dockedEdge));
9863
+ const [dockedTransitionEnabled, setDockedTransitionEnabled] = React31.useState(false);
9864
+ React31.useLayoutEffect(() => {
9231
9865
  const el = toolbarRef.current;
9232
9866
  if (!el) return;
9867
+ setDockedPos(getDockedPos());
9868
+ }, [getDockedPos, toolbarRef]);
9869
+ React31.useEffect(() => {
9233
9870
  const raf = requestAnimationFrame(() => {
9234
- const pos = getDockedPos();
9235
- dockedPosRef.current = pos;
9236
- setDockedPos(pos);
9237
- setReady(true);
9871
+ setDockedTransitionEnabled(true);
9238
9872
  });
9239
9873
  return () => cancelAnimationFrame(raf);
9240
- }, [getDockedPos, toolbarRef]);
9241
- React30.useEffect(() => {
9874
+ }, []);
9875
+ const predictSize = React31.useCallback((width, height) => {
9876
+ transitioningRef.current = true;
9877
+ setDockedPos(getDockedPosition(dockedEdge, width, height));
9878
+ if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
9879
+ transitionTimerRef.current = setTimeout(() => {
9880
+ transitioningRef.current = false;
9881
+ transitionTimerRef.current = null;
9882
+ recalcRef.current?.();
9883
+ }, 350);
9884
+ }, [dockedEdge]);
9885
+ React31.useEffect(() => {
9242
9886
  const el = toolbarRef.current;
9243
9887
  if (!el) return;
9244
9888
  function recalc() {
9245
- if (!el) return;
9889
+ if (!el || transitioningRef.current) return;
9246
9890
  const rect = el.getBoundingClientRect();
9247
- const pos = getDockedPosition(dockedEdge, rect.width, rect.height, dockedPosRef.current.x, dockedPosRef.current.y);
9248
- dockedPosRef.current = pos;
9249
- setDockedPos(pos);
9891
+ setDockedPos(getDockedPosition(dockedEdge, rect.width, rect.height));
9250
9892
  }
9893
+ recalcRef.current = recalc;
9251
9894
  const ro = new ResizeObserver(recalc);
9252
9895
  ro.observe(el);
9253
9896
  window.addEventListener("resize", recalc);
9254
9897
  return () => {
9898
+ recalcRef.current = null;
9255
9899
  ro.disconnect();
9256
9900
  window.removeEventListener("resize", recalc);
9257
9901
  };
9258
9902
  }, [dockedEdge, toolbarRef]);
9259
- const handlePointerDown = React30.useCallback((e) => {
9903
+ const handlePointerDown = React31.useCallback((e) => {
9260
9904
  const el = toolbarRef.current;
9261
9905
  if (!el) return;
9262
9906
  const rect = el.getBoundingClientRect();
@@ -9269,7 +9913,7 @@ function useToolbarDock(toolbarRef) {
9269
9913
  } catch {
9270
9914
  }
9271
9915
  }, [toolbarRef]);
9272
- const handlePointerMove = React30.useCallback((e) => {
9916
+ const handlePointerMove = React31.useCallback((e) => {
9273
9917
  if (!pendingDragRef.current && phase !== "dragging") return;
9274
9918
  const dx = e.clientX - pointerStartRef.current.x;
9275
9919
  const dy = e.clientY - pointerStartRef.current.y;
@@ -9286,7 +9930,7 @@ function useToolbarDock(toolbarRef) {
9286
9930
  const newY = Math.max(0, e.clientY - dragOffsetRef.current.y);
9287
9931
  setDragPosition({ x: newX, y: newY });
9288
9932
  }, [phase]);
9289
- const handlePointerUp = React30.useCallback((e) => {
9933
+ const handlePointerUp = React31.useCallback((e) => {
9290
9934
  if (capturedElementRef.current) {
9291
9935
  try {
9292
9936
  capturedElementRef.current.releasePointerCapture(e.pointerId);
@@ -9306,8 +9950,6 @@ function useToolbarDock(toolbarRef) {
9306
9950
  return;
9307
9951
  }
9308
9952
  const rect = el.getBoundingClientRect();
9309
- const width = el.offsetWidth;
9310
- const height = el.offsetHeight;
9311
9953
  const centerX = rect.left + rect.width / 2;
9312
9954
  const centerY = rect.top + rect.height / 2;
9313
9955
  const newEdge = getNearestEdge(centerX, centerY);
@@ -9316,9 +9958,7 @@ function useToolbarDock(toolbarRef) {
9316
9958
  localStorage.setItem(STORAGE_KEY3, newEdge);
9317
9959
  } catch {
9318
9960
  }
9319
- const newPos = getDockedPosition(newEdge, width, height, rect.left, rect.top);
9320
- dockedPosRef.current = newPos;
9321
- setDockedPos(newPos);
9961
+ setDockedPos(getDockedPosition(newEdge, el.offsetWidth, el.offsetHeight));
9322
9962
  setPhase("snapping");
9323
9963
  setDragPosition(null);
9324
9964
  if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
@@ -9327,7 +9967,7 @@ function useToolbarDock(toolbarRef) {
9327
9967
  setPhase("docked");
9328
9968
  }, 350);
9329
9969
  }, [phase, toolbarRef]);
9330
- const handlePointerCancel = React30.useCallback((e) => {
9970
+ const handlePointerCancel = React31.useCallback((e) => {
9331
9971
  if (capturedElementRef.current) {
9332
9972
  try {
9333
9973
  capturedElementRef.current.releasePointerCapture(e.pointerId);
@@ -9341,18 +9981,16 @@ function useToolbarDock(toolbarRef) {
9341
9981
  setDragPosition(null);
9342
9982
  }
9343
9983
  }, [phase]);
9344
- React30.useEffect(() => {
9984
+ React31.useEffect(() => {
9345
9985
  return () => {
9346
9986
  if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
9987
+ if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
9347
9988
  };
9348
9989
  }, []);
9349
9990
  const isDragging = phase === "dragging";
9350
9991
  const isSnapping = phase === "snapping";
9351
- const style = React30.useMemo(() => {
9352
- const base = {
9353
- position: "fixed",
9354
- ...!ready && { visibility: "hidden" }
9355
- };
9992
+ const style = React31.useMemo(() => {
9993
+ const base = { position: "fixed" };
9356
9994
  if (phase === "dragging" && dragPosition) {
9357
9995
  return {
9358
9996
  ...base,
@@ -9375,14 +10013,18 @@ function useToolbarDock(toolbarRef) {
9375
10013
  return {
9376
10014
  ...base,
9377
10015
  left: dockedPos.x,
9378
- top: dockedPos.y
10016
+ top: dockedPos.y,
10017
+ ...dockedTransitionEnabled && {
10018
+ transition: "left 300ms cubic-bezier(0.25, 1, 0.5, 1), top 300ms cubic-bezier(0.25, 1, 0.5, 1), box-shadow 150ms ease-out"
10019
+ }
9379
10020
  };
9380
- }, [phase, dragPosition, dockedPos, ready]);
10021
+ }, [phase, dragPosition, dockedPos, dockedTransitionEnabled]);
9381
10022
  return {
9382
10023
  dockedEdge,
9383
10024
  isDragging,
9384
10025
  isSnapping,
9385
10026
  style,
10027
+ predictSize,
9386
10028
  handlePointerDown,
9387
10029
  handlePointerMove,
9388
10030
  handlePointerUp,
@@ -9391,16 +10033,16 @@ function useToolbarDock(toolbarRef) {
9391
10033
  }
9392
10034
 
9393
10035
  // src/toolbar.tsx
9394
- import { MousePointer2, Ruler, Command as Command2, ArrowBigUp as ArrowBigUp2, MessageSquare } from "lucide-react";
10036
+ import { MousePointer2, Ruler, Command as Command2, ArrowBigUp as ArrowBigUp3, MessageSquare, X as X5 } from "lucide-react";
9395
10037
 
9396
10038
  // src/toolbar/edits-popover.tsx
9397
- import * as React32 from "react";
10039
+ import * as React33 from "react";
9398
10040
  import { Button as BaseButton } from "@base-ui/react/button";
9399
10041
  import { Popover as Popover2 } from "@base-ui/react/popover";
9400
10042
  import { X as X4, Check as Check6, Copy as Copy3, Send as Send3, Trash2 as Trash22 } from "lucide-react";
9401
10043
 
9402
10044
  // src/ui/badge.tsx
9403
- import * as React31 from "react";
10045
+ import * as React32 from "react";
9404
10046
  import { jsx as jsx29 } from "react/jsx-runtime";
9405
10047
  var badgeVariants = {
9406
10048
  base: "inline-flex items-center rounded-md border px-2 py-0.5 text-[10px] font-medium whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
@@ -9410,7 +10052,7 @@ var badgeVariants = {
9410
10052
  outline: "border-border bg-transparent text-foreground"
9411
10053
  }
9412
10054
  };
9413
- var Badge = React31.forwardRef(
10055
+ var Badge = React32.forwardRef(
9414
10056
  ({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ jsx29(
9415
10057
  "div",
9416
10058
  {
@@ -9436,14 +10078,11 @@ function truncateText(value, max = 64) {
9436
10078
  if (value.length <= max) return value;
9437
10079
  return `${value.slice(0, max)}...`;
9438
10080
  }
9439
- function isWithinFocusRegion(nextTarget, ...elements) {
9440
- if (!(nextTarget instanceof Node)) return false;
9441
- return elements.some((element) => Boolean(element?.contains(nextTarget)));
9442
- }
9443
10081
  function EditsPopover({
9444
10082
  tooltipSide,
9445
10083
  sessionEditCount,
9446
- isDragging,
10084
+ isOpen,
10085
+ onOpenChange,
9447
10086
  onGetSessionItems,
9448
10087
  onExportAllEdits,
9449
10088
  onSendAllToAgents,
@@ -9451,20 +10090,18 @@ function EditsPopover({
9451
10090
  onRemoveSessionEdit,
9452
10091
  onDeleteComment
9453
10092
  }) {
9454
- const [editsOpen, setEditsOpen] = React32.useState(false);
9455
- const [copied, setCopied] = React32.useState(false);
9456
- const [sendStatus, setSendStatus] = React32.useState("idle");
9457
- const editsPopupRef = React32.useRef(null);
9458
- const editsTriggerRef = React32.useRef(null);
9459
- const editsCloseTimerRef = React32.useRef(null);
9460
- const [editsSnapshot, setEditsSnapshot] = React32.useState([]);
9461
- React32.useEffect(() => {
9462
- if (!editsOpen) return;
10093
+ const [copied, setCopied] = React33.useState(false);
10094
+ const [sendStatus, setSendStatus] = React33.useState("idle");
10095
+ const editsPopupRef = React33.useRef(null);
10096
+ const editsTriggerRef = React33.useRef(null);
10097
+ const [editsSnapshot, setEditsSnapshot] = React33.useState([]);
10098
+ React33.useEffect(() => {
10099
+ if (!isOpen) return;
9463
10100
  function handlePointerDown(e) {
9464
10101
  const path = e.composedPath();
9465
10102
  if (editsPopupRef.current && path.includes(editsPopupRef.current)) return;
9466
10103
  if (editsTriggerRef.current && path.includes(editsTriggerRef.current)) return;
9467
- setEditsOpen(false);
10104
+ onOpenChange(false);
9468
10105
  }
9469
10106
  const raf = requestAnimationFrame(() => {
9470
10107
  document.addEventListener("pointerdown", handlePointerDown);
@@ -9473,42 +10110,19 @@ function EditsPopover({
9473
10110
  cancelAnimationFrame(raf);
9474
10111
  document.removeEventListener("pointerdown", handlePointerDown);
9475
10112
  };
9476
- }, [editsOpen]);
9477
- React32.useEffect(() => {
9478
- if (editsOpen && onGetSessionItems) {
10113
+ }, [isOpen, onOpenChange]);
10114
+ React33.useEffect(() => {
10115
+ if (isOpen && onGetSessionItems) {
9479
10116
  setEditsSnapshot(onGetSessionItems());
9480
10117
  }
9481
- }, [editsOpen, onGetSessionItems]);
9482
- React32.useEffect(() => {
9483
- return () => {
9484
- if (editsCloseTimerRef.current !== null) {
9485
- window.clearTimeout(editsCloseTimerRef.current);
9486
- }
9487
- };
9488
- }, []);
9489
- React32.useEffect(() => {
9490
- if (isDragging) setEditsOpen(false);
9491
- }, [isDragging]);
9492
- const clearEditsCloseTimer = React32.useCallback(() => {
9493
- if (editsCloseTimerRef.current !== null) {
9494
- window.clearTimeout(editsCloseTimerRef.current);
9495
- editsCloseTimerRef.current = null;
9496
- }
9497
- }, []);
9498
- const scheduleEditsClose = React32.useCallback(() => {
9499
- clearEditsCloseTimer();
9500
- editsCloseTimerRef.current = window.setTimeout(() => {
9501
- setEditsOpen(false);
9502
- editsCloseTimerRef.current = null;
9503
- }, 120);
9504
- }, [clearEditsCloseTimer]);
9505
- const handleCopyAll = React32.useCallback(async () => {
10118
+ }, [isOpen, onGetSessionItems]);
10119
+ const handleCopyAll = React33.useCallback(async () => {
9506
10120
  const success = await onExportAllEdits?.();
9507
10121
  if (!success) return;
9508
10122
  setCopied(true);
9509
10123
  window.setTimeout(() => setCopied(false), 2e3);
9510
10124
  }, [onExportAllEdits]);
9511
- const handleSendAll = React32.useCallback(async () => {
10125
+ const handleSendAll = React33.useCallback(async () => {
9512
10126
  if (!onSendAllToAgents || sendStatus === "sending") return;
9513
10127
  setSendStatus("sending");
9514
10128
  let success = false;
@@ -9525,7 +10139,7 @@ function EditsPopover({
9525
10139
  setSendStatus("offline");
9526
10140
  window.setTimeout(() => setSendStatus("idle"), 2e3);
9527
10141
  }, [onSendAllToAgents, sendStatus]);
9528
- const handleCopyItem = React32.useCallback(async (item) => {
10142
+ const handleCopyItem = React33.useCallback(async (item) => {
9529
10143
  const text = item.type === "edit" ? buildSessionExport([item.edit], []) : buildSessionExport([], [item.comment]);
9530
10144
  try {
9531
10145
  await navigator.clipboard.writeText(`implement the visual edits
@@ -9536,52 +10150,33 @@ ${text}`);
9536
10150
  } catch {
9537
10151
  }
9538
10152
  }, []);
9539
- return /* @__PURE__ */ jsxs23(Popover2.Root, { open: editsOpen, onOpenChange: setEditsOpen, children: [
9540
- /* @__PURE__ */ jsx30(Popover2.Trigger, { ref: editsTriggerRef, render: /* @__PURE__ */ jsx30(
9541
- "button",
9542
- {
9543
- type: "button",
9544
- className: cn(
9545
- "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
9546
- sessionEditCount > 0 || editsOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
9547
- ),
9548
- onPointerDown: (e) => e.stopPropagation(),
9549
- onPointerEnter: () => {
9550
- clearEditsCloseTimer();
9551
- setEditsOpen(true);
9552
- },
9553
- onPointerLeave: scheduleEditsClose,
9554
- onFocus: (e) => {
9555
- clearEditsCloseTimer();
9556
- if (e.currentTarget.matches(":focus-visible")) {
9557
- setEditsOpen(true);
10153
+ return /* @__PURE__ */ jsxs23(Popover2.Root, { open: isOpen, onOpenChange, children: [
10154
+ /* @__PURE__ */ jsxs23(Tooltip, { disabled: isOpen, children: [
10155
+ /* @__PURE__ */ jsx30(TooltipTrigger, { render: /* @__PURE__ */ jsx30(Popover2.Trigger, { render: /* @__PURE__ */ jsx30(
10156
+ "button",
10157
+ {
10158
+ ref: editsTriggerRef,
10159
+ type: "button",
10160
+ className: cn(
10161
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
10162
+ sessionEditCount > 0 || isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10163
+ ),
10164
+ onPointerDown: (e) => e.stopPropagation(),
10165
+ onClick: (e) => {
10166
+ e.preventDefault();
10167
+ e.stopPropagation();
10168
+ onOpenChange(!isOpen);
9558
10169
  }
9559
- },
9560
- onBlur: (e) => {
9561
- if (isWithinFocusRegion(e.relatedTarget, editsTriggerRef.current, editsPopupRef.current)) return;
9562
- scheduleEditsClose();
9563
- },
9564
- onClick: (e) => {
9565
- e.preventDefault();
9566
- e.stopPropagation();
9567
- clearEditsCloseTimer();
9568
- setEditsOpen((prev) => !prev);
9569
10170
  }
9570
- }
9571
- ), children: /* @__PURE__ */ jsx30(Copy3, { className: "size-4" }) }),
10171
+ ) }), children: /* @__PURE__ */ jsx30(Copy3, { className: "size-4" }) }),
10172
+ /* @__PURE__ */ jsx30(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ jsx30("span", { children: "Export edits" }) })
10173
+ ] }),
9572
10174
  /* @__PURE__ */ jsx30(EditsPopoverPortal, { children: /* @__PURE__ */ jsx30(Popover2.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsxs23(
9573
10175
  Popover2.Popup,
9574
10176
  {
9575
10177
  ref: editsPopupRef,
9576
10178
  className: "w-[340px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
9577
10179
  onPointerDown: (e) => e.stopPropagation(),
9578
- onPointerEnter: clearEditsCloseTimer,
9579
- onPointerLeave: scheduleEditsClose,
9580
- onFocus: clearEditsCloseTimer,
9581
- onBlur: (e) => {
9582
- if (isWithinFocusRegion(e.relatedTarget, editsTriggerRef.current, editsPopupRef.current)) return;
9583
- scheduleEditsClose();
9584
- },
9585
10180
  children: [
9586
10181
  /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-3 pb-1 pt-2.5", children: [
9587
10182
  /* @__PURE__ */ jsx30("span", { className: "text-xs font-medium text-foreground", children: "Copy to AI agents" }),
@@ -9712,38 +10307,200 @@ ${text}`);
9712
10307
  }
9713
10308
 
9714
10309
  // src/toolbar/settings-popover.tsx
9715
- import * as React33 from "react";
9716
- import { Button as BaseButton2 } from "@base-ui/react/button";
9717
- import { Popover as Popover3 } from "@base-ui/react/popover";
9718
- import { EllipsisVertical, Sun, Moon, Monitor, Command, ArrowBigUp, Option } from "lucide-react";
10310
+ import * as React34 from "react";
10311
+ import { Menu } from "@base-ui/react/menu";
10312
+ import { EllipsisVertical, Sun, Moon, Monitor, Command, ArrowBigUp, Option, Keyboard, ChevronRight } from "lucide-react";
9719
10313
  import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
9720
- function ThemePopoverPortal(props) {
10314
+ function SettingsMenuPortal(props) {
9721
10315
  const container = usePortalContainer();
9722
- return /* @__PURE__ */ jsx31(Popover3.Portal, { container, ...props });
9723
- }
9724
- function isWithinFocusRegion2(nextTarget, ...elements) {
9725
- if (!(nextTarget instanceof Node)) return false;
9726
- return elements.some((element) => Boolean(element?.contains(nextTarget)));
10316
+ return /* @__PURE__ */ jsx31(Menu.Portal, { container, ...props });
9727
10317
  }
9728
10318
  function SettingsPopover({
9729
10319
  tooltipSide,
9730
10320
  theme,
9731
10321
  isMac,
9732
- isDragging,
10322
+ isOpen,
10323
+ onOpenChange,
9733
10324
  onSetTheme
9734
10325
  }) {
9735
- const [settingsOpen, setSettingsOpen] = React33.useState(false);
9736
- const settingsPopupRef = React33.useRef(null);
9737
- const settingsTriggerRef = React33.useRef(null);
9738
- const settingsCloseTimerRef = React33.useRef(null);
9739
- const popupKbdClass = "inline-flex h-5 min-w-[20px] items-center justify-center rounded-md bg-muted px-1.5 font-mono text-[10px] text-muted-foreground";
9740
- React33.useEffect(() => {
9741
- if (!settingsOpen) return;
10326
+ const settingsTriggerRef = React34.useRef(null);
10327
+ const settingsPopupRef = React34.useRef(null);
10328
+ const popupKbdClass = "inline-flex h-4 min-w-[18px] items-center justify-center rounded-[6px] bg-muted px-1 text-[9px] font-mono text-muted-foreground";
10329
+ const popupTitleClass = "flex h-8 items-center px-3 text-xs font-medium text-foreground";
10330
+ const submenuSide = tooltipSide === "left" ? "left" : "right";
10331
+ const centeredSubmenuCollision = React34.useMemo(
10332
+ () => ({ side: "flip", align: "none", fallbackAxisSide: "none" }),
10333
+ []
10334
+ );
10335
+ return /* @__PURE__ */ jsxs24(Menu.Root, { open: isOpen, onOpenChange, modal: false, children: [
10336
+ /* @__PURE__ */ jsxs24(Tooltip, { disabled: isOpen, children: [
10337
+ /* @__PURE__ */ jsx31(TooltipTrigger, { render: /* @__PURE__ */ jsx31(Menu.Trigger, { render: /* @__PURE__ */ jsx31(
10338
+ "button",
10339
+ {
10340
+ ref: settingsTriggerRef,
10341
+ type: "button",
10342
+ className: cn(
10343
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
10344
+ isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10345
+ ),
10346
+ onPointerDown: (e) => e.stopPropagation()
10347
+ }
10348
+ ) }), children: /* @__PURE__ */ jsx31(EllipsisVertical, { className: "size-4" }) }),
10349
+ /* @__PURE__ */ jsx31(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ jsx31("span", { children: "Preferences" }) })
10350
+ ] }),
10351
+ /* @__PURE__ */ jsx31(SettingsMenuPortal, { children: /* @__PURE__ */ jsx31(Menu.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsxs24(
10352
+ Menu.Popup,
10353
+ {
10354
+ ref: settingsPopupRef,
10355
+ className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
10356
+ onPointerDown: (e) => e.stopPropagation(),
10357
+ children: [
10358
+ /* @__PURE__ */ jsx31("div", { className: popupTitleClass, children: "Preferences" }),
10359
+ /* @__PURE__ */ jsxs24("div", { className: "px-1 pb-1", children: [
10360
+ /* @__PURE__ */ jsxs24(Menu.SubmenuRoot, { children: [
10361
+ /* @__PURE__ */ jsxs24(
10362
+ Menu.SubmenuTrigger,
10363
+ {
10364
+ openOnHover: false,
10365
+ className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-muted-foreground transition-colors data-[highlighted]:bg-muted/50 data-[highlighted]:text-foreground",
10366
+ children: [
10367
+ /* @__PURE__ */ jsx31(Monitor, { className: "size-3.5" }),
10368
+ /* @__PURE__ */ jsx31("span", { className: "flex-1", children: "Theme" }),
10369
+ /* @__PURE__ */ jsx31(ChevronRight, { className: "size-3.5" })
10370
+ ]
10371
+ }
10372
+ ),
10373
+ /* @__PURE__ */ jsx31(SettingsMenuPortal, { children: /* @__PURE__ */ jsx31(
10374
+ Menu.Positioner,
10375
+ {
10376
+ anchor: settingsPopupRef,
10377
+ side: submenuSide,
10378
+ align: "center",
10379
+ sideOffset: 6,
10380
+ collisionAvoidance: centeredSubmenuCollision,
10381
+ className: "fixed z-[99999]",
10382
+ style: { pointerEvents: "auto" },
10383
+ children: /* @__PURE__ */ jsxs24(
10384
+ Menu.Popup,
10385
+ {
10386
+ className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
10387
+ onPointerDown: (e) => e.stopPropagation(),
10388
+ children: [
10389
+ /* @__PURE__ */ jsx31("div", { className: popupTitleClass, children: "Theme" }),
10390
+ /* @__PURE__ */ jsx31("div", { className: "px-1 pb-1", children: [
10391
+ { value: "light", label: "Light", Icon: Sun },
10392
+ { value: "dark", label: "Dark", Icon: Moon },
10393
+ { value: "system", label: "System", Icon: Monitor }
10394
+ ].map(({ value, label, Icon }) => /* @__PURE__ */ jsxs24(
10395
+ Menu.Item,
10396
+ {
10397
+ className: cn(
10398
+ "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs transition-colors",
10399
+ theme === value ? "bg-muted text-foreground" : "text-muted-foreground data-[highlighted]:bg-muted/50 data-[highlighted]:text-foreground"
10400
+ ),
10401
+ onClick: () => {
10402
+ onSetTheme?.(value);
10403
+ onOpenChange(false);
10404
+ },
10405
+ children: [
10406
+ /* @__PURE__ */ jsx31(Icon, { className: "size-3.5" }),
10407
+ label
10408
+ ]
10409
+ },
10410
+ value
10411
+ )) })
10412
+ ]
10413
+ }
10414
+ )
10415
+ }
10416
+ ) })
10417
+ ] }),
10418
+ /* @__PURE__ */ jsxs24(Menu.SubmenuRoot, { children: [
10419
+ /* @__PURE__ */ jsxs24(
10420
+ Menu.SubmenuTrigger,
10421
+ {
10422
+ openOnHover: false,
10423
+ className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-muted-foreground transition-colors data-[highlighted]:bg-muted/50 data-[highlighted]:text-foreground",
10424
+ children: [
10425
+ /* @__PURE__ */ jsx31(Keyboard, { className: "size-3.5" }),
10426
+ /* @__PURE__ */ jsx31("span", { className: "flex-1", children: "Keyboard shortcuts" }),
10427
+ /* @__PURE__ */ jsx31(ChevronRight, { className: "size-3.5" })
10428
+ ]
10429
+ }
10430
+ ),
10431
+ /* @__PURE__ */ jsx31(SettingsMenuPortal, { children: /* @__PURE__ */ jsx31(
10432
+ Menu.Positioner,
10433
+ {
10434
+ anchor: settingsPopupRef,
10435
+ side: submenuSide,
10436
+ align: "center",
10437
+ sideOffset: 6,
10438
+ collisionAvoidance: centeredSubmenuCollision,
10439
+ className: "fixed z-[99999]",
10440
+ style: { pointerEvents: "auto" },
10441
+ children: /* @__PURE__ */ jsxs24(
10442
+ Menu.Popup,
10443
+ {
10444
+ className: "w-[300px] rounded-xl bg-background text-[11px] outline outline-1 outline-foreground/10 shadow-lg",
10445
+ onPointerDown: (e) => e.stopPropagation(),
10446
+ children: [
10447
+ /* @__PURE__ */ jsx31("div", { className: "flex h-7 items-center px-3 text-[11px] font-medium text-foreground", children: "Keyboard Shortcuts" }),
10448
+ /* @__PURE__ */ jsx31("div", { className: "px-1 pb-1", children: [
10449
+ { label: "Toggle design mode", keys: isMac ? [/* @__PURE__ */ jsx31(Command, { className: "size-2.5" }, "cmd"), "."] : ["Ctrl", "."] },
10450
+ { label: "Undo", keys: isMac ? [/* @__PURE__ */ jsx31(Command, { className: "size-2.5" }, "cmd"), "Z"] : ["Ctrl", "Z"] },
10451
+ { label: "Toggle comments", keys: [/* @__PURE__ */ jsx31(ArrowBigUp, { className: "size-3" }, "shift"), "C"] },
10452
+ { label: "Toggle rulers", keys: [/* @__PURE__ */ jsx31(ArrowBigUp, { className: "size-3" }, "shift"), "R"] },
10453
+ { label: "Toggle canvas mode", keys: [/* @__PURE__ */ jsx31(ArrowBigUp, { className: "size-3" }, "shift"), "Z"] },
10454
+ { label: "Hover to measure", keys: isMac ? ["Hold", /* @__PURE__ */ jsx31(Option, { className: "size-2.5" }, "opt")] : ["Hold", "Alt"] },
10455
+ { label: "Back / Exit", keys: ["Esc"] }
10456
+ ].map(({ label, keys }) => /* @__PURE__ */ jsxs24("div", { className: "flex h-7 w-full items-center justify-between rounded-md px-2 text-[11px] text-muted-foreground", children: [
10457
+ /* @__PURE__ */ jsx31("span", { children: label }),
10458
+ /* @__PURE__ */ jsx31("span", { className: "flex items-center gap-1", children: keys.map((k, i) => /* @__PURE__ */ jsx31("kbd", { className: popupKbdClass, children: k }, typeof k === "string" ? k : i)) })
10459
+ ] }, label)) })
10460
+ ]
10461
+ }
10462
+ )
10463
+ }
10464
+ ) })
10465
+ ] })
10466
+ ] })
10467
+ ]
10468
+ }
10469
+ ) }) })
10470
+ ] });
10471
+ }
10472
+
10473
+ // src/toolbar/zoom-popover.tsx
10474
+ import * as React35 from "react";
10475
+ import { Button as BaseButton2 } from "@base-ui/react/button";
10476
+ import { Popover as Popover3 } from "@base-ui/react/popover";
10477
+ import { Scan, Minimize2, Maximize2, Check as Check7, ArrowBigUp as ArrowBigUp2 } from "lucide-react";
10478
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
10479
+ function ZoomPopoverPortal(props) {
10480
+ const container = usePortalContainer();
10481
+ return /* @__PURE__ */ jsx32(Popover3.Portal, { container, ...props });
10482
+ }
10483
+ function ZoomPopover({
10484
+ tooltipSide,
10485
+ canvasActive,
10486
+ canvasZoom,
10487
+ isOpen,
10488
+ onOpenChange,
10489
+ onToggleCanvas,
10490
+ onSetCanvasZoom,
10491
+ onZoomTo100,
10492
+ onFitToViewport
10493
+ }) {
10494
+ const popupRef = React35.useRef(null);
10495
+ const triggerRef = React35.useRef(null);
10496
+ const kbdClass = "inline-flex items-center justify-center rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground min-w-[20px] min-h-[18px]";
10497
+ React35.useEffect(() => {
10498
+ if (!isOpen) return;
9742
10499
  function handlePointerDown(e) {
9743
10500
  const path = e.composedPath();
9744
- if (settingsPopupRef.current && path.includes(settingsPopupRef.current)) return;
9745
- if (settingsTriggerRef.current && path.includes(settingsTriggerRef.current)) return;
9746
- setSettingsOpen(false);
10501
+ if (popupRef.current && path.includes(popupRef.current)) return;
10502
+ if (triggerRef.current && path.includes(triggerRef.current)) return;
10503
+ onOpenChange(false);
9747
10504
  }
9748
10505
  const raf = requestAnimationFrame(() => {
9749
10506
  document.addEventListener("pointerdown", handlePointerDown);
@@ -9752,121 +10509,90 @@ function SettingsPopover({
9752
10509
  cancelAnimationFrame(raf);
9753
10510
  document.removeEventListener("pointerdown", handlePointerDown);
9754
10511
  };
9755
- }, [settingsOpen]);
9756
- React33.useEffect(() => {
9757
- return () => {
9758
- if (settingsCloseTimerRef.current !== null) {
9759
- window.clearTimeout(settingsCloseTimerRef.current);
9760
- }
9761
- };
9762
- }, []);
9763
- React33.useEffect(() => {
9764
- if (isDragging) setSettingsOpen(false);
9765
- }, [isDragging]);
9766
- const clearSettingsCloseTimer = React33.useCallback(() => {
9767
- if (settingsCloseTimerRef.current !== null) {
9768
- window.clearTimeout(settingsCloseTimerRef.current);
9769
- settingsCloseTimerRef.current = null;
9770
- }
9771
- }, []);
9772
- const scheduleSettingsClose = React33.useCallback(() => {
9773
- clearSettingsCloseTimer();
9774
- settingsCloseTimerRef.current = window.setTimeout(() => {
9775
- setSettingsOpen(false);
9776
- settingsCloseTimerRef.current = null;
9777
- }, 120);
9778
- }, [clearSettingsCloseTimer]);
9779
- return /* @__PURE__ */ jsxs24(Popover3.Root, { open: settingsOpen, onOpenChange: setSettingsOpen, children: [
9780
- /* @__PURE__ */ jsx31(Popover3.Trigger, { ref: settingsTriggerRef, render: /* @__PURE__ */ jsx31(
9781
- "button",
9782
- {
9783
- type: "button",
9784
- className: cn(
9785
- "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
9786
- settingsOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
9787
- ),
9788
- onPointerDown: (e) => e.stopPropagation(),
9789
- onPointerEnter: () => {
9790
- clearSettingsCloseTimer();
9791
- setSettingsOpen(true);
9792
- },
9793
- onPointerLeave: scheduleSettingsClose,
9794
- onFocus: (e) => {
9795
- clearSettingsCloseTimer();
9796
- if (e.currentTarget.matches(":focus-visible")) {
9797
- setSettingsOpen(true);
10512
+ }, [isOpen, onOpenChange]);
10513
+ return /* @__PURE__ */ jsxs25(Popover3.Root, { open: isOpen, onOpenChange, children: [
10514
+ /* @__PURE__ */ jsxs25(Tooltip, { disabled: isOpen, children: [
10515
+ /* @__PURE__ */ jsx32(TooltipTrigger, { render: /* @__PURE__ */ jsx32(Popover3.Trigger, { render: /* @__PURE__ */ jsx32(
10516
+ "button",
10517
+ {
10518
+ ref: triggerRef,
10519
+ type: "button",
10520
+ className: cn(
10521
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
10522
+ isOpen ? "bg-muted text-foreground" : canvasActive ? "bg-muted text-foreground hover:bg-muted/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10523
+ ),
10524
+ onPointerDown: (e) => e.stopPropagation(),
10525
+ onClick: (e) => {
10526
+ e.preventDefault();
10527
+ e.stopPropagation();
10528
+ onOpenChange(!isOpen);
9798
10529
  }
9799
- },
9800
- onBlur: (e) => {
9801
- if (isWithinFocusRegion2(e.relatedTarget, settingsTriggerRef.current, settingsPopupRef.current)) return;
9802
- scheduleSettingsClose();
9803
- },
9804
- onClick: (e) => {
9805
- e.preventDefault();
9806
- e.stopPropagation();
9807
- clearSettingsCloseTimer();
9808
- setSettingsOpen((prev) => !prev);
9809
10530
  }
9810
- }
9811
- ), children: /* @__PURE__ */ jsx31(EllipsisVertical, { className: "size-4" }) }),
9812
- /* @__PURE__ */ jsx31(ThemePopoverPortal, { children: /* @__PURE__ */ jsx31(Popover3.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsxs24(
10531
+ ) }), children: /* @__PURE__ */ jsx32(Maximize2, { className: "size-4" }) }),
10532
+ /* @__PURE__ */ jsxs25(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
10533
+ /* @__PURE__ */ jsx32("span", { children: "Canvas mode" }),
10534
+ /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx32(ArrowBigUp2, { className: "size-2.5" }) }),
10535
+ /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "Z" })
10536
+ ] })
10537
+ ] }),
10538
+ /* @__PURE__ */ jsx32(ZoomPopoverPortal, { children: /* @__PURE__ */ jsx32(Popover3.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsx32(
9813
10539
  Popover3.Popup,
9814
10540
  {
9815
- ref: settingsPopupRef,
9816
- className: "w-[340px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
10541
+ ref: popupRef,
10542
+ className: "w-[180px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
9817
10543
  onPointerDown: (e) => e.stopPropagation(),
9818
- onPointerEnter: clearSettingsCloseTimer,
9819
- onPointerLeave: scheduleSettingsClose,
9820
- onFocus: clearSettingsCloseTimer,
9821
- onBlur: (e) => {
9822
- if (isWithinFocusRegion2(e.relatedTarget, settingsTriggerRef.current, settingsPopupRef.current)) return;
9823
- scheduleSettingsClose();
9824
- },
9825
- children: [
9826
- /* @__PURE__ */ jsx31("div", { className: "px-3 pb-1 pt-2.5 text-xs font-medium text-foreground", children: "Theme" }),
9827
- /* @__PURE__ */ jsx31("div", { className: "px-1 pb-1", children: [
9828
- { value: "light", label: "Light", Icon: Sun },
9829
- { value: "dark", label: "Dark", Icon: Moon },
9830
- { value: "system", label: "System", Icon: Monitor }
9831
- ].map(({ value, label, Icon }) => /* @__PURE__ */ jsxs24(
10544
+ children: /* @__PURE__ */ jsxs25("div", { className: "px-1 py-1", children: [
10545
+ /* @__PURE__ */ jsxs25(
9832
10546
  BaseButton2,
9833
10547
  {
9834
- className: cn(
9835
- "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs transition-colors",
9836
- theme === value ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
9837
- ),
10548
+ className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
9838
10549
  onClick: () => {
9839
- onSetTheme?.(value);
9840
- setSettingsOpen(false);
10550
+ onZoomTo100?.();
10551
+ onOpenChange(false);
9841
10552
  },
9842
10553
  children: [
9843
- /* @__PURE__ */ jsx31(Icon, { className: "size-3.5" }),
9844
- label
10554
+ /* @__PURE__ */ jsx32(Scan, { className: "size-3.5" }),
10555
+ "Actual size (100%)"
9845
10556
  ]
9846
- },
9847
- value
9848
- )) }),
9849
- /* @__PURE__ */ jsx31("div", { className: "mx-2 my-1 border-t border-foreground/10" }),
9850
- /* @__PURE__ */ jsx31("div", { className: "px-3 pb-1 pt-1.5 text-xs font-medium text-foreground", children: "Keyboard Shortcuts" }),
9851
- /* @__PURE__ */ jsx31("div", { className: "px-1 pb-1", children: [
9852
- { label: "Toggle design mode", keys: isMac ? [/* @__PURE__ */ jsx31(Command, { className: "size-2.5" }, "cmd"), "."] : ["Ctrl", "."] },
9853
- { label: "Undo", keys: isMac ? [/* @__PURE__ */ jsx31(Command, { className: "size-2.5" }, "cmd"), "Z"] : ["Ctrl", "Z"] },
9854
- { label: "Toggle comments", keys: [/* @__PURE__ */ jsx31(ArrowBigUp, { className: "size-3" }, "shift"), "C"] },
9855
- { label: "Toggle rulers", keys: [/* @__PURE__ */ jsx31(ArrowBigUp, { className: "size-3" }, "shift"), "R"] },
9856
- { label: "Hover to measure", keys: isMac ? ["Hold", /* @__PURE__ */ jsx31(Option, { className: "size-2.5" }, "opt")] : ["Hold", "Alt"] },
9857
- { label: "Back / Exit", keys: ["Esc"] }
9858
- ].map(({ label, keys }) => /* @__PURE__ */ jsxs24("div", { className: "flex h-8 w-full items-center justify-between rounded-md px-2 text-xs text-muted-foreground", children: [
9859
- /* @__PURE__ */ jsx31("span", { children: label }),
9860
- /* @__PURE__ */ jsx31("span", { className: "flex items-center gap-0.5", children: keys.map((k, i) => /* @__PURE__ */ jsx31("kbd", { className: popupKbdClass, children: k }, typeof k === "string" ? k : i)) })
9861
- ] }, label)) })
9862
- ]
10557
+ }
10558
+ ),
10559
+ /* @__PURE__ */ jsxs25(
10560
+ BaseButton2,
10561
+ {
10562
+ className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
10563
+ onClick: () => {
10564
+ onFitToViewport?.();
10565
+ onOpenChange(false);
10566
+ },
10567
+ children: [
10568
+ /* @__PURE__ */ jsx32(Minimize2, { className: "size-3.5" }),
10569
+ "Fit to viewport"
10570
+ ]
10571
+ }
10572
+ ),
10573
+ /* @__PURE__ */ jsx32("div", { className: "my-1 border-t border-foreground/10" }),
10574
+ /* @__PURE__ */ jsxs25(
10575
+ BaseButton2,
10576
+ {
10577
+ className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
10578
+ onClick: () => {
10579
+ onToggleCanvas?.();
10580
+ onOpenChange(false);
10581
+ },
10582
+ children: [
10583
+ /* @__PURE__ */ jsx32(Check7, { className: cn("size-3.5", canvasActive ? "opacity-100" : "opacity-0") }),
10584
+ "Canvas mode"
10585
+ ]
10586
+ }
10587
+ )
10588
+ ] })
9863
10589
  }
9864
10590
  ) }) })
9865
10591
  ] });
9866
10592
  }
9867
10593
 
9868
10594
  // src/toolbar.tsx
9869
- import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
10595
+ import { Fragment as Fragment7, jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
9870
10596
  function DirectEditToolbarInner({
9871
10597
  editModeActive,
9872
10598
  onToggleEditMode,
@@ -9883,33 +10609,63 @@ function DirectEditToolbarInner({
9883
10609
  onClearSessionEdits,
9884
10610
  onRemoveSessionEdit,
9885
10611
  onDeleteComment,
9886
- className
10612
+ className,
10613
+ canvasActive = false,
10614
+ canvasZoom = 1,
10615
+ onToggleCanvas,
10616
+ onSetCanvasZoom,
10617
+ onZoomTo100,
10618
+ onFitToViewport
9887
10619
  }) {
9888
10620
  const container = usePortalContainer();
9889
- const toolbarRef = React34.useRef(null);
9890
- const { dockedEdge, isDragging, isSnapping, style: dockStyle, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
10621
+ const toolbarRef = React36.useRef(null);
10622
+ const { dockedEdge, isDragging, isSnapping, style: dockStyle, predictSize, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
9891
10623
  const isVertical = dockedEdge === "left" || dockedEdge === "right";
10624
+ const [activePopover, setActivePopover] = React36.useState(null);
10625
+ const sizeCacheRef = React36.useRef({});
10626
+ React36.useEffect(() => {
10627
+ const el = toolbarRef.current;
10628
+ if (!el) return;
10629
+ const key = `${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`;
10630
+ const timer = setTimeout(() => {
10631
+ const rect = el.getBoundingClientRect();
10632
+ sizeCacheRef.current[key] = { w: rect.width, h: rect.height };
10633
+ }, 350);
10634
+ return () => clearTimeout(timer);
10635
+ }, [editModeActive, dockedEdge]);
10636
+ const prevEditModeRef = React36.useRef(editModeActive);
10637
+ React36.useEffect(() => {
10638
+ if (prevEditModeRef.current === editModeActive) return;
10639
+ prevEditModeRef.current = editModeActive;
10640
+ const target = sizeCacheRef.current[`${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`];
10641
+ if (target) {
10642
+ predictSize(target.w, target.h);
10643
+ }
10644
+ }, [editModeActive, dockedEdge, predictSize]);
10645
+ React36.useEffect(() => {
10646
+ if (isDragging) setActivePopover(null);
10647
+ }, [isDragging]);
10648
+ React36.useEffect(() => {
10649
+ if (!editModeActive) setActivePopover(null);
10650
+ }, [editModeActive]);
9892
10651
  const tooltipSide = dockedEdge === "bottom" ? "top" : dockedEdge === "top" ? "bottom" : dockedEdge === "left" ? "right" : "left";
9893
- const [isMac, setIsMac] = React34.useState(false);
9894
- React34.useEffect(() => {
9895
- setIsMac(navigator.platform?.includes("Mac") ?? false);
9896
- }, []);
10652
+ const [isMac] = React36.useState(() => typeof navigator !== "undefined" ? navigator.platform?.includes("Mac") ?? false : false);
9897
10653
  const kbdClass = "inline-flex items-center justify-center rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground min-w-[20px] min-h-[18px]";
9898
- const shortcutContent = isMac ? /* @__PURE__ */ jsxs25(Fragment7, { children: [
9899
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx32(Command2, { className: "size-2.5" }) }),
9900
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "." })
9901
- ] }) : /* @__PURE__ */ jsxs25(Fragment7, { children: [
9902
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "Ctrl" }),
9903
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "." })
10654
+ const shortcutContent = isMac ? /* @__PURE__ */ jsxs26(Fragment7, { children: [
10655
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx33(Command2, { className: "size-2.5" }) }),
10656
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "." })
10657
+ ] }) : /* @__PURE__ */ jsxs26(Fragment7, { children: [
10658
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "Ctrl" }),
10659
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "." })
9904
10660
  ] });
9905
- const toolbar = /* @__PURE__ */ jsx32(Fragment7, { children: /* @__PURE__ */ jsxs25(
10661
+ const toolbar = /* @__PURE__ */ jsx33(Fragment7, { children: /* @__PURE__ */ jsxs26(
9906
10662
  "div",
9907
10663
  {
9908
10664
  ref: toolbarRef,
9909
10665
  "data-direct-edit": "toolbar",
9910
10666
  style: { pointerEvents: "auto", touchAction: "none", ...dockStyle },
9911
10667
  className: cn(
9912
- "group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg transition-shadow duration-200",
10668
+ "group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg",
9913
10669
  isVertical ? "flex-col items-center" : "flex-row items-center",
9914
10670
  isDragging && "cursor-grabbing select-none shadow-2xl",
9915
10671
  className
@@ -9920,21 +10676,21 @@ function DirectEditToolbarInner({
9920
10676
  onPointerCancel: handlePointerCancel,
9921
10677
  onLostPointerCapture: handlePointerCancel,
9922
10678
  children: [
9923
- /* @__PURE__ */ jsx32("div", { className: cn(
10679
+ /* @__PURE__ */ jsx33("div", { className: cn(
9924
10680
  "flex shrink-0 cursor-grab items-center justify-center",
9925
10681
  isVertical ? "w-full pt-0 pb-1.5" : "h-full pl-0 pr-1.5"
9926
- ), children: /* @__PURE__ */ jsx32("div", { className: cn(
10682
+ ), children: /* @__PURE__ */ jsx33("div", { className: cn(
9927
10683
  "shrink-0 rounded-full bg-foreground/25",
9928
10684
  isVertical ? "h-0.5 w-4" : "h-4 w-0.5"
9929
10685
  ) }) }),
9930
- /* @__PURE__ */ jsxs25(TooltipProvider, { delayDuration: 200, children: [
9931
- /* @__PURE__ */ jsxs25(Tooltip, { children: [
9932
- /* @__PURE__ */ jsx32(
10686
+ /* @__PURE__ */ jsxs26(TooltipProvider, { delayDuration: 200, children: [
10687
+ /* @__PURE__ */ jsxs26(Tooltip, { children: [
10688
+ /* @__PURE__ */ jsx33(
9933
10689
  TooltipTrigger,
9934
10690
  {
9935
10691
  className: cn(
9936
- "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
9937
- editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" : editModeActive && activeTool === "comment" ? "text-muted-foreground hover:bg-muted hover:text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10692
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-[color,background-color] duration-150 ease-out",
10693
+ editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
9938
10694
  ),
9939
10695
  onPointerDown: (e) => e.stopPropagation(),
9940
10696
  onClick: () => {
@@ -9944,89 +10700,144 @@ function DirectEditToolbarInner({
9944
10700
  onToggleEditMode();
9945
10701
  }
9946
10702
  },
9947
- children: /* @__PURE__ */ jsx32(MousePointer2, { className: "size-4" })
10703
+ children: /* @__PURE__ */ jsx33(MousePointer2, { className: "size-4" })
9948
10704
  }
9949
10705
  ),
9950
- /* @__PURE__ */ jsxs25(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
9951
- /* @__PURE__ */ jsx32("span", { children: editModeActive ? "Select" : "Activate design mode" }),
10706
+ /* @__PURE__ */ jsxs26(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
10707
+ /* @__PURE__ */ jsx33("span", { children: editModeActive ? "Select" : "Activate design mode" }),
9952
10708
  shortcutContent
9953
10709
  ] })
9954
10710
  ] }),
9955
- /* @__PURE__ */ jsx32(
10711
+ /* @__PURE__ */ jsx33(
9956
10712
  "div",
9957
10713
  {
9958
10714
  className: cn(
9959
- "overflow-hidden transition-[max-width,max-height,margin,opacity] duration-300 ease-out",
9960
- isVertical ? editModeActive ? "mt-1 max-h-[220px] opacity-100" : "mt-0 max-h-0 opacity-0" : editModeActive ? "ml-1 max-w-[200px] opacity-100" : "ml-0 max-w-0 opacity-0"
10715
+ "grid place-items-center overflow-hidden",
10716
+ isVertical ? editModeActive ? "mt-1 grid-rows-[1fr]" : "mt-0 grid-rows-[0fr]" : editModeActive ? "ml-1 grid-cols-[1fr]" : "ml-0 grid-cols-[0fr]"
9961
10717
  ),
9962
- children: /* @__PURE__ */ jsxs25("div", { className: cn("flex gap-1", isVertical ? "flex-col items-center" : "flex-row items-center"), children: [
9963
- /* @__PURE__ */ jsxs25(Tooltip, { children: [
9964
- /* @__PURE__ */ jsx32(
9965
- TooltipTrigger,
9966
- {
9967
- className: cn(
9968
- "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
9969
- activeTool === "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10718
+ style: {
10719
+ transitionProperty: "grid-template-columns, grid-template-rows, margin",
10720
+ transitionDuration: "200ms",
10721
+ transitionTimingFunction: "cubic-bezier(0.25, 1, 0.5, 1)",
10722
+ transitionDelay: editModeActive ? "0ms" : "80ms"
10723
+ },
10724
+ children: /* @__PURE__ */ jsxs26(
10725
+ "div",
10726
+ {
10727
+ className: cn("flex gap-1 overflow-hidden", isVertical ? "min-h-0 flex-col items-center" : "min-w-0 flex-row items-center"),
10728
+ style: {
10729
+ filter: editModeActive ? "blur(0px)" : "blur(5px)",
10730
+ opacity: editModeActive ? 1 : 0,
10731
+ transitionProperty: "filter, opacity",
10732
+ transitionDuration: "250ms, 100ms",
10733
+ transitionTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
10734
+ transitionDelay: editModeActive ? "80ms" : "0ms"
10735
+ },
10736
+ children: [
10737
+ /* @__PURE__ */ jsxs26(Tooltip, { children: [
10738
+ /* @__PURE__ */ jsx33(
10739
+ TooltipTrigger,
10740
+ {
10741
+ className: cn(
10742
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
10743
+ activeTool === "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10744
+ ),
10745
+ onPointerDown: (e) => e.stopPropagation(),
10746
+ onClick: () => onSetActiveTool?.(activeTool === "comment" ? "select" : "comment"),
10747
+ children: /* @__PURE__ */ jsx33(MessageSquare, { className: "size-4" })
10748
+ }
9970
10749
  ),
9971
- onPointerDown: (e) => e.stopPropagation(),
9972
- onClick: () => onSetActiveTool?.(activeTool === "comment" ? "select" : "comment"),
9973
- children: /* @__PURE__ */ jsx32(MessageSquare, { className: "size-4" })
9974
- }
9975
- ),
9976
- /* @__PURE__ */ jsxs25(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
9977
- /* @__PURE__ */ jsx32("span", { children: activeTool === "comment" ? "Exit comment mode" : "Comment" }),
9978
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx32(ArrowBigUp2, { className: "size-3" }) }),
9979
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "C" })
9980
- ] })
9981
- ] }),
9982
- /* @__PURE__ */ jsxs25(Tooltip, { children: [
9983
- /* @__PURE__ */ jsx32(
9984
- TooltipTrigger,
9985
- {
9986
- className: cn(
9987
- "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
9988
- rulersVisible ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10750
+ /* @__PURE__ */ jsxs26(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
10751
+ /* @__PURE__ */ jsx33("span", { children: activeTool === "comment" ? "Exit comment mode" : "Comment" }),
10752
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx33(ArrowBigUp3, { className: "size-3" }) }),
10753
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "C" })
10754
+ ] })
10755
+ ] }),
10756
+ /* @__PURE__ */ jsxs26(Tooltip, { children: [
10757
+ /* @__PURE__ */ jsx33(
10758
+ TooltipTrigger,
10759
+ {
10760
+ className: cn(
10761
+ "flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
10762
+ rulersVisible ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
10763
+ ),
10764
+ onPointerDown: (e) => e.stopPropagation(),
10765
+ onClick: onToggleRulers,
10766
+ children: /* @__PURE__ */ jsx33(Ruler, { className: "size-4" })
10767
+ }
9989
10768
  ),
9990
- onPointerDown: (e) => e.stopPropagation(),
9991
- onClick: onToggleRulers,
9992
- children: /* @__PURE__ */ jsx32(Ruler, { className: "size-4" })
9993
- }
9994
- ),
9995
- /* @__PURE__ */ jsxs25(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
9996
- /* @__PURE__ */ jsx32("span", { children: rulersVisible ? "Hide rulers" : "Show rulers" }),
9997
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx32(ArrowBigUp2, { className: "size-2.5" }) }),
9998
- /* @__PURE__ */ jsx32("kbd", { className: kbdClass, children: "R" })
9999
- ] })
10000
- ] }),
10001
- /* @__PURE__ */ jsx32("div", { className: cn(
10002
- "border-foreground/10",
10003
- isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
10004
- ) }),
10005
- /* @__PURE__ */ jsx32(
10006
- EditsPopover,
10007
- {
10008
- tooltipSide,
10009
- sessionEditCount,
10010
- isDragging,
10011
- onGetSessionItems,
10012
- onExportAllEdits,
10013
- onSendAllToAgents,
10014
- onClearSessionEdits,
10015
- onRemoveSessionEdit,
10016
- onDeleteComment
10017
- }
10018
- ),
10019
- /* @__PURE__ */ jsx32(
10020
- SettingsPopover,
10021
- {
10022
- tooltipSide,
10023
- theme,
10024
- isMac,
10025
- isDragging,
10026
- onSetTheme
10027
- }
10028
- )
10029
- ] })
10769
+ /* @__PURE__ */ jsxs26(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
10770
+ /* @__PURE__ */ jsx33("span", { children: rulersVisible ? "Hide rulers" : "Show rulers" }),
10771
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: /* @__PURE__ */ jsx33(ArrowBigUp3, { className: "size-2.5" }) }),
10772
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "R" })
10773
+ ] })
10774
+ ] }),
10775
+ /* @__PURE__ */ jsx33(
10776
+ ZoomPopover,
10777
+ {
10778
+ tooltipSide,
10779
+ canvasActive,
10780
+ canvasZoom,
10781
+ isOpen: activePopover === "zoom",
10782
+ onOpenChange: (open) => setActivePopover(open ? "zoom" : null),
10783
+ onToggleCanvas,
10784
+ onSetCanvasZoom,
10785
+ onZoomTo100,
10786
+ onFitToViewport
10787
+ }
10788
+ ),
10789
+ /* @__PURE__ */ jsx33("div", { className: cn(
10790
+ "border-foreground/10",
10791
+ isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
10792
+ ) }),
10793
+ /* @__PURE__ */ jsx33(
10794
+ EditsPopover,
10795
+ {
10796
+ tooltipSide,
10797
+ sessionEditCount,
10798
+ isOpen: activePopover === "edits",
10799
+ onOpenChange: (open) => setActivePopover(open ? "edits" : null),
10800
+ onGetSessionItems,
10801
+ onExportAllEdits,
10802
+ onSendAllToAgents,
10803
+ onClearSessionEdits,
10804
+ onRemoveSessionEdit,
10805
+ onDeleteComment
10806
+ }
10807
+ ),
10808
+ /* @__PURE__ */ jsx33(
10809
+ SettingsPopover,
10810
+ {
10811
+ tooltipSide,
10812
+ theme,
10813
+ isMac,
10814
+ isOpen: activePopover === "settings",
10815
+ onOpenChange: (open) => setActivePopover(open ? "settings" : null),
10816
+ onSetTheme
10817
+ }
10818
+ ),
10819
+ /* @__PURE__ */ jsx33("div", { className: cn(
10820
+ "border-foreground/10",
10821
+ isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
10822
+ ) }),
10823
+ /* @__PURE__ */ jsxs26(Tooltip, { children: [
10824
+ /* @__PURE__ */ jsx33(
10825
+ TooltipTrigger,
10826
+ {
10827
+ className: "flex cursor-pointer items-center justify-center rounded-[8px] p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
10828
+ onPointerDown: (e) => e.stopPropagation(),
10829
+ onClick: onToggleEditMode,
10830
+ children: /* @__PURE__ */ jsx33(X5, { className: "size-4" })
10831
+ }
10832
+ ),
10833
+ /* @__PURE__ */ jsxs26(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
10834
+ /* @__PURE__ */ jsx33("span", { children: "Close" }),
10835
+ /* @__PURE__ */ jsx33("kbd", { className: kbdClass, children: "Esc" })
10836
+ ] })
10837
+ ] })
10838
+ ]
10839
+ }
10840
+ )
10030
10841
  }
10031
10842
  )
10032
10843
  ] })
@@ -10039,7 +10850,7 @@ function DirectEditToolbarInner({
10039
10850
  return toolbar;
10040
10851
  }
10041
10852
  function DirectEditToolbarContent() {
10042
- const { editModeActive, activeTool, theme, sessionEditCount } = useDirectEditState();
10853
+ const { editModeActive, activeTool, theme, sessionEditCount, canvas } = useDirectEditState();
10043
10854
  const {
10044
10855
  toggleEditMode,
10045
10856
  setActiveTool,
@@ -10049,10 +10860,14 @@ function DirectEditToolbarContent() {
10049
10860
  sendAllSessionItemsToAgent,
10050
10861
  clearSessionEdits,
10051
10862
  removeSessionEdit,
10052
- deleteComment
10863
+ deleteComment,
10864
+ toggleCanvas,
10865
+ setCanvasZoom,
10866
+ zoomCanvasTo100,
10867
+ fitCanvasToViewport
10053
10868
  } = useDirectEditActions();
10054
10869
  const [rulersVisible, toggleRulers] = useRulersVisible();
10055
- return /* @__PURE__ */ jsx32(
10870
+ return /* @__PURE__ */ jsx33(
10056
10871
  DirectEditToolbarInner,
10057
10872
  {
10058
10873
  editModeActive,
@@ -10069,34 +10884,40 @@ function DirectEditToolbarContent() {
10069
10884
  onSendAllToAgents: sendAllSessionItemsToAgent,
10070
10885
  onClearSessionEdits: clearSessionEdits,
10071
10886
  onRemoveSessionEdit: removeSessionEdit,
10072
- onDeleteComment: deleteComment
10887
+ onDeleteComment: deleteComment,
10888
+ canvasActive: canvas?.active ?? false,
10889
+ canvasZoom: canvas?.zoom ?? 1,
10890
+ onToggleCanvas: toggleCanvas,
10891
+ onSetCanvasZoom: setCanvasZoom,
10892
+ onZoomTo100: zoomCanvasTo100,
10893
+ onFitToViewport: fitCanvasToViewport
10073
10894
  }
10074
10895
  );
10075
10896
  }
10076
10897
  function DirectEditToolbar() {
10077
- const [mounted, setMounted] = React34.useState(false);
10078
- React34.useEffect(() => {
10898
+ const [mounted, setMounted] = React36.useState(false);
10899
+ React36.useEffect(() => {
10079
10900
  setMounted(true);
10080
10901
  }, []);
10081
10902
  if (!mounted) {
10082
10903
  return null;
10083
10904
  }
10084
- return /* @__PURE__ */ jsx32(DirectEditToolbarContent, {});
10905
+ return /* @__PURE__ */ jsx33(DirectEditToolbarContent, {});
10085
10906
  }
10086
10907
 
10087
10908
  // src/direct-edit.tsx
10088
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
10909
+ import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
10089
10910
  function DirectEdit() {
10090
- return /* @__PURE__ */ jsxs26(DirectEditProvider, { children: [
10091
- /* @__PURE__ */ jsx33(DirectEditPanel, {}),
10092
- /* @__PURE__ */ jsx33(DirectEditToolbar, {}),
10093
- /* @__PURE__ */ jsx33(Rulers, {})
10911
+ return /* @__PURE__ */ jsxs27(DirectEditProvider, { children: [
10912
+ /* @__PURE__ */ jsx34(DirectEditPanel, {}),
10913
+ /* @__PURE__ */ jsx34(DirectEditToolbar, {}),
10914
+ /* @__PURE__ */ jsx34(Rulers, {})
10094
10915
  ] });
10095
10916
  }
10096
10917
 
10097
10918
  // src/demo.tsx
10098
- import * as React35 from "react";
10099
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
10919
+ import * as React37 from "react";
10920
+ import { jsx as jsx35, jsxs as jsxs28 } from "react/jsx-runtime";
10100
10921
  function createValue(num, unit = "px") {
10101
10922
  return { numericValue: num, unit, raw: `${num}${unit}` };
10102
10923
  }
@@ -10124,7 +10945,7 @@ var DEMO_LOCATOR = {
10124
10945
  classList: ELEMENT_INFO.classList
10125
10946
  };
10126
10947
  function DirectEditDemo() {
10127
- const [spacing, setSpacing] = React35.useState({
10948
+ const [spacing, setSpacing] = React37.useState({
10128
10949
  paddingTop: createValue(16),
10129
10950
  paddingRight: createValue(16),
10130
10951
  paddingBottom: createValue(16),
@@ -10135,13 +10956,13 @@ function DirectEditDemo() {
10135
10956
  marginLeft: createValue(0),
10136
10957
  gap: createValue(16)
10137
10958
  });
10138
- const [borderRadius, setBorderRadius] = React35.useState({
10959
+ const [borderRadius, setBorderRadius] = React37.useState({
10139
10960
  borderTopLeftRadius: createValue(8),
10140
10961
  borderTopRightRadius: createValue(8),
10141
10962
  borderBottomRightRadius: createValue(8),
10142
10963
  borderBottomLeftRadius: createValue(8)
10143
10964
  });
10144
- const [border, setBorder] = React35.useState({
10965
+ const [border, setBorder] = React37.useState({
10145
10966
  borderTopStyle: "solid",
10146
10967
  borderTopWidth: createValue(1),
10147
10968
  borderRightStyle: "solid",
@@ -10151,23 +10972,23 @@ function DirectEditDemo() {
10151
10972
  borderLeftStyle: "solid",
10152
10973
  borderLeftWidth: createValue(1)
10153
10974
  });
10154
- const [flex, setFlex] = React35.useState({
10975
+ const [flex, setFlex] = React37.useState({
10155
10976
  display: "flex",
10156
10977
  flexDirection: "row",
10157
10978
  justifyContent: "flex-start",
10158
10979
  alignItems: "center"
10159
10980
  });
10160
- const [sizing, setSizing] = React35.useState({
10981
+ const [sizing, setSizing] = React37.useState({
10161
10982
  width: { mode: "fit", value: createValue(300) },
10162
10983
  height: { mode: "fit", value: createValue(100) }
10163
10984
  });
10164
- const [color, setColor] = React35.useState({
10985
+ const [color, setColor] = React37.useState({
10165
10986
  backgroundColor: { hex: "FFFFFF", alpha: 100, raw: "rgb(255, 255, 255)" },
10166
10987
  color: { hex: "000000", alpha: 100, raw: "rgb(0, 0, 0)" },
10167
10988
  borderColor: { hex: "DDDDDD", alpha: 100, raw: "rgb(221, 221, 221)" },
10168
10989
  outlineColor: { hex: "000000", alpha: 0, raw: "transparent" }
10169
10990
  });
10170
- const [typography, setTypography] = React35.useState({
10991
+ const [typography, setTypography] = React37.useState({
10171
10992
  fontFamily: "system-ui, sans-serif",
10172
10993
  fontWeight: "400",
10173
10994
  fontSize: createValue(16),
@@ -10176,9 +10997,9 @@ function DirectEditDemo() {
10176
10997
  textAlign: "left",
10177
10998
  textVerticalAlign: "flex-start"
10178
10999
  });
10179
- const [boxShadow, setBoxShadow] = React35.useState("none");
10180
- const [pendingStyles, setPendingStyles] = React35.useState({});
10181
- const [editModeActive, setEditModeActive] = React35.useState(false);
11000
+ const [boxShadow, setBoxShadow] = React37.useState("none");
11001
+ const [pendingStyles, setPendingStyles] = React37.useState({});
11002
+ const [editModeActive, setEditModeActive] = React37.useState(false);
10182
11003
  const handleUpdateSpacing = (key, value) => {
10183
11004
  setSpacing((prev) => ({ ...prev, [key]: value }));
10184
11005
  setPendingStyles((prev) => ({ ...prev, [camelToKebab(key)]: value.raw }));
@@ -10289,10 +11110,10 @@ function DirectEditDemo() {
10289
11110
  return false;
10290
11111
  }
10291
11112
  };
10292
- return /* @__PURE__ */ jsx34("div", { className: "min-h-screen p-8", children: /* @__PURE__ */ jsxs27("div", { className: "mx-auto max-w-4xl", children: [
10293
- /* @__PURE__ */ jsx34("h1", { className: "mb-2 text-2xl font-bold", children: "Direct Edit Panel" }),
10294
- /* @__PURE__ */ jsx34("p", { className: "mb-8 text-muted-foreground", children: "Interactive showcase of the visual editing panel UI with mock data." }),
10295
- /* @__PURE__ */ jsx34("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ jsx34(
11113
+ return /* @__PURE__ */ jsx35("div", { className: "min-h-screen p-8", children: /* @__PURE__ */ jsxs28("div", { className: "mx-auto max-w-4xl", children: [
11114
+ /* @__PURE__ */ jsx35("h1", { className: "mb-2 text-2xl font-bold", children: "Direct Edit Panel" }),
11115
+ /* @__PURE__ */ jsx35("p", { className: "mb-8 text-muted-foreground", children: "Interactive showcase of the visual editing panel UI with mock data." }),
11116
+ /* @__PURE__ */ jsx35("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ jsx35(
10296
11117
  DirectEditToolbarInner,
10297
11118
  {
10298
11119
  editModeActive,
@@ -10302,8 +11123,8 @@ function DirectEditDemo() {
10302
11123
  }
10303
11124
  }
10304
11125
  ) }),
10305
- /* @__PURE__ */ jsxs27("div", { className: "grid gap-8 lg:grid-cols-[300px_1fr]", children: [
10306
- /* @__PURE__ */ jsx34(
11126
+ /* @__PURE__ */ jsxs28("div", { className: "grid gap-8 lg:grid-cols-[300px_1fr]", children: [
11127
+ /* @__PURE__ */ jsx35(
10307
11128
  DirectEditPanelInner,
10308
11129
  {
10309
11130
  elementInfo: ELEMENT_INFO,
@@ -10335,10 +11156,10 @@ function DirectEditDemo() {
10335
11156
  onSendToAgent: async () => false
10336
11157
  }
10337
11158
  ),
10338
- /* @__PURE__ */ jsxs27("div", { className: "space-y-6", children: [
10339
- /* @__PURE__ */ jsxs27("div", { children: [
10340
- /* @__PURE__ */ jsx34("h2", { className: "mb-3 text-sm font-medium", children: "Live Preview" }),
10341
- /* @__PURE__ */ jsxs27(
11159
+ /* @__PURE__ */ jsxs28("div", { className: "space-y-6", children: [
11160
+ /* @__PURE__ */ jsxs28("div", { children: [
11161
+ /* @__PURE__ */ jsx35("h2", { className: "mb-3 text-sm font-medium", children: "Live Preview" }),
11162
+ /* @__PURE__ */ jsxs28(
10342
11163
  "div",
10343
11164
  {
10344
11165
  className: "bg-background border flex",
@@ -10361,20 +11182,20 @@ function DirectEditDemo() {
10361
11182
  alignItems: flex.alignItems
10362
11183
  },
10363
11184
  children: [
10364
- /* @__PURE__ */ jsx34("div", { className: "size-12 rounded bg-blue-500/20 border border-blue-500/30" }),
10365
- /* @__PURE__ */ jsx34("div", { className: "size-12 rounded bg-green-500/20 border border-green-500/30" }),
10366
- /* @__PURE__ */ jsx34("div", { className: "size-12 rounded bg-purple-500/20 border border-purple-500/30" })
11185
+ /* @__PURE__ */ jsx35("div", { className: "size-12 rounded bg-blue-500/20 border border-blue-500/30" }),
11186
+ /* @__PURE__ */ jsx35("div", { className: "size-12 rounded bg-green-500/20 border border-green-500/30" }),
11187
+ /* @__PURE__ */ jsx35("div", { className: "size-12 rounded bg-purple-500/20 border border-purple-500/30" })
10367
11188
  ]
10368
11189
  }
10369
11190
  )
10370
11191
  ] }),
10371
- /* @__PURE__ */ jsxs27("div", { children: [
10372
- /* @__PURE__ */ jsx34("h2", { className: "mb-3 text-sm font-medium", children: "Pending Styles" }),
10373
- /* @__PURE__ */ jsx34("pre", { className: "rounded-lg border bg-background p-4 text-xs min-h-[60px]", children: Object.keys(pendingStyles).length > 0 ? JSON.stringify(pendingStyles, null, 2) : "// Make changes to see pending styles" })
11192
+ /* @__PURE__ */ jsxs28("div", { children: [
11193
+ /* @__PURE__ */ jsx35("h2", { className: "mb-3 text-sm font-medium", children: "Pending Styles" }),
11194
+ /* @__PURE__ */ jsx35("pre", { className: "rounded-lg border bg-background p-4 text-xs min-h-[60px]", children: Object.keys(pendingStyles).length > 0 ? JSON.stringify(pendingStyles, null, 2) : "// Make changes to see pending styles" })
10374
11195
  ] }),
10375
- /* @__PURE__ */ jsxs27("div", { children: [
10376
- /* @__PURE__ */ jsx34("h2", { className: "mb-3 text-sm font-medium", children: "Tailwind Classes" }),
10377
- /* @__PURE__ */ jsx34("code", { className: "block rounded-lg border bg-background p-4 text-xs min-h-[40px]", children: Object.keys(pendingStyles).length > 0 ? stylesToTailwind(pendingStyles) : "// Tailwind classes will appear here" })
11196
+ /* @__PURE__ */ jsxs28("div", { children: [
11197
+ /* @__PURE__ */ jsx35("h2", { className: "mb-3 text-sm font-medium", children: "Tailwind Classes" }),
11198
+ /* @__PURE__ */ jsx35("code", { className: "block rounded-lg border bg-background p-4 text-xs min-h-[40px]", children: Object.keys(pendingStyles).length > 0 ? stylesToTailwind(pendingStyles) : "// Tailwind classes will appear here" })
10378
11199
  ] })
10379
11200
  ] })
10380
11201
  ] })