@insforge/react 0.2.10 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
5
5
  if (!document.getElementById(styleId)) {
6
6
  const style = document.createElement('style');
7
7
  style.id = styleId;
8
- style.textContent = "/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n@import \"https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap\";@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-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight: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-duration:initial;--tw-content:\"\"}}}@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-50:oklch(97.1% .013 17.38);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-green-100:oklch(96.2% .044 156.743);--color-green-400:oklch(79.2% .209 151.711);--color-green-600:oklch(62.7% .194 149.214);--color-green-900:oklch(39.3% .095 152.535);--color-blue-50:oklch(97% .014 254.604);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-900:oklch(37.9% .146 265.522);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-purple-900:oklch(38.1% .176 304.987);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-neutral-400:oklch(70.8% 0 0);--color-neutral-600:oklch(43.9% 0 0);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--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);--font-manrope:\"Manrope\",sans-serif}}@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}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.top-1\\/2{top:50%}.top-full{top:100%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.z-50{z-index:50}.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}}.mx-auto{margin-inline:auto}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-16{height:calc(var(--spacing)*16)}.h-\\[18px\\]{height:18px}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-12{width:calc(var(--spacing)*12)}.w-16{width:calc(var(--spacing)*16)}.w-\\[18px\\]{width:18px}.w-full{width:100%}.max-w-\\[400px\\]{max-width:400px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.min-w-40{min-width:calc(var(--spacing)*40)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-0{gap:calc(var(--spacing)*0)}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.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)}.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-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-none{--tw-border-style:none;border-style:none}.border-\\[\\#D4D4D4\\]{border-color:#d4d4d4}.border-\\[\\#E0E0E0\\]{border-color:#e0e0e0}.border-\\[\\#E4E4E7\\]{border-color:#e4e4e7}.border-black{border-color:var(--color-black)}.border-blue-500{border-color:var(--color-blue-500)}.border-blue-600{border-color:var(--color-blue-600)}.border-gray-200{border-color:var(--color-gray-200)}.border-neutral-400{border-color:var(--color-neutral-400)}.border-purple-300{border-color:var(--color-purple-300)}.border-red-600{border-color:var(--color-red-600)}.border-transparent{border-color:#0000}.bg-\\[\\#059669\\]{background-color:#059669}.bg-\\[\\#FAFAFA\\]{background-color:#fafafa}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-100{background-color:var(--color-green-100)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-50{--tw-gradient-from:var(--color-blue-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-white{--tw-gradient-to:var(--color-white);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{object-fit:cover}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-6{padding:calc(var(--spacing)*6)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-2{padding-block:calc(var(--spacing)*2)}.py-4{padding-block:calc(var(--spacing)*4)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pl-3{padding-left:calc(var(--spacing)*3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-manrope{font-family:var(--font-manrope)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.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))}.leading-4{--tw-leading:calc(var(--spacing)*4);line-height:calc(var(--spacing)*4)}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.leading-8{--tw-leading:calc(var(--spacing)*8);line-height:calc(var(--spacing)*8)}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.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)}.text-\\[\\#09090B\\]{color:#09090b}.text-\\[\\#525252\\]{color:#525252}.text-\\[\\#737373\\]{color:#737373}.text-\\[\\#828282\\]{color:#828282}.text-\\[\\#A3A3A3\\]{color:#a3a3a3}.text-\\[\\#A6A6A6\\]{color:#a6a6a6}.text-black{color:var(--color-black)}.text-blue-500{color:var(--color-blue-500)}.text-blue-900{color:var(--color-blue-900)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-600{color:var(--color-green-600)}.text-neutral-600{color:var(--color-neutral-600)}.text-purple-600{color:var(--color-purple-600)}.text-purple-700{color:var(--color-purple-700)}.text-purple-900{color:var(--color-purple-900)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.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-\\[0_1px_2px_0_rgba\\(0\\,0\\,0\\,0\\.10\\)\\]{--tw-shadow:0 1px 2px 0 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-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)}.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))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\\:font-normal::placeholder{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.placeholder\\:text-\\[\\#A3A3A3\\]::placeholder{color:#a3a3a3}.before\\:h-px:before{content:var(--tw-content);height:1px}.before\\:flex-1:before{content:var(--tw-content);flex:1}.before\\:bg-\\[\\#E5E5E5\\]:before{content:var(--tw-content);background-color:#e5e5e5}.before\\:content-\\[\\'\\'\\]:before{--tw-content:\"\";content:var(--tw-content)}.after\\:h-px:after{content:var(--tw-content);height:1px}.after\\:flex-1:after{content:var(--tw-content);flex:1}.after\\:bg-\\[\\#E5E5E5\\]:after{content:var(--tw-content);background-color:#e5e5e5}.after\\:content-\\[\\'\\'\\]:after{--tw-content:\"\";content:var(--tw-content)}@media (hover:hover){.hover\\:border-\\[\\#9ca3af\\]:hover{border-color:#9ca3af}.hover\\:bg-\\[\\#f9fafb\\]:hover{background-color:#f9fafb}.hover\\:bg-black\\/5:hover{background-color:#0000000d}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-black\\/5:hover{background-color:color-mix(in oklab,var(--color-black)5%,transparent)}}.hover\\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\\:bg-purple-700:hover{background-color:var(--color-purple-700)}.hover\\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\\:bg-white\\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-white\\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.hover\\:text-gray-600:hover{color:var(--color-gray-600)}.hover\\:text-purple-800:hover{color:var(--color-purple-800)}}.focus\\:border-black:focus{border-color:var(--color-black)}.focus\\:border-purple-500:focus{border-color:var(--color-purple-500)}.focus\\:shadow-\\[0_0_0_2px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]:focus{--tw-shadow:0 0 0 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)}.focus\\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:bg-\\[\\#F5F5F5\\]:disabled{background-color:#f5f5f5}.disabled\\:opacity-50:disabled{opacity:.5}.disabled\\:opacity-60:disabled{opacity:.6}@media (prefers-color-scheme:dark){.dark\\:border-white{border-color:var(--color-white)}.dark\\:bg-green-900{background-color:var(--color-green-900)}.dark\\:text-gray-400{color:var(--color-gray-400)}.dark\\:text-green-400{color:var(--color-green-400)}.dark\\:text-neutral-400{color:var(--color-neutral-400)}.dark\\:text-white{color:var(--color-white)}}}@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-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:\"*\";inherits:false}@property --tw-gradient-from{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:\"*\";inherits:false}@property --tw-gradient-via-stops{syntax:\"*\";inherits:false}@property --tw-gradient-from-position{syntax:\"<length-percentage>\";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:\"<length-percentage>\";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:\"<length-percentage>\";inherits:false;initial-value:100%}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{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-duration{syntax:\"*\";inherits:false}@property --tw-content{syntax:\"*\";inherits:false;initial-value:\"\"}@keyframes spin{to{transform:rotate(360deg)}}";
8
+ style.textContent = "/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */\n@import \"https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap\";@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-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight: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-duration:initial;--tw-content:\"\"}}}@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-50:oklch(97.1% .013 17.38);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-green-100:oklch(96.2% .044 156.743);--color-green-400:oklch(79.2% .209 151.711);--color-green-600:oklch(62.7% .194 149.214);--color-green-900:oklch(39.3% .095 152.535);--color-blue-50:oklch(97% .014 254.604);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-purple-900:oklch(38.1% .176 304.987);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-neutral-100:oklch(97% 0 0);--color-neutral-400:oklch(70.8% 0 0);--color-neutral-600:oklch(43.9% 0 0);--color-neutral-800:oklch(26.9% 0 0);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--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);--font-manrope:\"Manrope\",sans-serif}}@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}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.top-1\\/2{top:50%}.top-full{top:100%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.z-50{z-index:50}.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}}.mx-auto{margin-inline:auto}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-16{height:calc(var(--spacing)*16)}.h-\\[18px\\]{height:18px}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-12{width:calc(var(--spacing)*12)}.w-16{width:calc(var(--spacing)*16)}.w-\\[18px\\]{width:18px}.w-full{width:100%}.max-w-\\[400px\\]{max-width:400px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.min-w-40{min-width:calc(var(--spacing)*40)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-0{gap:calc(var(--spacing)*0)}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.self-stretch{align-self:stretch}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.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)}.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-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-none{--tw-border-style:none;border-style:none}.border-\\[\\#D4D4D4\\]{border-color:#d4d4d4}.border-\\[\\#E0E0E0\\]{border-color:#e0e0e0}.border-\\[\\#E4E4E7\\]{border-color:#e4e4e7}.border-black{border-color:var(--color-black)}.border-blue-500{border-color:var(--color-blue-500)}.border-blue-600{border-color:var(--color-blue-600)}.border-gray-200{border-color:var(--color-gray-200)}.border-neutral-400{border-color:var(--color-neutral-400)}.border-purple-300{border-color:var(--color-purple-300)}.border-red-600{border-color:var(--color-red-600)}.border-transparent{border-color:#0000}.bg-\\[\\#059669\\]{background-color:#059669}.bg-\\[\\#FAFAFA\\]{background-color:#fafafa}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-100{background-color:var(--color-green-100)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-neutral-100{background-color:var(--color-neutral-100)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-50{--tw-gradient-from:var(--color-blue-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-indigo-50{--tw-gradient-from:var(--color-indigo-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-white{--tw-gradient-to:var(--color-white);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{object-fit:cover}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-6{padding:calc(var(--spacing)*6)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-2{padding-block:calc(var(--spacing)*2)}.py-4{padding-block:calc(var(--spacing)*4)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pb-6{padding-bottom:calc(var(--spacing)*6)}.pl-3{padding-left:calc(var(--spacing)*3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-manrope{font-family:var(--font-manrope)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.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))}.leading-4{--tw-leading:calc(var(--spacing)*4);line-height:calc(var(--spacing)*4)}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.leading-8{--tw-leading:calc(var(--spacing)*8);line-height:calc(var(--spacing)*8)}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.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)}.text-\\[\\#09090B\\]{color:#09090b}.text-\\[\\#525252\\]{color:#525252}.text-\\[\\#737373\\]{color:#737373}.text-\\[\\#828282\\]{color:#828282}.text-\\[\\#A3A3A3\\]{color:#a3a3a3}.text-\\[\\#A6A6A6\\]{color:#a6a6a6}.text-black{color:var(--color-black)}.text-blue-500{color:var(--color-blue-500)}.text-blue-900{color:var(--color-blue-900)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-600{color:var(--color-green-600)}.text-neutral-600{color:var(--color-neutral-600)}.text-purple-600{color:var(--color-purple-600)}.text-purple-700{color:var(--color-purple-700)}.text-purple-900{color:var(--color-purple-900)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.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-\\[0_1px_2px_0_rgba\\(0\\,0\\,0\\,0\\.10\\)\\]{--tw-shadow:0 1px 2px 0 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-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)}.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))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\\:font-normal::placeholder{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.placeholder\\:text-\\[\\#A3A3A3\\]::placeholder{color:#a3a3a3}.before\\:h-px:before{content:var(--tw-content);height:1px}.before\\:flex-1:before{content:var(--tw-content);flex:1}.before\\:bg-\\[\\#E5E5E5\\]:before{content:var(--tw-content);background-color:#e5e5e5}.before\\:content-\\[\\'\\'\\]:before{--tw-content:\"\";content:var(--tw-content)}.after\\:h-px:after{content:var(--tw-content);height:1px}.after\\:flex-1:after{content:var(--tw-content);flex:1}.after\\:bg-\\[\\#E5E5E5\\]:after{content:var(--tw-content);background-color:#e5e5e5}.after\\:content-\\[\\'\\'\\]:after{--tw-content:\"\";content:var(--tw-content)}@media (hover:hover){.hover\\:border-\\[\\#9ca3af\\]:hover{border-color:#9ca3af}.hover\\:bg-\\[\\#f9fafb\\]:hover{background-color:#f9fafb}.hover\\:bg-black\\/5:hover{background-color:#0000000d}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-black\\/5:hover{background-color:color-mix(in oklab,var(--color-black)5%,transparent)}}.hover\\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\\:bg-purple-700:hover{background-color:var(--color-purple-700)}.hover\\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\\:bg-white\\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-white\\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.hover\\:text-gray-600:hover{color:var(--color-gray-600)}.hover\\:text-purple-800:hover{color:var(--color-purple-800)}.hover\\:underline:hover{text-decoration-line:underline}}.focus\\:border-black:focus{border-color:var(--color-black)}.focus\\:border-purple-500:focus{border-color:var(--color-purple-500)}.focus\\:shadow-\\[0_0_0_2px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]:focus{--tw-shadow:0 0 0 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)}.focus\\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:bg-\\[\\#F5F5F5\\]:disabled{background-color:#f5f5f5}.disabled\\:no-underline:disabled{text-decoration-line:none}.disabled\\:opacity-50:disabled{opacity:.5}.disabled\\:opacity-60:disabled{opacity:.6}@media (prefers-color-scheme:dark){.dark\\:border-white{border-color:var(--color-white)}.dark\\:bg-green-900{background-color:var(--color-green-900)}.dark\\:bg-neutral-800{background-color:var(--color-neutral-800)}.dark\\:text-gray-400{color:var(--color-gray-400)}.dark\\:text-green-400{color:var(--color-green-400)}.dark\\:text-neutral-400{color:var(--color-neutral-400)}.dark\\:text-red-400{color:var(--color-red-400)}.dark\\:text-white{color:var(--color-white)}}}@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-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:\"*\";inherits:false}@property --tw-gradient-from{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:\"<color>\";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:\"*\";inherits:false}@property --tw-gradient-via-stops{syntax:\"*\";inherits:false}@property --tw-gradient-from-position{syntax:\"<length-percentage>\";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:\"<length-percentage>\";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:\"<length-percentage>\";inherits:false;initial-value:100%}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{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-duration{syntax:\"*\";inherits:false}@property --tw-content{syntax:\"*\";inherits:false;initial-value:\"\"}@keyframes spin{to{transform:rotate(360deg)}}";
9
9
  if (document.head) {
10
10
  document.head.appendChild(style);
11
11
  }
@@ -158,70 +158,6 @@ function InsforgeProvider({
158
158
  },
159
159
  [insforge, onAuthChange, syncTokenToCookie]
160
160
  );
161
- const handleAuthCallback = useCallback(
162
- async (params) => {
163
- try {
164
- await insforge.auth.setSession({
165
- accessToken: params.accessToken,
166
- user: {
167
- id: params.userId || "",
168
- email: params.email || "",
169
- name: params.name || "",
170
- emailVerified: false,
171
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
172
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
173
- }
174
- });
175
- const userResult = await insforge.auth.getCurrentUser();
176
- if (!userResult.data) {
177
- await insforge.auth.signOut();
178
- if (clearCookie) {
179
- try {
180
- await clearCookie();
181
- } catch (error) {
182
- }
183
- }
184
- return { success: false, error: "invalid_token" };
185
- }
186
- const profile = userResult.data.profile;
187
- const userData = {
188
- id: userResult.data.user.id,
189
- email: userResult.data.user.email,
190
- name: profile?.nickname || params.name || "",
191
- avatarUrl: profile?.avatarUrl || ""
192
- };
193
- setUser(userData);
194
- if (onAuthChange) {
195
- onAuthChange(userData);
196
- }
197
- if (syncTokenToCookie) {
198
- try {
199
- await syncTokenToCookie(params.accessToken);
200
- } catch (error) {
201
- }
202
- }
203
- return { success: true };
204
- } catch (error) {
205
- console.error("[InsforgeProvider] Auth callback failed:", error);
206
- await insforge.auth.signOut();
207
- if (clearCookie) {
208
- try {
209
- await clearCookie();
210
- } catch (error2) {
211
- }
212
- }
213
- setUser(null);
214
- if (onAuthChange) {
215
- onAuthChange(null);
216
- }
217
- return {
218
- success: false,
219
- error: error instanceof Error ? error.message : "authentication_failed"
220
- };
221
- }
222
- },
223
- [insforge, onAuthChange, syncTokenToCookie, clearCookie]
224
- );
225
161
  const signIn = useCallback(
226
162
  async (email, password) => {
227
163
  const sdkResult = await insforge.auth.signInWithPassword({
@@ -239,8 +175,11 @@ function InsforgeProvider({
239
175
  );
240
176
  return sdkResult.data;
241
177
  } else {
242
- const errorMessage = sdkResult.error?.message || "Invalid email or password";
243
- return { error: errorMessage };
178
+ return {
179
+ error: sdkResult.error?.message || "Invalid email or password",
180
+ statusCode: sdkResult.error?.statusCode,
181
+ errorCode: sdkResult.error?.error
182
+ };
244
183
  }
245
184
  },
246
185
  [insforge, handleAuthSuccess]
@@ -249,18 +188,23 @@ function InsforgeProvider({
249
188
  async (email, password) => {
250
189
  const sdkResult = await insforge.auth.signUp({ email, password });
251
190
  if (sdkResult.data) {
252
- await handleAuthSuccess(
253
- sdkResult.data.accessToken || "",
254
- sdkResult.data.user ? {
255
- id: sdkResult.data.user.id,
256
- email: sdkResult.data.user.email,
257
- name: sdkResult.data.user.name
258
- } : void 0
259
- );
191
+ if (sdkResult.data.accessToken) {
192
+ await handleAuthSuccess(
193
+ sdkResult.data.accessToken,
194
+ sdkResult.data.user ? {
195
+ id: sdkResult.data.user.id,
196
+ email: sdkResult.data.user.email,
197
+ name: sdkResult.data.user.name
198
+ } : void 0
199
+ );
200
+ }
260
201
  return sdkResult.data;
261
202
  } else {
262
- const errorMessage = sdkResult.error?.message || "Sign up failed";
263
- return { error: errorMessage };
203
+ return {
204
+ error: sdkResult.error?.message || "Sign up failed",
205
+ statusCode: sdkResult.error?.statusCode,
206
+ errorCode: sdkResult.error?.error
207
+ };
264
208
  }
265
209
  },
266
210
  [insforge, handleAuthSuccess]
@@ -345,7 +289,6 @@ function InsforgeProvider({
345
289
  signOut,
346
290
  updateUser,
347
291
  reloadAuth: loadAuthState,
348
- handleAuthCallback,
349
292
  baseUrl,
350
293
  sendPasswordResetCode,
351
294
  resetPassword,
@@ -1034,6 +977,7 @@ function AuthVerificationCodeInput({
1034
977
  email,
1035
978
  onChange,
1036
979
  disabled = false,
980
+ onComplete,
1037
981
  appearance = {}
1038
982
  }) {
1039
983
  const inputRefs = useRef([]);
@@ -1047,6 +991,9 @@ function AuthVerificationCodeInput({
1047
991
  if (digit && index < length - 1) {
1048
992
  inputRefs.current[index + 1]?.focus();
1049
993
  }
994
+ if (digit && index === length - 1 && updatedValue.length === length && onComplete) {
995
+ onComplete(updatedValue);
996
+ }
1050
997
  };
1051
998
  const handleKeyDown = (index, e) => {
1052
999
  if (e.key === "Backspace") {
@@ -1067,6 +1014,9 @@ function AuthVerificationCodeInput({
1067
1014
  if (/^\d+$/.test(pastedData) && pastedData.length === length) {
1068
1015
  onChange(pastedData);
1069
1016
  inputRefs.current[length - 1]?.focus();
1017
+ if (onComplete) {
1018
+ onComplete(pastedData);
1019
+ }
1070
1020
  }
1071
1021
  };
1072
1022
  return /* @__PURE__ */ jsxs("div", { className: cn(
@@ -1107,6 +1057,126 @@ function AuthVerificationCodeInput({
1107
1057
  )) })
1108
1058
  ] });
1109
1059
  }
1060
+ function AuthEmailVerificationStep({
1061
+ email,
1062
+ title = "Verify Your Email",
1063
+ description,
1064
+ method = "code",
1065
+ onVerifyCode
1066
+ }) {
1067
+ const { baseUrl } = useInsforge();
1068
+ const [insforge] = useState(() => createClient({ baseUrl }));
1069
+ const [resendDisabled, setResendDisabled] = useState(true);
1070
+ const [resendCountdown, setResendCountdown] = useState(60);
1071
+ const [isSending, setIsSending] = useState(false);
1072
+ const [verificationCode, setVerificationCode] = useState("");
1073
+ const [isVerifying, setIsVerifying] = useState(false);
1074
+ const [verificationError, setVerificationError] = useState("");
1075
+ const defaultDescription = method === "code" ? "We've sent a 6-digit verification code to {email}. Please enter it below to verify your account. The code will expire in 10 minutes." : "We've sent a verification link to {email}. Please check your email and click the link to verify your account. The link will expire in 10 minutes.";
1076
+ useEffect(() => {
1077
+ const sendInitialEmail = async () => {
1078
+ try {
1079
+ if (method === "code") {
1080
+ await insforge.auth.sendVerificationCode({ email });
1081
+ } else {
1082
+ await insforge.auth.sendVerificationLink({ email });
1083
+ }
1084
+ } catch {
1085
+ }
1086
+ };
1087
+ void sendInitialEmail();
1088
+ }, [email, method, insforge.auth]);
1089
+ useEffect(() => {
1090
+ if (resendCountdown > 0) {
1091
+ const timer = setInterval(() => {
1092
+ setResendCountdown((prev) => {
1093
+ if (prev <= 1) {
1094
+ setResendDisabled(false);
1095
+ return 0;
1096
+ }
1097
+ return prev - 1;
1098
+ });
1099
+ }, 1e3);
1100
+ return () => clearInterval(timer);
1101
+ }
1102
+ }, [resendCountdown]);
1103
+ const handleResend = async () => {
1104
+ setResendDisabled(true);
1105
+ setResendCountdown(60);
1106
+ setIsSending(true);
1107
+ setVerificationError("");
1108
+ try {
1109
+ if (method === "code") {
1110
+ await insforge.auth.sendVerificationCode({ email });
1111
+ } else {
1112
+ await insforge.auth.sendVerificationLink({ email });
1113
+ }
1114
+ } catch {
1115
+ setResendDisabled(false);
1116
+ setResendCountdown(0);
1117
+ } finally {
1118
+ setIsSending(false);
1119
+ }
1120
+ };
1121
+ const handleVerifyCode = async (code) => {
1122
+ if (!onVerifyCode) {
1123
+ return;
1124
+ }
1125
+ setIsVerifying(true);
1126
+ setVerificationError("");
1127
+ try {
1128
+ await onVerifyCode(code);
1129
+ } catch (error) {
1130
+ setVerificationError(
1131
+ error instanceof Error ? error.message : "Invalid verification code. Please try again."
1132
+ );
1133
+ setVerificationCode("");
1134
+ } finally {
1135
+ setIsVerifying(false);
1136
+ }
1137
+ };
1138
+ const displayDescription = description || defaultDescription;
1139
+ return /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col gap-6 items-center", children: [
1140
+ /* @__PURE__ */ jsxs("div", { className: "w-full bg-neutral-100 dark:bg-neutral-800 rounded-lg px-4 pt-4 pb-6 flex flex-col gap-4", children: [
1141
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-black dark:text-white", children: title }),
1142
+ /* @__PURE__ */ jsx("p", { className: "text-neutral-600 dark:text-neutral-400 text-sm leading-relaxed", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
1143
+ part,
1144
+ index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "font-medium text-black dark:text-white", children: email })
1145
+ ] }, index)) }),
1146
+ method === "code" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 mt-2", children: [
1147
+ /* @__PURE__ */ jsx(
1148
+ AuthVerificationCodeInput,
1149
+ {
1150
+ value: verificationCode,
1151
+ onChange: setVerificationCode,
1152
+ email,
1153
+ disabled: isVerifying,
1154
+ onComplete: (code) => {
1155
+ void handleVerifyCode(code);
1156
+ }
1157
+ }
1158
+ ),
1159
+ verificationError && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 dark:text-red-400 text-center", children: verificationError }),
1160
+ isVerifying && /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 text-center", children: "Verifying..." })
1161
+ ] })
1162
+ ] }),
1163
+ /* @__PURE__ */ jsxs("div", { className: "w-full text-sm text-center text-neutral-600 dark:text-neutral-400", children: [
1164
+ "Didn't receive the email?",
1165
+ " ",
1166
+ /* @__PURE__ */ jsx(
1167
+ "button",
1168
+ {
1169
+ onClick: () => {
1170
+ void handleResend();
1171
+ },
1172
+ disabled: resendDisabled || isSending,
1173
+ className: "text-black dark:text-white font-medium transition-colors disabled:cursor-not-allowed cursor-pointer hover:underline disabled:no-underline disabled:opacity-50",
1174
+ children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
1175
+ }
1176
+ )
1177
+ ] })
1178
+ ] });
1179
+ }
1110
1180
  function SignInForm({
1111
1181
  email,
1112
1182
  password,
@@ -1271,6 +1341,7 @@ function SignIn({
1271
1341
  const [password, setPassword] = useState("");
1272
1342
  const [error, setError] = useState("");
1273
1343
  const [loading, setLoading] = useState(false);
1344
+ const [step, setStep] = useState("form");
1274
1345
  const [oauthLoading, setOauthLoading] = useState(
1275
1346
  null
1276
1347
  );
@@ -1282,6 +1353,11 @@ function SignIn({
1282
1353
  try {
1283
1354
  const result = await signIn(email, password);
1284
1355
  if ("error" in result) {
1356
+ if (result.statusCode === 403) {
1357
+ setStep("awaiting-verification");
1358
+ setLoading(false);
1359
+ return;
1360
+ }
1285
1361
  throw new Error(result.error);
1286
1362
  }
1287
1363
  const { user, accessToken } = result;
@@ -1296,6 +1372,21 @@ function SignIn({
1296
1372
  setLoading(false);
1297
1373
  }
1298
1374
  }
1375
+ async function handleVerifyCode(code) {
1376
+ try {
1377
+ const result = await insforge.auth.verifyEmail({ email, otp: code });
1378
+ if (result.error) {
1379
+ throw new Error(result.error.message || "Verification failed");
1380
+ }
1381
+ if (result.data?.accessToken) {
1382
+ if (onSuccess && result.data.user) {
1383
+ onSuccess(result.data.user, result.data.accessToken);
1384
+ }
1385
+ }
1386
+ } catch (err) {
1387
+ throw new Error(err.message || "Invalid verification code");
1388
+ }
1389
+ }
1299
1390
  async function handleOAuth(provider) {
1300
1391
  try {
1301
1392
  setOauthLoading(provider);
@@ -1314,7 +1405,7 @@ function SignIn({
1314
1405
  if (!emailConfig) {
1315
1406
  return null;
1316
1407
  }
1317
- return /* @__PURE__ */ jsx(
1408
+ return step === "form" ? /* @__PURE__ */ jsx(
1318
1409
  SignInForm,
1319
1410
  {
1320
1411
  email,
@@ -1330,6 +1421,12 @@ function SignIn({
1330
1421
  emailAuthConfig: emailConfig,
1331
1422
  ...uiProps
1332
1423
  }
1424
+ ) : /* @__PURE__ */ jsx(
1425
+ AuthEmailVerificationStep,
1426
+ {
1427
+ email,
1428
+ onVerifyCode: handleVerifyCode
1429
+ }
1333
1430
  );
1334
1431
  }
1335
1432
  function SignUpForm({
@@ -1480,6 +1577,77 @@ function SignUpForm({
1480
1577
  }
1481
1578
  );
1482
1579
  }
1580
+ var emailSchema = z.string().min(1, "Email is required").email("Invalid email address");
1581
+ function createPasswordSchema(options) {
1582
+ const {
1583
+ minLength = 6,
1584
+ requireUppercase = false,
1585
+ requireLowercase = false,
1586
+ requireNumber = false,
1587
+ requireSpecialChar = false
1588
+ } = options || {};
1589
+ let schema = z.string().min(minLength, `Password must be at least ${minLength} characters`);
1590
+ if (requireUppercase) {
1591
+ schema = schema.regex(/[A-Z]/, "Password must contain at least one uppercase letter");
1592
+ }
1593
+ if (requireLowercase) {
1594
+ schema = schema.regex(/[a-z]/, "Password must contain at least one lowercase letter");
1595
+ }
1596
+ if (requireNumber) {
1597
+ schema = schema.regex(/\d/, "Password must contain at least one number");
1598
+ }
1599
+ if (requireSpecialChar) {
1600
+ schema = schema.regex(
1601
+ /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/,
1602
+ "Password must contain at least one special character"
1603
+ );
1604
+ }
1605
+ return schema;
1606
+ }
1607
+ var passwordSchema = createPasswordSchema();
1608
+ function validateEmail(email) {
1609
+ const result = emailSchema.safeParse(email);
1610
+ if (result.success) {
1611
+ return { valid: true };
1612
+ }
1613
+ return { valid: false, error: result.error.message };
1614
+ }
1615
+ function validatePassword(password, options) {
1616
+ const schema = createPasswordSchema(options);
1617
+ const result = schema.safeParse(password);
1618
+ if (result.success) {
1619
+ return { valid: true };
1620
+ }
1621
+ return { valid: false, error: result.error.message };
1622
+ }
1623
+ function checkPasswordStrength(password) {
1624
+ const feedback = [];
1625
+ let score = 0;
1626
+ if (password.length >= 8) {
1627
+ score += 1;
1628
+ } else {
1629
+ feedback.push("Use at least 8 characters");
1630
+ }
1631
+ if (password.length >= 12) {
1632
+ score += 1;
1633
+ }
1634
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) {
1635
+ score += 1;
1636
+ } else {
1637
+ feedback.push("Use both uppercase and lowercase letters");
1638
+ }
1639
+ if (/\d/.test(password)) {
1640
+ score += 1;
1641
+ } else {
1642
+ feedback.push("Include at least one number");
1643
+ }
1644
+ if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
1645
+ score += 1;
1646
+ } else {
1647
+ feedback.push("Include at least one special character");
1648
+ }
1649
+ return { score, feedback };
1650
+ }
1483
1651
  function SignUp({
1484
1652
  afterSignUpUrl,
1485
1653
  onSuccess,
@@ -1492,6 +1660,7 @@ function SignUp({
1492
1660
  const [password, setPassword] = useState("");
1493
1661
  const [error, setError] = useState("");
1494
1662
  const [loading, setLoading] = useState(false);
1663
+ const [step, setStep] = useState("form");
1495
1664
  const [oauthLoading, setOauthLoading] = useState(
1496
1665
  null
1497
1666
  );
@@ -1500,19 +1669,46 @@ function SignUp({
1500
1669
  e.preventDefault();
1501
1670
  setLoading(true);
1502
1671
  setError("");
1503
- if (emailConfig && !validatePasswordStrength(password, emailConfig)) {
1504
- setError("Password does not meet all requirements");
1672
+ if (!emailConfig) {
1673
+ setError("Configuration not loaded. Please refresh the page.");
1674
+ setLoading(false);
1675
+ return;
1676
+ }
1677
+ const emailValidation = emailSchema.safeParse(email);
1678
+ if (!emailValidation.success) {
1679
+ const firstError = emailValidation.error.issues[0];
1680
+ setError(firstError.message);
1681
+ setLoading(false);
1682
+ return;
1683
+ }
1684
+ const passwordZodSchema = createPasswordSchema({
1685
+ minLength: emailConfig.passwordMinLength,
1686
+ requireUppercase: emailConfig.requireUppercase,
1687
+ requireLowercase: emailConfig.requireLowercase,
1688
+ requireNumber: emailConfig.requireNumber,
1689
+ requireSpecialChar: emailConfig.requireSpecialChar
1690
+ });
1691
+ const passwordValidation = passwordZodSchema.safeParse(password);
1692
+ if (!passwordValidation.success) {
1693
+ const firstError = passwordValidation.error.issues[0];
1694
+ setError(firstError.message);
1505
1695
  setLoading(false);
1506
1696
  return;
1507
1697
  }
1508
1698
  try {
1509
- const result = await signUp(email, password);
1699
+ const result = await signUp(emailValidation.data, password);
1510
1700
  if ("error" in result) {
1511
1701
  throw new Error(result.error);
1512
1702
  }
1513
- const { user, accessToken } = result;
1514
- if (onSuccess) {
1515
- if (user) onSuccess(user, accessToken || "");
1703
+ if (result.requiresEmailVerification && !result.accessToken) {
1704
+ setStep("awaiting-verification");
1705
+ setLoading(false);
1706
+ return;
1707
+ }
1708
+ if (result.accessToken && result.user) {
1709
+ if (onSuccess) {
1710
+ onSuccess(result.user, result.accessToken);
1711
+ }
1516
1712
  }
1517
1713
  } catch (err) {
1518
1714
  const errorMessage = err.message || "Sign up failed";
@@ -1522,6 +1718,21 @@ function SignUp({
1522
1718
  setLoading(false);
1523
1719
  }
1524
1720
  }
1721
+ async function handleVerifyCode(code) {
1722
+ try {
1723
+ const result = await insforge.auth.verifyEmail({ email, otp: code });
1724
+ if (result.error) {
1725
+ throw new Error(result.error.message || "Verification failed");
1726
+ }
1727
+ if (result.data?.accessToken) {
1728
+ if (onSuccess && result.data.user) {
1729
+ onSuccess(result.data.user, result.data.accessToken);
1730
+ }
1731
+ }
1732
+ } catch (err) {
1733
+ throw new Error(err.message || "Invalid verification code");
1734
+ }
1735
+ }
1525
1736
  async function handleOAuth(provider) {
1526
1737
  try {
1527
1738
  setOauthLoading(provider);
@@ -1540,7 +1751,7 @@ function SignUp({
1540
1751
  if (!emailConfig) {
1541
1752
  return null;
1542
1753
  }
1543
- return /* @__PURE__ */ jsx(
1754
+ return step === "form" ? /* @__PURE__ */ jsx(
1544
1755
  SignUpForm,
1545
1756
  {
1546
1757
  email,
@@ -1556,263 +1767,32 @@ function SignUp({
1556
1767
  emailAuthConfig: emailConfig,
1557
1768
  ...uiProps
1558
1769
  }
1770
+ ) : /* @__PURE__ */ jsx(
1771
+ AuthEmailVerificationStep,
1772
+ {
1773
+ email,
1774
+ onVerifyCode: handleVerifyCode
1775
+ }
1559
1776
  );
1560
1777
  }
1561
- function UserButton({
1562
- afterSignOutUrl = "/",
1563
- mode = "detailed",
1564
- appearance = {}
1565
- }) {
1566
- const { user, signOut } = useInsforge();
1567
- const [isOpen, setIsOpen] = useState(false);
1568
- const [imageError, setImageError] = useState(false);
1569
- const dropdownRef = useRef(null);
1570
- useEffect(() => {
1571
- setImageError(false);
1572
- const avatarUrl = user?.avatarUrl;
1573
- if (!avatarUrl) return;
1574
- const checkImageUrl = async () => {
1575
- try {
1576
- const response = await fetch(avatarUrl, {
1577
- method: "HEAD",
1578
- cache: "no-cache"
1579
- });
1580
- if (!response.ok) {
1581
- setImageError(true);
1582
- }
1583
- } catch (error) {
1584
- setImageError(true);
1585
- }
1586
- };
1587
- checkImageUrl();
1588
- }, [user?.avatarUrl]);
1589
- useEffect(() => {
1590
- function handleClickOutside(event) {
1591
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1592
- setIsOpen(false);
1593
- }
1594
- }
1595
- if (isOpen) {
1596
- document.addEventListener("mousedown", handleClickOutside);
1597
- }
1598
- return () => {
1599
- document.removeEventListener("mousedown", handleClickOutside);
1600
- };
1601
- }, [isOpen]);
1602
- async function handleSignOut() {
1603
- await signOut();
1604
- setIsOpen(false);
1605
- window.location.href = afterSignOutUrl;
1606
- }
1607
- if (!user) return null;
1608
- const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
1609
- return /* @__PURE__ */ jsxs(
1610
- "div",
1611
- {
1612
- className: cn("relative inline-block", appearance.containerClassName),
1613
- ref: dropdownRef,
1614
- children: [
1615
- /* @__PURE__ */ jsxs(
1616
- "button",
1617
- {
1618
- className: cn(
1619
- "p-1 bg-transparent border-0 rounded-full cursor-pointer transition-all duration-200",
1620
- "flex items-center justify-center gap-2",
1621
- "hover:bg-black/5",
1622
- mode === "detailed" && "rounded-lg p-2",
1623
- appearance.buttonClassName
1624
- ),
1625
- onClick: () => setIsOpen(!isOpen),
1626
- "aria-expanded": isOpen,
1627
- "aria-haspopup": "true",
1628
- children: [
1629
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-10 h-10 bg-blue-500 rounded-full", children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
1630
- "img",
1631
- {
1632
- src: user.avatarUrl,
1633
- alt: user.email,
1634
- onError: () => setImageError(true),
1635
- className: "rounded-full object-cover w-full h-full"
1636
- }
1637
- ) : /* @__PURE__ */ jsx("span", { className: "text-white font-semibold text-sm", children: initials }) }),
1638
- mode === "detailed" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-0.5", children: [
1639
- user.name && /* @__PURE__ */ jsx(
1640
- "div",
1641
- {
1642
- className: cn(
1643
- "text-sm font-semibold text-gray-900 leading-5 text-left",
1644
- appearance.nameClassName
1645
- ),
1646
- children: user.name
1647
- }
1648
- ),
1649
- /* @__PURE__ */ jsx(
1650
- "div",
1651
- {
1652
- className: cn(
1653
- "text-xs text-gray-500 leading-4 text-left",
1654
- appearance.emailClassName
1655
- ),
1656
- children: user.email
1657
- }
1658
- )
1659
- ] })
1660
- ]
1661
- }
1662
- ),
1663
- isOpen && /* @__PURE__ */ jsx(
1664
- "div",
1665
- {
1666
- className: cn(
1667
- "absolute top-full right-0 mt-2 min-w-40",
1668
- "bg-white border border-gray-200 rounded-lg",
1669
- "shadow-lg z-50 overflow-hidden p-1",
1670
- appearance.dropdownClassName
1671
- ),
1672
- children: /* @__PURE__ */ jsxs(
1673
- "button",
1674
- {
1675
- onClick: handleSignOut,
1676
- className: "flex items-center justify-start gap-2 w-full px-3 py-2 text-sm font-normal text-red-600 bg-transparent border-0 rounded-md cursor-pointer transition-colors hover:bg-red-50 text-left",
1677
- children: [
1678
- /* @__PURE__ */ jsx(LogOut, { className: "w-5 h-5" }),
1679
- "Sign out"
1680
- ]
1681
- }
1682
- )
1683
- }
1684
- )
1685
- ]
1686
- }
1687
- );
1688
- }
1689
- function Protect({
1690
- children,
1691
- fallback,
1692
- redirectTo = "/sign-in",
1693
- condition,
1694
- onRedirect
1695
- }) {
1696
- const { isSignedIn, isLoaded, user } = useInsforge();
1697
- useEffect(() => {
1698
- if (isLoaded && !isSignedIn) {
1699
- if (onRedirect) {
1700
- onRedirect(redirectTo);
1701
- } else {
1702
- window.location.href = redirectTo;
1703
- }
1704
- } else if (isLoaded && isSignedIn && condition && user) {
1705
- if (!condition(user)) {
1706
- if (onRedirect) {
1707
- onRedirect(redirectTo);
1708
- } else {
1709
- window.location.href = redirectTo;
1710
- }
1711
- }
1712
- }
1713
- }, [isLoaded, isSignedIn, redirectTo, condition, user, onRedirect]);
1714
- if (!isLoaded) {
1715
- return fallback || /* @__PURE__ */ jsx("div", { className: "insforge-loading", children: "Loading..." });
1716
- }
1717
- if (!isSignedIn) {
1718
- return fallback || null;
1719
- }
1720
- if (condition && user && !condition(user)) {
1721
- return fallback || null;
1722
- }
1723
- return /* @__PURE__ */ jsx(Fragment, { children });
1724
- }
1725
- function SignedIn({ children }) {
1726
- const { isSignedIn, isLoaded } = useInsforge();
1727
- if (!isLoaded) return null;
1728
- if (!isSignedIn) return null;
1729
- return /* @__PURE__ */ jsx(Fragment, { children });
1730
- }
1731
- function SignedOut({ children }) {
1732
- const { isSignedIn, isLoaded } = useInsforge();
1733
- if (!isLoaded) return null;
1734
- if (isSignedIn) return null;
1735
- return /* @__PURE__ */ jsx(Fragment, { children });
1736
- }
1737
- function InsforgeCallback({
1738
- redirectTo = "/",
1739
- onSuccess,
1740
- onError,
1741
- loadingComponent,
1742
- onRedirect
1743
- }) {
1744
- const isProcessingRef = useRef(false);
1745
- const { isLoaded, isSignedIn } = useInsforge();
1746
- useEffect(() => {
1747
- if (!isLoaded) return;
1748
- if (isProcessingRef.current) return;
1749
- isProcessingRef.current = true;
1750
- const processCallback = async () => {
1751
- const searchParams = new URLSearchParams(window.location.search);
1752
- const error = searchParams.get("error");
1753
- if (error) {
1754
- if (onError) {
1755
- onError(error);
1756
- } else {
1757
- const errorUrl = "/?error=" + encodeURIComponent(error);
1758
- if (onRedirect) {
1759
- onRedirect(errorUrl);
1760
- } else {
1761
- window.location.href = errorUrl;
1762
- }
1763
- }
1764
- return;
1765
- }
1766
- if (!isSignedIn) {
1767
- const errorMsg = "authentication_failed";
1768
- if (onError) {
1769
- onError(errorMsg);
1770
- } else {
1771
- const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
1772
- if (onRedirect) {
1773
- onRedirect(errorUrl);
1774
- } else {
1775
- window.location.href = errorUrl;
1776
- }
1777
- }
1778
- return;
1779
- }
1780
- window.history.replaceState({}, "", window.location.pathname);
1781
- if (onSuccess) {
1782
- onSuccess();
1783
- }
1784
- if (onRedirect) {
1785
- onRedirect(redirectTo);
1786
- } else {
1787
- window.location.href = redirectTo;
1788
- }
1789
- };
1790
- processCallback();
1791
- }, [isLoaded, isSignedIn, redirectTo, onSuccess, onError, onRedirect]);
1792
- const defaultLoading = /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1793
- /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold mb-4", children: "Completing authentication..." }),
1794
- /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto" })
1795
- ] }) });
1796
- return loadingComponent || defaultLoading;
1797
- }
1798
- function ForgotPasswordForm({
1799
- email,
1800
- onEmailChange,
1801
- onSubmit,
1802
- error,
1803
- loading = false,
1804
- success = false,
1805
- appearance = {},
1806
- title = "Forgot Password?",
1807
- subtitle = "Enter your email address and we'll send you a code to reset your password.",
1808
- emailLabel = "Email",
1809
- emailPlaceholder = "example@email.com",
1810
- submitButtonText = "Send Reset Code",
1811
- loadingButtonText = "Sending...",
1812
- backToSignInText = "Remember your password?",
1813
- backToSignInUrl = "/sign-in",
1814
- successTitle = "Check Your Email",
1815
- successMessage
1778
+ function ForgotPasswordForm({
1779
+ email,
1780
+ onEmailChange,
1781
+ onSubmit,
1782
+ error,
1783
+ loading = false,
1784
+ success = false,
1785
+ appearance = {},
1786
+ title = "Forgot Password?",
1787
+ subtitle = "Enter your email address and we'll send you a code to reset your password.",
1788
+ emailLabel = "Email",
1789
+ emailPlaceholder = "example@email.com",
1790
+ submitButtonText = "Send Reset Code",
1791
+ loadingButtonText = "Sending...",
1792
+ backToSignInText = "Remember your password?",
1793
+ backToSignInUrl = "/sign-in",
1794
+ successTitle = "Check Your Email",
1795
+ successMessage
1816
1796
  }) {
1817
1797
  if (success) {
1818
1798
  return /* @__PURE__ */ jsx(
@@ -2026,118 +2006,626 @@ function ResetPasswordForm({
2026
2006
  }
2027
2007
  );
2028
2008
  }
2029
- function VerifyEmailStatus({
2030
- status,
2031
- error,
2032
- appearance = {},
2033
- verifyingTitle = "Verifying your email...",
2034
- successTitle = "Email Verified!",
2035
- successMessage = "Your email has been verified successfully. You can close this page and return to your app.",
2036
- errorTitle = "Verification Failed"
2009
+ function ResetPassword({
2010
+ token,
2011
+ backToSignInUrl = "/sign-in",
2012
+ onSuccess,
2013
+ onError,
2014
+ ...uiProps
2037
2015
  }) {
2038
- if (status === "verifying") {
2039
- return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col items-center justify-center gap-6", children: [
2040
- /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-black dark:text-white", children: verifyingTitle }),
2041
- /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-black dark:border-white" })
2042
- ] }) });
2043
- }
2044
- if (status === "error") {
2045
- return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsx("div", { className: "w-full flex flex-col items-stretch justify-center gap-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start justify-center gap-2", children: [
2046
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-black dark:text-white", children: errorTitle }),
2047
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 leading-relaxed", children: [
2048
- error || "The verification link is invalid or has expired.",
2049
- " Please try again or contact support if the problem persists. You can close this page and return to your app."
2050
- ] })
2051
- ] }) }) });
2052
- }
2053
- return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsx("div", { className: "w-full flex flex-col items-stretch justify-center gap-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
2054
- /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-8 h-8 text-green-600 dark:text-green-400", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" }) }) }),
2055
- /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-black dark:text-white text-center", children: successTitle }),
2056
- /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 text-center", children: successMessage })
2057
- ] }) }) });
2058
- }
2059
-
2060
- // src/hooks/useAuth.ts
2061
- function useAuth() {
2062
- const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();
2063
- return { signIn, signUp, signOut, isLoaded, isSignedIn };
2064
- }
2065
-
2066
- // src/hooks/useUser.ts
2067
- function useUser() {
2068
- const { user, isLoaded, updateUser, setUser } = useInsforge();
2069
- return { user, isLoaded, updateUser, setUser };
2016
+ const { resetPassword } = useInsforge();
2017
+ const { emailConfig } = usePublicAuthConfig();
2018
+ const [newPassword, setNewPassword] = useState("");
2019
+ const [confirmPassword, setConfirmPassword] = useState("");
2020
+ const [error, setError] = useState("");
2021
+ const [loading, setLoading] = useState(false);
2022
+ async function handleSubmit(e) {
2023
+ e.preventDefault();
2024
+ setLoading(true);
2025
+ setError("");
2026
+ if (!emailConfig) {
2027
+ setError("Configuration not loaded. Please refresh the page.");
2028
+ setLoading(false);
2029
+ return;
2030
+ }
2031
+ if (newPassword !== confirmPassword) {
2032
+ setError("Passwords do not match");
2033
+ setLoading(false);
2034
+ return;
2035
+ }
2036
+ if (!token) {
2037
+ setError("Reset token is missing");
2038
+ setLoading(false);
2039
+ return;
2040
+ }
2041
+ const passwordZodSchema = createPasswordSchema({
2042
+ minLength: emailConfig.passwordMinLength,
2043
+ requireUppercase: emailConfig.requireUppercase,
2044
+ requireLowercase: emailConfig.requireLowercase,
2045
+ requireNumber: emailConfig.requireNumber,
2046
+ requireSpecialChar: emailConfig.requireSpecialChar
2047
+ });
2048
+ const passwordValidation = passwordZodSchema.safeParse(newPassword);
2049
+ if (!passwordValidation.success) {
2050
+ const firstError = passwordValidation.error.issues[0];
2051
+ setError(firstError.message);
2052
+ setLoading(false);
2053
+ return;
2054
+ }
2055
+ try {
2056
+ const result = await resetPassword(token, newPassword);
2057
+ if (result?.message) {
2058
+ if (onSuccess) {
2059
+ onSuccess(result.redirectTo);
2060
+ }
2061
+ } else {
2062
+ const errorMessage = "Failed to reset password";
2063
+ setError(errorMessage);
2064
+ if (onError) {
2065
+ onError(new Error(errorMessage));
2066
+ }
2067
+ }
2068
+ } catch (err) {
2069
+ const errorMessage = err.message || "Failed to reset password";
2070
+ setError(errorMessage);
2071
+ if (onError) {
2072
+ onError(new Error(errorMessage));
2073
+ }
2074
+ } finally {
2075
+ setLoading(false);
2076
+ }
2077
+ }
2078
+ if (!emailConfig) {
2079
+ return null;
2080
+ }
2081
+ return /* @__PURE__ */ jsx(
2082
+ ResetPasswordForm,
2083
+ {
2084
+ newPassword,
2085
+ confirmPassword,
2086
+ onNewPasswordChange: setNewPassword,
2087
+ onConfirmPasswordChange: setConfirmPassword,
2088
+ onSubmit: handleSubmit,
2089
+ error,
2090
+ loading,
2091
+ emailAuthConfig: emailConfig,
2092
+ backToSignInUrl,
2093
+ ...uiProps
2094
+ }
2095
+ );
2070
2096
  }
2071
- var emailSchema = z.string().min(1, "Email is required").email("Invalid email address");
2072
- function createPasswordSchema(options) {
2073
- const {
2074
- minLength = 6,
2075
- requireUppercase = false,
2076
- requireLowercase = false,
2077
- requireNumber = false,
2078
- requireSpecialChar = false
2079
- } = options || {};
2080
- let schema = z.string().min(minLength, `Password must be at least ${minLength} characters`);
2081
- if (requireUppercase) {
2082
- schema = schema.regex(/[A-Z]/, "Password must contain at least one uppercase letter");
2097
+ function ForgotPassword({
2098
+ backToSignInUrl = "/sign-in",
2099
+ onSuccess,
2100
+ onError,
2101
+ ...uiProps
2102
+ }) {
2103
+ const { sendPasswordResetCode, baseUrl } = useInsforge();
2104
+ const { emailConfig } = usePublicAuthConfig();
2105
+ const [insforge] = useState(() => createClient({ baseUrl }));
2106
+ const [step, setStep] = useState("email");
2107
+ const [email, setEmail] = useState("");
2108
+ const [verificationCode, setVerificationCode] = useState("");
2109
+ const [resetToken, setResetToken] = useState("");
2110
+ const [error, setError] = useState("");
2111
+ const [loading, setLoading] = useState(false);
2112
+ const [success, setSuccess] = useState(false);
2113
+ const [resendDisabled, setResendDisabled] = useState(true);
2114
+ const [resendCountdown, setResendCountdown] = useState(60);
2115
+ const [isSendingCode, setIsSendingCode] = useState(false);
2116
+ const [isVerifyingCode, setIsVerifyingCode] = useState(false);
2117
+ useEffect(() => {
2118
+ if (resendCountdown > 0 && step === "code") {
2119
+ const timer = setInterval(() => {
2120
+ setResendCountdown((prev) => {
2121
+ if (prev <= 1) {
2122
+ setResendDisabled(false);
2123
+ return 0;
2124
+ }
2125
+ return prev - 1;
2126
+ });
2127
+ }, 1e3);
2128
+ return () => clearInterval(timer);
2129
+ }
2130
+ }, [resendCountdown, step]);
2131
+ async function handleEmailSubmit(e) {
2132
+ e.preventDefault();
2133
+ setLoading(true);
2134
+ setError("");
2135
+ const emailValidation = emailSchema.safeParse(email);
2136
+ if (!emailValidation.success) {
2137
+ const firstError = emailValidation.error.issues[0];
2138
+ setError(firstError.message);
2139
+ setLoading(false);
2140
+ return;
2141
+ }
2142
+ try {
2143
+ const result = await sendPasswordResetCode(emailValidation.data);
2144
+ if (result?.success) {
2145
+ if (emailConfig?.resetPasswordMethod === "link") {
2146
+ setSuccess(true);
2147
+ if (onSuccess) {
2148
+ onSuccess();
2149
+ }
2150
+ } else {
2151
+ setStep("code");
2152
+ setResendDisabled(true);
2153
+ setResendCountdown(60);
2154
+ }
2155
+ } else {
2156
+ const errorMessage = result?.message || "Failed to send reset code";
2157
+ setError(errorMessage);
2158
+ if (onError) {
2159
+ onError(new Error(errorMessage));
2160
+ }
2161
+ }
2162
+ } catch (err) {
2163
+ const errorMessage = err.message || "Failed to send reset code";
2164
+ setError(errorMessage);
2165
+ if (onError) {
2166
+ onError(new Error(errorMessage));
2167
+ }
2168
+ } finally {
2169
+ setLoading(false);
2170
+ }
2083
2171
  }
2084
- if (requireLowercase) {
2085
- schema = schema.regex(/[a-z]/, "Password must contain at least one lowercase letter");
2172
+ async function handleVerifyCode(code) {
2173
+ setIsVerifyingCode(true);
2174
+ setError("");
2175
+ setVerificationCode(code);
2176
+ try {
2177
+ const result = await insforge.auth.verifyResetPasswordCode({ email, code });
2178
+ if (result.error) {
2179
+ throw new Error(result.error.message || "Failed to verify code");
2180
+ }
2181
+ if (result.data) {
2182
+ setResetToken(result.data.resetToken);
2183
+ setStep("password");
2184
+ }
2185
+ } catch (err) {
2186
+ setError(err.message || "Invalid verification code");
2187
+ setVerificationCode("");
2188
+ } finally {
2189
+ setIsVerifyingCode(false);
2190
+ }
2086
2191
  }
2087
- if (requireNumber) {
2088
- schema = schema.regex(/\d/, "Password must contain at least one number");
2192
+ const handleResendCode = useCallback(async () => {
2193
+ setResendDisabled(true);
2194
+ setResendCountdown(60);
2195
+ setIsSendingCode(true);
2196
+ setError("");
2197
+ try {
2198
+ await sendPasswordResetCode(email);
2199
+ } catch (err) {
2200
+ setError(err.message || "Failed to resend code");
2201
+ setResendDisabled(false);
2202
+ setResendCountdown(0);
2203
+ } finally {
2204
+ setIsSendingCode(false);
2205
+ }
2206
+ }, [email, sendPasswordResetCode]);
2207
+ function handlePasswordResetSuccess() {
2208
+ if (onSuccess) {
2209
+ onSuccess();
2210
+ }
2089
2211
  }
2090
- if (requireSpecialChar) {
2091
- schema = schema.regex(
2092
- /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/,
2093
- "Password must contain at least one special character"
2212
+ if (!emailConfig) {
2213
+ return null;
2214
+ }
2215
+ if (step === "email") {
2216
+ return /* @__PURE__ */ jsx(
2217
+ ForgotPasswordForm,
2218
+ {
2219
+ email,
2220
+ onEmailChange: setEmail,
2221
+ onSubmit: handleEmailSubmit,
2222
+ error,
2223
+ loading,
2224
+ success,
2225
+ backToSignInUrl,
2226
+ ...uiProps
2227
+ }
2094
2228
  );
2095
2229
  }
2096
- return schema;
2097
- }
2098
- var passwordSchema = createPasswordSchema();
2099
- function validateEmail(email) {
2100
- const result = emailSchema.safeParse(email);
2101
- if (result.success) {
2102
- return { valid: true };
2230
+ if (step === "code") {
2231
+ return /* @__PURE__ */ jsxs(
2232
+ AuthContainer,
2233
+ {
2234
+ appearance: {
2235
+ containerClassName: uiProps.appearance?.container,
2236
+ cardClassName: uiProps.appearance?.card
2237
+ },
2238
+ children: [
2239
+ /* @__PURE__ */ jsx(
2240
+ AuthHeader,
2241
+ {
2242
+ title: "Enter Reset Code",
2243
+ subtitle: `We've sent a 6-digit verification code to ${email}. Please enter it below to reset your password. The code will expire in 10 minutes.`,
2244
+ appearance: {
2245
+ containerClassName: uiProps.appearance?.header?.container,
2246
+ titleClassName: uiProps.appearance?.header?.title,
2247
+ subtitleClassName: uiProps.appearance?.header?.subtitle
2248
+ }
2249
+ }
2250
+ ),
2251
+ /* @__PURE__ */ jsx(AuthErrorBanner, { error, className: uiProps.appearance?.errorBanner }),
2252
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col gap-6 items-center", children: [
2253
+ /* @__PURE__ */ jsx("div", { className: "w-full bg-neutral-100 dark:bg-neutral-800 rounded-lg px-4 pt-4 pb-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 mt-2", children: [
2254
+ /* @__PURE__ */ jsx(
2255
+ AuthVerificationCodeInput,
2256
+ {
2257
+ value: verificationCode,
2258
+ onChange: setVerificationCode,
2259
+ email,
2260
+ disabled: isVerifyingCode,
2261
+ onComplete: (code) => {
2262
+ void handleVerifyCode(code);
2263
+ }
2264
+ }
2265
+ ),
2266
+ isVerifyingCode && /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 text-center", children: "Verifying..." })
2267
+ ] }) }),
2268
+ /* @__PURE__ */ jsxs("div", { className: "w-full text-sm text-center text-neutral-600 dark:text-neutral-400", children: [
2269
+ "Didn't receive the email?",
2270
+ " ",
2271
+ /* @__PURE__ */ jsx(
2272
+ "button",
2273
+ {
2274
+ onClick: () => {
2275
+ void handleResendCode();
2276
+ },
2277
+ disabled: resendDisabled || isSendingCode,
2278
+ className: "text-black dark:text-white font-medium transition-colors disabled:cursor-not-allowed cursor-pointer hover:underline disabled:no-underline disabled:opacity-50",
2279
+ children: isSendingCode ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
2280
+ }
2281
+ )
2282
+ ] })
2283
+ ] }),
2284
+ /* @__PURE__ */ jsx("p", { className: "text-center text-sm text-gray-600 dark:text-gray-400", children: /* @__PURE__ */ jsx("a", { href: backToSignInUrl, className: "text-black dark:text-white font-medium", children: "Back to Sign In" }) })
2285
+ ]
2286
+ }
2287
+ );
2103
2288
  }
2104
- return { valid: false, error: result.error.message };
2289
+ return /* @__PURE__ */ jsx(
2290
+ ResetPassword,
2291
+ {
2292
+ token: resetToken,
2293
+ backToSignInUrl,
2294
+ onSuccess: handlePasswordResetSuccess,
2295
+ onError,
2296
+ appearance: uiProps.appearance
2297
+ }
2298
+ );
2105
2299
  }
2106
- function validatePassword(password, options) {
2107
- const schema = createPasswordSchema(options);
2108
- const result = schema.safeParse(password);
2109
- if (result.success) {
2110
- return { valid: true };
2300
+ function VerifyEmailStatus({
2301
+ status,
2302
+ error,
2303
+ appearance = {},
2304
+ verifyingTitle = "Verifying your email...",
2305
+ successTitle = "Email Verified!",
2306
+ successMessage = "Your email has been verified successfully. You can close this page and return to your app.",
2307
+ errorTitle = "Verification Failed"
2308
+ }) {
2309
+ if (status === "verifying") {
2310
+ return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col items-center justify-center gap-6", children: [
2311
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-black dark:text-white", children: verifyingTitle }),
2312
+ /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-black dark:border-white" })
2313
+ ] }) });
2111
2314
  }
2112
- return { valid: false, error: result.error.message };
2113
- }
2114
- function checkPasswordStrength(password) {
2115
- const feedback = [];
2116
- let score = 0;
2117
- if (password.length >= 8) {
2118
- score += 1;
2119
- } else {
2120
- feedback.push("Use at least 8 characters");
2315
+ if (status === "error") {
2316
+ return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsx("div", { className: "w-full flex flex-col items-stretch justify-center gap-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start justify-center gap-2", children: [
2317
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-black dark:text-white", children: errorTitle }),
2318
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 leading-relaxed", children: [
2319
+ error || "The verification link is invalid or has expired.",
2320
+ " Please try again or contact support if the problem persists. You can close this page and return to your app."
2321
+ ] })
2322
+ ] }) }) });
2121
2323
  }
2122
- if (password.length >= 12) {
2123
- score += 1;
2324
+ return /* @__PURE__ */ jsx(AuthContainer, { appearance, children: /* @__PURE__ */ jsx("div", { className: "w-full flex flex-col items-stretch justify-center gap-6", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
2325
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-8 h-8 text-green-600 dark:text-green-400", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" }) }) }),
2326
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-black dark:text-white text-center", children: successTitle }),
2327
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400 text-center", children: successMessage })
2328
+ ] }) }) });
2329
+ }
2330
+ function VerifyEmail({
2331
+ token,
2332
+ onSuccess,
2333
+ onError,
2334
+ ...uiProps
2335
+ }) {
2336
+ const { verifyEmail } = useInsforge();
2337
+ const [status, setStatus] = useState("verifying");
2338
+ const [error, setError] = useState("");
2339
+ useEffect(() => {
2340
+ const verifyEmailFn = async () => {
2341
+ if (!token) {
2342
+ const errorMessage = "Invalid verification link. Missing required token.";
2343
+ setError(errorMessage);
2344
+ setStatus("error");
2345
+ if (onError) {
2346
+ onError(new Error(errorMessage));
2347
+ }
2348
+ return;
2349
+ }
2350
+ try {
2351
+ const result = await verifyEmail(token);
2352
+ if (!result?.accessToken) {
2353
+ const errorMessage = result ? "Verification succeeded but no access token received" : "Email verification failed";
2354
+ setError(errorMessage);
2355
+ setStatus("error");
2356
+ if (onError) {
2357
+ onError(new Error(errorMessage));
2358
+ }
2359
+ return;
2360
+ }
2361
+ setStatus("success");
2362
+ if (onSuccess) {
2363
+ onSuccess({
2364
+ accessToken: result.accessToken,
2365
+ user: result.user
2366
+ });
2367
+ }
2368
+ } catch (err) {
2369
+ const errorMessage = err.message || "Email verification failed";
2370
+ setError(errorMessage);
2371
+ setStatus("error");
2372
+ if (onError) {
2373
+ onError(new Error(errorMessage));
2374
+ }
2375
+ }
2376
+ };
2377
+ void verifyEmailFn();
2378
+ }, [token, verifyEmail, onSuccess, onError]);
2379
+ return /* @__PURE__ */ jsx(VerifyEmailStatus, { status, error, ...uiProps });
2380
+ }
2381
+ function UserButton({
2382
+ afterSignOutUrl = "/",
2383
+ mode = "detailed",
2384
+ appearance = {}
2385
+ }) {
2386
+ const { user, signOut } = useInsforge();
2387
+ const [isOpen, setIsOpen] = useState(false);
2388
+ const [imageError, setImageError] = useState(false);
2389
+ const dropdownRef = useRef(null);
2390
+ useEffect(() => {
2391
+ setImageError(false);
2392
+ const avatarUrl = user?.avatarUrl;
2393
+ if (!avatarUrl) return;
2394
+ const checkImageUrl = async () => {
2395
+ try {
2396
+ const response = await fetch(avatarUrl, {
2397
+ method: "HEAD",
2398
+ cache: "no-cache"
2399
+ });
2400
+ if (!response.ok) {
2401
+ setImageError(true);
2402
+ }
2403
+ } catch (error) {
2404
+ setImageError(true);
2405
+ }
2406
+ };
2407
+ checkImageUrl();
2408
+ }, [user?.avatarUrl]);
2409
+ useEffect(() => {
2410
+ function handleClickOutside(event) {
2411
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2412
+ setIsOpen(false);
2413
+ }
2414
+ }
2415
+ if (isOpen) {
2416
+ document.addEventListener("mousedown", handleClickOutside);
2417
+ }
2418
+ return () => {
2419
+ document.removeEventListener("mousedown", handleClickOutside);
2420
+ };
2421
+ }, [isOpen]);
2422
+ async function handleSignOut() {
2423
+ await signOut();
2424
+ setIsOpen(false);
2425
+ window.location.href = afterSignOutUrl;
2124
2426
  }
2125
- if (/[a-z]/.test(password) && /[A-Z]/.test(password)) {
2126
- score += 1;
2127
- } else {
2128
- feedback.push("Use both uppercase and lowercase letters");
2427
+ if (!user) return null;
2428
+ const initials = user.name ? user.name.charAt(0).toUpperCase() : user.email.split("@")[0].slice(0, 2).toUpperCase();
2429
+ return /* @__PURE__ */ jsxs(
2430
+ "div",
2431
+ {
2432
+ className: cn("relative inline-block", appearance.containerClassName),
2433
+ ref: dropdownRef,
2434
+ children: [
2435
+ /* @__PURE__ */ jsxs(
2436
+ "button",
2437
+ {
2438
+ className: cn(
2439
+ "p-1 bg-transparent border-0 rounded-full cursor-pointer transition-all duration-200",
2440
+ "flex items-center justify-center gap-2",
2441
+ "hover:bg-black/5",
2442
+ mode === "detailed" && "rounded-lg p-2",
2443
+ appearance.buttonClassName
2444
+ ),
2445
+ onClick: () => setIsOpen(!isOpen),
2446
+ "aria-expanded": isOpen,
2447
+ "aria-haspopup": "true",
2448
+ children: [
2449
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-10 h-10 bg-blue-500 rounded-full", children: user.avatarUrl && !imageError ? /* @__PURE__ */ jsx(
2450
+ "img",
2451
+ {
2452
+ src: user.avatarUrl,
2453
+ alt: user.email,
2454
+ onError: () => setImageError(true),
2455
+ className: "rounded-full object-cover w-full h-full"
2456
+ }
2457
+ ) : /* @__PURE__ */ jsx("span", { className: "text-white font-semibold text-sm", children: initials }) }),
2458
+ mode === "detailed" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-0.5", children: [
2459
+ user.name && /* @__PURE__ */ jsx(
2460
+ "div",
2461
+ {
2462
+ className: cn(
2463
+ "text-sm font-semibold text-gray-900 leading-5 text-left",
2464
+ appearance.nameClassName
2465
+ ),
2466
+ children: user.name
2467
+ }
2468
+ ),
2469
+ /* @__PURE__ */ jsx(
2470
+ "div",
2471
+ {
2472
+ className: cn(
2473
+ "text-xs text-gray-500 leading-4 text-left",
2474
+ appearance.emailClassName
2475
+ ),
2476
+ children: user.email
2477
+ }
2478
+ )
2479
+ ] })
2480
+ ]
2481
+ }
2482
+ ),
2483
+ isOpen && /* @__PURE__ */ jsx(
2484
+ "div",
2485
+ {
2486
+ className: cn(
2487
+ "absolute top-full right-0 mt-2 min-w-40",
2488
+ "bg-white border border-gray-200 rounded-lg",
2489
+ "shadow-lg z-50 overflow-hidden p-1",
2490
+ appearance.dropdownClassName
2491
+ ),
2492
+ children: /* @__PURE__ */ jsxs(
2493
+ "button",
2494
+ {
2495
+ onClick: handleSignOut,
2496
+ className: "flex items-center justify-start gap-2 w-full px-3 py-2 text-sm font-normal text-red-600 bg-transparent border-0 rounded-md cursor-pointer transition-colors hover:bg-red-50 text-left",
2497
+ children: [
2498
+ /* @__PURE__ */ jsx(LogOut, { className: "w-5 h-5" }),
2499
+ "Sign out"
2500
+ ]
2501
+ }
2502
+ )
2503
+ }
2504
+ )
2505
+ ]
2506
+ }
2507
+ );
2508
+ }
2509
+ function Protect({
2510
+ children,
2511
+ fallback,
2512
+ redirectTo = "/sign-in",
2513
+ condition,
2514
+ onRedirect
2515
+ }) {
2516
+ const { isSignedIn, isLoaded, user } = useInsforge();
2517
+ useEffect(() => {
2518
+ if (isLoaded && !isSignedIn) {
2519
+ if (onRedirect) {
2520
+ onRedirect(redirectTo);
2521
+ } else {
2522
+ window.location.href = redirectTo;
2523
+ }
2524
+ } else if (isLoaded && isSignedIn && condition && user) {
2525
+ if (!condition(user)) {
2526
+ if (onRedirect) {
2527
+ onRedirect(redirectTo);
2528
+ } else {
2529
+ window.location.href = redirectTo;
2530
+ }
2531
+ }
2532
+ }
2533
+ }, [isLoaded, isSignedIn, redirectTo, condition, user, onRedirect]);
2534
+ if (!isLoaded) {
2535
+ return fallback || /* @__PURE__ */ jsx("div", { className: "insforge-loading", children: "Loading..." });
2129
2536
  }
2130
- if (/\d/.test(password)) {
2131
- score += 1;
2132
- } else {
2133
- feedback.push("Include at least one number");
2537
+ if (!isSignedIn) {
2538
+ return fallback || null;
2134
2539
  }
2135
- if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
2136
- score += 1;
2137
- } else {
2138
- feedback.push("Include at least one special character");
2540
+ if (condition && user && !condition(user)) {
2541
+ return fallback || null;
2139
2542
  }
2140
- return { score, feedback };
2543
+ return /* @__PURE__ */ jsx(Fragment, { children });
2544
+ }
2545
+ function SignedIn({ children }) {
2546
+ const { isSignedIn, isLoaded } = useInsforge();
2547
+ if (!isLoaded) return null;
2548
+ if (!isSignedIn) return null;
2549
+ return /* @__PURE__ */ jsx(Fragment, { children });
2550
+ }
2551
+ function SignedOut({ children }) {
2552
+ const { isSignedIn, isLoaded } = useInsforge();
2553
+ if (!isLoaded) return null;
2554
+ if (isSignedIn) return null;
2555
+ return /* @__PURE__ */ jsx(Fragment, { children });
2556
+ }
2557
+ function InsforgeCallback({
2558
+ redirectTo = "/",
2559
+ onSuccess,
2560
+ onError,
2561
+ loadingComponent,
2562
+ onRedirect
2563
+ }) {
2564
+ const isProcessingRef = useRef(false);
2565
+ const { isLoaded, isSignedIn } = useInsforge();
2566
+ useEffect(() => {
2567
+ if (!isLoaded) return;
2568
+ if (isProcessingRef.current) return;
2569
+ isProcessingRef.current = true;
2570
+ const processCallback = async () => {
2571
+ const searchParams = new URLSearchParams(window.location.search);
2572
+ const error = searchParams.get("error");
2573
+ if (error) {
2574
+ if (onError) {
2575
+ onError(error);
2576
+ } else {
2577
+ const errorUrl = "/?error=" + encodeURIComponent(error);
2578
+ if (onRedirect) {
2579
+ onRedirect(errorUrl);
2580
+ } else {
2581
+ window.location.href = errorUrl;
2582
+ }
2583
+ }
2584
+ return;
2585
+ }
2586
+ if (!isSignedIn) {
2587
+ const errorMsg = "authentication_failed";
2588
+ if (onError) {
2589
+ onError(errorMsg);
2590
+ } else {
2591
+ const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
2592
+ if (onRedirect) {
2593
+ onRedirect(errorUrl);
2594
+ } else {
2595
+ window.location.href = errorUrl;
2596
+ }
2597
+ }
2598
+ return;
2599
+ }
2600
+ window.history.replaceState({}, "", window.location.pathname);
2601
+ if (onSuccess) {
2602
+ onSuccess();
2603
+ }
2604
+ if (onRedirect) {
2605
+ onRedirect(redirectTo);
2606
+ } else {
2607
+ window.location.href = redirectTo;
2608
+ }
2609
+ };
2610
+ processCallback();
2611
+ }, [isLoaded, isSignedIn, redirectTo, onSuccess, onError, onRedirect]);
2612
+ const defaultLoading = /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
2613
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold mb-4", children: "Completing authentication..." }),
2614
+ /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto" })
2615
+ ] }) });
2616
+ return loadingComponent || defaultLoading;
2617
+ }
2618
+
2619
+ // src/hooks/useAuth.ts
2620
+ function useAuth() {
2621
+ const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();
2622
+ return { signIn, signUp, signOut, isLoaded, isSignedIn };
2623
+ }
2624
+
2625
+ // src/hooks/useUser.ts
2626
+ function useUser() {
2627
+ const { user, isLoaded, updateUser, setUser } = useInsforge();
2628
+ return { user, isLoaded, updateUser, setUser };
2141
2629
  }
2142
2630
  function RedirectToAuth({ baseUrl, path }) {
2143
2631
  useEffect(() => {
@@ -2189,6 +2677,6 @@ function getInsforgeRoutes(config) {
2189
2677
  return routes;
2190
2678
  }
2191
2679
 
2192
- export { AuthBranding, AuthContainer, AuthDivider, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthSubmitButton, AuthVerificationCodeInput, ForgotPasswordForm, InsforgeCallback, InsforgeProvider, OAUTH_PROVIDER_CONFIG, Protect, ResetPasswordForm, SignIn, SignInForm, SignUp, SignUpForm, SignedIn, SignedOut, UserButton, VerifyEmailStatus, checkPasswordStrength, cn, createPasswordSchema, emailSchema, getAllProviderConfigs, getInsforgeRoutes, getProviderConfig, passwordSchema, useAuth, useInsforge, usePublicAuthConfig, useUser, validateEmail, validatePassword, validatePasswordStrength };
2680
+ export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthSubmitButton, AuthVerificationCodeInput, ForgotPassword, ForgotPasswordForm, InsforgeCallback, InsforgeProvider, OAUTH_PROVIDER_CONFIG, Protect, ResetPassword, ResetPasswordForm, SignIn, SignInForm, SignUp, SignUpForm, SignedIn, SignedOut, UserButton, VerifyEmail, VerifyEmailStatus, checkPasswordStrength, cn, createPasswordSchema, emailSchema, getAllProviderConfigs, getInsforgeRoutes, getProviderConfig, passwordSchema, useAuth, useInsforge, usePublicAuthConfig, useUser, validateEmail, validatePassword, validatePasswordStrength };
2193
2681
  //# sourceMappingURL=index.mjs.map
2194
2682
  //# sourceMappingURL=index.mjs.map