made-refine 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +17 -7
- package/dist/index.d.ts +17 -7
- package/dist/index.js +1332 -224
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1330 -224
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/{utils-C7RBdUAE.d.mts → utils-dcZIwXa7.d.mts} +114 -2
- package/dist/{utils-C7RBdUAE.d.ts → utils-dcZIwXa7.d.ts} +114 -2
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +661 -62
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +650 -62
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import * as React8 from "react";
|
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
|
|
9
9
|
// dist/styles.css
|
|
10
|
-
var styles_default = '/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-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}}';
|
|
10
|
+
var styles_default = '/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-thin:100;--font-weight-extralight:200;--font-weight-light:300;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--leading-relaxed:1.625;--radius-sm:calc(.5rem - 4px);--radius-md:calc(.5rem - 2px);--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-border:#e6e6e6;--color-ring:#262626;--color-background:#fff;--color-foreground:#171717;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary-foreground:#171717;--color-destructive:#ef4444;--color-destructive-foreground:#fafafa;--color-muted:#f2f2f2;--color-muted-foreground:#737373;--color-popover-foreground:#171717}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root,:host{color-scheme:light;color:var(--color-foreground)}@media (prefers-color-scheme:dark){:root,:host(:not([data-theme])),:host([data-theme=system]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}}:host([data-theme=dark]){color-scheme:dark;color:var(--color-foreground);--color-border:#2e2e2e;--color-input:#2e2e2e;--color-ring:#d4d4d4;--color-background:#121212;--color-foreground:#fafafa;--color-primary:#fafafa;--color-primary-foreground:#171717;--color-secondary:#262626;--color-secondary-foreground:#fafafa;--color-destructive:#7f1d1d;--color-destructive-foreground:#fafafa;--color-muted:#262626;--color-muted-foreground:#a3a3a3;--color-accent:#262626;--color-accent-foreground:#fafafa;--color-popover:#171717;--color-popover-foreground:#fafafa}*,:before,:after{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:var(--color-background);--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;border-color:var(--color-border)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.top-1\\/2{top:50%}.left-1\\.5{left:calc(var(--spacing)*1.5)}.left-1\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-3{left:calc(var(--spacing)*3)}.z-\\[99990\\]{z-index:99990}.z-\\[99991\\]{z-index:99991}.z-\\[99998\\]{z-index:99998}.z-\\[99999\\]{z-index:99999}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-4{margin:calc(var(--spacing)*4)}.mx-0\\.5{margin-inline:calc(var(--spacing)*.5)}.mx-2{margin-inline:calc(var(--spacing)*2)}.my-0\\.5{margin-block:calc(var(--spacing)*.5)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-0{margin-top:calc(var(--spacing)*0)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2\\.5{margin-top:calc(var(--spacing)*2.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-0{margin-left:calc(var(--spacing)*0)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.block{display:block}.contents{display:contents}.flex{display:flex}.flow-root{display:flow-root}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.size-1{width:calc(var(--spacing)*1);height:calc(var(--spacing)*1)}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-full{width:100%;height:100%}.h-0\\.5{height:calc(var(--spacing)*.5)}.h-2{height:calc(var(--spacing)*2)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-\\[150px\\]{height:150px}.h-auto{height:auto}.h-fit{height:fit-content}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\\[240px\\]{max-height:240px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\\[18px\\]{min-height:18px}.w-0\\.5{width:calc(var(--spacing)*.5)}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-10{width:calc(var(--spacing)*10)}.w-11{width:calc(var(--spacing)*11)}.w-14{width:calc(var(--spacing)*14)}.w-\\[1\\.5px\\]{width:1.5px}.w-\\[30px\\]{width:30px}.w-\\[60px\\]{width:60px}.w-\\[68px\\]{width:68px}.w-\\[180px\\]{width:180px}.w-\\[200px\\]{width:200px}.w-\\[260px\\]{width:260px}.w-\\[280px\\]{width:280px}.w-\\[300px\\]{width:300px}.w-\\[340px\\]{width:340px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\\[18px\\]{min-width:18px}.min-w-\\[20px\\]{min-width:20px}.min-w-\\[100px\\]{min-width:100px}.min-w-\\[120px\\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-\\(--transform-origin\\){transform-origin:var(--transform-origin)}.-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-crosshair{cursor:crosshair}.cursor-default{cursor:default}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.\\[appearance\\:textfield\\]{appearance:textfield}.appearance-none{appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-\\[0fr\\]{grid-template-columns:0fr}.grid-cols-\\[1fr\\]{grid-template-columns:1fr}.grid-rows-\\[0fr\\]{grid-template-rows:0fr}.grid-rows-\\[1fr\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-evenly{justify-content:space-evenly}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-\\[2px\\]{gap:2px}.gap-\\[4px\\]{gap:4px}:where(.space-y-1\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-\\[6px\\]{border-radius:6px}.rounded-\\[8px\\]{border-radius:8px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-tl{border-top-left-radius:.25rem}.rounded-tr{border-top-right-radius:.25rem}.rounded-br{border-bottom-right-radius:.25rem}.rounded-bl{border-bottom-left-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-double{--tw-border-style:double;border-style:double}.border-none{--tw-border-style:none;border-style:none}.border-solid{--tw-border-style:solid;border-style:solid}.\\[border-top-style\\:solid\\]{border-top-style:solid}.\\[border-right-style\\:dashed\\]{border-right-style:dashed}.\\[border-bottom-style\\:dashed\\]{border-bottom-style:dashed}.\\[border-bottom-style\\:dotted\\]{border-bottom-style:dotted}.\\[border-bottom-style\\:solid\\]{border-bottom-style:solid}.\\[border-left-style\\:double\\]{border-left-style:double}.\\[border-left-style\\:solid\\]{border-left-style:solid}.border-border{border-color:var(--color-border)}.border-border\\/30{border-color:#e6e6e64d}@supports (color:color-mix(in lab, red, red)){.border-border\\/30{border-color:color-mix(in oklab,var(--color-border)30%,transparent)}}.border-border\\/50{border-color:#e6e6e680}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--color-border)50%,transparent)}}.border-foreground\\/10{border-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/10{border-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.border-transparent{border-color:#0000}.border-white{border-color:var(--color-white)}.bg-\\[canvas\\]{background-color:canvas}.bg-background{background-color:var(--color-background)}.bg-background\\/85{background-color:#ffffffd9}@supports (color:color-mix(in lab, red, red)){.bg-background\\/85{background-color:color-mix(in oklab,var(--color-background)85%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-border{background-color:var(--color-border)}.bg-destructive{background-color:var(--color-destructive)}.bg-foreground{background-color:var(--color-foreground)}.bg-foreground\\/25{background-color:#17171740}@supports (color:color-mix(in lab, red, red)){.bg-foreground\\/25{background-color:color-mix(in oklab,var(--color-foreground)25%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\\/30{background-color:#7373734d}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/30{background-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-transparent{background-color:#0000}.fill-border{fill:var(--color-border)}.p-0{padding:calc(var(--spacing)*0)}.p-0\\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-3\\.5{padding-block:calc(var(--spacing)*3.5)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2\\.5{padding-top:calc(var(--spacing)*2.5)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pt-\\[13px\\]{padding-top:13px}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-1\\.5{padding-right:calc(var(--spacing)*1.5)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-1\\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-0{padding-left:calc(var(--spacing)*0)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-7{padding-left:calc(var(--spacing)*7)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[7px\\]{font-size:7px}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-extralight{--tw-font-weight:var(--font-weight-extralight);font-weight:var(--font-weight-extralight)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.font-thin{--tw-font-weight:var(--font-weight-thin);font-weight:var(--font-weight-thin)}.whitespace-nowrap{white-space:nowrap}.text-background{color:var(--color-background)}.text-blue-500{color:var(--color-blue-500)}.text-destructive-foreground{color:var(--color-destructive-foreground)}.text-foreground{color:var(--color-foreground)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-popover-foreground{color:var(--color-popover-foreground)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-500{color:var(--color-red-500)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xs{--tw-shadow:0 1px var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.3\\)\\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_4px_6px_-1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[inset_0_0_0_1px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:inset 0 0 0 1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-white{--tw-ring-color:var(--color-white)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.outline-border{outline-color:var(--color-border)}.outline-foreground\\/10{outline-color:#1717171a}@supports (color:color-mix(in lab, red, red)){.outline-foreground\\/10{outline-color:color-mix(in oklab,var(--color-foreground)10%,transparent)}}.outline-red-500\\/70{outline-color:#fb2c36b3}@supports (color:color-mix(in lab, red, red)){.outline-red-500\\/70{outline-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[color\\,background-color\\]{transition-property:color,background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[opacity\\,background-color\\,color\\]{transition-property:opacity,background-color,color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[transform\\,scale\\,opacity\\]{transition-property:transform,scale,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-dashed{--tw-outline-style:dashed;outline-style:dashed}.outline-dotted{--tw-outline-style:dotted;outline-style:dotted}.outline-double{--tw-outline-style:double;outline-style:double}.outline-none{--tw-outline-style:none;outline-style:none}.outline-solid{--tw-outline-style:solid;outline-style:solid}.select-none{-webkit-user-select:none;user-select:none}.\\[-ms-overflow-style\\:none\\]{-ms-overflow-style:none}.\\[scrollbar-width\\:none\\]{scrollbar-width:none}.duration-150{animation-duration:.15s}.duration-200{animation-duration:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}@media (hover:hover){.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\\/pin\\:inline:is(:where(.group\\/pin):hover *){display:inline}}.file\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\:bg-transparent::file-selector-button{background-color:#0000}.file\\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\:text-foreground::file-selector-button{color:var(--color-foreground)}.placeholder\\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.placeholder\\:text-red-400::placeholder{color:var(--color-red-400)}.focus-within\\:ring-1:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--color-ring)}.focus-within\\:outline-none:focus-within{--tw-outline-style:none;outline-style:none}.focus-within\\:ring-inset:focus-within{--tw-ring-inset:inset}@media (hover:hover){.hover\\:scale-\\[1\\.67\\]:hover{scale:1.67}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-destructive\\/90:hover{background-color:#ef4444e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--color-destructive)90%,transparent)}}.hover\\:bg-foreground\\/80:hover{background-color:#171717cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-foreground\\/80:hover{background-color:color-mix(in oklab,var(--color-foreground)80%,transparent)}}.hover\\:bg-muted:hover{background-color:var(--color-muted)}.hover\\:bg-muted-foreground\\/10:hover{background-color:#7373731a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/10:hover{background-color:color-mix(in oklab,var(--color-muted-foreground)10%,transparent)}}.hover\\:bg-muted\\/50:hover{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/50:hover{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.hover\\:bg-muted\\/80:hover{background-color:#f2f2f2cc}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted\\/80:hover{background-color:color-mix(in oklab,var(--color-muted)80%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\\:text-foreground:hover{color:var(--color-foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\:cursor-grabbing:active{cursor:grabbing}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.disabled\\:opacity-60:disabled{opacity:.6}.data-ending-style\\:scale-90[data-ending-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-ending-style\\:opacity-0[data-ending-style]{opacity:0}.data-instant\\:transition-none[data-instant]{transition-property:none}.data-starting-style\\:scale-90[data-starting-style]{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-starting-style\\:opacity-0[data-starting-style]{opacity:0}.data-\\[highlighted\\]\\:bg-muted[data-highlighted]{background-color:var(--color-muted)}.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:#f2f2f280}@supports (color:color-mix(in lab, red, red)){.data-\\[highlighted\\]\\:bg-muted\\/50[data-highlighted]{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.data-\\[highlighted\\]\\:text-foreground[data-highlighted]{color:var(--color-foreground)}@media (prefers-color-scheme:dark){.dark\\:shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\\:-outline-offset-1{outline-offset:calc(1px*-1)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&\\:\\:-webkit-inner-spin-button\\]\\:appearance-none::-webkit-inner-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-outer-spin-button\\]\\:appearance-none::-webkit-outer-spin-button{appearance:none}.\\[\\&\\:\\:-webkit-scrollbar\\]\\:hidden::-webkit-scrollbar{display:none}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none;animation:none}}.lucide{stroke-width:1px}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes pulse{50%{opacity:.5}}';
|
|
11
11
|
|
|
12
12
|
// src/portal-container.tsx
|
|
13
13
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -1143,6 +1143,10 @@ function getFlexDirection(element) {
|
|
|
1143
1143
|
const computed = window.getComputedStyle(element);
|
|
1144
1144
|
return computed.flexDirection;
|
|
1145
1145
|
}
|
|
1146
|
+
function isInFlowChild(el) {
|
|
1147
|
+
const cs = window.getComputedStyle(el);
|
|
1148
|
+
return cs.display !== "none" && cs.position !== "absolute" && cs.position !== "fixed";
|
|
1149
|
+
}
|
|
1146
1150
|
function detectChildrenDirection(container, exclude) {
|
|
1147
1151
|
const computed = window.getComputedStyle(container);
|
|
1148
1152
|
if (computed.display === "flex" || computed.display === "inline-flex") {
|
|
@@ -1155,8 +1159,7 @@ function detectChildrenDirection(container, exclude) {
|
|
|
1155
1159
|
const visible = [];
|
|
1156
1160
|
for (const c of container.children) {
|
|
1157
1161
|
if (!(c instanceof HTMLElement) || c === exclude) continue;
|
|
1158
|
-
|
|
1159
|
-
if (cs.display === "none" || cs.position === "absolute" || cs.position === "fixed") continue;
|
|
1162
|
+
if (!isInFlowChild(c)) continue;
|
|
1160
1163
|
visible.push(c);
|
|
1161
1164
|
if (visible.length === 2) break;
|
|
1162
1165
|
}
|
|
@@ -1169,6 +1172,29 @@ function detectChildrenDirection(container, exclude) {
|
|
|
1169
1172
|
}
|
|
1170
1173
|
return { axis: "vertical", reversed: second.bottom < first.top };
|
|
1171
1174
|
}
|
|
1175
|
+
function computeIntendedIndex(parent, draggedElement) {
|
|
1176
|
+
const { axis } = detectChildrenDirection(parent, draggedElement);
|
|
1177
|
+
const isHorizontal = axis === "horizontal";
|
|
1178
|
+
const draggedRect = draggedElement.getBoundingClientRect();
|
|
1179
|
+
const intendedCenter = isHorizontal ? draggedRect.left + draggedRect.width / 2 : draggedRect.top + draggedRect.height / 2;
|
|
1180
|
+
const siblings = [];
|
|
1181
|
+
for (const c of parent.children) {
|
|
1182
|
+
if (!(c instanceof HTMLElement) || c === draggedElement) continue;
|
|
1183
|
+
if (!isInFlowChild(c)) continue;
|
|
1184
|
+
siblings.push(c);
|
|
1185
|
+
}
|
|
1186
|
+
if (siblings.length === 0) {
|
|
1187
|
+
return { index: 0, siblingBefore: null, siblingAfter: null };
|
|
1188
|
+
}
|
|
1189
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
1190
|
+
const rect = siblings[i].getBoundingClientRect();
|
|
1191
|
+
const midpoint = isHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
|
|
1192
|
+
if (intendedCenter < midpoint) {
|
|
1193
|
+
return { index: i, siblingBefore: i > 0 ? siblings[i - 1] : null, siblingAfter: siblings[i] };
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
return { index: siblings.length, siblingBefore: siblings[siblings.length - 1], siblingAfter: null };
|
|
1197
|
+
}
|
|
1172
1198
|
function htmlChildren(el) {
|
|
1173
1199
|
return Array.from(el.children).filter(
|
|
1174
1200
|
(child) => child instanceof HTMLElement
|
|
@@ -1269,6 +1295,22 @@ function findContainerAtPoint(x, y, exclude, preferredParent) {
|
|
|
1269
1295
|
}
|
|
1270
1296
|
return findContainerViaTraversal(x, y, exclude);
|
|
1271
1297
|
}
|
|
1298
|
+
function findLayoutContainerAtPoint(x, y, exclude, preferredParent) {
|
|
1299
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
1300
|
+
if (host) host.style.display = "none";
|
|
1301
|
+
const elements = document.elementsFromPoint(x, y);
|
|
1302
|
+
if (host) host.style.display = "";
|
|
1303
|
+
for (const el of elements) {
|
|
1304
|
+
if (skipElement(el, exclude)) continue;
|
|
1305
|
+
if (isLayoutContainer(el)) return el;
|
|
1306
|
+
}
|
|
1307
|
+
if (preferredParent && isLayoutContainer(preferredParent)) {
|
|
1308
|
+
for (const el of elements) {
|
|
1309
|
+
if (el === preferredParent) return preferredParent;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
return null;
|
|
1313
|
+
}
|
|
1272
1314
|
function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
|
|
1273
1315
|
const { axis, reversed: isReversed } = detectChildrenDirection(container, draggedElement);
|
|
1274
1316
|
const isHorizontal = axis === "horizontal";
|
|
@@ -1663,7 +1705,11 @@ function getReactComponentStack(element) {
|
|
|
1663
1705
|
return getRenderStack(fiber);
|
|
1664
1706
|
}
|
|
1665
1707
|
function getElementDisplayName(element) {
|
|
1666
|
-
|
|
1708
|
+
const tag = element.tagName.toLowerCase();
|
|
1709
|
+
if (element.id) return `${tag}#${element.id}`;
|
|
1710
|
+
const firstClass = Array.from(element.classList).find((c) => c && !c.startsWith("direct-edit"));
|
|
1711
|
+
if (firstClass) return `${tag}.${firstClass}`;
|
|
1712
|
+
return tag;
|
|
1667
1713
|
}
|
|
1668
1714
|
var STABLE_ATTRIBUTES = ["data-testid", "data-qa", "data-cy", "aria-label", "role"];
|
|
1669
1715
|
var MAX_SELECTOR_DEPTH = 24;
|
|
@@ -1951,26 +1997,28 @@ function parseDomSource(element) {
|
|
|
1951
1997
|
}
|
|
1952
1998
|
return { file, line, column };
|
|
1953
1999
|
}
|
|
1954
|
-
function
|
|
1955
|
-
const
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
};
|
|
1969
|
-
break;
|
|
1970
|
-
}
|
|
1971
|
-
fiber = fiber._debugOwner ?? fiber.return ?? null;
|
|
2000
|
+
function getElementSource(element) {
|
|
2001
|
+
const domSource = parseDomSource(element);
|
|
2002
|
+
if (domSource) return domSource;
|
|
2003
|
+
const seenFibers = /* @__PURE__ */ new Set();
|
|
2004
|
+
let fiber = getFiberForElement(element);
|
|
2005
|
+
while (fiber && !seenFibers.has(fiber)) {
|
|
2006
|
+
seenFibers.add(fiber);
|
|
2007
|
+
const fiberSource = getSourceFromFiber(fiber);
|
|
2008
|
+
if (fiberSource?.fileName) {
|
|
2009
|
+
return {
|
|
2010
|
+
file: fiberSource.fileName,
|
|
2011
|
+
line: fiberSource.lineNumber,
|
|
2012
|
+
column: fiberSource.columnNumber
|
|
2013
|
+
};
|
|
1972
2014
|
}
|
|
2015
|
+
fiber = fiber._debugOwner ?? fiber.return ?? null;
|
|
1973
2016
|
}
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
function getElementLocator(element) {
|
|
2020
|
+
const elementInfo = getElementInfo(element);
|
|
2021
|
+
const domSource = getElementSource(element);
|
|
1974
2022
|
return {
|
|
1975
2023
|
reactStack: getReactComponentStack(element),
|
|
1976
2024
|
domSelector: buildDomSelector(element),
|
|
@@ -1989,7 +2037,7 @@ function getLocatorHeader(locator) {
|
|
|
1989
2037
|
const formattedSource = locator.domSource?.file ? formatSourceLocation(locator.domSource.file, locator.domSource.line, locator.domSource.column) : primaryFrame?.file ? formatSourceLocation(primaryFrame.file, primaryFrame.line, primaryFrame.column) : null;
|
|
1990
2038
|
return { componentLabel, formattedSource };
|
|
1991
2039
|
}
|
|
1992
|
-
function buildLocatorContextLines(locator) {
|
|
2040
|
+
function buildLocatorContextLines(locator, options) {
|
|
1993
2041
|
const lines = [];
|
|
1994
2042
|
const { componentLabel, formattedSource } = getLocatorHeader(locator);
|
|
1995
2043
|
const target = (locator.targetHtml || locator.domContextHtml || "").trim();
|
|
@@ -2002,7 +2050,7 @@ function buildLocatorContextLines(locator) {
|
|
|
2002
2050
|
lines.push("target:");
|
|
2003
2051
|
lines.push(target);
|
|
2004
2052
|
}
|
|
2005
|
-
if (context && context !== target) {
|
|
2053
|
+
if (!options?.skipContext && context && context !== target) {
|
|
2006
2054
|
lines.push("context:");
|
|
2007
2055
|
lines.push(context);
|
|
2008
2056
|
}
|
|
@@ -2156,6 +2204,29 @@ function buildEditExport(arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
|
|
|
2156
2204
|
}
|
|
2157
2205
|
return lines.join("\n");
|
|
2158
2206
|
}
|
|
2207
|
+
function buildEditExportWithOptions(locator, pendingStyles, textEdit, options) {
|
|
2208
|
+
const changes = [];
|
|
2209
|
+
const collapsedStyles = collapseExportShorthands(pendingStyles);
|
|
2210
|
+
for (const [property, value] of Object.entries(collapsedStyles)) {
|
|
2211
|
+
const tailwindClass = stylesToTailwind({ [property]: value });
|
|
2212
|
+
changes.push({ property, value, tailwind: tailwindClass });
|
|
2213
|
+
}
|
|
2214
|
+
const lines = buildLocatorContextLines(locator, options);
|
|
2215
|
+
lines.push("");
|
|
2216
|
+
if (changes.length > 0) {
|
|
2217
|
+
lines.push("edits:");
|
|
2218
|
+
for (const change of changes) {
|
|
2219
|
+
const tailwind = change.tailwind ? ` (${change.tailwind})` : "";
|
|
2220
|
+
lines.push(`${change.property}: ${change.value}${tailwind}`);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
if (textEdit) {
|
|
2224
|
+
lines.push("text content changed:");
|
|
2225
|
+
lines.push(`from: "${textEdit.originalText}"`);
|
|
2226
|
+
lines.push(`to: "${textEdit.newText}"`);
|
|
2227
|
+
}
|
|
2228
|
+
return lines.join("\n");
|
|
2229
|
+
}
|
|
2159
2230
|
function buildCommentExport(locator, commentText, replies) {
|
|
2160
2231
|
const lines = buildLocatorContextLines(locator);
|
|
2161
2232
|
lines.push("");
|
|
@@ -2167,55 +2238,545 @@ function buildCommentExport(locator, commentText, replies) {
|
|
|
2167
2238
|
}
|
|
2168
2239
|
return lines.join("\n");
|
|
2169
2240
|
}
|
|
2170
|
-
function
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
if (!siblingBefore && siblingAfter) return `before <${siblingAfter}> (first)`;
|
|
2174
|
-
return "(only child)";
|
|
2241
|
+
function normalizeSelector(selector) {
|
|
2242
|
+
const value = selector?.trim();
|
|
2243
|
+
return value && value.length > 0 ? value : null;
|
|
2175
2244
|
}
|
|
2176
|
-
function
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2245
|
+
function normalizeName(name) {
|
|
2246
|
+
return name?.trim().toLowerCase() || "element";
|
|
2247
|
+
}
|
|
2248
|
+
function buildAnchorRef(name, selector, source) {
|
|
2249
|
+
return {
|
|
2250
|
+
name: name?.trim() || "element",
|
|
2251
|
+
selector: normalizeSelector(selector),
|
|
2252
|
+
source: source?.file ? source : null
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
function anchorKey(anchor) {
|
|
2256
|
+
if (!anchor) return "none";
|
|
2257
|
+
const selector = normalizeSelector(anchor.selector);
|
|
2258
|
+
if (selector) return `selector:${selector}`;
|
|
2259
|
+
if (anchor.source?.file) {
|
|
2260
|
+
return `source:${anchor.source.file}:${anchor.source.line ?? 0}:${anchor.source.column ?? 0}`;
|
|
2261
|
+
}
|
|
2262
|
+
return `name:${normalizeName(anchor.name)}`;
|
|
2263
|
+
}
|
|
2264
|
+
function anchorsEqual(a, b) {
|
|
2265
|
+
if (!a && !b) return true;
|
|
2266
|
+
if (!a || !b) return false;
|
|
2267
|
+
const aSelector = normalizeSelector(a.selector);
|
|
2268
|
+
const bSelector = normalizeSelector(b.selector);
|
|
2269
|
+
if (aSelector && bSelector) return aSelector === bSelector;
|
|
2270
|
+
if (a.source?.file && b.source?.file) {
|
|
2271
|
+
return a.source.file === b.source.file && (a.source.line ?? null) === (b.source.line ?? null) && (a.source.column ?? null) === (b.source.column ?? null);
|
|
2272
|
+
}
|
|
2273
|
+
return normalizeName(a.name) === normalizeName(b.name);
|
|
2274
|
+
}
|
|
2275
|
+
function formatAnchorRef(anchor, fallback = "(none)") {
|
|
2276
|
+
if (!anchor) return fallback;
|
|
2277
|
+
const selector = normalizeSelector(anchor.selector);
|
|
2278
|
+
if (selector) return selector;
|
|
2279
|
+
if (anchor.source?.file) return `<${anchor.name}> @ ${formatSourceLocation(anchor.source.file, anchor.source.line, anchor.source.column)}`;
|
|
2280
|
+
return `<${anchor.name}>`;
|
|
2281
|
+
}
|
|
2282
|
+
function buildPlacementRef(before, after) {
|
|
2283
|
+
if (before && after) {
|
|
2284
|
+
return {
|
|
2285
|
+
before,
|
|
2286
|
+
after,
|
|
2287
|
+
description: `between after ${formatAnchorRef(before)} and before ${formatAnchorRef(after)}`
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
if (before) {
|
|
2291
|
+
return {
|
|
2292
|
+
before,
|
|
2293
|
+
after: null,
|
|
2294
|
+
description: `after ${formatAnchorRef(before)}`
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
if (after) {
|
|
2298
|
+
return {
|
|
2299
|
+
before: null,
|
|
2300
|
+
after,
|
|
2301
|
+
description: `before ${formatAnchorRef(after)}`
|
|
2302
|
+
};
|
|
2181
2303
|
}
|
|
2182
|
-
return
|
|
2304
|
+
return {
|
|
2305
|
+
before: null,
|
|
2306
|
+
after: null,
|
|
2307
|
+
description: "as the only child"
|
|
2308
|
+
};
|
|
2183
2309
|
}
|
|
2184
|
-
function
|
|
2185
|
-
const
|
|
2186
|
-
|
|
2310
|
+
function buildPlacementFromMove(beforeName, beforeSelector, beforeSource, afterName, afterSelector, afterSource) {
|
|
2311
|
+
const before = beforeName || beforeSelector || beforeSource?.file ? buildAnchorRef(beforeName, beforeSelector, beforeSource) : null;
|
|
2312
|
+
const after = afterName || afterSelector || afterSource?.file ? buildAnchorRef(afterName, afterSelector, afterSource) : null;
|
|
2313
|
+
return buildPlacementRef(before, after);
|
|
2314
|
+
}
|
|
2315
|
+
function toRoundedVisualDelta(move) {
|
|
2316
|
+
const delta = move.visualDelta ?? move.positionDelta;
|
|
2317
|
+
if (!delta) return void 0;
|
|
2318
|
+
const rounded = { x: Math.round(delta.x), y: Math.round(delta.y) };
|
|
2319
|
+
return rounded.x === 0 && rounded.y === 0 ? void 0 : rounded;
|
|
2320
|
+
}
|
|
2321
|
+
function hasVisualIntent(move) {
|
|
2322
|
+
return Boolean(toRoundedVisualDelta(move));
|
|
2323
|
+
}
|
|
2324
|
+
function hasStructuralChange(move) {
|
|
2325
|
+
const fromParent = buildAnchorRef(move.fromParentName, move.fromParentSelector, move.fromParentSource);
|
|
2326
|
+
const toParent = buildAnchorRef(move.toParentName, move.toParentSelector, move.toParentSource);
|
|
2327
|
+
const fromPlacement = buildPlacementFromMove(
|
|
2328
|
+
move.fromSiblingBefore,
|
|
2329
|
+
move.fromSiblingBeforeSelector,
|
|
2330
|
+
move.fromSiblingBeforeSource,
|
|
2331
|
+
move.fromSiblingAfter,
|
|
2332
|
+
move.fromSiblingAfterSelector,
|
|
2333
|
+
move.fromSiblingAfterSource
|
|
2334
|
+
);
|
|
2335
|
+
const toPlacement = buildPlacementFromMove(
|
|
2336
|
+
move.toSiblingBefore,
|
|
2337
|
+
move.toSiblingBeforeSelector,
|
|
2338
|
+
move.toSiblingBeforeSource,
|
|
2339
|
+
move.toSiblingAfter,
|
|
2340
|
+
move.toSiblingAfterSelector,
|
|
2341
|
+
move.toSiblingAfterSource
|
|
2342
|
+
);
|
|
2343
|
+
if (!anchorsEqual(fromParent, toParent)) return true;
|
|
2344
|
+
if (!anchorsEqual(fromPlacement.before, toPlacement.before)) return true;
|
|
2345
|
+
if (!anchorsEqual(fromPlacement.after, toPlacement.after)) return true;
|
|
2346
|
+
if (typeof move.fromIndex === "number" && typeof move.toIndex === "number" && move.fromIndex !== move.toIndex) return true;
|
|
2347
|
+
return false;
|
|
2187
2348
|
}
|
|
2188
|
-
function
|
|
2189
|
-
|
|
2190
|
-
|
|
2349
|
+
function isStructuredLayoutContainer(layout) {
|
|
2350
|
+
return layout === "flex" || layout === "grid";
|
|
2351
|
+
}
|
|
2352
|
+
function isExistingFlexWorkflow(move) {
|
|
2353
|
+
const structuralChange = hasStructuralChange(move);
|
|
2354
|
+
if (!structuralChange) return false;
|
|
2355
|
+
const fromParent = buildAnchorRef(move.fromParentName, move.fromParentSelector, move.fromParentSource);
|
|
2356
|
+
const toParent = buildAnchorRef(move.toParentName, move.toParentSelector, move.toParentSource);
|
|
2357
|
+
const sameParent = anchorsEqual(fromParent, toParent);
|
|
2358
|
+
const fromLayout = move.fromParentLayout;
|
|
2359
|
+
const toLayout = move.toParentLayout;
|
|
2360
|
+
if (sameParent) {
|
|
2361
|
+
return Boolean(move.mode === "reorder" && (isStructuredLayoutContainer(toLayout) || isStructuredLayoutContainer(fromLayout)));
|
|
2362
|
+
}
|
|
2363
|
+
return Boolean(isStructuredLayoutContainer(fromLayout) && isStructuredLayoutContainer(toLayout));
|
|
2364
|
+
}
|
|
2365
|
+
function classifyMove(move) {
|
|
2366
|
+
const structuralChange = hasStructuralChange(move);
|
|
2367
|
+
const visualIntent = hasVisualIntent(move);
|
|
2368
|
+
if (!structuralChange && !visualIntent) return "noop";
|
|
2369
|
+
if (isExistingFlexWorkflow(move)) return "existing_layout_move";
|
|
2370
|
+
if (move.mode === "free" || move.mode === "position") return "layout_refactor";
|
|
2371
|
+
if (!structuralChange && visualIntent) return "layout_refactor";
|
|
2372
|
+
return "layout_refactor";
|
|
2373
|
+
}
|
|
2374
|
+
function buildNumericClusters(values, tolerance) {
|
|
2375
|
+
if (values.length === 0) return [];
|
|
2376
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
2377
|
+
const clusters = [{ center: sorted[0], values: [sorted[0]] }];
|
|
2378
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
2379
|
+
const value = sorted[i];
|
|
2380
|
+
const current = clusters[clusters.length - 1];
|
|
2381
|
+
if (Math.abs(value - current.center) <= tolerance) {
|
|
2382
|
+
current.values.push(value);
|
|
2383
|
+
current.center = current.values.reduce((sum, n) => sum + n, 0) / current.values.length;
|
|
2384
|
+
} else {
|
|
2385
|
+
clusters.push({ center: value, values: [value] });
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
return clusters;
|
|
2191
2389
|
}
|
|
2192
|
-
function
|
|
2193
|
-
|
|
2390
|
+
function inferFlexDirection(sameRowCount, sameColumnCount, visualDelta) {
|
|
2391
|
+
if (sameRowCount > sameColumnCount) {
|
|
2392
|
+
return { direction: "row", reason: "Subject aligns with neighboring anchors on the same row." };
|
|
2393
|
+
}
|
|
2394
|
+
if (sameColumnCount > sameRowCount) {
|
|
2395
|
+
return { direction: "column", reason: "Subject aligns with neighboring anchors on the same column." };
|
|
2396
|
+
}
|
|
2397
|
+
if (sameRowCount > 0) {
|
|
2398
|
+
return { direction: "row", reason: "Detected row alignment in final geometry." };
|
|
2399
|
+
}
|
|
2400
|
+
if (sameColumnCount > 0) {
|
|
2401
|
+
return { direction: "column", reason: "Detected column alignment in final geometry." };
|
|
2402
|
+
}
|
|
2403
|
+
const horizontalDominant = Math.abs(visualDelta?.x ?? 0) >= Math.abs(visualDelta?.y ?? 0);
|
|
2404
|
+
return {
|
|
2405
|
+
direction: horizontalDominant ? "row" : "column",
|
|
2406
|
+
reason: "Fell back to movement axis because anchor alignment was ambiguous."
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
function inferLayoutPrescription(edit, operation, reasons) {
|
|
2410
|
+
const parent = edit.element.parentElement;
|
|
2411
|
+
if (!parent || !edit.element.isConnected) {
|
|
2412
|
+
return {
|
|
2413
|
+
recommendedSystem: "flex",
|
|
2414
|
+
intentPatterns: ["no_geometry_context"],
|
|
2415
|
+
refactorSteps: [
|
|
2416
|
+
`Reparent ${formatAnchorRef(operation.subject)} under ${formatAnchorRef(operation.to.parent)} at ${operation.to.placement.description}.`
|
|
2417
|
+
],
|
|
2418
|
+
styleSteps: [
|
|
2419
|
+
`Convert ${formatAnchorRef(operation.to.parent)} to flex and set a clear primary axis for this relationship.`,
|
|
2420
|
+
"Use `gap` for spacing and keep positioning static."
|
|
2421
|
+
],
|
|
2422
|
+
itemSteps: [
|
|
2423
|
+
"Remove any inline `left/top/transform` move artifacts from moved elements."
|
|
2424
|
+
]
|
|
2425
|
+
};
|
|
2426
|
+
}
|
|
2427
|
+
const children = Array.from(parent.children).filter(
|
|
2428
|
+
(node) => node instanceof HTMLElement && isInFlowChild(node) && !node.hasAttribute("data-direct-edit")
|
|
2429
|
+
);
|
|
2430
|
+
const childSnapshots = children.map((child) => {
|
|
2431
|
+
const rect = child.getBoundingClientRect();
|
|
2432
|
+
const locator = getElementLocator(child);
|
|
2433
|
+
const anchor = buildAnchorRef(getElementDisplayName(child), locator.domSelector, locator.domSource);
|
|
2434
|
+
return {
|
|
2435
|
+
child,
|
|
2436
|
+
rect,
|
|
2437
|
+
centerX: rect.left + rect.width / 2,
|
|
2438
|
+
centerY: rect.top + rect.height / 2,
|
|
2439
|
+
anchor,
|
|
2440
|
+
anchorLabel: formatAnchorRef(anchor)
|
|
2441
|
+
};
|
|
2442
|
+
});
|
|
2443
|
+
const subjectSnapshot = childSnapshots.find((snapshot2) => snapshot2.child === edit.element);
|
|
2444
|
+
const subjectRect = edit.element.getBoundingClientRect();
|
|
2445
|
+
const subjectCenterX = subjectRect.left + subjectRect.width / 2;
|
|
2446
|
+
const subjectCenterY = subjectRect.top + subjectRect.height / 2;
|
|
2447
|
+
const rowTolerance = Math.max(8, subjectRect.height * 0.35);
|
|
2448
|
+
const colTolerance = Math.max(8, subjectRect.width * 0.35);
|
|
2449
|
+
const sameRowWith = [];
|
|
2450
|
+
const sameColumnWith = [];
|
|
2451
|
+
const sameRowNodes = [];
|
|
2452
|
+
let aboveAnchor = null;
|
|
2453
|
+
let belowAnchor = null;
|
|
2454
|
+
let bestAboveDistance = Number.POSITIVE_INFINITY;
|
|
2455
|
+
let bestBelowDistance = Number.POSITIVE_INFINITY;
|
|
2456
|
+
for (const node of childSnapshots) {
|
|
2457
|
+
if (node.child === edit.element) continue;
|
|
2458
|
+
if (Math.abs(node.centerY - subjectCenterY) <= rowTolerance) {
|
|
2459
|
+
sameRowWith.push(node.anchorLabel);
|
|
2460
|
+
sameRowNodes.push(node);
|
|
2461
|
+
}
|
|
2462
|
+
if (Math.abs(node.centerX - subjectCenterX) <= colTolerance) {
|
|
2463
|
+
sameColumnWith.push(node.anchorLabel);
|
|
2464
|
+
}
|
|
2465
|
+
const yDelta = node.centerY - subjectCenterY;
|
|
2466
|
+
if (yDelta < 0 && Math.abs(yDelta) < bestAboveDistance) {
|
|
2467
|
+
bestAboveDistance = Math.abs(yDelta);
|
|
2468
|
+
aboveAnchor = node.anchorLabel;
|
|
2469
|
+
}
|
|
2470
|
+
if (yDelta > 0 && yDelta < bestBelowDistance) {
|
|
2471
|
+
bestBelowDistance = yDelta;
|
|
2472
|
+
belowAnchor = node.anchorLabel;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
const rowCenters = childSnapshots.map(({ centerY }) => centerY);
|
|
2476
|
+
const colCenters = childSnapshots.map(({ centerX }) => centerX);
|
|
2477
|
+
const rowClusters = buildNumericClusters(rowCenters, rowTolerance);
|
|
2478
|
+
const colClusters = buildNumericClusters(colCenters, colTolerance);
|
|
2479
|
+
const denseRowClusters = rowClusters.filter((cluster) => cluster.values.length >= 2).length;
|
|
2480
|
+
const denseColClusters = colClusters.filter((cluster) => cluster.values.length >= 2).length;
|
|
2481
|
+
const isTwoDimensional = childSnapshots.length >= 4 && denseRowClusters >= 2 && denseColClusters >= 2;
|
|
2482
|
+
const recommendedSystem = isTwoDimensional ? "grid" : "flex";
|
|
2483
|
+
const intentPatterns = [];
|
|
2484
|
+
if (sameRowWith.length > 0) intentPatterns.push(`same_row_with:${sameRowWith.slice(0, 3).join(", ")}`);
|
|
2485
|
+
if (sameColumnWith.length > 0) intentPatterns.push(`same_column_with:${sameColumnWith.slice(0, 3).join(", ")}`);
|
|
2486
|
+
if (aboveAnchor) intentPatterns.push(`below:${aboveAnchor}`);
|
|
2487
|
+
if (belowAnchor) intentPatterns.push(`above:${belowAnchor}`);
|
|
2488
|
+
if (sameRowWith.length === 0 && sameColumnWith.length === 0) intentPatterns.push("separate_cluster");
|
|
2489
|
+
const visualDelta = operation.visualDelta;
|
|
2490
|
+
const flexDirectionInfo = inferFlexDirection(sameRowWith.length, sameColumnWith.length, visualDelta);
|
|
2491
|
+
const flexDirection = flexDirectionInfo.direction;
|
|
2492
|
+
if (recommendedSystem === "grid") {
|
|
2493
|
+
reasons.push("Detected multiple dense row and column clusters; a 2D layout system is likely intentional.");
|
|
2494
|
+
return {
|
|
2495
|
+
recommendedSystem: "grid",
|
|
2496
|
+
intentPatterns,
|
|
2497
|
+
refactorSteps: [
|
|
2498
|
+
`Create/ensure a shared container around ${formatAnchorRef(operation.subject)} and related anchors under ${formatAnchorRef(operation.to.parent)}.`,
|
|
2499
|
+
`Reorder/reparent elements to satisfy placement ${operation.to.placement.description}.`
|
|
2500
|
+
],
|
|
2501
|
+
styleSteps: [
|
|
2502
|
+
`Set ${formatAnchorRef(operation.to.parent)} to grid with explicit template rows/columns for the final layout.`,
|
|
2503
|
+
"Use `gap` for consistent spacing and keep placement structural."
|
|
2504
|
+
],
|
|
2505
|
+
itemSteps: [
|
|
2506
|
+
`Set item alignment on ${formatAnchorRef(operation.subject)} with grid self-alignment (\`justify-self\`/\`align-self\`).`
|
|
2507
|
+
]
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
reasons.push(`${flexDirectionInfo.reason} Use a 1D flex layout instead of literal drag replay.`);
|
|
2511
|
+
let hasStackedCluster = false;
|
|
2512
|
+
const stackedAnchorLabels = /* @__PURE__ */ new Set();
|
|
2513
|
+
if (flexDirection === "row" && subjectSnapshot) {
|
|
2514
|
+
for (const rowPeer of sameRowNodes) {
|
|
2515
|
+
for (const node of childSnapshots) {
|
|
2516
|
+
if (node.child === edit.element || node.child === rowPeer.child) continue;
|
|
2517
|
+
const sameColumnAsPeer = Math.abs(node.centerX - rowPeer.centerX) <= colTolerance;
|
|
2518
|
+
const verticallySeparated = Math.abs(node.centerY - rowPeer.centerY) > rowTolerance;
|
|
2519
|
+
if (sameColumnAsPeer && verticallySeparated) {
|
|
2520
|
+
hasStackedCluster = true;
|
|
2521
|
+
stackedAnchorLabels.add(rowPeer.anchorLabel);
|
|
2522
|
+
stackedAnchorLabels.add(node.anchorLabel);
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
const hasBelowCluster = childSnapshots.some((node) => node.child !== edit.element && node.centerY - subjectCenterY > rowTolerance * 1.5 && Math.abs(node.centerY - subjectCenterY) > Math.abs(node.centerX - subjectCenterX));
|
|
2528
|
+
const refactorSteps = [
|
|
2529
|
+
`Ensure ${formatAnchorRef(operation.subject)} and referenced neighbors share a common container under ${formatAnchorRef(operation.to.parent)}.`,
|
|
2530
|
+
`Reparent/reorder nodes so ${formatAnchorRef(operation.subject)} lands ${operation.to.placement.description}.`
|
|
2531
|
+
];
|
|
2532
|
+
if (flexDirection === "row" && hasStackedCluster) {
|
|
2533
|
+
const clusterSample = Array.from(stackedAnchorLabels).slice(0, 3).join(", ");
|
|
2534
|
+
refactorSteps.push(`Create a left-side content wrapper for vertically stacked items (${clusterSample}), and keep ${formatAnchorRef(operation.subject)} as the opposite-side sibling.`);
|
|
2535
|
+
}
|
|
2536
|
+
if (hasBelowCluster) {
|
|
2537
|
+
refactorSteps.push("Keep lower content sections in a separate block below the horizontal header row; do not force them into the same row.");
|
|
2538
|
+
}
|
|
2539
|
+
const styleSteps = [
|
|
2540
|
+
`Set ${formatAnchorRef(operation.to.parent)} to flex with direction ${flexDirection}.`,
|
|
2541
|
+
flexDirection === "row" ? "Use `justify-content: space-between` and `align-items: flex-start` when the moved element should sit on the opposite edge." : "Use `justify-content` / `align-items` to establish top-bottom alignment.",
|
|
2542
|
+
"Use `gap` for spacing between siblings."
|
|
2543
|
+
];
|
|
2544
|
+
if (flexDirection === "row" && hasStackedCluster) {
|
|
2545
|
+
styleSteps.push("Set the content wrapper to `display: flex` with `flex-direction: column` and an appropriate vertical gap.");
|
|
2546
|
+
}
|
|
2547
|
+
return {
|
|
2548
|
+
recommendedSystem: "flex",
|
|
2549
|
+
intentPatterns,
|
|
2550
|
+
refactorSteps,
|
|
2551
|
+
styleSteps,
|
|
2552
|
+
itemSteps: [
|
|
2553
|
+
`Apply item-level alignment (\`align-self\` / flex-basis) only when needed for ${formatAnchorRef(operation.subject)}.`,
|
|
2554
|
+
"Do not use absolute positioning, top/left offsets, transforms, or margin hacks to simulate movement."
|
|
2555
|
+
]
|
|
2556
|
+
};
|
|
2557
|
+
}
|
|
2558
|
+
function buildMoveEntries(edits) {
|
|
2559
|
+
const entries = [];
|
|
2560
|
+
let noopMoveCount = 0;
|
|
2561
|
+
for (const edit of edits) {
|
|
2562
|
+
const move = edit.move;
|
|
2563
|
+
if (!move) continue;
|
|
2564
|
+
const subject = buildAnchorRef(
|
|
2565
|
+
getElementDisplayName(edit.element) || edit.locator.tagName,
|
|
2566
|
+
edit.locator.domSelector,
|
|
2567
|
+
edit.locator.domSource
|
|
2568
|
+
);
|
|
2569
|
+
const fromParent = buildAnchorRef(move.fromParentName, move.fromParentSelector, move.fromParentSource);
|
|
2570
|
+
const toParent = buildAnchorRef(move.toParentName, move.toParentSelector, move.toParentSource);
|
|
2571
|
+
const fromPlacement = buildPlacementFromMove(
|
|
2572
|
+
move.fromSiblingBefore,
|
|
2573
|
+
move.fromSiblingBeforeSelector,
|
|
2574
|
+
move.fromSiblingBeforeSource,
|
|
2575
|
+
move.fromSiblingAfter,
|
|
2576
|
+
move.fromSiblingAfterSelector,
|
|
2577
|
+
move.fromSiblingAfterSource
|
|
2578
|
+
);
|
|
2579
|
+
const toPlacement = buildPlacementFromMove(
|
|
2580
|
+
move.toSiblingBefore,
|
|
2581
|
+
move.toSiblingBeforeSelector,
|
|
2582
|
+
move.toSiblingBeforeSource,
|
|
2583
|
+
move.toSiblingAfter,
|
|
2584
|
+
move.toSiblingAfterSelector,
|
|
2585
|
+
move.toSiblingAfterSource
|
|
2586
|
+
);
|
|
2587
|
+
const reasons = [];
|
|
2588
|
+
const classification = classifyMove(move);
|
|
2589
|
+
if (classification === "noop") {
|
|
2590
|
+
noopMoveCount++;
|
|
2591
|
+
continue;
|
|
2592
|
+
}
|
|
2593
|
+
const interactionMode = move.mode ?? "free";
|
|
2594
|
+
const visualDelta = toRoundedVisualDelta(move);
|
|
2595
|
+
if (visualDelta) {
|
|
2596
|
+
reasons.push(`Non-zero visual delta detected (${visualDelta.x}px, ${visualDelta.y}px).`);
|
|
2597
|
+
}
|
|
2598
|
+
const structuralChange = hasStructuralChange(move);
|
|
2599
|
+
if (structuralChange) reasons.push("Anchor placement changed between source and target.");
|
|
2600
|
+
else reasons.push("No anchor placement change; treating movement as layout intent translation.");
|
|
2601
|
+
const operationBase = {
|
|
2602
|
+
classification,
|
|
2603
|
+
interactionMode,
|
|
2604
|
+
subject,
|
|
2605
|
+
from: { parent: fromParent, placement: fromPlacement },
|
|
2606
|
+
to: { parent: toParent, placement: toPlacement },
|
|
2607
|
+
...visualDelta ? { visualDelta } : {},
|
|
2608
|
+
confidence: classification === "existing_layout_move" ? "high" : structuralChange ? "medium" : "high",
|
|
2609
|
+
reasons
|
|
2610
|
+
};
|
|
2611
|
+
if (classification === "layout_refactor") {
|
|
2612
|
+
operationBase.layoutPrescription = inferLayoutPrescription(edit, operationBase, reasons);
|
|
2613
|
+
}
|
|
2614
|
+
const sortSource = subject.source?.file ? `${subject.source.file}:${subject.source.line ?? 0}:${subject.source.column ?? 0}` : "";
|
|
2615
|
+
const sortKey = [
|
|
2616
|
+
sortSource,
|
|
2617
|
+
anchorKey(subject),
|
|
2618
|
+
anchorKey(toParent),
|
|
2619
|
+
toPlacement.description
|
|
2620
|
+
].join("|");
|
|
2621
|
+
entries.push({ edit, operation: operationBase, sortKey });
|
|
2622
|
+
}
|
|
2623
|
+
entries.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
2624
|
+
return { entries, noopMoveCount };
|
|
2625
|
+
}
|
|
2626
|
+
function buildMovePlanContext(edits, _domContext) {
|
|
2627
|
+
const { entries, noopMoveCount } = buildMoveEntries(edits);
|
|
2628
|
+
if (entries.length === 0) {
|
|
2629
|
+
return {
|
|
2630
|
+
movePlan: null,
|
|
2631
|
+
intentsByEdit: /* @__PURE__ */ new Map(),
|
|
2632
|
+
noopMoveCount
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
const operations = [];
|
|
2636
|
+
const intentsByEdit = /* @__PURE__ */ new Map();
|
|
2637
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2638
|
+
const operationId = `op-${i + 1}`;
|
|
2639
|
+
const operation = { operationId, ...entries[i].operation };
|
|
2640
|
+
operations.push(operation);
|
|
2641
|
+
intentsByEdit.set(entries[i].edit, operation);
|
|
2642
|
+
}
|
|
2643
|
+
const affectedContainerMap = /* @__PURE__ */ new Map();
|
|
2644
|
+
for (const operation of operations) {
|
|
2645
|
+
affectedContainerMap.set(anchorKey(operation.from.parent), operation.from.parent);
|
|
2646
|
+
affectedContainerMap.set(anchorKey(operation.to.parent), operation.to.parent);
|
|
2647
|
+
}
|
|
2648
|
+
const orderingConstraints = operations.filter((op) => op.classification === "existing_layout_move").map((op) => `${op.operationId}: place ${formatAnchorRef(op.subject)} ${op.to.placement.description} in ${formatAnchorRef(op.to.parent)}.`);
|
|
2649
|
+
const notes = [];
|
|
2650
|
+
if (noopMoveCount > 0) notes.push(`Excluded ${noopMoveCount} no-op move(s).`);
|
|
2651
|
+
if (operations.some((op) => op.classification === "layout_refactor")) {
|
|
2652
|
+
notes.push("Layout refactor operations include best-practice flex/grid prescriptions.");
|
|
2653
|
+
}
|
|
2654
|
+
return {
|
|
2655
|
+
movePlan: {
|
|
2656
|
+
operations,
|
|
2657
|
+
affectedContainers: Array.from(affectedContainerMap.values()),
|
|
2658
|
+
orderingConstraints,
|
|
2659
|
+
notes
|
|
2660
|
+
},
|
|
2661
|
+
intentsByEdit,
|
|
2662
|
+
noopMoveCount
|
|
2663
|
+
};
|
|
2664
|
+
}
|
|
2665
|
+
function getMoveIntentForEdit(edit, context) {
|
|
2666
|
+
if (!edit.move) return null;
|
|
2667
|
+
if (context?.intentsByEdit.has(edit)) return context.intentsByEdit.get(edit) ?? null;
|
|
2668
|
+
const singleContext = buildMovePlanContext([edit]);
|
|
2669
|
+
return singleContext.intentsByEdit.get(edit) ?? null;
|
|
2670
|
+
}
|
|
2671
|
+
function buildMoveInstructionFromIntent(intent) {
|
|
2672
|
+
if (intent.classification === "existing_layout_move") {
|
|
2673
|
+
return `Apply as a structural move in code: place ${formatAnchorRef(intent.subject)} ${intent.to.placement.description} in ${formatAnchorRef(intent.to.parent)}.`;
|
|
2674
|
+
}
|
|
2675
|
+
const system = intent.layoutPrescription?.recommendedSystem ?? "flex";
|
|
2676
|
+
return `Treat this as a ${system} layout refactor. Implement the listed structure/style steps in source code instead of drag replay.`;
|
|
2677
|
+
}
|
|
2678
|
+
function formatMoveType(classification) {
|
|
2679
|
+
return classification === "existing_layout_move" ? "structural_move" : "layout_refactor";
|
|
2680
|
+
}
|
|
2681
|
+
function buildMoveExportLines(intent) {
|
|
2682
|
+
const moveType = formatMoveType(intent.classification);
|
|
2683
|
+
const implementationSteps = [];
|
|
2684
|
+
if (intent.classification === "existing_layout_move") {
|
|
2685
|
+
implementationSteps.push(`Reorder/reparent ${formatAnchorRef(intent.subject)} to ${intent.to.placement.description} in ${formatAnchorRef(intent.to.parent)}.`);
|
|
2686
|
+
} else {
|
|
2687
|
+
const prescription = intent.layoutPrescription;
|
|
2688
|
+
if (prescription) {
|
|
2689
|
+
implementationSteps.push(...prescription.refactorSteps);
|
|
2690
|
+
implementationSteps.push(...prescription.styleSteps);
|
|
2691
|
+
implementationSteps.push(...prescription.itemSteps);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
const lines = [
|
|
2194
2695
|
"moved:",
|
|
2195
|
-
`
|
|
2196
|
-
`
|
|
2197
|
-
`
|
|
2198
|
-
`
|
|
2199
|
-
`
|
|
2200
|
-
`
|
|
2201
|
-
`
|
|
2202
|
-
`to_parent_selector: ${formatMoveSelector(move.toParentSelector, "(unknown)")}`,
|
|
2203
|
-
`to_before_selector: ${formatMoveSelector(move.toSiblingBeforeSelector, "(none)")}`,
|
|
2204
|
-
`to_after_selector: ${formatMoveSelector(move.toSiblingAfterSelector, "(none)")}`,
|
|
2205
|
-
`to_parent_source: ${formatMoveSource(move.toParentSource, "(unknown)")}`,
|
|
2206
|
-
`to_before_source: ${formatMoveSource(move.toSiblingBeforeSource, "(none)")}`,
|
|
2207
|
-
`to_after_source: ${formatMoveSource(move.toSiblingAfterSource, "(none)")}`
|
|
2696
|
+
`id: ${intent.operationId}`,
|
|
2697
|
+
`type: ${moveType}`,
|
|
2698
|
+
`subject: ${formatAnchorRef(intent.subject, "(unknown)")}`,
|
|
2699
|
+
`parent: ${formatAnchorRef(intent.to.parent, "(unknown)")}`,
|
|
2700
|
+
`current_anchor: ${intent.from.placement.description}`,
|
|
2701
|
+
`target_anchor: ${intent.to.placement.description}`,
|
|
2702
|
+
...intent.visualDelta ? [`visual_hint: ${intent.visualDelta.x}px horizontal, ${intent.visualDelta.y}px vertical`] : []
|
|
2208
2703
|
];
|
|
2704
|
+
if (intent.layoutPrescription) {
|
|
2705
|
+
lines.push(`recommended_layout: ${intent.layoutPrescription.recommendedSystem}`);
|
|
2706
|
+
}
|
|
2707
|
+
lines.push("implementation_steps:");
|
|
2708
|
+
for (const step of implementationSteps) {
|
|
2709
|
+
lines.push(` - ${step}`);
|
|
2710
|
+
}
|
|
2711
|
+
lines.push("guardrails:");
|
|
2712
|
+
lines.push(" - Do not simulate movement with absolute positioning, left/top offsets, transform, or margin hacks.");
|
|
2713
|
+
lines.push(`instruction: ${buildMoveInstructionFromIntent(intent)}`);
|
|
2714
|
+
return lines;
|
|
2715
|
+
}
|
|
2716
|
+
function getExportContentProfile(edits, comments, movePlanOrContext) {
|
|
2717
|
+
const moveOpCount = movePlanOrContext ? "operations" in movePlanOrContext ? movePlanOrContext.operations.length : movePlanOrContext.movePlan?.operations.length ?? 0 : buildMovePlanContext(edits).movePlan?.operations.length ?? 0;
|
|
2718
|
+
return {
|
|
2719
|
+
hasCssEdits: edits.some((e) => Object.keys(e.pendingStyles).length > 0),
|
|
2720
|
+
hasTextEdits: edits.some((e) => e.textEdit != null),
|
|
2721
|
+
hasMoves: moveOpCount > 0,
|
|
2722
|
+
hasComments: comments.length > 0
|
|
2723
|
+
};
|
|
2724
|
+
}
|
|
2725
|
+
function buildExportInstruction(profile) {
|
|
2726
|
+
const { hasCssEdits, hasTextEdits, hasMoves, hasComments } = profile;
|
|
2727
|
+
if (!hasCssEdits && !hasTextEdits && !hasMoves && !hasComments) return "";
|
|
2728
|
+
if (!hasCssEdits && !hasTextEdits && !hasMoves) {
|
|
2729
|
+
return hasComments ? "Address this feedback on the UI. Use the provided source location and selector to find each element in the codebase." : "";
|
|
2730
|
+
}
|
|
2731
|
+
const parts = [];
|
|
2732
|
+
if (hasCssEdits) parts.push("Apply the CSS changes to the targeted elements using the project's existing styling approach (Tailwind, CSS modules, etc.).");
|
|
2733
|
+
if (hasTextEdits) parts.push("Update the text content as specified.");
|
|
2734
|
+
if (hasMoves) parts.push("Implement the move plan below directly in source code. For `structural_move`, reorder/reparent elements using the target anchors. For `layout_refactor`, apply the listed flex/grid refactor steps. Do NOT simulate movement with absolute positioning, left/top offsets, transform, or margin hacks.");
|
|
2735
|
+
if (hasComments) parts.push("Address the comments on the relevant elements.");
|
|
2736
|
+
return `${parts.join(" ")} Use the provided source locations, selectors, and context HTML to locate each element in the codebase.`;
|
|
2209
2737
|
}
|
|
2210
|
-
function buildSessionExport(edits, comments = []) {
|
|
2738
|
+
function buildSessionExport(edits, comments = [], options) {
|
|
2211
2739
|
const blocks = [];
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2740
|
+
const planContext = options?.movePlanContext ?? buildMovePlanContext(edits);
|
|
2741
|
+
const movePlan = planContext.movePlan;
|
|
2742
|
+
const includeMovePlanHeader = options?.includeMovePlanHeader !== false;
|
|
2743
|
+
if (includeMovePlanHeader && movePlan && movePlan.operations.length > 0) {
|
|
2744
|
+
const planLines = [
|
|
2745
|
+
"=== LAYOUT MOVE PLAN ===",
|
|
2746
|
+
`operations: ${movePlan.operations.length}`
|
|
2747
|
+
];
|
|
2748
|
+
if (movePlan.affectedContainers.length > 0) {
|
|
2749
|
+
planLines.push("containers:");
|
|
2750
|
+
for (const container of movePlan.affectedContainers) {
|
|
2751
|
+
planLines.push(` - ${formatAnchorRef(container, "(unknown)")}`);
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
if (movePlan.orderingConstraints.length > 0) {
|
|
2755
|
+
planLines.push("structural_constraints:");
|
|
2756
|
+
for (const constraint of movePlan.orderingConstraints) {
|
|
2757
|
+
planLines.push(` - ${constraint}`);
|
|
2758
|
+
}
|
|
2217
2759
|
}
|
|
2218
|
-
|
|
2760
|
+
if (movePlan.notes.length > 0) {
|
|
2761
|
+
planLines.push("plan_notes:");
|
|
2762
|
+
for (const note of movePlan.notes) {
|
|
2763
|
+
planLines.push(` - ${note}`);
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
blocks.push(planLines.join("\n"));
|
|
2767
|
+
}
|
|
2768
|
+
for (const edit of edits) {
|
|
2769
|
+
const moveIntent = getMoveIntentForEdit(edit, planContext);
|
|
2770
|
+
const hasMove = Boolean(moveIntent);
|
|
2771
|
+
const hasStyleOrText = Object.keys(edit.pendingStyles).length > 0 || edit.textEdit != null;
|
|
2772
|
+
if (!hasMove && !hasStyleOrText) continue;
|
|
2773
|
+
const block = hasMove ? buildEditExportWithOptions(edit.locator, edit.pendingStyles, edit.textEdit, { skipContext: true }) : buildEditExport(edit.locator, edit.pendingStyles, edit.textEdit);
|
|
2774
|
+
let moveBlock = "";
|
|
2775
|
+
if (moveIntent) {
|
|
2776
|
+
moveBlock = `
|
|
2777
|
+
${buildMoveExportLines(moveIntent).join("\n")}`;
|
|
2778
|
+
}
|
|
2779
|
+
blocks.push(block + moveBlock);
|
|
2219
2780
|
}
|
|
2220
2781
|
for (const comment of comments) {
|
|
2221
2782
|
blocks.push(buildCommentExport(comment.locator, comment.text, comment.replies));
|
|
@@ -2663,6 +3224,224 @@ function useStyleUpdaters({ stateRef, pushUndo, setState }) {
|
|
|
2663
3224
|
|
|
2664
3225
|
// src/use-session-manager.ts
|
|
2665
3226
|
import * as React3 from "react";
|
|
3227
|
+
|
|
3228
|
+
// src/clipboard.ts
|
|
3229
|
+
function buildAgentClipboardText(markdown) {
|
|
3230
|
+
return `implement the visual edits
|
|
3231
|
+
|
|
3232
|
+
${markdown}`;
|
|
3233
|
+
}
|
|
3234
|
+
function tryRestoreFocus(element) {
|
|
3235
|
+
if (!(element instanceof HTMLElement)) return;
|
|
3236
|
+
try {
|
|
3237
|
+
element.focus({ preventScroll: true });
|
|
3238
|
+
} catch {
|
|
3239
|
+
try {
|
|
3240
|
+
element.focus();
|
|
3241
|
+
} catch {
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
async function copyText(text) {
|
|
3246
|
+
const nav = globalThis.navigator;
|
|
3247
|
+
const clipboard = nav?.clipboard;
|
|
3248
|
+
const clipboardWrite = clipboard?.writeText;
|
|
3249
|
+
if (typeof clipboardWrite === "function") {
|
|
3250
|
+
try {
|
|
3251
|
+
await clipboardWrite.call(clipboard, text);
|
|
3252
|
+
return true;
|
|
3253
|
+
} catch {
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
if (typeof document === "undefined") return false;
|
|
3257
|
+
if (typeof document.execCommand !== "function") return false;
|
|
3258
|
+
const body = document.body;
|
|
3259
|
+
if (!body) return false;
|
|
3260
|
+
const activeElement = document.activeElement;
|
|
3261
|
+
const selection = typeof window !== "undefined" ? window.getSelection() : null;
|
|
3262
|
+
const previousRange = selection && selection.rangeCount > 0 ? selection.getRangeAt(0).cloneRange() : null;
|
|
3263
|
+
const textarea = document.createElement("textarea");
|
|
3264
|
+
textarea.value = text;
|
|
3265
|
+
textarea.setAttribute("readonly", "");
|
|
3266
|
+
textarea.style.position = "fixed";
|
|
3267
|
+
textarea.style.top = "0";
|
|
3268
|
+
textarea.style.left = "0";
|
|
3269
|
+
textarea.style.width = "1px";
|
|
3270
|
+
textarea.style.height = "1px";
|
|
3271
|
+
textarea.style.opacity = "0";
|
|
3272
|
+
textarea.style.pointerEvents = "none";
|
|
3273
|
+
body.appendChild(textarea);
|
|
3274
|
+
let copied = false;
|
|
3275
|
+
try {
|
|
3276
|
+
try {
|
|
3277
|
+
textarea.focus({ preventScroll: true });
|
|
3278
|
+
} catch {
|
|
3279
|
+
textarea.focus();
|
|
3280
|
+
}
|
|
3281
|
+
textarea.select();
|
|
3282
|
+
textarea.setSelectionRange(0, textarea.value.length);
|
|
3283
|
+
copied = document.execCommand("copy");
|
|
3284
|
+
} catch {
|
|
3285
|
+
copied = false;
|
|
3286
|
+
} finally {
|
|
3287
|
+
textarea.remove();
|
|
3288
|
+
if (selection) {
|
|
3289
|
+
selection.removeAllRanges();
|
|
3290
|
+
if (previousRange) {
|
|
3291
|
+
selection.addRange(previousRange);
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
tryRestoreFocus(activeElement);
|
|
3295
|
+
}
|
|
3296
|
+
return copied;
|
|
3297
|
+
}
|
|
3298
|
+
|
|
3299
|
+
// src/use-session-manager.ts
|
|
3300
|
+
function getLayoutFromDisplay(display) {
|
|
3301
|
+
if (display === "flex" || display === "inline-flex") return "flex";
|
|
3302
|
+
if (display === "grid" || display === "inline-grid") return "grid";
|
|
3303
|
+
if (display === "block" || display === "inline-block" || display === "flow-root" || display === "list-item") {
|
|
3304
|
+
return "block";
|
|
3305
|
+
}
|
|
3306
|
+
return "other";
|
|
3307
|
+
}
|
|
3308
|
+
function getParentLayoutMeta(parent) {
|
|
3309
|
+
if (!parent) return {};
|
|
3310
|
+
const computed = window.getComputedStyle(parent);
|
|
3311
|
+
const display = computed.display;
|
|
3312
|
+
const layout = getLayoutFromDisplay(display);
|
|
3313
|
+
const childCount = countInFlowChildren(parent);
|
|
3314
|
+
if (layout === "flex") {
|
|
3315
|
+
return {
|
|
3316
|
+
display,
|
|
3317
|
+
layout,
|
|
3318
|
+
childCount,
|
|
3319
|
+
flexDirection: computed.flexDirection,
|
|
3320
|
+
gap: computed.gap !== "normal" && computed.gap !== "0px" ? computed.gap : void 0
|
|
3321
|
+
};
|
|
3322
|
+
}
|
|
3323
|
+
if (layout === "grid") {
|
|
3324
|
+
return {
|
|
3325
|
+
display,
|
|
3326
|
+
layout,
|
|
3327
|
+
childCount,
|
|
3328
|
+
gap: computed.gap !== "normal" && computed.gap !== "0px" ? computed.gap : void 0
|
|
3329
|
+
};
|
|
3330
|
+
}
|
|
3331
|
+
return { display, layout, childCount };
|
|
3332
|
+
}
|
|
3333
|
+
function countInFlowChildren(parent) {
|
|
3334
|
+
let count = 0;
|
|
3335
|
+
for (const c of parent.children) {
|
|
3336
|
+
if (c instanceof HTMLElement && isInFlowChild(c)) count++;
|
|
3337
|
+
}
|
|
3338
|
+
return count;
|
|
3339
|
+
}
|
|
3340
|
+
function findChildIndex(parent, child) {
|
|
3341
|
+
if (!parent || !child) return void 0;
|
|
3342
|
+
const index = Array.from(parent.children).indexOf(child);
|
|
3343
|
+
return index >= 0 ? index : void 0;
|
|
3344
|
+
}
|
|
3345
|
+
function getOriginalMoveIndex(parent, previousSibling, nextSibling) {
|
|
3346
|
+
const previousIndex = findChildIndex(parent, previousSibling);
|
|
3347
|
+
if (previousIndex !== void 0) return previousIndex + 1;
|
|
3348
|
+
const nextIndex = findChildIndex(parent, nextSibling);
|
|
3349
|
+
if (nextIndex !== void 0) return nextIndex;
|
|
3350
|
+
return 0;
|
|
3351
|
+
}
|
|
3352
|
+
function applyPositionMoveCSS(element, delta) {
|
|
3353
|
+
const computed = window.getComputedStyle(element);
|
|
3354
|
+
const previousStyles = [];
|
|
3355
|
+
if (computed.position === "static") {
|
|
3356
|
+
previousStyles.push({ cssProperty: "position", previousValue: element.style.getPropertyValue("position") || null });
|
|
3357
|
+
element.style.setProperty("position", "relative");
|
|
3358
|
+
}
|
|
3359
|
+
const appliedLeft = `${(parseFloat(computed.left) || 0) + delta.x}px`;
|
|
3360
|
+
const appliedTop = `${(parseFloat(computed.top) || 0) + delta.y}px`;
|
|
3361
|
+
previousStyles.push({ cssProperty: "left", previousValue: element.style.getPropertyValue("left") || null });
|
|
3362
|
+
previousStyles.push({ cssProperty: "top", previousValue: element.style.getPropertyValue("top") || null });
|
|
3363
|
+
element.style.setProperty("left", appliedLeft);
|
|
3364
|
+
element.style.setProperty("top", appliedTop);
|
|
3365
|
+
return { previousStyles, appliedLeft, appliedTop };
|
|
3366
|
+
}
|
|
3367
|
+
function getAnchor(node) {
|
|
3368
|
+
if (!node) return { selector: null, source: null };
|
|
3369
|
+
const locator = getElementLocator(node);
|
|
3370
|
+
const selector = locator.domSelector.trim();
|
|
3371
|
+
return {
|
|
3372
|
+
selector: selector.length > 0 ? selector : null,
|
|
3373
|
+
source: locator.domSource ?? null
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
function buildPositionMoveFields(element, moveInfo, appliedLeft, appliedTop, existingMove) {
|
|
3377
|
+
const parent = element.parentElement;
|
|
3378
|
+
const intended = computeIntendedIndex(parent, element);
|
|
3379
|
+
const parentMeta = getParentLayoutMeta(parent);
|
|
3380
|
+
const parentName = getElementDisplayName(parent);
|
|
3381
|
+
const parentAnchor = getAnchor(parent);
|
|
3382
|
+
const fromIndex = getOriginalMoveIndex(
|
|
3383
|
+
moveInfo.originalParent,
|
|
3384
|
+
moveInfo.originalPreviousSibling,
|
|
3385
|
+
moveInfo.originalNextSibling
|
|
3386
|
+
);
|
|
3387
|
+
const fromParentMeta = existingMove ? getParentLayoutMeta(moveInfo.originalParent) : parentMeta;
|
|
3388
|
+
const fromFields = existingMove ? {
|
|
3389
|
+
fromParentName: existingMove.fromParentName,
|
|
3390
|
+
fromSiblingBefore: existingMove.fromSiblingBefore,
|
|
3391
|
+
fromSiblingAfter: existingMove.fromSiblingAfter,
|
|
3392
|
+
fromParentSelector: existingMove.fromParentSelector ?? null,
|
|
3393
|
+
fromSiblingBeforeSelector: existingMove.fromSiblingBeforeSelector ?? null,
|
|
3394
|
+
fromSiblingAfterSelector: existingMove.fromSiblingAfterSelector ?? null,
|
|
3395
|
+
fromParentSource: existingMove.fromParentSource ?? null,
|
|
3396
|
+
fromSiblingBeforeSource: existingMove.fromSiblingBeforeSource ?? null,
|
|
3397
|
+
fromSiblingAfterSource: existingMove.fromSiblingAfterSource ?? null,
|
|
3398
|
+
fromParentDisplay: existingMove.fromParentDisplay ?? parentMeta.display,
|
|
3399
|
+
fromParentLayout: existingMove.fromParentLayout ?? parentMeta.layout,
|
|
3400
|
+
fromIndex: existingMove.fromIndex ?? fromIndex,
|
|
3401
|
+
fromFlexDirection: existingMove.fromFlexDirection ?? fromParentMeta.flexDirection,
|
|
3402
|
+
fromGap: existingMove.fromGap ?? fromParentMeta.gap,
|
|
3403
|
+
fromChildCount: existingMove.fromChildCount ?? fromParentMeta.childCount
|
|
3404
|
+
} : {
|
|
3405
|
+
fromParentName: parentName,
|
|
3406
|
+
fromSiblingBefore: moveInfo.originalPreviousSibling ? getElementDisplayName(moveInfo.originalPreviousSibling) : null,
|
|
3407
|
+
fromSiblingAfter: moveInfo.originalNextSibling ? getElementDisplayName(moveInfo.originalNextSibling) : null,
|
|
3408
|
+
fromParentSelector: parentAnchor.selector,
|
|
3409
|
+
fromSiblingBeforeSelector: getAnchor(moveInfo.originalPreviousSibling).selector,
|
|
3410
|
+
fromSiblingAfterSelector: getAnchor(moveInfo.originalNextSibling).selector,
|
|
3411
|
+
fromParentSource: parentAnchor.source,
|
|
3412
|
+
fromSiblingBeforeSource: getAnchor(moveInfo.originalPreviousSibling).source,
|
|
3413
|
+
fromSiblingAfterSource: getAnchor(moveInfo.originalNextSibling).source,
|
|
3414
|
+
fromParentDisplay: parentMeta.display,
|
|
3415
|
+
fromParentLayout: parentMeta.layout,
|
|
3416
|
+
fromIndex,
|
|
3417
|
+
fromFlexDirection: parentMeta.flexDirection,
|
|
3418
|
+
fromGap: parentMeta.gap,
|
|
3419
|
+
fromChildCount: parentMeta.childCount
|
|
3420
|
+
};
|
|
3421
|
+
return {
|
|
3422
|
+
...fromFields,
|
|
3423
|
+
mode: "position",
|
|
3424
|
+
positionDelta: moveInfo.positionDelta,
|
|
3425
|
+
appliedLeft,
|
|
3426
|
+
appliedTop,
|
|
3427
|
+
visualDelta: moveInfo.positionDelta ? { x: Math.round(moveInfo.positionDelta.x), y: Math.round(moveInfo.positionDelta.y) } : void 0,
|
|
3428
|
+
toParentName: parentName,
|
|
3429
|
+
toSiblingBefore: intended.siblingBefore ? getElementDisplayName(intended.siblingBefore) : null,
|
|
3430
|
+
toSiblingAfter: intended.siblingAfter ? getElementDisplayName(intended.siblingAfter) : null,
|
|
3431
|
+
toParentSelector: parentAnchor.selector,
|
|
3432
|
+
toSiblingBeforeSelector: getAnchor(intended.siblingBefore).selector,
|
|
3433
|
+
toSiblingAfterSelector: getAnchor(intended.siblingAfter).selector,
|
|
3434
|
+
toParentSource: parentAnchor.source,
|
|
3435
|
+
toSiblingBeforeSource: getAnchor(intended.siblingBefore).source,
|
|
3436
|
+
toSiblingAfterSource: getAnchor(intended.siblingAfter).source,
|
|
3437
|
+
toParentDisplay: parentMeta.display,
|
|
3438
|
+
toParentLayout: parentMeta.layout,
|
|
3439
|
+
toIndex: intended.index,
|
|
3440
|
+
toFlexDirection: parentMeta.flexDirection,
|
|
3441
|
+
toGap: parentMeta.gap,
|
|
3442
|
+
toChildCount: parentMeta.childCount
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
2666
3445
|
function useSessionManager({
|
|
2667
3446
|
stateRef,
|
|
2668
3447
|
sessionEditsRef,
|
|
@@ -2909,6 +3688,15 @@ function useSessionManager({
|
|
|
2909
3688
|
}
|
|
2910
3689
|
} catch {
|
|
2911
3690
|
}
|
|
3691
|
+
if (entry.previousPositionStyles) {
|
|
3692
|
+
for (const { cssProperty, previousValue } of entry.previousPositionStyles) {
|
|
3693
|
+
if (previousValue) {
|
|
3694
|
+
entry.element.style.setProperty(cssProperty, previousValue);
|
|
3695
|
+
} else {
|
|
3696
|
+
entry.element.style.removeProperty(cssProperty);
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
2912
3700
|
const sessionEntry = sessionEditsRef.current.get(entry.element);
|
|
2913
3701
|
if (sessionEntry) {
|
|
2914
3702
|
const restoredMove = entry.previousSessionMove;
|
|
@@ -2980,77 +3768,137 @@ function useSessionManager({
|
|
|
2980
3768
|
};
|
|
2981
3769
|
};
|
|
2982
3770
|
if (moveInfo) {
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3771
|
+
if (moveInfo.mode === "position" && moveInfo.positionDelta) {
|
|
3772
|
+
const existing = sessionEditsRef.current.get(element);
|
|
3773
|
+
const styleState2 = getStyleStateForElement(existing);
|
|
3774
|
+
const { previousStyles, appliedLeft, appliedTop } = applyPositionMoveCSS(element, moveInfo.positionDelta);
|
|
3775
|
+
pushUndo({
|
|
3776
|
+
type: "move",
|
|
3777
|
+
element,
|
|
3778
|
+
originalParent: moveInfo.originalParent,
|
|
3779
|
+
originalNextSibling: moveInfo.originalNextSibling,
|
|
3780
|
+
previousSessionMove: existing?.move ?? null,
|
|
3781
|
+
previousPositionStyles: previousStyles
|
|
3782
|
+
});
|
|
3783
|
+
const locator = existing?.locator ?? getElementLocator(element);
|
|
3784
|
+
const pendingStyles = { ...styleState2.pendingStyles };
|
|
3785
|
+
delete pendingStyles["position"];
|
|
3786
|
+
delete pendingStyles["left"];
|
|
3787
|
+
delete pendingStyles["top"];
|
|
3788
|
+
const move = buildPositionMoveFields(element, moveInfo, appliedLeft, appliedTop, existing?.move ?? null);
|
|
3789
|
+
sessionEditsRef.current.set(element, {
|
|
3790
|
+
element,
|
|
3791
|
+
locator,
|
|
3792
|
+
originalStyles: styleState2.originalStyles,
|
|
3793
|
+
pendingStyles,
|
|
3794
|
+
textEdit: existing?.textEdit ?? null,
|
|
3795
|
+
move
|
|
3796
|
+
});
|
|
3797
|
+
syncSessionItemCount();
|
|
3798
|
+
} else {
|
|
3799
|
+
const existing = sessionEditsRef.current.get(element);
|
|
3800
|
+
const styleState2 = getStyleStateForElement(existing);
|
|
3801
|
+
const moveMode = moveInfo.mode ?? "free";
|
|
3802
|
+
let clearedPositionStyles;
|
|
3803
|
+
if (moveInfo.resetPositionOffsets) {
|
|
3804
|
+
clearedPositionStyles = [];
|
|
3805
|
+
for (const prop of ["position", "left", "top"]) {
|
|
3806
|
+
const prev = element.style.getPropertyValue(prop) || null;
|
|
3807
|
+
clearedPositionStyles.push({ cssProperty: prop, previousValue: prev });
|
|
3808
|
+
element.style.removeProperty(prop);
|
|
3809
|
+
}
|
|
2986
3810
|
}
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3811
|
+
pushUndo({
|
|
3812
|
+
type: "move",
|
|
3813
|
+
element,
|
|
3814
|
+
originalParent: moveInfo.originalParent,
|
|
3815
|
+
originalNextSibling: moveInfo.originalNextSibling,
|
|
3816
|
+
previousSessionMove: existing?.move ?? null,
|
|
3817
|
+
previousPositionStyles: clearedPositionStyles
|
|
3818
|
+
});
|
|
3819
|
+
const locator = existing?.locator ?? getElementLocator(element);
|
|
3820
|
+
const newParent = element.parentElement;
|
|
3821
|
+
const nextPrevSibling = element.previousElementSibling;
|
|
3822
|
+
const nextSibling = element.nextElementSibling;
|
|
3823
|
+
const fromParentAnchor = getAnchor(moveInfo.originalParent);
|
|
3824
|
+
const fromBeforeAnchor = getAnchor(moveInfo.originalPreviousSibling);
|
|
3825
|
+
const fromAfterAnchor = getAnchor(moveInfo.originalNextSibling);
|
|
3826
|
+
const toParentAnchor = getAnchor(newParent);
|
|
3827
|
+
const toBeforeAnchor = getAnchor(nextPrevSibling);
|
|
3828
|
+
const toAfterAnchor = getAnchor(nextSibling);
|
|
3829
|
+
const fromParentMeta = getParentLayoutMeta(moveInfo.originalParent);
|
|
3830
|
+
const toParentMeta = getParentLayoutMeta(newParent);
|
|
3831
|
+
const fromIndex = getOriginalMoveIndex(
|
|
3832
|
+
moveInfo.originalParent,
|
|
3833
|
+
moveInfo.originalPreviousSibling,
|
|
3834
|
+
moveInfo.originalNextSibling
|
|
3835
|
+
);
|
|
3836
|
+
const toIndex = findChildIndex(newParent, element);
|
|
3837
|
+
const fromFields = existing?.move ? {
|
|
3838
|
+
fromParentName: existing.move.fromParentName,
|
|
3839
|
+
fromSiblingBefore: existing.move.fromSiblingBefore,
|
|
3840
|
+
fromSiblingAfter: existing.move.fromSiblingAfter,
|
|
3841
|
+
fromParentSelector: existing.move.fromParentSelector ?? null,
|
|
3842
|
+
fromSiblingBeforeSelector: existing.move.fromSiblingBeforeSelector ?? null,
|
|
3843
|
+
fromSiblingAfterSelector: existing.move.fromSiblingAfterSelector ?? null,
|
|
3844
|
+
fromParentSource: existing.move.fromParentSource ?? null,
|
|
3845
|
+
fromSiblingBeforeSource: existing.move.fromSiblingBeforeSource ?? null,
|
|
3846
|
+
fromSiblingAfterSource: existing.move.fromSiblingAfterSource ?? null,
|
|
3847
|
+
fromParentDisplay: existing.move.fromParentDisplay ?? fromParentMeta.display,
|
|
3848
|
+
fromParentLayout: existing.move.fromParentLayout ?? fromParentMeta.layout,
|
|
3849
|
+
fromIndex: existing.move.fromIndex ?? fromIndex,
|
|
3850
|
+
fromFlexDirection: existing.move.fromFlexDirection ?? fromParentMeta.flexDirection,
|
|
3851
|
+
fromGap: existing.move.fromGap ?? fromParentMeta.gap,
|
|
3852
|
+
fromChildCount: existing.move.fromChildCount ?? fromParentMeta.childCount
|
|
3853
|
+
} : {
|
|
3854
|
+
fromParentName: getElementDisplayName(moveInfo.originalParent),
|
|
3855
|
+
fromSiblingBefore: moveInfo.originalPreviousSibling ? getElementDisplayName(moveInfo.originalPreviousSibling) : null,
|
|
3856
|
+
fromSiblingAfter: moveInfo.originalNextSibling ? getElementDisplayName(moveInfo.originalNextSibling) : null,
|
|
3857
|
+
fromParentSelector: fromParentAnchor.selector,
|
|
3858
|
+
fromSiblingBeforeSelector: fromBeforeAnchor.selector,
|
|
3859
|
+
fromSiblingAfterSelector: fromAfterAnchor.selector,
|
|
3860
|
+
fromParentSource: fromParentAnchor.source,
|
|
3861
|
+
fromSiblingBeforeSource: fromBeforeAnchor.source,
|
|
3862
|
+
fromSiblingAfterSource: fromAfterAnchor.source,
|
|
3863
|
+
fromParentDisplay: fromParentMeta.display,
|
|
3864
|
+
fromParentLayout: fromParentMeta.layout,
|
|
3865
|
+
fromIndex,
|
|
3866
|
+
fromFlexDirection: fromParentMeta.flexDirection,
|
|
3867
|
+
fromGap: fromParentMeta.gap,
|
|
3868
|
+
fromChildCount: fromParentMeta.childCount
|
|
2992
3869
|
};
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
fromSiblingBefore: moveInfo.originalPreviousSibling ? getElementDisplayName(moveInfo.originalPreviousSibling) : null,
|
|
3026
|
-
fromSiblingAfter: moveInfo.originalNextSibling ? getElementDisplayName(moveInfo.originalNextSibling) : null,
|
|
3027
|
-
fromParentSelector: fromParentAnchor.selector,
|
|
3028
|
-
fromSiblingBeforeSelector: fromBeforeAnchor.selector,
|
|
3029
|
-
fromSiblingAfterSelector: fromAfterAnchor.selector,
|
|
3030
|
-
fromParentSource: fromParentAnchor.source,
|
|
3031
|
-
fromSiblingBeforeSource: fromBeforeAnchor.source,
|
|
3032
|
-
fromSiblingAfterSource: fromAfterAnchor.source
|
|
3033
|
-
};
|
|
3034
|
-
sessionEditsRef.current.set(element, {
|
|
3035
|
-
element,
|
|
3036
|
-
locator,
|
|
3037
|
-
originalStyles: styleState2.originalStyles,
|
|
3038
|
-
pendingStyles: styleState2.pendingStyles,
|
|
3039
|
-
textEdit: existing?.textEdit ?? null,
|
|
3040
|
-
move: newParent ? {
|
|
3041
|
-
...fromFields,
|
|
3042
|
-
toParentName: getElementDisplayName(newParent),
|
|
3043
|
-
toSiblingBefore: nextPrevSibling ? getElementDisplayName(nextPrevSibling) : null,
|
|
3044
|
-
toSiblingAfter: nextSibling ? getElementDisplayName(nextSibling) : null,
|
|
3045
|
-
toParentSelector: toParentAnchor.selector,
|
|
3046
|
-
toSiblingBeforeSelector: toBeforeAnchor.selector,
|
|
3047
|
-
toSiblingAfterSelector: toAfterAnchor.selector,
|
|
3048
|
-
toParentSource: toParentAnchor.source,
|
|
3049
|
-
toSiblingBeforeSource: toBeforeAnchor.source,
|
|
3050
|
-
toSiblingAfterSource: toAfterAnchor.source
|
|
3051
|
-
} : null
|
|
3052
|
-
});
|
|
3053
|
-
syncSessionItemCount();
|
|
3870
|
+
sessionEditsRef.current.set(element, {
|
|
3871
|
+
element,
|
|
3872
|
+
locator,
|
|
3873
|
+
originalStyles: styleState2.originalStyles,
|
|
3874
|
+
pendingStyles: styleState2.pendingStyles,
|
|
3875
|
+
textEdit: existing?.textEdit ?? null,
|
|
3876
|
+
move: newParent ? {
|
|
3877
|
+
...fromFields,
|
|
3878
|
+
toParentName: getElementDisplayName(newParent),
|
|
3879
|
+
toSiblingBefore: nextPrevSibling ? getElementDisplayName(nextPrevSibling) : null,
|
|
3880
|
+
toSiblingAfter: nextSibling ? getElementDisplayName(nextSibling) : null,
|
|
3881
|
+
toParentSelector: toParentAnchor.selector,
|
|
3882
|
+
toSiblingBeforeSelector: toBeforeAnchor.selector,
|
|
3883
|
+
toSiblingAfterSelector: toAfterAnchor.selector,
|
|
3884
|
+
toParentSource: toParentAnchor.source,
|
|
3885
|
+
toSiblingBeforeSource: toBeforeAnchor.source,
|
|
3886
|
+
toSiblingAfterSource: toAfterAnchor.source,
|
|
3887
|
+
mode: moveMode,
|
|
3888
|
+
fromParentDisplay: fromFields.fromParentDisplay,
|
|
3889
|
+
fromParentLayout: fromFields.fromParentLayout,
|
|
3890
|
+
fromIndex: fromFields.fromIndex,
|
|
3891
|
+
toParentDisplay: toParentMeta.display,
|
|
3892
|
+
toParentLayout: toParentMeta.layout,
|
|
3893
|
+
toIndex,
|
|
3894
|
+
visualDelta: moveInfo.visualDelta,
|
|
3895
|
+
toFlexDirection: toParentMeta.flexDirection,
|
|
3896
|
+
toGap: toParentMeta.gap,
|
|
3897
|
+
toChildCount: toParentMeta.childCount
|
|
3898
|
+
} : null
|
|
3899
|
+
});
|
|
3900
|
+
syncSessionItemCount();
|
|
3901
|
+
}
|
|
3054
3902
|
}
|
|
3055
3903
|
const computed = getAllComputedStyles(element);
|
|
3056
3904
|
const elementInfo = getElementInfo(element);
|
|
@@ -3104,15 +3952,12 @@ function useSessionManager({
|
|
|
3104
3952
|
if (items.length === 0) return false;
|
|
3105
3953
|
const edits = items.filter((item) => item.type === "edit").map((item) => item.edit);
|
|
3106
3954
|
const comments = items.filter((item) => item.type === "comment").map((item) => item.comment);
|
|
3107
|
-
const
|
|
3108
|
-
|
|
3109
|
-
|
|
3955
|
+
const movePlanContext = buildMovePlanContext(edits);
|
|
3956
|
+
const text = buildSessionExport(edits, comments, { movePlanContext });
|
|
3957
|
+
const instruction = buildExportInstruction(getExportContentProfile(edits, comments, movePlanContext));
|
|
3958
|
+
return copyText(`${instruction}
|
|
3110
3959
|
|
|
3111
3960
|
${text}`);
|
|
3112
|
-
return true;
|
|
3113
|
-
} catch {
|
|
3114
|
-
return false;
|
|
3115
|
-
}
|
|
3116
3961
|
}, [getSessionItems]);
|
|
3117
3962
|
const revertElementStyles = React3.useCallback((element, sessionEdit) => {
|
|
3118
3963
|
for (const prop of Object.keys(sessionEdit.pendingStyles)) {
|
|
@@ -3187,22 +4032,27 @@ ${text}`);
|
|
|
3187
4032
|
const sessionEdit = sessionEditsRef.current.get(current.selectedElement);
|
|
3188
4033
|
const hasPendingStyles = Object.keys(current.pendingStyles).length > 0;
|
|
3189
4034
|
const hasTextEdit = Boolean(sessionEdit?.textEdit);
|
|
3190
|
-
const hasMove = Boolean(sessionEdit?.move);
|
|
3191
4035
|
const locator = getElementLocator(current.selectedElement);
|
|
3192
|
-
const
|
|
4036
|
+
const editForExport = sessionEdit ? {
|
|
3193
4037
|
...sessionEdit,
|
|
3194
4038
|
locator,
|
|
3195
4039
|
pendingStyles: { ...current.pendingStyles },
|
|
3196
4040
|
textEdit: sessionEdit.textEdit
|
|
3197
|
-
}
|
|
3198
|
-
|
|
3199
|
-
|
|
4041
|
+
} : null;
|
|
4042
|
+
const movePlanContext = editForExport?.move ? buildMovePlanContext([editForExport]) : null;
|
|
4043
|
+
const moveIntent = editForExport?.move ? getMoveIntentForEdit(editForExport, movePlanContext) : null;
|
|
4044
|
+
const hasMove = Boolean(moveIntent);
|
|
4045
|
+
const hasExportableEdit = hasPendingStyles || hasTextEdit || hasMove;
|
|
4046
|
+
const exportMarkdown = hasExportableEdit ? hasMove && editForExport ? buildSessionExport([editForExport], [], { movePlanContext }) : buildEditExport(locator, current.pendingStyles, sessionEdit?.textEdit) : buildElementContext(locator);
|
|
4047
|
+
const instruction = hasExportableEdit ? buildExportInstruction({
|
|
4048
|
+
hasCssEdits: hasPendingStyles,
|
|
4049
|
+
hasTextEdits: hasTextEdit,
|
|
4050
|
+
hasMoves: hasMove,
|
|
4051
|
+
hasComments: false
|
|
4052
|
+
}) : "Here is the element context for reference";
|
|
4053
|
+
return copyText(`${instruction}
|
|
3200
4054
|
|
|
3201
4055
|
${exportMarkdown}`);
|
|
3202
|
-
return true;
|
|
3203
|
-
} catch {
|
|
3204
|
-
return false;
|
|
3205
|
-
}
|
|
3206
4056
|
}, []);
|
|
3207
4057
|
return {
|
|
3208
4058
|
syncSessionItemCount,
|
|
@@ -3226,6 +4076,10 @@ ${exportMarkdown}`);
|
|
|
3226
4076
|
|
|
3227
4077
|
// src/use-text-and-comments.ts
|
|
3228
4078
|
import * as React4 from "react";
|
|
4079
|
+
function clampUnit(value) {
|
|
4080
|
+
if (!Number.isFinite(value)) return 0;
|
|
4081
|
+
return Math.max(0, Math.min(1, value));
|
|
4082
|
+
}
|
|
3229
4083
|
function useTextAndComments({
|
|
3230
4084
|
stateRef,
|
|
3231
4085
|
sessionEditsRef,
|
|
@@ -3289,8 +4143,8 @@ function useTextAndComments({
|
|
|
3289
4143
|
const locator = getElementLocator(element);
|
|
3290
4144
|
const rect = element.getBoundingClientRect();
|
|
3291
4145
|
const relativePosition = {
|
|
3292
|
-
x: rect.width > 0 ? (clickPosition.x - rect.left) / rect.width : 0,
|
|
3293
|
-
y: rect.height > 0 ? (clickPosition.y - rect.top) / rect.height : 0
|
|
4146
|
+
x: rect.width > 0 ? clampUnit((clickPosition.x - rect.left) / rect.width) : 0,
|
|
4147
|
+
y: rect.height > 0 ? clampUnit((clickPosition.y - rect.top) / rect.height) : 0
|
|
3294
4148
|
};
|
|
3295
4149
|
const id = `comment-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
3296
4150
|
const comment = {
|
|
@@ -3337,14 +4191,15 @@ function useTextAndComments({
|
|
|
3337
4191
|
const comment = stateRef.current.comments.find((c) => c.id === id);
|
|
3338
4192
|
if (!comment) return false;
|
|
3339
4193
|
const exportMarkdown = buildCommentExport(comment.locator, comment.text, comment.replies);
|
|
3340
|
-
|
|
3341
|
-
|
|
4194
|
+
const instruction = buildExportInstruction({
|
|
4195
|
+
hasCssEdits: false,
|
|
4196
|
+
hasTextEdits: false,
|
|
4197
|
+
hasMoves: false,
|
|
4198
|
+
hasComments: true
|
|
4199
|
+
});
|
|
4200
|
+
return copyText(`${instruction}
|
|
3342
4201
|
|
|
3343
4202
|
${exportMarkdown}`);
|
|
3344
|
-
return true;
|
|
3345
|
-
} catch {
|
|
3346
|
-
return false;
|
|
3347
|
-
}
|
|
3348
4203
|
}, []);
|
|
3349
4204
|
const setActiveCommentId = React4.useCallback((id) => {
|
|
3350
4205
|
setState((prev) => {
|
|
@@ -3742,24 +4597,36 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems }) {
|
|
|
3742
4597
|
const sessionEdit = sessionEditsRef.current.get(selectedElement);
|
|
3743
4598
|
const hasPendingStyles = Object.keys(pendingStyles).length > 0;
|
|
3744
4599
|
const hasTextEdit = Boolean(sessionEdit?.textEdit);
|
|
3745
|
-
const hasMove = Boolean(
|
|
4600
|
+
const hasMove = Boolean(
|
|
4601
|
+
sessionEdit?.move && getMoveIntentForEdit(sessionEdit, buildMovePlanContext([sessionEdit]))
|
|
4602
|
+
);
|
|
3746
4603
|
return hasPendingStyles || hasTextEdit || hasMove;
|
|
3747
4604
|
}, []);
|
|
3748
|
-
const sendSessionEditToAgent = React5.useCallback(async (sessionEdit) => {
|
|
4605
|
+
const sendSessionEditToAgent = React5.useCallback(async (sessionEdit, allEdits, movePlanContext, options) => {
|
|
3749
4606
|
const locator = sessionEdit.locator;
|
|
3750
4607
|
const pendingStyles = { ...sessionEdit.pendingStyles };
|
|
3751
|
-
const
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
4608
|
+
const editsForPlan = allEdits ?? [sessionEdit];
|
|
4609
|
+
const resolvedPlanContext = movePlanContext ?? buildMovePlanContext(editsForPlan);
|
|
4610
|
+
const includeBatchMoveEnvelope = Boolean(options?.includeBatchMoveEnvelope && sessionEdit.move);
|
|
4611
|
+
const isBatchSend = Boolean(allEdits && allEdits.length > 1);
|
|
4612
|
+
const exportMarkdown = sessionEdit.move ? buildSessionExport(
|
|
4613
|
+
includeBatchMoveEnvelope ? editsForPlan : [sessionEdit],
|
|
4614
|
+
[],
|
|
4615
|
+
{
|
|
4616
|
+
movePlanContext: resolvedPlanContext,
|
|
4617
|
+
includeMovePlanHeader: includeBatchMoveEnvelope || !isBatchSend
|
|
4618
|
+
}
|
|
4619
|
+
) : buildEditExport(locator, pendingStyles, sessionEdit.textEdit);
|
|
3757
4620
|
const collapsedStyles = collapseExportShorthands(pendingStyles);
|
|
3758
4621
|
const changes = Object.entries(collapsedStyles).map(([cssProperty, cssValue]) => ({
|
|
3759
4622
|
cssProperty,
|
|
3760
4623
|
cssValue,
|
|
3761
4624
|
tailwindClass: stylesToTailwind({ [cssProperty]: cssValue })
|
|
3762
4625
|
}));
|
|
4626
|
+
const moveIntent = sessionEdit.move ? getMoveIntentForEdit(sessionEdit, resolvedPlanContext) : null;
|
|
4627
|
+
const movePlan = includeBatchMoveEnvelope ? resolvedPlanContext.movePlan : null;
|
|
4628
|
+
const hasMeaningfulPayload = changes.length > 0 || sessionEdit.textEdit != null || moveIntent != null;
|
|
4629
|
+
if (!hasMeaningfulPayload) return true;
|
|
3763
4630
|
try {
|
|
3764
4631
|
const result = await sendEditToAgent({
|
|
3765
4632
|
element: {
|
|
@@ -3774,7 +4641,8 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems }) {
|
|
|
3774
4641
|
reactStack: locator.reactStack,
|
|
3775
4642
|
changes,
|
|
3776
4643
|
textChange: sessionEdit.textEdit ?? null,
|
|
3777
|
-
|
|
4644
|
+
moveIntent,
|
|
4645
|
+
...movePlan ? { movePlan } : {},
|
|
3778
4646
|
exportMarkdown
|
|
3779
4647
|
});
|
|
3780
4648
|
return result.ok;
|
|
@@ -3833,9 +4701,25 @@ function useAgentComms({ stateRef, sessionEditsRef, getSessionItems }) {
|
|
|
3833
4701
|
const sendAllSessionItemsToAgent = React5.useCallback(async () => {
|
|
3834
4702
|
const items = getSessionItems();
|
|
3835
4703
|
if (items.length === 0) return false;
|
|
4704
|
+
const allEdits = items.filter((i) => i.type === "edit").map((i) => i.edit);
|
|
4705
|
+
const movePlanContext = buildMovePlanContext(allEdits);
|
|
4706
|
+
let moveEnvelopeSent = false;
|
|
3836
4707
|
let allSucceeded = true;
|
|
3837
4708
|
for (const item of items) {
|
|
3838
|
-
|
|
4709
|
+
let succeeded;
|
|
4710
|
+
if (item.type === "edit") {
|
|
4711
|
+
const hasMoveIntent = Boolean(item.edit.move && getMoveIntentForEdit(item.edit, movePlanContext));
|
|
4712
|
+
const includeBatchMoveEnvelope = hasMoveIntent && !moveEnvelopeSent;
|
|
4713
|
+
succeeded = await sendSessionEditToAgent(
|
|
4714
|
+
item.edit,
|
|
4715
|
+
allEdits,
|
|
4716
|
+
movePlanContext,
|
|
4717
|
+
{ includeBatchMoveEnvelope }
|
|
4718
|
+
);
|
|
4719
|
+
if (includeBatchMoveEnvelope) moveEnvelopeSent = true;
|
|
4720
|
+
} else {
|
|
4721
|
+
succeeded = await sendSessionCommentToAgent(item.comment);
|
|
4722
|
+
}
|
|
3839
4723
|
if (!succeeded) {
|
|
3840
4724
|
allSucceeded = false;
|
|
3841
4725
|
}
|
|
@@ -4027,6 +4911,8 @@ var LINE_HEIGHT_PX = 40;
|
|
|
4027
4911
|
var PAGE_HEIGHT_PX = 800;
|
|
4028
4912
|
var CANVAS_MEASURE_NODE_BUDGET = 12e3;
|
|
4029
4913
|
var CANVAS_PRIORITY_ROOT_SELECTORS = ["#root", "#app", "#__next", "main"];
|
|
4914
|
+
var FIXED_FRAME_CANVAS_MIN_VIEWPORT_COVERAGE = 0.6;
|
|
4915
|
+
var FIXED_FRAME_CANVAS_EDGE_TOLERANCE_PX = 1;
|
|
4030
4916
|
function normalizeWheelDelta(e) {
|
|
4031
4917
|
let { deltaX, deltaY } = e;
|
|
4032
4918
|
if (e.deltaMode === 1) {
|
|
@@ -4038,6 +4924,46 @@ function normalizeWheelDelta(e) {
|
|
|
4038
4924
|
}
|
|
4039
4925
|
return { deltaX, deltaY };
|
|
4040
4926
|
}
|
|
4927
|
+
function getVisibleAreaInViewport(rect) {
|
|
4928
|
+
const left = Math.max(0, rect.left);
|
|
4929
|
+
const top = Math.max(0, rect.top);
|
|
4930
|
+
const right = Math.min(window.innerWidth, rect.right);
|
|
4931
|
+
const bottom = Math.min(window.innerHeight, rect.bottom);
|
|
4932
|
+
const width = Math.max(0, right - left);
|
|
4933
|
+
const height = Math.max(0, bottom - top);
|
|
4934
|
+
return width * height;
|
|
4935
|
+
}
|
|
4936
|
+
function getFixedFrameCanvasDimensions() {
|
|
4937
|
+
const viewportWidth = window.innerWidth;
|
|
4938
|
+
const viewportHeight = window.innerHeight;
|
|
4939
|
+
const viewportArea = viewportWidth * viewportHeight;
|
|
4940
|
+
if (viewportArea <= 0) return null;
|
|
4941
|
+
let bestArea = 0;
|
|
4942
|
+
let bestRect = null;
|
|
4943
|
+
const canvases = document.querySelectorAll("canvas");
|
|
4944
|
+
for (const canvas of canvases) {
|
|
4945
|
+
if (canvas.closest("[data-direct-edit]") || canvas.closest("[data-direct-edit-host]")) continue;
|
|
4946
|
+
const style = getComputedStyle(canvas);
|
|
4947
|
+
if (style.display === "none" || style.visibility === "hidden") continue;
|
|
4948
|
+
const opacity = parseFloat(style.opacity);
|
|
4949
|
+
if ((Number.isFinite(opacity) ? opacity : 1) <= 0) continue;
|
|
4950
|
+
const rect = canvas.getBoundingClientRect();
|
|
4951
|
+
if (style.position !== "fixed") continue;
|
|
4952
|
+
if (Math.abs(rect.left) > FIXED_FRAME_CANVAS_EDGE_TOLERANCE_PX || Math.abs(rect.top) > FIXED_FRAME_CANVAS_EDGE_TOLERANCE_PX) {
|
|
4953
|
+
continue;
|
|
4954
|
+
}
|
|
4955
|
+
const visibleArea = getVisibleAreaInViewport(rect);
|
|
4956
|
+
if (visibleArea <= bestArea) continue;
|
|
4957
|
+
bestArea = visibleArea;
|
|
4958
|
+
bestRect = rect;
|
|
4959
|
+
}
|
|
4960
|
+
if (!bestRect) return null;
|
|
4961
|
+
if (bestArea / viewportArea < FIXED_FRAME_CANVAS_MIN_VIEWPORT_COVERAGE) return null;
|
|
4962
|
+
return {
|
|
4963
|
+
width: Math.max(viewportWidth, bestRect.width),
|
|
4964
|
+
height: Math.max(viewportHeight, bestRect.height)
|
|
4965
|
+
};
|
|
4966
|
+
}
|
|
4041
4967
|
function getResolvedOverflowY(style) {
|
|
4042
4968
|
return style.overflowY || style.overflow;
|
|
4043
4969
|
}
|
|
@@ -4100,6 +5026,7 @@ function clampPan(zoom, panX, panY, bodyW, bodyH) {
|
|
|
4100
5026
|
function useCanvas({ stateRef, setState }) {
|
|
4101
5027
|
React7.useEffect(() => registerCanvasStoreOwner(), []);
|
|
4102
5028
|
const canvasRef = React7.useRef({ active: false, zoom: 1, panX: 0, panY: 0 });
|
|
5029
|
+
const canvasStrategyRef = React7.useRef("body-transform");
|
|
4103
5030
|
const savedScrollRef = React7.useRef({ x: 0, y: 0 });
|
|
4104
5031
|
const savedBodyOverflowRef = React7.useRef("");
|
|
4105
5032
|
const savedHtmlOverflowRef = React7.useRef("");
|
|
@@ -4120,6 +5047,9 @@ function useCanvas({ stateRef, setState }) {
|
|
|
4120
5047
|
window.dispatchEvent(new Event("direct-edit-canvas-change"));
|
|
4121
5048
|
}, []);
|
|
4122
5049
|
const readBodyOffset = React7.useCallback(() => {
|
|
5050
|
+
if (canvasStrategyRef.current !== "body-transform") {
|
|
5051
|
+
return { x: 0, y: 0 };
|
|
5052
|
+
}
|
|
4123
5053
|
const bodyStyle = getComputedStyle(document.body);
|
|
4124
5054
|
return {
|
|
4125
5055
|
x: parseFloat(bodyStyle.marginLeft) || 0,
|
|
@@ -4256,20 +5186,32 @@ function useCanvas({ stateRef, setState }) {
|
|
|
4256
5186
|
savedHtmlOverflowRef.current = document.documentElement.style.overflow;
|
|
4257
5187
|
savedHtmlBgColorRef.current = document.documentElement.style.backgroundColor;
|
|
4258
5188
|
domStateSavedRef.current = true;
|
|
4259
|
-
const
|
|
4260
|
-
|
|
4261
|
-
|
|
5189
|
+
const fixedFrameDims = getFixedFrameCanvasDimensions();
|
|
5190
|
+
canvasStrategyRef.current = fixedFrameDims ? "fixed-frame" : "body-transform";
|
|
5191
|
+
if (canvasStrategyRef.current === "body-transform") {
|
|
5192
|
+
const existingTransform = document.body.style.transform;
|
|
5193
|
+
if (existingTransform && existingTransform !== "none" && existingTransform !== "") {
|
|
5194
|
+
console.warn("[made-refine] canvas mode: overriding existing body transform:", existingTransform);
|
|
5195
|
+
}
|
|
4262
5196
|
}
|
|
4263
5197
|
let entered = false;
|
|
4264
5198
|
try {
|
|
4265
5199
|
window.scrollTo(0, 0);
|
|
4266
|
-
|
|
4267
|
-
|
|
5200
|
+
if (canvasStrategyRef.current === "body-transform") {
|
|
5201
|
+
savedBodyDimensionsRef.current = expandScrollableRegionsAndMeasureBody();
|
|
5202
|
+
updateBodyOffset();
|
|
5203
|
+
} else {
|
|
5204
|
+
savedBodyDimensionsRef.current = fixedFrameDims ?? {
|
|
5205
|
+
width: window.innerWidth,
|
|
5206
|
+
height: window.innerHeight
|
|
5207
|
+
};
|
|
5208
|
+
setBodyOffset({ x: 0, y: 0 });
|
|
5209
|
+
}
|
|
4268
5210
|
document.body.style.overflow = "hidden";
|
|
4269
5211
|
document.documentElement.style.overflow = "hidden";
|
|
4270
5212
|
document.documentElement.style.backgroundColor = "#F5F5F5";
|
|
4271
|
-
const initialPanX = -scrollX;
|
|
4272
|
-
const initialPanY = -scrollY;
|
|
5213
|
+
const initialPanX = canvasStrategyRef.current === "body-transform" ? -scrollX : 0;
|
|
5214
|
+
const initialPanY = canvasStrategyRef.current === "body-transform" ? -scrollY : 0;
|
|
4273
5215
|
applyTransform(1, initialPanX, initialPanY);
|
|
4274
5216
|
canvasRef.current = { active: true, zoom: 1, panX: initialPanX, panY: initialPanY };
|
|
4275
5217
|
setCanvasSnapshot(canvasRef.current);
|
|
@@ -4289,6 +5231,7 @@ function useCanvas({ stateRef, setState }) {
|
|
|
4289
5231
|
document.documentElement.style.backgroundColor = savedHtmlBgColorRef.current;
|
|
4290
5232
|
window.scrollTo(scrollX, scrollY);
|
|
4291
5233
|
domStateSavedRef.current = false;
|
|
5234
|
+
canvasStrategyRef.current = "body-transform";
|
|
4292
5235
|
}
|
|
4293
5236
|
}
|
|
4294
5237
|
}, [applyTransform, dispatchCanvasChange, setState, updateBodyOffset]);
|
|
@@ -4308,6 +5251,7 @@ function useCanvas({ stateRef, setState }) {
|
|
|
4308
5251
|
}
|
|
4309
5252
|
document.body.style.cursor = "";
|
|
4310
5253
|
domStateSavedRef.current = false;
|
|
5254
|
+
canvasStrategyRef.current = "body-transform";
|
|
4311
5255
|
setBodyOffset({ x: 0, y: 0 });
|
|
4312
5256
|
canvasRef.current = { active: false, zoom: 1, panX: 0, panY: 0 };
|
|
4313
5257
|
setCanvasSnapshot(canvasRef.current);
|
|
@@ -4377,6 +5321,14 @@ function useCanvas({ stateRef, setState }) {
|
|
|
4377
5321
|
React7.useEffect(() => {
|
|
4378
5322
|
function handleResize() {
|
|
4379
5323
|
if (!canvasRef.current.active) return;
|
|
5324
|
+
if (canvasStrategyRef.current === "fixed-frame") {
|
|
5325
|
+
savedBodyDimensionsRef.current = getFixedFrameCanvasDimensions() ?? {
|
|
5326
|
+
width: window.innerWidth,
|
|
5327
|
+
height: window.innerHeight
|
|
5328
|
+
};
|
|
5329
|
+
dispatchCanvasChange();
|
|
5330
|
+
return;
|
|
5331
|
+
}
|
|
4380
5332
|
if (updateBodyOffset()) {
|
|
4381
5333
|
dispatchCanvasChange();
|
|
4382
5334
|
}
|
|
@@ -4643,6 +5595,17 @@ function DirectEditProvider({ children }) {
|
|
|
4643
5595
|
document.removeEventListener("mousedown", handleMouseDown, true);
|
|
4644
5596
|
};
|
|
4645
5597
|
}, [state.textEditingElement, commitTextEditing]);
|
|
5598
|
+
React8.useEffect(() => {
|
|
5599
|
+
if (!state.editModeActive || state.textEditingElement) return;
|
|
5600
|
+
function blockClick(e) {
|
|
5601
|
+
const host = document.querySelector("[data-direct-edit-host]");
|
|
5602
|
+
if (host && e.target === host) return;
|
|
5603
|
+
e.preventDefault();
|
|
5604
|
+
e.stopPropagation();
|
|
5605
|
+
}
|
|
5606
|
+
document.addEventListener("click", blockClick, true);
|
|
5607
|
+
return () => document.removeEventListener("click", blockClick, true);
|
|
5608
|
+
}, [state.editModeActive, state.textEditingElement]);
|
|
4646
5609
|
const {
|
|
4647
5610
|
canSendEditToAgent,
|
|
4648
5611
|
sendEditToAgent: sendEditToAgent2,
|
|
@@ -5070,6 +6033,37 @@ var INITIAL_DRAG_STATE = {
|
|
|
5070
6033
|
ghostPosition: { x: 0, y: 0 },
|
|
5071
6034
|
dragOffset: { x: 0, y: 0 }
|
|
5072
6035
|
};
|
|
6036
|
+
var DEFAULT_DRAG_OPTIONS = {
|
|
6037
|
+
constrainToOriginalParent: false,
|
|
6038
|
+
mode: "free"
|
|
6039
|
+
};
|
|
6040
|
+
function normalizeStartDragOptions(options) {
|
|
6041
|
+
const mode = options?.mode ?? (options?.constrainToOriginalParent ? "reorder" : "free");
|
|
6042
|
+
return {
|
|
6043
|
+
mode,
|
|
6044
|
+
constrainToOriginalParent: mode === "reorder" || Boolean(options?.constrainToOriginalParent)
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
6047
|
+
function resolveFlexDirection(container, draggedElement) {
|
|
6048
|
+
const { axis, reversed } = detectChildrenDirection(container, draggedElement);
|
|
6049
|
+
if (axis === "horizontal") return reversed ? "row-reverse" : "row";
|
|
6050
|
+
return reversed ? "column-reverse" : "column";
|
|
6051
|
+
}
|
|
6052
|
+
function tryReparent(draggedElement, target, originalParent, originalNextSibling) {
|
|
6053
|
+
const isSamePosition = target.container === originalParent && target.insertBefore === originalNextSibling;
|
|
6054
|
+
const isInvalidTarget = target.container === draggedElement || draggedElement.contains(target.container) || (target.insertBefore ? draggedElement.contains(target.insertBefore) : false);
|
|
6055
|
+
if (isSamePosition || isInvalidTarget) return false;
|
|
6056
|
+
try {
|
|
6057
|
+
if (target.insertBefore) {
|
|
6058
|
+
target.container.insertBefore(draggedElement, target.insertBefore);
|
|
6059
|
+
} else {
|
|
6060
|
+
target.container.appendChild(draggedElement);
|
|
6061
|
+
}
|
|
6062
|
+
return true;
|
|
6063
|
+
} catch {
|
|
6064
|
+
return false;
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
5073
6067
|
function useMove({ onMoveComplete }) {
|
|
5074
6068
|
const [dragState, setDragState] = React12.useState(INITIAL_DRAG_STATE);
|
|
5075
6069
|
const [dropTarget, setDropTarget] = React12.useState(null);
|
|
@@ -5077,7 +6071,11 @@ function useMove({ onMoveComplete }) {
|
|
|
5077
6071
|
const dragStateRef = React12.useRef(dragState);
|
|
5078
6072
|
const dropTargetRef = React12.useRef(dropTarget);
|
|
5079
6073
|
const onMoveCompleteRef = React12.useRef(onMoveComplete);
|
|
5080
|
-
const dragOptionsRef = React12.useRef(
|
|
6074
|
+
const dragOptionsRef = React12.useRef(DEFAULT_DRAG_OPTIONS);
|
|
6075
|
+
const initialRectRef = React12.useRef(
|
|
6076
|
+
{ x: 0, y: 0, scaleX: 1, scaleY: 1 }
|
|
6077
|
+
);
|
|
6078
|
+
const originalTransformRef = React12.useRef("");
|
|
5081
6079
|
React12.useEffect(() => {
|
|
5082
6080
|
dragStateRef.current = dragState;
|
|
5083
6081
|
dropTargetRef.current = dropTarget;
|
|
@@ -5087,8 +6085,11 @@ function useMove({ onMoveComplete }) {
|
|
|
5087
6085
|
const current = dragStateRef.current;
|
|
5088
6086
|
if (current.draggedElement) {
|
|
5089
6087
|
current.draggedElement.style.opacity = "";
|
|
6088
|
+
current.draggedElement.style.transform = originalTransformRef.current;
|
|
5090
6089
|
}
|
|
5091
|
-
|
|
6090
|
+
originalTransformRef.current = "";
|
|
6091
|
+
initialRectRef.current = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
|
|
6092
|
+
dragOptionsRef.current = DEFAULT_DRAG_OPTIONS;
|
|
5092
6093
|
setDragState(INITIAL_DRAG_STATE);
|
|
5093
6094
|
setDropTarget(null);
|
|
5094
6095
|
setDropIndicator(null);
|
|
@@ -5101,31 +6102,43 @@ function useMove({ onMoveComplete }) {
|
|
|
5101
6102
|
cancelDrag();
|
|
5102
6103
|
return;
|
|
5103
6104
|
}
|
|
6105
|
+
const initialPos = { x: initialRectRef.current.x, y: initialRectRef.current.y };
|
|
6106
|
+
const { scaleX, scaleY } = initialRectRef.current;
|
|
6107
|
+
draggedElement.style.transform = originalTransformRef.current;
|
|
5104
6108
|
draggedElement.style.opacity = "";
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
6109
|
+
originalTransformRef.current = "";
|
|
6110
|
+
initialRectRef.current = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
|
|
6111
|
+
const dragMode = dragOptionsRef.current.mode;
|
|
6112
|
+
dragOptionsRef.current = DEFAULT_DRAG_OPTIONS;
|
|
6113
|
+
const vd = {
|
|
6114
|
+
x: Math.round(current.ghostPosition.x - initialPos.x),
|
|
6115
|
+
y: Math.round(current.ghostPosition.y - initialPos.y)
|
|
6116
|
+
};
|
|
6117
|
+
const hasVisualDelta = vd.x !== 0 || vd.y !== 0;
|
|
6118
|
+
let moveInfo = null;
|
|
6119
|
+
if (dragMode === "position") {
|
|
6120
|
+
if (target && tryReparent(draggedElement, target, originalParent, originalNextSibling)) {
|
|
6121
|
+
if (originalParent) {
|
|
6122
|
+
moveInfo = { originalParent, originalPreviousSibling, originalNextSibling, mode: "free", resetPositionOffsets: true, visualDelta: hasVisualDelta ? vd : void 0 };
|
|
5119
6123
|
}
|
|
5120
6124
|
}
|
|
6125
|
+
if (!moveInfo) {
|
|
6126
|
+
const rect = draggedElement.getBoundingClientRect();
|
|
6127
|
+
const deltaX = (current.ghostPosition.x - rect.left) / scaleX;
|
|
6128
|
+
const deltaY = (current.ghostPosition.y - rect.top) / scaleY;
|
|
6129
|
+
if ((Math.abs(deltaX) > 0.5 || Math.abs(deltaY) > 0.5) && originalParent) {
|
|
6130
|
+
moveInfo = { originalParent, originalPreviousSibling, originalNextSibling, mode: "position", positionDelta: { x: deltaX, y: deltaY } };
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
} else if (target && tryReparent(draggedElement, target, originalParent, originalNextSibling)) {
|
|
6134
|
+
if (originalParent) {
|
|
6135
|
+
moveInfo = { originalParent, originalPreviousSibling, originalNextSibling, mode: dragMode, visualDelta: hasVisualDelta ? vd : void 0 };
|
|
6136
|
+
}
|
|
5121
6137
|
}
|
|
5122
6138
|
setDragState(INITIAL_DRAG_STATE);
|
|
5123
6139
|
setDropTarget(null);
|
|
5124
6140
|
setDropIndicator(null);
|
|
5125
|
-
|
|
5126
|
-
const moveInfo = didMove && originalParent ? { originalParent, originalPreviousSibling, originalNextSibling } : null;
|
|
5127
|
-
onMoveCompleteRef.current(draggedElement, moveInfo);
|
|
5128
|
-
}
|
|
6141
|
+
onMoveCompleteRef.current?.(draggedElement, moveInfo);
|
|
5129
6142
|
}, [cancelDrag]);
|
|
5130
6143
|
const startDrag = React12.useCallback(
|
|
5131
6144
|
(e, element, options) => {
|
|
@@ -5133,7 +6146,14 @@ function useMove({ onMoveComplete }) {
|
|
|
5133
6146
|
const parent = element.parentElement;
|
|
5134
6147
|
const previousSibling = element.previousElementSibling;
|
|
5135
6148
|
const nextSibling = element.nextElementSibling;
|
|
5136
|
-
dragOptionsRef.current = options
|
|
6149
|
+
dragOptionsRef.current = normalizeStartDragOptions(options);
|
|
6150
|
+
initialRectRef.current = {
|
|
6151
|
+
x: rect.left,
|
|
6152
|
+
y: rect.top,
|
|
6153
|
+
scaleX: element.offsetWidth > 0 ? rect.width / element.offsetWidth : 1,
|
|
6154
|
+
scaleY: element.offsetHeight > 0 ? rect.height / element.offsetHeight : 1
|
|
6155
|
+
};
|
|
6156
|
+
originalTransformRef.current = element.style.transform;
|
|
5137
6157
|
setDragState({
|
|
5138
6158
|
isDragging: true,
|
|
5139
6159
|
draggedElement: element,
|
|
@@ -5159,6 +6179,44 @@ function useMove({ onMoveComplete }) {
|
|
|
5159
6179
|
y: e.clientY - dragOffset.y
|
|
5160
6180
|
}
|
|
5161
6181
|
}));
|
|
6182
|
+
if (draggedElement) {
|
|
6183
|
+
const { x, y, scaleX, scaleY } = initialRectRef.current;
|
|
6184
|
+
const dx = (e.clientX - dragOffset.x - x) / scaleX;
|
|
6185
|
+
const dy = (e.clientY - dragOffset.y - y) / scaleY;
|
|
6186
|
+
draggedElement.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
6187
|
+
}
|
|
6188
|
+
if (dragOptionsRef.current.mode === "position") {
|
|
6189
|
+
let container2 = findLayoutContainerAtPoint(
|
|
6190
|
+
e.clientX,
|
|
6191
|
+
e.clientY,
|
|
6192
|
+
draggedElement,
|
|
6193
|
+
originalParent
|
|
6194
|
+
);
|
|
6195
|
+
if (!container2 && draggedElement && originalParent) {
|
|
6196
|
+
const parentRect = originalParent.getBoundingClientRect();
|
|
6197
|
+
const hasSize = parentRect.width > 0 || parentRect.height > 0;
|
|
6198
|
+
const isOutside = hasSize && (e.clientX < parentRect.left || e.clientX > parentRect.right || e.clientY < parentRect.top || e.clientY > parentRect.bottom);
|
|
6199
|
+
if (isOutside) {
|
|
6200
|
+
const found = findContainerAtPoint(e.clientX, e.clientY, draggedElement, null);
|
|
6201
|
+
if (found && found !== originalParent) container2 = found;
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6204
|
+
if (container2 && draggedElement) {
|
|
6205
|
+
const dropPos = calculateDropPosition(container2, e.clientX, e.clientY, draggedElement);
|
|
6206
|
+
if (dropPos) {
|
|
6207
|
+
setDropTarget({
|
|
6208
|
+
container: container2,
|
|
6209
|
+
insertBefore: dropPos.insertBefore,
|
|
6210
|
+
flexDirection: resolveFlexDirection(container2, draggedElement)
|
|
6211
|
+
});
|
|
6212
|
+
setDropIndicator(dropPos.indicator);
|
|
6213
|
+
}
|
|
6214
|
+
} else {
|
|
6215
|
+
setDropTarget(null);
|
|
6216
|
+
setDropIndicator(null);
|
|
6217
|
+
}
|
|
6218
|
+
return;
|
|
6219
|
+
}
|
|
5162
6220
|
const container = dragOptionsRef.current.constrainToOriginalParent ? originalParent : findContainerAtPoint(
|
|
5163
6221
|
e.clientX,
|
|
5164
6222
|
e.clientY,
|
|
@@ -5176,11 +6234,7 @@ function useMove({ onMoveComplete }) {
|
|
|
5176
6234
|
setDropTarget({
|
|
5177
6235
|
container,
|
|
5178
6236
|
insertBefore: dropPos.insertBefore,
|
|
5179
|
-
flexDirection: (
|
|
5180
|
-
const { axis, reversed } = detectChildrenDirection(container, draggedElement);
|
|
5181
|
-
if (axis === "horizontal") return reversed ? "row-reverse" : "row";
|
|
5182
|
-
return reversed ? "column-reverse" : "column";
|
|
5183
|
-
})()
|
|
6237
|
+
flexDirection: resolveFlexDirection(container, draggedElement)
|
|
5184
6238
|
});
|
|
5185
6239
|
setDropIndicator(dropPos.indicator);
|
|
5186
6240
|
}
|
|
@@ -5641,6 +6695,12 @@ var MAGENTA = "#E11BB6";
|
|
|
5641
6695
|
var DRAG_THRESHOLD = 4;
|
|
5642
6696
|
var DBLCLICK_DELAY = 300;
|
|
5643
6697
|
var HANDLE_SIZE = 12;
|
|
6698
|
+
function isInLayoutContainer(element) {
|
|
6699
|
+
const parent = element.parentElement;
|
|
6700
|
+
if (!parent) return false;
|
|
6701
|
+
const display = window.getComputedStyle(parent).display;
|
|
6702
|
+
return display === "flex" || display === "inline-flex" || display === "grid" || display === "inline-grid";
|
|
6703
|
+
}
|
|
5644
6704
|
function SelectionOverlay({
|
|
5645
6705
|
selectedElement,
|
|
5646
6706
|
draggedElement,
|
|
@@ -5659,8 +6719,16 @@ function SelectionOverlay({
|
|
|
5659
6719
|
const [moveHandleRects, setMoveHandleRects] = React14.useState([]);
|
|
5660
6720
|
const cleanupRef = React14.useRef(null);
|
|
5661
6721
|
const clickThroughTimerRef = React14.useRef(null);
|
|
6722
|
+
const isDraggingRef = React14.useRef(isDragging);
|
|
6723
|
+
isDraggingRef.current = isDragging;
|
|
6724
|
+
React14.useLayoutEffect(() => {
|
|
6725
|
+
if (!isDragging) {
|
|
6726
|
+
setRect(rectElement.getBoundingClientRect());
|
|
6727
|
+
}
|
|
6728
|
+
}, [isDragging, rectElement]);
|
|
5662
6729
|
React14.useEffect(() => {
|
|
5663
6730
|
function updateRect() {
|
|
6731
|
+
if (isDraggingRef.current) return;
|
|
5664
6732
|
setRect(rectElement.getBoundingClientRect());
|
|
5665
6733
|
}
|
|
5666
6734
|
updateRect();
|
|
@@ -5701,7 +6769,9 @@ function SelectionOverlay({
|
|
|
5701
6769
|
const dy = moveEvent.clientY - origin.y;
|
|
5702
6770
|
if (dx * dx + dy * dy >= DRAG_THRESHOLD * DRAG_THRESHOLD) {
|
|
5703
6771
|
cleanup();
|
|
5704
|
-
onMoveStart(savedEvent
|
|
6772
|
+
onMoveStart(savedEvent, void 0, {
|
|
6773
|
+
mode: isInLayoutContainer(selectedElement) ? "free" : "position"
|
|
6774
|
+
});
|
|
5705
6775
|
}
|
|
5706
6776
|
};
|
|
5707
6777
|
const onUp = (upEvent) => {
|
|
@@ -5758,7 +6828,7 @@ function SelectionOverlay({
|
|
|
5758
6828
|
flexParent = flexParent.parentElement;
|
|
5759
6829
|
}
|
|
5760
6830
|
if (!flexParent) {
|
|
5761
|
-
return [
|
|
6831
|
+
return [];
|
|
5762
6832
|
}
|
|
5763
6833
|
let target = selectedElement;
|
|
5764
6834
|
while (target.parentElement && target.parentElement !== flexParent) {
|
|
@@ -5801,7 +6871,7 @@ function SelectionOverlay({
|
|
|
5801
6871
|
clearTimeout(clickThroughTimerRef.current);
|
|
5802
6872
|
clickThroughTimerRef.current = null;
|
|
5803
6873
|
}
|
|
5804
|
-
onMoveStart(e, target, { constrainToOriginalParent: true });
|
|
6874
|
+
onMoveStart(e, target, { constrainToOriginalParent: true, mode: "reorder" });
|
|
5805
6875
|
};
|
|
5806
6876
|
const displayX = isDragging && ghostPosition ? ghostPosition.x : rect.left;
|
|
5807
6877
|
const displayY = isDragging && ghostPosition ? ghostPosition.y : rect.top;
|
|
@@ -5881,6 +6951,10 @@ function SelectionOverlay({
|
|
|
5881
6951
|
import * as React15 from "react";
|
|
5882
6952
|
import { ChevronLeft, Check, Copy, Trash2, ArrowUp, Send, X } from "lucide-react";
|
|
5883
6953
|
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
6954
|
+
function clampUnit2(value) {
|
|
6955
|
+
if (!Number.isFinite(value)) return 0;
|
|
6956
|
+
return Math.max(0, Math.min(1, value));
|
|
6957
|
+
}
|
|
5884
6958
|
function formatRelativeTime(timestamp) {
|
|
5885
6959
|
const seconds = Math.floor((Date.now() - timestamp) / 1e3);
|
|
5886
6960
|
if (seconds < 60) return "just now";
|
|
@@ -5963,9 +7037,11 @@ function CommentPin({
|
|
|
5963
7037
|
function updatePosition() {
|
|
5964
7038
|
if (!comment.element.isConnected) return;
|
|
5965
7039
|
const rect = comment.element.getBoundingClientRect();
|
|
7040
|
+
const relativeX = clampUnit2(comment.relativePosition.x);
|
|
7041
|
+
const relativeY = clampUnit2(comment.relativePosition.y);
|
|
5966
7042
|
setPosition({
|
|
5967
|
-
x: rect.left +
|
|
5968
|
-
y: rect.top +
|
|
7043
|
+
x: rect.left + relativeX * rect.width,
|
|
7044
|
+
y: rect.top + relativeY * rect.height
|
|
5969
7045
|
});
|
|
5970
7046
|
setElementRect(rect);
|
|
5971
7047
|
}
|
|
@@ -10236,6 +11312,11 @@ function truncateText(value, max = 64) {
|
|
|
10236
11312
|
if (value.length <= max) return value;
|
|
10237
11313
|
return `${value.slice(0, max)}...`;
|
|
10238
11314
|
}
|
|
11315
|
+
function summarizeMoveForPreview(intent) {
|
|
11316
|
+
const system = intent.layoutPrescription?.recommendedSystem;
|
|
11317
|
+
const systemPart = system ? `, ${system}` : "";
|
|
11318
|
+
return `${intent.operationId}: ${intent.classification}${systemPart}`;
|
|
11319
|
+
}
|
|
10239
11320
|
function EditsPopover({
|
|
10240
11321
|
tooltipSide,
|
|
10241
11322
|
sessionEditCount,
|
|
@@ -10253,6 +11334,19 @@ function EditsPopover({
|
|
|
10253
11334
|
const editsPopupRef = React33.useRef(null);
|
|
10254
11335
|
const editsTriggerRef = React33.useRef(null);
|
|
10255
11336
|
const [editsSnapshot, setEditsSnapshot] = React33.useState([]);
|
|
11337
|
+
const movePlanContext = React33.useMemo(() => {
|
|
11338
|
+
const edits = editsSnapshot.filter((item) => item.type === "edit").map((item) => item.edit);
|
|
11339
|
+
return buildMovePlanContext(edits);
|
|
11340
|
+
}, [editsSnapshot]);
|
|
11341
|
+
const visibleItems = React33.useMemo(() => {
|
|
11342
|
+
return editsSnapshot.filter((item) => {
|
|
11343
|
+
if (item.type === "comment") return true;
|
|
11344
|
+
if (!item.edit.move) return true;
|
|
11345
|
+
const moveIntent = getMoveIntentForEdit(item.edit, movePlanContext);
|
|
11346
|
+
const hasStyleOrText = Object.keys(item.edit.pendingStyles).length > 0 || item.edit.textEdit != null;
|
|
11347
|
+
return Boolean(moveIntent || hasStyleOrText);
|
|
11348
|
+
});
|
|
11349
|
+
}, [editsSnapshot, movePlanContext]);
|
|
10256
11350
|
React33.useEffect(() => {
|
|
10257
11351
|
if (!isOpen) return;
|
|
10258
11352
|
function handlePointerDown(e) {
|
|
@@ -10298,16 +11392,22 @@ function EditsPopover({
|
|
|
10298
11392
|
window.setTimeout(() => setSendStatus("idle"), 2e3);
|
|
10299
11393
|
}, [onSendAllToAgents, sendStatus]);
|
|
10300
11394
|
const handleCopyItem = React33.useCallback(async (item) => {
|
|
10301
|
-
const text = item.type === "edit" ? buildSessionExport([item.edit], []
|
|
10302
|
-
|
|
10303
|
-
|
|
11395
|
+
const text = item.type === "edit" ? buildSessionExport([item.edit], [], {
|
|
11396
|
+
movePlanContext,
|
|
11397
|
+
includeMovePlanHeader: false
|
|
11398
|
+
}) : buildSessionExport([], [item.comment]);
|
|
11399
|
+
const instruction = item.type === "edit" ? buildExportInstruction(getExportContentProfile(
|
|
11400
|
+
[item.edit],
|
|
11401
|
+
[],
|
|
11402
|
+
item.edit.move ? buildMovePlanContext([item.edit]) : null
|
|
11403
|
+
)) : buildExportInstruction({ hasCssEdits: false, hasTextEdits: false, hasMoves: false, hasComments: true });
|
|
11404
|
+
const success = await copyText(`${instruction}
|
|
10304
11405
|
|
|
10305
11406
|
${text}`);
|
|
10306
|
-
|
|
10307
|
-
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
}, []);
|
|
11407
|
+
if (!success) return;
|
|
11408
|
+
setCopied(true);
|
|
11409
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
11410
|
+
}, [movePlanContext]);
|
|
10311
11411
|
return /* @__PURE__ */ jsxs23(Popover2.Root, { open: isOpen, onOpenChange, children: [
|
|
10312
11412
|
/* @__PURE__ */ jsxs23(Tooltip, { disabled: isOpen, children: [
|
|
10313
11413
|
/* @__PURE__ */ jsx30(TooltipTrigger, { render: /* @__PURE__ */ jsx30(Popover2.Trigger, { render: /* @__PURE__ */ jsx30(
|
|
@@ -10338,7 +11438,7 @@ ${text}`);
|
|
|
10338
11438
|
children: [
|
|
10339
11439
|
/* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-3 pb-1 pt-2.5", children: [
|
|
10340
11440
|
/* @__PURE__ */ jsx30("span", { className: "text-xs font-medium text-foreground", children: "Copy to AI agents" }),
|
|
10341
|
-
|
|
11441
|
+
visibleItems.length > 0 && /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1", children: [
|
|
10342
11442
|
/* @__PURE__ */ jsxs23(
|
|
10343
11443
|
BaseButton,
|
|
10344
11444
|
{
|
|
@@ -10381,9 +11481,10 @@ ${text}`);
|
|
|
10381
11481
|
] })
|
|
10382
11482
|
] })
|
|
10383
11483
|
] }),
|
|
10384
|
-
|
|
11484
|
+
visibleItems.length === 0 ? /* @__PURE__ */ jsx30("div", { className: "px-3 pb-3 pt-1 text-xs text-muted-foreground", children: "No edits or comments yet." }) : /* @__PURE__ */ jsx30("div", { className: "max-h-[240px] overflow-y-auto px-1 py-1", children: visibleItems.map((item, i) => {
|
|
10385
11485
|
const isEdit = item.type === "edit";
|
|
10386
|
-
const
|
|
11486
|
+
const moveIntent = isEdit && item.edit.move ? getMoveIntentForEdit(item.edit, movePlanContext) : null;
|
|
11487
|
+
const isMoved = Boolean(moveIntent);
|
|
10387
11488
|
const locator = isEdit ? item.edit.locator : item.comment.locator;
|
|
10388
11489
|
const componentName = locator.reactStack[0]?.name ?? locator.tagName;
|
|
10389
11490
|
let valueSummary = "";
|
|
@@ -10396,8 +11497,8 @@ ${text}`);
|
|
|
10396
11497
|
if (item.edit.textEdit) {
|
|
10397
11498
|
editValues.push(`text: "${item.edit.textEdit.newText}"`);
|
|
10398
11499
|
}
|
|
10399
|
-
if (
|
|
10400
|
-
editValues.push(
|
|
11500
|
+
if (moveIntent) {
|
|
11501
|
+
editValues.push(summarizeMoveForPreview(moveIntent));
|
|
10401
11502
|
}
|
|
10402
11503
|
valueSummary = editValues.length > 0 ? editValues.join(", ") : "(no edits)";
|
|
10403
11504
|
} else {
|
|
@@ -10448,7 +11549,15 @@ ${text}`);
|
|
|
10448
11549
|
} else {
|
|
10449
11550
|
onDeleteComment?.(item.comment.id);
|
|
10450
11551
|
}
|
|
10451
|
-
setEditsSnapshot((prev) => prev.filter((
|
|
11552
|
+
setEditsSnapshot((prev) => prev.filter((candidate) => {
|
|
11553
|
+
if (item.type === "edit" && candidate.type === "edit") {
|
|
11554
|
+
return candidate.edit.element !== item.edit.element;
|
|
11555
|
+
}
|
|
11556
|
+
if (item.type === "comment" && candidate.type === "comment") {
|
|
11557
|
+
return candidate.comment.id !== item.comment.id;
|
|
11558
|
+
}
|
|
11559
|
+
return true;
|
|
11560
|
+
}));
|
|
10452
11561
|
},
|
|
10453
11562
|
children: /* @__PURE__ */ jsx30(X4, { className: "size-3" })
|
|
10454
11563
|
}
|
|
@@ -11261,12 +12370,7 @@ function DirectEditDemo() {
|
|
|
11261
12370
|
const handleExportEdits = async () => {
|
|
11262
12371
|
if (Object.keys(pendingStyles).length === 0) return false;
|
|
11263
12372
|
const exportMarkdown = buildEditExport(DEMO_LOCATOR, pendingStyles);
|
|
11264
|
-
|
|
11265
|
-
await navigator.clipboard.writeText(exportMarkdown);
|
|
11266
|
-
return true;
|
|
11267
|
-
} catch {
|
|
11268
|
-
return false;
|
|
11269
|
-
}
|
|
12373
|
+
return copyText(buildAgentClipboardText(exportMarkdown));
|
|
11270
12374
|
};
|
|
11271
12375
|
return /* @__PURE__ */ jsx35("div", { className: "min-h-screen p-8", children: /* @__PURE__ */ jsxs28("div", { className: "mx-auto max-w-4xl", children: [
|
|
11272
12376
|
/* @__PURE__ */ jsx35("h1", { className: "mb-2 text-2xl font-bold", children: "Direct Edit Panel" }),
|
|
@@ -11382,6 +12486,7 @@ export {
|
|
|
11382
12486
|
colorToTailwind,
|
|
11383
12487
|
elementFromPointWithoutOverlays,
|
|
11384
12488
|
findContainerAtPoint,
|
|
12489
|
+
findLayoutContainerAtPoint,
|
|
11385
12490
|
formatColorValue,
|
|
11386
12491
|
formatPropertyValue,
|
|
11387
12492
|
getComputedBorderStyles,
|
|
@@ -11394,6 +12499,7 @@ export {
|
|
|
11394
12499
|
getFlexDirection,
|
|
11395
12500
|
getStoredGuidelines,
|
|
11396
12501
|
isFlexContainer,
|
|
12502
|
+
isLayoutContainer,
|
|
11397
12503
|
parseColorValue,
|
|
11398
12504
|
parsePropertyValue,
|
|
11399
12505
|
stylesToTailwind,
|