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/README.md +1 -1
- package/dist/index.d.mts +24 -6
- package/dist/index.d.ts +24 -6
- package/dist/index.js +1686 -865
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1687 -866
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/{utils-BHGlXxF7.d.mts → utils-C7RBdUAE.d.mts} +8 -1
- package/dist/{utils-BHGlXxF7.d.ts → utils-C7RBdUAE.d.ts} +8 -1
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +9 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +8 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/provider.tsx
|
|
4
|
-
import * as
|
|
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.
|
|
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
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
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((
|
|
3736
|
+
const canSendEditToAgent = React5.useCallback((snapshot2) => {
|
|
3724
3737
|
const current = stateRef.current;
|
|
3725
|
-
const selectedElement =
|
|
3726
|
-
const elementInfo =
|
|
3727
|
-
const 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
|
-
|
|
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
|
|
3880
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
3943
|
-
var DirectEditActionsContext =
|
|
4299
|
+
var DirectEditStateContext = React8.createContext(null);
|
|
4300
|
+
var DirectEditActionsContext = React8.createContext(null);
|
|
3944
4301
|
function useDirectEditState() {
|
|
3945
|
-
const context =
|
|
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 =
|
|
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
|
|
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] =
|
|
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:
|
|
3982
|
-
borderStyleControlPreference:
|
|
4361
|
+
theme: getInitialTheme(),
|
|
4362
|
+
borderStyleControlPreference: getInitialBorderStyleControlPreference(),
|
|
3983
4363
|
comments: [],
|
|
3984
4364
|
activeCommentId: null,
|
|
3985
|
-
textEditingElement: null
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4529
|
+
const stateContextValue = React8.useMemo(() => ({
|
|
4146
4530
|
...state,
|
|
4147
4531
|
sessionEditCount
|
|
4148
4532
|
}), [state, sessionEditCount]);
|
|
4149
|
-
const actionsContextValue =
|
|
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
|
-
|
|
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
|
|
4643
|
+
import * as React29 from "react";
|
|
4252
4644
|
import { createPortal } from "react-dom";
|
|
4253
4645
|
|
|
4254
4646
|
// src/ui/tooltip.tsx
|
|
4255
|
-
import * as
|
|
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 =
|
|
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-
|
|
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
|
|
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] =
|
|
4301
|
-
const [state, setState] =
|
|
4302
|
-
const [mousePosition, setMousePosition] =
|
|
4303
|
-
const rafRef =
|
|
4304
|
-
const mousePositionRef =
|
|
4305
|
-
const getElementBelow =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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] =
|
|
4478
|
-
|
|
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
|
|
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] =
|
|
4523
|
-
const [dropTarget, setDropTarget] =
|
|
4524
|
-
const [dropIndicator, setDropIndicator] =
|
|
4525
|
-
const dragStateRef =
|
|
4526
|
-
const dropTargetRef =
|
|
4527
|
-
const onMoveCompleteRef =
|
|
4528
|
-
const dragOptionsRef =
|
|
4529
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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] =
|
|
4714
|
-
const [hydrated, setHydrated] =
|
|
4715
|
-
const [activeGuidelineId, setActiveGuidelineId] =
|
|
4716
|
-
const [dragPosition, setDragPosition] =
|
|
4717
|
-
const [isCreating, setIsCreating] =
|
|
4718
|
-
const [scrollOffset, setScrollOffset] =
|
|
4719
|
-
const hostRef =
|
|
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
|
|
4722
|
-
|
|
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 =
|
|
4725
|
-
|
|
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
|
-
|
|
5168
|
+
React13.useEffect(() => {
|
|
4730
5169
|
if (!hydrated) return;
|
|
4731
5170
|
saveGuidelines(guidelines);
|
|
4732
5171
|
}, [guidelines, hydrated]);
|
|
4733
|
-
|
|
5172
|
+
React13.useEffect(() => {
|
|
4734
5173
|
if (!enabled) return;
|
|
4735
5174
|
function update() {
|
|
4736
|
-
setScrollOffset(
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
4761
|
-
|
|
4762
|
-
return viewportToCssCoord(hostRef.current, raw, axis);
|
|
4763
|
-
}
|
|
5208
|
+
let lastPos = NaN;
|
|
5209
|
+
let lastTime = 0;
|
|
4764
5210
|
function onPointerMove(e) {
|
|
4765
|
-
const
|
|
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
|
|
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:
|
|
5241
|
+
(prev) => prev.map((g) => g.id === guidelineId ? { ...g, position: storedPosition } : g)
|
|
4770
5242
|
);
|
|
4771
5243
|
}
|
|
4772
5244
|
function onPointerUp(e) {
|
|
4773
|
-
const
|
|
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
|
-
|
|
5260
|
+
React13.useEffect(() => {
|
|
4787
5261
|
if (!enabled && dragging) {
|
|
4788
5262
|
endDrag();
|
|
4789
5263
|
}
|
|
4790
5264
|
}, [enabled, dragging, endDrag]);
|
|
4791
|
-
const activeGuideline =
|
|
5265
|
+
const activeGuideline = React13.useMemo(
|
|
4792
5266
|
() => guidelines.find((g) => g.id === activeGuidelineId) ?? null,
|
|
4793
5267
|
[guidelines, activeGuidelineId]
|
|
4794
5268
|
);
|
|
4795
|
-
const startCreate =
|
|
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
|
|
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 =
|
|
5295
|
+
const startDrag = React13.useCallback((guidelineId) => {
|
|
4812
5296
|
const guideline = guidelinesRef.current.find((g) => g.id === guidelineId);
|
|
4813
5297
|
if (!guideline) return;
|
|
4814
|
-
|
|
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(
|
|
5310
|
+
setDragPosition(viewportPos);
|
|
4817
5311
|
dragInfoRef.current = { guidelineId, orientation: guideline.orientation, isCreating: false };
|
|
4818
5312
|
setDragging(true);
|
|
4819
5313
|
}, []);
|
|
4820
|
-
const deleteGuideline =
|
|
5314
|
+
const deleteGuideline = React13.useCallback((guidelineId) => {
|
|
4821
5315
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
4822
5316
|
}, []);
|
|
4823
|
-
const clearAll =
|
|
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
|
-
|
|
4886
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
5405
|
+
"div",
|
|
4916
5406
|
{
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
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
|
-
"
|
|
5422
|
+
"div",
|
|
4930
5423
|
{
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
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
|
|
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] =
|
|
5005
|
-
const [moveHandleRects, setMoveHandleRects] =
|
|
5006
|
-
const cleanupRef =
|
|
5007
|
-
const clickThroughTimerRef =
|
|
5008
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
"
|
|
5651
|
+
!isTextEditing && /* @__PURE__ */ jsx7(
|
|
5652
|
+
"div",
|
|
5155
5653
|
{
|
|
5156
5654
|
"data-direct-edit": "selection-overlay",
|
|
5157
5655
|
style: {
|
|
5158
5656
|
position: "fixed",
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5657
|
+
left: displayX,
|
|
5658
|
+
top: displayY,
|
|
5659
|
+
width: rect.width,
|
|
5660
|
+
height: rect.height,
|
|
5162
5661
|
pointerEvents: "none",
|
|
5163
|
-
zIndex: 99996
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
"
|
|
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
|
|
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] =
|
|
5308
|
-
const [elementRect, setElementRect] =
|
|
5309
|
-
const [flipHorizontal, setFlipHorizontal] =
|
|
5310
|
-
const [flipVertical, setFlipVertical] =
|
|
5311
|
-
|
|
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
|
-
|
|
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] =
|
|
5425
|
-
const [showError, setShowError] =
|
|
5426
|
-
const inputRef =
|
|
5427
|
-
const cardRef =
|
|
5428
|
-
|
|
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
|
-
|
|
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) =>
|
|
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] =
|
|
5521
|
-
const [copied, setCopied] =
|
|
5522
|
-
const [sendStatus, setSendStatus] =
|
|
5523
|
-
const inputRef =
|
|
5524
|
-
const copyTimerRef =
|
|
5525
|
-
|
|
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
|
-
|
|
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
|
|
6216
|
+
import * as React17 from "react";
|
|
5717
6217
|
|
|
5718
6218
|
// src/ui/input.tsx
|
|
5719
|
-
import * as
|
|
6219
|
+
import * as React16 from "react";
|
|
5720
6220
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
5721
|
-
var Input =
|
|
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] =
|
|
5744
|
-
|
|
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 =
|
|
5792
|
-
const [activeSection, setActiveSection] =
|
|
5793
|
-
|
|
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
|
|
6354
|
+
import * as React20 from "react";
|
|
5855
6355
|
|
|
5856
6356
|
// src/ui/button.tsx
|
|
5857
|
-
import * as
|
|
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 =
|
|
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
|
|
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 =
|
|
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] =
|
|
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
|
|
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
|
|
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 =
|
|
6642
|
+
var ColorPickerGroupContext = React21.createContext(null);
|
|
6143
6643
|
function ColorPickerGroup({ children }) {
|
|
6144
|
-
const [activePickerId, setActivePickerId] =
|
|
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 =
|
|
6149
|
-
const handlePointerEvent =
|
|
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 =
|
|
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 =
|
|
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] =
|
|
6239
|
-
|
|
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 =
|
|
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] =
|
|
6265
|
-
const [alpha, setAlpha] =
|
|
6266
|
-
const lastSyncedHex =
|
|
6267
|
-
|
|
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 =
|
|
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 =
|
|
6362
|
-
const triggerRef =
|
|
6363
|
-
const onCloseRef =
|
|
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
|
-
|
|
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] =
|
|
6436
|
-
|
|
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] =
|
|
6456
|
-
|
|
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
|
|
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] =
|
|
6486
|
-
const [alphaInput, setAlphaInput] =
|
|
6487
|
-
|
|
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] =
|
|
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
|
|
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
|
|
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__ */
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
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] =
|
|
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
|
|
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] =
|
|
7097
|
-
const [alphaInput, setAlphaInput] =
|
|
7098
|
-
|
|
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 =
|
|
7190
|
-
const [layers, setLayers] =
|
|
7693
|
+
const parsedLayers = React24.useMemo(() => parseShadowLayers(effectiveShadow), [effectiveShadow]);
|
|
7694
|
+
const [layers, setLayers] = React24.useState(parsedLayers);
|
|
7191
7695
|
const hasShadow = layers.length > 0;
|
|
7192
|
-
|
|
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
|
|
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] =
|
|
7511
|
-
const [copyError, setCopyError] =
|
|
7512
|
-
const [sendStatus, setSendStatus] =
|
|
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
|
|
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] =
|
|
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
|
|
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] =
|
|
7733
|
-
|
|
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] =
|
|
7795
|
-
const ratioRef =
|
|
7796
|
-
|
|
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
|
|
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] =
|
|
8143
|
-
const [isDragging, setIsDragging] =
|
|
8144
|
-
const [isSnapping, setIsSnapping] =
|
|
8145
|
-
const [dragOffset, setDragOffset] =
|
|
8146
|
-
const snapTimerRef =
|
|
8147
|
-
const panelRef =
|
|
8148
|
-
const positionRef =
|
|
8149
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
8278
|
-
radius:
|
|
8279
|
-
border:
|
|
8280
|
-
shadow:
|
|
8281
|
-
colors:
|
|
8282
|
-
text:
|
|
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] =
|
|
8481
|
-
const [commentInputAttention, setCommentInputAttention] =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
8504
|
-
if (
|
|
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:
|
|
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] =
|
|
8686
|
-
|
|
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
|
|
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
|
|
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 =
|
|
8708
|
-
mq
|
|
8709
|
-
|
|
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
|
|
9263
|
+
return getColorSchemeQuery()?.matches ?? false;
|
|
8713
9264
|
}
|
|
8714
9265
|
function useSystemDark() {
|
|
8715
|
-
return
|
|
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 =
|
|
9278
|
+
const canvasRef = React30.useRef(null);
|
|
8727
9279
|
const viewportWidth = useViewportWidth();
|
|
8728
9280
|
const { theme } = useDirectEditState();
|
|
8729
9281
|
const systemDark = useSystemDark();
|
|
8730
|
-
|
|
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
|
|
8749
|
-
const
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
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
|
|
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 =
|
|
9354
|
+
const canvasRef = React30.useRef(null);
|
|
8798
9355
|
const viewportHeight = useViewportHeight();
|
|
8799
9356
|
const { theme } = useDirectEditState();
|
|
8800
9357
|
const systemDark = useSystemDark();
|
|
8801
|
-
|
|
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
|
|
8820
|
-
const
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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-
|
|
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
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
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
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
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] =
|
|
9021
|
-
|
|
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] =
|
|
9031
|
-
|
|
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
|
|
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 =
|
|
9751
|
+
const visible = React30.useSyncExternalStore(
|
|
9124
9752
|
subscribeRulersVisible,
|
|
9125
9753
|
() => rulersVisibleSnapshot,
|
|
9126
9754
|
() => true
|
|
9127
9755
|
);
|
|
9128
|
-
const toggle =
|
|
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
|
-
|
|
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
|
|
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
|
|
9806
|
+
function getDockedPosition(edge, width, height) {
|
|
9179
9807
|
const { minX, maxX, minY, maxY } = getToolbarBounds(width, height);
|
|
9180
|
-
const
|
|
9181
|
-
const
|
|
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:
|
|
9812
|
+
return { x: centerX, y: maxY };
|
|
9185
9813
|
case "top":
|
|
9186
|
-
return { x:
|
|
9814
|
+
return { x: centerX, y: minY };
|
|
9187
9815
|
case "left":
|
|
9188
|
-
return { x: minX, y:
|
|
9816
|
+
return { x: minX, y: centerY };
|
|
9189
9817
|
case "right":
|
|
9190
|
-
return { x: maxX, y:
|
|
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] =
|
|
9214
|
-
const [phase, setPhase] =
|
|
9215
|
-
const [dragPosition, setDragPosition] =
|
|
9216
|
-
const dragOffsetRef =
|
|
9217
|
-
const
|
|
9218
|
-
const
|
|
9219
|
-
const
|
|
9220
|
-
const
|
|
9221
|
-
const
|
|
9222
|
-
const
|
|
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] =
|
|
9229
|
-
const [
|
|
9230
|
-
|
|
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
|
-
|
|
9235
|
-
dockedPosRef.current = pos;
|
|
9236
|
-
setDockedPos(pos);
|
|
9237
|
-
setReady(true);
|
|
9871
|
+
setDockedTransitionEnabled(true);
|
|
9238
9872
|
});
|
|
9239
9873
|
return () => cancelAnimationFrame(raf);
|
|
9240
|
-
}, [
|
|
9241
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 [
|
|
9455
|
-
const [
|
|
9456
|
-
const
|
|
9457
|
-
const
|
|
9458
|
-
const
|
|
9459
|
-
|
|
9460
|
-
|
|
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
|
-
|
|
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
|
-
}, [
|
|
9477
|
-
|
|
9478
|
-
if (
|
|
10113
|
+
}, [isOpen, onOpenChange]);
|
|
10114
|
+
React33.useEffect(() => {
|
|
10115
|
+
if (isOpen && onGetSessionItems) {
|
|
9479
10116
|
setEditsSnapshot(onGetSessionItems());
|
|
9480
10117
|
}
|
|
9481
|
-
}, [
|
|
9482
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
9540
|
-
/* @__PURE__ */
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
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
|
-
|
|
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
|
|
9716
|
-
import {
|
|
9717
|
-
import {
|
|
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
|
|
10314
|
+
function SettingsMenuPortal(props) {
|
|
9721
10315
|
const container = usePortalContainer();
|
|
9722
|
-
return /* @__PURE__ */ jsx31(
|
|
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
|
-
|
|
10322
|
+
isOpen,
|
|
10323
|
+
onOpenChange,
|
|
9733
10324
|
onSetTheme
|
|
9734
10325
|
}) {
|
|
9735
|
-
const
|
|
9736
|
-
const settingsPopupRef =
|
|
9737
|
-
const
|
|
9738
|
-
const
|
|
9739
|
-
const
|
|
9740
|
-
|
|
9741
|
-
|
|
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 (
|
|
9745
|
-
if (
|
|
9746
|
-
|
|
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
|
-
}, [
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
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
|
-
|
|
9812
|
-
|
|
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:
|
|
9816
|
-
className: "w-[
|
|
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
|
-
|
|
9819
|
-
|
|
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:
|
|
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
|
-
|
|
9840
|
-
|
|
10550
|
+
onZoomTo100?.();
|
|
10551
|
+
onOpenChange(false);
|
|
9841
10552
|
},
|
|
9842
10553
|
children: [
|
|
9843
|
-
/* @__PURE__ */
|
|
9844
|
-
|
|
10554
|
+
/* @__PURE__ */ jsx32(Scan, { className: "size-3.5" }),
|
|
10555
|
+
"Actual size (100%)"
|
|
9845
10556
|
]
|
|
9846
|
-
}
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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__ */
|
|
9899
|
-
/* @__PURE__ */
|
|
9900
|
-
/* @__PURE__ */
|
|
9901
|
-
] }) : /* @__PURE__ */
|
|
9902
|
-
/* @__PURE__ */
|
|
9903
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
9931
|
-
/* @__PURE__ */
|
|
9932
|
-
/* @__PURE__ */
|
|
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-
|
|
9937
|
-
editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" :
|
|
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__ */
|
|
10703
|
+
children: /* @__PURE__ */ jsx33(MousePointer2, { className: "size-4" })
|
|
9948
10704
|
}
|
|
9949
10705
|
),
|
|
9950
|
-
/* @__PURE__ */
|
|
9951
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10711
|
+
/* @__PURE__ */ jsx33(
|
|
9956
10712
|
"div",
|
|
9957
10713
|
{
|
|
9958
10714
|
className: cn(
|
|
9959
|
-
"
|
|
9960
|
-
isVertical ? editModeActive ? "mt-1
|
|
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
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
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
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
/* @__PURE__ */
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
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
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
/* @__PURE__ */
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
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__ */
|
|
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] =
|
|
10078
|
-
|
|
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__ */
|
|
10905
|
+
return /* @__PURE__ */ jsx33(DirectEditToolbarContent, {});
|
|
10085
10906
|
}
|
|
10086
10907
|
|
|
10087
10908
|
// src/direct-edit.tsx
|
|
10088
|
-
import { jsx as
|
|
10909
|
+
import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
10089
10910
|
function DirectEdit() {
|
|
10090
|
-
return /* @__PURE__ */
|
|
10091
|
-
/* @__PURE__ */
|
|
10092
|
-
/* @__PURE__ */
|
|
10093
|
-
/* @__PURE__ */
|
|
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
|
|
10099
|
-
import { jsx as
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
10180
|
-
const [pendingStyles, setPendingStyles] =
|
|
10181
|
-
const [editModeActive, setEditModeActive] =
|
|
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__ */
|
|
10293
|
-
/* @__PURE__ */
|
|
10294
|
-
/* @__PURE__ */
|
|
10295
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10306
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10339
|
-
/* @__PURE__ */
|
|
10340
|
-
/* @__PURE__ */
|
|
10341
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10365
|
-
/* @__PURE__ */
|
|
10366
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10372
|
-
/* @__PURE__ */
|
|
10373
|
-
/* @__PURE__ */
|
|
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__ */
|
|
10376
|
-
/* @__PURE__ */
|
|
10377
|
-
/* @__PURE__ */
|
|
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
|
] })
|