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.js
CHANGED
|
@@ -79,13 +79,13 @@ __export(index_exports, {
|
|
|
79
79
|
module.exports = __toCommonJS(index_exports);
|
|
80
80
|
|
|
81
81
|
// src/provider.tsx
|
|
82
|
-
var
|
|
82
|
+
var React8 = __toESM(require("react"));
|
|
83
83
|
|
|
84
84
|
// src/portal-container.tsx
|
|
85
85
|
var React = __toESM(require("react"));
|
|
86
86
|
|
|
87
87
|
// dist/styles.css
|
|
88
|
-
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}}';
|
|
88
|
+
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}}';
|
|
89
89
|
|
|
90
90
|
// src/portal-container.tsx
|
|
91
91
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -114,7 +114,7 @@ function PortalContainerProvider({ children }) {
|
|
|
114
114
|
const root = document.createElement("div");
|
|
115
115
|
root.setAttribute("data-direct-edit-root", "");
|
|
116
116
|
shadow.appendChild(root);
|
|
117
|
-
document.
|
|
117
|
+
document.documentElement.appendChild(host);
|
|
118
118
|
setContainer(root);
|
|
119
119
|
return () => {
|
|
120
120
|
host.remove();
|
|
@@ -156,6 +156,13 @@ function clamp(value, min, max) {
|
|
|
156
156
|
if (max < min) return min;
|
|
157
157
|
return Math.max(min, Math.min(max, value));
|
|
158
158
|
}
|
|
159
|
+
function isInputFocused() {
|
|
160
|
+
let active = document.activeElement;
|
|
161
|
+
while (active?.shadowRoot?.activeElement) {
|
|
162
|
+
active = active.shadowRoot.activeElement;
|
|
163
|
+
}
|
|
164
|
+
return active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
|
|
165
|
+
}
|
|
159
166
|
function getComputedStyles(element) {
|
|
160
167
|
const computed = window.getComputedStyle(element);
|
|
161
168
|
return {
|
|
@@ -2812,6 +2819,7 @@ function useSessionManager({
|
|
|
2812
2819
|
borderStyleControlPreference: prev.borderStyleControlPreference,
|
|
2813
2820
|
comments: prev.comments,
|
|
2814
2821
|
activeCommentId: prev.activeCommentId,
|
|
2822
|
+
canvas: prev.canvas,
|
|
2815
2823
|
textEditingElement: null
|
|
2816
2824
|
}));
|
|
2817
2825
|
}, [pushUndo, saveCurrentToSession]);
|
|
@@ -2946,6 +2954,7 @@ function useSessionManager({
|
|
|
2946
2954
|
borderStyleControlPreference: prev.borderStyleControlPreference,
|
|
2947
2955
|
comments: prev.comments,
|
|
2948
2956
|
activeCommentId: prev.activeCommentId,
|
|
2957
|
+
canvas: prev.canvas,
|
|
2949
2958
|
textEditingElement: null
|
|
2950
2959
|
}));
|
|
2951
2960
|
} else {
|
|
@@ -3144,6 +3153,7 @@ function useSessionManager({
|
|
|
3144
3153
|
borderStyleControlPreference: prev.borderStyleControlPreference,
|
|
3145
3154
|
comments: prev.comments,
|
|
3146
3155
|
activeCommentId: prev.activeCommentId,
|
|
3156
|
+
canvas: prev.canvas,
|
|
3147
3157
|
textEditingElement: null
|
|
3148
3158
|
}));
|
|
3149
3159
|
},
|
|
@@ -3357,8 +3367,8 @@ function useTextAndComments({
|
|
|
3357
3367
|
const locator = getElementLocator(element);
|
|
3358
3368
|
const rect = element.getBoundingClientRect();
|
|
3359
3369
|
const relativePosition = {
|
|
3360
|
-
x: clickPosition.x - rect.left,
|
|
3361
|
-
y: clickPosition.y - rect.top
|
|
3370
|
+
x: rect.width > 0 ? (clickPosition.x - rect.left) / rect.width : 0,
|
|
3371
|
+
y: rect.height > 0 ? (clickPosition.y - rect.top) / rect.height : 0
|
|
3362
3372
|
};
|
|
3363
3373
|
const id = `comment-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
3364
3374
|
const comment = {
|
|
@@ -3371,11 +3381,14 @@ function useTextAndComments({
|
|
|
3371
3381
|
createdAt: Date.now(),
|
|
3372
3382
|
replies: []
|
|
3373
3383
|
};
|
|
3374
|
-
setState((prev) =>
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3384
|
+
setState((prev) => {
|
|
3385
|
+
const filtered = prev.activeCommentId ? prev.comments.filter((c) => c.id !== prev.activeCommentId || c.text.trim().length > 0) : prev.comments;
|
|
3386
|
+
return {
|
|
3387
|
+
...prev,
|
|
3388
|
+
comments: [...filtered, comment],
|
|
3389
|
+
activeCommentId: id
|
|
3390
|
+
};
|
|
3391
|
+
});
|
|
3379
3392
|
}, []);
|
|
3380
3393
|
const updateCommentText = React4.useCallback((id, text) => {
|
|
3381
3394
|
setState((prev) => ({
|
|
@@ -3798,11 +3811,11 @@ async function sendCommentToAgent(comment) {
|
|
|
3798
3811
|
|
|
3799
3812
|
// src/use-agent-comms.ts
|
|
3800
3813
|
function useAgentComms({ stateRef, sessionEditsRef, getSessionItems }) {
|
|
3801
|
-
const canSendEditToAgent = React5.useCallback((
|
|
3814
|
+
const canSendEditToAgent = React5.useCallback((snapshot2) => {
|
|
3802
3815
|
const current = stateRef.current;
|
|
3803
|
-
const selectedElement =
|
|
3804
|
-
const elementInfo =
|
|
3805
|
-
const pendingStyles =
|
|
3816
|
+
const selectedElement = snapshot2?.selectedElement ?? current.selectedElement;
|
|
3817
|
+
const elementInfo = snapshot2?.elementInfo ?? current.elementInfo;
|
|
3818
|
+
const pendingStyles = snapshot2?.pendingStyles ?? current.pendingStyles;
|
|
3806
3819
|
if (!selectedElement || !elementInfo) return false;
|
|
3807
3820
|
const sessionEdit = sessionEditsRef.current.get(selectedElement);
|
|
3808
3821
|
const hasPendingStyles = Object.keys(pendingStyles).length > 0;
|
|
@@ -3925,7 +3938,11 @@ function useKeyboardShortcuts({
|
|
|
3925
3938
|
commitTextEditing,
|
|
3926
3939
|
startTextEditing,
|
|
3927
3940
|
closePanel,
|
|
3928
|
-
setState
|
|
3941
|
+
setState,
|
|
3942
|
+
toggleCanvas,
|
|
3943
|
+
setCanvasZoom,
|
|
3944
|
+
fitCanvasToViewport,
|
|
3945
|
+
zoomCanvasTo100
|
|
3929
3946
|
}) {
|
|
3930
3947
|
React6.useEffect(() => {
|
|
3931
3948
|
function handleToggle(e) {
|
|
@@ -3947,15 +3964,13 @@ function useKeyboardShortcuts({
|
|
|
3947
3964
|
return;
|
|
3948
3965
|
}
|
|
3949
3966
|
if (e.key === "C" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive) {
|
|
3950
|
-
|
|
3951
|
-
const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
|
|
3952
|
-
if (!isInput) {
|
|
3967
|
+
if (!isInputFocused()) {
|
|
3953
3968
|
e.preventDefault();
|
|
3954
3969
|
setState((prev) => {
|
|
3955
3970
|
let comments = prev.comments;
|
|
3956
3971
|
if (prev.activeCommentId) {
|
|
3957
|
-
const
|
|
3958
|
-
if (
|
|
3972
|
+
const active = comments.find((c) => c.id === prev.activeCommentId);
|
|
3973
|
+
if (active && active.text === "") {
|
|
3959
3974
|
comments = comments.filter((c) => c.id !== prev.activeCommentId);
|
|
3960
3975
|
}
|
|
3961
3976
|
}
|
|
@@ -3969,19 +3984,44 @@ function useKeyboardShortcuts({
|
|
|
3969
3984
|
return;
|
|
3970
3985
|
}
|
|
3971
3986
|
}
|
|
3987
|
+
if (e.key === "Z" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive) {
|
|
3988
|
+
if (!isInputFocused()) {
|
|
3989
|
+
e.preventDefault();
|
|
3990
|
+
toggleCanvas();
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey && s.canvas?.active) {
|
|
3995
|
+
if (e.code === "Digit0" || e.key === "0") {
|
|
3996
|
+
e.preventDefault();
|
|
3997
|
+
fitCanvasToViewport();
|
|
3998
|
+
return;
|
|
3999
|
+
}
|
|
4000
|
+
if (e.code === "Digit1" || e.key === "1") {
|
|
4001
|
+
e.preventDefault();
|
|
4002
|
+
zoomCanvasTo100();
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
if (e.code === "Equal" || e.key === "=") {
|
|
4006
|
+
e.preventDefault();
|
|
4007
|
+
setCanvasZoom(Math.min(5, (s.canvas?.zoom ?? 1) * 1.1));
|
|
4008
|
+
return;
|
|
4009
|
+
}
|
|
4010
|
+
if (e.code === "Minus" || e.key === "-") {
|
|
4011
|
+
e.preventDefault();
|
|
4012
|
+
setCanvasZoom(Math.max(0.1, (s.canvas?.zoom ?? 1) / 1.1));
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
3972
4016
|
if (e.key === "A" && e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey && s.editModeActive && s.selectedElement) {
|
|
3973
|
-
|
|
3974
|
-
const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
|
|
3975
|
-
if (!isInput) {
|
|
4017
|
+
if (!isInputFocused()) {
|
|
3976
4018
|
e.preventDefault();
|
|
3977
4019
|
toggleFlexLayout();
|
|
3978
4020
|
return;
|
|
3979
4021
|
}
|
|
3980
4022
|
}
|
|
3981
4023
|
if (e.key === "Enter" && s.editModeActive && !s.textEditingElement && s.selectedElement) {
|
|
3982
|
-
|
|
3983
|
-
const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
|
|
3984
|
-
if (!isInput && isTextElement(s.selectedElement)) {
|
|
4024
|
+
if (!isInputFocused() && isTextElement(s.selectedElement)) {
|
|
3985
4025
|
e.preventDefault();
|
|
3986
4026
|
startTextEditing(s.selectedElement);
|
|
3987
4027
|
return;
|
|
@@ -4012,22 +4052,339 @@ function useKeyboardShortcuts({
|
|
|
4012
4052
|
}
|
|
4013
4053
|
window.addEventListener("keydown", handleKeyDown);
|
|
4014
4054
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4015
|
-
}, [closePanel, toggleEditMode, toggleFlexLayout, undo, commitTextEditing, startTextEditing]);
|
|
4055
|
+
}, [closePanel, toggleEditMode, toggleFlexLayout, undo, commitTextEditing, startTextEditing, toggleCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100]);
|
|
4056
|
+
}
|
|
4057
|
+
|
|
4058
|
+
// src/use-canvas.ts
|
|
4059
|
+
var React7 = __toESM(require("react"));
|
|
4060
|
+
|
|
4061
|
+
// src/canvas-store.ts
|
|
4062
|
+
var import_react = require("react");
|
|
4063
|
+
var DEFAULT = { active: false, zoom: 1, panX: 0, panY: 0 };
|
|
4064
|
+
var snapshot = DEFAULT;
|
|
4065
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
4066
|
+
var ownerCount = 0;
|
|
4067
|
+
var bodyOffset = { x: 0, y: 0 };
|
|
4068
|
+
function getBodyOffset() {
|
|
4069
|
+
return bodyOffset;
|
|
4070
|
+
}
|
|
4071
|
+
function setBodyOffset(o) {
|
|
4072
|
+
bodyOffset = o;
|
|
4073
|
+
}
|
|
4074
|
+
function getCanvasSnapshot() {
|
|
4075
|
+
return snapshot;
|
|
4076
|
+
}
|
|
4077
|
+
function setCanvasSnapshot(next) {
|
|
4078
|
+
snapshot = next;
|
|
4079
|
+
listeners.forEach((cb) => cb());
|
|
4080
|
+
}
|
|
4081
|
+
function registerCanvasStoreOwner() {
|
|
4082
|
+
ownerCount += 1;
|
|
4083
|
+
if (ownerCount > 1 && (typeof process === "undefined" || process.env.NODE_ENV !== "test")) {
|
|
4084
|
+
console.warn("[made-refine] multiple DirectEditProvider instances share canvas-store globals");
|
|
4085
|
+
}
|
|
4086
|
+
return () => {
|
|
4087
|
+
ownerCount = Math.max(0, ownerCount - 1);
|
|
4088
|
+
};
|
|
4089
|
+
}
|
|
4090
|
+
function subscribe(cb) {
|
|
4091
|
+
listeners.add(cb);
|
|
4092
|
+
return () => {
|
|
4093
|
+
listeners.delete(cb);
|
|
4094
|
+
};
|
|
4095
|
+
}
|
|
4096
|
+
function useCanvasSnapshot() {
|
|
4097
|
+
return (0, import_react.useSyncExternalStore)(subscribe, getCanvasSnapshot, () => DEFAULT);
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
// src/use-canvas.ts
|
|
4101
|
+
var MIN_ZOOM = 0.1;
|
|
4102
|
+
var MAX_ZOOM = 5;
|
|
4103
|
+
var ZOOM_SENSITIVITY = 0.0145;
|
|
4104
|
+
var LINE_HEIGHT_PX = 40;
|
|
4105
|
+
var PAGE_HEIGHT_PX = 800;
|
|
4106
|
+
function normalizeWheelDelta(e) {
|
|
4107
|
+
let { deltaX, deltaY } = e;
|
|
4108
|
+
if (e.deltaMode === 1) {
|
|
4109
|
+
deltaX *= LINE_HEIGHT_PX;
|
|
4110
|
+
deltaY *= LINE_HEIGHT_PX;
|
|
4111
|
+
} else if (e.deltaMode === 2) {
|
|
4112
|
+
deltaX *= PAGE_HEIGHT_PX;
|
|
4113
|
+
deltaY *= PAGE_HEIGHT_PX;
|
|
4114
|
+
}
|
|
4115
|
+
return { deltaX, deltaY };
|
|
4116
|
+
}
|
|
4117
|
+
var PAN_MARGIN = 0.1;
|
|
4118
|
+
function clampPan(zoom, panX, panY, bodyW, bodyH) {
|
|
4119
|
+
const vw = window.innerWidth;
|
|
4120
|
+
const vh = window.innerHeight;
|
|
4121
|
+
const minPanX = PAN_MARGIN * vw / zoom - bodyW;
|
|
4122
|
+
const maxPanX = (1 - PAN_MARGIN) * vw / zoom;
|
|
4123
|
+
const minPanY = PAN_MARGIN * vh / zoom - bodyH;
|
|
4124
|
+
const maxPanY = (1 - PAN_MARGIN) * vh / zoom;
|
|
4125
|
+
return {
|
|
4126
|
+
panX: Math.max(minPanX, Math.min(maxPanX, panX)),
|
|
4127
|
+
panY: Math.max(minPanY, Math.min(maxPanY, panY))
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
function useCanvas({ stateRef, setState }) {
|
|
4131
|
+
React7.useEffect(() => registerCanvasStoreOwner(), []);
|
|
4132
|
+
const canvasRef = React7.useRef({ active: false, zoom: 1, panX: 0, panY: 0 });
|
|
4133
|
+
const savedScrollRef = React7.useRef({ x: 0, y: 0 });
|
|
4134
|
+
const savedBodyOverflowRef = React7.useRef("");
|
|
4135
|
+
const savedHtmlOverflowRef = React7.useRef("");
|
|
4136
|
+
const savedHtmlBgColorRef = React7.useRef("");
|
|
4137
|
+
const savedBodyDimensionsRef = React7.useRef({ width: 0, height: 0 });
|
|
4138
|
+
const rafIdRef = React7.useRef(null);
|
|
4139
|
+
const rafPendingRef = React7.useRef(false);
|
|
4140
|
+
const spaceHeldRef = React7.useRef(false);
|
|
4141
|
+
const isDraggingRef = React7.useRef(false);
|
|
4142
|
+
const dragStartRef = React7.useRef({ x: 0, y: 0, panX: 0, panY: 0 });
|
|
4143
|
+
const applyTransform = React7.useCallback((zoom, panX, panY) => {
|
|
4144
|
+
document.body.style.transformOrigin = "0 0";
|
|
4145
|
+
document.body.style.transform = `scale(${zoom}) translate(${panX}px, ${panY}px)`;
|
|
4146
|
+
}, []);
|
|
4147
|
+
const dispatchCanvasChange = React7.useCallback(() => {
|
|
4148
|
+
window.dispatchEvent(new Event("direct-edit-canvas-change"));
|
|
4149
|
+
}, []);
|
|
4150
|
+
const readBodyOffset = React7.useCallback(() => {
|
|
4151
|
+
const bodyStyle = getComputedStyle(document.body);
|
|
4152
|
+
return {
|
|
4153
|
+
x: parseFloat(bodyStyle.marginLeft) || 0,
|
|
4154
|
+
y: parseFloat(bodyStyle.marginTop) || 0
|
|
4155
|
+
};
|
|
4156
|
+
}, []);
|
|
4157
|
+
const updateBodyOffset = React7.useCallback(() => {
|
|
4158
|
+
const next = readBodyOffset();
|
|
4159
|
+
const prev = getBodyOffset();
|
|
4160
|
+
if (prev.x === next.x && prev.y === next.y) return false;
|
|
4161
|
+
setBodyOffset(next);
|
|
4162
|
+
return true;
|
|
4163
|
+
}, [readBodyOffset]);
|
|
4164
|
+
const cancelPendingRaf = React7.useCallback(() => {
|
|
4165
|
+
if (rafIdRef.current !== null) {
|
|
4166
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
4167
|
+
rafIdRef.current = null;
|
|
4168
|
+
rafPendingRef.current = false;
|
|
4169
|
+
}
|
|
4170
|
+
}, []);
|
|
4171
|
+
const updateCanvas = React7.useCallback((zoom, panX, panY) => {
|
|
4172
|
+
const dims = savedBodyDimensionsRef.current;
|
|
4173
|
+
const bodyW = dims.width || window.innerWidth;
|
|
4174
|
+
const bodyH = dims.height || window.innerHeight;
|
|
4175
|
+
const clamped = clampPan(zoom, panX, panY, bodyW, bodyH);
|
|
4176
|
+
canvasRef.current = { ...canvasRef.current, zoom, panX: clamped.panX, panY: clamped.panY };
|
|
4177
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4178
|
+
applyTransform(zoom, clamped.panX, clamped.panY);
|
|
4179
|
+
dispatchCanvasChange();
|
|
4180
|
+
if (!rafPendingRef.current) {
|
|
4181
|
+
rafPendingRef.current = true;
|
|
4182
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
4183
|
+
rafPendingRef.current = false;
|
|
4184
|
+
rafIdRef.current = null;
|
|
4185
|
+
const s = canvasRef.current;
|
|
4186
|
+
setState((prev) => ({
|
|
4187
|
+
...prev,
|
|
4188
|
+
canvas: { active: s.active, zoom: s.zoom, panX: s.panX, panY: s.panY }
|
|
4189
|
+
}));
|
|
4190
|
+
});
|
|
4191
|
+
}
|
|
4192
|
+
}, [applyTransform, dispatchCanvasChange, setState]);
|
|
4193
|
+
const enterCanvas = React7.useCallback(() => {
|
|
4194
|
+
const scrollX = window.scrollX;
|
|
4195
|
+
const scrollY = window.scrollY;
|
|
4196
|
+
savedScrollRef.current = { x: scrollX, y: scrollY };
|
|
4197
|
+
savedBodyOverflowRef.current = document.body.style.overflow;
|
|
4198
|
+
savedHtmlOverflowRef.current = document.documentElement.style.overflow;
|
|
4199
|
+
savedHtmlBgColorRef.current = document.documentElement.style.backgroundColor;
|
|
4200
|
+
savedBodyDimensionsRef.current = {
|
|
4201
|
+
width: document.body.scrollWidth,
|
|
4202
|
+
height: document.body.scrollHeight
|
|
4203
|
+
};
|
|
4204
|
+
const existingTransform = document.body.style.transform;
|
|
4205
|
+
if (existingTransform && existingTransform !== "none" && existingTransform !== "") {
|
|
4206
|
+
console.warn("[made-refine] canvas mode: overriding existing body transform:", existingTransform);
|
|
4207
|
+
}
|
|
4208
|
+
window.scrollTo(0, 0);
|
|
4209
|
+
updateBodyOffset();
|
|
4210
|
+
document.body.style.overflow = "hidden";
|
|
4211
|
+
document.documentElement.style.overflow = "hidden";
|
|
4212
|
+
document.documentElement.style.backgroundColor = "#F5F5F5";
|
|
4213
|
+
const initialPanX = -scrollX;
|
|
4214
|
+
const initialPanY = -scrollY;
|
|
4215
|
+
applyTransform(1, initialPanX, initialPanY);
|
|
4216
|
+
canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
|
|
4217
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4218
|
+
setState((prev) => ({
|
|
4219
|
+
...prev,
|
|
4220
|
+
canvas: { active: true, zoom: 1, panX: initialPanX, panY: initialPanY }
|
|
4221
|
+
}));
|
|
4222
|
+
dispatchCanvasChange();
|
|
4223
|
+
}, [applyTransform, dispatchCanvasChange, setState, updateBodyOffset]);
|
|
4224
|
+
const exitCanvas = React7.useCallback(() => {
|
|
4225
|
+
cancelPendingRaf();
|
|
4226
|
+
document.body.style.transform = "";
|
|
4227
|
+
document.body.style.transformOrigin = "";
|
|
4228
|
+
document.body.style.overflow = savedBodyOverflowRef.current;
|
|
4229
|
+
document.documentElement.style.overflow = savedHtmlOverflowRef.current;
|
|
4230
|
+
document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
|
|
4231
|
+
document.body.style.cursor = "";
|
|
4232
|
+
window.scrollTo(savedScrollRef.current.x, savedScrollRef.current.y);
|
|
4233
|
+
setBodyOffset({ x: 0, y: 0 });
|
|
4234
|
+
canvasRef.current = { active: false, zoom: 1, panX: 0, panY: 0 };
|
|
4235
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4236
|
+
setState((prev) => ({
|
|
4237
|
+
...prev,
|
|
4238
|
+
canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
|
|
4239
|
+
}));
|
|
4240
|
+
dispatchCanvasChange();
|
|
4241
|
+
}, [cancelPendingRaf, dispatchCanvasChange, setState]);
|
|
4242
|
+
const toggleCanvas = React7.useCallback(() => {
|
|
4243
|
+
if (canvasRef.current.active) {
|
|
4244
|
+
exitCanvas();
|
|
4245
|
+
} else {
|
|
4246
|
+
enterCanvas();
|
|
4247
|
+
}
|
|
4248
|
+
}, [enterCanvas, exitCanvas]);
|
|
4249
|
+
const setCanvasZoom = React7.useCallback((zoom) => {
|
|
4250
|
+
const c = canvasRef.current;
|
|
4251
|
+
if (!c.active) return;
|
|
4252
|
+
const clampedZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
|
|
4253
|
+
updateCanvas(clampedZoom, c.panX, c.panY);
|
|
4254
|
+
}, [updateCanvas]);
|
|
4255
|
+
const fitCanvasToViewport = React7.useCallback(() => {
|
|
4256
|
+
const c = canvasRef.current;
|
|
4257
|
+
if (!c.active) return;
|
|
4258
|
+
const bodyWidth = savedBodyDimensionsRef.current.width || window.innerWidth;
|
|
4259
|
+
const bodyHeight = savedBodyDimensionsRef.current.height || window.innerHeight;
|
|
4260
|
+
const scaleX = window.innerWidth / bodyWidth;
|
|
4261
|
+
const scaleY = window.innerHeight / bodyHeight;
|
|
4262
|
+
const zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, Math.min(scaleX, scaleY) * 0.9));
|
|
4263
|
+
const panX = (window.innerWidth / zoom - bodyWidth) / 2;
|
|
4264
|
+
const panY = (window.innerHeight / zoom - bodyHeight) / 2;
|
|
4265
|
+
updateCanvas(zoom, panX, panY);
|
|
4266
|
+
}, [updateCanvas]);
|
|
4267
|
+
const zoomCanvasTo100 = React7.useCallback(() => {
|
|
4268
|
+
const c = canvasRef.current;
|
|
4269
|
+
if (!c.active) return;
|
|
4270
|
+
updateCanvas(1, 0, 0);
|
|
4271
|
+
}, [updateCanvas]);
|
|
4272
|
+
React7.useEffect(() => {
|
|
4273
|
+
function handleWheel(e) {
|
|
4274
|
+
const c = canvasRef.current;
|
|
4275
|
+
if (!c.active) return;
|
|
4276
|
+
e.preventDefault();
|
|
4277
|
+
const { deltaX, deltaY } = normalizeWheelDelta(e);
|
|
4278
|
+
if (e.ctrlKey || e.metaKey) {
|
|
4279
|
+
const zoomFactor = Math.exp(-deltaY * ZOOM_SENSITIVITY);
|
|
4280
|
+
const oldZoom = c.zoom;
|
|
4281
|
+
const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * zoomFactor));
|
|
4282
|
+
const cx = e.clientX;
|
|
4283
|
+
const cy = e.clientY;
|
|
4284
|
+
const bo = getBodyOffset();
|
|
4285
|
+
const newPanX = c.panX + (cx - bo.x) * (1 / newZoom - 1 / oldZoom);
|
|
4286
|
+
const newPanY = c.panY + (cy - bo.y) * (1 / newZoom - 1 / oldZoom);
|
|
4287
|
+
updateCanvas(newZoom, newPanX, newPanY);
|
|
4288
|
+
} else {
|
|
4289
|
+
const newPanX = c.panX - deltaX / c.zoom;
|
|
4290
|
+
const newPanY = c.panY - deltaY / c.zoom;
|
|
4291
|
+
updateCanvas(c.zoom, newPanX, newPanY);
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
window.addEventListener("wheel", handleWheel, { passive: false });
|
|
4295
|
+
return () => window.removeEventListener("wheel", handleWheel);
|
|
4296
|
+
}, [updateCanvas]);
|
|
4297
|
+
React7.useEffect(() => {
|
|
4298
|
+
function handleResize() {
|
|
4299
|
+
if (!canvasRef.current.active) return;
|
|
4300
|
+
if (updateBodyOffset()) {
|
|
4301
|
+
dispatchCanvasChange();
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
window.addEventListener("resize", handleResize);
|
|
4305
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
4306
|
+
}, [dispatchCanvasChange, updateBodyOffset]);
|
|
4307
|
+
React7.useEffect(() => {
|
|
4308
|
+
function handleKeyDown(e) {
|
|
4309
|
+
if (e.code !== "Space" || e.repeat) return;
|
|
4310
|
+
if (!canvasRef.current.active) return;
|
|
4311
|
+
if (isInputFocused()) return;
|
|
4312
|
+
spaceHeldRef.current = true;
|
|
4313
|
+
if (!isDraggingRef.current) {
|
|
4314
|
+
document.body.style.cursor = "grab";
|
|
4315
|
+
}
|
|
4316
|
+
e.preventDefault();
|
|
4317
|
+
}
|
|
4318
|
+
function handleKeyUp(e) {
|
|
4319
|
+
if (e.code !== "Space") return;
|
|
4320
|
+
if (!canvasRef.current.active) return;
|
|
4321
|
+
spaceHeldRef.current = false;
|
|
4322
|
+
if (!isDraggingRef.current) {
|
|
4323
|
+
document.body.style.cursor = "";
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
4327
|
+
window.addEventListener("keyup", handleKeyUp, true);
|
|
4328
|
+
return () => {
|
|
4329
|
+
window.removeEventListener("keydown", handleKeyDown, true);
|
|
4330
|
+
window.removeEventListener("keyup", handleKeyUp, true);
|
|
4331
|
+
};
|
|
4332
|
+
}, []);
|
|
4333
|
+
React7.useEffect(() => {
|
|
4334
|
+
function handlePointerDown(e) {
|
|
4335
|
+
const c = canvasRef.current;
|
|
4336
|
+
if (!c.active) return;
|
|
4337
|
+
const isMiddleMouse = e.button === 1;
|
|
4338
|
+
const isSpaceDrag = spaceHeldRef.current && e.button === 0;
|
|
4339
|
+
if (!isMiddleMouse && !isSpaceDrag) return;
|
|
4340
|
+
e.preventDefault();
|
|
4341
|
+
isDraggingRef.current = true;
|
|
4342
|
+
dragStartRef.current = { x: e.clientX, y: e.clientY, panX: c.panX, panY: c.panY };
|
|
4343
|
+
document.body.style.cursor = "grabbing";
|
|
4344
|
+
const dragAbort = new AbortController();
|
|
4345
|
+
const opts = { signal: dragAbort.signal };
|
|
4346
|
+
function endDrag() {
|
|
4347
|
+
isDraggingRef.current = false;
|
|
4348
|
+
document.body.style.cursor = spaceHeldRef.current ? "grab" : "";
|
|
4349
|
+
dragAbort.abort();
|
|
4350
|
+
}
|
|
4351
|
+
window.addEventListener("pointermove", (moveE) => {
|
|
4352
|
+
const current = canvasRef.current;
|
|
4353
|
+
const dx = (moveE.clientX - dragStartRef.current.x) / current.zoom;
|
|
4354
|
+
const dy = (moveE.clientY - dragStartRef.current.y) / current.zoom;
|
|
4355
|
+
updateCanvas(current.zoom, dragStartRef.current.panX + dx, dragStartRef.current.panY + dy);
|
|
4356
|
+
}, opts);
|
|
4357
|
+
window.addEventListener("pointerup", endDrag, opts);
|
|
4358
|
+
window.addEventListener("pointercancel", endDrag, opts);
|
|
4359
|
+
window.addEventListener("blur", endDrag, opts);
|
|
4360
|
+
}
|
|
4361
|
+
window.addEventListener("pointerdown", handlePointerDown, true);
|
|
4362
|
+
return () => window.removeEventListener("pointerdown", handlePointerDown, true);
|
|
4363
|
+
}, [updateCanvas]);
|
|
4364
|
+
React7.useEffect(() => {
|
|
4365
|
+
return () => {
|
|
4366
|
+
cancelPendingRaf();
|
|
4367
|
+
if (canvasRef.current.active) {
|
|
4368
|
+
exitCanvas();
|
|
4369
|
+
}
|
|
4370
|
+
};
|
|
4371
|
+
}, [cancelPendingRaf, exitCanvas]);
|
|
4372
|
+
return { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 };
|
|
4016
4373
|
}
|
|
4017
4374
|
|
|
4018
4375
|
// src/provider.tsx
|
|
4019
4376
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
4020
|
-
var DirectEditStateContext =
|
|
4021
|
-
var DirectEditActionsContext =
|
|
4377
|
+
var DirectEditStateContext = React8.createContext(null);
|
|
4378
|
+
var DirectEditActionsContext = React8.createContext(null);
|
|
4022
4379
|
function useDirectEditState() {
|
|
4023
|
-
const context =
|
|
4380
|
+
const context = React8.useContext(DirectEditStateContext);
|
|
4024
4381
|
if (!context) {
|
|
4025
4382
|
throw new Error("useDirectEditState must be used within a DirectEditProvider");
|
|
4026
4383
|
}
|
|
4027
4384
|
return context;
|
|
4028
4385
|
}
|
|
4029
4386
|
function useDirectEditActions() {
|
|
4030
|
-
const context =
|
|
4387
|
+
const context = React8.useContext(DirectEditActionsContext);
|
|
4031
4388
|
if (!context) {
|
|
4032
4389
|
throw new Error("useDirectEditActions must be used within a DirectEditProvider");
|
|
4033
4390
|
}
|
|
@@ -4036,11 +4393,34 @@ function useDirectEditActions() {
|
|
|
4036
4393
|
function useDirectEdit() {
|
|
4037
4394
|
const state = useDirectEditState();
|
|
4038
4395
|
const actions = useDirectEditActions();
|
|
4039
|
-
return
|
|
4396
|
+
return React8.useMemo(() => ({ ...state, ...actions }), [state, actions]);
|
|
4040
4397
|
}
|
|
4041
4398
|
var BORDER_STYLE_CONTROL_PREFERENCE_KEY = "direct-edit-border-style-control";
|
|
4399
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? React8.useEffect : React8.useLayoutEffect;
|
|
4400
|
+
function getInitialTheme() {
|
|
4401
|
+
if (typeof window === "undefined") return "system";
|
|
4402
|
+
try {
|
|
4403
|
+
const theme = localStorage.getItem("direct-edit-theme");
|
|
4404
|
+
if (theme === "light" || theme === "dark" || theme === "system") {
|
|
4405
|
+
return theme;
|
|
4406
|
+
}
|
|
4407
|
+
} catch {
|
|
4408
|
+
}
|
|
4409
|
+
return "system";
|
|
4410
|
+
}
|
|
4411
|
+
function getInitialBorderStyleControlPreference() {
|
|
4412
|
+
if (typeof window === "undefined") return "icon";
|
|
4413
|
+
try {
|
|
4414
|
+
const borderPref = localStorage.getItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY);
|
|
4415
|
+
if (borderPref === "label" || borderPref === "icon") {
|
|
4416
|
+
return borderPref;
|
|
4417
|
+
}
|
|
4418
|
+
} catch {
|
|
4419
|
+
}
|
|
4420
|
+
return "icon";
|
|
4421
|
+
}
|
|
4042
4422
|
function DirectEditProvider({ children }) {
|
|
4043
|
-
const [state, setState] =
|
|
4423
|
+
const [state, setState] = React8.useState(() => ({
|
|
4044
4424
|
isOpen: false,
|
|
4045
4425
|
selectedElement: null,
|
|
4046
4426
|
elementInfo: null,
|
|
@@ -4056,38 +4436,22 @@ function DirectEditProvider({ children }) {
|
|
|
4056
4436
|
pendingStyles: {},
|
|
4057
4437
|
editModeActive: false,
|
|
4058
4438
|
activeTool: "select",
|
|
4059
|
-
theme:
|
|
4060
|
-
borderStyleControlPreference:
|
|
4439
|
+
theme: getInitialTheme(),
|
|
4440
|
+
borderStyleControlPreference: getInitialBorderStyleControlPreference(),
|
|
4061
4441
|
comments: [],
|
|
4062
4442
|
activeCommentId: null,
|
|
4063
|
-
textEditingElement: null
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
const borderPref = localStorage.getItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY);
|
|
4073
|
-
if (borderPref === "label" || borderPref === "icon") {
|
|
4074
|
-
updates.borderStyleControlPreference = borderPref;
|
|
4075
|
-
}
|
|
4076
|
-
if (Object.keys(updates).length > 0) {
|
|
4077
|
-
setState((prev) => ({ ...prev, ...updates }));
|
|
4078
|
-
}
|
|
4079
|
-
} catch {
|
|
4080
|
-
}
|
|
4081
|
-
}, []);
|
|
4082
|
-
const undoStackRef = React7.useRef([]);
|
|
4083
|
-
const sessionEditsRef = React7.useRef(/* @__PURE__ */ new Map());
|
|
4084
|
-
const removedSessionEditsRef = React7.useRef(/* @__PURE__ */ new WeakSet());
|
|
4085
|
-
const [sessionEditCount, setSessionEditCount] = React7.useState(0);
|
|
4086
|
-
const stateRef = React7.useRef(state);
|
|
4087
|
-
React7.useEffect(() => {
|
|
4443
|
+
textEditingElement: null,
|
|
4444
|
+
canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
|
|
4445
|
+
}));
|
|
4446
|
+
const undoStackRef = React8.useRef([]);
|
|
4447
|
+
const sessionEditsRef = React8.useRef(/* @__PURE__ */ new Map());
|
|
4448
|
+
const removedSessionEditsRef = React8.useRef(/* @__PURE__ */ new WeakSet());
|
|
4449
|
+
const [sessionEditCount, setSessionEditCount] = React8.useState(0);
|
|
4450
|
+
const stateRef = React8.useRef(state);
|
|
4451
|
+
React8.useEffect(() => {
|
|
4088
4452
|
stateRef.current = state;
|
|
4089
4453
|
});
|
|
4090
|
-
const pushUndo =
|
|
4454
|
+
const pushUndo = React8.useCallback((entry) => {
|
|
4091
4455
|
undoStackRef.current.push(entry);
|
|
4092
4456
|
if (undoStackRef.current.length > 500) {
|
|
4093
4457
|
undoStackRef.current = undoStackRef.current.slice(-500);
|
|
@@ -4132,13 +4496,13 @@ function DirectEditProvider({ children }) {
|
|
|
4132
4496
|
setState,
|
|
4133
4497
|
setSessionEditCount
|
|
4134
4498
|
});
|
|
4135
|
-
|
|
4499
|
+
React8.useEffect(() => {
|
|
4136
4500
|
if (!state.selectedElement) return;
|
|
4137
4501
|
saveCurrentToSession();
|
|
4138
4502
|
}, [state.selectedElement, state.pendingStyles, saveCurrentToSession]);
|
|
4139
4503
|
const {
|
|
4140
4504
|
finalizeTextEditing,
|
|
4141
|
-
toggleEditMode,
|
|
4505
|
+
toggleEditMode: toggleEditModeBase,
|
|
4142
4506
|
startTextEditing,
|
|
4143
4507
|
commitTextEditing,
|
|
4144
4508
|
addComment,
|
|
@@ -4155,10 +4519,32 @@ function DirectEditProvider({ children }) {
|
|
|
4155
4519
|
syncSessionItemCount,
|
|
4156
4520
|
setState
|
|
4157
4521
|
});
|
|
4158
|
-
|
|
4522
|
+
const { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 } = useCanvas({
|
|
4523
|
+
stateRef,
|
|
4524
|
+
setState
|
|
4525
|
+
});
|
|
4526
|
+
const closePanel = React8.useCallback(() => {
|
|
4527
|
+
setState((prev) => ({
|
|
4528
|
+
...prev,
|
|
4529
|
+
isOpen: false
|
|
4530
|
+
}));
|
|
4531
|
+
}, []);
|
|
4532
|
+
const toggleEditMode = React8.useCallback(() => {
|
|
4533
|
+
const wasActive = stateRef.current.editModeActive;
|
|
4534
|
+
toggleEditModeBase();
|
|
4535
|
+
if (wasActive && stateRef.current.canvas?.active) {
|
|
4536
|
+
exitCanvas();
|
|
4537
|
+
} else if (!wasActive) {
|
|
4538
|
+
enterCanvas();
|
|
4539
|
+
}
|
|
4540
|
+
if (wasActive) {
|
|
4541
|
+
closePanel();
|
|
4542
|
+
}
|
|
4543
|
+
}, [toggleEditModeBase, stateRef, exitCanvas, enterCanvas, closePanel]);
|
|
4544
|
+
React8.useEffect(() => {
|
|
4159
4545
|
syncSessionItemCount(state.comments);
|
|
4160
4546
|
}, [state.comments, syncSessionItemCount]);
|
|
4161
|
-
|
|
4547
|
+
React8.useEffect(() => {
|
|
4162
4548
|
const editingElement = state.textEditingElement;
|
|
4163
4549
|
if (!editingElement) return;
|
|
4164
4550
|
const activeEditingElement = editingElement;
|
|
@@ -4183,27 +4569,21 @@ function DirectEditProvider({ children }) {
|
|
|
4183
4569
|
sendCommentToAgent: sendCommentToAgent2,
|
|
4184
4570
|
sendAllSessionItemsToAgent
|
|
4185
4571
|
} = useAgentComms({ stateRef, sessionEditsRef, getSessionItems });
|
|
4186
|
-
const
|
|
4187
|
-
setState((prev) => ({
|
|
4188
|
-
...prev,
|
|
4189
|
-
isOpen: false
|
|
4190
|
-
}));
|
|
4191
|
-
}, []);
|
|
4192
|
-
const setActiveTool = React7.useCallback((tool) => {
|
|
4572
|
+
const setActiveTool = React8.useCallback((tool) => {
|
|
4193
4573
|
setState((prev) => ({
|
|
4194
4574
|
...prev,
|
|
4195
4575
|
activeTool: tool,
|
|
4196
4576
|
activeCommentId: null
|
|
4197
4577
|
}));
|
|
4198
4578
|
}, []);
|
|
4199
|
-
const setTheme =
|
|
4579
|
+
const setTheme = React8.useCallback((theme) => {
|
|
4200
4580
|
setState((prev) => ({ ...prev, theme }));
|
|
4201
4581
|
try {
|
|
4202
4582
|
localStorage.setItem("direct-edit-theme", theme);
|
|
4203
4583
|
} catch {
|
|
4204
4584
|
}
|
|
4205
4585
|
}, []);
|
|
4206
|
-
const setBorderStyleControlPreference =
|
|
4586
|
+
const setBorderStyleControlPreference = React8.useCallback((preference) => {
|
|
4207
4587
|
setState((prev) => ({ ...prev, borderStyleControlPreference: preference }));
|
|
4208
4588
|
try {
|
|
4209
4589
|
localStorage.setItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY, preference);
|
|
@@ -4218,13 +4598,17 @@ function DirectEditProvider({ children }) {
|
|
|
4218
4598
|
commitTextEditing,
|
|
4219
4599
|
startTextEditing,
|
|
4220
4600
|
closePanel,
|
|
4221
|
-
setState
|
|
4601
|
+
setState,
|
|
4602
|
+
toggleCanvas,
|
|
4603
|
+
setCanvasZoom,
|
|
4604
|
+
fitCanvasToViewport,
|
|
4605
|
+
zoomCanvasTo100
|
|
4222
4606
|
});
|
|
4223
|
-
const stateContextValue =
|
|
4607
|
+
const stateContextValue = React8.useMemo(() => ({
|
|
4224
4608
|
...state,
|
|
4225
4609
|
sessionEditCount
|
|
4226
4610
|
}), [state, sessionEditCount]);
|
|
4227
|
-
const actionsContextValue =
|
|
4611
|
+
const actionsContextValue = React8.useMemo(() => ({
|
|
4228
4612
|
selectElement,
|
|
4229
4613
|
selectParent,
|
|
4230
4614
|
selectChild,
|
|
@@ -4263,7 +4647,11 @@ function DirectEditProvider({ children }) {
|
|
|
4263
4647
|
clearSessionEdits,
|
|
4264
4648
|
removeSessionEdit,
|
|
4265
4649
|
startTextEditing,
|
|
4266
|
-
commitTextEditing
|
|
4650
|
+
commitTextEditing,
|
|
4651
|
+
toggleCanvas,
|
|
4652
|
+
setCanvasZoom,
|
|
4653
|
+
fitCanvasToViewport,
|
|
4654
|
+
zoomCanvasTo100
|
|
4267
4655
|
}), [
|
|
4268
4656
|
selectElement,
|
|
4269
4657
|
selectParent,
|
|
@@ -4303,7 +4691,11 @@ function DirectEditProvider({ children }) {
|
|
|
4303
4691
|
clearSessionEdits,
|
|
4304
4692
|
removeSessionEdit,
|
|
4305
4693
|
startTextEditing,
|
|
4306
|
-
commitTextEditing
|
|
4694
|
+
commitTextEditing,
|
|
4695
|
+
toggleCanvas,
|
|
4696
|
+
setCanvasZoom,
|
|
4697
|
+
fitCanvasToViewport,
|
|
4698
|
+
zoomCanvasTo100
|
|
4307
4699
|
]);
|
|
4308
4700
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PortalContainerProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DirectEditStateContext.Provider, { value: stateContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(DirectEditActionsContext.Provider, { value: actionsContextValue, children: [
|
|
4309
4701
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThemeApplier, {}),
|
|
@@ -4313,7 +4705,7 @@ function DirectEditProvider({ children }) {
|
|
|
4313
4705
|
function ThemeApplier() {
|
|
4314
4706
|
const { theme } = useDirectEditState();
|
|
4315
4707
|
const container = usePortalContainer();
|
|
4316
|
-
|
|
4708
|
+
useIsomorphicLayoutEffect(() => {
|
|
4317
4709
|
if (!container) return;
|
|
4318
4710
|
const host = container.getRootNode().host;
|
|
4319
4711
|
if (theme === "system") {
|
|
@@ -4326,11 +4718,11 @@ function ThemeApplier() {
|
|
|
4326
4718
|
}
|
|
4327
4719
|
|
|
4328
4720
|
// src/panel.tsx
|
|
4329
|
-
var
|
|
4721
|
+
var React29 = __toESM(require("react"));
|
|
4330
4722
|
var import_react_dom = require("react-dom");
|
|
4331
4723
|
|
|
4332
4724
|
// src/ui/tooltip.tsx
|
|
4333
|
-
var
|
|
4725
|
+
var React9 = __toESM(require("react"));
|
|
4334
4726
|
var import_tooltip = require("@base-ui/react/tooltip");
|
|
4335
4727
|
|
|
4336
4728
|
// src/cn.ts
|
|
@@ -4351,14 +4743,14 @@ var TooltipProvider = ({
|
|
|
4351
4743
|
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip.Tooltip.Provider, { delay: delay ?? delayDuration, closeDelay, ...props, children });
|
|
4352
4744
|
var Tooltip = import_tooltip.Tooltip.Root;
|
|
4353
4745
|
var TooltipTrigger = import_tooltip.Tooltip.Trigger;
|
|
4354
|
-
var TooltipContent =
|
|
4746
|
+
var TooltipContent = React9.forwardRef(({ className, side, align, sideOffset = 8, ...props }, ref) => {
|
|
4355
4747
|
const container = usePortalContainer();
|
|
4356
4748
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip.Tooltip.Portal, { container, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip.Tooltip.Positioner, { side, align, sideOffset, className: "fixed z-[99999]", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4357
4749
|
import_tooltip.Tooltip.Popup,
|
|
4358
4750
|
{
|
|
4359
4751
|
ref,
|
|
4360
4752
|
className: cn(
|
|
4361
|
-
"rounded-md bg-[canvas] px-2 py-1 text-xs origin-(--transform-origin) shadow-xs outline-1 outline-
|
|
4753
|
+
"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",
|
|
4362
4754
|
className
|
|
4363
4755
|
),
|
|
4364
4756
|
...props
|
|
@@ -4369,23 +4761,23 @@ TooltipContent.displayName = "TooltipContent";
|
|
|
4369
4761
|
var createTooltipHandle = import_tooltip.Tooltip.createHandle;
|
|
4370
4762
|
|
|
4371
4763
|
// src/use-measurement.ts
|
|
4372
|
-
var
|
|
4764
|
+
var React10 = __toESM(require("react"));
|
|
4373
4765
|
var INITIAL_STATE = {
|
|
4374
4766
|
hoveredElement: null,
|
|
4375
4767
|
measurements: []
|
|
4376
4768
|
};
|
|
4377
4769
|
function useMeasurement(selectedElement) {
|
|
4378
|
-
const [altHeld, setAltHeld] =
|
|
4379
|
-
const [state, setState] =
|
|
4380
|
-
const [mousePosition, setMousePosition] =
|
|
4381
|
-
const rafRef =
|
|
4382
|
-
const mousePositionRef =
|
|
4383
|
-
const getElementBelow =
|
|
4770
|
+
const [altHeld, setAltHeld] = React10.useState(false);
|
|
4771
|
+
const [state, setState] = React10.useState(INITIAL_STATE);
|
|
4772
|
+
const [mousePosition, setMousePosition] = React10.useState(null);
|
|
4773
|
+
const rafRef = React10.useRef(null);
|
|
4774
|
+
const mousePositionRef = React10.useRef(null);
|
|
4775
|
+
const getElementBelow = React10.useCallback((x, y) => {
|
|
4384
4776
|
const element = elementFromPointWithoutOverlays(x, y);
|
|
4385
4777
|
if (element?.closest("[data-direct-edit-host]")) return null;
|
|
4386
4778
|
return element;
|
|
4387
4779
|
}, []);
|
|
4388
|
-
|
|
4780
|
+
React10.useEffect(() => {
|
|
4389
4781
|
function handleKeyDown(e) {
|
|
4390
4782
|
if (e.key === "Alt") {
|
|
4391
4783
|
e.preventDefault();
|
|
@@ -4416,7 +4808,7 @@ function useMeasurement(selectedElement) {
|
|
|
4416
4808
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
4417
4809
|
};
|
|
4418
4810
|
}, []);
|
|
4419
|
-
|
|
4811
|
+
React10.useEffect(() => {
|
|
4420
4812
|
if (!altHeld || !selectedElement) {
|
|
4421
4813
|
setState(INITIAL_STATE);
|
|
4422
4814
|
return;
|
|
@@ -4475,7 +4867,7 @@ function useMeasurement(selectedElement) {
|
|
|
4475
4867
|
}
|
|
4476
4868
|
|
|
4477
4869
|
// src/measurement-overlay.tsx
|
|
4478
|
-
var
|
|
4870
|
+
var React11 = __toESM(require("react"));
|
|
4479
4871
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
4480
4872
|
var TOMATO = "#E54D2E";
|
|
4481
4873
|
var BLUE = "#0D99FF";
|
|
@@ -4552,16 +4944,18 @@ function MeasurementOverlay({
|
|
|
4552
4944
|
hoveredElement,
|
|
4553
4945
|
measurements
|
|
4554
4946
|
}) {
|
|
4555
|
-
const [, forceUpdate] =
|
|
4556
|
-
|
|
4947
|
+
const [, forceUpdate] = React11.useReducer((x) => x + 1, 0);
|
|
4948
|
+
React11.useEffect(() => {
|
|
4557
4949
|
function handleUpdate() {
|
|
4558
4950
|
requestAnimationFrame(forceUpdate);
|
|
4559
4951
|
}
|
|
4560
4952
|
window.addEventListener("scroll", handleUpdate, true);
|
|
4561
4953
|
window.addEventListener("resize", handleUpdate);
|
|
4954
|
+
window.addEventListener("direct-edit-canvas-change", handleUpdate);
|
|
4562
4955
|
return () => {
|
|
4563
4956
|
window.removeEventListener("scroll", handleUpdate, true);
|
|
4564
4957
|
window.removeEventListener("resize", handleUpdate);
|
|
4958
|
+
window.removeEventListener("direct-edit-canvas-change", handleUpdate);
|
|
4565
4959
|
};
|
|
4566
4960
|
}, [selectedElement]);
|
|
4567
4961
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -4586,7 +4980,7 @@ function MeasurementOverlay({
|
|
|
4586
4980
|
}
|
|
4587
4981
|
|
|
4588
4982
|
// src/use-move.ts
|
|
4589
|
-
var
|
|
4983
|
+
var React12 = __toESM(require("react"));
|
|
4590
4984
|
var INITIAL_DRAG_STATE = {
|
|
4591
4985
|
isDragging: false,
|
|
4592
4986
|
draggedElement: null,
|
|
@@ -4597,19 +4991,19 @@ var INITIAL_DRAG_STATE = {
|
|
|
4597
4991
|
dragOffset: { x: 0, y: 0 }
|
|
4598
4992
|
};
|
|
4599
4993
|
function useMove({ onMoveComplete }) {
|
|
4600
|
-
const [dragState, setDragState] =
|
|
4601
|
-
const [dropTarget, setDropTarget] =
|
|
4602
|
-
const [dropIndicator, setDropIndicator] =
|
|
4603
|
-
const dragStateRef =
|
|
4604
|
-
const dropTargetRef =
|
|
4605
|
-
const onMoveCompleteRef =
|
|
4606
|
-
const dragOptionsRef =
|
|
4607
|
-
|
|
4994
|
+
const [dragState, setDragState] = React12.useState(INITIAL_DRAG_STATE);
|
|
4995
|
+
const [dropTarget, setDropTarget] = React12.useState(null);
|
|
4996
|
+
const [dropIndicator, setDropIndicator] = React12.useState(null);
|
|
4997
|
+
const dragStateRef = React12.useRef(dragState);
|
|
4998
|
+
const dropTargetRef = React12.useRef(dropTarget);
|
|
4999
|
+
const onMoveCompleteRef = React12.useRef(onMoveComplete);
|
|
5000
|
+
const dragOptionsRef = React12.useRef({});
|
|
5001
|
+
React12.useEffect(() => {
|
|
4608
5002
|
dragStateRef.current = dragState;
|
|
4609
5003
|
dropTargetRef.current = dropTarget;
|
|
4610
5004
|
onMoveCompleteRef.current = onMoveComplete;
|
|
4611
5005
|
});
|
|
4612
|
-
const cancelDrag =
|
|
5006
|
+
const cancelDrag = React12.useCallback(() => {
|
|
4613
5007
|
const current = dragStateRef.current;
|
|
4614
5008
|
if (current.draggedElement) {
|
|
4615
5009
|
current.draggedElement.style.opacity = "";
|
|
@@ -4619,7 +5013,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4619
5013
|
setDropTarget(null);
|
|
4620
5014
|
setDropIndicator(null);
|
|
4621
5015
|
}, []);
|
|
4622
|
-
const completeDrag =
|
|
5016
|
+
const completeDrag = React12.useCallback(() => {
|
|
4623
5017
|
const current = dragStateRef.current;
|
|
4624
5018
|
const target = dropTargetRef.current;
|
|
4625
5019
|
const { draggedElement, originalParent, originalPreviousSibling, originalNextSibling } = current;
|
|
@@ -4653,7 +5047,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4653
5047
|
onMoveCompleteRef.current(draggedElement, moveInfo);
|
|
4654
5048
|
}
|
|
4655
5049
|
}, [cancelDrag]);
|
|
4656
|
-
const startDrag =
|
|
5050
|
+
const startDrag = React12.useCallback(
|
|
4657
5051
|
(e, element, options) => {
|
|
4658
5052
|
const rect = element.getBoundingClientRect();
|
|
4659
5053
|
const parent = element.parentElement;
|
|
@@ -4673,7 +5067,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4673
5067
|
},
|
|
4674
5068
|
[]
|
|
4675
5069
|
);
|
|
4676
|
-
|
|
5070
|
+
React12.useEffect(() => {
|
|
4677
5071
|
if (!dragState.isDragging) return;
|
|
4678
5072
|
function handlePointerMove(e) {
|
|
4679
5073
|
const current = dragStateRef.current;
|
|
@@ -4741,7 +5135,46 @@ function useMove({ onMoveComplete }) {
|
|
|
4741
5135
|
}
|
|
4742
5136
|
|
|
4743
5137
|
// src/use-guidelines.ts
|
|
4744
|
-
var
|
|
5138
|
+
var React13 = __toESM(require("react"));
|
|
5139
|
+
|
|
5140
|
+
// src/utils/snap-targets.ts
|
|
5141
|
+
var SNAP_THRESHOLD_PX = 6;
|
|
5142
|
+
function collectSnapTargets(orientation) {
|
|
5143
|
+
const edges = [];
|
|
5144
|
+
const elements = document.body.querySelectorAll("*");
|
|
5145
|
+
const viewportW = window.innerWidth;
|
|
5146
|
+
const viewportH = window.innerHeight;
|
|
5147
|
+
for (let i = 0; i < elements.length; i++) {
|
|
5148
|
+
const el = elements[i];
|
|
5149
|
+
if (el === document.body || el === document.documentElement) continue;
|
|
5150
|
+
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) continue;
|
|
5151
|
+
if (el.offsetParent === null && el !== document.body) continue;
|
|
5152
|
+
const rect = el.getBoundingClientRect();
|
|
5153
|
+
if (rect.width < 4 || rect.height < 4) continue;
|
|
5154
|
+
if (rect.right < -200 || rect.bottom < -200 || rect.left > viewportW + 200 || rect.top > viewportH + 200) continue;
|
|
5155
|
+
if (orientation === "horizontal") {
|
|
5156
|
+
edges.push(rect.top, rect.bottom);
|
|
5157
|
+
} else {
|
|
5158
|
+
edges.push(rect.left, rect.right);
|
|
5159
|
+
}
|
|
5160
|
+
if (edges.length >= 2e3) break;
|
|
5161
|
+
}
|
|
5162
|
+
return edges;
|
|
5163
|
+
}
|
|
5164
|
+
function findSnap(viewportPos, snapEdges, threshold) {
|
|
5165
|
+
let best = null;
|
|
5166
|
+
let bestDist = threshold + 1;
|
|
5167
|
+
for (let i = 0; i < snapEdges.length; i++) {
|
|
5168
|
+
const dist = Math.abs(snapEdges[i] - viewportPos);
|
|
5169
|
+
if (dist < bestDist) {
|
|
5170
|
+
bestDist = dist;
|
|
5171
|
+
best = snapEdges[i];
|
|
5172
|
+
}
|
|
5173
|
+
}
|
|
5174
|
+
return bestDist <= threshold ? best : null;
|
|
5175
|
+
}
|
|
5176
|
+
|
|
5177
|
+
// src/use-guidelines.ts
|
|
4745
5178
|
var STORAGE_KEY = "direct-edit-guidelines";
|
|
4746
5179
|
function isGuidelineOrientation(value) {
|
|
4747
5180
|
return value === "horizontal" || value === "vertical";
|
|
@@ -4778,6 +5211,7 @@ function generateId() {
|
|
|
4778
5211
|
return `gl-${Date.now()}-${idCounter++}`;
|
|
4779
5212
|
}
|
|
4780
5213
|
var RULER_SIZE = 20;
|
|
5214
|
+
var SNAP_VELOCITY_THRESHOLD = 3;
|
|
4781
5215
|
function viewportToCssCoord(hostElement, value, axis) {
|
|
4782
5216
|
if (!hostElement) return value;
|
|
4783
5217
|
const rect = hostElement.getBoundingClientRect();
|
|
@@ -4787,68 +5221,108 @@ function viewportToCssCoord(hostElement, value, axis) {
|
|
|
4787
5221
|
if (size === 0) return value;
|
|
4788
5222
|
return (value - origin) * (cssSize / size);
|
|
4789
5223
|
}
|
|
4790
|
-
function useGuidelines(enabled, hostElement) {
|
|
4791
|
-
const [guidelines, setGuidelines] =
|
|
4792
|
-
const [hydrated, setHydrated] =
|
|
4793
|
-
const [activeGuidelineId, setActiveGuidelineId] =
|
|
4794
|
-
const [dragPosition, setDragPosition] =
|
|
4795
|
-
const [isCreating, setIsCreating] =
|
|
4796
|
-
const [scrollOffset, setScrollOffset] =
|
|
4797
|
-
const hostRef =
|
|
5224
|
+
function useGuidelines(enabled, hostElement, canvas) {
|
|
5225
|
+
const [guidelines, setGuidelines] = React13.useState([]);
|
|
5226
|
+
const [hydrated, setHydrated] = React13.useState(false);
|
|
5227
|
+
const [activeGuidelineId, setActiveGuidelineId] = React13.useState(null);
|
|
5228
|
+
const [dragPosition, setDragPosition] = React13.useState(null);
|
|
5229
|
+
const [isCreating, setIsCreating] = React13.useState(false);
|
|
5230
|
+
const [scrollOffset, setScrollOffset] = React13.useState({ x: 0, y: 0 });
|
|
5231
|
+
const hostRef = React13.useRef(hostElement ?? null);
|
|
4798
5232
|
hostRef.current = hostElement ?? null;
|
|
4799
|
-
const
|
|
4800
|
-
|
|
5233
|
+
const canvasRef = React13.useRef(canvas);
|
|
5234
|
+
canvasRef.current = canvas;
|
|
5235
|
+
const [dragging, setDragging] = React13.useState(false);
|
|
5236
|
+
const guidelinesRef = React13.useRef(guidelines);
|
|
4801
5237
|
guidelinesRef.current = guidelines;
|
|
4802
|
-
const dragInfoRef =
|
|
4803
|
-
|
|
5238
|
+
const dragInfoRef = React13.useRef(null);
|
|
5239
|
+
const snapTargetsRef = React13.useRef([]);
|
|
5240
|
+
const isSnappedRef = React13.useRef(false);
|
|
5241
|
+
const [isSnapped, setIsSnapped] = React13.useState(false);
|
|
5242
|
+
React13.useEffect(() => {
|
|
4804
5243
|
setGuidelines(loadGuidelines());
|
|
4805
5244
|
setHydrated(true);
|
|
4806
5245
|
}, []);
|
|
4807
|
-
|
|
5246
|
+
React13.useEffect(() => {
|
|
4808
5247
|
if (!hydrated) return;
|
|
4809
5248
|
saveGuidelines(guidelines);
|
|
4810
5249
|
}, [guidelines, hydrated]);
|
|
4811
|
-
|
|
5250
|
+
React13.useEffect(() => {
|
|
4812
5251
|
if (!enabled) return;
|
|
4813
5252
|
function update() {
|
|
4814
|
-
setScrollOffset(
|
|
5253
|
+
setScrollOffset((prev) => {
|
|
5254
|
+
const x = window.scrollX;
|
|
5255
|
+
const y = window.scrollY;
|
|
5256
|
+
return prev.x === x && prev.y === y ? prev : { x, y };
|
|
5257
|
+
});
|
|
4815
5258
|
}
|
|
4816
5259
|
update();
|
|
4817
5260
|
window.addEventListener("scroll", update, true);
|
|
4818
5261
|
window.addEventListener("resize", update);
|
|
5262
|
+
window.addEventListener("direct-edit-canvas-change", update);
|
|
4819
5263
|
return () => {
|
|
4820
5264
|
window.removeEventListener("scroll", update, true);
|
|
4821
5265
|
window.removeEventListener("resize", update);
|
|
5266
|
+
window.removeEventListener("direct-edit-canvas-change", update);
|
|
4822
5267
|
};
|
|
4823
5268
|
}, [enabled]);
|
|
4824
|
-
const endDrag =
|
|
5269
|
+
const endDrag = React13.useCallback(() => {
|
|
4825
5270
|
const wasCreating = dragInfoRef.current?.isCreating ?? false;
|
|
4826
5271
|
dragInfoRef.current = null;
|
|
5272
|
+
snapTargetsRef.current = [];
|
|
5273
|
+
isSnappedRef.current = false;
|
|
5274
|
+
setIsSnapped(false);
|
|
4827
5275
|
setDragging(false);
|
|
4828
5276
|
setActiveGuidelineId(null);
|
|
4829
5277
|
setDragPosition(null);
|
|
4830
5278
|
if (wasCreating) setIsCreating(false);
|
|
4831
5279
|
}, []);
|
|
4832
|
-
|
|
5280
|
+
React13.useEffect(() => {
|
|
4833
5281
|
if (!dragging) return;
|
|
4834
5282
|
const info = dragInfoRef.current;
|
|
4835
5283
|
if (!info) return;
|
|
4836
5284
|
const { guidelineId, orientation } = info;
|
|
4837
5285
|
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
return viewportToCssCoord(hostRef.current, raw, axis);
|
|
4841
|
-
}
|
|
5286
|
+
let lastPos = NaN;
|
|
5287
|
+
let lastTime = 0;
|
|
4842
5288
|
function onPointerMove(e) {
|
|
4843
|
-
const
|
|
5289
|
+
const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
|
|
5290
|
+
const now = performance.now();
|
|
5291
|
+
const dt = now - lastTime;
|
|
5292
|
+
const velocity = dt > 0 && !Number.isNaN(lastPos) ? Math.abs(rawViewportPos - lastPos) / dt : 0;
|
|
5293
|
+
lastPos = rawViewportPos;
|
|
5294
|
+
lastTime = now;
|
|
5295
|
+
let effectiveViewportPos = rawViewportPos;
|
|
5296
|
+
let snapped = false;
|
|
5297
|
+
if (velocity < SNAP_VELOCITY_THRESHOLD) {
|
|
5298
|
+
const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
|
|
5299
|
+
if (snapResult !== null) {
|
|
5300
|
+
effectiveViewportPos = snapResult;
|
|
5301
|
+
snapped = true;
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
isSnappedRef.current = snapped;
|
|
5305
|
+
setIsSnapped(snapped);
|
|
5306
|
+
const pos = viewportToCssCoord(hostRef.current, effectiveViewportPos, axis);
|
|
4844
5307
|
setDragPosition(pos);
|
|
4845
|
-
const
|
|
5308
|
+
const c = canvasRef.current;
|
|
5309
|
+
let storedPosition;
|
|
5310
|
+
if (c?.active) {
|
|
5311
|
+
const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5312
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5313
|
+
storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
|
|
5314
|
+
} else {
|
|
5315
|
+
const currentScroll = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5316
|
+
storedPosition = pos + currentScroll;
|
|
5317
|
+
}
|
|
4846
5318
|
setGuidelines(
|
|
4847
|
-
(prev) => prev.map((g) => g.id === guidelineId ? { ...g, position:
|
|
5319
|
+
(prev) => prev.map((g) => g.id === guidelineId ? { ...g, position: storedPosition } : g)
|
|
4848
5320
|
);
|
|
4849
5321
|
}
|
|
4850
5322
|
function onPointerUp(e) {
|
|
4851
|
-
const
|
|
5323
|
+
const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
|
|
5324
|
+
const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
|
|
5325
|
+
const pos = viewportToCssCoord(hostRef.current, snapResult ?? rawViewportPos, axis);
|
|
4852
5326
|
if (pos <= RULER_SIZE) {
|
|
4853
5327
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
4854
5328
|
}
|
|
@@ -4861,22 +5335,32 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4861
5335
|
window.removeEventListener("pointerup", onPointerUp);
|
|
4862
5336
|
};
|
|
4863
5337
|
}, [dragging, endDrag]);
|
|
4864
|
-
|
|
5338
|
+
React13.useEffect(() => {
|
|
4865
5339
|
if (!enabled && dragging) {
|
|
4866
5340
|
endDrag();
|
|
4867
5341
|
}
|
|
4868
5342
|
}, [enabled, dragging, endDrag]);
|
|
4869
|
-
const activeGuideline =
|
|
5343
|
+
const activeGuideline = React13.useMemo(
|
|
4870
5344
|
() => guidelines.find((g) => g.id === activeGuidelineId) ?? null,
|
|
4871
5345
|
[guidelines, activeGuidelineId]
|
|
4872
5346
|
);
|
|
4873
|
-
const startCreate =
|
|
5347
|
+
const startCreate = React13.useCallback(
|
|
4874
5348
|
(orientation, viewportPosition) => {
|
|
4875
5349
|
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4876
5350
|
const pos = viewportToCssCoord(hostRef.current, viewportPosition, axis);
|
|
4877
|
-
const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
4878
5351
|
const id = generateId();
|
|
4879
|
-
const
|
|
5352
|
+
const c = canvasRef.current;
|
|
5353
|
+
let storedPosition;
|
|
5354
|
+
if (c?.active) {
|
|
5355
|
+
const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5356
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5357
|
+
storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
|
|
5358
|
+
} else {
|
|
5359
|
+
const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5360
|
+
storedPosition = pos + scrollPos;
|
|
5361
|
+
}
|
|
5362
|
+
const newGuideline = { id, orientation, position: storedPosition };
|
|
5363
|
+
snapTargetsRef.current = collectSnapTargets(orientation);
|
|
4880
5364
|
setGuidelines((prev) => [...prev, newGuideline]);
|
|
4881
5365
|
setActiveGuidelineId(id);
|
|
4882
5366
|
setDragPosition(pos);
|
|
@@ -4886,19 +5370,29 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4886
5370
|
},
|
|
4887
5371
|
[]
|
|
4888
5372
|
);
|
|
4889
|
-
const startDrag =
|
|
5373
|
+
const startDrag = React13.useCallback((guidelineId) => {
|
|
4890
5374
|
const guideline = guidelinesRef.current.find((g) => g.id === guidelineId);
|
|
4891
5375
|
if (!guideline) return;
|
|
4892
|
-
|
|
5376
|
+
snapTargetsRef.current = collectSnapTargets(guideline.orientation);
|
|
5377
|
+
const c = canvasRef.current;
|
|
5378
|
+
let viewportPos;
|
|
5379
|
+
if (c?.active) {
|
|
5380
|
+
const pan = guideline.orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5381
|
+
const bo = guideline.orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5382
|
+
viewportPos = bo + (guideline.position - bo + pan) * (c.zoom || 1);
|
|
5383
|
+
} else {
|
|
5384
|
+
const scrollPos = guideline.orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5385
|
+
viewportPos = guideline.position - scrollPos;
|
|
5386
|
+
}
|
|
4893
5387
|
setActiveGuidelineId(guidelineId);
|
|
4894
|
-
setDragPosition(
|
|
5388
|
+
setDragPosition(viewportPos);
|
|
4895
5389
|
dragInfoRef.current = { guidelineId, orientation: guideline.orientation, isCreating: false };
|
|
4896
5390
|
setDragging(true);
|
|
4897
5391
|
}, []);
|
|
4898
|
-
const deleteGuideline =
|
|
5392
|
+
const deleteGuideline = React13.useCallback((guidelineId) => {
|
|
4899
5393
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
4900
5394
|
}, []);
|
|
4901
|
-
const clearAll =
|
|
5395
|
+
const clearAll = React13.useCallback(() => {
|
|
4902
5396
|
setGuidelines([]);
|
|
4903
5397
|
}, []);
|
|
4904
5398
|
return {
|
|
@@ -4906,6 +5400,7 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4906
5400
|
activeGuideline,
|
|
4907
5401
|
dragPosition,
|
|
4908
5402
|
isCreating,
|
|
5403
|
+
isSnapped,
|
|
4909
5404
|
scrollOffset,
|
|
4910
5405
|
startCreate,
|
|
4911
5406
|
startDrag,
|
|
@@ -4960,10 +5455,8 @@ function InteractionOverlay({
|
|
|
4960
5455
|
if (activeTool === "comment") {
|
|
4961
5456
|
if (hasPendingCommentDraft()) return;
|
|
4962
5457
|
const elementUnder2 = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
onAddComment(resolved, { x: e.clientX, y: e.clientY });
|
|
4966
|
-
}
|
|
5458
|
+
const target = elementUnder2 && elementUnder2 !== document.body && elementUnder2 !== document.documentElement ? resolveElementTarget(elementUnder2, selectedElement) : document.body;
|
|
5459
|
+
onAddComment(target, { x: e.clientX, y: e.clientY });
|
|
4967
5460
|
return;
|
|
4968
5461
|
}
|
|
4969
5462
|
if (activeCommentId) {
|
|
@@ -4981,39 +5474,41 @@ function InteractionOverlay({
|
|
|
4981
5474
|
hoverHighlight && (() => {
|
|
4982
5475
|
const cr = hoverHighlight.flexContainer.getBoundingClientRect();
|
|
4983
5476
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4984
|
-
"
|
|
5477
|
+
"div",
|
|
4985
5478
|
{
|
|
4986
5479
|
"data-direct-edit": "hover-highlight",
|
|
4987
5480
|
className: "pointer-events-none fixed inset-0 z-[99991]",
|
|
4988
|
-
width: "100%",
|
|
4989
|
-
height: "100%",
|
|
4990
|
-
style: { width: "100vw", height: "100vh" },
|
|
4991
5481
|
children: [
|
|
4992
5482
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
4993
|
-
"
|
|
5483
|
+
"div",
|
|
4994
5484
|
{
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5485
|
+
style: {
|
|
5486
|
+
position: "absolute",
|
|
5487
|
+
left: cr.left,
|
|
5488
|
+
top: cr.top,
|
|
5489
|
+
width: cr.width,
|
|
5490
|
+
height: cr.height,
|
|
5491
|
+
border: "1px solid #3b82f6",
|
|
5492
|
+
borderRadius: "0px",
|
|
5493
|
+
boxSizing: "border-box"
|
|
5494
|
+
}
|
|
5002
5495
|
}
|
|
5003
5496
|
),
|
|
5004
5497
|
hoverHighlight.children.map((child) => {
|
|
5005
5498
|
const r = child.getBoundingClientRect();
|
|
5006
5499
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
5007
|
-
"
|
|
5500
|
+
"div",
|
|
5008
5501
|
{
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5502
|
+
style: {
|
|
5503
|
+
position: "absolute",
|
|
5504
|
+
left: r.left,
|
|
5505
|
+
top: r.top,
|
|
5506
|
+
width: r.width,
|
|
5507
|
+
height: r.height,
|
|
5508
|
+
border: "1px dashed #3b82f6",
|
|
5509
|
+
borderRadius: "0px",
|
|
5510
|
+
boxSizing: "border-box"
|
|
5511
|
+
}
|
|
5017
5512
|
},
|
|
5018
5513
|
`${r.left}-${r.top}-${r.width}-${r.height}`
|
|
5019
5514
|
);
|
|
@@ -5059,7 +5554,7 @@ function MoveOverlay({ dropIndicator }) {
|
|
|
5059
5554
|
}
|
|
5060
5555
|
|
|
5061
5556
|
// src/selection-overlay.tsx
|
|
5062
|
-
var
|
|
5557
|
+
var React14 = __toESM(require("react"));
|
|
5063
5558
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
5064
5559
|
var BLUE3 = "#0D99FF";
|
|
5065
5560
|
var MAGENTA = "#E11BB6";
|
|
@@ -5073,23 +5568,25 @@ function SelectionOverlay({
|
|
|
5073
5568
|
ghostPosition,
|
|
5074
5569
|
onMoveStart,
|
|
5075
5570
|
showMoveHandle = false,
|
|
5571
|
+
activeTool = "select",
|
|
5076
5572
|
isTextEditing,
|
|
5077
5573
|
onDoubleClick,
|
|
5078
5574
|
onHoverElement,
|
|
5079
5575
|
onClickThrough
|
|
5080
5576
|
}) {
|
|
5081
5577
|
const rectElement = isDragging && draggedElement ? draggedElement : selectedElement;
|
|
5082
|
-
const [rect, setRect] =
|
|
5083
|
-
const [moveHandleRects, setMoveHandleRects] =
|
|
5084
|
-
const cleanupRef =
|
|
5085
|
-
const clickThroughTimerRef =
|
|
5086
|
-
|
|
5578
|
+
const [rect, setRect] = React14.useState(() => rectElement.getBoundingClientRect());
|
|
5579
|
+
const [moveHandleRects, setMoveHandleRects] = React14.useState([]);
|
|
5580
|
+
const cleanupRef = React14.useRef(null);
|
|
5581
|
+
const clickThroughTimerRef = React14.useRef(null);
|
|
5582
|
+
React14.useEffect(() => {
|
|
5087
5583
|
function updateRect() {
|
|
5088
5584
|
setRect(rectElement.getBoundingClientRect());
|
|
5089
5585
|
}
|
|
5090
5586
|
updateRect();
|
|
5091
5587
|
window.addEventListener("scroll", updateRect, true);
|
|
5092
5588
|
window.addEventListener("resize", updateRect);
|
|
5589
|
+
window.addEventListener("direct-edit-canvas-change", updateRect);
|
|
5093
5590
|
const observer = new MutationObserver(updateRect);
|
|
5094
5591
|
observer.observe(rectElement, {
|
|
5095
5592
|
attributes: true,
|
|
@@ -5099,10 +5596,11 @@ function SelectionOverlay({
|
|
|
5099
5596
|
return () => {
|
|
5100
5597
|
window.removeEventListener("scroll", updateRect, true);
|
|
5101
5598
|
window.removeEventListener("resize", updateRect);
|
|
5599
|
+
window.removeEventListener("direct-edit-canvas-change", updateRect);
|
|
5102
5600
|
observer.disconnect();
|
|
5103
5601
|
};
|
|
5104
5602
|
}, [rectElement]);
|
|
5105
|
-
|
|
5603
|
+
React14.useEffect(() => {
|
|
5106
5604
|
return () => {
|
|
5107
5605
|
cleanupRef.current?.();
|
|
5108
5606
|
if (clickThroughTimerRef.current) clearTimeout(clickThroughTimerRef.current);
|
|
@@ -5163,7 +5661,7 @@ function SelectionOverlay({
|
|
|
5163
5661
|
const handleMouseLeave = () => {
|
|
5164
5662
|
onHoverElement?.(null);
|
|
5165
5663
|
};
|
|
5166
|
-
const getMoveHandleTargets =
|
|
5664
|
+
const getMoveHandleTargets = React14.useCallback(() => {
|
|
5167
5665
|
if (!showMoveHandle) return [];
|
|
5168
5666
|
const selectedDisplay = window.getComputedStyle(selectedElement).display;
|
|
5169
5667
|
const selectedIsFlexContainer = selectedDisplay === "flex" || selectedDisplay === "inline-flex";
|
|
@@ -5188,7 +5686,7 @@ function SelectionOverlay({
|
|
|
5188
5686
|
}
|
|
5189
5687
|
return [target];
|
|
5190
5688
|
}, [selectedElement, showMoveHandle]);
|
|
5191
|
-
|
|
5689
|
+
React14.useEffect(() => {
|
|
5192
5690
|
if (!showMoveHandle || isDragging || isTextEditing) {
|
|
5193
5691
|
setMoveHandleRects([]);
|
|
5194
5692
|
return;
|
|
@@ -5228,30 +5726,22 @@ function SelectionOverlay({
|
|
|
5228
5726
|
const displayX = isDragging && ghostPosition ? ghostPosition.x : rect.left;
|
|
5229
5727
|
const displayY = isDragging && ghostPosition ? ghostPosition.y : rect.top;
|
|
5230
5728
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
5231
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5232
|
-
"
|
|
5729
|
+
!isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5730
|
+
"div",
|
|
5233
5731
|
{
|
|
5234
5732
|
"data-direct-edit": "selection-overlay",
|
|
5235
5733
|
style: {
|
|
5236
5734
|
position: "fixed",
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5735
|
+
left: displayX,
|
|
5736
|
+
top: displayY,
|
|
5737
|
+
width: rect.width,
|
|
5738
|
+
height: rect.height,
|
|
5240
5739
|
pointerEvents: "none",
|
|
5241
|
-
zIndex: 99996
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
"
|
|
5245
|
-
|
|
5246
|
-
x: displayX,
|
|
5247
|
-
y: displayY,
|
|
5248
|
-
width: rect.width,
|
|
5249
|
-
height: rect.height,
|
|
5250
|
-
fill: "transparent",
|
|
5251
|
-
stroke: BLUE3,
|
|
5252
|
-
strokeWidth: 1
|
|
5253
|
-
}
|
|
5254
|
-
)
|
|
5740
|
+
zIndex: 99996,
|
|
5741
|
+
border: `1px solid ${BLUE3}`,
|
|
5742
|
+
borderRadius: "0px",
|
|
5743
|
+
boxSizing: "border-box"
|
|
5744
|
+
}
|
|
5255
5745
|
}
|
|
5256
5746
|
),
|
|
5257
5747
|
!isDragging && !isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -5266,7 +5756,7 @@ function SelectionOverlay({
|
|
|
5266
5756
|
height: rect.height,
|
|
5267
5757
|
zIndex: 99996,
|
|
5268
5758
|
cursor: "default",
|
|
5269
|
-
pointerEvents: "auto"
|
|
5759
|
+
pointerEvents: activeTool === "comment" ? "none" : "auto"
|
|
5270
5760
|
},
|
|
5271
5761
|
onPointerDown: handlePointerDown,
|
|
5272
5762
|
onDoubleClick: handleDoubleClick,
|
|
@@ -5308,7 +5798,7 @@ function SelectionOverlay({
|
|
|
5308
5798
|
}
|
|
5309
5799
|
|
|
5310
5800
|
// src/comment-overlay.tsx
|
|
5311
|
-
var
|
|
5801
|
+
var React15 = __toESM(require("react"));
|
|
5312
5802
|
var import_lucide_react = require("lucide-react");
|
|
5313
5803
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
5314
5804
|
function formatRelativeTime(timestamp) {
|
|
@@ -5348,7 +5838,8 @@ function CommentOverlay({
|
|
|
5348
5838
|
onDelete,
|
|
5349
5839
|
onExport,
|
|
5350
5840
|
onSendToAgent,
|
|
5351
|
-
attentionRequest = null
|
|
5841
|
+
attentionRequest = null,
|
|
5842
|
+
draftRef
|
|
5352
5843
|
}) {
|
|
5353
5844
|
if (comments.length === 0) return null;
|
|
5354
5845
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: comments.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
@@ -5364,7 +5855,8 @@ function CommentOverlay({
|
|
|
5364
5855
|
onDelete: () => onDelete(comment.id),
|
|
5365
5856
|
onExport: onExport ? () => onExport(comment.id) : void 0,
|
|
5366
5857
|
onSendToAgent: () => onSendToAgent(comment.id),
|
|
5367
|
-
attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0
|
|
5858
|
+
attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0,
|
|
5859
|
+
draftRef: activeCommentId === comment.id ? draftRef : void 0
|
|
5368
5860
|
},
|
|
5369
5861
|
comment.id
|
|
5370
5862
|
)) });
|
|
@@ -5380,31 +5872,34 @@ function CommentPin({
|
|
|
5380
5872
|
onDelete,
|
|
5381
5873
|
onExport,
|
|
5382
5874
|
onSendToAgent,
|
|
5383
|
-
attentionNonce
|
|
5875
|
+
attentionNonce,
|
|
5876
|
+
draftRef
|
|
5384
5877
|
}) {
|
|
5385
|
-
const [position, setPosition] =
|
|
5386
|
-
const [elementRect, setElementRect] =
|
|
5387
|
-
const [flipHorizontal, setFlipHorizontal] =
|
|
5388
|
-
const [flipVertical, setFlipVertical] =
|
|
5389
|
-
|
|
5878
|
+
const [position, setPosition] = React15.useState(comment.clickPosition);
|
|
5879
|
+
const [elementRect, setElementRect] = React15.useState(null);
|
|
5880
|
+
const [flipHorizontal, setFlipHorizontal] = React15.useState(false);
|
|
5881
|
+
const [flipVertical, setFlipVertical] = React15.useState(false);
|
|
5882
|
+
React15.useEffect(() => {
|
|
5390
5883
|
function updatePosition() {
|
|
5391
5884
|
if (!comment.element.isConnected) return;
|
|
5392
5885
|
const rect = comment.element.getBoundingClientRect();
|
|
5393
5886
|
setPosition({
|
|
5394
|
-
x: rect.left + comment.relativePosition.x,
|
|
5395
|
-
y: rect.top + comment.relativePosition.y
|
|
5887
|
+
x: rect.left + comment.relativePosition.x * rect.width,
|
|
5888
|
+
y: rect.top + comment.relativePosition.y * rect.height
|
|
5396
5889
|
});
|
|
5397
5890
|
setElementRect(rect);
|
|
5398
5891
|
}
|
|
5399
5892
|
updatePosition();
|
|
5400
5893
|
window.addEventListener("scroll", updatePosition, true);
|
|
5401
5894
|
window.addEventListener("resize", updatePosition);
|
|
5895
|
+
window.addEventListener("direct-edit-canvas-change", updatePosition);
|
|
5402
5896
|
return () => {
|
|
5403
5897
|
window.removeEventListener("scroll", updatePosition, true);
|
|
5404
5898
|
window.removeEventListener("resize", updatePosition);
|
|
5899
|
+
window.removeEventListener("direct-edit-canvas-change", updatePosition);
|
|
5405
5900
|
};
|
|
5406
5901
|
}, [comment.element, comment.relativePosition]);
|
|
5407
|
-
|
|
5902
|
+
React15.useEffect(() => {
|
|
5408
5903
|
if (isActive) {
|
|
5409
5904
|
const hasText = comment.text !== "";
|
|
5410
5905
|
const cardWidth = hasText ? 280 : 220;
|
|
@@ -5470,7 +5965,8 @@ function CommentPin({
|
|
|
5470
5965
|
onUpdateText(text);
|
|
5471
5966
|
},
|
|
5472
5967
|
onCancel: onClose,
|
|
5473
|
-
attentionNonce
|
|
5968
|
+
attentionNonce,
|
|
5969
|
+
draftRef
|
|
5474
5970
|
}
|
|
5475
5971
|
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5476
5972
|
CommentThread,
|
|
@@ -5497,16 +5993,17 @@ function NewCommentInput({
|
|
|
5497
5993
|
flipVertical,
|
|
5498
5994
|
onSubmit,
|
|
5499
5995
|
onCancel,
|
|
5500
|
-
attentionNonce
|
|
5996
|
+
attentionNonce,
|
|
5997
|
+
draftRef
|
|
5501
5998
|
}) {
|
|
5502
|
-
const [text, setText] =
|
|
5503
|
-
const [showError, setShowError] =
|
|
5504
|
-
const inputRef =
|
|
5505
|
-
const cardRef =
|
|
5506
|
-
|
|
5999
|
+
const [text, setText] = React15.useState("");
|
|
6000
|
+
const [showError, setShowError] = React15.useState(false);
|
|
6001
|
+
const inputRef = React15.useRef(null);
|
|
6002
|
+
const cardRef = React15.useRef(null);
|
|
6003
|
+
React15.useEffect(() => {
|
|
5507
6004
|
inputRef.current?.focus();
|
|
5508
6005
|
}, []);
|
|
5509
|
-
|
|
6006
|
+
React15.useEffect(() => {
|
|
5510
6007
|
if (attentionNonce <= 0) return;
|
|
5511
6008
|
setShowError(true);
|
|
5512
6009
|
cardRef.current?.animate?.(
|
|
@@ -5553,7 +6050,10 @@ function NewCommentInput({
|
|
|
5553
6050
|
),
|
|
5554
6051
|
placeholder: "Add a comment...",
|
|
5555
6052
|
value: text,
|
|
5556
|
-
onChange: (e) =>
|
|
6053
|
+
onChange: (e) => {
|
|
6054
|
+
setText(e.target.value);
|
|
6055
|
+
if (draftRef) draftRef.current = e.target.value;
|
|
6056
|
+
},
|
|
5557
6057
|
onKeyDown: (e) => {
|
|
5558
6058
|
e.stopPropagation();
|
|
5559
6059
|
if (e.key === "Enter" && text.trim()) {
|
|
@@ -5595,15 +6095,15 @@ function CommentThread({
|
|
|
5595
6095
|
onExport,
|
|
5596
6096
|
onSendToAgent
|
|
5597
6097
|
}) {
|
|
5598
|
-
const [replyText, setReplyText] =
|
|
5599
|
-
const [copied, setCopied] =
|
|
5600
|
-
const [sendStatus, setSendStatus] =
|
|
5601
|
-
const inputRef =
|
|
5602
|
-
const copyTimerRef =
|
|
5603
|
-
|
|
6098
|
+
const [replyText, setReplyText] = React15.useState("");
|
|
6099
|
+
const [copied, setCopied] = React15.useState(false);
|
|
6100
|
+
const [sendStatus, setSendStatus] = React15.useState("idle");
|
|
6101
|
+
const inputRef = React15.useRef(null);
|
|
6102
|
+
const copyTimerRef = React15.useRef(null);
|
|
6103
|
+
React15.useEffect(() => {
|
|
5604
6104
|
inputRef.current?.focus();
|
|
5605
6105
|
}, []);
|
|
5606
|
-
|
|
6106
|
+
React15.useEffect(() => {
|
|
5607
6107
|
return () => {
|
|
5608
6108
|
if (copyTimerRef.current) {
|
|
5609
6109
|
window.clearTimeout(copyTimerRef.current);
|
|
@@ -5791,12 +6291,12 @@ function CommentThread({
|
|
|
5791
6291
|
}
|
|
5792
6292
|
|
|
5793
6293
|
// src/panel/shared.tsx
|
|
5794
|
-
var
|
|
6294
|
+
var React17 = __toESM(require("react"));
|
|
5795
6295
|
|
|
5796
6296
|
// src/ui/input.tsx
|
|
5797
|
-
var
|
|
6297
|
+
var React16 = __toESM(require("react"));
|
|
5798
6298
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
5799
|
-
var Input =
|
|
6299
|
+
var Input = React16.forwardRef(
|
|
5800
6300
|
({ className, type, ...props }, ref) => {
|
|
5801
6301
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
5802
6302
|
"input",
|
|
@@ -5818,8 +6318,8 @@ Input.displayName = "Input";
|
|
|
5818
6318
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
5819
6319
|
var selectOnFocus = (e) => e.target.select();
|
|
5820
6320
|
function NumberInput({ value: propValue, onValueChange, ...props }) {
|
|
5821
|
-
const [localValue, setLocalValue] =
|
|
5822
|
-
|
|
6321
|
+
const [localValue, setLocalValue] = React17.useState(propValue === null ? "" : String(propValue));
|
|
6322
|
+
React17.useEffect(() => {
|
|
5823
6323
|
setLocalValue(propValue === null ? "" : String(propValue));
|
|
5824
6324
|
}, [propValue]);
|
|
5825
6325
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -5866,9 +6366,9 @@ var SECTION_LABELS = {
|
|
|
5866
6366
|
text: "Text"
|
|
5867
6367
|
};
|
|
5868
6368
|
function useSectionNav(sectionRefs) {
|
|
5869
|
-
const scrollRef =
|
|
5870
|
-
const [activeSection, setActiveSection] =
|
|
5871
|
-
|
|
6369
|
+
const scrollRef = React17.useRef(null);
|
|
6370
|
+
const [activeSection, setActiveSection] = React17.useState("layout");
|
|
6371
|
+
React17.useEffect(() => {
|
|
5872
6372
|
const scrollEl = scrollRef.current;
|
|
5873
6373
|
if (!scrollEl) return;
|
|
5874
6374
|
const handleScroll = () => {
|
|
@@ -5929,10 +6429,10 @@ function SectionNav({
|
|
|
5929
6429
|
}
|
|
5930
6430
|
|
|
5931
6431
|
// src/panel/border-radius-inputs.tsx
|
|
5932
|
-
var
|
|
6432
|
+
var React20 = __toESM(require("react"));
|
|
5933
6433
|
|
|
5934
6434
|
// src/ui/button.tsx
|
|
5935
|
-
var
|
|
6435
|
+
var React18 = __toESM(require("react"));
|
|
5936
6436
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
5937
6437
|
var buttonVariants = {
|
|
5938
6438
|
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",
|
|
@@ -5951,7 +6451,7 @@ var buttonVariants = {
|
|
|
5951
6451
|
icon: "h-10 w-10"
|
|
5952
6452
|
}
|
|
5953
6453
|
};
|
|
5954
|
-
var Button =
|
|
6454
|
+
var Button = React18.forwardRef(
|
|
5955
6455
|
({ className, variant = "default", size = "default", ...props }, ref) => {
|
|
5956
6456
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5957
6457
|
"button",
|
|
@@ -5971,10 +6471,10 @@ var Button = React17.forwardRef(
|
|
|
5971
6471
|
Button.displayName = "Button";
|
|
5972
6472
|
|
|
5973
6473
|
// src/ui/slider.tsx
|
|
5974
|
-
var
|
|
6474
|
+
var React19 = __toESM(require("react"));
|
|
5975
6475
|
var import_slider = require("@base-ui/react/slider");
|
|
5976
6476
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5977
|
-
var Slider =
|
|
6477
|
+
var Slider = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5978
6478
|
import_slider.Slider.Root,
|
|
5979
6479
|
{
|
|
5980
6480
|
ref,
|
|
@@ -6009,7 +6509,7 @@ function RadiusCornerIcon({ corner, className }) {
|
|
|
6009
6509
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: cn("size-3", className), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: paths[corner] }) });
|
|
6010
6510
|
}
|
|
6011
6511
|
function BorderRadiusInputs({ values, onChange }) {
|
|
6012
|
-
const [individual, setIndividual] =
|
|
6512
|
+
const [individual, setIndividual] = React20.useState(false);
|
|
6013
6513
|
const handleChange = (corners, numericValue) => {
|
|
6014
6514
|
const newValue = {
|
|
6015
6515
|
numericValue,
|
|
@@ -6142,7 +6642,7 @@ function BorderRadiusInputs({ values, onChange }) {
|
|
|
6142
6642
|
}
|
|
6143
6643
|
|
|
6144
6644
|
// src/panel/border-section.tsx
|
|
6145
|
-
var
|
|
6645
|
+
var React23 = __toESM(require("react"));
|
|
6146
6646
|
|
|
6147
6647
|
// src/ui/select.tsx
|
|
6148
6648
|
var import_select = require("@base-ui/react/select");
|
|
@@ -6207,21 +6707,21 @@ function SimpleSelect({
|
|
|
6207
6707
|
}
|
|
6208
6708
|
|
|
6209
6709
|
// src/ui/color-picker.tsx
|
|
6210
|
-
var
|
|
6710
|
+
var React21 = __toESM(require("react"));
|
|
6211
6711
|
var import_popover = require("@base-ui/react/popover");
|
|
6212
6712
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
6213
6713
|
function ColorPickerPortal(props) {
|
|
6214
6714
|
const container = usePortalContainer();
|
|
6215
6715
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_popover.Popover.Portal, { container, ...props });
|
|
6216
6716
|
}
|
|
6217
|
-
var ColorPickerGroupContext =
|
|
6717
|
+
var ColorPickerGroupContext = React21.createContext(null);
|
|
6218
6718
|
function ColorPickerGroup({ children }) {
|
|
6219
|
-
const [activePickerId, setActivePickerId] =
|
|
6719
|
+
const [activePickerId, setActivePickerId] = React21.useState(null);
|
|
6220
6720
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ColorPickerGroupContext.Provider, { value: { activePickerId, setActivePickerId }, children });
|
|
6221
6721
|
}
|
|
6222
6722
|
function useDrag(onMove) {
|
|
6223
|
-
const ref =
|
|
6224
|
-
const handlePointerEvent =
|
|
6723
|
+
const ref = React21.useRef(null);
|
|
6724
|
+
const handlePointerEvent = React21.useCallback(
|
|
6225
6725
|
(e) => {
|
|
6226
6726
|
const el = ref.current;
|
|
6227
6727
|
if (!el) return;
|
|
@@ -6232,7 +6732,7 @@ function useDrag(onMove) {
|
|
|
6232
6732
|
},
|
|
6233
6733
|
[onMove]
|
|
6234
6734
|
);
|
|
6235
|
-
const onPointerDown =
|
|
6735
|
+
const onPointerDown = React21.useCallback(
|
|
6236
6736
|
(e) => {
|
|
6237
6737
|
e.preventDefault();
|
|
6238
6738
|
ref.current?.setPointerCapture(e.pointerId);
|
|
@@ -6240,7 +6740,7 @@ function useDrag(onMove) {
|
|
|
6240
6740
|
},
|
|
6241
6741
|
[handlePointerEvent]
|
|
6242
6742
|
);
|
|
6243
|
-
const onPointerMove =
|
|
6743
|
+
const onPointerMove = React21.useCallback(
|
|
6244
6744
|
(e) => {
|
|
6245
6745
|
if (e.buttons === 0) return;
|
|
6246
6746
|
handlePointerEvent(e);
|
|
@@ -6310,8 +6810,8 @@ function NumericInput({
|
|
|
6310
6810
|
max,
|
|
6311
6811
|
onChange
|
|
6312
6812
|
}) {
|
|
6313
|
-
const [local, setLocal] =
|
|
6314
|
-
|
|
6813
|
+
const [local, setLocal] = React21.useState(Math.round(value).toString());
|
|
6814
|
+
React21.useEffect(() => {
|
|
6315
6815
|
setLocal(Math.round(value).toString());
|
|
6316
6816
|
}, [value]);
|
|
6317
6817
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
@@ -6333,13 +6833,13 @@ function NumericInput({
|
|
|
6333
6833
|
] });
|
|
6334
6834
|
}
|
|
6335
6835
|
function ColorPickerPopover({ id, value, onChange, children }) {
|
|
6336
|
-
const group =
|
|
6836
|
+
const group = React21.useContext(ColorPickerGroupContext);
|
|
6337
6837
|
const rgb = hexToRgb(value.hex);
|
|
6338
6838
|
const initialHsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
6339
|
-
const [hsv, setHsv] =
|
|
6340
|
-
const [alpha, setAlpha] =
|
|
6341
|
-
const lastSyncedHex =
|
|
6342
|
-
|
|
6839
|
+
const [hsv, setHsv] = React21.useState({ h: initialHsv.h, s: initialHsv.s, v: initialHsv.v });
|
|
6840
|
+
const [alpha, setAlpha] = React21.useState(value.alpha);
|
|
6841
|
+
const lastSyncedHex = React21.useRef(value.hex);
|
|
6842
|
+
React21.useEffect(() => {
|
|
6343
6843
|
if (value.hex !== lastSyncedHex.current) {
|
|
6344
6844
|
const newRgb = hexToRgb(value.hex);
|
|
6345
6845
|
const newHsv = rgbToHsv(newRgb.r, newRgb.g, newRgb.b);
|
|
@@ -6352,7 +6852,7 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6352
6852
|
}
|
|
6353
6853
|
setAlpha(value.alpha);
|
|
6354
6854
|
}, [value.hex, value.alpha]);
|
|
6355
|
-
const emitChange =
|
|
6855
|
+
const emitChange = React21.useCallback(
|
|
6356
6856
|
(h, s, v, a) => {
|
|
6357
6857
|
const newRgb = hsvToRgb(h, s, v);
|
|
6358
6858
|
const hex = rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
@@ -6433,11 +6933,11 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6433
6933
|
const handleOpenChange = isControlled ? (open) => {
|
|
6434
6934
|
group.setActivePickerId(open ? id : null);
|
|
6435
6935
|
} : void 0;
|
|
6436
|
-
const popupRef =
|
|
6437
|
-
const triggerRef =
|
|
6438
|
-
const onCloseRef =
|
|
6936
|
+
const popupRef = React21.useRef(null);
|
|
6937
|
+
const triggerRef = React21.useRef(null);
|
|
6938
|
+
const onCloseRef = React21.useRef();
|
|
6439
6939
|
onCloseRef.current = () => group?.setActivePickerId(null);
|
|
6440
|
-
|
|
6940
|
+
React21.useEffect(() => {
|
|
6441
6941
|
if (!isOpen) return;
|
|
6442
6942
|
function handlePointerDown(e) {
|
|
6443
6943
|
const path = e.composedPath();
|
|
@@ -6507,8 +7007,8 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6507
7007
|
] });
|
|
6508
7008
|
}
|
|
6509
7009
|
function HexInput({ value, onChange }) {
|
|
6510
|
-
const [local, setLocal] =
|
|
6511
|
-
|
|
7010
|
+
const [local, setLocal] = React21.useState(value);
|
|
7011
|
+
React21.useEffect(() => {
|
|
6512
7012
|
setLocal(value);
|
|
6513
7013
|
}, [value]);
|
|
6514
7014
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -6527,8 +7027,8 @@ function HexInput({ value, onChange }) {
|
|
|
6527
7027
|
);
|
|
6528
7028
|
}
|
|
6529
7029
|
function AlphaInput({ value, onChange }) {
|
|
6530
|
-
const [local, setLocal] =
|
|
6531
|
-
|
|
7030
|
+
const [local, setLocal] = React21.useState(value.toString());
|
|
7031
|
+
React21.useEffect(() => {
|
|
6532
7032
|
setLocal(value.toString());
|
|
6533
7033
|
}, [value]);
|
|
6534
7034
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -6548,13 +7048,13 @@ function AlphaInput({ value, onChange }) {
|
|
|
6548
7048
|
}
|
|
6549
7049
|
|
|
6550
7050
|
// src/panel/fill-section.tsx
|
|
6551
|
-
var
|
|
7051
|
+
var React22 = __toESM(require("react"));
|
|
6552
7052
|
var import_lucide_react4 = require("lucide-react");
|
|
6553
7053
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
6554
7054
|
function ColorInput({ id, label, icon, value, onChange }) {
|
|
6555
|
-
const [hexInput, setHexInput] =
|
|
6556
|
-
const [alphaInput, setAlphaInput] =
|
|
6557
|
-
|
|
7055
|
+
const [hexInput, setHexInput] = React22.useState(value.hex);
|
|
7056
|
+
const [alphaInput, setAlphaInput] = React22.useState(value.alpha.toString());
|
|
7057
|
+
React22.useEffect(() => {
|
|
6558
7058
|
setHexInput(value.hex);
|
|
6559
7059
|
setAlphaInput(value.alpha.toString());
|
|
6560
7060
|
}, [value.hex, value.alpha]);
|
|
@@ -6745,7 +7245,7 @@ function BorderSideIcon({ side, className }) {
|
|
|
6745
7245
|
] });
|
|
6746
7246
|
}
|
|
6747
7247
|
function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, borderPosition, borderStyleControlPreference, onPositionChange, outlineStyle, outlineWidth }) {
|
|
6748
|
-
const [selectedSide, setSelectedSide] =
|
|
7248
|
+
const [selectedSide, setSelectedSide] = React23.useState("All");
|
|
6749
7249
|
const isOutline = borderPosition === "outline";
|
|
6750
7250
|
const activeSides = selectedSide === "All" || selectedSide === "Custom" ? BORDER_SIDES : [selectedSide];
|
|
6751
7251
|
const stylesMatch = activeSides.every(
|
|
@@ -6857,7 +7357,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6857
7357
|
onValueChange: (val) => handleStyleChange(val),
|
|
6858
7358
|
options: BORDER_STYLE_OPTIONS,
|
|
6859
7359
|
popupMinWidth: "120px",
|
|
6860
|
-
children: borderStyleControlPreference === "icon" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Tip, { label: `Border style: ${currentStyleLabel}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0
|
|
7360
|
+
children: borderStyleControlPreference === "icon" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Tip, { label: `Border style: ${currentStyleLabel}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(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__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Settings2, { className: "size-3.5" }) }) }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(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: [
|
|
6861
7361
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "flex items-center gap-1.5", children: [
|
|
6862
7362
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Square, { className: "size-3.5 text-muted-foreground" }),
|
|
6863
7363
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: currentStyleLabel })
|
|
@@ -6873,7 +7373,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6873
7373
|
onValueChange: (val) => handleSideChange(val),
|
|
6874
7374
|
options: BORDER_SIDE_OPTIONS.map((side) => ({ value: side, label: side })),
|
|
6875
7375
|
popupMinWidth: "90px",
|
|
6876
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Tip, { label: `Sides: ${selectedSide}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SelectTrigger, { className: "flex h-7 w-auto shrink-0 items-center justify-center rounded-md border-0
|
|
7376
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Tip, { label: `Sides: ${selectedSide}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(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__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Grid2x2, { className: "size-3.5 text-muted-foreground", strokeWidth: 1 }) : selectedSide === "All" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Square, { className: "size-3.5 text-muted-foreground" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(BorderSideIcon, { side: selectedSide, className: "text-muted-foreground" }) }) })
|
|
6877
7377
|
}
|
|
6878
7378
|
)
|
|
6879
7379
|
] }),
|
|
@@ -6893,23 +7393,27 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6893
7393
|
)
|
|
6894
7394
|
] }) }, side);
|
|
6895
7395
|
}) }),
|
|
6896
|
-
activeColor && activeColorChange && /* @__PURE__ */ (0, import_jsx_runtime18.
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
7396
|
+
activeColor && activeColorChange && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
7397
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
7398
|
+
ColorInput,
|
|
7399
|
+
{
|
|
7400
|
+
id: isOutline ? "outline-color" : "border-color",
|
|
7401
|
+
label: isOutline ? "Outline" : "Border",
|
|
7402
|
+
icon: isOutline ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Focus, { className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Square, { className: "size-3.5" }),
|
|
7403
|
+
value: activeColor,
|
|
7404
|
+
onChange: activeColorChange
|
|
7405
|
+
}
|
|
7406
|
+
) }),
|
|
7407
|
+
borderStyleControlPreference === "icon" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-[30px] shrink-0" }),
|
|
7408
|
+
!isOutline && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-[30px] shrink-0" })
|
|
7409
|
+
] })
|
|
6906
7410
|
] });
|
|
6907
7411
|
}
|
|
6908
7412
|
function BorderSection({ border, borderColor, outlineColor, borderStyleControlPreference, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, pendingStyles }) {
|
|
6909
7413
|
const hasOutlinePending = Boolean(
|
|
6910
7414
|
pendingStyles?.["outline-style"] || pendingStyles?.["outline-width"]
|
|
6911
7415
|
);
|
|
6912
|
-
const [borderPosition, setBorderPosition] =
|
|
7416
|
+
const [borderPosition, setBorderPosition] = React23.useState(
|
|
6913
7417
|
hasOutlinePending ? "outline" : "border"
|
|
6914
7418
|
);
|
|
6915
7419
|
const isOutline = borderPosition === "outline";
|
|
@@ -7015,7 +7519,7 @@ function BorderSection({ border, borderColor, outlineColor, borderStyleControlPr
|
|
|
7015
7519
|
}
|
|
7016
7520
|
|
|
7017
7521
|
// src/panel/shadow-section.tsx
|
|
7018
|
-
var
|
|
7522
|
+
var React24 = __toESM(require("react"));
|
|
7019
7523
|
|
|
7020
7524
|
// src/shadow-utils.ts
|
|
7021
7525
|
var TAILWIND_SHADOW_PRESETS = [
|
|
@@ -7152,9 +7656,9 @@ function ShadowLayerEditor({
|
|
|
7152
7656
|
onChange,
|
|
7153
7657
|
onRemoveLayer
|
|
7154
7658
|
}) {
|
|
7155
|
-
const [hexInput, setHexInput] =
|
|
7156
|
-
const [alphaInput, setAlphaInput] =
|
|
7157
|
-
|
|
7659
|
+
const [hexInput, setHexInput] = React24.useState(layer.color.hex);
|
|
7660
|
+
const [alphaInput, setAlphaInput] = React24.useState(String(layer.color.alpha));
|
|
7661
|
+
React24.useEffect(() => {
|
|
7158
7662
|
setHexInput(layer.color.hex);
|
|
7159
7663
|
setAlphaInput(String(layer.color.alpha));
|
|
7160
7664
|
}, [layer.color.hex, layer.color.alpha]);
|
|
@@ -7245,10 +7749,10 @@ function ShadowLayerEditor({
|
|
|
7245
7749
|
}
|
|
7246
7750
|
function ShadowSection({ boxShadow, onSetCSS, pendingStyles }) {
|
|
7247
7751
|
const effectiveShadow = (pendingStyles?.["box-shadow"] ?? boxShadow ?? "none").trim();
|
|
7248
|
-
const parsedLayers =
|
|
7249
|
-
const [layers, setLayers] =
|
|
7752
|
+
const parsedLayers = React24.useMemo(() => parseShadowLayers(effectiveShadow), [effectiveShadow]);
|
|
7753
|
+
const [layers, setLayers] = React24.useState(parsedLayers);
|
|
7250
7754
|
const hasShadow = layers.length > 0;
|
|
7251
|
-
|
|
7755
|
+
React24.useEffect(() => {
|
|
7252
7756
|
setLayers(parsedLayers);
|
|
7253
7757
|
}, [parsedLayers]);
|
|
7254
7758
|
const commitLayers = (nextLayers) => {
|
|
@@ -7540,7 +8044,7 @@ function PanelHeader({
|
|
|
7540
8044
|
}
|
|
7541
8045
|
|
|
7542
8046
|
// src/panel/panel-footer.tsx
|
|
7543
|
-
var
|
|
8047
|
+
var React25 = __toESM(require("react"));
|
|
7544
8048
|
var import_lucide_react9 = require("lucide-react");
|
|
7545
8049
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7546
8050
|
var panelBarBaseClass2 = "flex h-11 shrink-0 items-center border-border/50 bg-background pl-3 pr-2";
|
|
@@ -7554,9 +8058,9 @@ function PanelFooter({
|
|
|
7554
8058
|
onPointerUp,
|
|
7555
8059
|
onPointerCancel
|
|
7556
8060
|
}) {
|
|
7557
|
-
const [copied, setCopied] =
|
|
7558
|
-
const [copyError, setCopyError] =
|
|
7559
|
-
const [sendStatus, setSendStatus] =
|
|
8061
|
+
const [copied, setCopied] = React25.useState(false);
|
|
8062
|
+
const [copyError, setCopyError] = React25.useState(false);
|
|
8063
|
+
const [sendStatus, setSendStatus] = React25.useState("idle");
|
|
7560
8064
|
const handleCopy = async () => {
|
|
7561
8065
|
const success = await onExportEdits();
|
|
7562
8066
|
if (success) {
|
|
@@ -7624,11 +8128,11 @@ function PanelFooter({
|
|
|
7624
8128
|
}
|
|
7625
8129
|
|
|
7626
8130
|
// src/panel/spacing-inputs.tsx
|
|
7627
|
-
var
|
|
8131
|
+
var React26 = __toESM(require("react"));
|
|
7628
8132
|
var import_lucide_react10 = require("lucide-react");
|
|
7629
8133
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
7630
8134
|
function SpacingInputs({ prefix, values, onChange }) {
|
|
7631
|
-
const [individual, setIndividual] =
|
|
8135
|
+
const [individual, setIndividual] = React26.useState(false);
|
|
7632
8136
|
const allowNegative = prefix === "margin";
|
|
7633
8137
|
const handleChange = (sides, numericValue) => {
|
|
7634
8138
|
const clamped = allowNegative ? numericValue : Math.max(0, numericValue);
|
|
@@ -7746,7 +8250,7 @@ function SpacingInputs({ prefix, values, onChange }) {
|
|
|
7746
8250
|
}
|
|
7747
8251
|
|
|
7748
8252
|
// src/panel/sizing-inputs.tsx
|
|
7749
|
-
var
|
|
8253
|
+
var React27 = __toESM(require("react"));
|
|
7750
8254
|
var import_lucide_react11 = require("lucide-react");
|
|
7751
8255
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
7752
8256
|
var SIZING_OPTIONS = [
|
|
@@ -7762,8 +8266,8 @@ var DISTRIBUTE_LABELS = {
|
|
|
7762
8266
|
"space-evenly": "Evenly"
|
|
7763
8267
|
};
|
|
7764
8268
|
function SizingFixedInput({ value, onValueChange }) {
|
|
7765
|
-
const [localValue, setLocalValue] =
|
|
7766
|
-
|
|
8269
|
+
const [localValue, setLocalValue] = React27.useState(String(value));
|
|
8270
|
+
React27.useEffect(() => {
|
|
7767
8271
|
setLocalValue(String(value));
|
|
7768
8272
|
}, [value]);
|
|
7769
8273
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
@@ -7824,9 +8328,9 @@ function SizingDropdown({ label, value, onChange }) {
|
|
|
7824
8328
|
}
|
|
7825
8329
|
function SizingInputs({ width, height, onWidthChange, onHeightChange }) {
|
|
7826
8330
|
const { selectedElement } = useDirectEditState();
|
|
7827
|
-
const [locked, setLocked] =
|
|
7828
|
-
const ratioRef =
|
|
7829
|
-
|
|
8331
|
+
const [locked, setLocked] = React27.useState(false);
|
|
8332
|
+
const ratioRef = React27.useRef(1);
|
|
8333
|
+
React27.useEffect(() => {
|
|
7830
8334
|
setLocked(false);
|
|
7831
8335
|
}, [selectedElement]);
|
|
7832
8336
|
const canLock = width.mode === "fixed" && height.mode === "fixed" && height.value.numericValue > 0 && width.value.numericValue > 0;
|
|
@@ -8082,7 +8586,7 @@ function LayoutSection({
|
|
|
8082
8586
|
}
|
|
8083
8587
|
|
|
8084
8588
|
// src/use-panel-position.ts
|
|
8085
|
-
var
|
|
8589
|
+
var React28 = __toESM(require("react"));
|
|
8086
8590
|
var PANEL_WIDTH = 300;
|
|
8087
8591
|
var PANEL_HEIGHT = 420;
|
|
8088
8592
|
var STORAGE_KEY2 = "direct-edit-panel-position";
|
|
@@ -8164,14 +8668,14 @@ function getInitialPosition() {
|
|
|
8164
8668
|
});
|
|
8165
8669
|
}
|
|
8166
8670
|
function usePanelPosition() {
|
|
8167
|
-
const [position, setPosition] =
|
|
8168
|
-
const [isDragging, setIsDragging] =
|
|
8169
|
-
const [isSnapping, setIsSnapping] =
|
|
8170
|
-
const [dragOffset, setDragOffset] =
|
|
8171
|
-
const snapTimerRef =
|
|
8172
|
-
const panelRef =
|
|
8173
|
-
const positionRef =
|
|
8174
|
-
|
|
8671
|
+
const [position, setPosition] = React28.useState(getInitialPosition);
|
|
8672
|
+
const [isDragging, setIsDragging] = React28.useState(false);
|
|
8673
|
+
const [isSnapping, setIsSnapping] = React28.useState(false);
|
|
8674
|
+
const [dragOffset, setDragOffset] = React28.useState({ x: 0, y: 0 });
|
|
8675
|
+
const snapTimerRef = React28.useRef(null);
|
|
8676
|
+
const panelRef = React28.useRef(null);
|
|
8677
|
+
const positionRef = React28.useRef(position);
|
|
8678
|
+
React28.useEffect(() => {
|
|
8175
8679
|
positionRef.current = position;
|
|
8176
8680
|
}, [position]);
|
|
8177
8681
|
const handlePointerDown = (e) => {
|
|
@@ -8227,7 +8731,7 @@ function usePanelPosition() {
|
|
|
8227
8731
|
} catch {
|
|
8228
8732
|
}
|
|
8229
8733
|
};
|
|
8230
|
-
|
|
8734
|
+
React28.useEffect(() => {
|
|
8231
8735
|
function handleResize() {
|
|
8232
8736
|
setPosition((prev) => {
|
|
8233
8737
|
const next = snapToEdge(prev);
|
|
@@ -8238,7 +8742,7 @@ function usePanelPosition() {
|
|
|
8238
8742
|
window.addEventListener("resize", handleResize);
|
|
8239
8743
|
return () => window.removeEventListener("resize", handleResize);
|
|
8240
8744
|
}, []);
|
|
8241
|
-
|
|
8745
|
+
React28.useEffect(() => {
|
|
8242
8746
|
return () => {
|
|
8243
8747
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
8244
8748
|
};
|
|
@@ -8299,12 +8803,12 @@ function DirectEditPanelInner({
|
|
|
8299
8803
|
const canTriggerSend = canSendToAgent || hasPendingChanges;
|
|
8300
8804
|
const isDraggable = onHeaderPointerDown !== void 0;
|
|
8301
8805
|
const sectionRefs = {
|
|
8302
|
-
layout:
|
|
8303
|
-
radius:
|
|
8304
|
-
border:
|
|
8305
|
-
shadow:
|
|
8306
|
-
colors:
|
|
8307
|
-
text:
|
|
8806
|
+
layout: React29.useRef(null),
|
|
8807
|
+
radius: React29.useRef(null),
|
|
8808
|
+
border: React29.useRef(null),
|
|
8809
|
+
shadow: React29.useRef(null),
|
|
8810
|
+
colors: React29.useRef(null),
|
|
8811
|
+
text: React29.useRef(null)
|
|
8308
8812
|
};
|
|
8309
8813
|
const { scrollRef, activeSection } = useSectionNav(sectionRefs);
|
|
8310
8814
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
@@ -8347,7 +8851,7 @@ function DirectEditPanelInner({
|
|
|
8347
8851
|
sectionRefs
|
|
8348
8852
|
}
|
|
8349
8853
|
),
|
|
8350
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, children: [
|
|
8854
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, onWheelCapture: (e) => e.stopPropagation(), children: [
|
|
8351
8855
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
8352
8856
|
LayoutSection,
|
|
8353
8857
|
{
|
|
@@ -8502,8 +9006,12 @@ function DirectEditPanelContent() {
|
|
|
8502
9006
|
handlePointerUp,
|
|
8503
9007
|
handlePointerCancel
|
|
8504
9008
|
} = usePanelPosition();
|
|
8505
|
-
const [hoverHighlight, setHoverHighlight] =
|
|
8506
|
-
const [commentInputAttention, setCommentInputAttention] =
|
|
9009
|
+
const [hoverHighlight, setHoverHighlight] = React29.useState(null);
|
|
9010
|
+
const [commentInputAttention, setCommentInputAttention] = React29.useState(null);
|
|
9011
|
+
const commentDraftRef = React29.useRef("");
|
|
9012
|
+
React29.useEffect(() => {
|
|
9013
|
+
commentDraftRef.current = "";
|
|
9014
|
+
}, [activeCommentId]);
|
|
8507
9015
|
const { isActive: measurementActive, hoveredElement, measurements, mousePosition } = useMeasurement(
|
|
8508
9016
|
isOpen ? selectedElement : null
|
|
8509
9017
|
);
|
|
@@ -8514,21 +9022,29 @@ function DirectEditPanelContent() {
|
|
|
8514
9022
|
} = useMove({
|
|
8515
9023
|
onMoveComplete: handleMoveComplete
|
|
8516
9024
|
});
|
|
8517
|
-
const triggerCommentInputAttention =
|
|
9025
|
+
const triggerCommentInputAttention = React29.useCallback((commentId) => {
|
|
8518
9026
|
setCommentInputAttention((prev) => prev?.commentId === commentId ? { commentId, nonce: prev.nonce + 1 } : { commentId, nonce: 1 });
|
|
8519
9027
|
}, []);
|
|
8520
|
-
const hasPendingCommentDraft =
|
|
9028
|
+
const hasPendingCommentDraft = React29.useCallback((nextCommentId = null) => {
|
|
8521
9029
|
if (!activeCommentId) return false;
|
|
8522
9030
|
if (nextCommentId && nextCommentId === activeCommentId) return false;
|
|
8523
9031
|
const active = comments.find((comment) => comment.id === activeCommentId);
|
|
8524
|
-
if (!active
|
|
9032
|
+
if (!active) return false;
|
|
9033
|
+
const hasUnsentDraft = active.text.trim().length === 0 && commentDraftRef.current.trim().length > 0;
|
|
9034
|
+
if (!hasUnsentDraft) return false;
|
|
8525
9035
|
triggerCommentInputAttention(active.id);
|
|
8526
9036
|
return true;
|
|
8527
9037
|
}, [activeCommentId, comments, triggerCommentInputAttention]);
|
|
8528
|
-
const handleSetActiveComment =
|
|
8529
|
-
if (
|
|
9038
|
+
const handleSetActiveComment = React29.useCallback((id) => {
|
|
9039
|
+
if (hasPendingCommentDraft(id)) return;
|
|
9040
|
+
if (activeCommentId && activeCommentId !== id) {
|
|
9041
|
+
const active = comments.find((comment) => comment.id === activeCommentId);
|
|
9042
|
+
if (active && active.text.trim().length === 0) {
|
|
9043
|
+
deleteComment(active.id);
|
|
9044
|
+
}
|
|
9045
|
+
}
|
|
8530
9046
|
setActiveCommentId(id);
|
|
8531
|
-
}, [hasPendingCommentDraft, setActiveCommentId]);
|
|
9047
|
+
}, [activeCommentId, comments, hasPendingCommentDraft, deleteComment, setActiveCommentId]);
|
|
8532
9048
|
const overlay = editModeActive && container ? (0, import_react_dom.createPortal)(
|
|
8533
9049
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
8534
9050
|
InteractionOverlay,
|
|
@@ -8541,7 +9057,7 @@ function DirectEditPanelContent() {
|
|
|
8541
9057
|
onSelectElement: selectElement,
|
|
8542
9058
|
onStartTextEditing: startTextEditing,
|
|
8543
9059
|
onAddComment: addComment,
|
|
8544
|
-
onSetActiveCommentId:
|
|
9060
|
+
onSetActiveCommentId: handleSetActiveComment,
|
|
8545
9061
|
onSetHoverHighlight: setHoverHighlight,
|
|
8546
9062
|
hasPendingCommentDraft
|
|
8547
9063
|
}
|
|
@@ -8560,7 +9076,8 @@ function DirectEditPanelContent() {
|
|
|
8560
9076
|
onDelete: deleteComment,
|
|
8561
9077
|
onExport: exportComment,
|
|
8562
9078
|
onSendToAgent: sendCommentToAgent2,
|
|
8563
|
-
attentionRequest: commentInputAttention
|
|
9079
|
+
attentionRequest: commentInputAttention,
|
|
9080
|
+
draftRef: commentDraftRef
|
|
8564
9081
|
}
|
|
8565
9082
|
),
|
|
8566
9083
|
container
|
|
@@ -8602,6 +9119,7 @@ function DirectEditPanelContent() {
|
|
|
8602
9119
|
ghostPosition: dragState.ghostPosition,
|
|
8603
9120
|
onMoveStart: handleMoveStart,
|
|
8604
9121
|
showMoveHandle,
|
|
9122
|
+
activeTool,
|
|
8605
9123
|
isTextEditing: Boolean(textEditingElement),
|
|
8606
9124
|
onDoubleClick: (clientX, clientY) => {
|
|
8607
9125
|
if (!selectedElement) return;
|
|
@@ -8707,8 +9225,8 @@ function DirectEditPanelContent() {
|
|
|
8707
9225
|
);
|
|
8708
9226
|
}
|
|
8709
9227
|
function DirectEditPanel() {
|
|
8710
|
-
const [mounted, setMounted] =
|
|
8711
|
-
|
|
9228
|
+
const [mounted, setMounted] = React29.useState(false);
|
|
9229
|
+
React29.useEffect(() => {
|
|
8712
9230
|
setMounted(true);
|
|
8713
9231
|
}, []);
|
|
8714
9232
|
if (!mounted) {
|
|
@@ -8718,26 +9236,59 @@ function DirectEditPanel() {
|
|
|
8718
9236
|
}
|
|
8719
9237
|
|
|
8720
9238
|
// src/toolbar.tsx
|
|
8721
|
-
var
|
|
9239
|
+
var React36 = __toESM(require("react"));
|
|
8722
9240
|
var import_react_dom3 = require("react-dom");
|
|
8723
9241
|
|
|
8724
9242
|
// src/rulers-overlay.tsx
|
|
8725
|
-
var
|
|
9243
|
+
var React30 = __toESM(require("react"));
|
|
8726
9244
|
var import_react_dom2 = require("react-dom");
|
|
8727
9245
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
8728
9246
|
var RULER_SIZE2 = 20;
|
|
8729
9247
|
var GUIDELINE_COLOR = "#FF6B6B";
|
|
9248
|
+
var SNAPPED_COLOR = "#0D99FF";
|
|
8730
9249
|
var HIT_ZONE = 9;
|
|
9250
|
+
function computeCanvasRulerScrollOffset(pan, zoom, bodyOffset2) {
|
|
9251
|
+
if (zoom === 0) return -pan;
|
|
9252
|
+
return bodyOffset2 * (1 - 1 / zoom) - pan;
|
|
9253
|
+
}
|
|
9254
|
+
function computeTickIntervals(zoom) {
|
|
9255
|
+
const MIN_LABEL_SPACING_PX = 80;
|
|
9256
|
+
const rawInterval = MIN_LABEL_SPACING_PX / zoom;
|
|
9257
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval)));
|
|
9258
|
+
const residual = rawInterval / magnitude;
|
|
9259
|
+
let nice;
|
|
9260
|
+
if (residual <= 1) nice = 1;
|
|
9261
|
+
else if (residual <= 2) nice = 2;
|
|
9262
|
+
else if (residual <= 2.5) nice = 2.5;
|
|
9263
|
+
else if (residual <= 5) nice = 5;
|
|
9264
|
+
else nice = 10;
|
|
9265
|
+
const major = nice * magnitude;
|
|
9266
|
+
const stepsPerMajor = 10;
|
|
9267
|
+
const minor = major / stepsPerMajor;
|
|
9268
|
+
return { major, minor, stepsPerMajor };
|
|
9269
|
+
}
|
|
9270
|
+
function getColorSchemeQuery() {
|
|
9271
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
9272
|
+
return null;
|
|
9273
|
+
}
|
|
9274
|
+
return window.matchMedia("(prefers-color-scheme: dark)");
|
|
9275
|
+
}
|
|
8731
9276
|
function subscribeColorScheme(cb) {
|
|
8732
|
-
const mq =
|
|
8733
|
-
mq
|
|
8734
|
-
|
|
9277
|
+
const mq = getColorSchemeQuery();
|
|
9278
|
+
if (!mq) return () => {
|
|
9279
|
+
};
|
|
9280
|
+
if (typeof mq.addEventListener === "function") {
|
|
9281
|
+
mq.addEventListener("change", cb);
|
|
9282
|
+
return () => mq.removeEventListener("change", cb);
|
|
9283
|
+
}
|
|
9284
|
+
mq.addListener(cb);
|
|
9285
|
+
return () => mq.removeListener(cb);
|
|
8735
9286
|
}
|
|
8736
9287
|
function getColorScheme() {
|
|
8737
|
-
return
|
|
9288
|
+
return getColorSchemeQuery()?.matches ?? false;
|
|
8738
9289
|
}
|
|
8739
9290
|
function useSystemDark() {
|
|
8740
|
-
return
|
|
9291
|
+
return React30.useSyncExternalStore(subscribeColorScheme, getColorScheme, () => false);
|
|
8741
9292
|
}
|
|
8742
9293
|
var rulerFont = {
|
|
8743
9294
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -8746,13 +9297,14 @@ var rulerFont = {
|
|
|
8746
9297
|
};
|
|
8747
9298
|
function HorizontalRuler({
|
|
8748
9299
|
scrollOffset,
|
|
9300
|
+
zoom = 1,
|
|
8749
9301
|
onPointerDown
|
|
8750
9302
|
}) {
|
|
8751
|
-
const canvasRef =
|
|
9303
|
+
const canvasRef = React30.useRef(null);
|
|
8752
9304
|
const viewportWidth = useViewportWidth();
|
|
8753
9305
|
const { theme } = useDirectEditState();
|
|
8754
9306
|
const systemDark = useSystemDark();
|
|
8755
|
-
|
|
9307
|
+
React30.useEffect(() => {
|
|
8756
9308
|
const canvas = canvasRef.current;
|
|
8757
9309
|
if (!canvas) return;
|
|
8758
9310
|
const dpr = window.devicePixelRatio || 1;
|
|
@@ -8770,12 +9322,16 @@ function HorizontalRuler({
|
|
|
8770
9322
|
const computed = getComputedStyle(canvas);
|
|
8771
9323
|
const tick = computed.getPropertyValue("color");
|
|
8772
9324
|
const label = tick;
|
|
8773
|
-
const
|
|
8774
|
-
const
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
9325
|
+
const { minor, stepsPerMajor } = computeTickIntervals(zoom);
|
|
9326
|
+
const midIdx = stepsPerMajor / 2;
|
|
9327
|
+
const visibleContentWidth = width / zoom;
|
|
9328
|
+
const startIdx = Math.floor(scrollOffset.x / minor);
|
|
9329
|
+
const endIdx = Math.ceil((scrollOffset.x + visibleContentWidth) / minor);
|
|
9330
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
9331
|
+
const px = i * minor;
|
|
9332
|
+
const x = (px - scrollOffset.x) * zoom;
|
|
9333
|
+
const isMajor = i % stepsPerMajor === 0;
|
|
9334
|
+
const isMid = !isMajor && i % midIdx === 0;
|
|
8779
9335
|
ctx.beginPath();
|
|
8780
9336
|
ctx.moveTo(x, height);
|
|
8781
9337
|
ctx.lineTo(x, height - (isMajor ? 10 : isMid ? 7 : 4));
|
|
@@ -8783,15 +9339,15 @@ function HorizontalRuler({
|
|
|
8783
9339
|
ctx.globalAlpha = 0.6;
|
|
8784
9340
|
ctx.lineWidth = 1;
|
|
8785
9341
|
ctx.stroke();
|
|
8786
|
-
if (isMajor
|
|
9342
|
+
if (isMajor) {
|
|
8787
9343
|
ctx.globalAlpha = 1;
|
|
8788
9344
|
ctx.fillStyle = label;
|
|
8789
9345
|
ctx.font = "9px system-ui, -apple-system, sans-serif";
|
|
8790
9346
|
ctx.textAlign = "center";
|
|
8791
|
-
ctx.fillText(String(px), x, 9);
|
|
9347
|
+
ctx.fillText(String(Math.round(px)), x, 9);
|
|
8792
9348
|
}
|
|
8793
9349
|
}
|
|
8794
|
-
}, [scrollOffset.x, viewportWidth, theme, systemDark]);
|
|
9350
|
+
}, [scrollOffset.x, viewportWidth, zoom, theme, systemDark]);
|
|
8795
9351
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8796
9352
|
"div",
|
|
8797
9353
|
{
|
|
@@ -8817,13 +9373,14 @@ function HorizontalRuler({
|
|
|
8817
9373
|
}
|
|
8818
9374
|
function VerticalRuler({
|
|
8819
9375
|
scrollOffset,
|
|
9376
|
+
zoom = 1,
|
|
8820
9377
|
onPointerDown
|
|
8821
9378
|
}) {
|
|
8822
|
-
const canvasRef =
|
|
9379
|
+
const canvasRef = React30.useRef(null);
|
|
8823
9380
|
const viewportHeight = useViewportHeight();
|
|
8824
9381
|
const { theme } = useDirectEditState();
|
|
8825
9382
|
const systemDark = useSystemDark();
|
|
8826
|
-
|
|
9383
|
+
React30.useEffect(() => {
|
|
8827
9384
|
const canvas = canvasRef.current;
|
|
8828
9385
|
if (!canvas) return;
|
|
8829
9386
|
const dpr = window.devicePixelRatio || 1;
|
|
@@ -8841,12 +9398,16 @@ function VerticalRuler({
|
|
|
8841
9398
|
const computed = getComputedStyle(canvas);
|
|
8842
9399
|
const tick = computed.getPropertyValue("color");
|
|
8843
9400
|
const label = tick;
|
|
8844
|
-
const
|
|
8845
|
-
const
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
9401
|
+
const { minor, stepsPerMajor } = computeTickIntervals(zoom);
|
|
9402
|
+
const midIdx = stepsPerMajor / 2;
|
|
9403
|
+
const visibleContentHeight = height / zoom;
|
|
9404
|
+
const startIdx = Math.floor(scrollOffset.y / minor);
|
|
9405
|
+
const endIdx = Math.ceil((scrollOffset.y + visibleContentHeight) / minor);
|
|
9406
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
9407
|
+
const px = i * minor;
|
|
9408
|
+
const y = (px - scrollOffset.y) * zoom;
|
|
9409
|
+
const isMajor = i % stepsPerMajor === 0;
|
|
9410
|
+
const isMid = !isMajor && i % midIdx === 0;
|
|
8850
9411
|
ctx.beginPath();
|
|
8851
9412
|
ctx.moveTo(width, y);
|
|
8852
9413
|
ctx.lineTo(width - (isMajor ? 10 : isMid ? 7 : 4), y);
|
|
@@ -8854,7 +9415,7 @@ function VerticalRuler({
|
|
|
8854
9415
|
ctx.globalAlpha = 0.6;
|
|
8855
9416
|
ctx.lineWidth = 1;
|
|
8856
9417
|
ctx.stroke();
|
|
8857
|
-
if (isMajor
|
|
9418
|
+
if (isMajor) {
|
|
8858
9419
|
ctx.save();
|
|
8859
9420
|
ctx.globalAlpha = 1;
|
|
8860
9421
|
ctx.fillStyle = label;
|
|
@@ -8862,11 +9423,11 @@ function VerticalRuler({
|
|
|
8862
9423
|
ctx.textAlign = "center";
|
|
8863
9424
|
ctx.translate(9, y);
|
|
8864
9425
|
ctx.rotate(-Math.PI / 2);
|
|
8865
|
-
ctx.fillText(String(px), 0, 0);
|
|
9426
|
+
ctx.fillText(String(Math.round(px)), 0, 0);
|
|
8866
9427
|
ctx.restore();
|
|
8867
9428
|
}
|
|
8868
9429
|
}
|
|
8869
|
-
}, [scrollOffset.y, viewportHeight, theme, systemDark]);
|
|
9430
|
+
}, [scrollOffset.y, viewportHeight, zoom, theme, systemDark]);
|
|
8870
9431
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8871
9432
|
"div",
|
|
8872
9433
|
{
|
|
@@ -8910,17 +9471,26 @@ function CornerSquare() {
|
|
|
8910
9471
|
}
|
|
8911
9472
|
);
|
|
8912
9473
|
}
|
|
9474
|
+
function computeGuidelineViewportPos(position, orientation) {
|
|
9475
|
+
const snap = getCanvasSnapshot();
|
|
9476
|
+
const zoom = snap.active ? snap.zoom : 1;
|
|
9477
|
+
const pan = orientation === "horizontal" ? snap.active ? snap.panY : -window.scrollY : snap.active ? snap.panX : -window.scrollX;
|
|
9478
|
+
if (snap.active) {
|
|
9479
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
9480
|
+
return bo + (position - bo + pan) * zoom;
|
|
9481
|
+
}
|
|
9482
|
+
return (position + pan) * zoom;
|
|
9483
|
+
}
|
|
8913
9484
|
function GuidelineLine({
|
|
8914
9485
|
guideline,
|
|
8915
|
-
scrollOffset,
|
|
8916
9486
|
isActive,
|
|
9487
|
+
isSnapped,
|
|
8917
9488
|
dragPosition,
|
|
8918
9489
|
onStartDrag,
|
|
8919
9490
|
onDelete
|
|
8920
9491
|
}) {
|
|
8921
9492
|
const isHorizontal = guideline.orientation === "horizontal";
|
|
8922
|
-
const
|
|
8923
|
-
const viewportPos = guideline.position - scrollPos;
|
|
9493
|
+
const lineColor = isActive && isSnapped ? SNAPPED_COLOR : GUIDELINE_COLOR;
|
|
8924
9494
|
const handlePointerDown = (e) => {
|
|
8925
9495
|
e.preventDefault();
|
|
8926
9496
|
e.stopPropagation();
|
|
@@ -8931,119 +9501,137 @@ function GuidelineLine({
|
|
|
8931
9501
|
e.stopPropagation();
|
|
8932
9502
|
onDelete(guideline.id);
|
|
8933
9503
|
};
|
|
8934
|
-
const
|
|
9504
|
+
const isDragging = isActive && dragPosition !== null;
|
|
9505
|
+
const viewportPos = isDragging ? dragPosition : computeGuidelineViewportPos(guideline.position, guideline.orientation);
|
|
9506
|
+
const translate = isHorizontal ? `translateY(${viewportPos}px)` : `translateX(${viewportPos}px)`;
|
|
8935
9507
|
if (isHorizontal) {
|
|
8936
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
8937
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8938
|
-
"div",
|
|
8939
|
-
{
|
|
8940
|
-
"data-direct-edit": "guideline",
|
|
8941
|
-
style: {
|
|
8942
|
-
position: "fixed",
|
|
8943
|
-
top: displayPos,
|
|
8944
|
-
left: 0,
|
|
8945
|
-
right: 0,
|
|
8946
|
-
height: 1,
|
|
8947
|
-
background: GUIDELINE_COLOR,
|
|
8948
|
-
zIndex: 99993,
|
|
8949
|
-
pointerEvents: "none"
|
|
8950
|
-
}
|
|
8951
|
-
}
|
|
8952
|
-
),
|
|
8953
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8954
|
-
"div",
|
|
8955
|
-
{
|
|
8956
|
-
style: {
|
|
8957
|
-
position: "fixed",
|
|
8958
|
-
top: displayPos - Math.floor(HIT_ZONE / 2),
|
|
8959
|
-
left: RULER_SIZE2,
|
|
8960
|
-
right: 0,
|
|
8961
|
-
height: HIT_ZONE,
|
|
8962
|
-
zIndex: 99993,
|
|
8963
|
-
cursor: "ns-resize",
|
|
8964
|
-
pointerEvents: "auto"
|
|
8965
|
-
},
|
|
8966
|
-
onPointerDown: handlePointerDown,
|
|
8967
|
-
onDoubleClick: handleDoubleClick
|
|
8968
|
-
}
|
|
8969
|
-
),
|
|
8970
|
-
isActive && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8971
|
-
"div",
|
|
8972
|
-
{
|
|
8973
|
-
style: {
|
|
8974
|
-
position: "fixed",
|
|
8975
|
-
top: displayPos + 4,
|
|
8976
|
-
left: RULER_SIZE2 + 4,
|
|
8977
|
-
background: GUIDELINE_COLOR,
|
|
8978
|
-
color: "#fff",
|
|
8979
|
-
padding: "1px 4px",
|
|
8980
|
-
borderRadius: 2,
|
|
8981
|
-
zIndex: 99995,
|
|
8982
|
-
pointerEvents: "none",
|
|
8983
|
-
...rulerFont
|
|
8984
|
-
},
|
|
8985
|
-
children: Math.round(guideline.position)
|
|
8986
|
-
}
|
|
8987
|
-
)
|
|
8988
|
-
] });
|
|
8989
|
-
}
|
|
8990
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
8991
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
8992
9509
|
"div",
|
|
8993
9510
|
{
|
|
8994
|
-
"data-
|
|
9511
|
+
"data-gl-pos": guideline.position,
|
|
9512
|
+
"data-gl-orient": "h",
|
|
9513
|
+
...isDragging ? { "data-gl-dragging": "" } : {},
|
|
8995
9514
|
style: {
|
|
8996
9515
|
position: "fixed",
|
|
8997
|
-
left: displayPos,
|
|
8998
9516
|
top: 0,
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9517
|
+
left: 0,
|
|
9518
|
+
right: 0,
|
|
9519
|
+
height: 0,
|
|
9520
|
+
transform: translate,
|
|
9002
9521
|
zIndex: 99993,
|
|
9003
9522
|
pointerEvents: "none"
|
|
9004
|
-
}
|
|
9005
|
-
}
|
|
9006
|
-
),
|
|
9007
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9008
|
-
"div",
|
|
9009
|
-
{
|
|
9010
|
-
style: {
|
|
9011
|
-
position: "fixed",
|
|
9012
|
-
left: displayPos - Math.floor(HIT_ZONE / 2),
|
|
9013
|
-
top: RULER_SIZE2,
|
|
9014
|
-
bottom: 0,
|
|
9015
|
-
width: HIT_ZONE,
|
|
9016
|
-
zIndex: 99993,
|
|
9017
|
-
cursor: "ew-resize",
|
|
9018
|
-
pointerEvents: "auto"
|
|
9019
9523
|
},
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9524
|
+
children: [
|
|
9525
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9526
|
+
"div",
|
|
9527
|
+
{
|
|
9528
|
+
"data-direct-edit": "guideline",
|
|
9529
|
+
style: { position: "absolute", top: 0, left: 0, right: 0, height: 1, background: lineColor }
|
|
9530
|
+
}
|
|
9531
|
+
),
|
|
9532
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9533
|
+
"div",
|
|
9534
|
+
{
|
|
9535
|
+
style: {
|
|
9536
|
+
position: "absolute",
|
|
9537
|
+
top: -Math.floor(HIT_ZONE / 2),
|
|
9538
|
+
left: RULER_SIZE2,
|
|
9539
|
+
right: 0,
|
|
9540
|
+
height: HIT_ZONE,
|
|
9541
|
+
cursor: "ns-resize",
|
|
9542
|
+
pointerEvents: "auto"
|
|
9543
|
+
},
|
|
9544
|
+
onPointerDown: handlePointerDown,
|
|
9545
|
+
onDoubleClick: handleDoubleClick
|
|
9546
|
+
}
|
|
9547
|
+
),
|
|
9548
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9549
|
+
"div",
|
|
9550
|
+
{
|
|
9551
|
+
style: {
|
|
9552
|
+
position: "absolute",
|
|
9553
|
+
top: 4,
|
|
9554
|
+
left: RULER_SIZE2 + 4,
|
|
9555
|
+
background: lineColor,
|
|
9556
|
+
color: "#fff",
|
|
9557
|
+
padding: "1px 4px",
|
|
9558
|
+
borderRadius: 2,
|
|
9559
|
+
zIndex: 99995,
|
|
9560
|
+
pointerEvents: "none",
|
|
9561
|
+
...rulerFont
|
|
9562
|
+
},
|
|
9563
|
+
children: Math.round(guideline.position)
|
|
9564
|
+
}
|
|
9565
|
+
)
|
|
9566
|
+
]
|
|
9040
9567
|
}
|
|
9041
|
-
)
|
|
9042
|
-
|
|
9568
|
+
);
|
|
9569
|
+
}
|
|
9570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
9571
|
+
"div",
|
|
9572
|
+
{
|
|
9573
|
+
"data-gl-pos": guideline.position,
|
|
9574
|
+
"data-gl-orient": "v",
|
|
9575
|
+
...isDragging ? { "data-gl-dragging": "" } : {},
|
|
9576
|
+
style: {
|
|
9577
|
+
position: "fixed",
|
|
9578
|
+
top: 0,
|
|
9579
|
+
left: 0,
|
|
9580
|
+
bottom: 0,
|
|
9581
|
+
width: 0,
|
|
9582
|
+
transform: translate,
|
|
9583
|
+
zIndex: 99993,
|
|
9584
|
+
pointerEvents: "none"
|
|
9585
|
+
},
|
|
9586
|
+
children: [
|
|
9587
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9588
|
+
"div",
|
|
9589
|
+
{
|
|
9590
|
+
"data-direct-edit": "guideline",
|
|
9591
|
+
style: { position: "absolute", left: 0, top: 0, bottom: 0, width: 1, background: lineColor }
|
|
9592
|
+
}
|
|
9593
|
+
),
|
|
9594
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9595
|
+
"div",
|
|
9596
|
+
{
|
|
9597
|
+
style: {
|
|
9598
|
+
position: "absolute",
|
|
9599
|
+
left: -Math.floor(HIT_ZONE / 2),
|
|
9600
|
+
top: RULER_SIZE2,
|
|
9601
|
+
bottom: 0,
|
|
9602
|
+
width: HIT_ZONE,
|
|
9603
|
+
cursor: "ew-resize",
|
|
9604
|
+
pointerEvents: "auto"
|
|
9605
|
+
},
|
|
9606
|
+
onPointerDown: handlePointerDown,
|
|
9607
|
+
onDoubleClick: handleDoubleClick
|
|
9608
|
+
}
|
|
9609
|
+
),
|
|
9610
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9611
|
+
"div",
|
|
9612
|
+
{
|
|
9613
|
+
style: {
|
|
9614
|
+
position: "absolute",
|
|
9615
|
+
left: 4,
|
|
9616
|
+
top: RULER_SIZE2 + 4,
|
|
9617
|
+
background: lineColor,
|
|
9618
|
+
color: "#fff",
|
|
9619
|
+
padding: "1px 4px",
|
|
9620
|
+
borderRadius: 2,
|
|
9621
|
+
zIndex: 99995,
|
|
9622
|
+
pointerEvents: "none",
|
|
9623
|
+
...rulerFont
|
|
9624
|
+
},
|
|
9625
|
+
children: Math.round(guideline.position)
|
|
9626
|
+
}
|
|
9627
|
+
)
|
|
9628
|
+
]
|
|
9629
|
+
}
|
|
9630
|
+
);
|
|
9043
9631
|
}
|
|
9044
9632
|
function useViewportWidth() {
|
|
9045
|
-
const [width, setWidth] =
|
|
9046
|
-
|
|
9633
|
+
const [width, setWidth] = React30.useState(0);
|
|
9634
|
+
React30.useEffect(() => {
|
|
9047
9635
|
setWidth(window.innerWidth);
|
|
9048
9636
|
const onResize = () => setWidth(window.innerWidth);
|
|
9049
9637
|
window.addEventListener("resize", onResize);
|
|
@@ -9052,8 +9640,8 @@ function useViewportWidth() {
|
|
|
9052
9640
|
return width;
|
|
9053
9641
|
}
|
|
9054
9642
|
function useViewportHeight() {
|
|
9055
|
-
const [height, setHeight] =
|
|
9056
|
-
|
|
9643
|
+
const [height, setHeight] = React30.useState(0);
|
|
9644
|
+
React30.useEffect(() => {
|
|
9057
9645
|
setHeight(window.innerHeight);
|
|
9058
9646
|
const onResize = () => setHeight(window.innerHeight);
|
|
9059
9647
|
window.addEventListener("resize", onResize);
|
|
@@ -9063,7 +9651,8 @@ function useViewportHeight() {
|
|
|
9063
9651
|
}
|
|
9064
9652
|
function RulersOverlay({ enabled }) {
|
|
9065
9653
|
const container = usePortalContainer();
|
|
9066
|
-
const
|
|
9654
|
+
const canvas = useCanvasSnapshot();
|
|
9655
|
+
const hostElement = React30.useMemo(() => {
|
|
9067
9656
|
if (!container) return null;
|
|
9068
9657
|
const root = container.getRootNode();
|
|
9069
9658
|
if (root instanceof ShadowRoot) return root.host;
|
|
@@ -9073,12 +9662,51 @@ function RulersOverlay({ enabled }) {
|
|
|
9073
9662
|
guidelines,
|
|
9074
9663
|
activeGuideline,
|
|
9075
9664
|
dragPosition,
|
|
9665
|
+
isSnapped,
|
|
9076
9666
|
scrollOffset,
|
|
9077
9667
|
startCreate,
|
|
9078
9668
|
startDrag,
|
|
9079
9669
|
deleteGuideline
|
|
9080
|
-
} = useGuidelines(enabled, hostElement);
|
|
9670
|
+
} = useGuidelines(enabled, hostElement, canvas);
|
|
9671
|
+
React30.useLayoutEffect(() => {
|
|
9672
|
+
if (!container || !enabled) return;
|
|
9673
|
+
const el = container;
|
|
9674
|
+
function updateGuidelinePositions() {
|
|
9675
|
+
const snap = getCanvasSnapshot();
|
|
9676
|
+
const zoom2 = snap.active ? snap.zoom : 1;
|
|
9677
|
+
const panX = snap.active ? snap.panX : -window.scrollX;
|
|
9678
|
+
const panY = snap.active ? snap.panY : -window.scrollY;
|
|
9679
|
+
const bo = getBodyOffset();
|
|
9680
|
+
el.querySelectorAll("[data-gl-pos]").forEach((node) => {
|
|
9681
|
+
if (node.hasAttribute("data-gl-dragging")) return;
|
|
9682
|
+
const pos = Number(node.dataset.glPos);
|
|
9683
|
+
const orient = node.dataset.glOrient;
|
|
9684
|
+
let vp;
|
|
9685
|
+
if (snap.active) {
|
|
9686
|
+
vp = orient === "h" ? bo.y + (pos - bo.y + panY) * zoom2 : bo.x + (pos - bo.x + panX) * zoom2;
|
|
9687
|
+
} else {
|
|
9688
|
+
vp = orient === "h" ? (pos + panY) * zoom2 : (pos + panX) * zoom2;
|
|
9689
|
+
}
|
|
9690
|
+
node.style.transform = orient === "h" ? `translateY(${vp}px)` : `translateX(${vp}px)`;
|
|
9691
|
+
});
|
|
9692
|
+
}
|
|
9693
|
+
updateGuidelinePositions();
|
|
9694
|
+
window.addEventListener("direct-edit-canvas-change", updateGuidelinePositions);
|
|
9695
|
+
window.addEventListener("scroll", updateGuidelinePositions, true);
|
|
9696
|
+
return () => {
|
|
9697
|
+
window.removeEventListener("direct-edit-canvas-change", updateGuidelinePositions);
|
|
9698
|
+
window.removeEventListener("scroll", updateGuidelinePositions, true);
|
|
9699
|
+
};
|
|
9700
|
+
}, [container, enabled]);
|
|
9081
9701
|
if (!enabled || !container) return null;
|
|
9702
|
+
const zoom = canvas?.active ? canvas.zoom || 1 : 1;
|
|
9703
|
+
const effectiveScrollOffset = canvas?.active ? (() => {
|
|
9704
|
+
const bo = getBodyOffset();
|
|
9705
|
+
return {
|
|
9706
|
+
x: computeCanvasRulerScrollOffset(canvas.panX || 0, zoom, bo.x),
|
|
9707
|
+
y: computeCanvasRulerScrollOffset(canvas.panY || 0, zoom, bo.y)
|
|
9708
|
+
};
|
|
9709
|
+
})() : scrollOffset;
|
|
9082
9710
|
const handleHorizontalPointerDown = (e) => {
|
|
9083
9711
|
e.preventDefault();
|
|
9084
9712
|
startCreate("horizontal", e.clientY);
|
|
@@ -9090,14 +9718,14 @@ function RulersOverlay({ enabled }) {
|
|
|
9090
9718
|
return (0, import_react_dom2.createPortal)(
|
|
9091
9719
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
9092
9720
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(CornerSquare, {}),
|
|
9093
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HorizontalRuler, { scrollOffset, onPointerDown: handleHorizontalPointerDown }),
|
|
9094
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VerticalRuler, { scrollOffset, onPointerDown: handleVerticalPointerDown }),
|
|
9721
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HorizontalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleHorizontalPointerDown }),
|
|
9722
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VerticalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleVerticalPointerDown }),
|
|
9095
9723
|
guidelines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9096
9724
|
GuidelineLine,
|
|
9097
9725
|
{
|
|
9098
9726
|
guideline: g,
|
|
9099
|
-
scrollOffset,
|
|
9100
9727
|
isActive: activeGuideline?.id === g.id,
|
|
9728
|
+
isSnapped: activeGuideline?.id === g.id ? isSnapped : false,
|
|
9101
9729
|
dragPosition: activeGuideline?.id === g.id ? dragPosition : null,
|
|
9102
9730
|
onStartDrag: startDrag,
|
|
9103
9731
|
onDelete: deleteGuideline
|
|
@@ -9145,12 +9773,12 @@ function subscribeRulersVisible(listener) {
|
|
|
9145
9773
|
};
|
|
9146
9774
|
}
|
|
9147
9775
|
function useRulersVisible() {
|
|
9148
|
-
const visible =
|
|
9776
|
+
const visible = React30.useSyncExternalStore(
|
|
9149
9777
|
subscribeRulersVisible,
|
|
9150
9778
|
() => rulersVisibleSnapshot,
|
|
9151
9779
|
() => true
|
|
9152
9780
|
);
|
|
9153
|
-
const toggle =
|
|
9781
|
+
const toggle = React30.useCallback(() => {
|
|
9154
9782
|
setRulersVisible(!rulersVisibleSnapshot);
|
|
9155
9783
|
}, []);
|
|
9156
9784
|
return [visible, toggle];
|
|
@@ -9158,7 +9786,7 @@ function useRulersVisible() {
|
|
|
9158
9786
|
function Rulers() {
|
|
9159
9787
|
const { editModeActive } = useDirectEditState();
|
|
9160
9788
|
const [rulersVisible, toggleRulers] = useRulersVisible();
|
|
9161
|
-
|
|
9789
|
+
React30.useEffect(() => {
|
|
9162
9790
|
if (!editModeActive) return;
|
|
9163
9791
|
function handleKeyDown(e) {
|
|
9164
9792
|
if (e.shiftKey && e.key === "R" && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
@@ -9176,7 +9804,7 @@ function Rulers() {
|
|
|
9176
9804
|
}
|
|
9177
9805
|
|
|
9178
9806
|
// src/use-toolbar-dock.ts
|
|
9179
|
-
var
|
|
9807
|
+
var React31 = __toESM(require("react"));
|
|
9180
9808
|
var STORAGE_KEY3 = "direct-edit-toolbar-dock";
|
|
9181
9809
|
var EDGE_MARGIN = 8;
|
|
9182
9810
|
var DRAG_THRESHOLD2 = 3;
|
|
@@ -9200,21 +9828,25 @@ function getToolbarBounds(width, height) {
|
|
|
9200
9828
|
const maxY = availableY <= 0 ? 0 : Math.max(minY, availableY - EDGE_MARGIN);
|
|
9201
9829
|
return { minX, maxX, minY, maxY };
|
|
9202
9830
|
}
|
|
9203
|
-
function getDockedPosition(edge, width, height
|
|
9831
|
+
function getDockedPosition(edge, width, height) {
|
|
9204
9832
|
const { minX, maxX, minY, maxY } = getToolbarBounds(width, height);
|
|
9205
|
-
const
|
|
9206
|
-
const
|
|
9833
|
+
const centerX = clamp((window.innerWidth - width) / 2, minX, maxX);
|
|
9834
|
+
const centerY = clamp((window.innerHeight - height) / 2, minY, maxY);
|
|
9207
9835
|
switch (edge) {
|
|
9208
9836
|
case "bottom":
|
|
9209
|
-
return { x:
|
|
9837
|
+
return { x: centerX, y: maxY };
|
|
9210
9838
|
case "top":
|
|
9211
|
-
return { x:
|
|
9839
|
+
return { x: centerX, y: minY };
|
|
9212
9840
|
case "left":
|
|
9213
|
-
return { x: minX, y:
|
|
9841
|
+
return { x: minX, y: centerY };
|
|
9214
9842
|
case "right":
|
|
9215
|
-
return { x: maxX, y:
|
|
9843
|
+
return { x: maxX, y: centerY };
|
|
9216
9844
|
}
|
|
9217
9845
|
}
|
|
9846
|
+
function getInitialDockedPosition(edge) {
|
|
9847
|
+
if (typeof window === "undefined") return { x: 0, y: 0 };
|
|
9848
|
+
return getDockedPosition(edge, 0, 0);
|
|
9849
|
+
}
|
|
9218
9850
|
function getNearestEdge(centerX, centerY) {
|
|
9219
9851
|
const vw = window.innerWidth;
|
|
9220
9852
|
const vh = window.innerHeight;
|
|
@@ -9235,53 +9867,65 @@ function getNearestEdge(centerX, centerY) {
|
|
|
9235
9867
|
return nearest;
|
|
9236
9868
|
}
|
|
9237
9869
|
function useToolbarDock(toolbarRef) {
|
|
9238
|
-
const [dockedEdge, setDockedEdge] =
|
|
9239
|
-
const [phase, setPhase] =
|
|
9240
|
-
const [dragPosition, setDragPosition] =
|
|
9241
|
-
const dragOffsetRef =
|
|
9242
|
-
const
|
|
9243
|
-
const
|
|
9244
|
-
const
|
|
9245
|
-
const
|
|
9246
|
-
const
|
|
9247
|
-
const
|
|
9870
|
+
const [dockedEdge, setDockedEdge] = React31.useState(getInitialEdge);
|
|
9871
|
+
const [phase, setPhase] = React31.useState("docked");
|
|
9872
|
+
const [dragPosition, setDragPosition] = React31.useState(null);
|
|
9873
|
+
const dragOffsetRef = React31.useRef({ x: 0, y: 0 });
|
|
9874
|
+
const pointerStartRef = React31.useRef({ x: 0, y: 0 });
|
|
9875
|
+
const pendingDragRef = React31.useRef(false);
|
|
9876
|
+
const capturedElementRef = React31.useRef(null);
|
|
9877
|
+
const snapTimerRef = React31.useRef(null);
|
|
9878
|
+
const transitionTimerRef = React31.useRef(null);
|
|
9879
|
+
const transitioningRef = React31.useRef(false);
|
|
9880
|
+
const recalcRef = React31.useRef(null);
|
|
9881
|
+
const getDockedPos = React31.useCallback(() => {
|
|
9248
9882
|
const el = toolbarRef.current;
|
|
9249
9883
|
if (!el) return { x: 0, y: 0 };
|
|
9250
9884
|
const rect = el.getBoundingClientRect();
|
|
9251
9885
|
return getDockedPosition(dockedEdge, rect.width, rect.height);
|
|
9252
9886
|
}, [dockedEdge, toolbarRef]);
|
|
9253
|
-
const [dockedPos, setDockedPos] =
|
|
9254
|
-
const [
|
|
9255
|
-
|
|
9887
|
+
const [dockedPos, setDockedPos] = React31.useState(() => getInitialDockedPosition(dockedEdge));
|
|
9888
|
+
const [dockedTransitionEnabled, setDockedTransitionEnabled] = React31.useState(false);
|
|
9889
|
+
React31.useLayoutEffect(() => {
|
|
9256
9890
|
const el = toolbarRef.current;
|
|
9257
9891
|
if (!el) return;
|
|
9892
|
+
setDockedPos(getDockedPos());
|
|
9893
|
+
}, [getDockedPos, toolbarRef]);
|
|
9894
|
+
React31.useEffect(() => {
|
|
9258
9895
|
const raf = requestAnimationFrame(() => {
|
|
9259
|
-
|
|
9260
|
-
dockedPosRef.current = pos;
|
|
9261
|
-
setDockedPos(pos);
|
|
9262
|
-
setReady(true);
|
|
9896
|
+
setDockedTransitionEnabled(true);
|
|
9263
9897
|
});
|
|
9264
9898
|
return () => cancelAnimationFrame(raf);
|
|
9265
|
-
}, [
|
|
9266
|
-
|
|
9899
|
+
}, []);
|
|
9900
|
+
const predictSize = React31.useCallback((width, height) => {
|
|
9901
|
+
transitioningRef.current = true;
|
|
9902
|
+
setDockedPos(getDockedPosition(dockedEdge, width, height));
|
|
9903
|
+
if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
|
|
9904
|
+
transitionTimerRef.current = setTimeout(() => {
|
|
9905
|
+
transitioningRef.current = false;
|
|
9906
|
+
transitionTimerRef.current = null;
|
|
9907
|
+
recalcRef.current?.();
|
|
9908
|
+
}, 350);
|
|
9909
|
+
}, [dockedEdge]);
|
|
9910
|
+
React31.useEffect(() => {
|
|
9267
9911
|
const el = toolbarRef.current;
|
|
9268
9912
|
if (!el) return;
|
|
9269
9913
|
function recalc() {
|
|
9270
|
-
if (!el) return;
|
|
9914
|
+
if (!el || transitioningRef.current) return;
|
|
9271
9915
|
const rect = el.getBoundingClientRect();
|
|
9272
|
-
|
|
9273
|
-
dockedPosRef.current = pos;
|
|
9274
|
-
setDockedPos(pos);
|
|
9916
|
+
setDockedPos(getDockedPosition(dockedEdge, rect.width, rect.height));
|
|
9275
9917
|
}
|
|
9918
|
+
recalcRef.current = recalc;
|
|
9276
9919
|
const ro = new ResizeObserver(recalc);
|
|
9277
9920
|
ro.observe(el);
|
|
9278
9921
|
window.addEventListener("resize", recalc);
|
|
9279
9922
|
return () => {
|
|
9923
|
+
recalcRef.current = null;
|
|
9280
9924
|
ro.disconnect();
|
|
9281
9925
|
window.removeEventListener("resize", recalc);
|
|
9282
9926
|
};
|
|
9283
9927
|
}, [dockedEdge, toolbarRef]);
|
|
9284
|
-
const handlePointerDown =
|
|
9928
|
+
const handlePointerDown = React31.useCallback((e) => {
|
|
9285
9929
|
const el = toolbarRef.current;
|
|
9286
9930
|
if (!el) return;
|
|
9287
9931
|
const rect = el.getBoundingClientRect();
|
|
@@ -9294,7 +9938,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9294
9938
|
} catch {
|
|
9295
9939
|
}
|
|
9296
9940
|
}, [toolbarRef]);
|
|
9297
|
-
const handlePointerMove =
|
|
9941
|
+
const handlePointerMove = React31.useCallback((e) => {
|
|
9298
9942
|
if (!pendingDragRef.current && phase !== "dragging") return;
|
|
9299
9943
|
const dx = e.clientX - pointerStartRef.current.x;
|
|
9300
9944
|
const dy = e.clientY - pointerStartRef.current.y;
|
|
@@ -9311,7 +9955,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9311
9955
|
const newY = Math.max(0, e.clientY - dragOffsetRef.current.y);
|
|
9312
9956
|
setDragPosition({ x: newX, y: newY });
|
|
9313
9957
|
}, [phase]);
|
|
9314
|
-
const handlePointerUp =
|
|
9958
|
+
const handlePointerUp = React31.useCallback((e) => {
|
|
9315
9959
|
if (capturedElementRef.current) {
|
|
9316
9960
|
try {
|
|
9317
9961
|
capturedElementRef.current.releasePointerCapture(e.pointerId);
|
|
@@ -9331,8 +9975,6 @@ function useToolbarDock(toolbarRef) {
|
|
|
9331
9975
|
return;
|
|
9332
9976
|
}
|
|
9333
9977
|
const rect = el.getBoundingClientRect();
|
|
9334
|
-
const width = el.offsetWidth;
|
|
9335
|
-
const height = el.offsetHeight;
|
|
9336
9978
|
const centerX = rect.left + rect.width / 2;
|
|
9337
9979
|
const centerY = rect.top + rect.height / 2;
|
|
9338
9980
|
const newEdge = getNearestEdge(centerX, centerY);
|
|
@@ -9341,9 +9983,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9341
9983
|
localStorage.setItem(STORAGE_KEY3, newEdge);
|
|
9342
9984
|
} catch {
|
|
9343
9985
|
}
|
|
9344
|
-
|
|
9345
|
-
dockedPosRef.current = newPos;
|
|
9346
|
-
setDockedPos(newPos);
|
|
9986
|
+
setDockedPos(getDockedPosition(newEdge, el.offsetWidth, el.offsetHeight));
|
|
9347
9987
|
setPhase("snapping");
|
|
9348
9988
|
setDragPosition(null);
|
|
9349
9989
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
@@ -9352,7 +9992,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9352
9992
|
setPhase("docked");
|
|
9353
9993
|
}, 350);
|
|
9354
9994
|
}, [phase, toolbarRef]);
|
|
9355
|
-
const handlePointerCancel =
|
|
9995
|
+
const handlePointerCancel = React31.useCallback((e) => {
|
|
9356
9996
|
if (capturedElementRef.current) {
|
|
9357
9997
|
try {
|
|
9358
9998
|
capturedElementRef.current.releasePointerCapture(e.pointerId);
|
|
@@ -9366,18 +10006,16 @@ function useToolbarDock(toolbarRef) {
|
|
|
9366
10006
|
setDragPosition(null);
|
|
9367
10007
|
}
|
|
9368
10008
|
}, [phase]);
|
|
9369
|
-
|
|
10009
|
+
React31.useEffect(() => {
|
|
9370
10010
|
return () => {
|
|
9371
10011
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
10012
|
+
if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
|
|
9372
10013
|
};
|
|
9373
10014
|
}, []);
|
|
9374
10015
|
const isDragging = phase === "dragging";
|
|
9375
10016
|
const isSnapping = phase === "snapping";
|
|
9376
|
-
const style =
|
|
9377
|
-
const base = {
|
|
9378
|
-
position: "fixed",
|
|
9379
|
-
...!ready && { visibility: "hidden" }
|
|
9380
|
-
};
|
|
10017
|
+
const style = React31.useMemo(() => {
|
|
10018
|
+
const base = { position: "fixed" };
|
|
9381
10019
|
if (phase === "dragging" && dragPosition) {
|
|
9382
10020
|
return {
|
|
9383
10021
|
...base,
|
|
@@ -9400,14 +10038,18 @@ function useToolbarDock(toolbarRef) {
|
|
|
9400
10038
|
return {
|
|
9401
10039
|
...base,
|
|
9402
10040
|
left: dockedPos.x,
|
|
9403
|
-
top: dockedPos.y
|
|
10041
|
+
top: dockedPos.y,
|
|
10042
|
+
...dockedTransitionEnabled && {
|
|
10043
|
+
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"
|
|
10044
|
+
}
|
|
9404
10045
|
};
|
|
9405
|
-
}, [phase, dragPosition, dockedPos,
|
|
10046
|
+
}, [phase, dragPosition, dockedPos, dockedTransitionEnabled]);
|
|
9406
10047
|
return {
|
|
9407
10048
|
dockedEdge,
|
|
9408
10049
|
isDragging,
|
|
9409
10050
|
isSnapping,
|
|
9410
10051
|
style,
|
|
10052
|
+
predictSize,
|
|
9411
10053
|
handlePointerDown,
|
|
9412
10054
|
handlePointerMove,
|
|
9413
10055
|
handlePointerUp,
|
|
@@ -9416,16 +10058,16 @@ function useToolbarDock(toolbarRef) {
|
|
|
9416
10058
|
}
|
|
9417
10059
|
|
|
9418
10060
|
// src/toolbar.tsx
|
|
9419
|
-
var
|
|
10061
|
+
var import_lucide_react16 = require("lucide-react");
|
|
9420
10062
|
|
|
9421
10063
|
// src/toolbar/edits-popover.tsx
|
|
9422
|
-
var
|
|
10064
|
+
var React33 = __toESM(require("react"));
|
|
9423
10065
|
var import_button7 = require("@base-ui/react/button");
|
|
9424
10066
|
var import_popover2 = require("@base-ui/react/popover");
|
|
9425
10067
|
var import_lucide_react13 = require("lucide-react");
|
|
9426
10068
|
|
|
9427
10069
|
// src/ui/badge.tsx
|
|
9428
|
-
var
|
|
10070
|
+
var React32 = __toESM(require("react"));
|
|
9429
10071
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
9430
10072
|
var badgeVariants = {
|
|
9431
10073
|
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",
|
|
@@ -9435,7 +10077,7 @@ var badgeVariants = {
|
|
|
9435
10077
|
outline: "border-border bg-transparent text-foreground"
|
|
9436
10078
|
}
|
|
9437
10079
|
};
|
|
9438
|
-
var Badge =
|
|
10080
|
+
var Badge = React32.forwardRef(
|
|
9439
10081
|
({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
9440
10082
|
"div",
|
|
9441
10083
|
{
|
|
@@ -9461,14 +10103,11 @@ function truncateText(value, max = 64) {
|
|
|
9461
10103
|
if (value.length <= max) return value;
|
|
9462
10104
|
return `${value.slice(0, max)}...`;
|
|
9463
10105
|
}
|
|
9464
|
-
function isWithinFocusRegion(nextTarget, ...elements) {
|
|
9465
|
-
if (!(nextTarget instanceof Node)) return false;
|
|
9466
|
-
return elements.some((element) => Boolean(element?.contains(nextTarget)));
|
|
9467
|
-
}
|
|
9468
10106
|
function EditsPopover({
|
|
9469
10107
|
tooltipSide,
|
|
9470
10108
|
sessionEditCount,
|
|
9471
|
-
|
|
10109
|
+
isOpen,
|
|
10110
|
+
onOpenChange,
|
|
9472
10111
|
onGetSessionItems,
|
|
9473
10112
|
onExportAllEdits,
|
|
9474
10113
|
onSendAllToAgents,
|
|
@@ -9476,20 +10115,18 @@ function EditsPopover({
|
|
|
9476
10115
|
onRemoveSessionEdit,
|
|
9477
10116
|
onDeleteComment
|
|
9478
10117
|
}) {
|
|
9479
|
-
const [
|
|
9480
|
-
const [
|
|
9481
|
-
const
|
|
9482
|
-
const
|
|
9483
|
-
const
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
React32.useEffect(() => {
|
|
9487
|
-
if (!editsOpen) return;
|
|
10118
|
+
const [copied, setCopied] = React33.useState(false);
|
|
10119
|
+
const [sendStatus, setSendStatus] = React33.useState("idle");
|
|
10120
|
+
const editsPopupRef = React33.useRef(null);
|
|
10121
|
+
const editsTriggerRef = React33.useRef(null);
|
|
10122
|
+
const [editsSnapshot, setEditsSnapshot] = React33.useState([]);
|
|
10123
|
+
React33.useEffect(() => {
|
|
10124
|
+
if (!isOpen) return;
|
|
9488
10125
|
function handlePointerDown(e) {
|
|
9489
10126
|
const path = e.composedPath();
|
|
9490
10127
|
if (editsPopupRef.current && path.includes(editsPopupRef.current)) return;
|
|
9491
10128
|
if (editsTriggerRef.current && path.includes(editsTriggerRef.current)) return;
|
|
9492
|
-
|
|
10129
|
+
onOpenChange(false);
|
|
9493
10130
|
}
|
|
9494
10131
|
const raf = requestAnimationFrame(() => {
|
|
9495
10132
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
@@ -9498,42 +10135,19 @@ function EditsPopover({
|
|
|
9498
10135
|
cancelAnimationFrame(raf);
|
|
9499
10136
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
9500
10137
|
};
|
|
9501
|
-
}, [
|
|
9502
|
-
|
|
9503
|
-
if (
|
|
10138
|
+
}, [isOpen, onOpenChange]);
|
|
10139
|
+
React33.useEffect(() => {
|
|
10140
|
+
if (isOpen && onGetSessionItems) {
|
|
9504
10141
|
setEditsSnapshot(onGetSessionItems());
|
|
9505
10142
|
}
|
|
9506
|
-
}, [
|
|
9507
|
-
|
|
9508
|
-
return () => {
|
|
9509
|
-
if (editsCloseTimerRef.current !== null) {
|
|
9510
|
-
window.clearTimeout(editsCloseTimerRef.current);
|
|
9511
|
-
}
|
|
9512
|
-
};
|
|
9513
|
-
}, []);
|
|
9514
|
-
React32.useEffect(() => {
|
|
9515
|
-
if (isDragging) setEditsOpen(false);
|
|
9516
|
-
}, [isDragging]);
|
|
9517
|
-
const clearEditsCloseTimer = React32.useCallback(() => {
|
|
9518
|
-
if (editsCloseTimerRef.current !== null) {
|
|
9519
|
-
window.clearTimeout(editsCloseTimerRef.current);
|
|
9520
|
-
editsCloseTimerRef.current = null;
|
|
9521
|
-
}
|
|
9522
|
-
}, []);
|
|
9523
|
-
const scheduleEditsClose = React32.useCallback(() => {
|
|
9524
|
-
clearEditsCloseTimer();
|
|
9525
|
-
editsCloseTimerRef.current = window.setTimeout(() => {
|
|
9526
|
-
setEditsOpen(false);
|
|
9527
|
-
editsCloseTimerRef.current = null;
|
|
9528
|
-
}, 120);
|
|
9529
|
-
}, [clearEditsCloseTimer]);
|
|
9530
|
-
const handleCopyAll = React32.useCallback(async () => {
|
|
10143
|
+
}, [isOpen, onGetSessionItems]);
|
|
10144
|
+
const handleCopyAll = React33.useCallback(async () => {
|
|
9531
10145
|
const success = await onExportAllEdits?.();
|
|
9532
10146
|
if (!success) return;
|
|
9533
10147
|
setCopied(true);
|
|
9534
10148
|
window.setTimeout(() => setCopied(false), 2e3);
|
|
9535
10149
|
}, [onExportAllEdits]);
|
|
9536
|
-
const handleSendAll =
|
|
10150
|
+
const handleSendAll = React33.useCallback(async () => {
|
|
9537
10151
|
if (!onSendAllToAgents || sendStatus === "sending") return;
|
|
9538
10152
|
setSendStatus("sending");
|
|
9539
10153
|
let success = false;
|
|
@@ -9550,7 +10164,7 @@ function EditsPopover({
|
|
|
9550
10164
|
setSendStatus("offline");
|
|
9551
10165
|
window.setTimeout(() => setSendStatus("idle"), 2e3);
|
|
9552
10166
|
}, [onSendAllToAgents, sendStatus]);
|
|
9553
|
-
const handleCopyItem =
|
|
10167
|
+
const handleCopyItem = React33.useCallback(async (item) => {
|
|
9554
10168
|
const text = item.type === "edit" ? buildSessionExport([item.edit], []) : buildSessionExport([], [item.comment]);
|
|
9555
10169
|
try {
|
|
9556
10170
|
await navigator.clipboard.writeText(`implement the visual edits
|
|
@@ -9561,52 +10175,33 @@ ${text}`);
|
|
|
9561
10175
|
} catch {
|
|
9562
10176
|
}
|
|
9563
10177
|
}, []);
|
|
9564
|
-
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_popover2.Popover.Root, { open:
|
|
9565
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
clearEditsCloseTimer();
|
|
9581
|
-
if (e.currentTarget.matches(":focus-visible")) {
|
|
9582
|
-
setEditsOpen(true);
|
|
10178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange, children: [
|
|
10179
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10180
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_popover2.Popover.Trigger, { render: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
10181
|
+
"button",
|
|
10182
|
+
{
|
|
10183
|
+
ref: editsTriggerRef,
|
|
10184
|
+
type: "button",
|
|
10185
|
+
className: cn(
|
|
10186
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10187
|
+
sessionEditCount > 0 || isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10188
|
+
),
|
|
10189
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10190
|
+
onClick: (e) => {
|
|
10191
|
+
e.preventDefault();
|
|
10192
|
+
e.stopPropagation();
|
|
10193
|
+
onOpenChange(!isOpen);
|
|
9583
10194
|
}
|
|
9584
|
-
},
|
|
9585
|
-
onBlur: (e) => {
|
|
9586
|
-
if (isWithinFocusRegion(e.relatedTarget, editsTriggerRef.current, editsPopupRef.current)) return;
|
|
9587
|
-
scheduleEditsClose();
|
|
9588
|
-
},
|
|
9589
|
-
onClick: (e) => {
|
|
9590
|
-
e.preventDefault();
|
|
9591
|
-
e.stopPropagation();
|
|
9592
|
-
clearEditsCloseTimer();
|
|
9593
|
-
setEditsOpen((prev) => !prev);
|
|
9594
10195
|
}
|
|
9595
|
-
}
|
|
9596
|
-
|
|
10196
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react13.Copy, { className: "size-4" }) }),
|
|
10197
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Export edits" }) })
|
|
10198
|
+
] }),
|
|
9597
10199
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(EditsPopoverPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_popover2.Popover.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
9598
10200
|
import_popover2.Popover.Popup,
|
|
9599
10201
|
{
|
|
9600
10202
|
ref: editsPopupRef,
|
|
9601
10203
|
className: "w-[340px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
9602
10204
|
onPointerDown: (e) => e.stopPropagation(),
|
|
9603
|
-
onPointerEnter: clearEditsCloseTimer,
|
|
9604
|
-
onPointerLeave: scheduleEditsClose,
|
|
9605
|
-
onFocus: clearEditsCloseTimer,
|
|
9606
|
-
onBlur: (e) => {
|
|
9607
|
-
if (isWithinFocusRegion(e.relatedTarget, editsTriggerRef.current, editsPopupRef.current)) return;
|
|
9608
|
-
scheduleEditsClose();
|
|
9609
|
-
},
|
|
9610
10205
|
children: [
|
|
9611
10206
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between px-3 pb-1 pt-2.5", children: [
|
|
9612
10207
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs font-medium text-foreground", children: "Copy to AI agents" }),
|
|
@@ -9737,38 +10332,200 @@ ${text}`);
|
|
|
9737
10332
|
}
|
|
9738
10333
|
|
|
9739
10334
|
// src/toolbar/settings-popover.tsx
|
|
9740
|
-
var
|
|
9741
|
-
var
|
|
9742
|
-
var import_popover3 = require("@base-ui/react/popover");
|
|
10335
|
+
var React34 = __toESM(require("react"));
|
|
10336
|
+
var import_menu = require("@base-ui/react/menu");
|
|
9743
10337
|
var import_lucide_react14 = require("lucide-react");
|
|
9744
10338
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
9745
|
-
function
|
|
10339
|
+
function SettingsMenuPortal(props) {
|
|
9746
10340
|
const container = usePortalContainer();
|
|
9747
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
9748
|
-
}
|
|
9749
|
-
function isWithinFocusRegion2(nextTarget, ...elements) {
|
|
9750
|
-
if (!(nextTarget instanceof Node)) return false;
|
|
9751
|
-
return elements.some((element) => Boolean(element?.contains(nextTarget)));
|
|
10341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_menu.Menu.Portal, { container, ...props });
|
|
9752
10342
|
}
|
|
9753
10343
|
function SettingsPopover({
|
|
9754
10344
|
tooltipSide,
|
|
9755
10345
|
theme,
|
|
9756
10346
|
isMac,
|
|
9757
|
-
|
|
10347
|
+
isOpen,
|
|
10348
|
+
onOpenChange,
|
|
9758
10349
|
onSetTheme
|
|
9759
10350
|
}) {
|
|
9760
|
-
const
|
|
9761
|
-
const settingsPopupRef =
|
|
9762
|
-
const
|
|
9763
|
-
const
|
|
9764
|
-
const
|
|
9765
|
-
|
|
9766
|
-
|
|
10351
|
+
const settingsTriggerRef = React34.useRef(null);
|
|
10352
|
+
const settingsPopupRef = React34.useRef(null);
|
|
10353
|
+
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";
|
|
10354
|
+
const popupTitleClass = "flex h-8 items-center px-3 text-xs font-medium text-foreground";
|
|
10355
|
+
const submenuSide = tooltipSide === "left" ? "left" : "right";
|
|
10356
|
+
const centeredSubmenuCollision = React34.useMemo(
|
|
10357
|
+
() => ({ side: "flip", align: "none", fallbackAxisSide: "none" }),
|
|
10358
|
+
[]
|
|
10359
|
+
);
|
|
10360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.Root, { open: isOpen, onOpenChange, modal: false, children: [
|
|
10361
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10362
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TooltipTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_menu.Menu.Trigger, { render: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
10363
|
+
"button",
|
|
10364
|
+
{
|
|
10365
|
+
ref: settingsTriggerRef,
|
|
10366
|
+
type: "button",
|
|
10367
|
+
className: cn(
|
|
10368
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10369
|
+
isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10370
|
+
),
|
|
10371
|
+
onPointerDown: (e) => e.stopPropagation()
|
|
10372
|
+
}
|
|
10373
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.EllipsisVertical, { className: "size-4" }) }),
|
|
10374
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: "Preferences" }) })
|
|
10375
|
+
] }),
|
|
10376
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SettingsMenuPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_menu.Menu.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10377
|
+
import_menu.Menu.Popup,
|
|
10378
|
+
{
|
|
10379
|
+
ref: settingsPopupRef,
|
|
10380
|
+
className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
10381
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10382
|
+
children: [
|
|
10383
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: popupTitleClass, children: "Preferences" }),
|
|
10384
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "px-1 pb-1", children: [
|
|
10385
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.SubmenuRoot, { children: [
|
|
10386
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10387
|
+
import_menu.Menu.SubmenuTrigger,
|
|
10388
|
+
{
|
|
10389
|
+
openOnHover: false,
|
|
10390
|
+
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",
|
|
10391
|
+
children: [
|
|
10392
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Monitor, { className: "size-3.5" }),
|
|
10393
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex-1", children: "Theme" }),
|
|
10394
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ChevronRight, { className: "size-3.5" })
|
|
10395
|
+
]
|
|
10396
|
+
}
|
|
10397
|
+
),
|
|
10398
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SettingsMenuPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
10399
|
+
import_menu.Menu.Positioner,
|
|
10400
|
+
{
|
|
10401
|
+
anchor: settingsPopupRef,
|
|
10402
|
+
side: submenuSide,
|
|
10403
|
+
align: "center",
|
|
10404
|
+
sideOffset: 6,
|
|
10405
|
+
collisionAvoidance: centeredSubmenuCollision,
|
|
10406
|
+
className: "fixed z-[99999]",
|
|
10407
|
+
style: { pointerEvents: "auto" },
|
|
10408
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10409
|
+
import_menu.Menu.Popup,
|
|
10410
|
+
{
|
|
10411
|
+
className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
10412
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10413
|
+
children: [
|
|
10414
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: popupTitleClass, children: "Theme" }),
|
|
10415
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-1 pb-1", children: [
|
|
10416
|
+
{ value: "light", label: "Light", Icon: import_lucide_react14.Sun },
|
|
10417
|
+
{ value: "dark", label: "Dark", Icon: import_lucide_react14.Moon },
|
|
10418
|
+
{ value: "system", label: "System", Icon: import_lucide_react14.Monitor }
|
|
10419
|
+
].map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10420
|
+
import_menu.Menu.Item,
|
|
10421
|
+
{
|
|
10422
|
+
className: cn(
|
|
10423
|
+
"flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs transition-colors",
|
|
10424
|
+
theme === value ? "bg-muted text-foreground" : "text-muted-foreground data-[highlighted]:bg-muted/50 data-[highlighted]:text-foreground"
|
|
10425
|
+
),
|
|
10426
|
+
onClick: () => {
|
|
10427
|
+
onSetTheme?.(value);
|
|
10428
|
+
onOpenChange(false);
|
|
10429
|
+
},
|
|
10430
|
+
children: [
|
|
10431
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "size-3.5" }),
|
|
10432
|
+
label
|
|
10433
|
+
]
|
|
10434
|
+
},
|
|
10435
|
+
value
|
|
10436
|
+
)) })
|
|
10437
|
+
]
|
|
10438
|
+
}
|
|
10439
|
+
)
|
|
10440
|
+
}
|
|
10441
|
+
) })
|
|
10442
|
+
] }),
|
|
10443
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.SubmenuRoot, { children: [
|
|
10444
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10445
|
+
import_menu.Menu.SubmenuTrigger,
|
|
10446
|
+
{
|
|
10447
|
+
openOnHover: false,
|
|
10448
|
+
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",
|
|
10449
|
+
children: [
|
|
10450
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Keyboard, { className: "size-3.5" }),
|
|
10451
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex-1", children: "Keyboard shortcuts" }),
|
|
10452
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ChevronRight, { className: "size-3.5" })
|
|
10453
|
+
]
|
|
10454
|
+
}
|
|
10455
|
+
),
|
|
10456
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SettingsMenuPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
10457
|
+
import_menu.Menu.Positioner,
|
|
10458
|
+
{
|
|
10459
|
+
anchor: settingsPopupRef,
|
|
10460
|
+
side: submenuSide,
|
|
10461
|
+
align: "center",
|
|
10462
|
+
sideOffset: 6,
|
|
10463
|
+
collisionAvoidance: centeredSubmenuCollision,
|
|
10464
|
+
className: "fixed z-[99999]",
|
|
10465
|
+
style: { pointerEvents: "auto" },
|
|
10466
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10467
|
+
import_menu.Menu.Popup,
|
|
10468
|
+
{
|
|
10469
|
+
className: "w-[300px] rounded-xl bg-background text-[11px] outline outline-1 outline-foreground/10 shadow-lg",
|
|
10470
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10471
|
+
children: [
|
|
10472
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex h-7 items-center px-3 text-[11px] font-medium text-foreground", children: "Keyboard Shortcuts" }),
|
|
10473
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-1 pb-1", children: [
|
|
10474
|
+
{ label: "Toggle design mode", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Command, { className: "size-2.5" }, "cmd"), "."] : ["Ctrl", "."] },
|
|
10475
|
+
{ label: "Undo", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Command, { className: "size-2.5" }, "cmd"), "Z"] : ["Ctrl", "Z"] },
|
|
10476
|
+
{ label: "Toggle comments", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "C"] },
|
|
10477
|
+
{ label: "Toggle rulers", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "R"] },
|
|
10478
|
+
{ label: "Toggle canvas mode", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "Z"] },
|
|
10479
|
+
{ label: "Hover to measure", keys: isMac ? ["Hold", /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Option, { className: "size-2.5" }, "opt")] : ["Hold", "Alt"] },
|
|
10480
|
+
{ label: "Back / Exit", keys: ["Esc"] }
|
|
10481
|
+
].map(({ label, keys }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex h-7 w-full items-center justify-between rounded-md px-2 text-[11px] text-muted-foreground", children: [
|
|
10482
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: label }),
|
|
10483
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex items-center gap-1", children: keys.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("kbd", { className: popupKbdClass, children: k }, typeof k === "string" ? k : i)) })
|
|
10484
|
+
] }, label)) })
|
|
10485
|
+
]
|
|
10486
|
+
}
|
|
10487
|
+
)
|
|
10488
|
+
}
|
|
10489
|
+
) })
|
|
10490
|
+
] })
|
|
10491
|
+
] })
|
|
10492
|
+
]
|
|
10493
|
+
}
|
|
10494
|
+
) }) })
|
|
10495
|
+
] });
|
|
10496
|
+
}
|
|
10497
|
+
|
|
10498
|
+
// src/toolbar/zoom-popover.tsx
|
|
10499
|
+
var React35 = __toESM(require("react"));
|
|
10500
|
+
var import_button8 = require("@base-ui/react/button");
|
|
10501
|
+
var import_popover3 = require("@base-ui/react/popover");
|
|
10502
|
+
var import_lucide_react15 = require("lucide-react");
|
|
10503
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
10504
|
+
function ZoomPopoverPortal(props) {
|
|
10505
|
+
const container = usePortalContainer();
|
|
10506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_popover3.Popover.Portal, { container, ...props });
|
|
10507
|
+
}
|
|
10508
|
+
function ZoomPopover({
|
|
10509
|
+
tooltipSide,
|
|
10510
|
+
canvasActive,
|
|
10511
|
+
canvasZoom,
|
|
10512
|
+
isOpen,
|
|
10513
|
+
onOpenChange,
|
|
10514
|
+
onToggleCanvas,
|
|
10515
|
+
onSetCanvasZoom,
|
|
10516
|
+
onZoomTo100,
|
|
10517
|
+
onFitToViewport
|
|
10518
|
+
}) {
|
|
10519
|
+
const popupRef = React35.useRef(null);
|
|
10520
|
+
const triggerRef = React35.useRef(null);
|
|
10521
|
+
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]";
|
|
10522
|
+
React35.useEffect(() => {
|
|
10523
|
+
if (!isOpen) return;
|
|
9767
10524
|
function handlePointerDown(e) {
|
|
9768
10525
|
const path = e.composedPath();
|
|
9769
|
-
if (
|
|
9770
|
-
if (
|
|
9771
|
-
|
|
10526
|
+
if (popupRef.current && path.includes(popupRef.current)) return;
|
|
10527
|
+
if (triggerRef.current && path.includes(triggerRef.current)) return;
|
|
10528
|
+
onOpenChange(false);
|
|
9772
10529
|
}
|
|
9773
10530
|
const raf = requestAnimationFrame(() => {
|
|
9774
10531
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
@@ -9777,121 +10534,90 @@ function SettingsPopover({
|
|
|
9777
10534
|
cancelAnimationFrame(raf);
|
|
9778
10535
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
9779
10536
|
};
|
|
9780
|
-
}, [
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
const scheduleSettingsClose = React33.useCallback(() => {
|
|
9798
|
-
clearSettingsCloseTimer();
|
|
9799
|
-
settingsCloseTimerRef.current = window.setTimeout(() => {
|
|
9800
|
-
setSettingsOpen(false);
|
|
9801
|
-
settingsCloseTimerRef.current = null;
|
|
9802
|
-
}, 120);
|
|
9803
|
-
}, [clearSettingsCloseTimer]);
|
|
9804
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_popover3.Popover.Root, { open: settingsOpen, onOpenChange: setSettingsOpen, children: [
|
|
9805
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_popover3.Popover.Trigger, { ref: settingsTriggerRef, render: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
9806
|
-
"button",
|
|
9807
|
-
{
|
|
9808
|
-
type: "button",
|
|
9809
|
-
className: cn(
|
|
9810
|
-
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
9811
|
-
settingsOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
9812
|
-
),
|
|
9813
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
9814
|
-
onPointerEnter: () => {
|
|
9815
|
-
clearSettingsCloseTimer();
|
|
9816
|
-
setSettingsOpen(true);
|
|
9817
|
-
},
|
|
9818
|
-
onPointerLeave: scheduleSettingsClose,
|
|
9819
|
-
onFocus: (e) => {
|
|
9820
|
-
clearSettingsCloseTimer();
|
|
9821
|
-
if (e.currentTarget.matches(":focus-visible")) {
|
|
9822
|
-
setSettingsOpen(true);
|
|
10537
|
+
}, [isOpen, onOpenChange]);
|
|
10538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_popover3.Popover.Root, { open: isOpen, onOpenChange, children: [
|
|
10539
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10540
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_popover3.Popover.Trigger, { render: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
10541
|
+
"button",
|
|
10542
|
+
{
|
|
10543
|
+
ref: triggerRef,
|
|
10544
|
+
type: "button",
|
|
10545
|
+
className: cn(
|
|
10546
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10547
|
+
isOpen ? "bg-muted text-foreground" : canvasActive ? "bg-muted text-foreground hover:bg-muted/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10548
|
+
),
|
|
10549
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10550
|
+
onClick: (e) => {
|
|
10551
|
+
e.preventDefault();
|
|
10552
|
+
e.stopPropagation();
|
|
10553
|
+
onOpenChange(!isOpen);
|
|
9823
10554
|
}
|
|
9824
|
-
},
|
|
9825
|
-
onBlur: (e) => {
|
|
9826
|
-
if (isWithinFocusRegion2(e.relatedTarget, settingsTriggerRef.current, settingsPopupRef.current)) return;
|
|
9827
|
-
scheduleSettingsClose();
|
|
9828
|
-
},
|
|
9829
|
-
onClick: (e) => {
|
|
9830
|
-
e.preventDefault();
|
|
9831
|
-
e.stopPropagation();
|
|
9832
|
-
clearSettingsCloseTimer();
|
|
9833
|
-
setSettingsOpen((prev) => !prev);
|
|
9834
10555
|
}
|
|
9835
|
-
}
|
|
9836
|
-
|
|
9837
|
-
|
|
10556
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Maximize2, { className: "size-4" }) }),
|
|
10557
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10558
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Canvas mode" }),
|
|
10559
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.ArrowBigUp, { className: "size-2.5" }) }),
|
|
10560
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: kbdClass, children: "Z" })
|
|
10561
|
+
] })
|
|
10562
|
+
] }),
|
|
10563
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ZoomPopoverPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_popover3.Popover.Positioner, { side: tooltipSide, sideOffset: 12, className: "fixed z-[99999]", style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
9838
10564
|
import_popover3.Popover.Popup,
|
|
9839
10565
|
{
|
|
9840
|
-
ref:
|
|
9841
|
-
className: "w-[
|
|
10566
|
+
ref: popupRef,
|
|
10567
|
+
className: "w-[180px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
9842
10568
|
onPointerDown: (e) => e.stopPropagation(),
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
onFocus: clearSettingsCloseTimer,
|
|
9846
|
-
onBlur: (e) => {
|
|
9847
|
-
if (isWithinFocusRegion2(e.relatedTarget, settingsTriggerRef.current, settingsPopupRef.current)) return;
|
|
9848
|
-
scheduleSettingsClose();
|
|
9849
|
-
},
|
|
9850
|
-
children: [
|
|
9851
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-3 pb-1 pt-2.5 text-xs font-medium text-foreground", children: "Theme" }),
|
|
9852
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-1 pb-1", children: [
|
|
9853
|
-
{ value: "light", label: "Light", Icon: import_lucide_react14.Sun },
|
|
9854
|
-
{ value: "dark", label: "Dark", Icon: import_lucide_react14.Moon },
|
|
9855
|
-
{ value: "system", label: "System", Icon: import_lucide_react14.Monitor }
|
|
9856
|
-
].map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10569
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "px-1 py-1", children: [
|
|
10570
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
9857
10571
|
import_button8.Button,
|
|
9858
10572
|
{
|
|
9859
|
-
className:
|
|
9860
|
-
"flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs transition-colors",
|
|
9861
|
-
theme === value ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
|
|
9862
|
-
),
|
|
10573
|
+
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",
|
|
9863
10574
|
onClick: () => {
|
|
9864
|
-
|
|
9865
|
-
|
|
10575
|
+
onZoomTo100?.();
|
|
10576
|
+
onOpenChange(false);
|
|
9866
10577
|
},
|
|
9867
10578
|
children: [
|
|
9868
|
-
/* @__PURE__ */ (0,
|
|
9869
|
-
|
|
10579
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Scan, { className: "size-3.5" }),
|
|
10580
|
+
"Actual size (100%)"
|
|
9870
10581
|
]
|
|
9871
|
-
}
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
10582
|
+
}
|
|
10583
|
+
),
|
|
10584
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
10585
|
+
import_button8.Button,
|
|
10586
|
+
{
|
|
10587
|
+
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",
|
|
10588
|
+
onClick: () => {
|
|
10589
|
+
onFitToViewport?.();
|
|
10590
|
+
onOpenChange(false);
|
|
10591
|
+
},
|
|
10592
|
+
children: [
|
|
10593
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Minimize2, { className: "size-3.5" }),
|
|
10594
|
+
"Fit to viewport"
|
|
10595
|
+
]
|
|
10596
|
+
}
|
|
10597
|
+
),
|
|
10598
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "my-1 border-t border-foreground/10" }),
|
|
10599
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
10600
|
+
import_button8.Button,
|
|
10601
|
+
{
|
|
10602
|
+
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",
|
|
10603
|
+
onClick: () => {
|
|
10604
|
+
onToggleCanvas?.();
|
|
10605
|
+
onOpenChange(false);
|
|
10606
|
+
},
|
|
10607
|
+
children: [
|
|
10608
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Check, { className: cn("size-3.5", canvasActive ? "opacity-100" : "opacity-0") }),
|
|
10609
|
+
"Canvas mode"
|
|
10610
|
+
]
|
|
10611
|
+
}
|
|
10612
|
+
)
|
|
10613
|
+
] })
|
|
9888
10614
|
}
|
|
9889
10615
|
) }) })
|
|
9890
10616
|
] });
|
|
9891
10617
|
}
|
|
9892
10618
|
|
|
9893
10619
|
// src/toolbar.tsx
|
|
9894
|
-
var
|
|
10620
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
9895
10621
|
function DirectEditToolbarInner({
|
|
9896
10622
|
editModeActive,
|
|
9897
10623
|
onToggleEditMode,
|
|
@@ -9908,33 +10634,63 @@ function DirectEditToolbarInner({
|
|
|
9908
10634
|
onClearSessionEdits,
|
|
9909
10635
|
onRemoveSessionEdit,
|
|
9910
10636
|
onDeleteComment,
|
|
9911
|
-
className
|
|
10637
|
+
className,
|
|
10638
|
+
canvasActive = false,
|
|
10639
|
+
canvasZoom = 1,
|
|
10640
|
+
onToggleCanvas,
|
|
10641
|
+
onSetCanvasZoom,
|
|
10642
|
+
onZoomTo100,
|
|
10643
|
+
onFitToViewport
|
|
9912
10644
|
}) {
|
|
9913
10645
|
const container = usePortalContainer();
|
|
9914
|
-
const toolbarRef =
|
|
9915
|
-
const { dockedEdge, isDragging, isSnapping, style: dockStyle, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
|
|
10646
|
+
const toolbarRef = React36.useRef(null);
|
|
10647
|
+
const { dockedEdge, isDragging, isSnapping, style: dockStyle, predictSize, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
|
|
9916
10648
|
const isVertical = dockedEdge === "left" || dockedEdge === "right";
|
|
10649
|
+
const [activePopover, setActivePopover] = React36.useState(null);
|
|
10650
|
+
const sizeCacheRef = React36.useRef({});
|
|
10651
|
+
React36.useEffect(() => {
|
|
10652
|
+
const el = toolbarRef.current;
|
|
10653
|
+
if (!el) return;
|
|
10654
|
+
const key = `${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`;
|
|
10655
|
+
const timer = setTimeout(() => {
|
|
10656
|
+
const rect = el.getBoundingClientRect();
|
|
10657
|
+
sizeCacheRef.current[key] = { w: rect.width, h: rect.height };
|
|
10658
|
+
}, 350);
|
|
10659
|
+
return () => clearTimeout(timer);
|
|
10660
|
+
}, [editModeActive, dockedEdge]);
|
|
10661
|
+
const prevEditModeRef = React36.useRef(editModeActive);
|
|
10662
|
+
React36.useEffect(() => {
|
|
10663
|
+
if (prevEditModeRef.current === editModeActive) return;
|
|
10664
|
+
prevEditModeRef.current = editModeActive;
|
|
10665
|
+
const target = sizeCacheRef.current[`${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`];
|
|
10666
|
+
if (target) {
|
|
10667
|
+
predictSize(target.w, target.h);
|
|
10668
|
+
}
|
|
10669
|
+
}, [editModeActive, dockedEdge, predictSize]);
|
|
10670
|
+
React36.useEffect(() => {
|
|
10671
|
+
if (isDragging) setActivePopover(null);
|
|
10672
|
+
}, [isDragging]);
|
|
10673
|
+
React36.useEffect(() => {
|
|
10674
|
+
if (!editModeActive) setActivePopover(null);
|
|
10675
|
+
}, [editModeActive]);
|
|
9917
10676
|
const tooltipSide = dockedEdge === "bottom" ? "top" : dockedEdge === "top" ? "bottom" : dockedEdge === "left" ? "right" : "left";
|
|
9918
|
-
const [isMac
|
|
9919
|
-
React34.useEffect(() => {
|
|
9920
|
-
setIsMac(navigator.platform?.includes("Mac") ?? false);
|
|
9921
|
-
}, []);
|
|
10677
|
+
const [isMac] = React36.useState(() => typeof navigator !== "undefined" ? navigator.platform?.includes("Mac") ?? false : false);
|
|
9922
10678
|
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]";
|
|
9923
|
-
const shortcutContent = isMac ? /* @__PURE__ */ (0,
|
|
9924
|
-
/* @__PURE__ */ (0,
|
|
9925
|
-
/* @__PURE__ */ (0,
|
|
9926
|
-
] }) : /* @__PURE__ */ (0,
|
|
9927
|
-
/* @__PURE__ */ (0,
|
|
9928
|
-
/* @__PURE__ */ (0,
|
|
10679
|
+
const shortcutContent = isMac ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
10680
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Command, { className: "size-2.5" }) }),
|
|
10681
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "." })
|
|
10682
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
10683
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "Ctrl" }),
|
|
10684
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "." })
|
|
9929
10685
|
] });
|
|
9930
|
-
const toolbar = /* @__PURE__ */ (0,
|
|
10686
|
+
const toolbar = /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
9931
10687
|
"div",
|
|
9932
10688
|
{
|
|
9933
10689
|
ref: toolbarRef,
|
|
9934
10690
|
"data-direct-edit": "toolbar",
|
|
9935
10691
|
style: { pointerEvents: "auto", touchAction: "none", ...dockStyle },
|
|
9936
10692
|
className: cn(
|
|
9937
|
-
"group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg
|
|
10693
|
+
"group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg",
|
|
9938
10694
|
isVertical ? "flex-col items-center" : "flex-row items-center",
|
|
9939
10695
|
isDragging && "cursor-grabbing select-none shadow-2xl",
|
|
9940
10696
|
className
|
|
@@ -9945,21 +10701,21 @@ function DirectEditToolbarInner({
|
|
|
9945
10701
|
onPointerCancel: handlePointerCancel,
|
|
9946
10702
|
onLostPointerCapture: handlePointerCancel,
|
|
9947
10703
|
children: [
|
|
9948
|
-
/* @__PURE__ */ (0,
|
|
10704
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
9949
10705
|
"flex shrink-0 cursor-grab items-center justify-center",
|
|
9950
10706
|
isVertical ? "w-full pt-0 pb-1.5" : "h-full pl-0 pr-1.5"
|
|
9951
|
-
), children: /* @__PURE__ */ (0,
|
|
10707
|
+
), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
9952
10708
|
"shrink-0 rounded-full bg-foreground/25",
|
|
9953
10709
|
isVertical ? "h-0.5 w-4" : "h-4 w-0.5"
|
|
9954
10710
|
) }) }),
|
|
9955
|
-
/* @__PURE__ */ (0,
|
|
9956
|
-
/* @__PURE__ */ (0,
|
|
9957
|
-
/* @__PURE__ */ (0,
|
|
10711
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipProvider, { delayDuration: 200, children: [
|
|
10712
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10713
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
9958
10714
|
TooltipTrigger,
|
|
9959
10715
|
{
|
|
9960
10716
|
className: cn(
|
|
9961
|
-
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-
|
|
9962
|
-
editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" :
|
|
10717
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-[color,background-color] duration-150 ease-out",
|
|
10718
|
+
editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
9963
10719
|
),
|
|
9964
10720
|
onPointerDown: (e) => e.stopPropagation(),
|
|
9965
10721
|
onClick: () => {
|
|
@@ -9969,89 +10725,144 @@ function DirectEditToolbarInner({
|
|
|
9969
10725
|
onToggleEditMode();
|
|
9970
10726
|
}
|
|
9971
10727
|
},
|
|
9972
|
-
children: /* @__PURE__ */ (0,
|
|
10728
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.MousePointer2, { className: "size-4" })
|
|
9973
10729
|
}
|
|
9974
10730
|
),
|
|
9975
|
-
/* @__PURE__ */ (0,
|
|
9976
|
-
/* @__PURE__ */ (0,
|
|
10731
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10732
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: editModeActive ? "Select" : "Activate design mode" }),
|
|
9977
10733
|
shortcutContent
|
|
9978
10734
|
] })
|
|
9979
10735
|
] }),
|
|
9980
|
-
/* @__PURE__ */ (0,
|
|
10736
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
9981
10737
|
"div",
|
|
9982
10738
|
{
|
|
9983
10739
|
className: cn(
|
|
9984
|
-
"
|
|
9985
|
-
isVertical ? editModeActive ? "mt-1
|
|
10740
|
+
"grid place-items-center overflow-hidden",
|
|
10741
|
+
isVertical ? editModeActive ? "mt-1 grid-rows-[1fr]" : "mt-0 grid-rows-[0fr]" : editModeActive ? "ml-1 grid-cols-[1fr]" : "ml-0 grid-cols-[0fr]"
|
|
9986
10742
|
),
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
10743
|
+
style: {
|
|
10744
|
+
transitionProperty: "grid-template-columns, grid-template-rows, margin",
|
|
10745
|
+
transitionDuration: "200ms",
|
|
10746
|
+
transitionTimingFunction: "cubic-bezier(0.25, 1, 0.5, 1)",
|
|
10747
|
+
transitionDelay: editModeActive ? "0ms" : "80ms"
|
|
10748
|
+
},
|
|
10749
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
10750
|
+
"div",
|
|
10751
|
+
{
|
|
10752
|
+
className: cn("flex gap-1 overflow-hidden", isVertical ? "min-h-0 flex-col items-center" : "min-w-0 flex-row items-center"),
|
|
10753
|
+
style: {
|
|
10754
|
+
filter: editModeActive ? "blur(0px)" : "blur(5px)",
|
|
10755
|
+
opacity: editModeActive ? 1 : 0,
|
|
10756
|
+
transitionProperty: "filter, opacity",
|
|
10757
|
+
transitionDuration: "250ms, 100ms",
|
|
10758
|
+
transitionTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
|
|
10759
|
+
transitionDelay: editModeActive ? "80ms" : "0ms"
|
|
10760
|
+
},
|
|
10761
|
+
children: [
|
|
10762
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10763
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10764
|
+
TooltipTrigger,
|
|
10765
|
+
{
|
|
10766
|
+
className: cn(
|
|
10767
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10768
|
+
activeTool === "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10769
|
+
),
|
|
10770
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10771
|
+
onClick: () => onSetActiveTool?.(activeTool === "comment" ? "select" : "comment"),
|
|
10772
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.MessageSquare, { className: "size-4" })
|
|
10773
|
+
}
|
|
9995
10774
|
),
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
/* @__PURE__ */ (0,
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10775
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10776
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: activeTool === "comment" ? "Exit comment mode" : "Comment" }),
|
|
10777
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ArrowBigUp, { className: "size-3" }) }),
|
|
10778
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "C" })
|
|
10779
|
+
] })
|
|
10780
|
+
] }),
|
|
10781
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10782
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10783
|
+
TooltipTrigger,
|
|
10784
|
+
{
|
|
10785
|
+
className: cn(
|
|
10786
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10787
|
+
rulersVisible ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10788
|
+
),
|
|
10789
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10790
|
+
onClick: onToggleRulers,
|
|
10791
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Ruler, { className: "size-4" })
|
|
10792
|
+
}
|
|
10014
10793
|
),
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
/* @__PURE__ */ (0,
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10794
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10795
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: rulersVisible ? "Hide rulers" : "Show rulers" }),
|
|
10796
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ArrowBigUp, { className: "size-2.5" }) }),
|
|
10797
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "R" })
|
|
10798
|
+
] })
|
|
10799
|
+
] }),
|
|
10800
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10801
|
+
ZoomPopover,
|
|
10802
|
+
{
|
|
10803
|
+
tooltipSide,
|
|
10804
|
+
canvasActive,
|
|
10805
|
+
canvasZoom,
|
|
10806
|
+
isOpen: activePopover === "zoom",
|
|
10807
|
+
onOpenChange: (open) => setActivePopover(open ? "zoom" : null),
|
|
10808
|
+
onToggleCanvas,
|
|
10809
|
+
onSetCanvasZoom,
|
|
10810
|
+
onZoomTo100,
|
|
10811
|
+
onFitToViewport
|
|
10812
|
+
}
|
|
10813
|
+
),
|
|
10814
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
10815
|
+
"border-foreground/10",
|
|
10816
|
+
isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
|
|
10817
|
+
) }),
|
|
10818
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10819
|
+
EditsPopover,
|
|
10820
|
+
{
|
|
10821
|
+
tooltipSide,
|
|
10822
|
+
sessionEditCount,
|
|
10823
|
+
isOpen: activePopover === "edits",
|
|
10824
|
+
onOpenChange: (open) => setActivePopover(open ? "edits" : null),
|
|
10825
|
+
onGetSessionItems,
|
|
10826
|
+
onExportAllEdits,
|
|
10827
|
+
onSendAllToAgents,
|
|
10828
|
+
onClearSessionEdits,
|
|
10829
|
+
onRemoveSessionEdit,
|
|
10830
|
+
onDeleteComment
|
|
10831
|
+
}
|
|
10832
|
+
),
|
|
10833
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10834
|
+
SettingsPopover,
|
|
10835
|
+
{
|
|
10836
|
+
tooltipSide,
|
|
10837
|
+
theme,
|
|
10838
|
+
isMac,
|
|
10839
|
+
isOpen: activePopover === "settings",
|
|
10840
|
+
onOpenChange: (open) => setActivePopover(open ? "settings" : null),
|
|
10841
|
+
onSetTheme
|
|
10842
|
+
}
|
|
10843
|
+
),
|
|
10844
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
10845
|
+
"border-foreground/10",
|
|
10846
|
+
isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
|
|
10847
|
+
) }),
|
|
10848
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10849
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10850
|
+
TooltipTrigger,
|
|
10851
|
+
{
|
|
10852
|
+
className: "flex cursor-pointer items-center justify-center rounded-[8px] p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
10853
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10854
|
+
onClick: onToggleEditMode,
|
|
10855
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.X, { className: "size-4" })
|
|
10856
|
+
}
|
|
10857
|
+
),
|
|
10858
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10859
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: "Close" }),
|
|
10860
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "Esc" })
|
|
10861
|
+
] })
|
|
10862
|
+
] })
|
|
10863
|
+
]
|
|
10864
|
+
}
|
|
10865
|
+
)
|
|
10055
10866
|
}
|
|
10056
10867
|
)
|
|
10057
10868
|
] })
|
|
@@ -10064,7 +10875,7 @@ function DirectEditToolbarInner({
|
|
|
10064
10875
|
return toolbar;
|
|
10065
10876
|
}
|
|
10066
10877
|
function DirectEditToolbarContent() {
|
|
10067
|
-
const { editModeActive, activeTool, theme, sessionEditCount } = useDirectEditState();
|
|
10878
|
+
const { editModeActive, activeTool, theme, sessionEditCount, canvas } = useDirectEditState();
|
|
10068
10879
|
const {
|
|
10069
10880
|
toggleEditMode,
|
|
10070
10881
|
setActiveTool,
|
|
@@ -10074,10 +10885,14 @@ function DirectEditToolbarContent() {
|
|
|
10074
10885
|
sendAllSessionItemsToAgent,
|
|
10075
10886
|
clearSessionEdits,
|
|
10076
10887
|
removeSessionEdit,
|
|
10077
|
-
deleteComment
|
|
10888
|
+
deleteComment,
|
|
10889
|
+
toggleCanvas,
|
|
10890
|
+
setCanvasZoom,
|
|
10891
|
+
zoomCanvasTo100,
|
|
10892
|
+
fitCanvasToViewport
|
|
10078
10893
|
} = useDirectEditActions();
|
|
10079
10894
|
const [rulersVisible, toggleRulers] = useRulersVisible();
|
|
10080
|
-
return /* @__PURE__ */ (0,
|
|
10895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10081
10896
|
DirectEditToolbarInner,
|
|
10082
10897
|
{
|
|
10083
10898
|
editModeActive,
|
|
@@ -10094,34 +10909,40 @@ function DirectEditToolbarContent() {
|
|
|
10094
10909
|
onSendAllToAgents: sendAllSessionItemsToAgent,
|
|
10095
10910
|
onClearSessionEdits: clearSessionEdits,
|
|
10096
10911
|
onRemoveSessionEdit: removeSessionEdit,
|
|
10097
|
-
onDeleteComment: deleteComment
|
|
10912
|
+
onDeleteComment: deleteComment,
|
|
10913
|
+
canvasActive: canvas?.active ?? false,
|
|
10914
|
+
canvasZoom: canvas?.zoom ?? 1,
|
|
10915
|
+
onToggleCanvas: toggleCanvas,
|
|
10916
|
+
onSetCanvasZoom: setCanvasZoom,
|
|
10917
|
+
onZoomTo100: zoomCanvasTo100,
|
|
10918
|
+
onFitToViewport: fitCanvasToViewport
|
|
10098
10919
|
}
|
|
10099
10920
|
);
|
|
10100
10921
|
}
|
|
10101
10922
|
function DirectEditToolbar() {
|
|
10102
|
-
const [mounted, setMounted] =
|
|
10103
|
-
|
|
10923
|
+
const [mounted, setMounted] = React36.useState(false);
|
|
10924
|
+
React36.useEffect(() => {
|
|
10104
10925
|
setMounted(true);
|
|
10105
10926
|
}, []);
|
|
10106
10927
|
if (!mounted) {
|
|
10107
10928
|
return null;
|
|
10108
10929
|
}
|
|
10109
|
-
return /* @__PURE__ */ (0,
|
|
10930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(DirectEditToolbarContent, {});
|
|
10110
10931
|
}
|
|
10111
10932
|
|
|
10112
10933
|
// src/direct-edit.tsx
|
|
10113
|
-
var
|
|
10934
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
10114
10935
|
function DirectEdit() {
|
|
10115
|
-
return /* @__PURE__ */ (0,
|
|
10116
|
-
/* @__PURE__ */ (0,
|
|
10117
|
-
/* @__PURE__ */ (0,
|
|
10118
|
-
/* @__PURE__ */ (0,
|
|
10936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(DirectEditProvider, { children: [
|
|
10937
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DirectEditPanel, {}),
|
|
10938
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DirectEditToolbar, {}),
|
|
10939
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Rulers, {})
|
|
10119
10940
|
] });
|
|
10120
10941
|
}
|
|
10121
10942
|
|
|
10122
10943
|
// src/demo.tsx
|
|
10123
|
-
var
|
|
10124
|
-
var
|
|
10944
|
+
var React37 = __toESM(require("react"));
|
|
10945
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
10125
10946
|
function createValue(num, unit = "px") {
|
|
10126
10947
|
return { numericValue: num, unit, raw: `${num}${unit}` };
|
|
10127
10948
|
}
|
|
@@ -10149,7 +10970,7 @@ var DEMO_LOCATOR = {
|
|
|
10149
10970
|
classList: ELEMENT_INFO.classList
|
|
10150
10971
|
};
|
|
10151
10972
|
function DirectEditDemo() {
|
|
10152
|
-
const [spacing, setSpacing] =
|
|
10973
|
+
const [spacing, setSpacing] = React37.useState({
|
|
10153
10974
|
paddingTop: createValue(16),
|
|
10154
10975
|
paddingRight: createValue(16),
|
|
10155
10976
|
paddingBottom: createValue(16),
|
|
@@ -10160,13 +10981,13 @@ function DirectEditDemo() {
|
|
|
10160
10981
|
marginLeft: createValue(0),
|
|
10161
10982
|
gap: createValue(16)
|
|
10162
10983
|
});
|
|
10163
|
-
const [borderRadius, setBorderRadius] =
|
|
10984
|
+
const [borderRadius, setBorderRadius] = React37.useState({
|
|
10164
10985
|
borderTopLeftRadius: createValue(8),
|
|
10165
10986
|
borderTopRightRadius: createValue(8),
|
|
10166
10987
|
borderBottomRightRadius: createValue(8),
|
|
10167
10988
|
borderBottomLeftRadius: createValue(8)
|
|
10168
10989
|
});
|
|
10169
|
-
const [border, setBorder] =
|
|
10990
|
+
const [border, setBorder] = React37.useState({
|
|
10170
10991
|
borderTopStyle: "solid",
|
|
10171
10992
|
borderTopWidth: createValue(1),
|
|
10172
10993
|
borderRightStyle: "solid",
|
|
@@ -10176,23 +10997,23 @@ function DirectEditDemo() {
|
|
|
10176
10997
|
borderLeftStyle: "solid",
|
|
10177
10998
|
borderLeftWidth: createValue(1)
|
|
10178
10999
|
});
|
|
10179
|
-
const [flex, setFlex] =
|
|
11000
|
+
const [flex, setFlex] = React37.useState({
|
|
10180
11001
|
display: "flex",
|
|
10181
11002
|
flexDirection: "row",
|
|
10182
11003
|
justifyContent: "flex-start",
|
|
10183
11004
|
alignItems: "center"
|
|
10184
11005
|
});
|
|
10185
|
-
const [sizing, setSizing] =
|
|
11006
|
+
const [sizing, setSizing] = React37.useState({
|
|
10186
11007
|
width: { mode: "fit", value: createValue(300) },
|
|
10187
11008
|
height: { mode: "fit", value: createValue(100) }
|
|
10188
11009
|
});
|
|
10189
|
-
const [color, setColor] =
|
|
11010
|
+
const [color, setColor] = React37.useState({
|
|
10190
11011
|
backgroundColor: { hex: "FFFFFF", alpha: 100, raw: "rgb(255, 255, 255)" },
|
|
10191
11012
|
color: { hex: "000000", alpha: 100, raw: "rgb(0, 0, 0)" },
|
|
10192
11013
|
borderColor: { hex: "DDDDDD", alpha: 100, raw: "rgb(221, 221, 221)" },
|
|
10193
11014
|
outlineColor: { hex: "000000", alpha: 0, raw: "transparent" }
|
|
10194
11015
|
});
|
|
10195
|
-
const [typography, setTypography] =
|
|
11016
|
+
const [typography, setTypography] = React37.useState({
|
|
10196
11017
|
fontFamily: "system-ui, sans-serif",
|
|
10197
11018
|
fontWeight: "400",
|
|
10198
11019
|
fontSize: createValue(16),
|
|
@@ -10201,9 +11022,9 @@ function DirectEditDemo() {
|
|
|
10201
11022
|
textAlign: "left",
|
|
10202
11023
|
textVerticalAlign: "flex-start"
|
|
10203
11024
|
});
|
|
10204
|
-
const [boxShadow, setBoxShadow] =
|
|
10205
|
-
const [pendingStyles, setPendingStyles] =
|
|
10206
|
-
const [editModeActive, setEditModeActive] =
|
|
11025
|
+
const [boxShadow, setBoxShadow] = React37.useState("none");
|
|
11026
|
+
const [pendingStyles, setPendingStyles] = React37.useState({});
|
|
11027
|
+
const [editModeActive, setEditModeActive] = React37.useState(false);
|
|
10207
11028
|
const handleUpdateSpacing = (key, value) => {
|
|
10208
11029
|
setSpacing((prev) => ({ ...prev, [key]: value }));
|
|
10209
11030
|
setPendingStyles((prev) => ({ ...prev, [camelToKebab(key)]: value.raw }));
|
|
@@ -10314,10 +11135,10 @@ function DirectEditDemo() {
|
|
|
10314
11135
|
return false;
|
|
10315
11136
|
}
|
|
10316
11137
|
};
|
|
10317
|
-
return /* @__PURE__ */ (0,
|
|
10318
|
-
/* @__PURE__ */ (0,
|
|
10319
|
-
/* @__PURE__ */ (0,
|
|
10320
|
-
/* @__PURE__ */ (0,
|
|
11138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "min-h-screen p-8", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mx-auto max-w-4xl", children: [
|
|
11139
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { className: "mb-2 text-2xl font-bold", children: "Direct Edit Panel" }),
|
|
11140
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "mb-8 text-muted-foreground", children: "Interactive showcase of the visual editing panel UI with mock data." }),
|
|
11141
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10321
11142
|
DirectEditToolbarInner,
|
|
10322
11143
|
{
|
|
10323
11144
|
editModeActive,
|
|
@@ -10327,8 +11148,8 @@ function DirectEditDemo() {
|
|
|
10327
11148
|
}
|
|
10328
11149
|
}
|
|
10329
11150
|
) }),
|
|
10330
|
-
/* @__PURE__ */ (0,
|
|
10331
|
-
/* @__PURE__ */ (0,
|
|
11151
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "grid gap-8 lg:grid-cols-[300px_1fr]", children: [
|
|
11152
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10332
11153
|
DirectEditPanelInner,
|
|
10333
11154
|
{
|
|
10334
11155
|
elementInfo: ELEMENT_INFO,
|
|
@@ -10360,10 +11181,10 @@ function DirectEditDemo() {
|
|
|
10360
11181
|
onSendToAgent: async () => false
|
|
10361
11182
|
}
|
|
10362
11183
|
),
|
|
10363
|
-
/* @__PURE__ */ (0,
|
|
10364
|
-
/* @__PURE__ */ (0,
|
|
10365
|
-
/* @__PURE__ */ (0,
|
|
10366
|
-
/* @__PURE__ */ (0,
|
|
11184
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "space-y-6", children: [
|
|
11185
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11186
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Live Preview" }),
|
|
11187
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
10367
11188
|
"div",
|
|
10368
11189
|
{
|
|
10369
11190
|
className: "bg-background border flex",
|
|
@@ -10386,20 +11207,20 @@ function DirectEditDemo() {
|
|
|
10386
11207
|
alignItems: flex.alignItems
|
|
10387
11208
|
},
|
|
10388
11209
|
children: [
|
|
10389
|
-
/* @__PURE__ */ (0,
|
|
10390
|
-
/* @__PURE__ */ (0,
|
|
10391
|
-
/* @__PURE__ */ (0,
|
|
11210
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-blue-500/20 border border-blue-500/30" }),
|
|
11211
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-green-500/20 border border-green-500/30" }),
|
|
11212
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-purple-500/20 border border-purple-500/30" })
|
|
10392
11213
|
]
|
|
10393
11214
|
}
|
|
10394
11215
|
)
|
|
10395
11216
|
] }),
|
|
10396
|
-
/* @__PURE__ */ (0,
|
|
10397
|
-
/* @__PURE__ */ (0,
|
|
10398
|
-
/* @__PURE__ */ (0,
|
|
11217
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11218
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Pending Styles" }),
|
|
11219
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("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" })
|
|
10399
11220
|
] }),
|
|
10400
|
-
/* @__PURE__ */ (0,
|
|
10401
|
-
/* @__PURE__ */ (0,
|
|
10402
|
-
/* @__PURE__ */ (0,
|
|
11221
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11222
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Tailwind Classes" }),
|
|
11223
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("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" })
|
|
10403
11224
|
] })
|
|
10404
11225
|
] })
|
|
10405
11226
|
] })
|