made-refine 0.2.2 → 0.2.4
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 +1741 -865
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1742 -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,394 @@ 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 savedScrollContainersRef = React7.useRef([]);
|
|
4139
|
+
const rafIdRef = React7.useRef(null);
|
|
4140
|
+
const rafPendingRef = React7.useRef(false);
|
|
4141
|
+
const spaceHeldRef = React7.useRef(false);
|
|
4142
|
+
const isDraggingRef = React7.useRef(false);
|
|
4143
|
+
const dragStartRef = React7.useRef({ x: 0, y: 0, panX: 0, panY: 0 });
|
|
4144
|
+
const applyTransform = React7.useCallback((zoom, panX, panY) => {
|
|
4145
|
+
document.body.style.transformOrigin = "0 0";
|
|
4146
|
+
document.body.style.transform = `scale(${zoom}) translate(${panX}px, ${panY}px)`;
|
|
4147
|
+
}, []);
|
|
4148
|
+
const dispatchCanvasChange = React7.useCallback(() => {
|
|
4149
|
+
window.dispatchEvent(new Event("direct-edit-canvas-change"));
|
|
4150
|
+
}, []);
|
|
4151
|
+
const readBodyOffset = React7.useCallback(() => {
|
|
4152
|
+
const bodyStyle = getComputedStyle(document.body);
|
|
4153
|
+
return {
|
|
4154
|
+
x: parseFloat(bodyStyle.marginLeft) || 0,
|
|
4155
|
+
y: parseFloat(bodyStyle.marginTop) || 0
|
|
4156
|
+
};
|
|
4157
|
+
}, []);
|
|
4158
|
+
const updateBodyOffset = React7.useCallback(() => {
|
|
4159
|
+
const next = readBodyOffset();
|
|
4160
|
+
const prev = getBodyOffset();
|
|
4161
|
+
if (prev.x === next.x && prev.y === next.y) return false;
|
|
4162
|
+
setBodyOffset(next);
|
|
4163
|
+
return true;
|
|
4164
|
+
}, [readBodyOffset]);
|
|
4165
|
+
const cancelPendingRaf = React7.useCallback(() => {
|
|
4166
|
+
if (rafIdRef.current !== null) {
|
|
4167
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
4168
|
+
rafIdRef.current = null;
|
|
4169
|
+
rafPendingRef.current = false;
|
|
4170
|
+
}
|
|
4171
|
+
}, []);
|
|
4172
|
+
const updateCanvas = React7.useCallback((zoom, panX, panY) => {
|
|
4173
|
+
const dims = savedBodyDimensionsRef.current;
|
|
4174
|
+
const bodyW = dims.width || window.innerWidth;
|
|
4175
|
+
const bodyH = dims.height || window.innerHeight;
|
|
4176
|
+
const clamped = clampPan(zoom, panX, panY, bodyW, bodyH);
|
|
4177
|
+
canvasRef.current = { ...canvasRef.current, zoom, panX: clamped.panX, panY: clamped.panY };
|
|
4178
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4179
|
+
applyTransform(zoom, clamped.panX, clamped.panY);
|
|
4180
|
+
dispatchCanvasChange();
|
|
4181
|
+
if (!rafPendingRef.current) {
|
|
4182
|
+
rafPendingRef.current = true;
|
|
4183
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
4184
|
+
rafPendingRef.current = false;
|
|
4185
|
+
rafIdRef.current = null;
|
|
4186
|
+
const s = canvasRef.current;
|
|
4187
|
+
setState((prev) => ({
|
|
4188
|
+
...prev,
|
|
4189
|
+
canvas: { active: s.active, zoom: s.zoom, panX: s.panX, panY: s.panY }
|
|
4190
|
+
}));
|
|
4191
|
+
});
|
|
4192
|
+
}
|
|
4193
|
+
}, [applyTransform, dispatchCanvasChange, setState]);
|
|
4194
|
+
function isScrollableContainer(el) {
|
|
4195
|
+
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
4196
|
+
const style = getComputedStyle(el);
|
|
4197
|
+
const overflowY = style.overflowY || style.overflow;
|
|
4198
|
+
if (overflowY === "hidden" || overflowY === "clip") return false;
|
|
4199
|
+
return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
|
|
4200
|
+
}
|
|
4201
|
+
function expandScrollContainers() {
|
|
4202
|
+
const saved = [];
|
|
4203
|
+
const queue = Array.from(document.body.children).filter(
|
|
4204
|
+
(el) => el instanceof HTMLElement
|
|
4205
|
+
);
|
|
4206
|
+
let visited = 0;
|
|
4207
|
+
const maxNodes = 5e3;
|
|
4208
|
+
while (queue.length > 0 && visited < maxNodes) {
|
|
4209
|
+
const nextQueue = [];
|
|
4210
|
+
for (const el of queue) {
|
|
4211
|
+
if (visited >= maxNodes) break;
|
|
4212
|
+
visited++;
|
|
4213
|
+
if (isScrollableContainer(el)) {
|
|
4214
|
+
const style = el.style;
|
|
4215
|
+
saved.push({
|
|
4216
|
+
el,
|
|
4217
|
+
height: style.height,
|
|
4218
|
+
maxHeight: style.maxHeight,
|
|
4219
|
+
overflowX: style.overflowX,
|
|
4220
|
+
overflowY: style.overflowY
|
|
4221
|
+
});
|
|
4222
|
+
style.height = "auto";
|
|
4223
|
+
style.maxHeight = "none";
|
|
4224
|
+
style.overflowX = "visible";
|
|
4225
|
+
style.overflowY = "visible";
|
|
4226
|
+
}
|
|
4227
|
+
for (const child of el.children) {
|
|
4228
|
+
if (child instanceof HTMLElement) nextQueue.push(child);
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
queue.length = 0;
|
|
4232
|
+
queue.push(...nextQueue);
|
|
4233
|
+
}
|
|
4234
|
+
savedScrollContainersRef.current = saved;
|
|
4235
|
+
}
|
|
4236
|
+
function restoreScrollContainers() {
|
|
4237
|
+
for (let i = savedScrollContainersRef.current.length - 1; i >= 0; i--) {
|
|
4238
|
+
const { el, height, maxHeight, overflowX, overflowY } = savedScrollContainersRef.current[i];
|
|
4239
|
+
el.style.height = height;
|
|
4240
|
+
el.style.maxHeight = maxHeight;
|
|
4241
|
+
el.style.overflowX = overflowX;
|
|
4242
|
+
el.style.overflowY = overflowY;
|
|
4243
|
+
}
|
|
4244
|
+
savedScrollContainersRef.current = [];
|
|
4245
|
+
}
|
|
4246
|
+
const enterCanvas = React7.useCallback(() => {
|
|
4247
|
+
const scrollX = window.scrollX;
|
|
4248
|
+
const scrollY = window.scrollY;
|
|
4249
|
+
savedScrollRef.current = { x: scrollX, y: scrollY };
|
|
4250
|
+
savedBodyOverflowRef.current = document.body.style.overflow;
|
|
4251
|
+
savedHtmlOverflowRef.current = document.documentElement.style.overflow;
|
|
4252
|
+
savedHtmlBgColorRef.current = document.documentElement.style.backgroundColor;
|
|
4253
|
+
const existingTransform = document.body.style.transform;
|
|
4254
|
+
if (existingTransform && existingTransform !== "none" && existingTransform !== "") {
|
|
4255
|
+
console.warn("[made-refine] canvas mode: overriding existing body transform:", existingTransform);
|
|
4256
|
+
}
|
|
4257
|
+
window.scrollTo(0, 0);
|
|
4258
|
+
expandScrollContainers();
|
|
4259
|
+
savedBodyDimensionsRef.current = {
|
|
4260
|
+
width: document.body.scrollWidth,
|
|
4261
|
+
height: document.body.scrollHeight
|
|
4262
|
+
};
|
|
4263
|
+
updateBodyOffset();
|
|
4264
|
+
document.body.style.overflow = "hidden";
|
|
4265
|
+
document.documentElement.style.overflow = "hidden";
|
|
4266
|
+
document.documentElement.style.backgroundColor = "#F5F5F5";
|
|
4267
|
+
const initialPanX = -scrollX;
|
|
4268
|
+
const initialPanY = -scrollY;
|
|
4269
|
+
applyTransform(1, initialPanX, initialPanY);
|
|
4270
|
+
canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
|
|
4271
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4272
|
+
setState((prev) => ({
|
|
4273
|
+
...prev,
|
|
4274
|
+
canvas: { active: true, zoom: 1, panX: initialPanX, panY: initialPanY }
|
|
4275
|
+
}));
|
|
4276
|
+
dispatchCanvasChange();
|
|
4277
|
+
}, [applyTransform, dispatchCanvasChange, setState, updateBodyOffset]);
|
|
4278
|
+
const exitCanvas = React7.useCallback(() => {
|
|
4279
|
+
cancelPendingRaf();
|
|
4280
|
+
document.body.style.transform = "";
|
|
4281
|
+
document.body.style.transformOrigin = "";
|
|
4282
|
+
restoreScrollContainers();
|
|
4283
|
+
document.body.style.overflow = savedBodyOverflowRef.current;
|
|
4284
|
+
document.documentElement.style.overflow = savedHtmlOverflowRef.current;
|
|
4285
|
+
document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
|
|
4286
|
+
document.body.style.cursor = "";
|
|
4287
|
+
window.scrollTo(savedScrollRef.current.x, savedScrollRef.current.y);
|
|
4288
|
+
setBodyOffset({ x: 0, y: 0 });
|
|
4289
|
+
canvasRef.current = { active: false, zoom: 1, panX: 0, panY: 0 };
|
|
4290
|
+
setCanvasSnapshot(canvasRef.current);
|
|
4291
|
+
setState((prev) => ({
|
|
4292
|
+
...prev,
|
|
4293
|
+
canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
|
|
4294
|
+
}));
|
|
4295
|
+
dispatchCanvasChange();
|
|
4296
|
+
}, [cancelPendingRaf, dispatchCanvasChange, setState]);
|
|
4297
|
+
const toggleCanvas = React7.useCallback(() => {
|
|
4298
|
+
if (canvasRef.current.active) {
|
|
4299
|
+
exitCanvas();
|
|
4300
|
+
} else {
|
|
4301
|
+
enterCanvas();
|
|
4302
|
+
}
|
|
4303
|
+
}, [enterCanvas, exitCanvas]);
|
|
4304
|
+
const setCanvasZoom = React7.useCallback((zoom) => {
|
|
4305
|
+
const c = canvasRef.current;
|
|
4306
|
+
if (!c.active) return;
|
|
4307
|
+
const clampedZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
|
|
4308
|
+
updateCanvas(clampedZoom, c.panX, c.panY);
|
|
4309
|
+
}, [updateCanvas]);
|
|
4310
|
+
const fitCanvasToViewport = React7.useCallback(() => {
|
|
4311
|
+
const c = canvasRef.current;
|
|
4312
|
+
if (!c.active) return;
|
|
4313
|
+
const bodyWidth = savedBodyDimensionsRef.current.width || window.innerWidth;
|
|
4314
|
+
const bodyHeight = savedBodyDimensionsRef.current.height || window.innerHeight;
|
|
4315
|
+
const scaleX = window.innerWidth / bodyWidth;
|
|
4316
|
+
const scaleY = window.innerHeight / bodyHeight;
|
|
4317
|
+
const zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, Math.min(scaleX, scaleY) * 0.9));
|
|
4318
|
+
const panX = (window.innerWidth / zoom - bodyWidth) / 2;
|
|
4319
|
+
const panY = (window.innerHeight / zoom - bodyHeight) / 2;
|
|
4320
|
+
updateCanvas(zoom, panX, panY);
|
|
4321
|
+
}, [updateCanvas]);
|
|
4322
|
+
const zoomCanvasTo100 = React7.useCallback(() => {
|
|
4323
|
+
const c = canvasRef.current;
|
|
4324
|
+
if (!c.active) return;
|
|
4325
|
+
updateCanvas(1, 0, 0);
|
|
4326
|
+
}, [updateCanvas]);
|
|
4327
|
+
React7.useEffect(() => {
|
|
4328
|
+
function handleWheel(e) {
|
|
4329
|
+
const c = canvasRef.current;
|
|
4330
|
+
if (!c.active) return;
|
|
4331
|
+
e.preventDefault();
|
|
4332
|
+
const { deltaX, deltaY } = normalizeWheelDelta(e);
|
|
4333
|
+
if (e.ctrlKey || e.metaKey) {
|
|
4334
|
+
const zoomFactor = Math.exp(-deltaY * ZOOM_SENSITIVITY);
|
|
4335
|
+
const oldZoom = c.zoom;
|
|
4336
|
+
const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * zoomFactor));
|
|
4337
|
+
const cx = e.clientX;
|
|
4338
|
+
const cy = e.clientY;
|
|
4339
|
+
const bo = getBodyOffset();
|
|
4340
|
+
const newPanX = c.panX + (cx - bo.x) * (1 / newZoom - 1 / oldZoom);
|
|
4341
|
+
const newPanY = c.panY + (cy - bo.y) * (1 / newZoom - 1 / oldZoom);
|
|
4342
|
+
updateCanvas(newZoom, newPanX, newPanY);
|
|
4343
|
+
} else {
|
|
4344
|
+
const newPanX = c.panX - deltaX / c.zoom;
|
|
4345
|
+
const newPanY = c.panY - deltaY / c.zoom;
|
|
4346
|
+
updateCanvas(c.zoom, newPanX, newPanY);
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
window.addEventListener("wheel", handleWheel, { passive: false });
|
|
4350
|
+
return () => window.removeEventListener("wheel", handleWheel);
|
|
4351
|
+
}, [updateCanvas]);
|
|
4352
|
+
React7.useEffect(() => {
|
|
4353
|
+
function handleResize() {
|
|
4354
|
+
if (!canvasRef.current.active) return;
|
|
4355
|
+
if (updateBodyOffset()) {
|
|
4356
|
+
dispatchCanvasChange();
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
window.addEventListener("resize", handleResize);
|
|
4360
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
4361
|
+
}, [dispatchCanvasChange, updateBodyOffset]);
|
|
4362
|
+
React7.useEffect(() => {
|
|
4363
|
+
function handleKeyDown(e) {
|
|
4364
|
+
if (e.code !== "Space" || e.repeat) return;
|
|
4365
|
+
if (!canvasRef.current.active) return;
|
|
4366
|
+
if (isInputFocused()) return;
|
|
4367
|
+
spaceHeldRef.current = true;
|
|
4368
|
+
if (!isDraggingRef.current) {
|
|
4369
|
+
document.body.style.cursor = "grab";
|
|
4370
|
+
}
|
|
4371
|
+
e.preventDefault();
|
|
4372
|
+
}
|
|
4373
|
+
function handleKeyUp(e) {
|
|
4374
|
+
if (e.code !== "Space") return;
|
|
4375
|
+
if (!canvasRef.current.active) return;
|
|
4376
|
+
spaceHeldRef.current = false;
|
|
4377
|
+
if (!isDraggingRef.current) {
|
|
4378
|
+
document.body.style.cursor = "";
|
|
4379
|
+
}
|
|
4380
|
+
}
|
|
4381
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
4382
|
+
window.addEventListener("keyup", handleKeyUp, true);
|
|
4383
|
+
return () => {
|
|
4384
|
+
window.removeEventListener("keydown", handleKeyDown, true);
|
|
4385
|
+
window.removeEventListener("keyup", handleKeyUp, true);
|
|
4386
|
+
};
|
|
4387
|
+
}, []);
|
|
4388
|
+
React7.useEffect(() => {
|
|
4389
|
+
function handlePointerDown(e) {
|
|
4390
|
+
const c = canvasRef.current;
|
|
4391
|
+
if (!c.active) return;
|
|
4392
|
+
const isMiddleMouse = e.button === 1;
|
|
4393
|
+
const isSpaceDrag = spaceHeldRef.current && e.button === 0;
|
|
4394
|
+
if (!isMiddleMouse && !isSpaceDrag) return;
|
|
4395
|
+
e.preventDefault();
|
|
4396
|
+
isDraggingRef.current = true;
|
|
4397
|
+
dragStartRef.current = { x: e.clientX, y: e.clientY, panX: c.panX, panY: c.panY };
|
|
4398
|
+
document.body.style.cursor = "grabbing";
|
|
4399
|
+
const dragAbort = new AbortController();
|
|
4400
|
+
const opts = { signal: dragAbort.signal };
|
|
4401
|
+
function endDrag() {
|
|
4402
|
+
isDraggingRef.current = false;
|
|
4403
|
+
document.body.style.cursor = spaceHeldRef.current ? "grab" : "";
|
|
4404
|
+
dragAbort.abort();
|
|
4405
|
+
}
|
|
4406
|
+
window.addEventListener("pointermove", (moveE) => {
|
|
4407
|
+
const current = canvasRef.current;
|
|
4408
|
+
const dx = (moveE.clientX - dragStartRef.current.x) / current.zoom;
|
|
4409
|
+
const dy = (moveE.clientY - dragStartRef.current.y) / current.zoom;
|
|
4410
|
+
updateCanvas(current.zoom, dragStartRef.current.panX + dx, dragStartRef.current.panY + dy);
|
|
4411
|
+
}, opts);
|
|
4412
|
+
window.addEventListener("pointerup", endDrag, opts);
|
|
4413
|
+
window.addEventListener("pointercancel", endDrag, opts);
|
|
4414
|
+
window.addEventListener("blur", endDrag, opts);
|
|
4415
|
+
}
|
|
4416
|
+
window.addEventListener("pointerdown", handlePointerDown, true);
|
|
4417
|
+
return () => window.removeEventListener("pointerdown", handlePointerDown, true);
|
|
4418
|
+
}, [updateCanvas]);
|
|
4419
|
+
React7.useEffect(() => {
|
|
4420
|
+
return () => {
|
|
4421
|
+
cancelPendingRaf();
|
|
4422
|
+
if (canvasRef.current.active) {
|
|
4423
|
+
exitCanvas();
|
|
4424
|
+
}
|
|
4425
|
+
};
|
|
4426
|
+
}, [cancelPendingRaf, exitCanvas]);
|
|
4427
|
+
return { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 };
|
|
4016
4428
|
}
|
|
4017
4429
|
|
|
4018
4430
|
// src/provider.tsx
|
|
4019
4431
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
4020
|
-
var DirectEditStateContext =
|
|
4021
|
-
var DirectEditActionsContext =
|
|
4432
|
+
var DirectEditStateContext = React8.createContext(null);
|
|
4433
|
+
var DirectEditActionsContext = React8.createContext(null);
|
|
4022
4434
|
function useDirectEditState() {
|
|
4023
|
-
const context =
|
|
4435
|
+
const context = React8.useContext(DirectEditStateContext);
|
|
4024
4436
|
if (!context) {
|
|
4025
4437
|
throw new Error("useDirectEditState must be used within a DirectEditProvider");
|
|
4026
4438
|
}
|
|
4027
4439
|
return context;
|
|
4028
4440
|
}
|
|
4029
4441
|
function useDirectEditActions() {
|
|
4030
|
-
const context =
|
|
4442
|
+
const context = React8.useContext(DirectEditActionsContext);
|
|
4031
4443
|
if (!context) {
|
|
4032
4444
|
throw new Error("useDirectEditActions must be used within a DirectEditProvider");
|
|
4033
4445
|
}
|
|
@@ -4036,11 +4448,34 @@ function useDirectEditActions() {
|
|
|
4036
4448
|
function useDirectEdit() {
|
|
4037
4449
|
const state = useDirectEditState();
|
|
4038
4450
|
const actions = useDirectEditActions();
|
|
4039
|
-
return
|
|
4451
|
+
return React8.useMemo(() => ({ ...state, ...actions }), [state, actions]);
|
|
4040
4452
|
}
|
|
4041
4453
|
var BORDER_STYLE_CONTROL_PREFERENCE_KEY = "direct-edit-border-style-control";
|
|
4454
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? React8.useEffect : React8.useLayoutEffect;
|
|
4455
|
+
function getInitialTheme() {
|
|
4456
|
+
if (typeof window === "undefined") return "system";
|
|
4457
|
+
try {
|
|
4458
|
+
const theme = localStorage.getItem("direct-edit-theme");
|
|
4459
|
+
if (theme === "light" || theme === "dark" || theme === "system") {
|
|
4460
|
+
return theme;
|
|
4461
|
+
}
|
|
4462
|
+
} catch {
|
|
4463
|
+
}
|
|
4464
|
+
return "system";
|
|
4465
|
+
}
|
|
4466
|
+
function getInitialBorderStyleControlPreference() {
|
|
4467
|
+
if (typeof window === "undefined") return "icon";
|
|
4468
|
+
try {
|
|
4469
|
+
const borderPref = localStorage.getItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY);
|
|
4470
|
+
if (borderPref === "label" || borderPref === "icon") {
|
|
4471
|
+
return borderPref;
|
|
4472
|
+
}
|
|
4473
|
+
} catch {
|
|
4474
|
+
}
|
|
4475
|
+
return "icon";
|
|
4476
|
+
}
|
|
4042
4477
|
function DirectEditProvider({ children }) {
|
|
4043
|
-
const [state, setState] =
|
|
4478
|
+
const [state, setState] = React8.useState(() => ({
|
|
4044
4479
|
isOpen: false,
|
|
4045
4480
|
selectedElement: null,
|
|
4046
4481
|
elementInfo: null,
|
|
@@ -4056,38 +4491,22 @@ function DirectEditProvider({ children }) {
|
|
|
4056
4491
|
pendingStyles: {},
|
|
4057
4492
|
editModeActive: false,
|
|
4058
4493
|
activeTool: "select",
|
|
4059
|
-
theme:
|
|
4060
|
-
borderStyleControlPreference:
|
|
4494
|
+
theme: getInitialTheme(),
|
|
4495
|
+
borderStyleControlPreference: getInitialBorderStyleControlPreference(),
|
|
4061
4496
|
comments: [],
|
|
4062
4497
|
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(() => {
|
|
4498
|
+
textEditingElement: null,
|
|
4499
|
+
canvas: { active: false, zoom: 1, panX: 0, panY: 0 }
|
|
4500
|
+
}));
|
|
4501
|
+
const undoStackRef = React8.useRef([]);
|
|
4502
|
+
const sessionEditsRef = React8.useRef(/* @__PURE__ */ new Map());
|
|
4503
|
+
const removedSessionEditsRef = React8.useRef(/* @__PURE__ */ new WeakSet());
|
|
4504
|
+
const [sessionEditCount, setSessionEditCount] = React8.useState(0);
|
|
4505
|
+
const stateRef = React8.useRef(state);
|
|
4506
|
+
React8.useEffect(() => {
|
|
4088
4507
|
stateRef.current = state;
|
|
4089
4508
|
});
|
|
4090
|
-
const pushUndo =
|
|
4509
|
+
const pushUndo = React8.useCallback((entry) => {
|
|
4091
4510
|
undoStackRef.current.push(entry);
|
|
4092
4511
|
if (undoStackRef.current.length > 500) {
|
|
4093
4512
|
undoStackRef.current = undoStackRef.current.slice(-500);
|
|
@@ -4132,13 +4551,13 @@ function DirectEditProvider({ children }) {
|
|
|
4132
4551
|
setState,
|
|
4133
4552
|
setSessionEditCount
|
|
4134
4553
|
});
|
|
4135
|
-
|
|
4554
|
+
React8.useEffect(() => {
|
|
4136
4555
|
if (!state.selectedElement) return;
|
|
4137
4556
|
saveCurrentToSession();
|
|
4138
4557
|
}, [state.selectedElement, state.pendingStyles, saveCurrentToSession]);
|
|
4139
4558
|
const {
|
|
4140
4559
|
finalizeTextEditing,
|
|
4141
|
-
toggleEditMode,
|
|
4560
|
+
toggleEditMode: toggleEditModeBase,
|
|
4142
4561
|
startTextEditing,
|
|
4143
4562
|
commitTextEditing,
|
|
4144
4563
|
addComment,
|
|
@@ -4155,10 +4574,32 @@ function DirectEditProvider({ children }) {
|
|
|
4155
4574
|
syncSessionItemCount,
|
|
4156
4575
|
setState
|
|
4157
4576
|
});
|
|
4158
|
-
|
|
4577
|
+
const { toggleCanvas, enterCanvas, exitCanvas, setCanvasZoom, fitCanvasToViewport, zoomCanvasTo100 } = useCanvas({
|
|
4578
|
+
stateRef,
|
|
4579
|
+
setState
|
|
4580
|
+
});
|
|
4581
|
+
const closePanel = React8.useCallback(() => {
|
|
4582
|
+
setState((prev) => ({
|
|
4583
|
+
...prev,
|
|
4584
|
+
isOpen: false
|
|
4585
|
+
}));
|
|
4586
|
+
}, []);
|
|
4587
|
+
const toggleEditMode = React8.useCallback(() => {
|
|
4588
|
+
const wasActive = stateRef.current.editModeActive;
|
|
4589
|
+
toggleEditModeBase();
|
|
4590
|
+
if (wasActive && stateRef.current.canvas?.active) {
|
|
4591
|
+
exitCanvas();
|
|
4592
|
+
} else if (!wasActive) {
|
|
4593
|
+
enterCanvas();
|
|
4594
|
+
}
|
|
4595
|
+
if (wasActive) {
|
|
4596
|
+
closePanel();
|
|
4597
|
+
}
|
|
4598
|
+
}, [toggleEditModeBase, stateRef, exitCanvas, enterCanvas, closePanel]);
|
|
4599
|
+
React8.useEffect(() => {
|
|
4159
4600
|
syncSessionItemCount(state.comments);
|
|
4160
4601
|
}, [state.comments, syncSessionItemCount]);
|
|
4161
|
-
|
|
4602
|
+
React8.useEffect(() => {
|
|
4162
4603
|
const editingElement = state.textEditingElement;
|
|
4163
4604
|
if (!editingElement) return;
|
|
4164
4605
|
const activeEditingElement = editingElement;
|
|
@@ -4183,27 +4624,21 @@ function DirectEditProvider({ children }) {
|
|
|
4183
4624
|
sendCommentToAgent: sendCommentToAgent2,
|
|
4184
4625
|
sendAllSessionItemsToAgent
|
|
4185
4626
|
} = useAgentComms({ stateRef, sessionEditsRef, getSessionItems });
|
|
4186
|
-
const
|
|
4187
|
-
setState((prev) => ({
|
|
4188
|
-
...prev,
|
|
4189
|
-
isOpen: false
|
|
4190
|
-
}));
|
|
4191
|
-
}, []);
|
|
4192
|
-
const setActiveTool = React7.useCallback((tool) => {
|
|
4627
|
+
const setActiveTool = React8.useCallback((tool) => {
|
|
4193
4628
|
setState((prev) => ({
|
|
4194
4629
|
...prev,
|
|
4195
4630
|
activeTool: tool,
|
|
4196
4631
|
activeCommentId: null
|
|
4197
4632
|
}));
|
|
4198
4633
|
}, []);
|
|
4199
|
-
const setTheme =
|
|
4634
|
+
const setTheme = React8.useCallback((theme) => {
|
|
4200
4635
|
setState((prev) => ({ ...prev, theme }));
|
|
4201
4636
|
try {
|
|
4202
4637
|
localStorage.setItem("direct-edit-theme", theme);
|
|
4203
4638
|
} catch {
|
|
4204
4639
|
}
|
|
4205
4640
|
}, []);
|
|
4206
|
-
const setBorderStyleControlPreference =
|
|
4641
|
+
const setBorderStyleControlPreference = React8.useCallback((preference) => {
|
|
4207
4642
|
setState((prev) => ({ ...prev, borderStyleControlPreference: preference }));
|
|
4208
4643
|
try {
|
|
4209
4644
|
localStorage.setItem(BORDER_STYLE_CONTROL_PREFERENCE_KEY, preference);
|
|
@@ -4218,13 +4653,17 @@ function DirectEditProvider({ children }) {
|
|
|
4218
4653
|
commitTextEditing,
|
|
4219
4654
|
startTextEditing,
|
|
4220
4655
|
closePanel,
|
|
4221
|
-
setState
|
|
4656
|
+
setState,
|
|
4657
|
+
toggleCanvas,
|
|
4658
|
+
setCanvasZoom,
|
|
4659
|
+
fitCanvasToViewport,
|
|
4660
|
+
zoomCanvasTo100
|
|
4222
4661
|
});
|
|
4223
|
-
const stateContextValue =
|
|
4662
|
+
const stateContextValue = React8.useMemo(() => ({
|
|
4224
4663
|
...state,
|
|
4225
4664
|
sessionEditCount
|
|
4226
4665
|
}), [state, sessionEditCount]);
|
|
4227
|
-
const actionsContextValue =
|
|
4666
|
+
const actionsContextValue = React8.useMemo(() => ({
|
|
4228
4667
|
selectElement,
|
|
4229
4668
|
selectParent,
|
|
4230
4669
|
selectChild,
|
|
@@ -4263,7 +4702,11 @@ function DirectEditProvider({ children }) {
|
|
|
4263
4702
|
clearSessionEdits,
|
|
4264
4703
|
removeSessionEdit,
|
|
4265
4704
|
startTextEditing,
|
|
4266
|
-
commitTextEditing
|
|
4705
|
+
commitTextEditing,
|
|
4706
|
+
toggleCanvas,
|
|
4707
|
+
setCanvasZoom,
|
|
4708
|
+
fitCanvasToViewport,
|
|
4709
|
+
zoomCanvasTo100
|
|
4267
4710
|
}), [
|
|
4268
4711
|
selectElement,
|
|
4269
4712
|
selectParent,
|
|
@@ -4303,7 +4746,11 @@ function DirectEditProvider({ children }) {
|
|
|
4303
4746
|
clearSessionEdits,
|
|
4304
4747
|
removeSessionEdit,
|
|
4305
4748
|
startTextEditing,
|
|
4306
|
-
commitTextEditing
|
|
4749
|
+
commitTextEditing,
|
|
4750
|
+
toggleCanvas,
|
|
4751
|
+
setCanvasZoom,
|
|
4752
|
+
fitCanvasToViewport,
|
|
4753
|
+
zoomCanvasTo100
|
|
4307
4754
|
]);
|
|
4308
4755
|
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
4756
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThemeApplier, {}),
|
|
@@ -4313,7 +4760,7 @@ function DirectEditProvider({ children }) {
|
|
|
4313
4760
|
function ThemeApplier() {
|
|
4314
4761
|
const { theme } = useDirectEditState();
|
|
4315
4762
|
const container = usePortalContainer();
|
|
4316
|
-
|
|
4763
|
+
useIsomorphicLayoutEffect(() => {
|
|
4317
4764
|
if (!container) return;
|
|
4318
4765
|
const host = container.getRootNode().host;
|
|
4319
4766
|
if (theme === "system") {
|
|
@@ -4326,11 +4773,11 @@ function ThemeApplier() {
|
|
|
4326
4773
|
}
|
|
4327
4774
|
|
|
4328
4775
|
// src/panel.tsx
|
|
4329
|
-
var
|
|
4776
|
+
var React29 = __toESM(require("react"));
|
|
4330
4777
|
var import_react_dom = require("react-dom");
|
|
4331
4778
|
|
|
4332
4779
|
// src/ui/tooltip.tsx
|
|
4333
|
-
var
|
|
4780
|
+
var React9 = __toESM(require("react"));
|
|
4334
4781
|
var import_tooltip = require("@base-ui/react/tooltip");
|
|
4335
4782
|
|
|
4336
4783
|
// src/cn.ts
|
|
@@ -4351,14 +4798,14 @@ var TooltipProvider = ({
|
|
|
4351
4798
|
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_tooltip.Tooltip.Provider, { delay: delay ?? delayDuration, closeDelay, ...props, children });
|
|
4352
4799
|
var Tooltip = import_tooltip.Tooltip.Root;
|
|
4353
4800
|
var TooltipTrigger = import_tooltip.Tooltip.Trigger;
|
|
4354
|
-
var TooltipContent =
|
|
4801
|
+
var TooltipContent = React9.forwardRef(({ className, side, align, sideOffset = 8, ...props }, ref) => {
|
|
4355
4802
|
const container = usePortalContainer();
|
|
4356
4803
|
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
4804
|
import_tooltip.Tooltip.Popup,
|
|
4358
4805
|
{
|
|
4359
4806
|
ref,
|
|
4360
4807
|
className: cn(
|
|
4361
|
-
"rounded-md bg-[canvas] px-2 py-1 text-xs origin-(--transform-origin) shadow-xs outline-1 outline-
|
|
4808
|
+
"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
4809
|
className
|
|
4363
4810
|
),
|
|
4364
4811
|
...props
|
|
@@ -4369,23 +4816,23 @@ TooltipContent.displayName = "TooltipContent";
|
|
|
4369
4816
|
var createTooltipHandle = import_tooltip.Tooltip.createHandle;
|
|
4370
4817
|
|
|
4371
4818
|
// src/use-measurement.ts
|
|
4372
|
-
var
|
|
4819
|
+
var React10 = __toESM(require("react"));
|
|
4373
4820
|
var INITIAL_STATE = {
|
|
4374
4821
|
hoveredElement: null,
|
|
4375
4822
|
measurements: []
|
|
4376
4823
|
};
|
|
4377
4824
|
function useMeasurement(selectedElement) {
|
|
4378
|
-
const [altHeld, setAltHeld] =
|
|
4379
|
-
const [state, setState] =
|
|
4380
|
-
const [mousePosition, setMousePosition] =
|
|
4381
|
-
const rafRef =
|
|
4382
|
-
const mousePositionRef =
|
|
4383
|
-
const getElementBelow =
|
|
4825
|
+
const [altHeld, setAltHeld] = React10.useState(false);
|
|
4826
|
+
const [state, setState] = React10.useState(INITIAL_STATE);
|
|
4827
|
+
const [mousePosition, setMousePosition] = React10.useState(null);
|
|
4828
|
+
const rafRef = React10.useRef(null);
|
|
4829
|
+
const mousePositionRef = React10.useRef(null);
|
|
4830
|
+
const getElementBelow = React10.useCallback((x, y) => {
|
|
4384
4831
|
const element = elementFromPointWithoutOverlays(x, y);
|
|
4385
4832
|
if (element?.closest("[data-direct-edit-host]")) return null;
|
|
4386
4833
|
return element;
|
|
4387
4834
|
}, []);
|
|
4388
|
-
|
|
4835
|
+
React10.useEffect(() => {
|
|
4389
4836
|
function handleKeyDown(e) {
|
|
4390
4837
|
if (e.key === "Alt") {
|
|
4391
4838
|
e.preventDefault();
|
|
@@ -4416,7 +4863,7 @@ function useMeasurement(selectedElement) {
|
|
|
4416
4863
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
4417
4864
|
};
|
|
4418
4865
|
}, []);
|
|
4419
|
-
|
|
4866
|
+
React10.useEffect(() => {
|
|
4420
4867
|
if (!altHeld || !selectedElement) {
|
|
4421
4868
|
setState(INITIAL_STATE);
|
|
4422
4869
|
return;
|
|
@@ -4475,7 +4922,7 @@ function useMeasurement(selectedElement) {
|
|
|
4475
4922
|
}
|
|
4476
4923
|
|
|
4477
4924
|
// src/measurement-overlay.tsx
|
|
4478
|
-
var
|
|
4925
|
+
var React11 = __toESM(require("react"));
|
|
4479
4926
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
4480
4927
|
var TOMATO = "#E54D2E";
|
|
4481
4928
|
var BLUE = "#0D99FF";
|
|
@@ -4552,16 +4999,18 @@ function MeasurementOverlay({
|
|
|
4552
4999
|
hoveredElement,
|
|
4553
5000
|
measurements
|
|
4554
5001
|
}) {
|
|
4555
|
-
const [, forceUpdate] =
|
|
4556
|
-
|
|
5002
|
+
const [, forceUpdate] = React11.useReducer((x) => x + 1, 0);
|
|
5003
|
+
React11.useEffect(() => {
|
|
4557
5004
|
function handleUpdate() {
|
|
4558
5005
|
requestAnimationFrame(forceUpdate);
|
|
4559
5006
|
}
|
|
4560
5007
|
window.addEventListener("scroll", handleUpdate, true);
|
|
4561
5008
|
window.addEventListener("resize", handleUpdate);
|
|
5009
|
+
window.addEventListener("direct-edit-canvas-change", handleUpdate);
|
|
4562
5010
|
return () => {
|
|
4563
5011
|
window.removeEventListener("scroll", handleUpdate, true);
|
|
4564
5012
|
window.removeEventListener("resize", handleUpdate);
|
|
5013
|
+
window.removeEventListener("direct-edit-canvas-change", handleUpdate);
|
|
4565
5014
|
};
|
|
4566
5015
|
}, [selectedElement]);
|
|
4567
5016
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -4586,7 +5035,7 @@ function MeasurementOverlay({
|
|
|
4586
5035
|
}
|
|
4587
5036
|
|
|
4588
5037
|
// src/use-move.ts
|
|
4589
|
-
var
|
|
5038
|
+
var React12 = __toESM(require("react"));
|
|
4590
5039
|
var INITIAL_DRAG_STATE = {
|
|
4591
5040
|
isDragging: false,
|
|
4592
5041
|
draggedElement: null,
|
|
@@ -4597,19 +5046,19 @@ var INITIAL_DRAG_STATE = {
|
|
|
4597
5046
|
dragOffset: { x: 0, y: 0 }
|
|
4598
5047
|
};
|
|
4599
5048
|
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
|
-
|
|
5049
|
+
const [dragState, setDragState] = React12.useState(INITIAL_DRAG_STATE);
|
|
5050
|
+
const [dropTarget, setDropTarget] = React12.useState(null);
|
|
5051
|
+
const [dropIndicator, setDropIndicator] = React12.useState(null);
|
|
5052
|
+
const dragStateRef = React12.useRef(dragState);
|
|
5053
|
+
const dropTargetRef = React12.useRef(dropTarget);
|
|
5054
|
+
const onMoveCompleteRef = React12.useRef(onMoveComplete);
|
|
5055
|
+
const dragOptionsRef = React12.useRef({});
|
|
5056
|
+
React12.useEffect(() => {
|
|
4608
5057
|
dragStateRef.current = dragState;
|
|
4609
5058
|
dropTargetRef.current = dropTarget;
|
|
4610
5059
|
onMoveCompleteRef.current = onMoveComplete;
|
|
4611
5060
|
});
|
|
4612
|
-
const cancelDrag =
|
|
5061
|
+
const cancelDrag = React12.useCallback(() => {
|
|
4613
5062
|
const current = dragStateRef.current;
|
|
4614
5063
|
if (current.draggedElement) {
|
|
4615
5064
|
current.draggedElement.style.opacity = "";
|
|
@@ -4619,7 +5068,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4619
5068
|
setDropTarget(null);
|
|
4620
5069
|
setDropIndicator(null);
|
|
4621
5070
|
}, []);
|
|
4622
|
-
const completeDrag =
|
|
5071
|
+
const completeDrag = React12.useCallback(() => {
|
|
4623
5072
|
const current = dragStateRef.current;
|
|
4624
5073
|
const target = dropTargetRef.current;
|
|
4625
5074
|
const { draggedElement, originalParent, originalPreviousSibling, originalNextSibling } = current;
|
|
@@ -4653,7 +5102,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4653
5102
|
onMoveCompleteRef.current(draggedElement, moveInfo);
|
|
4654
5103
|
}
|
|
4655
5104
|
}, [cancelDrag]);
|
|
4656
|
-
const startDrag =
|
|
5105
|
+
const startDrag = React12.useCallback(
|
|
4657
5106
|
(e, element, options) => {
|
|
4658
5107
|
const rect = element.getBoundingClientRect();
|
|
4659
5108
|
const parent = element.parentElement;
|
|
@@ -4673,7 +5122,7 @@ function useMove({ onMoveComplete }) {
|
|
|
4673
5122
|
},
|
|
4674
5123
|
[]
|
|
4675
5124
|
);
|
|
4676
|
-
|
|
5125
|
+
React12.useEffect(() => {
|
|
4677
5126
|
if (!dragState.isDragging) return;
|
|
4678
5127
|
function handlePointerMove(e) {
|
|
4679
5128
|
const current = dragStateRef.current;
|
|
@@ -4741,7 +5190,46 @@ function useMove({ onMoveComplete }) {
|
|
|
4741
5190
|
}
|
|
4742
5191
|
|
|
4743
5192
|
// src/use-guidelines.ts
|
|
4744
|
-
var
|
|
5193
|
+
var React13 = __toESM(require("react"));
|
|
5194
|
+
|
|
5195
|
+
// src/utils/snap-targets.ts
|
|
5196
|
+
var SNAP_THRESHOLD_PX = 6;
|
|
5197
|
+
function collectSnapTargets(orientation) {
|
|
5198
|
+
const edges = [];
|
|
5199
|
+
const elements = document.body.querySelectorAll("*");
|
|
5200
|
+
const viewportW = window.innerWidth;
|
|
5201
|
+
const viewportH = window.innerHeight;
|
|
5202
|
+
for (let i = 0; i < elements.length; i++) {
|
|
5203
|
+
const el = elements[i];
|
|
5204
|
+
if (el === document.body || el === document.documentElement) continue;
|
|
5205
|
+
if (el.closest("[data-direct-edit]") || el.closest("[data-direct-edit-host]")) continue;
|
|
5206
|
+
if (el.offsetParent === null && el !== document.body) continue;
|
|
5207
|
+
const rect = el.getBoundingClientRect();
|
|
5208
|
+
if (rect.width < 4 || rect.height < 4) continue;
|
|
5209
|
+
if (rect.right < -200 || rect.bottom < -200 || rect.left > viewportW + 200 || rect.top > viewportH + 200) continue;
|
|
5210
|
+
if (orientation === "horizontal") {
|
|
5211
|
+
edges.push(rect.top, rect.bottom);
|
|
5212
|
+
} else {
|
|
5213
|
+
edges.push(rect.left, rect.right);
|
|
5214
|
+
}
|
|
5215
|
+
if (edges.length >= 2e3) break;
|
|
5216
|
+
}
|
|
5217
|
+
return edges;
|
|
5218
|
+
}
|
|
5219
|
+
function findSnap(viewportPos, snapEdges, threshold) {
|
|
5220
|
+
let best = null;
|
|
5221
|
+
let bestDist = threshold + 1;
|
|
5222
|
+
for (let i = 0; i < snapEdges.length; i++) {
|
|
5223
|
+
const dist = Math.abs(snapEdges[i] - viewportPos);
|
|
5224
|
+
if (dist < bestDist) {
|
|
5225
|
+
bestDist = dist;
|
|
5226
|
+
best = snapEdges[i];
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
return bestDist <= threshold ? best : null;
|
|
5230
|
+
}
|
|
5231
|
+
|
|
5232
|
+
// src/use-guidelines.ts
|
|
4745
5233
|
var STORAGE_KEY = "direct-edit-guidelines";
|
|
4746
5234
|
function isGuidelineOrientation(value) {
|
|
4747
5235
|
return value === "horizontal" || value === "vertical";
|
|
@@ -4778,6 +5266,7 @@ function generateId() {
|
|
|
4778
5266
|
return `gl-${Date.now()}-${idCounter++}`;
|
|
4779
5267
|
}
|
|
4780
5268
|
var RULER_SIZE = 20;
|
|
5269
|
+
var SNAP_VELOCITY_THRESHOLD = 3;
|
|
4781
5270
|
function viewportToCssCoord(hostElement, value, axis) {
|
|
4782
5271
|
if (!hostElement) return value;
|
|
4783
5272
|
const rect = hostElement.getBoundingClientRect();
|
|
@@ -4787,68 +5276,108 @@ function viewportToCssCoord(hostElement, value, axis) {
|
|
|
4787
5276
|
if (size === 0) return value;
|
|
4788
5277
|
return (value - origin) * (cssSize / size);
|
|
4789
5278
|
}
|
|
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 =
|
|
5279
|
+
function useGuidelines(enabled, hostElement, canvas) {
|
|
5280
|
+
const [guidelines, setGuidelines] = React13.useState([]);
|
|
5281
|
+
const [hydrated, setHydrated] = React13.useState(false);
|
|
5282
|
+
const [activeGuidelineId, setActiveGuidelineId] = React13.useState(null);
|
|
5283
|
+
const [dragPosition, setDragPosition] = React13.useState(null);
|
|
5284
|
+
const [isCreating, setIsCreating] = React13.useState(false);
|
|
5285
|
+
const [scrollOffset, setScrollOffset] = React13.useState({ x: 0, y: 0 });
|
|
5286
|
+
const hostRef = React13.useRef(hostElement ?? null);
|
|
4798
5287
|
hostRef.current = hostElement ?? null;
|
|
4799
|
-
const
|
|
4800
|
-
|
|
5288
|
+
const canvasRef = React13.useRef(canvas);
|
|
5289
|
+
canvasRef.current = canvas;
|
|
5290
|
+
const [dragging, setDragging] = React13.useState(false);
|
|
5291
|
+
const guidelinesRef = React13.useRef(guidelines);
|
|
4801
5292
|
guidelinesRef.current = guidelines;
|
|
4802
|
-
const dragInfoRef =
|
|
4803
|
-
|
|
5293
|
+
const dragInfoRef = React13.useRef(null);
|
|
5294
|
+
const snapTargetsRef = React13.useRef([]);
|
|
5295
|
+
const isSnappedRef = React13.useRef(false);
|
|
5296
|
+
const [isSnapped, setIsSnapped] = React13.useState(false);
|
|
5297
|
+
React13.useEffect(() => {
|
|
4804
5298
|
setGuidelines(loadGuidelines());
|
|
4805
5299
|
setHydrated(true);
|
|
4806
5300
|
}, []);
|
|
4807
|
-
|
|
5301
|
+
React13.useEffect(() => {
|
|
4808
5302
|
if (!hydrated) return;
|
|
4809
5303
|
saveGuidelines(guidelines);
|
|
4810
5304
|
}, [guidelines, hydrated]);
|
|
4811
|
-
|
|
5305
|
+
React13.useEffect(() => {
|
|
4812
5306
|
if (!enabled) return;
|
|
4813
5307
|
function update() {
|
|
4814
|
-
setScrollOffset(
|
|
5308
|
+
setScrollOffset((prev) => {
|
|
5309
|
+
const x = window.scrollX;
|
|
5310
|
+
const y = window.scrollY;
|
|
5311
|
+
return prev.x === x && prev.y === y ? prev : { x, y };
|
|
5312
|
+
});
|
|
4815
5313
|
}
|
|
4816
5314
|
update();
|
|
4817
5315
|
window.addEventListener("scroll", update, true);
|
|
4818
5316
|
window.addEventListener("resize", update);
|
|
5317
|
+
window.addEventListener("direct-edit-canvas-change", update);
|
|
4819
5318
|
return () => {
|
|
4820
5319
|
window.removeEventListener("scroll", update, true);
|
|
4821
5320
|
window.removeEventListener("resize", update);
|
|
5321
|
+
window.removeEventListener("direct-edit-canvas-change", update);
|
|
4822
5322
|
};
|
|
4823
5323
|
}, [enabled]);
|
|
4824
|
-
const endDrag =
|
|
5324
|
+
const endDrag = React13.useCallback(() => {
|
|
4825
5325
|
const wasCreating = dragInfoRef.current?.isCreating ?? false;
|
|
4826
5326
|
dragInfoRef.current = null;
|
|
5327
|
+
snapTargetsRef.current = [];
|
|
5328
|
+
isSnappedRef.current = false;
|
|
5329
|
+
setIsSnapped(false);
|
|
4827
5330
|
setDragging(false);
|
|
4828
5331
|
setActiveGuidelineId(null);
|
|
4829
5332
|
setDragPosition(null);
|
|
4830
5333
|
if (wasCreating) setIsCreating(false);
|
|
4831
5334
|
}, []);
|
|
4832
|
-
|
|
5335
|
+
React13.useEffect(() => {
|
|
4833
5336
|
if (!dragging) return;
|
|
4834
5337
|
const info = dragInfoRef.current;
|
|
4835
5338
|
if (!info) return;
|
|
4836
5339
|
const { guidelineId, orientation } = info;
|
|
4837
5340
|
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
return viewportToCssCoord(hostRef.current, raw, axis);
|
|
4841
|
-
}
|
|
5341
|
+
let lastPos = NaN;
|
|
5342
|
+
let lastTime = 0;
|
|
4842
5343
|
function onPointerMove(e) {
|
|
4843
|
-
const
|
|
5344
|
+
const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
|
|
5345
|
+
const now = performance.now();
|
|
5346
|
+
const dt = now - lastTime;
|
|
5347
|
+
const velocity = dt > 0 && !Number.isNaN(lastPos) ? Math.abs(rawViewportPos - lastPos) / dt : 0;
|
|
5348
|
+
lastPos = rawViewportPos;
|
|
5349
|
+
lastTime = now;
|
|
5350
|
+
let effectiveViewportPos = rawViewportPos;
|
|
5351
|
+
let snapped = false;
|
|
5352
|
+
if (velocity < SNAP_VELOCITY_THRESHOLD) {
|
|
5353
|
+
const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
|
|
5354
|
+
if (snapResult !== null) {
|
|
5355
|
+
effectiveViewportPos = snapResult;
|
|
5356
|
+
snapped = true;
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
isSnappedRef.current = snapped;
|
|
5360
|
+
setIsSnapped(snapped);
|
|
5361
|
+
const pos = viewportToCssCoord(hostRef.current, effectiveViewportPos, axis);
|
|
4844
5362
|
setDragPosition(pos);
|
|
4845
|
-
const
|
|
5363
|
+
const c = canvasRef.current;
|
|
5364
|
+
let storedPosition;
|
|
5365
|
+
if (c?.active) {
|
|
5366
|
+
const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5367
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5368
|
+
storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
|
|
5369
|
+
} else {
|
|
5370
|
+
const currentScroll = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5371
|
+
storedPosition = pos + currentScroll;
|
|
5372
|
+
}
|
|
4846
5373
|
setGuidelines(
|
|
4847
|
-
(prev) => prev.map((g) => g.id === guidelineId ? { ...g, position:
|
|
5374
|
+
(prev) => prev.map((g) => g.id === guidelineId ? { ...g, position: storedPosition } : g)
|
|
4848
5375
|
);
|
|
4849
5376
|
}
|
|
4850
5377
|
function onPointerUp(e) {
|
|
4851
|
-
const
|
|
5378
|
+
const rawViewportPos = orientation === "horizontal" ? e.clientY : e.clientX;
|
|
5379
|
+
const snapResult = findSnap(rawViewportPos, snapTargetsRef.current, SNAP_THRESHOLD_PX);
|
|
5380
|
+
const pos = viewportToCssCoord(hostRef.current, snapResult ?? rawViewportPos, axis);
|
|
4852
5381
|
if (pos <= RULER_SIZE) {
|
|
4853
5382
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
4854
5383
|
}
|
|
@@ -4861,22 +5390,32 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4861
5390
|
window.removeEventListener("pointerup", onPointerUp);
|
|
4862
5391
|
};
|
|
4863
5392
|
}, [dragging, endDrag]);
|
|
4864
|
-
|
|
5393
|
+
React13.useEffect(() => {
|
|
4865
5394
|
if (!enabled && dragging) {
|
|
4866
5395
|
endDrag();
|
|
4867
5396
|
}
|
|
4868
5397
|
}, [enabled, dragging, endDrag]);
|
|
4869
|
-
const activeGuideline =
|
|
5398
|
+
const activeGuideline = React13.useMemo(
|
|
4870
5399
|
() => guidelines.find((g) => g.id === activeGuidelineId) ?? null,
|
|
4871
5400
|
[guidelines, activeGuidelineId]
|
|
4872
5401
|
);
|
|
4873
|
-
const startCreate =
|
|
5402
|
+
const startCreate = React13.useCallback(
|
|
4874
5403
|
(orientation, viewportPosition) => {
|
|
4875
5404
|
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4876
5405
|
const pos = viewportToCssCoord(hostRef.current, viewportPosition, axis);
|
|
4877
|
-
const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
4878
5406
|
const id = generateId();
|
|
4879
|
-
const
|
|
5407
|
+
const c = canvasRef.current;
|
|
5408
|
+
let storedPosition;
|
|
5409
|
+
if (c?.active) {
|
|
5410
|
+
const pan = orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5411
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5412
|
+
storedPosition = bo + (pos - bo) / (c.zoom || 1) - pan;
|
|
5413
|
+
} else {
|
|
5414
|
+
const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5415
|
+
storedPosition = pos + scrollPos;
|
|
5416
|
+
}
|
|
5417
|
+
const newGuideline = { id, orientation, position: storedPosition };
|
|
5418
|
+
snapTargetsRef.current = collectSnapTargets(orientation);
|
|
4880
5419
|
setGuidelines((prev) => [...prev, newGuideline]);
|
|
4881
5420
|
setActiveGuidelineId(id);
|
|
4882
5421
|
setDragPosition(pos);
|
|
@@ -4886,19 +5425,29 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4886
5425
|
},
|
|
4887
5426
|
[]
|
|
4888
5427
|
);
|
|
4889
|
-
const startDrag =
|
|
5428
|
+
const startDrag = React13.useCallback((guidelineId) => {
|
|
4890
5429
|
const guideline = guidelinesRef.current.find((g) => g.id === guidelineId);
|
|
4891
5430
|
if (!guideline) return;
|
|
4892
|
-
|
|
5431
|
+
snapTargetsRef.current = collectSnapTargets(guideline.orientation);
|
|
5432
|
+
const c = canvasRef.current;
|
|
5433
|
+
let viewportPos;
|
|
5434
|
+
if (c?.active) {
|
|
5435
|
+
const pan = guideline.orientation === "horizontal" ? c.panY || 0 : c.panX || 0;
|
|
5436
|
+
const bo = guideline.orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
5437
|
+
viewportPos = bo + (guideline.position - bo + pan) * (c.zoom || 1);
|
|
5438
|
+
} else {
|
|
5439
|
+
const scrollPos = guideline.orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
5440
|
+
viewportPos = guideline.position - scrollPos;
|
|
5441
|
+
}
|
|
4893
5442
|
setActiveGuidelineId(guidelineId);
|
|
4894
|
-
setDragPosition(
|
|
5443
|
+
setDragPosition(viewportPos);
|
|
4895
5444
|
dragInfoRef.current = { guidelineId, orientation: guideline.orientation, isCreating: false };
|
|
4896
5445
|
setDragging(true);
|
|
4897
5446
|
}, []);
|
|
4898
|
-
const deleteGuideline =
|
|
5447
|
+
const deleteGuideline = React13.useCallback((guidelineId) => {
|
|
4899
5448
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
4900
5449
|
}, []);
|
|
4901
|
-
const clearAll =
|
|
5450
|
+
const clearAll = React13.useCallback(() => {
|
|
4902
5451
|
setGuidelines([]);
|
|
4903
5452
|
}, []);
|
|
4904
5453
|
return {
|
|
@@ -4906,6 +5455,7 @@ function useGuidelines(enabled, hostElement) {
|
|
|
4906
5455
|
activeGuideline,
|
|
4907
5456
|
dragPosition,
|
|
4908
5457
|
isCreating,
|
|
5458
|
+
isSnapped,
|
|
4909
5459
|
scrollOffset,
|
|
4910
5460
|
startCreate,
|
|
4911
5461
|
startDrag,
|
|
@@ -4960,10 +5510,8 @@ function InteractionOverlay({
|
|
|
4960
5510
|
if (activeTool === "comment") {
|
|
4961
5511
|
if (hasPendingCommentDraft()) return;
|
|
4962
5512
|
const elementUnder2 = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
onAddComment(resolved, { x: e.clientX, y: e.clientY });
|
|
4966
|
-
}
|
|
5513
|
+
const target = elementUnder2 && elementUnder2 !== document.body && elementUnder2 !== document.documentElement ? resolveElementTarget(elementUnder2, selectedElement) : document.body;
|
|
5514
|
+
onAddComment(target, { x: e.clientX, y: e.clientY });
|
|
4967
5515
|
return;
|
|
4968
5516
|
}
|
|
4969
5517
|
if (activeCommentId) {
|
|
@@ -4981,39 +5529,41 @@ function InteractionOverlay({
|
|
|
4981
5529
|
hoverHighlight && (() => {
|
|
4982
5530
|
const cr = hoverHighlight.flexContainer.getBoundingClientRect();
|
|
4983
5531
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4984
|
-
"
|
|
5532
|
+
"div",
|
|
4985
5533
|
{
|
|
4986
5534
|
"data-direct-edit": "hover-highlight",
|
|
4987
5535
|
className: "pointer-events-none fixed inset-0 z-[99991]",
|
|
4988
|
-
width: "100%",
|
|
4989
|
-
height: "100%",
|
|
4990
|
-
style: { width: "100vw", height: "100vh" },
|
|
4991
5536
|
children: [
|
|
4992
5537
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
4993
|
-
"
|
|
5538
|
+
"div",
|
|
4994
5539
|
{
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5540
|
+
style: {
|
|
5541
|
+
position: "absolute",
|
|
5542
|
+
left: cr.left,
|
|
5543
|
+
top: cr.top,
|
|
5544
|
+
width: cr.width,
|
|
5545
|
+
height: cr.height,
|
|
5546
|
+
border: "1px solid #3b82f6",
|
|
5547
|
+
borderRadius: "0px",
|
|
5548
|
+
boxSizing: "border-box"
|
|
5549
|
+
}
|
|
5002
5550
|
}
|
|
5003
5551
|
),
|
|
5004
5552
|
hoverHighlight.children.map((child) => {
|
|
5005
5553
|
const r = child.getBoundingClientRect();
|
|
5006
5554
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
5007
|
-
"
|
|
5555
|
+
"div",
|
|
5008
5556
|
{
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5557
|
+
style: {
|
|
5558
|
+
position: "absolute",
|
|
5559
|
+
left: r.left,
|
|
5560
|
+
top: r.top,
|
|
5561
|
+
width: r.width,
|
|
5562
|
+
height: r.height,
|
|
5563
|
+
border: "1px dashed #3b82f6",
|
|
5564
|
+
borderRadius: "0px",
|
|
5565
|
+
boxSizing: "border-box"
|
|
5566
|
+
}
|
|
5017
5567
|
},
|
|
5018
5568
|
`${r.left}-${r.top}-${r.width}-${r.height}`
|
|
5019
5569
|
);
|
|
@@ -5059,7 +5609,7 @@ function MoveOverlay({ dropIndicator }) {
|
|
|
5059
5609
|
}
|
|
5060
5610
|
|
|
5061
5611
|
// src/selection-overlay.tsx
|
|
5062
|
-
var
|
|
5612
|
+
var React14 = __toESM(require("react"));
|
|
5063
5613
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
5064
5614
|
var BLUE3 = "#0D99FF";
|
|
5065
5615
|
var MAGENTA = "#E11BB6";
|
|
@@ -5073,23 +5623,25 @@ function SelectionOverlay({
|
|
|
5073
5623
|
ghostPosition,
|
|
5074
5624
|
onMoveStart,
|
|
5075
5625
|
showMoveHandle = false,
|
|
5626
|
+
activeTool = "select",
|
|
5076
5627
|
isTextEditing,
|
|
5077
5628
|
onDoubleClick,
|
|
5078
5629
|
onHoverElement,
|
|
5079
5630
|
onClickThrough
|
|
5080
5631
|
}) {
|
|
5081
5632
|
const rectElement = isDragging && draggedElement ? draggedElement : selectedElement;
|
|
5082
|
-
const [rect, setRect] =
|
|
5083
|
-
const [moveHandleRects, setMoveHandleRects] =
|
|
5084
|
-
const cleanupRef =
|
|
5085
|
-
const clickThroughTimerRef =
|
|
5086
|
-
|
|
5633
|
+
const [rect, setRect] = React14.useState(() => rectElement.getBoundingClientRect());
|
|
5634
|
+
const [moveHandleRects, setMoveHandleRects] = React14.useState([]);
|
|
5635
|
+
const cleanupRef = React14.useRef(null);
|
|
5636
|
+
const clickThroughTimerRef = React14.useRef(null);
|
|
5637
|
+
React14.useEffect(() => {
|
|
5087
5638
|
function updateRect() {
|
|
5088
5639
|
setRect(rectElement.getBoundingClientRect());
|
|
5089
5640
|
}
|
|
5090
5641
|
updateRect();
|
|
5091
5642
|
window.addEventListener("scroll", updateRect, true);
|
|
5092
5643
|
window.addEventListener("resize", updateRect);
|
|
5644
|
+
window.addEventListener("direct-edit-canvas-change", updateRect);
|
|
5093
5645
|
const observer = new MutationObserver(updateRect);
|
|
5094
5646
|
observer.observe(rectElement, {
|
|
5095
5647
|
attributes: true,
|
|
@@ -5099,10 +5651,11 @@ function SelectionOverlay({
|
|
|
5099
5651
|
return () => {
|
|
5100
5652
|
window.removeEventListener("scroll", updateRect, true);
|
|
5101
5653
|
window.removeEventListener("resize", updateRect);
|
|
5654
|
+
window.removeEventListener("direct-edit-canvas-change", updateRect);
|
|
5102
5655
|
observer.disconnect();
|
|
5103
5656
|
};
|
|
5104
5657
|
}, [rectElement]);
|
|
5105
|
-
|
|
5658
|
+
React14.useEffect(() => {
|
|
5106
5659
|
return () => {
|
|
5107
5660
|
cleanupRef.current?.();
|
|
5108
5661
|
if (clickThroughTimerRef.current) clearTimeout(clickThroughTimerRef.current);
|
|
@@ -5163,7 +5716,7 @@ function SelectionOverlay({
|
|
|
5163
5716
|
const handleMouseLeave = () => {
|
|
5164
5717
|
onHoverElement?.(null);
|
|
5165
5718
|
};
|
|
5166
|
-
const getMoveHandleTargets =
|
|
5719
|
+
const getMoveHandleTargets = React14.useCallback(() => {
|
|
5167
5720
|
if (!showMoveHandle) return [];
|
|
5168
5721
|
const selectedDisplay = window.getComputedStyle(selectedElement).display;
|
|
5169
5722
|
const selectedIsFlexContainer = selectedDisplay === "flex" || selectedDisplay === "inline-flex";
|
|
@@ -5188,7 +5741,7 @@ function SelectionOverlay({
|
|
|
5188
5741
|
}
|
|
5189
5742
|
return [target];
|
|
5190
5743
|
}, [selectedElement, showMoveHandle]);
|
|
5191
|
-
|
|
5744
|
+
React14.useEffect(() => {
|
|
5192
5745
|
if (!showMoveHandle || isDragging || isTextEditing) {
|
|
5193
5746
|
setMoveHandleRects([]);
|
|
5194
5747
|
return;
|
|
@@ -5228,30 +5781,22 @@ function SelectionOverlay({
|
|
|
5228
5781
|
const displayX = isDragging && ghostPosition ? ghostPosition.x : rect.left;
|
|
5229
5782
|
const displayY = isDragging && ghostPosition ? ghostPosition.y : rect.top;
|
|
5230
5783
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
5231
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5232
|
-
"
|
|
5784
|
+
!isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5785
|
+
"div",
|
|
5233
5786
|
{
|
|
5234
5787
|
"data-direct-edit": "selection-overlay",
|
|
5235
5788
|
style: {
|
|
5236
5789
|
position: "fixed",
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5790
|
+
left: displayX,
|
|
5791
|
+
top: displayY,
|
|
5792
|
+
width: rect.width,
|
|
5793
|
+
height: rect.height,
|
|
5240
5794
|
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
|
-
)
|
|
5795
|
+
zIndex: 99996,
|
|
5796
|
+
border: `1px solid ${BLUE3}`,
|
|
5797
|
+
borderRadius: "0px",
|
|
5798
|
+
boxSizing: "border-box"
|
|
5799
|
+
}
|
|
5255
5800
|
}
|
|
5256
5801
|
),
|
|
5257
5802
|
!isDragging && !isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -5266,7 +5811,7 @@ function SelectionOverlay({
|
|
|
5266
5811
|
height: rect.height,
|
|
5267
5812
|
zIndex: 99996,
|
|
5268
5813
|
cursor: "default",
|
|
5269
|
-
pointerEvents: "auto"
|
|
5814
|
+
pointerEvents: activeTool === "comment" ? "none" : "auto"
|
|
5270
5815
|
},
|
|
5271
5816
|
onPointerDown: handlePointerDown,
|
|
5272
5817
|
onDoubleClick: handleDoubleClick,
|
|
@@ -5308,7 +5853,7 @@ function SelectionOverlay({
|
|
|
5308
5853
|
}
|
|
5309
5854
|
|
|
5310
5855
|
// src/comment-overlay.tsx
|
|
5311
|
-
var
|
|
5856
|
+
var React15 = __toESM(require("react"));
|
|
5312
5857
|
var import_lucide_react = require("lucide-react");
|
|
5313
5858
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
5314
5859
|
function formatRelativeTime(timestamp) {
|
|
@@ -5348,7 +5893,8 @@ function CommentOverlay({
|
|
|
5348
5893
|
onDelete,
|
|
5349
5894
|
onExport,
|
|
5350
5895
|
onSendToAgent,
|
|
5351
|
-
attentionRequest = null
|
|
5896
|
+
attentionRequest = null,
|
|
5897
|
+
draftRef
|
|
5352
5898
|
}) {
|
|
5353
5899
|
if (comments.length === 0) return null;
|
|
5354
5900
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: comments.map((comment, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
@@ -5364,7 +5910,8 @@ function CommentOverlay({
|
|
|
5364
5910
|
onDelete: () => onDelete(comment.id),
|
|
5365
5911
|
onExport: onExport ? () => onExport(comment.id) : void 0,
|
|
5366
5912
|
onSendToAgent: () => onSendToAgent(comment.id),
|
|
5367
|
-
attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0
|
|
5913
|
+
attentionNonce: attentionRequest?.commentId === comment.id ? attentionRequest.nonce : 0,
|
|
5914
|
+
draftRef: activeCommentId === comment.id ? draftRef : void 0
|
|
5368
5915
|
},
|
|
5369
5916
|
comment.id
|
|
5370
5917
|
)) });
|
|
@@ -5380,31 +5927,34 @@ function CommentPin({
|
|
|
5380
5927
|
onDelete,
|
|
5381
5928
|
onExport,
|
|
5382
5929
|
onSendToAgent,
|
|
5383
|
-
attentionNonce
|
|
5930
|
+
attentionNonce,
|
|
5931
|
+
draftRef
|
|
5384
5932
|
}) {
|
|
5385
|
-
const [position, setPosition] =
|
|
5386
|
-
const [elementRect, setElementRect] =
|
|
5387
|
-
const [flipHorizontal, setFlipHorizontal] =
|
|
5388
|
-
const [flipVertical, setFlipVertical] =
|
|
5389
|
-
|
|
5933
|
+
const [position, setPosition] = React15.useState(comment.clickPosition);
|
|
5934
|
+
const [elementRect, setElementRect] = React15.useState(null);
|
|
5935
|
+
const [flipHorizontal, setFlipHorizontal] = React15.useState(false);
|
|
5936
|
+
const [flipVertical, setFlipVertical] = React15.useState(false);
|
|
5937
|
+
React15.useEffect(() => {
|
|
5390
5938
|
function updatePosition() {
|
|
5391
5939
|
if (!comment.element.isConnected) return;
|
|
5392
5940
|
const rect = comment.element.getBoundingClientRect();
|
|
5393
5941
|
setPosition({
|
|
5394
|
-
x: rect.left + comment.relativePosition.x,
|
|
5395
|
-
y: rect.top + comment.relativePosition.y
|
|
5942
|
+
x: rect.left + comment.relativePosition.x * rect.width,
|
|
5943
|
+
y: rect.top + comment.relativePosition.y * rect.height
|
|
5396
5944
|
});
|
|
5397
5945
|
setElementRect(rect);
|
|
5398
5946
|
}
|
|
5399
5947
|
updatePosition();
|
|
5400
5948
|
window.addEventListener("scroll", updatePosition, true);
|
|
5401
5949
|
window.addEventListener("resize", updatePosition);
|
|
5950
|
+
window.addEventListener("direct-edit-canvas-change", updatePosition);
|
|
5402
5951
|
return () => {
|
|
5403
5952
|
window.removeEventListener("scroll", updatePosition, true);
|
|
5404
5953
|
window.removeEventListener("resize", updatePosition);
|
|
5954
|
+
window.removeEventListener("direct-edit-canvas-change", updatePosition);
|
|
5405
5955
|
};
|
|
5406
5956
|
}, [comment.element, comment.relativePosition]);
|
|
5407
|
-
|
|
5957
|
+
React15.useEffect(() => {
|
|
5408
5958
|
if (isActive) {
|
|
5409
5959
|
const hasText = comment.text !== "";
|
|
5410
5960
|
const cardWidth = hasText ? 280 : 220;
|
|
@@ -5470,7 +6020,8 @@ function CommentPin({
|
|
|
5470
6020
|
onUpdateText(text);
|
|
5471
6021
|
},
|
|
5472
6022
|
onCancel: onClose,
|
|
5473
|
-
attentionNonce
|
|
6023
|
+
attentionNonce,
|
|
6024
|
+
draftRef
|
|
5474
6025
|
}
|
|
5475
6026
|
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5476
6027
|
CommentThread,
|
|
@@ -5497,16 +6048,17 @@ function NewCommentInput({
|
|
|
5497
6048
|
flipVertical,
|
|
5498
6049
|
onSubmit,
|
|
5499
6050
|
onCancel,
|
|
5500
|
-
attentionNonce
|
|
6051
|
+
attentionNonce,
|
|
6052
|
+
draftRef
|
|
5501
6053
|
}) {
|
|
5502
|
-
const [text, setText] =
|
|
5503
|
-
const [showError, setShowError] =
|
|
5504
|
-
const inputRef =
|
|
5505
|
-
const cardRef =
|
|
5506
|
-
|
|
6054
|
+
const [text, setText] = React15.useState("");
|
|
6055
|
+
const [showError, setShowError] = React15.useState(false);
|
|
6056
|
+
const inputRef = React15.useRef(null);
|
|
6057
|
+
const cardRef = React15.useRef(null);
|
|
6058
|
+
React15.useEffect(() => {
|
|
5507
6059
|
inputRef.current?.focus();
|
|
5508
6060
|
}, []);
|
|
5509
|
-
|
|
6061
|
+
React15.useEffect(() => {
|
|
5510
6062
|
if (attentionNonce <= 0) return;
|
|
5511
6063
|
setShowError(true);
|
|
5512
6064
|
cardRef.current?.animate?.(
|
|
@@ -5553,7 +6105,10 @@ function NewCommentInput({
|
|
|
5553
6105
|
),
|
|
5554
6106
|
placeholder: "Add a comment...",
|
|
5555
6107
|
value: text,
|
|
5556
|
-
onChange: (e) =>
|
|
6108
|
+
onChange: (e) => {
|
|
6109
|
+
setText(e.target.value);
|
|
6110
|
+
if (draftRef) draftRef.current = e.target.value;
|
|
6111
|
+
},
|
|
5557
6112
|
onKeyDown: (e) => {
|
|
5558
6113
|
e.stopPropagation();
|
|
5559
6114
|
if (e.key === "Enter" && text.trim()) {
|
|
@@ -5595,15 +6150,15 @@ function CommentThread({
|
|
|
5595
6150
|
onExport,
|
|
5596
6151
|
onSendToAgent
|
|
5597
6152
|
}) {
|
|
5598
|
-
const [replyText, setReplyText] =
|
|
5599
|
-
const [copied, setCopied] =
|
|
5600
|
-
const [sendStatus, setSendStatus] =
|
|
5601
|
-
const inputRef =
|
|
5602
|
-
const copyTimerRef =
|
|
5603
|
-
|
|
6153
|
+
const [replyText, setReplyText] = React15.useState("");
|
|
6154
|
+
const [copied, setCopied] = React15.useState(false);
|
|
6155
|
+
const [sendStatus, setSendStatus] = React15.useState("idle");
|
|
6156
|
+
const inputRef = React15.useRef(null);
|
|
6157
|
+
const copyTimerRef = React15.useRef(null);
|
|
6158
|
+
React15.useEffect(() => {
|
|
5604
6159
|
inputRef.current?.focus();
|
|
5605
6160
|
}, []);
|
|
5606
|
-
|
|
6161
|
+
React15.useEffect(() => {
|
|
5607
6162
|
return () => {
|
|
5608
6163
|
if (copyTimerRef.current) {
|
|
5609
6164
|
window.clearTimeout(copyTimerRef.current);
|
|
@@ -5791,12 +6346,12 @@ function CommentThread({
|
|
|
5791
6346
|
}
|
|
5792
6347
|
|
|
5793
6348
|
// src/panel/shared.tsx
|
|
5794
|
-
var
|
|
6349
|
+
var React17 = __toESM(require("react"));
|
|
5795
6350
|
|
|
5796
6351
|
// src/ui/input.tsx
|
|
5797
|
-
var
|
|
6352
|
+
var React16 = __toESM(require("react"));
|
|
5798
6353
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
5799
|
-
var Input =
|
|
6354
|
+
var Input = React16.forwardRef(
|
|
5800
6355
|
({ className, type, ...props }, ref) => {
|
|
5801
6356
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
5802
6357
|
"input",
|
|
@@ -5818,8 +6373,8 @@ Input.displayName = "Input";
|
|
|
5818
6373
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
5819
6374
|
var selectOnFocus = (e) => e.target.select();
|
|
5820
6375
|
function NumberInput({ value: propValue, onValueChange, ...props }) {
|
|
5821
|
-
const [localValue, setLocalValue] =
|
|
5822
|
-
|
|
6376
|
+
const [localValue, setLocalValue] = React17.useState(propValue === null ? "" : String(propValue));
|
|
6377
|
+
React17.useEffect(() => {
|
|
5823
6378
|
setLocalValue(propValue === null ? "" : String(propValue));
|
|
5824
6379
|
}, [propValue]);
|
|
5825
6380
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -5866,9 +6421,9 @@ var SECTION_LABELS = {
|
|
|
5866
6421
|
text: "Text"
|
|
5867
6422
|
};
|
|
5868
6423
|
function useSectionNav(sectionRefs) {
|
|
5869
|
-
const scrollRef =
|
|
5870
|
-
const [activeSection, setActiveSection] =
|
|
5871
|
-
|
|
6424
|
+
const scrollRef = React17.useRef(null);
|
|
6425
|
+
const [activeSection, setActiveSection] = React17.useState("layout");
|
|
6426
|
+
React17.useEffect(() => {
|
|
5872
6427
|
const scrollEl = scrollRef.current;
|
|
5873
6428
|
if (!scrollEl) return;
|
|
5874
6429
|
const handleScroll = () => {
|
|
@@ -5929,10 +6484,10 @@ function SectionNav({
|
|
|
5929
6484
|
}
|
|
5930
6485
|
|
|
5931
6486
|
// src/panel/border-radius-inputs.tsx
|
|
5932
|
-
var
|
|
6487
|
+
var React20 = __toESM(require("react"));
|
|
5933
6488
|
|
|
5934
6489
|
// src/ui/button.tsx
|
|
5935
|
-
var
|
|
6490
|
+
var React18 = __toESM(require("react"));
|
|
5936
6491
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
5937
6492
|
var buttonVariants = {
|
|
5938
6493
|
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 +6506,7 @@ var buttonVariants = {
|
|
|
5951
6506
|
icon: "h-10 w-10"
|
|
5952
6507
|
}
|
|
5953
6508
|
};
|
|
5954
|
-
var Button =
|
|
6509
|
+
var Button = React18.forwardRef(
|
|
5955
6510
|
({ className, variant = "default", size = "default", ...props }, ref) => {
|
|
5956
6511
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5957
6512
|
"button",
|
|
@@ -5971,10 +6526,10 @@ var Button = React17.forwardRef(
|
|
|
5971
6526
|
Button.displayName = "Button";
|
|
5972
6527
|
|
|
5973
6528
|
// src/ui/slider.tsx
|
|
5974
|
-
var
|
|
6529
|
+
var React19 = __toESM(require("react"));
|
|
5975
6530
|
var import_slider = require("@base-ui/react/slider");
|
|
5976
6531
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5977
|
-
var Slider =
|
|
6532
|
+
var Slider = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5978
6533
|
import_slider.Slider.Root,
|
|
5979
6534
|
{
|
|
5980
6535
|
ref,
|
|
@@ -6009,7 +6564,7 @@ function RadiusCornerIcon({ corner, className }) {
|
|
|
6009
6564
|
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
6565
|
}
|
|
6011
6566
|
function BorderRadiusInputs({ values, onChange }) {
|
|
6012
|
-
const [individual, setIndividual] =
|
|
6567
|
+
const [individual, setIndividual] = React20.useState(false);
|
|
6013
6568
|
const handleChange = (corners, numericValue) => {
|
|
6014
6569
|
const newValue = {
|
|
6015
6570
|
numericValue,
|
|
@@ -6142,7 +6697,7 @@ function BorderRadiusInputs({ values, onChange }) {
|
|
|
6142
6697
|
}
|
|
6143
6698
|
|
|
6144
6699
|
// src/panel/border-section.tsx
|
|
6145
|
-
var
|
|
6700
|
+
var React23 = __toESM(require("react"));
|
|
6146
6701
|
|
|
6147
6702
|
// src/ui/select.tsx
|
|
6148
6703
|
var import_select = require("@base-ui/react/select");
|
|
@@ -6207,21 +6762,21 @@ function SimpleSelect({
|
|
|
6207
6762
|
}
|
|
6208
6763
|
|
|
6209
6764
|
// src/ui/color-picker.tsx
|
|
6210
|
-
var
|
|
6765
|
+
var React21 = __toESM(require("react"));
|
|
6211
6766
|
var import_popover = require("@base-ui/react/popover");
|
|
6212
6767
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
6213
6768
|
function ColorPickerPortal(props) {
|
|
6214
6769
|
const container = usePortalContainer();
|
|
6215
6770
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_popover.Popover.Portal, { container, ...props });
|
|
6216
6771
|
}
|
|
6217
|
-
var ColorPickerGroupContext =
|
|
6772
|
+
var ColorPickerGroupContext = React21.createContext(null);
|
|
6218
6773
|
function ColorPickerGroup({ children }) {
|
|
6219
|
-
const [activePickerId, setActivePickerId] =
|
|
6774
|
+
const [activePickerId, setActivePickerId] = React21.useState(null);
|
|
6220
6775
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ColorPickerGroupContext.Provider, { value: { activePickerId, setActivePickerId }, children });
|
|
6221
6776
|
}
|
|
6222
6777
|
function useDrag(onMove) {
|
|
6223
|
-
const ref =
|
|
6224
|
-
const handlePointerEvent =
|
|
6778
|
+
const ref = React21.useRef(null);
|
|
6779
|
+
const handlePointerEvent = React21.useCallback(
|
|
6225
6780
|
(e) => {
|
|
6226
6781
|
const el = ref.current;
|
|
6227
6782
|
if (!el) return;
|
|
@@ -6232,7 +6787,7 @@ function useDrag(onMove) {
|
|
|
6232
6787
|
},
|
|
6233
6788
|
[onMove]
|
|
6234
6789
|
);
|
|
6235
|
-
const onPointerDown =
|
|
6790
|
+
const onPointerDown = React21.useCallback(
|
|
6236
6791
|
(e) => {
|
|
6237
6792
|
e.preventDefault();
|
|
6238
6793
|
ref.current?.setPointerCapture(e.pointerId);
|
|
@@ -6240,7 +6795,7 @@ function useDrag(onMove) {
|
|
|
6240
6795
|
},
|
|
6241
6796
|
[handlePointerEvent]
|
|
6242
6797
|
);
|
|
6243
|
-
const onPointerMove =
|
|
6798
|
+
const onPointerMove = React21.useCallback(
|
|
6244
6799
|
(e) => {
|
|
6245
6800
|
if (e.buttons === 0) return;
|
|
6246
6801
|
handlePointerEvent(e);
|
|
@@ -6310,8 +6865,8 @@ function NumericInput({
|
|
|
6310
6865
|
max,
|
|
6311
6866
|
onChange
|
|
6312
6867
|
}) {
|
|
6313
|
-
const [local, setLocal] =
|
|
6314
|
-
|
|
6868
|
+
const [local, setLocal] = React21.useState(Math.round(value).toString());
|
|
6869
|
+
React21.useEffect(() => {
|
|
6315
6870
|
setLocal(Math.round(value).toString());
|
|
6316
6871
|
}, [value]);
|
|
6317
6872
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
@@ -6333,13 +6888,13 @@ function NumericInput({
|
|
|
6333
6888
|
] });
|
|
6334
6889
|
}
|
|
6335
6890
|
function ColorPickerPopover({ id, value, onChange, children }) {
|
|
6336
|
-
const group =
|
|
6891
|
+
const group = React21.useContext(ColorPickerGroupContext);
|
|
6337
6892
|
const rgb = hexToRgb(value.hex);
|
|
6338
6893
|
const initialHsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
6339
|
-
const [hsv, setHsv] =
|
|
6340
|
-
const [alpha, setAlpha] =
|
|
6341
|
-
const lastSyncedHex =
|
|
6342
|
-
|
|
6894
|
+
const [hsv, setHsv] = React21.useState({ h: initialHsv.h, s: initialHsv.s, v: initialHsv.v });
|
|
6895
|
+
const [alpha, setAlpha] = React21.useState(value.alpha);
|
|
6896
|
+
const lastSyncedHex = React21.useRef(value.hex);
|
|
6897
|
+
React21.useEffect(() => {
|
|
6343
6898
|
if (value.hex !== lastSyncedHex.current) {
|
|
6344
6899
|
const newRgb = hexToRgb(value.hex);
|
|
6345
6900
|
const newHsv = rgbToHsv(newRgb.r, newRgb.g, newRgb.b);
|
|
@@ -6352,7 +6907,7 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6352
6907
|
}
|
|
6353
6908
|
setAlpha(value.alpha);
|
|
6354
6909
|
}, [value.hex, value.alpha]);
|
|
6355
|
-
const emitChange =
|
|
6910
|
+
const emitChange = React21.useCallback(
|
|
6356
6911
|
(h, s, v, a) => {
|
|
6357
6912
|
const newRgb = hsvToRgb(h, s, v);
|
|
6358
6913
|
const hex = rgbToHex(newRgb.r, newRgb.g, newRgb.b);
|
|
@@ -6433,11 +6988,11 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6433
6988
|
const handleOpenChange = isControlled ? (open) => {
|
|
6434
6989
|
group.setActivePickerId(open ? id : null);
|
|
6435
6990
|
} : void 0;
|
|
6436
|
-
const popupRef =
|
|
6437
|
-
const triggerRef =
|
|
6438
|
-
const onCloseRef =
|
|
6991
|
+
const popupRef = React21.useRef(null);
|
|
6992
|
+
const triggerRef = React21.useRef(null);
|
|
6993
|
+
const onCloseRef = React21.useRef();
|
|
6439
6994
|
onCloseRef.current = () => group?.setActivePickerId(null);
|
|
6440
|
-
|
|
6995
|
+
React21.useEffect(() => {
|
|
6441
6996
|
if (!isOpen) return;
|
|
6442
6997
|
function handlePointerDown(e) {
|
|
6443
6998
|
const path = e.composedPath();
|
|
@@ -6507,8 +7062,8 @@ function ColorPickerPopover({ id, value, onChange, children }) {
|
|
|
6507
7062
|
] });
|
|
6508
7063
|
}
|
|
6509
7064
|
function HexInput({ value, onChange }) {
|
|
6510
|
-
const [local, setLocal] =
|
|
6511
|
-
|
|
7065
|
+
const [local, setLocal] = React21.useState(value);
|
|
7066
|
+
React21.useEffect(() => {
|
|
6512
7067
|
setLocal(value);
|
|
6513
7068
|
}, [value]);
|
|
6514
7069
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -6527,8 +7082,8 @@ function HexInput({ value, onChange }) {
|
|
|
6527
7082
|
);
|
|
6528
7083
|
}
|
|
6529
7084
|
function AlphaInput({ value, onChange }) {
|
|
6530
|
-
const [local, setLocal] =
|
|
6531
|
-
|
|
7085
|
+
const [local, setLocal] = React21.useState(value.toString());
|
|
7086
|
+
React21.useEffect(() => {
|
|
6532
7087
|
setLocal(value.toString());
|
|
6533
7088
|
}, [value]);
|
|
6534
7089
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -6548,13 +7103,13 @@ function AlphaInput({ value, onChange }) {
|
|
|
6548
7103
|
}
|
|
6549
7104
|
|
|
6550
7105
|
// src/panel/fill-section.tsx
|
|
6551
|
-
var
|
|
7106
|
+
var React22 = __toESM(require("react"));
|
|
6552
7107
|
var import_lucide_react4 = require("lucide-react");
|
|
6553
7108
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
6554
7109
|
function ColorInput({ id, label, icon, value, onChange }) {
|
|
6555
|
-
const [hexInput, setHexInput] =
|
|
6556
|
-
const [alphaInput, setAlphaInput] =
|
|
6557
|
-
|
|
7110
|
+
const [hexInput, setHexInput] = React22.useState(value.hex);
|
|
7111
|
+
const [alphaInput, setAlphaInput] = React22.useState(value.alpha.toString());
|
|
7112
|
+
React22.useEffect(() => {
|
|
6558
7113
|
setHexInput(value.hex);
|
|
6559
7114
|
setAlphaInput(value.alpha.toString());
|
|
6560
7115
|
}, [value.hex, value.alpha]);
|
|
@@ -6745,7 +7300,7 @@ function BorderSideIcon({ side, className }) {
|
|
|
6745
7300
|
] });
|
|
6746
7301
|
}
|
|
6747
7302
|
function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, borderPosition, borderStyleControlPreference, onPositionChange, outlineStyle, outlineWidth }) {
|
|
6748
|
-
const [selectedSide, setSelectedSide] =
|
|
7303
|
+
const [selectedSide, setSelectedSide] = React23.useState("All");
|
|
6749
7304
|
const isOutline = borderPosition === "outline";
|
|
6750
7305
|
const activeSides = selectedSide === "All" || selectedSide === "Custom" ? BORDER_SIDES : [selectedSide];
|
|
6751
7306
|
const stylesMatch = activeSides.every(
|
|
@@ -6857,7 +7412,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6857
7412
|
onValueChange: (val) => handleStyleChange(val),
|
|
6858
7413
|
options: BORDER_STYLE_OPTIONS,
|
|
6859
7414
|
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
|
|
7415
|
+
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
7416
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "flex items-center gap-1.5", children: [
|
|
6862
7417
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react5.Square, { className: "size-3.5 text-muted-foreground" }),
|
|
6863
7418
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: currentStyleLabel })
|
|
@@ -6873,7 +7428,7 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6873
7428
|
onValueChange: (val) => handleSideChange(val),
|
|
6874
7429
|
options: BORDER_SIDE_OPTIONS.map((side) => ({ value: side, label: side })),
|
|
6875
7430
|
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
|
|
7431
|
+
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
7432
|
}
|
|
6878
7433
|
)
|
|
6879
7434
|
] }),
|
|
@@ -6893,23 +7448,27 @@ function BorderInputs({ border, borderColor, outlineColor, onChange, onBatchChan
|
|
|
6893
7448
|
)
|
|
6894
7449
|
] }) }, side);
|
|
6895
7450
|
}) }),
|
|
6896
|
-
activeColor && activeColorChange && /* @__PURE__ */ (0, import_jsx_runtime18.
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
7451
|
+
activeColor && activeColorChange && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
7452
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
7453
|
+
ColorInput,
|
|
7454
|
+
{
|
|
7455
|
+
id: isOutline ? "outline-color" : "border-color",
|
|
7456
|
+
label: isOutline ? "Outline" : "Border",
|
|
7457
|
+
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" }),
|
|
7458
|
+
value: activeColor,
|
|
7459
|
+
onChange: activeColorChange
|
|
7460
|
+
}
|
|
7461
|
+
) }),
|
|
7462
|
+
borderStyleControlPreference === "icon" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-[30px] shrink-0" }),
|
|
7463
|
+
!isOutline && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-[30px] shrink-0" })
|
|
7464
|
+
] })
|
|
6906
7465
|
] });
|
|
6907
7466
|
}
|
|
6908
7467
|
function BorderSection({ border, borderColor, outlineColor, borderStyleControlPreference, onChange, onBatchChange, onBorderColorChange, onOutlineColorChange, onSetCSS, pendingStyles }) {
|
|
6909
7468
|
const hasOutlinePending = Boolean(
|
|
6910
7469
|
pendingStyles?.["outline-style"] || pendingStyles?.["outline-width"]
|
|
6911
7470
|
);
|
|
6912
|
-
const [borderPosition, setBorderPosition] =
|
|
7471
|
+
const [borderPosition, setBorderPosition] = React23.useState(
|
|
6913
7472
|
hasOutlinePending ? "outline" : "border"
|
|
6914
7473
|
);
|
|
6915
7474
|
const isOutline = borderPosition === "outline";
|
|
@@ -7015,7 +7574,7 @@ function BorderSection({ border, borderColor, outlineColor, borderStyleControlPr
|
|
|
7015
7574
|
}
|
|
7016
7575
|
|
|
7017
7576
|
// src/panel/shadow-section.tsx
|
|
7018
|
-
var
|
|
7577
|
+
var React24 = __toESM(require("react"));
|
|
7019
7578
|
|
|
7020
7579
|
// src/shadow-utils.ts
|
|
7021
7580
|
var TAILWIND_SHADOW_PRESETS = [
|
|
@@ -7152,9 +7711,9 @@ function ShadowLayerEditor({
|
|
|
7152
7711
|
onChange,
|
|
7153
7712
|
onRemoveLayer
|
|
7154
7713
|
}) {
|
|
7155
|
-
const [hexInput, setHexInput] =
|
|
7156
|
-
const [alphaInput, setAlphaInput] =
|
|
7157
|
-
|
|
7714
|
+
const [hexInput, setHexInput] = React24.useState(layer.color.hex);
|
|
7715
|
+
const [alphaInput, setAlphaInput] = React24.useState(String(layer.color.alpha));
|
|
7716
|
+
React24.useEffect(() => {
|
|
7158
7717
|
setHexInput(layer.color.hex);
|
|
7159
7718
|
setAlphaInput(String(layer.color.alpha));
|
|
7160
7719
|
}, [layer.color.hex, layer.color.alpha]);
|
|
@@ -7245,10 +7804,10 @@ function ShadowLayerEditor({
|
|
|
7245
7804
|
}
|
|
7246
7805
|
function ShadowSection({ boxShadow, onSetCSS, pendingStyles }) {
|
|
7247
7806
|
const effectiveShadow = (pendingStyles?.["box-shadow"] ?? boxShadow ?? "none").trim();
|
|
7248
|
-
const parsedLayers =
|
|
7249
|
-
const [layers, setLayers] =
|
|
7807
|
+
const parsedLayers = React24.useMemo(() => parseShadowLayers(effectiveShadow), [effectiveShadow]);
|
|
7808
|
+
const [layers, setLayers] = React24.useState(parsedLayers);
|
|
7250
7809
|
const hasShadow = layers.length > 0;
|
|
7251
|
-
|
|
7810
|
+
React24.useEffect(() => {
|
|
7252
7811
|
setLayers(parsedLayers);
|
|
7253
7812
|
}, [parsedLayers]);
|
|
7254
7813
|
const commitLayers = (nextLayers) => {
|
|
@@ -7540,7 +8099,7 @@ function PanelHeader({
|
|
|
7540
8099
|
}
|
|
7541
8100
|
|
|
7542
8101
|
// src/panel/panel-footer.tsx
|
|
7543
|
-
var
|
|
8102
|
+
var React25 = __toESM(require("react"));
|
|
7544
8103
|
var import_lucide_react9 = require("lucide-react");
|
|
7545
8104
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7546
8105
|
var panelBarBaseClass2 = "flex h-11 shrink-0 items-center border-border/50 bg-background pl-3 pr-2";
|
|
@@ -7554,9 +8113,9 @@ function PanelFooter({
|
|
|
7554
8113
|
onPointerUp,
|
|
7555
8114
|
onPointerCancel
|
|
7556
8115
|
}) {
|
|
7557
|
-
const [copied, setCopied] =
|
|
7558
|
-
const [copyError, setCopyError] =
|
|
7559
|
-
const [sendStatus, setSendStatus] =
|
|
8116
|
+
const [copied, setCopied] = React25.useState(false);
|
|
8117
|
+
const [copyError, setCopyError] = React25.useState(false);
|
|
8118
|
+
const [sendStatus, setSendStatus] = React25.useState("idle");
|
|
7560
8119
|
const handleCopy = async () => {
|
|
7561
8120
|
const success = await onExportEdits();
|
|
7562
8121
|
if (success) {
|
|
@@ -7624,11 +8183,11 @@ function PanelFooter({
|
|
|
7624
8183
|
}
|
|
7625
8184
|
|
|
7626
8185
|
// src/panel/spacing-inputs.tsx
|
|
7627
|
-
var
|
|
8186
|
+
var React26 = __toESM(require("react"));
|
|
7628
8187
|
var import_lucide_react10 = require("lucide-react");
|
|
7629
8188
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
7630
8189
|
function SpacingInputs({ prefix, values, onChange }) {
|
|
7631
|
-
const [individual, setIndividual] =
|
|
8190
|
+
const [individual, setIndividual] = React26.useState(false);
|
|
7632
8191
|
const allowNegative = prefix === "margin";
|
|
7633
8192
|
const handleChange = (sides, numericValue) => {
|
|
7634
8193
|
const clamped = allowNegative ? numericValue : Math.max(0, numericValue);
|
|
@@ -7746,7 +8305,7 @@ function SpacingInputs({ prefix, values, onChange }) {
|
|
|
7746
8305
|
}
|
|
7747
8306
|
|
|
7748
8307
|
// src/panel/sizing-inputs.tsx
|
|
7749
|
-
var
|
|
8308
|
+
var React27 = __toESM(require("react"));
|
|
7750
8309
|
var import_lucide_react11 = require("lucide-react");
|
|
7751
8310
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
7752
8311
|
var SIZING_OPTIONS = [
|
|
@@ -7762,8 +8321,8 @@ var DISTRIBUTE_LABELS = {
|
|
|
7762
8321
|
"space-evenly": "Evenly"
|
|
7763
8322
|
};
|
|
7764
8323
|
function SizingFixedInput({ value, onValueChange }) {
|
|
7765
|
-
const [localValue, setLocalValue] =
|
|
7766
|
-
|
|
8324
|
+
const [localValue, setLocalValue] = React27.useState(String(value));
|
|
8325
|
+
React27.useEffect(() => {
|
|
7767
8326
|
setLocalValue(String(value));
|
|
7768
8327
|
}, [value]);
|
|
7769
8328
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
@@ -7824,9 +8383,9 @@ function SizingDropdown({ label, value, onChange }) {
|
|
|
7824
8383
|
}
|
|
7825
8384
|
function SizingInputs({ width, height, onWidthChange, onHeightChange }) {
|
|
7826
8385
|
const { selectedElement } = useDirectEditState();
|
|
7827
|
-
const [locked, setLocked] =
|
|
7828
|
-
const ratioRef =
|
|
7829
|
-
|
|
8386
|
+
const [locked, setLocked] = React27.useState(false);
|
|
8387
|
+
const ratioRef = React27.useRef(1);
|
|
8388
|
+
React27.useEffect(() => {
|
|
7830
8389
|
setLocked(false);
|
|
7831
8390
|
}, [selectedElement]);
|
|
7832
8391
|
const canLock = width.mode === "fixed" && height.mode === "fixed" && height.value.numericValue > 0 && width.value.numericValue > 0;
|
|
@@ -8082,7 +8641,7 @@ function LayoutSection({
|
|
|
8082
8641
|
}
|
|
8083
8642
|
|
|
8084
8643
|
// src/use-panel-position.ts
|
|
8085
|
-
var
|
|
8644
|
+
var React28 = __toESM(require("react"));
|
|
8086
8645
|
var PANEL_WIDTH = 300;
|
|
8087
8646
|
var PANEL_HEIGHT = 420;
|
|
8088
8647
|
var STORAGE_KEY2 = "direct-edit-panel-position";
|
|
@@ -8164,14 +8723,14 @@ function getInitialPosition() {
|
|
|
8164
8723
|
});
|
|
8165
8724
|
}
|
|
8166
8725
|
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
|
-
|
|
8726
|
+
const [position, setPosition] = React28.useState(getInitialPosition);
|
|
8727
|
+
const [isDragging, setIsDragging] = React28.useState(false);
|
|
8728
|
+
const [isSnapping, setIsSnapping] = React28.useState(false);
|
|
8729
|
+
const [dragOffset, setDragOffset] = React28.useState({ x: 0, y: 0 });
|
|
8730
|
+
const snapTimerRef = React28.useRef(null);
|
|
8731
|
+
const panelRef = React28.useRef(null);
|
|
8732
|
+
const positionRef = React28.useRef(position);
|
|
8733
|
+
React28.useEffect(() => {
|
|
8175
8734
|
positionRef.current = position;
|
|
8176
8735
|
}, [position]);
|
|
8177
8736
|
const handlePointerDown = (e) => {
|
|
@@ -8227,7 +8786,7 @@ function usePanelPosition() {
|
|
|
8227
8786
|
} catch {
|
|
8228
8787
|
}
|
|
8229
8788
|
};
|
|
8230
|
-
|
|
8789
|
+
React28.useEffect(() => {
|
|
8231
8790
|
function handleResize() {
|
|
8232
8791
|
setPosition((prev) => {
|
|
8233
8792
|
const next = snapToEdge(prev);
|
|
@@ -8238,7 +8797,7 @@ function usePanelPosition() {
|
|
|
8238
8797
|
window.addEventListener("resize", handleResize);
|
|
8239
8798
|
return () => window.removeEventListener("resize", handleResize);
|
|
8240
8799
|
}, []);
|
|
8241
|
-
|
|
8800
|
+
React28.useEffect(() => {
|
|
8242
8801
|
return () => {
|
|
8243
8802
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
8244
8803
|
};
|
|
@@ -8299,12 +8858,12 @@ function DirectEditPanelInner({
|
|
|
8299
8858
|
const canTriggerSend = canSendToAgent || hasPendingChanges;
|
|
8300
8859
|
const isDraggable = onHeaderPointerDown !== void 0;
|
|
8301
8860
|
const sectionRefs = {
|
|
8302
|
-
layout:
|
|
8303
|
-
radius:
|
|
8304
|
-
border:
|
|
8305
|
-
shadow:
|
|
8306
|
-
colors:
|
|
8307
|
-
text:
|
|
8861
|
+
layout: React29.useRef(null),
|
|
8862
|
+
radius: React29.useRef(null),
|
|
8863
|
+
border: React29.useRef(null),
|
|
8864
|
+
shadow: React29.useRef(null),
|
|
8865
|
+
colors: React29.useRef(null),
|
|
8866
|
+
text: React29.useRef(null)
|
|
8308
8867
|
};
|
|
8309
8868
|
const { scrollRef, activeSection } = useSectionNav(sectionRefs);
|
|
8310
8869
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
@@ -8347,7 +8906,7 @@ function DirectEditPanelInner({
|
|
|
8347
8906
|
sectionRefs
|
|
8348
8907
|
}
|
|
8349
8908
|
),
|
|
8350
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 overflow-y-auto backdrop-blur-xl bg-background/85", ref: scrollRef, children: [
|
|
8909
|
+
/* @__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
8910
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
8352
8911
|
LayoutSection,
|
|
8353
8912
|
{
|
|
@@ -8502,8 +9061,12 @@ function DirectEditPanelContent() {
|
|
|
8502
9061
|
handlePointerUp,
|
|
8503
9062
|
handlePointerCancel
|
|
8504
9063
|
} = usePanelPosition();
|
|
8505
|
-
const [hoverHighlight, setHoverHighlight] =
|
|
8506
|
-
const [commentInputAttention, setCommentInputAttention] =
|
|
9064
|
+
const [hoverHighlight, setHoverHighlight] = React29.useState(null);
|
|
9065
|
+
const [commentInputAttention, setCommentInputAttention] = React29.useState(null);
|
|
9066
|
+
const commentDraftRef = React29.useRef("");
|
|
9067
|
+
React29.useEffect(() => {
|
|
9068
|
+
commentDraftRef.current = "";
|
|
9069
|
+
}, [activeCommentId]);
|
|
8507
9070
|
const { isActive: measurementActive, hoveredElement, measurements, mousePosition } = useMeasurement(
|
|
8508
9071
|
isOpen ? selectedElement : null
|
|
8509
9072
|
);
|
|
@@ -8514,21 +9077,29 @@ function DirectEditPanelContent() {
|
|
|
8514
9077
|
} = useMove({
|
|
8515
9078
|
onMoveComplete: handleMoveComplete
|
|
8516
9079
|
});
|
|
8517
|
-
const triggerCommentInputAttention =
|
|
9080
|
+
const triggerCommentInputAttention = React29.useCallback((commentId) => {
|
|
8518
9081
|
setCommentInputAttention((prev) => prev?.commentId === commentId ? { commentId, nonce: prev.nonce + 1 } : { commentId, nonce: 1 });
|
|
8519
9082
|
}, []);
|
|
8520
|
-
const hasPendingCommentDraft =
|
|
9083
|
+
const hasPendingCommentDraft = React29.useCallback((nextCommentId = null) => {
|
|
8521
9084
|
if (!activeCommentId) return false;
|
|
8522
9085
|
if (nextCommentId && nextCommentId === activeCommentId) return false;
|
|
8523
9086
|
const active = comments.find((comment) => comment.id === activeCommentId);
|
|
8524
|
-
if (!active
|
|
9087
|
+
if (!active) return false;
|
|
9088
|
+
const hasUnsentDraft = active.text.trim().length === 0 && commentDraftRef.current.trim().length > 0;
|
|
9089
|
+
if (!hasUnsentDraft) return false;
|
|
8525
9090
|
triggerCommentInputAttention(active.id);
|
|
8526
9091
|
return true;
|
|
8527
9092
|
}, [activeCommentId, comments, triggerCommentInputAttention]);
|
|
8528
|
-
const handleSetActiveComment =
|
|
8529
|
-
if (
|
|
9093
|
+
const handleSetActiveComment = React29.useCallback((id) => {
|
|
9094
|
+
if (hasPendingCommentDraft(id)) return;
|
|
9095
|
+
if (activeCommentId && activeCommentId !== id) {
|
|
9096
|
+
const active = comments.find((comment) => comment.id === activeCommentId);
|
|
9097
|
+
if (active && active.text.trim().length === 0) {
|
|
9098
|
+
deleteComment(active.id);
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
8530
9101
|
setActiveCommentId(id);
|
|
8531
|
-
}, [hasPendingCommentDraft, setActiveCommentId]);
|
|
9102
|
+
}, [activeCommentId, comments, hasPendingCommentDraft, deleteComment, setActiveCommentId]);
|
|
8532
9103
|
const overlay = editModeActive && container ? (0, import_react_dom.createPortal)(
|
|
8533
9104
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
8534
9105
|
InteractionOverlay,
|
|
@@ -8541,7 +9112,7 @@ function DirectEditPanelContent() {
|
|
|
8541
9112
|
onSelectElement: selectElement,
|
|
8542
9113
|
onStartTextEditing: startTextEditing,
|
|
8543
9114
|
onAddComment: addComment,
|
|
8544
|
-
onSetActiveCommentId:
|
|
9115
|
+
onSetActiveCommentId: handleSetActiveComment,
|
|
8545
9116
|
onSetHoverHighlight: setHoverHighlight,
|
|
8546
9117
|
hasPendingCommentDraft
|
|
8547
9118
|
}
|
|
@@ -8560,7 +9131,8 @@ function DirectEditPanelContent() {
|
|
|
8560
9131
|
onDelete: deleteComment,
|
|
8561
9132
|
onExport: exportComment,
|
|
8562
9133
|
onSendToAgent: sendCommentToAgent2,
|
|
8563
|
-
attentionRequest: commentInputAttention
|
|
9134
|
+
attentionRequest: commentInputAttention,
|
|
9135
|
+
draftRef: commentDraftRef
|
|
8564
9136
|
}
|
|
8565
9137
|
),
|
|
8566
9138
|
container
|
|
@@ -8602,6 +9174,7 @@ function DirectEditPanelContent() {
|
|
|
8602
9174
|
ghostPosition: dragState.ghostPosition,
|
|
8603
9175
|
onMoveStart: handleMoveStart,
|
|
8604
9176
|
showMoveHandle,
|
|
9177
|
+
activeTool,
|
|
8605
9178
|
isTextEditing: Boolean(textEditingElement),
|
|
8606
9179
|
onDoubleClick: (clientX, clientY) => {
|
|
8607
9180
|
if (!selectedElement) return;
|
|
@@ -8707,8 +9280,8 @@ function DirectEditPanelContent() {
|
|
|
8707
9280
|
);
|
|
8708
9281
|
}
|
|
8709
9282
|
function DirectEditPanel() {
|
|
8710
|
-
const [mounted, setMounted] =
|
|
8711
|
-
|
|
9283
|
+
const [mounted, setMounted] = React29.useState(false);
|
|
9284
|
+
React29.useEffect(() => {
|
|
8712
9285
|
setMounted(true);
|
|
8713
9286
|
}, []);
|
|
8714
9287
|
if (!mounted) {
|
|
@@ -8718,26 +9291,59 @@ function DirectEditPanel() {
|
|
|
8718
9291
|
}
|
|
8719
9292
|
|
|
8720
9293
|
// src/toolbar.tsx
|
|
8721
|
-
var
|
|
9294
|
+
var React36 = __toESM(require("react"));
|
|
8722
9295
|
var import_react_dom3 = require("react-dom");
|
|
8723
9296
|
|
|
8724
9297
|
// src/rulers-overlay.tsx
|
|
8725
|
-
var
|
|
9298
|
+
var React30 = __toESM(require("react"));
|
|
8726
9299
|
var import_react_dom2 = require("react-dom");
|
|
8727
9300
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
8728
9301
|
var RULER_SIZE2 = 20;
|
|
8729
9302
|
var GUIDELINE_COLOR = "#FF6B6B";
|
|
9303
|
+
var SNAPPED_COLOR = "#0D99FF";
|
|
8730
9304
|
var HIT_ZONE = 9;
|
|
9305
|
+
function computeCanvasRulerScrollOffset(pan, zoom, bodyOffset2) {
|
|
9306
|
+
if (zoom === 0) return -pan;
|
|
9307
|
+
return bodyOffset2 * (1 - 1 / zoom) - pan;
|
|
9308
|
+
}
|
|
9309
|
+
function computeTickIntervals(zoom) {
|
|
9310
|
+
const MIN_LABEL_SPACING_PX = 80;
|
|
9311
|
+
const rawInterval = MIN_LABEL_SPACING_PX / zoom;
|
|
9312
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval)));
|
|
9313
|
+
const residual = rawInterval / magnitude;
|
|
9314
|
+
let nice;
|
|
9315
|
+
if (residual <= 1) nice = 1;
|
|
9316
|
+
else if (residual <= 2) nice = 2;
|
|
9317
|
+
else if (residual <= 2.5) nice = 2.5;
|
|
9318
|
+
else if (residual <= 5) nice = 5;
|
|
9319
|
+
else nice = 10;
|
|
9320
|
+
const major = nice * magnitude;
|
|
9321
|
+
const stepsPerMajor = 10;
|
|
9322
|
+
const minor = major / stepsPerMajor;
|
|
9323
|
+
return { major, minor, stepsPerMajor };
|
|
9324
|
+
}
|
|
9325
|
+
function getColorSchemeQuery() {
|
|
9326
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
9327
|
+
return null;
|
|
9328
|
+
}
|
|
9329
|
+
return window.matchMedia("(prefers-color-scheme: dark)");
|
|
9330
|
+
}
|
|
8731
9331
|
function subscribeColorScheme(cb) {
|
|
8732
|
-
const mq =
|
|
8733
|
-
mq
|
|
8734
|
-
|
|
9332
|
+
const mq = getColorSchemeQuery();
|
|
9333
|
+
if (!mq) return () => {
|
|
9334
|
+
};
|
|
9335
|
+
if (typeof mq.addEventListener === "function") {
|
|
9336
|
+
mq.addEventListener("change", cb);
|
|
9337
|
+
return () => mq.removeEventListener("change", cb);
|
|
9338
|
+
}
|
|
9339
|
+
mq.addListener(cb);
|
|
9340
|
+
return () => mq.removeListener(cb);
|
|
8735
9341
|
}
|
|
8736
9342
|
function getColorScheme() {
|
|
8737
|
-
return
|
|
9343
|
+
return getColorSchemeQuery()?.matches ?? false;
|
|
8738
9344
|
}
|
|
8739
9345
|
function useSystemDark() {
|
|
8740
|
-
return
|
|
9346
|
+
return React30.useSyncExternalStore(subscribeColorScheme, getColorScheme, () => false);
|
|
8741
9347
|
}
|
|
8742
9348
|
var rulerFont = {
|
|
8743
9349
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -8746,13 +9352,14 @@ var rulerFont = {
|
|
|
8746
9352
|
};
|
|
8747
9353
|
function HorizontalRuler({
|
|
8748
9354
|
scrollOffset,
|
|
9355
|
+
zoom = 1,
|
|
8749
9356
|
onPointerDown
|
|
8750
9357
|
}) {
|
|
8751
|
-
const canvasRef =
|
|
9358
|
+
const canvasRef = React30.useRef(null);
|
|
8752
9359
|
const viewportWidth = useViewportWidth();
|
|
8753
9360
|
const { theme } = useDirectEditState();
|
|
8754
9361
|
const systemDark = useSystemDark();
|
|
8755
|
-
|
|
9362
|
+
React30.useEffect(() => {
|
|
8756
9363
|
const canvas = canvasRef.current;
|
|
8757
9364
|
if (!canvas) return;
|
|
8758
9365
|
const dpr = window.devicePixelRatio || 1;
|
|
@@ -8770,12 +9377,16 @@ function HorizontalRuler({
|
|
|
8770
9377
|
const computed = getComputedStyle(canvas);
|
|
8771
9378
|
const tick = computed.getPropertyValue("color");
|
|
8772
9379
|
const label = tick;
|
|
8773
|
-
const
|
|
8774
|
-
const
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
9380
|
+
const { minor, stepsPerMajor } = computeTickIntervals(zoom);
|
|
9381
|
+
const midIdx = stepsPerMajor / 2;
|
|
9382
|
+
const visibleContentWidth = width / zoom;
|
|
9383
|
+
const startIdx = Math.floor(scrollOffset.x / minor);
|
|
9384
|
+
const endIdx = Math.ceil((scrollOffset.x + visibleContentWidth) / minor);
|
|
9385
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
9386
|
+
const px = i * minor;
|
|
9387
|
+
const x = (px - scrollOffset.x) * zoom;
|
|
9388
|
+
const isMajor = i % stepsPerMajor === 0;
|
|
9389
|
+
const isMid = !isMajor && i % midIdx === 0;
|
|
8779
9390
|
ctx.beginPath();
|
|
8780
9391
|
ctx.moveTo(x, height);
|
|
8781
9392
|
ctx.lineTo(x, height - (isMajor ? 10 : isMid ? 7 : 4));
|
|
@@ -8783,15 +9394,15 @@ function HorizontalRuler({
|
|
|
8783
9394
|
ctx.globalAlpha = 0.6;
|
|
8784
9395
|
ctx.lineWidth = 1;
|
|
8785
9396
|
ctx.stroke();
|
|
8786
|
-
if (isMajor
|
|
9397
|
+
if (isMajor) {
|
|
8787
9398
|
ctx.globalAlpha = 1;
|
|
8788
9399
|
ctx.fillStyle = label;
|
|
8789
9400
|
ctx.font = "9px system-ui, -apple-system, sans-serif";
|
|
8790
9401
|
ctx.textAlign = "center";
|
|
8791
|
-
ctx.fillText(String(px), x, 9);
|
|
9402
|
+
ctx.fillText(String(Math.round(px)), x, 9);
|
|
8792
9403
|
}
|
|
8793
9404
|
}
|
|
8794
|
-
}, [scrollOffset.x, viewportWidth, theme, systemDark]);
|
|
9405
|
+
}, [scrollOffset.x, viewportWidth, zoom, theme, systemDark]);
|
|
8795
9406
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8796
9407
|
"div",
|
|
8797
9408
|
{
|
|
@@ -8817,13 +9428,14 @@ function HorizontalRuler({
|
|
|
8817
9428
|
}
|
|
8818
9429
|
function VerticalRuler({
|
|
8819
9430
|
scrollOffset,
|
|
9431
|
+
zoom = 1,
|
|
8820
9432
|
onPointerDown
|
|
8821
9433
|
}) {
|
|
8822
|
-
const canvasRef =
|
|
9434
|
+
const canvasRef = React30.useRef(null);
|
|
8823
9435
|
const viewportHeight = useViewportHeight();
|
|
8824
9436
|
const { theme } = useDirectEditState();
|
|
8825
9437
|
const systemDark = useSystemDark();
|
|
8826
|
-
|
|
9438
|
+
React30.useEffect(() => {
|
|
8827
9439
|
const canvas = canvasRef.current;
|
|
8828
9440
|
if (!canvas) return;
|
|
8829
9441
|
const dpr = window.devicePixelRatio || 1;
|
|
@@ -8841,12 +9453,16 @@ function VerticalRuler({
|
|
|
8841
9453
|
const computed = getComputedStyle(canvas);
|
|
8842
9454
|
const tick = computed.getPropertyValue("color");
|
|
8843
9455
|
const label = tick;
|
|
8844
|
-
const
|
|
8845
|
-
const
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
9456
|
+
const { minor, stepsPerMajor } = computeTickIntervals(zoom);
|
|
9457
|
+
const midIdx = stepsPerMajor / 2;
|
|
9458
|
+
const visibleContentHeight = height / zoom;
|
|
9459
|
+
const startIdx = Math.floor(scrollOffset.y / minor);
|
|
9460
|
+
const endIdx = Math.ceil((scrollOffset.y + visibleContentHeight) / minor);
|
|
9461
|
+
for (let i = startIdx; i <= endIdx; i++) {
|
|
9462
|
+
const px = i * minor;
|
|
9463
|
+
const y = (px - scrollOffset.y) * zoom;
|
|
9464
|
+
const isMajor = i % stepsPerMajor === 0;
|
|
9465
|
+
const isMid = !isMajor && i % midIdx === 0;
|
|
8850
9466
|
ctx.beginPath();
|
|
8851
9467
|
ctx.moveTo(width, y);
|
|
8852
9468
|
ctx.lineTo(width - (isMajor ? 10 : isMid ? 7 : 4), y);
|
|
@@ -8854,7 +9470,7 @@ function VerticalRuler({
|
|
|
8854
9470
|
ctx.globalAlpha = 0.6;
|
|
8855
9471
|
ctx.lineWidth = 1;
|
|
8856
9472
|
ctx.stroke();
|
|
8857
|
-
if (isMajor
|
|
9473
|
+
if (isMajor) {
|
|
8858
9474
|
ctx.save();
|
|
8859
9475
|
ctx.globalAlpha = 1;
|
|
8860
9476
|
ctx.fillStyle = label;
|
|
@@ -8862,11 +9478,11 @@ function VerticalRuler({
|
|
|
8862
9478
|
ctx.textAlign = "center";
|
|
8863
9479
|
ctx.translate(9, y);
|
|
8864
9480
|
ctx.rotate(-Math.PI / 2);
|
|
8865
|
-
ctx.fillText(String(px), 0, 0);
|
|
9481
|
+
ctx.fillText(String(Math.round(px)), 0, 0);
|
|
8866
9482
|
ctx.restore();
|
|
8867
9483
|
}
|
|
8868
9484
|
}
|
|
8869
|
-
}, [scrollOffset.y, viewportHeight, theme, systemDark]);
|
|
9485
|
+
}, [scrollOffset.y, viewportHeight, zoom, theme, systemDark]);
|
|
8870
9486
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
8871
9487
|
"div",
|
|
8872
9488
|
{
|
|
@@ -8910,17 +9526,26 @@ function CornerSquare() {
|
|
|
8910
9526
|
}
|
|
8911
9527
|
);
|
|
8912
9528
|
}
|
|
9529
|
+
function computeGuidelineViewportPos(position, orientation) {
|
|
9530
|
+
const snap = getCanvasSnapshot();
|
|
9531
|
+
const zoom = snap.active ? snap.zoom : 1;
|
|
9532
|
+
const pan = orientation === "horizontal" ? snap.active ? snap.panY : -window.scrollY : snap.active ? snap.panX : -window.scrollX;
|
|
9533
|
+
if (snap.active) {
|
|
9534
|
+
const bo = orientation === "horizontal" ? getBodyOffset().y : getBodyOffset().x;
|
|
9535
|
+
return bo + (position - bo + pan) * zoom;
|
|
9536
|
+
}
|
|
9537
|
+
return (position + pan) * zoom;
|
|
9538
|
+
}
|
|
8913
9539
|
function GuidelineLine({
|
|
8914
9540
|
guideline,
|
|
8915
|
-
scrollOffset,
|
|
8916
9541
|
isActive,
|
|
9542
|
+
isSnapped,
|
|
8917
9543
|
dragPosition,
|
|
8918
9544
|
onStartDrag,
|
|
8919
9545
|
onDelete
|
|
8920
9546
|
}) {
|
|
8921
9547
|
const isHorizontal = guideline.orientation === "horizontal";
|
|
8922
|
-
const
|
|
8923
|
-
const viewportPos = guideline.position - scrollPos;
|
|
9548
|
+
const lineColor = isActive && isSnapped ? SNAPPED_COLOR : GUIDELINE_COLOR;
|
|
8924
9549
|
const handlePointerDown = (e) => {
|
|
8925
9550
|
e.preventDefault();
|
|
8926
9551
|
e.stopPropagation();
|
|
@@ -8931,119 +9556,137 @@ function GuidelineLine({
|
|
|
8931
9556
|
e.stopPropagation();
|
|
8932
9557
|
onDelete(guideline.id);
|
|
8933
9558
|
};
|
|
8934
|
-
const
|
|
9559
|
+
const isDragging = isActive && dragPosition !== null;
|
|
9560
|
+
const viewportPos = isDragging ? dragPosition : computeGuidelineViewportPos(guideline.position, guideline.orientation);
|
|
9561
|
+
const translate = isHorizontal ? `translateY(${viewportPos}px)` : `translateX(${viewportPos}px)`;
|
|
8935
9562
|
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)(
|
|
9563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
8992
9564
|
"div",
|
|
8993
9565
|
{
|
|
8994
|
-
"data-
|
|
9566
|
+
"data-gl-pos": guideline.position,
|
|
9567
|
+
"data-gl-orient": "h",
|
|
9568
|
+
...isDragging ? { "data-gl-dragging": "" } : {},
|
|
8995
9569
|
style: {
|
|
8996
9570
|
position: "fixed",
|
|
8997
|
-
left: displayPos,
|
|
8998
9571
|
top: 0,
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9572
|
+
left: 0,
|
|
9573
|
+
right: 0,
|
|
9574
|
+
height: 0,
|
|
9575
|
+
transform: translate,
|
|
9002
9576
|
zIndex: 99993,
|
|
9003
9577
|
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
9578
|
},
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9579
|
+
children: [
|
|
9580
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9581
|
+
"div",
|
|
9582
|
+
{
|
|
9583
|
+
"data-direct-edit": "guideline",
|
|
9584
|
+
style: { position: "absolute", top: 0, left: 0, right: 0, height: 1, background: lineColor }
|
|
9585
|
+
}
|
|
9586
|
+
),
|
|
9587
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9588
|
+
"div",
|
|
9589
|
+
{
|
|
9590
|
+
style: {
|
|
9591
|
+
position: "absolute",
|
|
9592
|
+
top: -Math.floor(HIT_ZONE / 2),
|
|
9593
|
+
left: RULER_SIZE2,
|
|
9594
|
+
right: 0,
|
|
9595
|
+
height: HIT_ZONE,
|
|
9596
|
+
cursor: "ns-resize",
|
|
9597
|
+
pointerEvents: "auto"
|
|
9598
|
+
},
|
|
9599
|
+
onPointerDown: handlePointerDown,
|
|
9600
|
+
onDoubleClick: handleDoubleClick
|
|
9601
|
+
}
|
|
9602
|
+
),
|
|
9603
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9604
|
+
"div",
|
|
9605
|
+
{
|
|
9606
|
+
style: {
|
|
9607
|
+
position: "absolute",
|
|
9608
|
+
top: 4,
|
|
9609
|
+
left: RULER_SIZE2 + 4,
|
|
9610
|
+
background: lineColor,
|
|
9611
|
+
color: "#fff",
|
|
9612
|
+
padding: "1px 4px",
|
|
9613
|
+
borderRadius: 2,
|
|
9614
|
+
zIndex: 99995,
|
|
9615
|
+
pointerEvents: "none",
|
|
9616
|
+
...rulerFont
|
|
9617
|
+
},
|
|
9618
|
+
children: Math.round(guideline.position)
|
|
9619
|
+
}
|
|
9620
|
+
)
|
|
9621
|
+
]
|
|
9040
9622
|
}
|
|
9041
|
-
)
|
|
9042
|
-
|
|
9623
|
+
);
|
|
9624
|
+
}
|
|
9625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
9626
|
+
"div",
|
|
9627
|
+
{
|
|
9628
|
+
"data-gl-pos": guideline.position,
|
|
9629
|
+
"data-gl-orient": "v",
|
|
9630
|
+
...isDragging ? { "data-gl-dragging": "" } : {},
|
|
9631
|
+
style: {
|
|
9632
|
+
position: "fixed",
|
|
9633
|
+
top: 0,
|
|
9634
|
+
left: 0,
|
|
9635
|
+
bottom: 0,
|
|
9636
|
+
width: 0,
|
|
9637
|
+
transform: translate,
|
|
9638
|
+
zIndex: 99993,
|
|
9639
|
+
pointerEvents: "none"
|
|
9640
|
+
},
|
|
9641
|
+
children: [
|
|
9642
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9643
|
+
"div",
|
|
9644
|
+
{
|
|
9645
|
+
"data-direct-edit": "guideline",
|
|
9646
|
+
style: { position: "absolute", left: 0, top: 0, bottom: 0, width: 1, background: lineColor }
|
|
9647
|
+
}
|
|
9648
|
+
),
|
|
9649
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9650
|
+
"div",
|
|
9651
|
+
{
|
|
9652
|
+
style: {
|
|
9653
|
+
position: "absolute",
|
|
9654
|
+
left: -Math.floor(HIT_ZONE / 2),
|
|
9655
|
+
top: RULER_SIZE2,
|
|
9656
|
+
bottom: 0,
|
|
9657
|
+
width: HIT_ZONE,
|
|
9658
|
+
cursor: "ew-resize",
|
|
9659
|
+
pointerEvents: "auto"
|
|
9660
|
+
},
|
|
9661
|
+
onPointerDown: handlePointerDown,
|
|
9662
|
+
onDoubleClick: handleDoubleClick
|
|
9663
|
+
}
|
|
9664
|
+
),
|
|
9665
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9666
|
+
"div",
|
|
9667
|
+
{
|
|
9668
|
+
style: {
|
|
9669
|
+
position: "absolute",
|
|
9670
|
+
left: 4,
|
|
9671
|
+
top: RULER_SIZE2 + 4,
|
|
9672
|
+
background: lineColor,
|
|
9673
|
+
color: "#fff",
|
|
9674
|
+
padding: "1px 4px",
|
|
9675
|
+
borderRadius: 2,
|
|
9676
|
+
zIndex: 99995,
|
|
9677
|
+
pointerEvents: "none",
|
|
9678
|
+
...rulerFont
|
|
9679
|
+
},
|
|
9680
|
+
children: Math.round(guideline.position)
|
|
9681
|
+
}
|
|
9682
|
+
)
|
|
9683
|
+
]
|
|
9684
|
+
}
|
|
9685
|
+
);
|
|
9043
9686
|
}
|
|
9044
9687
|
function useViewportWidth() {
|
|
9045
|
-
const [width, setWidth] =
|
|
9046
|
-
|
|
9688
|
+
const [width, setWidth] = React30.useState(0);
|
|
9689
|
+
React30.useEffect(() => {
|
|
9047
9690
|
setWidth(window.innerWidth);
|
|
9048
9691
|
const onResize = () => setWidth(window.innerWidth);
|
|
9049
9692
|
window.addEventListener("resize", onResize);
|
|
@@ -9052,8 +9695,8 @@ function useViewportWidth() {
|
|
|
9052
9695
|
return width;
|
|
9053
9696
|
}
|
|
9054
9697
|
function useViewportHeight() {
|
|
9055
|
-
const [height, setHeight] =
|
|
9056
|
-
|
|
9698
|
+
const [height, setHeight] = React30.useState(0);
|
|
9699
|
+
React30.useEffect(() => {
|
|
9057
9700
|
setHeight(window.innerHeight);
|
|
9058
9701
|
const onResize = () => setHeight(window.innerHeight);
|
|
9059
9702
|
window.addEventListener("resize", onResize);
|
|
@@ -9063,7 +9706,8 @@ function useViewportHeight() {
|
|
|
9063
9706
|
}
|
|
9064
9707
|
function RulersOverlay({ enabled }) {
|
|
9065
9708
|
const container = usePortalContainer();
|
|
9066
|
-
const
|
|
9709
|
+
const canvas = useCanvasSnapshot();
|
|
9710
|
+
const hostElement = React30.useMemo(() => {
|
|
9067
9711
|
if (!container) return null;
|
|
9068
9712
|
const root = container.getRootNode();
|
|
9069
9713
|
if (root instanceof ShadowRoot) return root.host;
|
|
@@ -9073,12 +9717,51 @@ function RulersOverlay({ enabled }) {
|
|
|
9073
9717
|
guidelines,
|
|
9074
9718
|
activeGuideline,
|
|
9075
9719
|
dragPosition,
|
|
9720
|
+
isSnapped,
|
|
9076
9721
|
scrollOffset,
|
|
9077
9722
|
startCreate,
|
|
9078
9723
|
startDrag,
|
|
9079
9724
|
deleteGuideline
|
|
9080
|
-
} = useGuidelines(enabled, hostElement);
|
|
9725
|
+
} = useGuidelines(enabled, hostElement, canvas);
|
|
9726
|
+
React30.useLayoutEffect(() => {
|
|
9727
|
+
if (!container || !enabled) return;
|
|
9728
|
+
const el = container;
|
|
9729
|
+
function updateGuidelinePositions() {
|
|
9730
|
+
const snap = getCanvasSnapshot();
|
|
9731
|
+
const zoom2 = snap.active ? snap.zoom : 1;
|
|
9732
|
+
const panX = snap.active ? snap.panX : -window.scrollX;
|
|
9733
|
+
const panY = snap.active ? snap.panY : -window.scrollY;
|
|
9734
|
+
const bo = getBodyOffset();
|
|
9735
|
+
el.querySelectorAll("[data-gl-pos]").forEach((node) => {
|
|
9736
|
+
if (node.hasAttribute("data-gl-dragging")) return;
|
|
9737
|
+
const pos = Number(node.dataset.glPos);
|
|
9738
|
+
const orient = node.dataset.glOrient;
|
|
9739
|
+
let vp;
|
|
9740
|
+
if (snap.active) {
|
|
9741
|
+
vp = orient === "h" ? bo.y + (pos - bo.y + panY) * zoom2 : bo.x + (pos - bo.x + panX) * zoom2;
|
|
9742
|
+
} else {
|
|
9743
|
+
vp = orient === "h" ? (pos + panY) * zoom2 : (pos + panX) * zoom2;
|
|
9744
|
+
}
|
|
9745
|
+
node.style.transform = orient === "h" ? `translateY(${vp}px)` : `translateX(${vp}px)`;
|
|
9746
|
+
});
|
|
9747
|
+
}
|
|
9748
|
+
updateGuidelinePositions();
|
|
9749
|
+
window.addEventListener("direct-edit-canvas-change", updateGuidelinePositions);
|
|
9750
|
+
window.addEventListener("scroll", updateGuidelinePositions, true);
|
|
9751
|
+
return () => {
|
|
9752
|
+
window.removeEventListener("direct-edit-canvas-change", updateGuidelinePositions);
|
|
9753
|
+
window.removeEventListener("scroll", updateGuidelinePositions, true);
|
|
9754
|
+
};
|
|
9755
|
+
}, [container, enabled]);
|
|
9081
9756
|
if (!enabled || !container) return null;
|
|
9757
|
+
const zoom = canvas?.active ? canvas.zoom || 1 : 1;
|
|
9758
|
+
const effectiveScrollOffset = canvas?.active ? (() => {
|
|
9759
|
+
const bo = getBodyOffset();
|
|
9760
|
+
return {
|
|
9761
|
+
x: computeCanvasRulerScrollOffset(canvas.panX || 0, zoom, bo.x),
|
|
9762
|
+
y: computeCanvasRulerScrollOffset(canvas.panY || 0, zoom, bo.y)
|
|
9763
|
+
};
|
|
9764
|
+
})() : scrollOffset;
|
|
9082
9765
|
const handleHorizontalPointerDown = (e) => {
|
|
9083
9766
|
e.preventDefault();
|
|
9084
9767
|
startCreate("horizontal", e.clientY);
|
|
@@ -9090,14 +9773,14 @@ function RulersOverlay({ enabled }) {
|
|
|
9090
9773
|
return (0, import_react_dom2.createPortal)(
|
|
9091
9774
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
9092
9775
|
/* @__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 }),
|
|
9776
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HorizontalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleHorizontalPointerDown }),
|
|
9777
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VerticalRuler, { scrollOffset: effectiveScrollOffset, zoom, onPointerDown: handleVerticalPointerDown }),
|
|
9095
9778
|
guidelines.map((g) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
9096
9779
|
GuidelineLine,
|
|
9097
9780
|
{
|
|
9098
9781
|
guideline: g,
|
|
9099
|
-
scrollOffset,
|
|
9100
9782
|
isActive: activeGuideline?.id === g.id,
|
|
9783
|
+
isSnapped: activeGuideline?.id === g.id ? isSnapped : false,
|
|
9101
9784
|
dragPosition: activeGuideline?.id === g.id ? dragPosition : null,
|
|
9102
9785
|
onStartDrag: startDrag,
|
|
9103
9786
|
onDelete: deleteGuideline
|
|
@@ -9145,12 +9828,12 @@ function subscribeRulersVisible(listener) {
|
|
|
9145
9828
|
};
|
|
9146
9829
|
}
|
|
9147
9830
|
function useRulersVisible() {
|
|
9148
|
-
const visible =
|
|
9831
|
+
const visible = React30.useSyncExternalStore(
|
|
9149
9832
|
subscribeRulersVisible,
|
|
9150
9833
|
() => rulersVisibleSnapshot,
|
|
9151
9834
|
() => true
|
|
9152
9835
|
);
|
|
9153
|
-
const toggle =
|
|
9836
|
+
const toggle = React30.useCallback(() => {
|
|
9154
9837
|
setRulersVisible(!rulersVisibleSnapshot);
|
|
9155
9838
|
}, []);
|
|
9156
9839
|
return [visible, toggle];
|
|
@@ -9158,7 +9841,7 @@ function useRulersVisible() {
|
|
|
9158
9841
|
function Rulers() {
|
|
9159
9842
|
const { editModeActive } = useDirectEditState();
|
|
9160
9843
|
const [rulersVisible, toggleRulers] = useRulersVisible();
|
|
9161
|
-
|
|
9844
|
+
React30.useEffect(() => {
|
|
9162
9845
|
if (!editModeActive) return;
|
|
9163
9846
|
function handleKeyDown(e) {
|
|
9164
9847
|
if (e.shiftKey && e.key === "R" && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
@@ -9176,7 +9859,7 @@ function Rulers() {
|
|
|
9176
9859
|
}
|
|
9177
9860
|
|
|
9178
9861
|
// src/use-toolbar-dock.ts
|
|
9179
|
-
var
|
|
9862
|
+
var React31 = __toESM(require("react"));
|
|
9180
9863
|
var STORAGE_KEY3 = "direct-edit-toolbar-dock";
|
|
9181
9864
|
var EDGE_MARGIN = 8;
|
|
9182
9865
|
var DRAG_THRESHOLD2 = 3;
|
|
@@ -9200,21 +9883,25 @@ function getToolbarBounds(width, height) {
|
|
|
9200
9883
|
const maxY = availableY <= 0 ? 0 : Math.max(minY, availableY - EDGE_MARGIN);
|
|
9201
9884
|
return { minX, maxX, minY, maxY };
|
|
9202
9885
|
}
|
|
9203
|
-
function getDockedPosition(edge, width, height
|
|
9886
|
+
function getDockedPosition(edge, width, height) {
|
|
9204
9887
|
const { minX, maxX, minY, maxY } = getToolbarBounds(width, height);
|
|
9205
|
-
const
|
|
9206
|
-
const
|
|
9888
|
+
const centerX = clamp((window.innerWidth - width) / 2, minX, maxX);
|
|
9889
|
+
const centerY = clamp((window.innerHeight - height) / 2, minY, maxY);
|
|
9207
9890
|
switch (edge) {
|
|
9208
9891
|
case "bottom":
|
|
9209
|
-
return { x:
|
|
9892
|
+
return { x: centerX, y: maxY };
|
|
9210
9893
|
case "top":
|
|
9211
|
-
return { x:
|
|
9894
|
+
return { x: centerX, y: minY };
|
|
9212
9895
|
case "left":
|
|
9213
|
-
return { x: minX, y:
|
|
9896
|
+
return { x: minX, y: centerY };
|
|
9214
9897
|
case "right":
|
|
9215
|
-
return { x: maxX, y:
|
|
9898
|
+
return { x: maxX, y: centerY };
|
|
9216
9899
|
}
|
|
9217
9900
|
}
|
|
9901
|
+
function getInitialDockedPosition(edge) {
|
|
9902
|
+
if (typeof window === "undefined") return { x: 0, y: 0 };
|
|
9903
|
+
return getDockedPosition(edge, 0, 0);
|
|
9904
|
+
}
|
|
9218
9905
|
function getNearestEdge(centerX, centerY) {
|
|
9219
9906
|
const vw = window.innerWidth;
|
|
9220
9907
|
const vh = window.innerHeight;
|
|
@@ -9235,53 +9922,65 @@ function getNearestEdge(centerX, centerY) {
|
|
|
9235
9922
|
return nearest;
|
|
9236
9923
|
}
|
|
9237
9924
|
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
|
|
9925
|
+
const [dockedEdge, setDockedEdge] = React31.useState(getInitialEdge);
|
|
9926
|
+
const [phase, setPhase] = React31.useState("docked");
|
|
9927
|
+
const [dragPosition, setDragPosition] = React31.useState(null);
|
|
9928
|
+
const dragOffsetRef = React31.useRef({ x: 0, y: 0 });
|
|
9929
|
+
const pointerStartRef = React31.useRef({ x: 0, y: 0 });
|
|
9930
|
+
const pendingDragRef = React31.useRef(false);
|
|
9931
|
+
const capturedElementRef = React31.useRef(null);
|
|
9932
|
+
const snapTimerRef = React31.useRef(null);
|
|
9933
|
+
const transitionTimerRef = React31.useRef(null);
|
|
9934
|
+
const transitioningRef = React31.useRef(false);
|
|
9935
|
+
const recalcRef = React31.useRef(null);
|
|
9936
|
+
const getDockedPos = React31.useCallback(() => {
|
|
9248
9937
|
const el = toolbarRef.current;
|
|
9249
9938
|
if (!el) return { x: 0, y: 0 };
|
|
9250
9939
|
const rect = el.getBoundingClientRect();
|
|
9251
9940
|
return getDockedPosition(dockedEdge, rect.width, rect.height);
|
|
9252
9941
|
}, [dockedEdge, toolbarRef]);
|
|
9253
|
-
const [dockedPos, setDockedPos] =
|
|
9254
|
-
const [
|
|
9255
|
-
|
|
9942
|
+
const [dockedPos, setDockedPos] = React31.useState(() => getInitialDockedPosition(dockedEdge));
|
|
9943
|
+
const [dockedTransitionEnabled, setDockedTransitionEnabled] = React31.useState(false);
|
|
9944
|
+
React31.useLayoutEffect(() => {
|
|
9256
9945
|
const el = toolbarRef.current;
|
|
9257
9946
|
if (!el) return;
|
|
9947
|
+
setDockedPos(getDockedPos());
|
|
9948
|
+
}, [getDockedPos, toolbarRef]);
|
|
9949
|
+
React31.useEffect(() => {
|
|
9258
9950
|
const raf = requestAnimationFrame(() => {
|
|
9259
|
-
|
|
9260
|
-
dockedPosRef.current = pos;
|
|
9261
|
-
setDockedPos(pos);
|
|
9262
|
-
setReady(true);
|
|
9951
|
+
setDockedTransitionEnabled(true);
|
|
9263
9952
|
});
|
|
9264
9953
|
return () => cancelAnimationFrame(raf);
|
|
9265
|
-
}, [
|
|
9266
|
-
|
|
9954
|
+
}, []);
|
|
9955
|
+
const predictSize = React31.useCallback((width, height) => {
|
|
9956
|
+
transitioningRef.current = true;
|
|
9957
|
+
setDockedPos(getDockedPosition(dockedEdge, width, height));
|
|
9958
|
+
if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
|
|
9959
|
+
transitionTimerRef.current = setTimeout(() => {
|
|
9960
|
+
transitioningRef.current = false;
|
|
9961
|
+
transitionTimerRef.current = null;
|
|
9962
|
+
recalcRef.current?.();
|
|
9963
|
+
}, 350);
|
|
9964
|
+
}, [dockedEdge]);
|
|
9965
|
+
React31.useEffect(() => {
|
|
9267
9966
|
const el = toolbarRef.current;
|
|
9268
9967
|
if (!el) return;
|
|
9269
9968
|
function recalc() {
|
|
9270
|
-
if (!el) return;
|
|
9969
|
+
if (!el || transitioningRef.current) return;
|
|
9271
9970
|
const rect = el.getBoundingClientRect();
|
|
9272
|
-
|
|
9273
|
-
dockedPosRef.current = pos;
|
|
9274
|
-
setDockedPos(pos);
|
|
9971
|
+
setDockedPos(getDockedPosition(dockedEdge, rect.width, rect.height));
|
|
9275
9972
|
}
|
|
9973
|
+
recalcRef.current = recalc;
|
|
9276
9974
|
const ro = new ResizeObserver(recalc);
|
|
9277
9975
|
ro.observe(el);
|
|
9278
9976
|
window.addEventListener("resize", recalc);
|
|
9279
9977
|
return () => {
|
|
9978
|
+
recalcRef.current = null;
|
|
9280
9979
|
ro.disconnect();
|
|
9281
9980
|
window.removeEventListener("resize", recalc);
|
|
9282
9981
|
};
|
|
9283
9982
|
}, [dockedEdge, toolbarRef]);
|
|
9284
|
-
const handlePointerDown =
|
|
9983
|
+
const handlePointerDown = React31.useCallback((e) => {
|
|
9285
9984
|
const el = toolbarRef.current;
|
|
9286
9985
|
if (!el) return;
|
|
9287
9986
|
const rect = el.getBoundingClientRect();
|
|
@@ -9294,7 +9993,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9294
9993
|
} catch {
|
|
9295
9994
|
}
|
|
9296
9995
|
}, [toolbarRef]);
|
|
9297
|
-
const handlePointerMove =
|
|
9996
|
+
const handlePointerMove = React31.useCallback((e) => {
|
|
9298
9997
|
if (!pendingDragRef.current && phase !== "dragging") return;
|
|
9299
9998
|
const dx = e.clientX - pointerStartRef.current.x;
|
|
9300
9999
|
const dy = e.clientY - pointerStartRef.current.y;
|
|
@@ -9311,7 +10010,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9311
10010
|
const newY = Math.max(0, e.clientY - dragOffsetRef.current.y);
|
|
9312
10011
|
setDragPosition({ x: newX, y: newY });
|
|
9313
10012
|
}, [phase]);
|
|
9314
|
-
const handlePointerUp =
|
|
10013
|
+
const handlePointerUp = React31.useCallback((e) => {
|
|
9315
10014
|
if (capturedElementRef.current) {
|
|
9316
10015
|
try {
|
|
9317
10016
|
capturedElementRef.current.releasePointerCapture(e.pointerId);
|
|
@@ -9331,8 +10030,6 @@ function useToolbarDock(toolbarRef) {
|
|
|
9331
10030
|
return;
|
|
9332
10031
|
}
|
|
9333
10032
|
const rect = el.getBoundingClientRect();
|
|
9334
|
-
const width = el.offsetWidth;
|
|
9335
|
-
const height = el.offsetHeight;
|
|
9336
10033
|
const centerX = rect.left + rect.width / 2;
|
|
9337
10034
|
const centerY = rect.top + rect.height / 2;
|
|
9338
10035
|
const newEdge = getNearestEdge(centerX, centerY);
|
|
@@ -9341,9 +10038,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9341
10038
|
localStorage.setItem(STORAGE_KEY3, newEdge);
|
|
9342
10039
|
} catch {
|
|
9343
10040
|
}
|
|
9344
|
-
|
|
9345
|
-
dockedPosRef.current = newPos;
|
|
9346
|
-
setDockedPos(newPos);
|
|
10041
|
+
setDockedPos(getDockedPosition(newEdge, el.offsetWidth, el.offsetHeight));
|
|
9347
10042
|
setPhase("snapping");
|
|
9348
10043
|
setDragPosition(null);
|
|
9349
10044
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
@@ -9352,7 +10047,7 @@ function useToolbarDock(toolbarRef) {
|
|
|
9352
10047
|
setPhase("docked");
|
|
9353
10048
|
}, 350);
|
|
9354
10049
|
}, [phase, toolbarRef]);
|
|
9355
|
-
const handlePointerCancel =
|
|
10050
|
+
const handlePointerCancel = React31.useCallback((e) => {
|
|
9356
10051
|
if (capturedElementRef.current) {
|
|
9357
10052
|
try {
|
|
9358
10053
|
capturedElementRef.current.releasePointerCapture(e.pointerId);
|
|
@@ -9366,18 +10061,16 @@ function useToolbarDock(toolbarRef) {
|
|
|
9366
10061
|
setDragPosition(null);
|
|
9367
10062
|
}
|
|
9368
10063
|
}, [phase]);
|
|
9369
|
-
|
|
10064
|
+
React31.useEffect(() => {
|
|
9370
10065
|
return () => {
|
|
9371
10066
|
if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
|
|
10067
|
+
if (transitionTimerRef.current) clearTimeout(transitionTimerRef.current);
|
|
9372
10068
|
};
|
|
9373
10069
|
}, []);
|
|
9374
10070
|
const isDragging = phase === "dragging";
|
|
9375
10071
|
const isSnapping = phase === "snapping";
|
|
9376
|
-
const style =
|
|
9377
|
-
const base = {
|
|
9378
|
-
position: "fixed",
|
|
9379
|
-
...!ready && { visibility: "hidden" }
|
|
9380
|
-
};
|
|
10072
|
+
const style = React31.useMemo(() => {
|
|
10073
|
+
const base = { position: "fixed" };
|
|
9381
10074
|
if (phase === "dragging" && dragPosition) {
|
|
9382
10075
|
return {
|
|
9383
10076
|
...base,
|
|
@@ -9400,14 +10093,18 @@ function useToolbarDock(toolbarRef) {
|
|
|
9400
10093
|
return {
|
|
9401
10094
|
...base,
|
|
9402
10095
|
left: dockedPos.x,
|
|
9403
|
-
top: dockedPos.y
|
|
10096
|
+
top: dockedPos.y,
|
|
10097
|
+
...dockedTransitionEnabled && {
|
|
10098
|
+
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"
|
|
10099
|
+
}
|
|
9404
10100
|
};
|
|
9405
|
-
}, [phase, dragPosition, dockedPos,
|
|
10101
|
+
}, [phase, dragPosition, dockedPos, dockedTransitionEnabled]);
|
|
9406
10102
|
return {
|
|
9407
10103
|
dockedEdge,
|
|
9408
10104
|
isDragging,
|
|
9409
10105
|
isSnapping,
|
|
9410
10106
|
style,
|
|
10107
|
+
predictSize,
|
|
9411
10108
|
handlePointerDown,
|
|
9412
10109
|
handlePointerMove,
|
|
9413
10110
|
handlePointerUp,
|
|
@@ -9416,16 +10113,16 @@ function useToolbarDock(toolbarRef) {
|
|
|
9416
10113
|
}
|
|
9417
10114
|
|
|
9418
10115
|
// src/toolbar.tsx
|
|
9419
|
-
var
|
|
10116
|
+
var import_lucide_react16 = require("lucide-react");
|
|
9420
10117
|
|
|
9421
10118
|
// src/toolbar/edits-popover.tsx
|
|
9422
|
-
var
|
|
10119
|
+
var React33 = __toESM(require("react"));
|
|
9423
10120
|
var import_button7 = require("@base-ui/react/button");
|
|
9424
10121
|
var import_popover2 = require("@base-ui/react/popover");
|
|
9425
10122
|
var import_lucide_react13 = require("lucide-react");
|
|
9426
10123
|
|
|
9427
10124
|
// src/ui/badge.tsx
|
|
9428
|
-
var
|
|
10125
|
+
var React32 = __toESM(require("react"));
|
|
9429
10126
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
9430
10127
|
var badgeVariants = {
|
|
9431
10128
|
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 +10132,7 @@ var badgeVariants = {
|
|
|
9435
10132
|
outline: "border-border bg-transparent text-foreground"
|
|
9436
10133
|
}
|
|
9437
10134
|
};
|
|
9438
|
-
var Badge =
|
|
10135
|
+
var Badge = React32.forwardRef(
|
|
9439
10136
|
({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
9440
10137
|
"div",
|
|
9441
10138
|
{
|
|
@@ -9461,14 +10158,11 @@ function truncateText(value, max = 64) {
|
|
|
9461
10158
|
if (value.length <= max) return value;
|
|
9462
10159
|
return `${value.slice(0, max)}...`;
|
|
9463
10160
|
}
|
|
9464
|
-
function isWithinFocusRegion(nextTarget, ...elements) {
|
|
9465
|
-
if (!(nextTarget instanceof Node)) return false;
|
|
9466
|
-
return elements.some((element) => Boolean(element?.contains(nextTarget)));
|
|
9467
|
-
}
|
|
9468
10161
|
function EditsPopover({
|
|
9469
10162
|
tooltipSide,
|
|
9470
10163
|
sessionEditCount,
|
|
9471
|
-
|
|
10164
|
+
isOpen,
|
|
10165
|
+
onOpenChange,
|
|
9472
10166
|
onGetSessionItems,
|
|
9473
10167
|
onExportAllEdits,
|
|
9474
10168
|
onSendAllToAgents,
|
|
@@ -9476,20 +10170,18 @@ function EditsPopover({
|
|
|
9476
10170
|
onRemoveSessionEdit,
|
|
9477
10171
|
onDeleteComment
|
|
9478
10172
|
}) {
|
|
9479
|
-
const [
|
|
9480
|
-
const [
|
|
9481
|
-
const
|
|
9482
|
-
const
|
|
9483
|
-
const
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
React32.useEffect(() => {
|
|
9487
|
-
if (!editsOpen) return;
|
|
10173
|
+
const [copied, setCopied] = React33.useState(false);
|
|
10174
|
+
const [sendStatus, setSendStatus] = React33.useState("idle");
|
|
10175
|
+
const editsPopupRef = React33.useRef(null);
|
|
10176
|
+
const editsTriggerRef = React33.useRef(null);
|
|
10177
|
+
const [editsSnapshot, setEditsSnapshot] = React33.useState([]);
|
|
10178
|
+
React33.useEffect(() => {
|
|
10179
|
+
if (!isOpen) return;
|
|
9488
10180
|
function handlePointerDown(e) {
|
|
9489
10181
|
const path = e.composedPath();
|
|
9490
10182
|
if (editsPopupRef.current && path.includes(editsPopupRef.current)) return;
|
|
9491
10183
|
if (editsTriggerRef.current && path.includes(editsTriggerRef.current)) return;
|
|
9492
|
-
|
|
10184
|
+
onOpenChange(false);
|
|
9493
10185
|
}
|
|
9494
10186
|
const raf = requestAnimationFrame(() => {
|
|
9495
10187
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
@@ -9498,42 +10190,19 @@ function EditsPopover({
|
|
|
9498
10190
|
cancelAnimationFrame(raf);
|
|
9499
10191
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
9500
10192
|
};
|
|
9501
|
-
}, [
|
|
9502
|
-
|
|
9503
|
-
if (
|
|
10193
|
+
}, [isOpen, onOpenChange]);
|
|
10194
|
+
React33.useEffect(() => {
|
|
10195
|
+
if (isOpen && onGetSessionItems) {
|
|
9504
10196
|
setEditsSnapshot(onGetSessionItems());
|
|
9505
10197
|
}
|
|
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 () => {
|
|
10198
|
+
}, [isOpen, onGetSessionItems]);
|
|
10199
|
+
const handleCopyAll = React33.useCallback(async () => {
|
|
9531
10200
|
const success = await onExportAllEdits?.();
|
|
9532
10201
|
if (!success) return;
|
|
9533
10202
|
setCopied(true);
|
|
9534
10203
|
window.setTimeout(() => setCopied(false), 2e3);
|
|
9535
10204
|
}, [onExportAllEdits]);
|
|
9536
|
-
const handleSendAll =
|
|
10205
|
+
const handleSendAll = React33.useCallback(async () => {
|
|
9537
10206
|
if (!onSendAllToAgents || sendStatus === "sending") return;
|
|
9538
10207
|
setSendStatus("sending");
|
|
9539
10208
|
let success = false;
|
|
@@ -9550,7 +10219,7 @@ function EditsPopover({
|
|
|
9550
10219
|
setSendStatus("offline");
|
|
9551
10220
|
window.setTimeout(() => setSendStatus("idle"), 2e3);
|
|
9552
10221
|
}, [onSendAllToAgents, sendStatus]);
|
|
9553
|
-
const handleCopyItem =
|
|
10222
|
+
const handleCopyItem = React33.useCallback(async (item) => {
|
|
9554
10223
|
const text = item.type === "edit" ? buildSessionExport([item.edit], []) : buildSessionExport([], [item.comment]);
|
|
9555
10224
|
try {
|
|
9556
10225
|
await navigator.clipboard.writeText(`implement the visual edits
|
|
@@ -9561,52 +10230,33 @@ ${text}`);
|
|
|
9561
10230
|
} catch {
|
|
9562
10231
|
}
|
|
9563
10232
|
}, []);
|
|
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);
|
|
10233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange, children: [
|
|
10234
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10235
|
+
/* @__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)(
|
|
10236
|
+
"button",
|
|
10237
|
+
{
|
|
10238
|
+
ref: editsTriggerRef,
|
|
10239
|
+
type: "button",
|
|
10240
|
+
className: cn(
|
|
10241
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10242
|
+
sessionEditCount > 0 || isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10243
|
+
),
|
|
10244
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10245
|
+
onClick: (e) => {
|
|
10246
|
+
e.preventDefault();
|
|
10247
|
+
e.stopPropagation();
|
|
10248
|
+
onOpenChange(!isOpen);
|
|
9583
10249
|
}
|
|
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
10250
|
}
|
|
9595
|
-
}
|
|
9596
|
-
|
|
10251
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react13.Copy, { className: "size-4" }) }),
|
|
10252
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Export edits" }) })
|
|
10253
|
+
] }),
|
|
9597
10254
|
/* @__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
10255
|
import_popover2.Popover.Popup,
|
|
9599
10256
|
{
|
|
9600
10257
|
ref: editsPopupRef,
|
|
9601
10258
|
className: "w-[340px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
9602
10259
|
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
10260
|
children: [
|
|
9611
10261
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between px-3 pb-1 pt-2.5", children: [
|
|
9612
10262
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs font-medium text-foreground", children: "Copy to AI agents" }),
|
|
@@ -9737,38 +10387,200 @@ ${text}`);
|
|
|
9737
10387
|
}
|
|
9738
10388
|
|
|
9739
10389
|
// src/toolbar/settings-popover.tsx
|
|
9740
|
-
var
|
|
9741
|
-
var
|
|
9742
|
-
var import_popover3 = require("@base-ui/react/popover");
|
|
10390
|
+
var React34 = __toESM(require("react"));
|
|
10391
|
+
var import_menu = require("@base-ui/react/menu");
|
|
9743
10392
|
var import_lucide_react14 = require("lucide-react");
|
|
9744
10393
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
9745
|
-
function
|
|
10394
|
+
function SettingsMenuPortal(props) {
|
|
9746
10395
|
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)));
|
|
10396
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_menu.Menu.Portal, { container, ...props });
|
|
9752
10397
|
}
|
|
9753
10398
|
function SettingsPopover({
|
|
9754
10399
|
tooltipSide,
|
|
9755
10400
|
theme,
|
|
9756
10401
|
isMac,
|
|
9757
|
-
|
|
10402
|
+
isOpen,
|
|
10403
|
+
onOpenChange,
|
|
9758
10404
|
onSetTheme
|
|
9759
10405
|
}) {
|
|
9760
|
-
const
|
|
9761
|
-
const settingsPopupRef =
|
|
9762
|
-
const
|
|
9763
|
-
const
|
|
9764
|
-
const
|
|
9765
|
-
|
|
9766
|
-
|
|
10406
|
+
const settingsTriggerRef = React34.useRef(null);
|
|
10407
|
+
const settingsPopupRef = React34.useRef(null);
|
|
10408
|
+
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";
|
|
10409
|
+
const popupTitleClass = "flex h-8 items-center px-3 text-xs font-medium text-foreground";
|
|
10410
|
+
const submenuSide = tooltipSide === "left" ? "left" : "right";
|
|
10411
|
+
const centeredSubmenuCollision = React34.useMemo(
|
|
10412
|
+
() => ({ side: "flip", align: "none", fallbackAxisSide: "none" }),
|
|
10413
|
+
[]
|
|
10414
|
+
);
|
|
10415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.Root, { open: isOpen, onOpenChange, modal: false, children: [
|
|
10416
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10417
|
+
/* @__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)(
|
|
10418
|
+
"button",
|
|
10419
|
+
{
|
|
10420
|
+
ref: settingsTriggerRef,
|
|
10421
|
+
type: "button",
|
|
10422
|
+
className: cn(
|
|
10423
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10424
|
+
isOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10425
|
+
),
|
|
10426
|
+
onPointerDown: (e) => e.stopPropagation()
|
|
10427
|
+
}
|
|
10428
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.EllipsisVertical, { className: "size-4" }) }),
|
|
10429
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TooltipContent, { side: tooltipSide, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: "Preferences" }) })
|
|
10430
|
+
] }),
|
|
10431
|
+
/* @__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)(
|
|
10432
|
+
import_menu.Menu.Popup,
|
|
10433
|
+
{
|
|
10434
|
+
ref: settingsPopupRef,
|
|
10435
|
+
className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
10436
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10437
|
+
children: [
|
|
10438
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: popupTitleClass, children: "Preferences" }),
|
|
10439
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "px-1 pb-1", children: [
|
|
10440
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.SubmenuRoot, { children: [
|
|
10441
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10442
|
+
import_menu.Menu.SubmenuTrigger,
|
|
10443
|
+
{
|
|
10444
|
+
openOnHover: false,
|
|
10445
|
+
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",
|
|
10446
|
+
children: [
|
|
10447
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Monitor, { className: "size-3.5" }),
|
|
10448
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex-1", children: "Theme" }),
|
|
10449
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ChevronRight, { className: "size-3.5" })
|
|
10450
|
+
]
|
|
10451
|
+
}
|
|
10452
|
+
),
|
|
10453
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SettingsMenuPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
10454
|
+
import_menu.Menu.Positioner,
|
|
10455
|
+
{
|
|
10456
|
+
anchor: settingsPopupRef,
|
|
10457
|
+
side: submenuSide,
|
|
10458
|
+
align: "center",
|
|
10459
|
+
sideOffset: 6,
|
|
10460
|
+
collisionAvoidance: centeredSubmenuCollision,
|
|
10461
|
+
className: "fixed z-[99999]",
|
|
10462
|
+
style: { pointerEvents: "auto" },
|
|
10463
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10464
|
+
import_menu.Menu.Popup,
|
|
10465
|
+
{
|
|
10466
|
+
className: "w-[200px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
10467
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10468
|
+
children: [
|
|
10469
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: popupTitleClass, children: "Theme" }),
|
|
10470
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-1 pb-1", children: [
|
|
10471
|
+
{ value: "light", label: "Light", Icon: import_lucide_react14.Sun },
|
|
10472
|
+
{ value: "dark", label: "Dark", Icon: import_lucide_react14.Moon },
|
|
10473
|
+
{ value: "system", label: "System", Icon: import_lucide_react14.Monitor }
|
|
10474
|
+
].map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10475
|
+
import_menu.Menu.Item,
|
|
10476
|
+
{
|
|
10477
|
+
className: cn(
|
|
10478
|
+
"flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs transition-colors",
|
|
10479
|
+
theme === value ? "bg-muted text-foreground" : "text-muted-foreground data-[highlighted]:bg-muted/50 data-[highlighted]:text-foreground"
|
|
10480
|
+
),
|
|
10481
|
+
onClick: () => {
|
|
10482
|
+
onSetTheme?.(value);
|
|
10483
|
+
onOpenChange(false);
|
|
10484
|
+
},
|
|
10485
|
+
children: [
|
|
10486
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "size-3.5" }),
|
|
10487
|
+
label
|
|
10488
|
+
]
|
|
10489
|
+
},
|
|
10490
|
+
value
|
|
10491
|
+
)) })
|
|
10492
|
+
]
|
|
10493
|
+
}
|
|
10494
|
+
)
|
|
10495
|
+
}
|
|
10496
|
+
) })
|
|
10497
|
+
] }),
|
|
10498
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_menu.Menu.SubmenuRoot, { children: [
|
|
10499
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10500
|
+
import_menu.Menu.SubmenuTrigger,
|
|
10501
|
+
{
|
|
10502
|
+
openOnHover: false,
|
|
10503
|
+
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",
|
|
10504
|
+
children: [
|
|
10505
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Keyboard, { className: "size-3.5" }),
|
|
10506
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex-1", children: "Keyboard shortcuts" }),
|
|
10507
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ChevronRight, { className: "size-3.5" })
|
|
10508
|
+
]
|
|
10509
|
+
}
|
|
10510
|
+
),
|
|
10511
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SettingsMenuPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
10512
|
+
import_menu.Menu.Positioner,
|
|
10513
|
+
{
|
|
10514
|
+
anchor: settingsPopupRef,
|
|
10515
|
+
side: submenuSide,
|
|
10516
|
+
align: "center",
|
|
10517
|
+
sideOffset: 6,
|
|
10518
|
+
collisionAvoidance: centeredSubmenuCollision,
|
|
10519
|
+
className: "fixed z-[99999]",
|
|
10520
|
+
style: { pointerEvents: "auto" },
|
|
10521
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
10522
|
+
import_menu.Menu.Popup,
|
|
10523
|
+
{
|
|
10524
|
+
className: "w-[300px] rounded-xl bg-background text-[11px] outline outline-1 outline-foreground/10 shadow-lg",
|
|
10525
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10526
|
+
children: [
|
|
10527
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex h-7 items-center px-3 text-[11px] font-medium text-foreground", children: "Keyboard Shortcuts" }),
|
|
10528
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-1 pb-1", children: [
|
|
10529
|
+
{ label: "Toggle design mode", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Command, { className: "size-2.5" }, "cmd"), "."] : ["Ctrl", "."] },
|
|
10530
|
+
{ label: "Undo", keys: isMac ? [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Command, { className: "size-2.5" }, "cmd"), "Z"] : ["Ctrl", "Z"] },
|
|
10531
|
+
{ label: "Toggle comments", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "C"] },
|
|
10532
|
+
{ label: "Toggle rulers", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "R"] },
|
|
10533
|
+
{ label: "Toggle canvas mode", keys: [/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.ArrowBigUp, { className: "size-3" }, "shift"), "Z"] },
|
|
10534
|
+
{ label: "Hover to measure", keys: isMac ? ["Hold", /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react14.Option, { className: "size-2.5" }, "opt")] : ["Hold", "Alt"] },
|
|
10535
|
+
{ label: "Back / Exit", keys: ["Esc"] }
|
|
10536
|
+
].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: [
|
|
10537
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: label }),
|
|
10538
|
+
/* @__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)) })
|
|
10539
|
+
] }, label)) })
|
|
10540
|
+
]
|
|
10541
|
+
}
|
|
10542
|
+
)
|
|
10543
|
+
}
|
|
10544
|
+
) })
|
|
10545
|
+
] })
|
|
10546
|
+
] })
|
|
10547
|
+
]
|
|
10548
|
+
}
|
|
10549
|
+
) }) })
|
|
10550
|
+
] });
|
|
10551
|
+
}
|
|
10552
|
+
|
|
10553
|
+
// src/toolbar/zoom-popover.tsx
|
|
10554
|
+
var React35 = __toESM(require("react"));
|
|
10555
|
+
var import_button8 = require("@base-ui/react/button");
|
|
10556
|
+
var import_popover3 = require("@base-ui/react/popover");
|
|
10557
|
+
var import_lucide_react15 = require("lucide-react");
|
|
10558
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
10559
|
+
function ZoomPopoverPortal(props) {
|
|
10560
|
+
const container = usePortalContainer();
|
|
10561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_popover3.Popover.Portal, { container, ...props });
|
|
10562
|
+
}
|
|
10563
|
+
function ZoomPopover({
|
|
10564
|
+
tooltipSide,
|
|
10565
|
+
canvasActive,
|
|
10566
|
+
canvasZoom,
|
|
10567
|
+
isOpen,
|
|
10568
|
+
onOpenChange,
|
|
10569
|
+
onToggleCanvas,
|
|
10570
|
+
onSetCanvasZoom,
|
|
10571
|
+
onZoomTo100,
|
|
10572
|
+
onFitToViewport
|
|
10573
|
+
}) {
|
|
10574
|
+
const popupRef = React35.useRef(null);
|
|
10575
|
+
const triggerRef = React35.useRef(null);
|
|
10576
|
+
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]";
|
|
10577
|
+
React35.useEffect(() => {
|
|
10578
|
+
if (!isOpen) return;
|
|
9767
10579
|
function handlePointerDown(e) {
|
|
9768
10580
|
const path = e.composedPath();
|
|
9769
|
-
if (
|
|
9770
|
-
if (
|
|
9771
|
-
|
|
10581
|
+
if (popupRef.current && path.includes(popupRef.current)) return;
|
|
10582
|
+
if (triggerRef.current && path.includes(triggerRef.current)) return;
|
|
10583
|
+
onOpenChange(false);
|
|
9772
10584
|
}
|
|
9773
10585
|
const raf = requestAnimationFrame(() => {
|
|
9774
10586
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
@@ -9777,121 +10589,90 @@ function SettingsPopover({
|
|
|
9777
10589
|
cancelAnimationFrame(raf);
|
|
9778
10590
|
document.removeEventListener("pointerdown", handlePointerDown);
|
|
9779
10591
|
};
|
|
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);
|
|
10592
|
+
}, [isOpen, onOpenChange]);
|
|
10593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_popover3.Popover.Root, { open: isOpen, onOpenChange, children: [
|
|
10594
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Tooltip, { disabled: isOpen, children: [
|
|
10595
|
+
/* @__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)(
|
|
10596
|
+
"button",
|
|
10597
|
+
{
|
|
10598
|
+
ref: triggerRef,
|
|
10599
|
+
type: "button",
|
|
10600
|
+
className: cn(
|
|
10601
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10602
|
+
isOpen ? "bg-muted text-foreground" : canvasActive ? "bg-muted text-foreground hover:bg-muted/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10603
|
+
),
|
|
10604
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10605
|
+
onClick: (e) => {
|
|
10606
|
+
e.preventDefault();
|
|
10607
|
+
e.stopPropagation();
|
|
10608
|
+
onOpenChange(!isOpen);
|
|
9823
10609
|
}
|
|
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
10610
|
}
|
|
9835
|
-
}
|
|
9836
|
-
|
|
9837
|
-
|
|
10611
|
+
) }), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Maximize2, { className: "size-4" }) }),
|
|
10612
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10613
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Canvas mode" }),
|
|
10614
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.ArrowBigUp, { className: "size-2.5" }) }),
|
|
10615
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: kbdClass, children: "Z" })
|
|
10616
|
+
] })
|
|
10617
|
+
] }),
|
|
10618
|
+
/* @__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
10619
|
import_popover3.Popover.Popup,
|
|
9839
10620
|
{
|
|
9840
|
-
ref:
|
|
9841
|
-
className: "w-[
|
|
10621
|
+
ref: popupRef,
|
|
10622
|
+
className: "w-[180px] rounded-xl bg-background text-xs outline outline-1 outline-foreground/10 shadow-lg",
|
|
9842
10623
|
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)(
|
|
10624
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "px-1 py-1", children: [
|
|
10625
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
9857
10626
|
import_button8.Button,
|
|
9858
10627
|
{
|
|
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
|
-
),
|
|
10628
|
+
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
10629
|
onClick: () => {
|
|
9864
|
-
|
|
9865
|
-
|
|
10630
|
+
onZoomTo100?.();
|
|
10631
|
+
onOpenChange(false);
|
|
9866
10632
|
},
|
|
9867
10633
|
children: [
|
|
9868
|
-
/* @__PURE__ */ (0,
|
|
9869
|
-
|
|
10634
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Scan, { className: "size-3.5" }),
|
|
10635
|
+
"Actual size (100%)"
|
|
9870
10636
|
]
|
|
9871
|
-
}
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
10637
|
+
}
|
|
10638
|
+
),
|
|
10639
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
10640
|
+
import_button8.Button,
|
|
10641
|
+
{
|
|
10642
|
+
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",
|
|
10643
|
+
onClick: () => {
|
|
10644
|
+
onFitToViewport?.();
|
|
10645
|
+
onOpenChange(false);
|
|
10646
|
+
},
|
|
10647
|
+
children: [
|
|
10648
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Minimize2, { className: "size-3.5" }),
|
|
10649
|
+
"Fit to viewport"
|
|
10650
|
+
]
|
|
10651
|
+
}
|
|
10652
|
+
),
|
|
10653
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "my-1 border-t border-foreground/10" }),
|
|
10654
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
10655
|
+
import_button8.Button,
|
|
10656
|
+
{
|
|
10657
|
+
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",
|
|
10658
|
+
onClick: () => {
|
|
10659
|
+
onToggleCanvas?.();
|
|
10660
|
+
onOpenChange(false);
|
|
10661
|
+
},
|
|
10662
|
+
children: [
|
|
10663
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react15.Check, { className: cn("size-3.5", canvasActive ? "opacity-100" : "opacity-0") }),
|
|
10664
|
+
"Canvas mode"
|
|
10665
|
+
]
|
|
10666
|
+
}
|
|
10667
|
+
)
|
|
10668
|
+
] })
|
|
9888
10669
|
}
|
|
9889
10670
|
) }) })
|
|
9890
10671
|
] });
|
|
9891
10672
|
}
|
|
9892
10673
|
|
|
9893
10674
|
// src/toolbar.tsx
|
|
9894
|
-
var
|
|
10675
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
9895
10676
|
function DirectEditToolbarInner({
|
|
9896
10677
|
editModeActive,
|
|
9897
10678
|
onToggleEditMode,
|
|
@@ -9908,33 +10689,63 @@ function DirectEditToolbarInner({
|
|
|
9908
10689
|
onClearSessionEdits,
|
|
9909
10690
|
onRemoveSessionEdit,
|
|
9910
10691
|
onDeleteComment,
|
|
9911
|
-
className
|
|
10692
|
+
className,
|
|
10693
|
+
canvasActive = false,
|
|
10694
|
+
canvasZoom = 1,
|
|
10695
|
+
onToggleCanvas,
|
|
10696
|
+
onSetCanvasZoom,
|
|
10697
|
+
onZoomTo100,
|
|
10698
|
+
onFitToViewport
|
|
9912
10699
|
}) {
|
|
9913
10700
|
const container = usePortalContainer();
|
|
9914
|
-
const toolbarRef =
|
|
9915
|
-
const { dockedEdge, isDragging, isSnapping, style: dockStyle, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
|
|
10701
|
+
const toolbarRef = React36.useRef(null);
|
|
10702
|
+
const { dockedEdge, isDragging, isSnapping, style: dockStyle, predictSize, handlePointerDown, handlePointerMove, handlePointerUp, handlePointerCancel } = useToolbarDock(toolbarRef);
|
|
9916
10703
|
const isVertical = dockedEdge === "left" || dockedEdge === "right";
|
|
10704
|
+
const [activePopover, setActivePopover] = React36.useState(null);
|
|
10705
|
+
const sizeCacheRef = React36.useRef({});
|
|
10706
|
+
React36.useEffect(() => {
|
|
10707
|
+
const el = toolbarRef.current;
|
|
10708
|
+
if (!el) return;
|
|
10709
|
+
const key = `${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`;
|
|
10710
|
+
const timer = setTimeout(() => {
|
|
10711
|
+
const rect = el.getBoundingClientRect();
|
|
10712
|
+
sizeCacheRef.current[key] = { w: rect.width, h: rect.height };
|
|
10713
|
+
}, 350);
|
|
10714
|
+
return () => clearTimeout(timer);
|
|
10715
|
+
}, [editModeActive, dockedEdge]);
|
|
10716
|
+
const prevEditModeRef = React36.useRef(editModeActive);
|
|
10717
|
+
React36.useEffect(() => {
|
|
10718
|
+
if (prevEditModeRef.current === editModeActive) return;
|
|
10719
|
+
prevEditModeRef.current = editModeActive;
|
|
10720
|
+
const target = sizeCacheRef.current[`${dockedEdge}:${editModeActive ? "expanded" : "collapsed"}`];
|
|
10721
|
+
if (target) {
|
|
10722
|
+
predictSize(target.w, target.h);
|
|
10723
|
+
}
|
|
10724
|
+
}, [editModeActive, dockedEdge, predictSize]);
|
|
10725
|
+
React36.useEffect(() => {
|
|
10726
|
+
if (isDragging) setActivePopover(null);
|
|
10727
|
+
}, [isDragging]);
|
|
10728
|
+
React36.useEffect(() => {
|
|
10729
|
+
if (!editModeActive) setActivePopover(null);
|
|
10730
|
+
}, [editModeActive]);
|
|
9917
10731
|
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
|
-
}, []);
|
|
10732
|
+
const [isMac] = React36.useState(() => typeof navigator !== "undefined" ? navigator.platform?.includes("Mac") ?? false : false);
|
|
9922
10733
|
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,
|
|
10734
|
+
const shortcutContent = isMac ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
10735
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Command, { className: "size-2.5" }) }),
|
|
10736
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "." })
|
|
10737
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
10738
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "Ctrl" }),
|
|
10739
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "." })
|
|
9929
10740
|
] });
|
|
9930
|
-
const toolbar = /* @__PURE__ */ (0,
|
|
10741
|
+
const toolbar = /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
9931
10742
|
"div",
|
|
9932
10743
|
{
|
|
9933
10744
|
ref: toolbarRef,
|
|
9934
10745
|
"data-direct-edit": "toolbar",
|
|
9935
10746
|
style: { pointerEvents: "auto", touchAction: "none", ...dockStyle },
|
|
9936
10747
|
className: cn(
|
|
9937
|
-
"group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg
|
|
10748
|
+
"group z-[99999] flex rounded-xl outline outline-1 outline-foreground/10 bg-background p-1.5 shadow-lg",
|
|
9938
10749
|
isVertical ? "flex-col items-center" : "flex-row items-center",
|
|
9939
10750
|
isDragging && "cursor-grabbing select-none shadow-2xl",
|
|
9940
10751
|
className
|
|
@@ -9945,21 +10756,21 @@ function DirectEditToolbarInner({
|
|
|
9945
10756
|
onPointerCancel: handlePointerCancel,
|
|
9946
10757
|
onLostPointerCapture: handlePointerCancel,
|
|
9947
10758
|
children: [
|
|
9948
|
-
/* @__PURE__ */ (0,
|
|
10759
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
9949
10760
|
"flex shrink-0 cursor-grab items-center justify-center",
|
|
9950
10761
|
isVertical ? "w-full pt-0 pb-1.5" : "h-full pl-0 pr-1.5"
|
|
9951
|
-
), children: /* @__PURE__ */ (0,
|
|
10762
|
+
), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
9952
10763
|
"shrink-0 rounded-full bg-foreground/25",
|
|
9953
10764
|
isVertical ? "h-0.5 w-4" : "h-4 w-0.5"
|
|
9954
10765
|
) }) }),
|
|
9955
|
-
/* @__PURE__ */ (0,
|
|
9956
|
-
/* @__PURE__ */ (0,
|
|
9957
|
-
/* @__PURE__ */ (0,
|
|
10766
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipProvider, { delayDuration: 200, children: [
|
|
10767
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10768
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
9958
10769
|
TooltipTrigger,
|
|
9959
10770
|
{
|
|
9960
10771
|
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" :
|
|
10772
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-[color,background-color] duration-150 ease-out",
|
|
10773
|
+
editModeActive && activeTool !== "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
9963
10774
|
),
|
|
9964
10775
|
onPointerDown: (e) => e.stopPropagation(),
|
|
9965
10776
|
onClick: () => {
|
|
@@ -9969,89 +10780,144 @@ function DirectEditToolbarInner({
|
|
|
9969
10780
|
onToggleEditMode();
|
|
9970
10781
|
}
|
|
9971
10782
|
},
|
|
9972
|
-
children: /* @__PURE__ */ (0,
|
|
10783
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.MousePointer2, { className: "size-4" })
|
|
9973
10784
|
}
|
|
9974
10785
|
),
|
|
9975
|
-
/* @__PURE__ */ (0,
|
|
9976
|
-
/* @__PURE__ */ (0,
|
|
10786
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10787
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: editModeActive ? "Select" : "Activate design mode" }),
|
|
9977
10788
|
shortcutContent
|
|
9978
10789
|
] })
|
|
9979
10790
|
] }),
|
|
9980
|
-
/* @__PURE__ */ (0,
|
|
10791
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
9981
10792
|
"div",
|
|
9982
10793
|
{
|
|
9983
10794
|
className: cn(
|
|
9984
|
-
"
|
|
9985
|
-
isVertical ? editModeActive ? "mt-1
|
|
10795
|
+
"grid place-items-center overflow-hidden",
|
|
10796
|
+
isVertical ? editModeActive ? "mt-1 grid-rows-[1fr]" : "mt-0 grid-rows-[0fr]" : editModeActive ? "ml-1 grid-cols-[1fr]" : "ml-0 grid-cols-[0fr]"
|
|
9986
10797
|
),
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
10798
|
+
style: {
|
|
10799
|
+
transitionProperty: "grid-template-columns, grid-template-rows, margin",
|
|
10800
|
+
transitionDuration: "200ms",
|
|
10801
|
+
transitionTimingFunction: "cubic-bezier(0.25, 1, 0.5, 1)",
|
|
10802
|
+
transitionDelay: editModeActive ? "0ms" : "80ms"
|
|
10803
|
+
},
|
|
10804
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
10805
|
+
"div",
|
|
10806
|
+
{
|
|
10807
|
+
className: cn("flex gap-1 overflow-hidden", isVertical ? "min-h-0 flex-col items-center" : "min-w-0 flex-row items-center"),
|
|
10808
|
+
style: {
|
|
10809
|
+
filter: editModeActive ? "blur(0px)" : "blur(5px)",
|
|
10810
|
+
opacity: editModeActive ? 1 : 0,
|
|
10811
|
+
transitionProperty: "filter, opacity",
|
|
10812
|
+
transitionDuration: "250ms, 100ms",
|
|
10813
|
+
transitionTimingFunction: "cubic-bezier(0.33, 1, 0.68, 1)",
|
|
10814
|
+
transitionDelay: editModeActive ? "80ms" : "0ms"
|
|
10815
|
+
},
|
|
10816
|
+
children: [
|
|
10817
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10818
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10819
|
+
TooltipTrigger,
|
|
10820
|
+
{
|
|
10821
|
+
className: cn(
|
|
10822
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10823
|
+
activeTool === "comment" ? "bg-foreground text-background hover:bg-foreground/80" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10824
|
+
),
|
|
10825
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10826
|
+
onClick: () => onSetActiveTool?.(activeTool === "comment" ? "select" : "comment"),
|
|
10827
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.MessageSquare, { className: "size-4" })
|
|
10828
|
+
}
|
|
9995
10829
|
),
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
/* @__PURE__ */ (0,
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10830
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10831
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: activeTool === "comment" ? "Exit comment mode" : "Comment" }),
|
|
10832
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ArrowBigUp, { className: "size-3" }) }),
|
|
10833
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "C" })
|
|
10834
|
+
] })
|
|
10835
|
+
] }),
|
|
10836
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10837
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10838
|
+
TooltipTrigger,
|
|
10839
|
+
{
|
|
10840
|
+
className: cn(
|
|
10841
|
+
"flex cursor-pointer items-center justify-center rounded-[8px] p-2 transition-colors",
|
|
10842
|
+
rulersVisible ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
10843
|
+
),
|
|
10844
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10845
|
+
onClick: onToggleRulers,
|
|
10846
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.Ruler, { className: "size-4" })
|
|
10847
|
+
}
|
|
10014
10848
|
),
|
|
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
|
-
|
|
10849
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10850
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: rulersVisible ? "Hide rulers" : "Show rulers" }),
|
|
10851
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ArrowBigUp, { className: "size-2.5" }) }),
|
|
10852
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "R" })
|
|
10853
|
+
] })
|
|
10854
|
+
] }),
|
|
10855
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10856
|
+
ZoomPopover,
|
|
10857
|
+
{
|
|
10858
|
+
tooltipSide,
|
|
10859
|
+
canvasActive,
|
|
10860
|
+
canvasZoom,
|
|
10861
|
+
isOpen: activePopover === "zoom",
|
|
10862
|
+
onOpenChange: (open) => setActivePopover(open ? "zoom" : null),
|
|
10863
|
+
onToggleCanvas,
|
|
10864
|
+
onSetCanvasZoom,
|
|
10865
|
+
onZoomTo100,
|
|
10866
|
+
onFitToViewport
|
|
10867
|
+
}
|
|
10868
|
+
),
|
|
10869
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
10870
|
+
"border-foreground/10",
|
|
10871
|
+
isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
|
|
10872
|
+
) }),
|
|
10873
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10874
|
+
EditsPopover,
|
|
10875
|
+
{
|
|
10876
|
+
tooltipSide,
|
|
10877
|
+
sessionEditCount,
|
|
10878
|
+
isOpen: activePopover === "edits",
|
|
10879
|
+
onOpenChange: (open) => setActivePopover(open ? "edits" : null),
|
|
10880
|
+
onGetSessionItems,
|
|
10881
|
+
onExportAllEdits,
|
|
10882
|
+
onSendAllToAgents,
|
|
10883
|
+
onClearSessionEdits,
|
|
10884
|
+
onRemoveSessionEdit,
|
|
10885
|
+
onDeleteComment
|
|
10886
|
+
}
|
|
10887
|
+
),
|
|
10888
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10889
|
+
SettingsPopover,
|
|
10890
|
+
{
|
|
10891
|
+
tooltipSide,
|
|
10892
|
+
theme,
|
|
10893
|
+
isMac,
|
|
10894
|
+
isOpen: activePopover === "settings",
|
|
10895
|
+
onOpenChange: (open) => setActivePopover(open ? "settings" : null),
|
|
10896
|
+
onSetTheme
|
|
10897
|
+
}
|
|
10898
|
+
),
|
|
10899
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(
|
|
10900
|
+
"border-foreground/10",
|
|
10901
|
+
isVertical ? "my-0.5 w-5 border-t" : "mx-0.5 h-5 border-l"
|
|
10902
|
+
) }),
|
|
10903
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
10904
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10905
|
+
TooltipTrigger,
|
|
10906
|
+
{
|
|
10907
|
+
className: "flex cursor-pointer items-center justify-center rounded-[8px] p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
10908
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
10909
|
+
onClick: onToggleEditMode,
|
|
10910
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.X, { className: "size-4" })
|
|
10911
|
+
}
|
|
10912
|
+
),
|
|
10913
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TooltipContent, { side: tooltipSide, className: "inline-flex items-center gap-1.5", children: [
|
|
10914
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { children: "Close" }),
|
|
10915
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: kbdClass, children: "Esc" })
|
|
10916
|
+
] })
|
|
10917
|
+
] })
|
|
10918
|
+
]
|
|
10919
|
+
}
|
|
10920
|
+
)
|
|
10055
10921
|
}
|
|
10056
10922
|
)
|
|
10057
10923
|
] })
|
|
@@ -10064,7 +10930,7 @@ function DirectEditToolbarInner({
|
|
|
10064
10930
|
return toolbar;
|
|
10065
10931
|
}
|
|
10066
10932
|
function DirectEditToolbarContent() {
|
|
10067
|
-
const { editModeActive, activeTool, theme, sessionEditCount } = useDirectEditState();
|
|
10933
|
+
const { editModeActive, activeTool, theme, sessionEditCount, canvas } = useDirectEditState();
|
|
10068
10934
|
const {
|
|
10069
10935
|
toggleEditMode,
|
|
10070
10936
|
setActiveTool,
|
|
@@ -10074,10 +10940,14 @@ function DirectEditToolbarContent() {
|
|
|
10074
10940
|
sendAllSessionItemsToAgent,
|
|
10075
10941
|
clearSessionEdits,
|
|
10076
10942
|
removeSessionEdit,
|
|
10077
|
-
deleteComment
|
|
10943
|
+
deleteComment,
|
|
10944
|
+
toggleCanvas,
|
|
10945
|
+
setCanvasZoom,
|
|
10946
|
+
zoomCanvasTo100,
|
|
10947
|
+
fitCanvasToViewport
|
|
10078
10948
|
} = useDirectEditActions();
|
|
10079
10949
|
const [rulersVisible, toggleRulers] = useRulersVisible();
|
|
10080
|
-
return /* @__PURE__ */ (0,
|
|
10950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
10081
10951
|
DirectEditToolbarInner,
|
|
10082
10952
|
{
|
|
10083
10953
|
editModeActive,
|
|
@@ -10094,34 +10964,40 @@ function DirectEditToolbarContent() {
|
|
|
10094
10964
|
onSendAllToAgents: sendAllSessionItemsToAgent,
|
|
10095
10965
|
onClearSessionEdits: clearSessionEdits,
|
|
10096
10966
|
onRemoveSessionEdit: removeSessionEdit,
|
|
10097
|
-
onDeleteComment: deleteComment
|
|
10967
|
+
onDeleteComment: deleteComment,
|
|
10968
|
+
canvasActive: canvas?.active ?? false,
|
|
10969
|
+
canvasZoom: canvas?.zoom ?? 1,
|
|
10970
|
+
onToggleCanvas: toggleCanvas,
|
|
10971
|
+
onSetCanvasZoom: setCanvasZoom,
|
|
10972
|
+
onZoomTo100: zoomCanvasTo100,
|
|
10973
|
+
onFitToViewport: fitCanvasToViewport
|
|
10098
10974
|
}
|
|
10099
10975
|
);
|
|
10100
10976
|
}
|
|
10101
10977
|
function DirectEditToolbar() {
|
|
10102
|
-
const [mounted, setMounted] =
|
|
10103
|
-
|
|
10978
|
+
const [mounted, setMounted] = React36.useState(false);
|
|
10979
|
+
React36.useEffect(() => {
|
|
10104
10980
|
setMounted(true);
|
|
10105
10981
|
}, []);
|
|
10106
10982
|
if (!mounted) {
|
|
10107
10983
|
return null;
|
|
10108
10984
|
}
|
|
10109
|
-
return /* @__PURE__ */ (0,
|
|
10985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(DirectEditToolbarContent, {});
|
|
10110
10986
|
}
|
|
10111
10987
|
|
|
10112
10988
|
// src/direct-edit.tsx
|
|
10113
|
-
var
|
|
10989
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
10114
10990
|
function DirectEdit() {
|
|
10115
|
-
return /* @__PURE__ */ (0,
|
|
10116
|
-
/* @__PURE__ */ (0,
|
|
10117
|
-
/* @__PURE__ */ (0,
|
|
10118
|
-
/* @__PURE__ */ (0,
|
|
10991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(DirectEditProvider, { children: [
|
|
10992
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DirectEditPanel, {}),
|
|
10993
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DirectEditToolbar, {}),
|
|
10994
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Rulers, {})
|
|
10119
10995
|
] });
|
|
10120
10996
|
}
|
|
10121
10997
|
|
|
10122
10998
|
// src/demo.tsx
|
|
10123
|
-
var
|
|
10124
|
-
var
|
|
10999
|
+
var React37 = __toESM(require("react"));
|
|
11000
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
10125
11001
|
function createValue(num, unit = "px") {
|
|
10126
11002
|
return { numericValue: num, unit, raw: `${num}${unit}` };
|
|
10127
11003
|
}
|
|
@@ -10149,7 +11025,7 @@ var DEMO_LOCATOR = {
|
|
|
10149
11025
|
classList: ELEMENT_INFO.classList
|
|
10150
11026
|
};
|
|
10151
11027
|
function DirectEditDemo() {
|
|
10152
|
-
const [spacing, setSpacing] =
|
|
11028
|
+
const [spacing, setSpacing] = React37.useState({
|
|
10153
11029
|
paddingTop: createValue(16),
|
|
10154
11030
|
paddingRight: createValue(16),
|
|
10155
11031
|
paddingBottom: createValue(16),
|
|
@@ -10160,13 +11036,13 @@ function DirectEditDemo() {
|
|
|
10160
11036
|
marginLeft: createValue(0),
|
|
10161
11037
|
gap: createValue(16)
|
|
10162
11038
|
});
|
|
10163
|
-
const [borderRadius, setBorderRadius] =
|
|
11039
|
+
const [borderRadius, setBorderRadius] = React37.useState({
|
|
10164
11040
|
borderTopLeftRadius: createValue(8),
|
|
10165
11041
|
borderTopRightRadius: createValue(8),
|
|
10166
11042
|
borderBottomRightRadius: createValue(8),
|
|
10167
11043
|
borderBottomLeftRadius: createValue(8)
|
|
10168
11044
|
});
|
|
10169
|
-
const [border, setBorder] =
|
|
11045
|
+
const [border, setBorder] = React37.useState({
|
|
10170
11046
|
borderTopStyle: "solid",
|
|
10171
11047
|
borderTopWidth: createValue(1),
|
|
10172
11048
|
borderRightStyle: "solid",
|
|
@@ -10176,23 +11052,23 @@ function DirectEditDemo() {
|
|
|
10176
11052
|
borderLeftStyle: "solid",
|
|
10177
11053
|
borderLeftWidth: createValue(1)
|
|
10178
11054
|
});
|
|
10179
|
-
const [flex, setFlex] =
|
|
11055
|
+
const [flex, setFlex] = React37.useState({
|
|
10180
11056
|
display: "flex",
|
|
10181
11057
|
flexDirection: "row",
|
|
10182
11058
|
justifyContent: "flex-start",
|
|
10183
11059
|
alignItems: "center"
|
|
10184
11060
|
});
|
|
10185
|
-
const [sizing, setSizing] =
|
|
11061
|
+
const [sizing, setSizing] = React37.useState({
|
|
10186
11062
|
width: { mode: "fit", value: createValue(300) },
|
|
10187
11063
|
height: { mode: "fit", value: createValue(100) }
|
|
10188
11064
|
});
|
|
10189
|
-
const [color, setColor] =
|
|
11065
|
+
const [color, setColor] = React37.useState({
|
|
10190
11066
|
backgroundColor: { hex: "FFFFFF", alpha: 100, raw: "rgb(255, 255, 255)" },
|
|
10191
11067
|
color: { hex: "000000", alpha: 100, raw: "rgb(0, 0, 0)" },
|
|
10192
11068
|
borderColor: { hex: "DDDDDD", alpha: 100, raw: "rgb(221, 221, 221)" },
|
|
10193
11069
|
outlineColor: { hex: "000000", alpha: 0, raw: "transparent" }
|
|
10194
11070
|
});
|
|
10195
|
-
const [typography, setTypography] =
|
|
11071
|
+
const [typography, setTypography] = React37.useState({
|
|
10196
11072
|
fontFamily: "system-ui, sans-serif",
|
|
10197
11073
|
fontWeight: "400",
|
|
10198
11074
|
fontSize: createValue(16),
|
|
@@ -10201,9 +11077,9 @@ function DirectEditDemo() {
|
|
|
10201
11077
|
textAlign: "left",
|
|
10202
11078
|
textVerticalAlign: "flex-start"
|
|
10203
11079
|
});
|
|
10204
|
-
const [boxShadow, setBoxShadow] =
|
|
10205
|
-
const [pendingStyles, setPendingStyles] =
|
|
10206
|
-
const [editModeActive, setEditModeActive] =
|
|
11080
|
+
const [boxShadow, setBoxShadow] = React37.useState("none");
|
|
11081
|
+
const [pendingStyles, setPendingStyles] = React37.useState({});
|
|
11082
|
+
const [editModeActive, setEditModeActive] = React37.useState(false);
|
|
10207
11083
|
const handleUpdateSpacing = (key, value) => {
|
|
10208
11084
|
setSpacing((prev) => ({ ...prev, [key]: value }));
|
|
10209
11085
|
setPendingStyles((prev) => ({ ...prev, [camelToKebab(key)]: value.raw }));
|
|
@@ -10314,10 +11190,10 @@ function DirectEditDemo() {
|
|
|
10314
11190
|
return false;
|
|
10315
11191
|
}
|
|
10316
11192
|
};
|
|
10317
|
-
return /* @__PURE__ */ (0,
|
|
10318
|
-
/* @__PURE__ */ (0,
|
|
10319
|
-
/* @__PURE__ */ (0,
|
|
10320
|
-
/* @__PURE__ */ (0,
|
|
11193
|
+
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: [
|
|
11194
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { className: "mb-2 text-2xl font-bold", children: "Direct Edit Panel" }),
|
|
11195
|
+
/* @__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." }),
|
|
11196
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "mb-8 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10321
11197
|
DirectEditToolbarInner,
|
|
10322
11198
|
{
|
|
10323
11199
|
editModeActive,
|
|
@@ -10327,8 +11203,8 @@ function DirectEditDemo() {
|
|
|
10327
11203
|
}
|
|
10328
11204
|
}
|
|
10329
11205
|
) }),
|
|
10330
|
-
/* @__PURE__ */ (0,
|
|
10331
|
-
/* @__PURE__ */ (0,
|
|
11206
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "grid gap-8 lg:grid-cols-[300px_1fr]", children: [
|
|
11207
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
10332
11208
|
DirectEditPanelInner,
|
|
10333
11209
|
{
|
|
10334
11210
|
elementInfo: ELEMENT_INFO,
|
|
@@ -10360,10 +11236,10 @@ function DirectEditDemo() {
|
|
|
10360
11236
|
onSendToAgent: async () => false
|
|
10361
11237
|
}
|
|
10362
11238
|
),
|
|
10363
|
-
/* @__PURE__ */ (0,
|
|
10364
|
-
/* @__PURE__ */ (0,
|
|
10365
|
-
/* @__PURE__ */ (0,
|
|
10366
|
-
/* @__PURE__ */ (0,
|
|
11239
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "space-y-6", children: [
|
|
11240
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11241
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Live Preview" }),
|
|
11242
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
10367
11243
|
"div",
|
|
10368
11244
|
{
|
|
10369
11245
|
className: "bg-background border flex",
|
|
@@ -10386,20 +11262,20 @@ function DirectEditDemo() {
|
|
|
10386
11262
|
alignItems: flex.alignItems
|
|
10387
11263
|
},
|
|
10388
11264
|
children: [
|
|
10389
|
-
/* @__PURE__ */ (0,
|
|
10390
|
-
/* @__PURE__ */ (0,
|
|
10391
|
-
/* @__PURE__ */ (0,
|
|
11265
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-blue-500/20 border border-blue-500/30" }),
|
|
11266
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-green-500/20 border border-green-500/30" }),
|
|
11267
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "size-12 rounded bg-purple-500/20 border border-purple-500/30" })
|
|
10392
11268
|
]
|
|
10393
11269
|
}
|
|
10394
11270
|
)
|
|
10395
11271
|
] }),
|
|
10396
|
-
/* @__PURE__ */ (0,
|
|
10397
|
-
/* @__PURE__ */ (0,
|
|
10398
|
-
/* @__PURE__ */ (0,
|
|
11272
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11273
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Pending Styles" }),
|
|
11274
|
+
/* @__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
11275
|
] }),
|
|
10400
|
-
/* @__PURE__ */ (0,
|
|
10401
|
-
/* @__PURE__ */ (0,
|
|
10402
|
-
/* @__PURE__ */ (0,
|
|
11276
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
|
|
11277
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "mb-3 text-sm font-medium", children: "Tailwind Classes" }),
|
|
11278
|
+
/* @__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
11279
|
] })
|
|
10404
11280
|
] })
|
|
10405
11281
|
] })
|