@adriansteffan/reactive 0.0.21 → 0.0.22

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/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-blue-400:oklch(.707 .165 254.624);--color-blue-500:oklch(.623 .214 259.815);--color-blue-600:oklch(.546 .245 262.881);--color-gray-200:oklch(.928 .006 264.531);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-2xl:42rem;--container-4xl:56rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-semibold:600;--font-weight-bold:700;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-font-feature-settings:var(--font-sans--font-feature-settings);--default-font-variation-settings:var(--font-sans--font-variation-settings);--default-mono-font-family:var(--font-mono);--default-mono-font-feature-settings:var(--font-mono--font-feature-settings);--default-mono-font-variation-settings:var(--font-mono--font-variation-settings);--font-sans:Atkinson Hyperlegible,sans-serif;--animate-slide-down:slideDown .8s ease-out forwards;--animate-fade-in:fadeIn .5s ease-out forwards}}@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%;-moz-tab-size:4;-o-tab-size:4;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}body{line-height:inherit}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;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}::-moz-placeholder{opacity:1;color:color-mix(in oklab,currentColor 50%,transparent)}::placeholder{opacity:1;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}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*,:after,:before,::backdrop{border-color:var(--color-gray-200,currentColor)}::file-selector-button{border-color:var(--color-gray-200,currentColor)}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.visible\!{visibility:visible!important}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.-z-10{z-index:-10}.z-1{z-index:1}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.me-1{margin-inline-end:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-8{margin-top:calc(var(--spacing)*8)}.mt-16{margin-top:calc(var(--spacing)*16)}.mt-20{margin-top:calc(var(--spacing)*20)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-20{margin-bottom:calc(var(--spacing)*20)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-12{height:calc(var(--spacing)*12)}.h-full{height:100%}.max-h-60{max-height:calc(var(--spacing)*60)}.min-h-10{min-height:calc(var(--spacing)*10)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-64{width:calc(var(--spacing)*64)}.w-258{width:calc(var(--spacing)*258)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-md{max-width:var(--container-md)}.max-w-prose{max-width:65ch}.flex-1{flex:1}.translate-x-1{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-1{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.animate-fade-in{animation:var(--animate-fade-in)}.animate-pulse{animation:var(--animate-pulse)}.animate-slide-down{animation:var(--animate-slide-down)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*4)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-black{border-color:var(--color-black)}.border-blue-500{border-color:var(--color-blue-500)}.border-t-transparent{border-top-color:#0000}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-red-500{background-color:var(--color-red-500)}.bg-white{background-color:var(--color-white)}.bg-\[radial-gradient\(\#e5e7eb_1px\,transparent_1px\)\]{background-image:radial-gradient(#e5e7eb 1px,#0000 1px)}.\[background-size\:16px_16px\]{background-size:16px 16px}.p-1{padding:calc(var(--spacing)*1)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.px-10{padding-inline:calc(var(--spacing)*10)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.text-center{text-align:center}.text-left{text-align:left}.font-sans{font-family:var(--font-sans)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--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-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.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-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-black{color:var(--color-black)}.text-blue-400{color:var(--color-blue-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.shadow-\[2px_2px_0px_0px_rgba\(0\,0\,0\,1\)\]{--tw-shadow:2px 2px 0px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[2px_2px_0px_rgba\(0\,0\,0\,1\)\]{--tw-shadow:2px 2px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:translate-x-\[2px\]:hover{--tw-translate-x:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:translate-y-\[2px\]:hover{--tw-translate-y:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:bg-black:hover{background-color:var(--color-black)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:text-white:hover{color:var(--color-white)}.hover\:shadow-\[1px_1px_0px_0px_rgba\(0\,0\,0\,1\)\]:hover{--tw-shadow:1px 1px 0px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-none:hover{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.active\:translate-x-1:active{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.active\:translate-y-1:active{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.active\:shadow-none:active{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}@media (width>=40rem){.sm\:mt-12{margin-top:calc(var(--spacing)*12)}}}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}:root{--font-atkinson:"Atkinson Hyperlegible",system-ui,sans-serif}*{-webkit-touch-callout:none}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf)format("truetype");font-weight:400;font-style:normal}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf)format("truetype");font-weight:700;font-style:normal}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf)format("truetype");font-weight:400;font-style:italic}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf)format("truetype");font-weight:700;font-style:italic}.sd-root-modern{background-image:radial-gradient(#e5e7eb 1px,#0000 1px);background-size:16px 16px;font-family:Atkinson Hyperlegible,sans-serif;position:relative;background-color:#fff!important}.sd-root-modern *{font-family:Atkinson Hyperlegible,sans-serif}.sd-row,.sd-clearfix{padding-bottom:20px!important}@media (width<=639px){.sd-imagepicker__item--inline{margin-top:10px;margin-left:auto;margin-right:auto}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}/*!
1
+ /*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-blue-400:oklch(.707 .165 254.624);--color-blue-500:oklch(.623 .214 259.815);--color-blue-600:oklch(.546 .245 262.881);--color-gray-200:oklch(.928 .006 264.531);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-2xl:42rem;--container-4xl:56rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-semibold:600;--font-weight-bold:700;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-font-feature-settings:var(--font-sans--font-feature-settings);--default-font-variation-settings:var(--font-sans--font-variation-settings);--default-mono-font-family:var(--font-mono);--default-mono-font-feature-settings:var(--font-mono--font-feature-settings);--default-mono-font-variation-settings:var(--font-mono--font-variation-settings);--font-sans:Atkinson Hyperlegible,sans-serif;--animate-slide-down:slideDown .8s ease-out forwards;--animate-fade-in:fadeIn .5s ease-out forwards}}@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%;-moz-tab-size:4;-o-tab-size:4;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}body{line-height:inherit}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;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}::-moz-placeholder{opacity:1;color:color-mix(in oklab,currentColor 50%,transparent)}::placeholder{opacity:1;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}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*,:after,:before,::backdrop{border-color:var(--color-gray-200,currentColor)}::file-selector-button{border-color:var(--color-gray-200,currentColor)}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.visible\!{visibility:visible!important}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.-z-10{z-index:-10}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.me-1{margin-inline-end:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-8{margin-top:calc(var(--spacing)*8)}.mt-16{margin-top:calc(var(--spacing)*16)}.mt-20{margin-top:calc(var(--spacing)*20)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-20{margin-bottom:calc(var(--spacing)*20)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-12{height:calc(var(--spacing)*12)}.h-full{height:100%}.max-h-60{max-height:calc(var(--spacing)*60)}.min-h-10{min-height:calc(var(--spacing)*10)}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-64{width:calc(var(--spacing)*64)}.w-258{width:calc(var(--spacing)*258)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-md{max-width:var(--container-md)}.max-w-prose{max-width:65ch}.flex-1{flex:1}.translate-x-1{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-1{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.animate-fade-in{animation:var(--animate-fade-in)}.animate-pulse{animation:var(--animate-pulse)}.animate-slide-down{animation:var(--animate-slide-down)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*4)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-black{border-color:var(--color-black)}.border-blue-500{border-color:var(--color-blue-500)}.border-t-transparent{border-top-color:#0000}.bg-black{background-color:var(--color-black)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-red-500{background-color:var(--color-red-500)}.bg-white{background-color:var(--color-white)}.bg-\[radial-gradient\(\#e5e7eb_1px\,transparent_1px\)\]{background-image:radial-gradient(#e5e7eb 1px,#0000 1px)}.\[background-size\:16px_16px\]{background-size:16px 16px}.p-1{padding:calc(var(--spacing)*1)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-8{padding-inline:calc(var(--spacing)*8)}.px-10{padding-inline:calc(var(--spacing)*10)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.text-center{text-align:center}.text-left{text-align:left}.font-sans{font-family:var(--font-sans)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--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-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.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-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-black{color:var(--color-black)}.text-blue-400{color:var(--color-blue-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.shadow-\[2px_2px_0px_0px_rgba\(0\,0\,0\,1\)\]{--tw-shadow:2px 2px 0px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[2px_2px_0px_rgba\(0\,0\,0\,1\)\]{--tw-shadow:2px 2px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:translate-x-\[2px\]:hover{--tw-translate-x:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:translate-y-\[2px\]:hover{--tw-translate-y:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.hover\:bg-black:hover{background-color:var(--color-black)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:text-white:hover{color:var(--color-white)}.hover\:shadow-\[1px_1px_0px_0px_rgba\(0\,0\,0\,1\)\]:hover{--tw-shadow:1px 1px 0px 0px var(--tw-shadow-color,#000);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-none:hover{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:translate-x-1:active{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.active\:translate-y-1:active{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.active\:shadow-none:active{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}@media (width>=40rem){.sm\:mt-12{margin-top:calc(var(--spacing)*12)}}}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}:root{--font-atkinson:"Atkinson Hyperlegible",system-ui,sans-serif}*{-webkit-touch-callout:none}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf)format("truetype");font-weight:400;font-style:normal}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf)format("truetype");font-weight:700;font-style:normal}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf)format("truetype");font-weight:400;font-style:italic}@font-face{font-family:Atkinson Hyperlegible;src:url(/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf)format("truetype");font-weight:700;font-style:italic}.sd-root-modern{background-image:radial-gradient(#e5e7eb 1px,#0000 1px);background-size:16px 16px;font-family:Atkinson Hyperlegible,sans-serif;position:relative;background-color:#fff!important}.sd-root-modern *{font-family:Atkinson Hyperlegible,sans-serif}.sd-row,.sd-clearfix{padding-bottom:20px!important}@media (width<=639px){.sd-imagepicker__item--inline{margin-top:10px;margin-left:auto;margin-right:auto}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}/*!
2
2
  * surveyjs - Survey JavaScript library v1.12.11
3
3
  * Copyright (c) 2015-2024 Devsoft Baltic OÜ - http://surveyjs.io/
4
4
  * License: MIT (http://www.opensource.org/licenses/mit-license.php)
@@ -1,4 +1,4 @@
1
- import { W as P, b as x, E } from "./mod-jEw82wE_.js";
1
+ import { W as P, b as x, E } from "./mod-DgcCRxWo.js";
2
2
  function m(w) {
3
3
  const e = w.split("/").filter((t) => t !== "."), r = [];
4
4
  return e.forEach((t) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adriansteffan/reactive",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -1,12 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { ExperimentConfig, now } from '../utils/common';
4
- import { useEffect, useRef, useState } from 'react';
3
+ import { ExperimentConfig, now, Store, TrialData } from '../utils/common';
4
+ import { useEffect, useMemo, useRef, useState } from 'react';
5
5
  import { ComponentType } from 'react';
6
6
 
7
7
  // Default components
8
8
  import Upload from './upload';
9
9
  import Text from './text';
10
+ import PlainInput from './plaininput';
10
11
  import ProlificEnding from './prolificending';
11
12
  import Quest from './quest';
12
13
  import EnterFullscreen from './enterfullscreen';
@@ -25,64 +26,212 @@ const defaultComponents: ComponentsMap = {
25
26
  Text,
26
27
  ProlificEnding,
27
28
  EnterFullscreen,
28
- ExitFullscreen,
29
+ ExitFullscreen,
29
30
  Quest,
30
31
  Upload,
31
32
  MicrophoneCheck,
33
+ PlainInput,
32
34
  };
33
35
 
34
36
  const defaultCustomQuestions = {
35
37
  voicerecorder: VoicerecorderQuestionComponent,
36
38
  };
37
39
 
38
- interface ExperimentTrial {
40
+ interface ComponentTrial {
39
41
  name: string;
40
42
  type: string;
41
- props?: Record<string, any>;
43
+ props?: Record<string, any> | ((store: Store, data: TrialData[]) => Record<string, any>);
42
44
  }
43
45
 
44
- interface TrialData {
45
- index: number;
46
- type: string;
47
- name: string;
48
- data: object | undefined;
49
- start: number;
50
- end: number;
51
- duration: number;
46
+
47
+ // The | string parts need some refactoring in the future, but right now this prevents the consumer from having to write "as const" behind every type
48
+
49
+ interface MarkerTrial {
50
+ type: 'MARKER' | string;
51
+ id: string;
52
+ }
53
+
54
+ interface IfGotoTrial {
55
+ type: 'IF_GOTO' | string;
56
+ cond: (store: Store, data: TrialData[]) => boolean;
57
+ marker: string;
58
+ }
59
+
60
+ interface UpdateStoreTrial {
61
+ type: 'UPDATE_STORE' | string;
62
+ fun: (store: Store, data: TrialData[]) => Store;
63
+ }
64
+
65
+ interface IfBlockTrial {
66
+ type: 'IF_BLOCK' | string;
67
+ cond: (store: Store, data: TrialData[]) => boolean;
68
+ timeline: ExperimentTrial[];
69
+ }
70
+
71
+ interface WhileBlockTrial {
72
+ type: 'WHILE_BLOCK' | string;
73
+ cond: (store: Store, data: TrialData[]) => boolean;
74
+ timeline: ExperimentTrial[];
75
+ }
76
+
77
+ type ExperimentTrial =
78
+ | MarkerTrial
79
+ | IfGotoTrial
80
+ | UpdateStoreTrial
81
+ | IfBlockTrial
82
+ | WhileBlockTrial
83
+ | ComponentTrial;
84
+
85
+ interface ComponentInstruction {
86
+ type: 'Component';
87
+ content: ComponentTrial;
88
+ }
89
+
90
+ interface IfGotoInstruction {
91
+ type: 'IfGoto';
92
+ cond: (store: Store, data: TrialData[]) => boolean;
93
+ marker: string;
94
+ }
95
+
96
+ interface UpdateStoreInstruction {
97
+ type: 'UpdateStore';
98
+ fun: (store: Store, data: TrialData[]) => Store;
52
99
  }
53
100
 
54
- // Function to transform experiment definition into components
55
- const transformExperiment = (
56
- experimentDef: ExperimentTrial[],
57
- index: number,
101
+ type BytecodeInstruction = ComponentInstruction | IfGotoInstruction | UpdateStoreInstruction;
102
+
103
+ const renderComponentTrial = (
104
+ componentTrial: ComponentTrial,
105
+ key: number,
58
106
  next: (data: any) => void,
107
+ updateStore: (update: Store) => void,
59
108
  data: any,
60
109
  componentsMap: ComponentsMap,
61
110
  customQuestions: ComponentsMap,
111
+ store: Store,
62
112
  ) => {
63
- if (index >= experimentDef.length) {
64
- return <></>;
65
- }
66
-
67
- const def = experimentDef[index];
68
-
69
- const Component = componentsMap[def.type];
113
+ const Component = componentsMap[componentTrial.type];
70
114
 
71
115
  if (!Component) {
72
- throw new Error(`No component found for type: ${def.type}`);
116
+ throw new Error(`No component found for type: ${componentTrial.type}`);
73
117
  }
74
118
 
119
+ const componentProps =
120
+ typeof componentTrial.props === 'function'
121
+ ? componentTrial.props(store, data)
122
+ : componentTrial.props || {};
123
+
75
124
  return (
76
125
  <Component
77
126
  next={next}
78
- key={index}
127
+ updateStore={updateStore}
128
+ key={key}
79
129
  data={data}
80
- {...(def.type === 'Quest' ? { customQuestions: customQuestions } : {})}
81
- {...def.props}
130
+ {...(componentTrial.type === 'Quest' ? { customQuestions: customQuestions } : {})}
131
+ {...componentProps}
82
132
  />
83
133
  );
84
134
  };
85
135
 
136
+ function prefixUserMarkers(marker: string) {
137
+ return `user_${marker}`;
138
+ }
139
+
140
+ let uniqueMarkerCounter = 0;
141
+ function generateUniqueMarker(prefix: string): string {
142
+ return `${prefix}_auto_${uniqueMarkerCounter++}`;
143
+ }
144
+
145
+ function compileTimeline(timeline: ExperimentTrial[]): {
146
+ instructions: BytecodeInstruction[];
147
+ markers: { [key: string]: number };
148
+ } {
149
+ const instructions: BytecodeInstruction[] = [];
150
+ const markers: { [key: string]: number } = {};
151
+
152
+ function processTimeline(trials: ExperimentTrial[]) {
153
+ for (let i = 0; i < trials.length; i++) {
154
+ const trial = trials[i];
155
+
156
+ switch (trial.type) {
157
+ case 'MARKER':
158
+ markers[prefixUserMarkers((trial as MarkerTrial).id)] = instructions.length;
159
+ break;
160
+
161
+ case 'IF_GOTO':
162
+ const ifgotoTrial = trial as IfGotoTrial;
163
+ instructions.push({
164
+ type: 'IfGoto',
165
+ cond: ifgotoTrial.cond,
166
+ marker: prefixUserMarkers(ifgotoTrial.marker),
167
+ });
168
+ break;
169
+
170
+ case 'UPDATE_STORE':
171
+ instructions.push({
172
+ type: 'UpdateStore',
173
+ fun: (trial as UpdateStoreTrial).fun,
174
+ });
175
+ break;
176
+
177
+ case 'IF_BLOCK': {
178
+ const ifBlockTrial = trial as IfBlockTrial;
179
+
180
+ const endMarker = generateUniqueMarker('if_end');
181
+
182
+ instructions.push({
183
+ type: 'IfGoto',
184
+ cond: (store, data) => !ifBlockTrial.cond(store, data), // Negate condition to skip if false
185
+ marker: endMarker,
186
+ });
187
+
188
+ processTimeline(ifBlockTrial.timeline);
189
+
190
+ markers[endMarker] = instructions.length;
191
+ break;
192
+ }
193
+
194
+ case 'WHILE_BLOCK': {
195
+ const whileBlockTrial = trial as WhileBlockTrial;
196
+
197
+ const startMarker = generateUniqueMarker('while_start');
198
+ const endMarker = generateUniqueMarker('while_end');
199
+
200
+ markers[startMarker] = instructions.length;
201
+
202
+ instructions.push({
203
+ type: 'IfGoto',
204
+ cond: (store, data) => !whileBlockTrial.cond(store, data),
205
+ marker: endMarker,
206
+ });
207
+
208
+ processTimeline(whileBlockTrial.timeline);
209
+
210
+ instructions.push({
211
+ type: 'IfGoto',
212
+ cond: () => true, // Always jump back
213
+ marker: startMarker,
214
+ });
215
+
216
+ markers[endMarker] = instructions.length;
217
+ break;
218
+ }
219
+
220
+ default:
221
+ instructions.push({
222
+ type: 'Component',
223
+ content: trial as ComponentTrial,
224
+ });
225
+ break;
226
+ }
227
+ }
228
+ }
229
+
230
+ processTimeline(timeline);
231
+
232
+ return { instructions, markers };
233
+ }
234
+
86
235
  export default function Experiment({
87
236
  timeline,
88
237
  config = {
@@ -96,26 +245,38 @@ export default function Experiment({
96
245
  components?: ComponentsMap;
97
246
  questions?: ComponentsMap;
98
247
  }) {
248
+ const trialByteCode = useMemo(() => {
249
+ return compileTimeline(timeline);
250
+ }, [timeline]);
251
+
99
252
  const [trialCounter, setTrialCounter] = useState(0);
253
+ const [totalTrialsCompleted, setTotalTrialsCompleted] = useState(0);
100
254
  const [data, setData] = useState<TrialData[]>([]);
101
255
  const trialStartTimeRef = useRef(now());
256
+ const experimentStoreRef = useRef({});
102
257
 
103
258
  const componentsMap = { ...defaultComponents, ...components };
104
259
  const customQuestions: ComponentsMap = { ...defaultCustomQuestions, ...questions };
105
260
 
106
- const progress = trialCounter / (timeline.length - 1);
261
+ const progress = trialCounter / (trialByteCode.instructions.length - 1);
107
262
 
108
263
  useEffect(() => {
109
264
  window.scrollTo(0, 0);
110
265
  }, [trialCounter]);
111
266
 
267
+ function updateStore(update: Store) {
268
+ const updatedStore = update;
269
+ experimentStoreRef.current = { ...experimentStoreRef.current, ...updatedStore };
270
+ }
271
+
112
272
  function next(newData?: object): void {
113
273
  const currentTime = now();
114
- const currentTrial = timeline[trialCounter];
274
+ const currentTrial = (trialByteCode.instructions[trialCounter] as ComponentInstruction).content;
115
275
 
116
276
  if (currentTrial && data) {
117
277
  const trialData: TrialData = {
118
278
  index: trialCounter,
279
+ trialNumber: totalTrialsCompleted,
119
280
  type: currentTrial.type,
120
281
  name: currentTrial.name,
121
282
  data: newData,
@@ -124,10 +285,47 @@ export default function Experiment({
124
285
  duration: currentTime - trialStartTimeRef.current,
125
286
  };
126
287
  setData([...data, trialData]);
288
+ setTotalTrialsCompleted(totalTrialsCompleted + 1);
289
+ }
290
+
291
+ let nextCounter = trialCounter + 1;
292
+ let foundNextComponent = false;
293
+
294
+ // Process control flow instructions until we find a Component or reach the end
295
+ while (!foundNextComponent && nextCounter < trialByteCode.instructions.length) {
296
+ const nextInstruction = trialByteCode.instructions[nextCounter];
297
+
298
+ switch (nextInstruction.type) {
299
+ case 'IfGoto':
300
+ if (nextInstruction.cond(experimentStoreRef.current, data)) {
301
+ const markerIndex = trialByteCode.markers[nextInstruction.marker];
302
+ if (markerIndex !== undefined) {
303
+ nextCounter = markerIndex;
304
+ } else {
305
+ console.error(`Marker ${nextInstruction.marker} not found`);
306
+ nextCounter++;
307
+ }
308
+ } else {
309
+ nextCounter++;
310
+ }
311
+ break;
312
+
313
+ case 'UpdateStore':
314
+ updateStore(nextInstruction.fun(experimentStoreRef.current, data));
315
+ nextCounter++;
316
+ break;
317
+
318
+ case 'Component':
319
+ foundNextComponent = true;
320
+ break;
321
+
322
+ default: // Unknown, skip
323
+ nextCounter++;
324
+ }
127
325
  }
128
326
 
129
- trialStartTimeRef.current = currentTime;
130
- setTrialCounter(trialCounter + 1);
327
+ trialStartTimeRef.current = now();
328
+ setTrialCounter(nextCounter);
131
329
  }
132
330
 
133
331
  return (
@@ -154,7 +352,18 @@ export default function Experiment({
154
352
  }}
155
353
  />
156
354
  </div>
157
- {transformExperiment(timeline, trialCounter, next, data, componentsMap, customQuestions)}
355
+ {trialCounter < trialByteCode.instructions.length &&
356
+ trialByteCode.instructions[trialCounter].type === 'Component' &&
357
+ renderComponentTrial(
358
+ (trialByteCode.instructions[trialCounter] as ComponentInstruction).content,
359
+ totalTrialsCompleted,
360
+ next,
361
+ updateStore,
362
+ data,
363
+ componentsMap,
364
+ customQuestions,
365
+ experimentStoreRef.current, // Pass the current store
366
+ )}
158
367
  </div>
159
368
  );
160
369
  }
@@ -0,0 +1,72 @@
1
+ import { BaseComponentProps } from "../mod";
2
+ import { useState } from "react";
3
+
4
+ function PlainInput({
5
+ content,
6
+ buttonText = 'Click me',
7
+ className = '',
8
+ next,
9
+ updateStore,
10
+ animate = false,
11
+ storeupdate, // user defined function
12
+ placeholder = 'Enter your response here',
13
+ }: BaseComponentProps & {
14
+ content: React.ReactNode;
15
+ buttonText?: string;
16
+ onButtonClick?: () => void;
17
+ className?: string;
18
+ animate?: boolean;
19
+ storeupdate?: (entry: string) => { [key: string]: any };
20
+ placeholder?: string;
21
+ }) {
22
+ const [inputValue, setInputValue] = useState('');
23
+
24
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
25
+ setInputValue(e.target.value);
26
+ };
27
+
28
+ const handleClick = () => {
29
+ if (storeupdate) {
30
+ updateStore(storeupdate(inputValue));
31
+ }
32
+ next({value: inputValue});
33
+ };
34
+
35
+ return (
36
+ <div className={`max-w-prose mx-auto ${className} mt-20 mb-20 px-4 `}>
37
+ <article
38
+ className={`prose prose-2xl prose-slate text-xl prose-a:text-blue-600 prose-a:underline prose-h1:text-4xl prose-h1:mb-10 prose-h1:font-bold prose-p:mb-4 prose-strong:font-bold text-black leading-relaxed
39
+ ${animate ? 'animate-slide-down opacity-0' : ''}`}
40
+ >
41
+ {content}
42
+ </article>
43
+
44
+ <div className={`mt-8 ${animate ? 'animate-slide-down opacity-0' : ''}`}>
45
+ <input
46
+ type="text"
47
+ value={inputValue}
48
+ onChange={handleChange}
49
+ placeholder={placeholder}
50
+ className="w-full px-4 py-3 border-2 border-black rounded-xl text-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
51
+ />
52
+ </div>
53
+
54
+ {buttonText && (
55
+ <div
56
+ className={`mt-8 flex justify-center ${animate ? 'animate-fade-in opacity-0' : ''}`}
57
+ style={animate ? { animationDelay: '1s' } : {}}
58
+ >
59
+ <button
60
+ onClick={handleClick}
61
+ className='bg-white cursor-pointer px-8 py-3 border-2 border-black font-bold text-black text-lg rounded-xl shadow-[2px_2px_0px_rgba(0,0,0,1)] hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none'
62
+ >
63
+ {buttonText}
64
+ </button>
65
+ </div>
66
+ )}
67
+ </div>
68
+ );
69
+ }
70
+
71
+
72
+ export default PlainInput;
@@ -10,7 +10,7 @@ function Text({
10
10
  onButtonClick?: () => void;
11
11
  className?: string;
12
12
  next: (newData: object) => void;
13
- animate?: boolean; // new parameter
13
+ animate?: boolean;
14
14
  }) {
15
15
  const handleClick = () => {
16
16
  next({});
@@ -2,11 +2,10 @@ import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useMutation } from '@tanstack/react-query';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { post } from '../utils/request';
5
- import { FileUpload, getParam, StudyEvent } from '../utils/common';
5
+ import { BaseComponentProps, FileUpload, getParam, getPlatform, Platform, Store, TrialData } from '../utils/common';
6
6
  import { BlobWriter, TextReader, ZipWriter } from '@zip.js/zip.js';
7
7
 
8
8
  import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
9
- import { Capacitor } from '@capacitor/core';
10
9
 
11
10
  interface UploadPayload {
12
11
  sessionId: string;
@@ -120,25 +119,13 @@ const createCapacitorFileBackend = (parentFolder?: string): FileBackend => {
120
119
  };
121
120
  };
122
121
 
123
- export type Platform = 'electron' | 'capacitor' | 'web';
124
-
125
- export const getPlatform = (): Platform => {
126
- if ((window as any).electronAPI) {
127
- return 'electron';
128
- } else if (Capacitor.isNativePlatform()) {
129
- return 'capacitor';
130
- } else {
131
- return 'web';
132
- }
133
- };
134
-
135
122
  const getFileBackend = (parentDir?: string): { backend: FileBackend | null, type: Platform } => {
136
123
  const platform = getPlatform();
137
124
 
138
125
  switch (platform) {
139
- case 'electron':
126
+ case 'desktop':
140
127
  return { backend: createElectronFileBackend(), type: platform };
141
- case 'capacitor':
128
+ case 'mobile':
142
129
  return { backend: createCapacitorFileBackend(parentDir), type: platform };
143
130
  case 'web':
144
131
  return { backend: null, type: platform };
@@ -168,16 +155,15 @@ const getUniqueDirectoryName = async (
168
155
  export default function Upload({
169
156
  data,
170
157
  next,
158
+ store,
171
159
  sessionID,
172
160
  generateFiles,
173
161
  uploadRaw = true,
174
162
  autoUpload = false,
175
163
  androidFolderName,
176
- }: {
177
- data: StudyEvent[];
178
- next: () => void;
164
+ }: BaseComponentProps & {
179
165
  sessionID?: string | null;
180
- generateFiles: (sessionID: string, data: StudyEvent[]) => FileUpload[];
166
+ generateFiles: (sessionID: string, data: TrialData[], store?: Store) => FileUpload[];
181
167
  uploadRaw: boolean;
182
168
  autoUpload: boolean;
183
169
  androidFolderName?: string;
@@ -199,7 +185,7 @@ export default function Upload({
199
185
  onSuccess: (res: UploadResponse) => {
200
186
  if (res.status === 200) {
201
187
  setUploadState('success');
202
- next();
188
+ next({});
203
189
  } else {
204
190
  setUploadState('error');
205
191
  }
@@ -239,7 +225,7 @@ export default function Upload({
239
225
 
240
226
  const sessionIDUpload = sessionID ?? uuidv4();
241
227
 
242
- const files: FileUpload[] = generateFiles ? generateFiles(sessionIDUpload, data) : [];
228
+ const files: FileUpload[] = generateFiles ? generateFiles(sessionIDUpload, data, store) : [];
243
229
  if (uploadRaw) {
244
230
  files.push({
245
231
  filename: `${sessionIDUpload}.raw.json`,
@@ -259,7 +245,7 @@ export default function Upload({
259
245
  }
260
246
 
261
247
  if (!shouldUpload) {
262
- next();
248
+ next({});
263
249
  return;
264
250
  }
265
251
 
@@ -283,7 +269,7 @@ export default function Upload({
283
269
  }
284
270
 
285
271
  setUploadState('success');
286
- next();
272
+ next({});
287
273
  } catch (error) {
288
274
  console.error(`Error saving files with ${type}:`, error);
289
275
  setUploadState('error');
package/src/mod.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  import './index.css';
2
2
  import Text from './components/text';
3
+ import PlainInput from './components/plaininput';
3
4
  import ProlificEnding from './components/prolificending';
4
5
  import MicCheck from './components/microphonecheck';
5
6
  import Quest from './components/quest';
@@ -10,7 +11,7 @@ import ExperimentProvider from './components/experimentprovider';
10
11
  import Experiment from './components/experiment';
11
12
  import { BaseComponentProps, ExperimentConfig } from './utils/common';
12
13
 
13
- export { Text, ProlificEnding, MicCheck, Quest, Upload, EnterFullscreen, ExitFullscreen, Experiment, ExperimentProvider};
14
+ export { Text, ProlificEnding, MicCheck, Quest, Upload, EnterFullscreen, ExitFullscreen, Experiment, ExperimentProvider, PlainInput};
14
15
  export type { BaseComponentProps, ExperimentConfig };
15
16
  export * from './utils/common';
16
17