@nyuccl/smile 0.2.0-beta.4 → 0.2.0-beta.41

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.
Files changed (310) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +109 -21
  3. package/dist/runtime/components/builtins/AdvertisementView.d.vue.ts +13 -1
  4. package/dist/runtime/components/builtins/AdvertisementView.vue +7 -3
  5. package/dist/runtime/components/builtins/AdvertisementView.vue.d.ts +13 -1
  6. package/dist/runtime/components/builtins/DebriefView.vue +3 -1
  7. package/dist/runtime/components/builtins/DemographicSurveyView.vue +8 -6
  8. package/dist/runtime/components/builtins/DeviceSurveyView.vue +5 -3
  9. package/dist/runtime/components/builtins/ExpView.vue +4 -2
  10. package/dist/runtime/components/builtins/ExperimentStatusBar.vue +3 -0
  11. package/dist/runtime/components/builtins/FavoriteColor.vue +3 -1
  12. package/dist/runtime/components/builtins/FavoriteNumber.vue +3 -1
  13. package/dist/runtime/components/builtins/InformedConsentModal.vue +5 -3
  14. package/dist/runtime/components/builtins/InformedConsentView.vue +3 -2
  15. package/dist/runtime/components/builtins/InstructionsQuiz.vue +7 -5
  16. package/dist/runtime/components/builtins/InstructionsView.vue +5 -3
  17. package/dist/runtime/components/builtins/LocalDevBanner.vue +16 -0
  18. package/dist/runtime/components/builtins/MTurkRecruitView.vue +4 -3
  19. package/dist/runtime/components/builtins/PresentationModeView.vue +9 -8
  20. package/dist/runtime/components/builtins/StatusBar.vue +7 -4
  21. package/dist/runtime/components/builtins/StudyPreviewText.vue +12 -10
  22. package/dist/runtime/components/builtins/TaskFeedbackSurveyView.vue +3 -1
  23. package/dist/runtime/components/builtins/ThanksView.vue +22 -21
  24. package/dist/runtime/components/builtins/WindowSizerView.vue +5 -3
  25. package/dist/runtime/components/builtins/WithdrawModal.vue +9 -7
  26. package/dist/runtime/components/builtins/WithdrawView.vue +4 -2
  27. package/dist/runtime/components/dev/RecruitmentChooserView.vue +532 -224
  28. package/dist/runtime/components/dev/ResponsiveDeviceContainer.vue +17 -8
  29. package/dist/runtime/components/dev/SmileDevPresentationView.vue +83 -0
  30. package/dist/runtime/components/dev/console/ConfigList.vue +14 -11
  31. package/dist/runtime/components/dev/console/ConsoleConfigPanel.vue +28 -7
  32. package/dist/runtime/components/dev/console/ConsoleDatabaseBrowsePanel.vue +6 -4
  33. package/dist/runtime/components/dev/console/ConsoleLogPanel.vue +68 -23
  34. package/dist/runtime/components/dev/console/DatabaseList.vue +9 -7
  35. package/dist/runtime/components/dev/console/SmileDevConsole.vue +7 -5
  36. package/dist/runtime/components/dev/devicePresets.d.ts +4 -4
  37. package/dist/runtime/components/dev/devicePresets.js +4 -4
  38. package/dist/runtime/components/dev/menu/DevConfigPanel.vue +3 -1
  39. package/dist/runtime/components/dev/menu/ResponsiveDeviceSelect.vue +1 -0
  40. package/dist/runtime/components/dev/menu/SmileDevAppMenu.vue +27 -24
  41. package/dist/runtime/components/dev/navbar/ColorModeButton.vue +5 -3
  42. package/dist/runtime/components/dev/navbar/DatabaseButtonGroup.vue +8 -6
  43. package/dist/runtime/components/dev/navbar/FullScreenButton.vue +4 -2
  44. package/dist/runtime/components/dev/navbar/KeyCommandNotification.vue +1 -1
  45. package/dist/runtime/components/dev/navbar/PanelButtonGroup.d.vue.ts +3 -0
  46. package/dist/runtime/components/dev/navbar/PanelButtonGroup.vue +79 -0
  47. package/dist/runtime/components/dev/navbar/PanelButtonGroup.vue.d.ts +3 -0
  48. package/dist/runtime/components/dev/navbar/ReloadButton.vue +3 -1
  49. package/dist/runtime/components/dev/navbar/ResetButton.vue +3 -1
  50. package/dist/runtime/components/dev/navbar/RouteJumper.vue +9 -5
  51. package/dist/runtime/components/dev/navbar/SmileDevNavBar.vue +19 -27
  52. package/dist/runtime/components/dev/navbar/StepInfoButtonGroup.vue +5 -3
  53. package/dist/runtime/components/dev/navbar/ViewInfoButtonGroup.vue +13 -10
  54. package/dist/runtime/components/dev/presentation/DarkModeButton.vue +5 -3
  55. package/dist/runtime/components/dev/presentation/LogoutButton.vue +2 -1
  56. package/dist/runtime/components/dev/presentation/PresentationModeResetButton.vue +11 -2
  57. package/dist/runtime/components/dev/presentation/PresentationNavBar.d.vue.ts +13 -1
  58. package/dist/runtime/components/dev/presentation/PresentationNavBar.vue +13 -6
  59. package/dist/runtime/components/dev/presentation/PresentationNavBar.vue.d.ts +13 -1
  60. package/dist/runtime/components/dev/presentation/QRCodeButton.vue +4 -2
  61. package/dist/runtime/components/dev/sidebar/AppProgressPanel.vue +23 -21
  62. package/dist/runtime/components/dev/sidebar/ConfigurationVariablesPanel.vue +7 -5
  63. package/dist/runtime/components/dev/sidebar/DatabaseStatusInfoPanel.vue +27 -7
  64. package/dist/runtime/components/dev/sidebar/RandomizationSidebarPanel.vue +9 -5
  65. package/dist/runtime/components/dev/sidebar/SmileDevSideBar.vue +12 -5
  66. package/dist/runtime/components/dev/sidebar/StepDataViewer.d.vue.ts +2 -2
  67. package/dist/runtime/components/dev/sidebar/StepDataViewer.vue +1 -1
  68. package/dist/runtime/components/dev/sidebar/StepDataViewer.vue.d.ts +2 -2
  69. package/dist/runtime/components/dev/sidebar/StepExplorerPanel.vue +13 -8
  70. package/dist/runtime/components/dev/sidebar/StepNode.vue +7 -5
  71. package/dist/runtime/components/dev/sidebar/StudyInfoPanel.vue +3 -2
  72. package/dist/runtime/components/forms/MonthYearDayPicker.vue +1 -0
  73. package/dist/runtime/components/layouts/ConstrainedPage.d.vue.ts +1 -1
  74. package/dist/runtime/components/layouts/ConstrainedPage.vue.d.ts +1 -1
  75. package/dist/runtime/components/layouts/ConstrainedTaskWindow.d.vue.ts +2 -2
  76. package/dist/runtime/components/layouts/ConstrainedTaskWindow.vue +1 -1
  77. package/dist/runtime/components/layouts/ConstrainedTaskWindow.vue.d.ts +2 -2
  78. package/dist/runtime/components/layouts/TitleTwoCol.d.vue.ts +1 -1
  79. package/dist/runtime/components/layouts/TitleTwoCol.vue.d.ts +1 -1
  80. package/dist/runtime/components/layouts/TwoCol.d.vue.ts +1 -1
  81. package/dist/runtime/components/layouts/TwoCol.vue.d.ts +1 -1
  82. package/dist/runtime/components/ui/avatar/Avatar.vue +1 -0
  83. package/dist/runtime/components/ui/avatar/AvatarFallback.vue +1 -0
  84. package/dist/runtime/components/ui/badge/Badge.vue +1 -0
  85. package/dist/runtime/components/ui/badge/index.d.ts +1 -1
  86. package/dist/runtime/components/ui/breadcrumb/BreadcrumbEllipsis.vue +1 -0
  87. package/dist/runtime/components/ui/breadcrumb/BreadcrumbItem.vue +1 -0
  88. package/dist/runtime/components/ui/breadcrumb/BreadcrumbLink.vue +1 -0
  89. package/dist/runtime/components/ui/breadcrumb/BreadcrumbList.vue +1 -0
  90. package/dist/runtime/components/ui/breadcrumb/BreadcrumbPage.vue +1 -0
  91. package/dist/runtime/components/ui/breadcrumb/BreadcrumbSeparator.vue +1 -0
  92. package/dist/runtime/components/ui/button/Button.vue +1 -0
  93. package/dist/runtime/components/ui/button/index.d.ts +2 -2
  94. package/dist/runtime/components/ui/button-group/ButtonGroup.vue +1 -0
  95. package/dist/runtime/components/ui/button-group/ButtonGroupItem.vue +1 -0
  96. package/dist/runtime/components/ui/calendar/Calendar.vue +1 -0
  97. package/dist/runtime/components/ui/calendar/CalendarCell.vue +1 -0
  98. package/dist/runtime/components/ui/calendar/CalendarCellTrigger.vue +1 -0
  99. package/dist/runtime/components/ui/calendar/CalendarGrid.vue +1 -0
  100. package/dist/runtime/components/ui/calendar/CalendarGridRow.vue +1 -0
  101. package/dist/runtime/components/ui/calendar/CalendarHeadCell.vue +1 -0
  102. package/dist/runtime/components/ui/calendar/CalendarHeader.vue +1 -0
  103. package/dist/runtime/components/ui/calendar/CalendarHeading.vue +1 -0
  104. package/dist/runtime/components/ui/calendar/CalendarNextButton.vue +1 -0
  105. package/dist/runtime/components/ui/calendar/CalendarPrevButton.vue +1 -0
  106. package/dist/runtime/components/ui/card/Card.vue +1 -0
  107. package/dist/runtime/components/ui/card/CardAction.vue +1 -0
  108. package/dist/runtime/components/ui/card/CardContent.vue +1 -0
  109. package/dist/runtime/components/ui/card/CardDescription.vue +1 -0
  110. package/dist/runtime/components/ui/card/CardFooter.vue +1 -0
  111. package/dist/runtime/components/ui/card/CardHeader.vue +1 -0
  112. package/dist/runtime/components/ui/card/CardTitle.vue +1 -0
  113. package/dist/runtime/components/ui/checkbox/Checkbox.d.vue.ts +6 -6
  114. package/dist/runtime/components/ui/checkbox/Checkbox.vue +1 -0
  115. package/dist/runtime/components/ui/checkbox/Checkbox.vue.d.ts +6 -6
  116. package/dist/runtime/components/ui/checkbox/index.d.ts +2 -2
  117. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.d.vue.ts +4 -4
  118. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -0
  119. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue.d.ts +4 -4
  120. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuContent.d.vue.ts +3 -3
  121. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuContent.vue +1 -0
  122. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +3 -3
  123. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuItem.d.vue.ts +1 -1
  124. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuItem.vue +1 -0
  125. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuItem.vue.d.ts +1 -1
  126. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuLabel.vue +1 -0
  127. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +1 -0
  128. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSeparator.vue +1 -0
  129. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuShortcut.vue +1 -0
  130. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubContent.d.vue.ts +3 -3
  131. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubContent.vue +1 -0
  132. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubContent.vue.d.ts +3 -3
  133. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -0
  134. package/dist/runtime/components/ui/input/Input.d.vue.ts +4 -4
  135. package/dist/runtime/components/ui/input/Input.vue +1 -0
  136. package/dist/runtime/components/ui/input/Input.vue.d.ts +4 -4
  137. package/dist/runtime/components/ui/label/Label.vue +1 -0
  138. package/dist/runtime/components/ui/multiselect/MultiSelect.d.vue.ts +1 -1
  139. package/dist/runtime/components/ui/multiselect/MultiSelect.vue +1 -0
  140. package/dist/runtime/components/ui/multiselect/MultiSelect.vue.d.ts +1 -1
  141. package/dist/runtime/components/ui/pagination/Pagination.vue +1 -0
  142. package/dist/runtime/components/ui/pagination/PaginationContent.vue +1 -0
  143. package/dist/runtime/components/ui/pagination/PaginationEllipsis.vue +1 -0
  144. package/dist/runtime/components/ui/pagination/PaginationFirst.vue +1 -0
  145. package/dist/runtime/components/ui/pagination/PaginationItem.vue +1 -0
  146. package/dist/runtime/components/ui/pagination/PaginationLast.vue +1 -0
  147. package/dist/runtime/components/ui/pagination/PaginationNext.vue +1 -0
  148. package/dist/runtime/components/ui/pagination/PaginationPrevious.vue +1 -0
  149. package/dist/runtime/components/ui/popover/PopoverContent.d.vue.ts +2 -2
  150. package/dist/runtime/components/ui/popover/PopoverContent.vue +1 -0
  151. package/dist/runtime/components/ui/popover/PopoverContent.vue.d.ts +2 -2
  152. package/dist/runtime/components/ui/progress/Progress.vue +1 -0
  153. package/dist/runtime/components/ui/resizable/ResizableHandle.vue +1 -0
  154. package/dist/runtime/components/ui/resizable/ResizablePanel.d.vue.ts +1 -1
  155. package/dist/runtime/components/ui/resizable/ResizablePanel.vue.d.ts +1 -1
  156. package/dist/runtime/components/ui/resizable/ResizablePanelGroup.vue +1 -0
  157. package/dist/runtime/components/ui/select/Select.d.vue.ts +1 -1
  158. package/dist/runtime/components/ui/select/Select.vue.d.ts +1 -1
  159. package/dist/runtime/components/ui/select/SelectContent.d.vue.ts +2 -2
  160. package/dist/runtime/components/ui/select/SelectContent.vue +1 -0
  161. package/dist/runtime/components/ui/select/SelectContent.vue.d.ts +2 -2
  162. package/dist/runtime/components/ui/select/SelectItem.vue +1 -0
  163. package/dist/runtime/components/ui/select/SelectLabel.vue +1 -0
  164. package/dist/runtime/components/ui/select/SelectScrollDownButton.vue +1 -0
  165. package/dist/runtime/components/ui/select/SelectScrollUpButton.vue +1 -0
  166. package/dist/runtime/components/ui/select/SelectSeparator.vue +1 -0
  167. package/dist/runtime/components/ui/select/SelectTrigger.vue +1 -0
  168. package/dist/runtime/components/ui/separator/Separator.vue +1 -0
  169. package/dist/runtime/components/ui/sheet/SheetContent.d.vue.ts +1 -1
  170. package/dist/runtime/components/ui/sheet/SheetContent.vue +1 -0
  171. package/dist/runtime/components/ui/sheet/SheetContent.vue.d.ts +1 -1
  172. package/dist/runtime/components/ui/sheet/SheetDescription.vue +1 -0
  173. package/dist/runtime/components/ui/sheet/SheetFooter.vue +1 -0
  174. package/dist/runtime/components/ui/sheet/SheetHeader.vue +1 -0
  175. package/dist/runtime/components/ui/sheet/SheetOverlay.vue +1 -0
  176. package/dist/runtime/components/ui/sheet/SheetTitle.vue +1 -0
  177. package/dist/runtime/components/ui/sidebar/Sidebar.d.vue.ts +1 -1
  178. package/dist/runtime/components/ui/sidebar/Sidebar.vue +1 -0
  179. package/dist/runtime/components/ui/sidebar/Sidebar.vue.d.ts +1 -1
  180. package/dist/runtime/components/ui/sidebar/SidebarContent.vue +1 -0
  181. package/dist/runtime/components/ui/sidebar/SidebarFooter.vue +1 -0
  182. package/dist/runtime/components/ui/sidebar/SidebarGroup.vue +1 -0
  183. package/dist/runtime/components/ui/sidebar/SidebarGroupAction.vue +1 -0
  184. package/dist/runtime/components/ui/sidebar/SidebarGroupContent.vue +1 -0
  185. package/dist/runtime/components/ui/sidebar/SidebarGroupLabel.vue +1 -0
  186. package/dist/runtime/components/ui/sidebar/SidebarHeader.vue +1 -0
  187. package/dist/runtime/components/ui/sidebar/SidebarInput.vue +1 -0
  188. package/dist/runtime/components/ui/sidebar/SidebarInset.vue +1 -0
  189. package/dist/runtime/components/ui/sidebar/SidebarMenu.vue +1 -0
  190. package/dist/runtime/components/ui/sidebar/SidebarMenuAction.vue +1 -0
  191. package/dist/runtime/components/ui/sidebar/SidebarMenuBadge.vue +1 -0
  192. package/dist/runtime/components/ui/sidebar/SidebarMenuButton.d.vue.ts +1 -1
  193. package/dist/runtime/components/ui/sidebar/SidebarMenuButton.vue.d.ts +1 -1
  194. package/dist/runtime/components/ui/sidebar/SidebarMenuButtonChild.d.vue.ts +1 -1
  195. package/dist/runtime/components/ui/sidebar/SidebarMenuButtonChild.vue +1 -0
  196. package/dist/runtime/components/ui/sidebar/SidebarMenuButtonChild.vue.d.ts +1 -1
  197. package/dist/runtime/components/ui/sidebar/SidebarMenuItem.vue +1 -0
  198. package/dist/runtime/components/ui/sidebar/SidebarMenuSkeleton.vue +1 -0
  199. package/dist/runtime/components/ui/sidebar/SidebarMenuSub.vue +1 -0
  200. package/dist/runtime/components/ui/sidebar/SidebarMenuSubButton.vue +1 -0
  201. package/dist/runtime/components/ui/sidebar/SidebarMenuSubItem.vue +1 -0
  202. package/dist/runtime/components/ui/sidebar/SidebarProvider.vue +1 -0
  203. package/dist/runtime/components/ui/sidebar/SidebarRail.vue +1 -0
  204. package/dist/runtime/components/ui/sidebar/SidebarSeparator.vue +1 -0
  205. package/dist/runtime/components/ui/sidebar/SidebarTrigger.vue +1 -0
  206. package/dist/runtime/components/ui/sidebar/index.d.ts +1 -1
  207. package/dist/runtime/components/ui/skeleton/Skeleton.vue +1 -0
  208. package/dist/runtime/components/ui/sonner/Sonner.d.vue.ts +4 -4
  209. package/dist/runtime/components/ui/sonner/Sonner.vue.d.ts +4 -4
  210. package/dist/runtime/components/ui/stepper/Stepper.vue +1 -0
  211. package/dist/runtime/components/ui/stepper/StepperDescription.vue +1 -0
  212. package/dist/runtime/components/ui/stepper/StepperIndicator.vue +1 -0
  213. package/dist/runtime/components/ui/stepper/StepperItem.d.vue.ts +1 -1
  214. package/dist/runtime/components/ui/stepper/StepperItem.vue +1 -0
  215. package/dist/runtime/components/ui/stepper/StepperItem.vue.d.ts +1 -1
  216. package/dist/runtime/components/ui/stepper/StepperSeparator.vue +1 -0
  217. package/dist/runtime/components/ui/stepper/StepperTitle.vue +1 -0
  218. package/dist/runtime/components/ui/stepper/StepperTrigger.vue +1 -0
  219. package/dist/runtime/components/ui/switch/Switch.d.vue.ts +2 -2
  220. package/dist/runtime/components/ui/switch/Switch.vue +1 -0
  221. package/dist/runtime/components/ui/switch/Switch.vue.d.ts +2 -2
  222. package/dist/runtime/components/ui/switch/index.d.ts +2 -2
  223. package/dist/runtime/components/ui/table/Table.vue +1 -0
  224. package/dist/runtime/components/ui/table/TableBody.vue +1 -0
  225. package/dist/runtime/components/ui/table/TableCaption.vue +1 -0
  226. package/dist/runtime/components/ui/table/TableCell.vue +1 -0
  227. package/dist/runtime/components/ui/table/TableEmpty.vue +1 -0
  228. package/dist/runtime/components/ui/table/TableFooter.vue +1 -0
  229. package/dist/runtime/components/ui/table/TableHead.vue +1 -0
  230. package/dist/runtime/components/ui/table/TableHeader.vue +1 -0
  231. package/dist/runtime/components/ui/table/TableRow.vue +1 -0
  232. package/dist/runtime/components/ui/tabs/Tabs.vue +1 -0
  233. package/dist/runtime/components/ui/tabs/TabsContent.d.vue.ts +2 -2
  234. package/dist/runtime/components/ui/tabs/TabsContent.vue +1 -0
  235. package/dist/runtime/components/ui/tabs/TabsContent.vue.d.ts +2 -2
  236. package/dist/runtime/components/ui/tabs/TabsList.d.vue.ts +1 -1
  237. package/dist/runtime/components/ui/tabs/TabsList.vue +1 -0
  238. package/dist/runtime/components/ui/tabs/TabsList.vue.d.ts +1 -1
  239. package/dist/runtime/components/ui/tabs/TabsTrigger.d.vue.ts +2 -2
  240. package/dist/runtime/components/ui/tabs/TabsTrigger.vue +1 -0
  241. package/dist/runtime/components/ui/tabs/TabsTrigger.vue.d.ts +2 -2
  242. package/dist/runtime/components/ui/tags-input/TagsInput.d.vue.ts +3 -3
  243. package/dist/runtime/components/ui/tags-input/TagsInput.vue +1 -0
  244. package/dist/runtime/components/ui/tags-input/TagsInput.vue.d.ts +3 -3
  245. package/dist/runtime/components/ui/tags-input/TagsInputInput.vue +1 -0
  246. package/dist/runtime/components/ui/tags-input/TagsInputItem.d.vue.ts +2 -2
  247. package/dist/runtime/components/ui/tags-input/TagsInputItem.vue +1 -0
  248. package/dist/runtime/components/ui/tags-input/TagsInputItem.vue.d.ts +2 -2
  249. package/dist/runtime/components/ui/tags-input/TagsInputItemDelete.vue +1 -0
  250. package/dist/runtime/components/ui/tags-input/TagsInputItemText.vue +1 -0
  251. package/dist/runtime/components/ui/textarea/Textarea.d.vue.ts +4 -4
  252. package/dist/runtime/components/ui/textarea/Textarea.vue +1 -0
  253. package/dist/runtime/components/ui/textarea/Textarea.vue.d.ts +4 -4
  254. package/dist/runtime/components/ui/toggle/Toggle.d.vue.ts +2 -2
  255. package/dist/runtime/components/ui/toggle/Toggle.vue +1 -0
  256. package/dist/runtime/components/ui/toggle/Toggle.vue.d.ts +2 -2
  257. package/dist/runtime/components/ui/toggle/index.d.ts +1 -1
  258. package/dist/runtime/components/ui/toggle-group/ToggleGroup.d.vue.ts +2 -2
  259. package/dist/runtime/components/ui/toggle-group/ToggleGroup.vue +1 -0
  260. package/dist/runtime/components/ui/toggle-group/ToggleGroup.vue.d.ts +2 -2
  261. package/dist/runtime/components/ui/toggle-group/ToggleGroupItem.vue +1 -0
  262. package/dist/runtime/components/ui/tooltip/TooltipContent.d.vue.ts +2 -2
  263. package/dist/runtime/components/ui/tooltip/TooltipContent.vue +1 -0
  264. package/dist/runtime/components/ui/tooltip/TooltipContent.vue.d.ts +2 -2
  265. package/dist/runtime/composables/useAPI.d.ts +2 -2
  266. package/dist/runtime/composables/useAPI.js +6 -11
  267. package/dist/runtime/composables/useViewAPI.d.ts +1 -0
  268. package/dist/runtime/composables/useViewAPI.js +20 -4
  269. package/dist/runtime/composables/useWindowSizer.d.ts +14 -0
  270. package/dist/runtime/composables/useWindowSizer.js +48 -0
  271. package/dist/runtime/core/config.d.ts +78 -48
  272. package/dist/runtime/core/config.js +21 -27
  273. package/dist/runtime/core/stepper/Stepper.d.ts +13 -10
  274. package/dist/runtime/core/stepper/Stepper.js +70 -55
  275. package/dist/runtime/core/stepper/StepperSerializer.js +32 -14
  276. package/dist/runtime/core/timeline/Timeline.js +1 -2
  277. package/dist/runtime/css/main.css +1 -1
  278. package/dist/runtime/css/smile.css +1 -1
  279. package/dist/runtime/layouts/development.vue +38 -78
  280. package/dist/runtime/layouts/experiment.d.vue.ts +7 -10
  281. package/dist/runtime/layouts/experiment.vue +13 -0
  282. package/dist/runtime/layouts/experiment.vue.d.ts +7 -10
  283. package/dist/runtime/layouts/presentation.vue +24 -3
  284. package/dist/runtime/middleware/timeline.global.js +2 -4
  285. package/dist/runtime/pages/[...slug].vue +2 -0
  286. package/dist/runtime/pages/dev/[...slug].vue +2 -0
  287. package/dist/runtime/pages/dev-login.vue +5 -3
  288. package/dist/runtime/pages/presentation/[...slug].vue +2 -0
  289. package/dist/runtime/plugins/dev-sync.client.js +0 -2
  290. package/dist/runtime/plugins/seed.client.js +1 -3
  291. package/dist/runtime/plugins/store-sync.client.js +8 -10
  292. package/dist/runtime/public/images/helpus.png +0 -0
  293. package/dist/runtime/public/images/smile.svg +78 -0
  294. package/dist/runtime/public/images/universitylogo.png +0 -0
  295. package/dist/runtime/server/api/auth/login.post.js +11 -2
  296. package/dist/runtime/server/api/db-info.get.d.ts +5 -0
  297. package/dist/runtime/server/api/db-info.get.js +10 -0
  298. package/dist/runtime/server/api/qr.get.js +1 -2
  299. package/dist/runtime/server/middleware/dev-auth.js +10 -5
  300. package/dist/runtime/stores/log.js +4 -7
  301. package/dist/runtime/stores/smilestore.d.ts +161 -1014
  302. package/dist/runtime/stores/smilestore.js +39 -7
  303. package/dist/runtime/utils/utils.js +7 -0
  304. package/package.json +5 -3
  305. package/dist/runtime/components/dev/navbar/ViewButton.vue +0 -159
  306. package/dist/runtime/pages/info.vue +0 -462
  307. /package/dist/runtime/components/{dev/navbar/ViewButton.d.vue.ts → builtins/LocalDevBanner.d.vue.ts} +0 -0
  308. /package/dist/runtime/components/{dev/navbar/ViewButton.vue.d.ts → builtins/LocalDevBanner.vue.d.ts} +0 -0
  309. /package/dist/runtime/{pages/info.d.vue.ts → components/dev/SmileDevPresentationView.d.vue.ts} +0 -0
  310. /package/dist/runtime/{pages/info.vue.d.ts → components/dev/SmileDevPresentationView.vue.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { ref, computed, onMounted } from "vue";
2
+ import { computed, ref, onMounted } from "vue";
3
3
  import { Toaster } from "vue-sonner";
4
4
  import "vue-sonner/style.css";
5
5
  import SmileDevAppMenu from "#smile-dev/menu/SmileDevAppMenu.vue";
@@ -7,54 +7,20 @@ import DevNavBar from "#smile-dev/navbar/SmileDevNavBar.vue";
7
7
  import DevConsole from "#smile-dev/console/SmileDevConsole.vue";
8
8
  import DevSideBar from "#smile-dev/sidebar/SmileDevSideBar.vue";
9
9
  import ResponsiveDeviceContainer from "#smile-dev/ResponsiveDeviceContainer.vue";
10
+ import SmileDevPresentationView from "#smile-dev/SmileDevPresentationView.vue";
11
+ import useWindowSizer from "#smile-composables/useWindowSizer";
10
12
  const api = useAPI();
11
- const dashboardUrl = ref("");
12
- const dashboardIframe = ref(null);
13
+ const { showAggressiveOverlay } = useWindowSizer({ useDeviceContainer: true });
13
14
  const height_pct = computed(() => `${api.store.dev.consoleBarHeight}px`);
15
+ const mounted = ref(false);
16
+ onMounted(() => {
17
+ mounted.value = true;
18
+ });
14
19
  const isLoading = computed(() => {
15
- return api.currentRouteName() === void 0;
20
+ return !mounted.value;
16
21
  });
17
- function initializeDashboardUrl() {
18
- const savedUrl = localStorage.getItem("smile-dashboard-url");
19
- if (savedUrl) {
20
- dashboardUrl.value = savedUrl;
21
- } else {
22
- dashboardUrl.value = api.getPublicUrl("dashboard.html");
23
- }
24
- }
25
- function saveDashboardUrl(url) {
26
- localStorage.setItem("smile-dashboard-url", url);
27
- dashboardUrl.value = url;
28
- }
29
- function monitorIframeUrl() {
30
- if (!dashboardIframe.value) return;
31
- try {
32
- const iframeDoc = dashboardIframe.value.contentDocument || dashboardIframe.value.contentWindow?.document;
33
- if (iframeDoc) {
34
- const currentUrl = dashboardIframe.value.contentWindow.location.href;
35
- if (currentUrl !== dashboardUrl.value) {
36
- saveDashboardUrl(currentUrl);
37
- }
38
- }
39
- } catch {
40
- console.log("Cannot access iframe content (cross-origin)");
41
- }
42
- }
43
- function onIframeLoad() {
44
- if (!dashboardIframe.value) return;
45
- const interval = setInterval(() => {
46
- if (api.store.dev.mainView !== "dashboard") {
47
- clearInterval(interval);
48
- return;
49
- }
50
- monitorIframeUrl();
51
- }, 1e3);
52
- if (dashboardIframe.value.contentWindow) {
53
- dashboardIframe.value.contentWindow.addEventListener("focus", monitorIframeUrl);
54
- }
55
- }
56
- onMounted(() => {
57
- initializeDashboardUrl();
22
+ const isRouteNotFound = computed(() => {
23
+ return mounted.value && api.currentRouteName() === void 0;
58
24
  });
59
25
  </script>
60
26
 
@@ -82,33 +48,10 @@ onMounted(() => {
82
48
  <SidebarInset>
83
49
  <!-- Main app container for developer mode -->
84
50
  <div class="app-container">
85
- <!-- Analyze Mode - Clean full-screen dashboard -->
86
- <div
87
- v-if="api.store.dev.mainView === 'dashboard'"
88
- class="analyze-container"
89
- >
90
- <iframe
91
- ref="dashboardIframe"
92
- :src="dashboardUrl"
93
- class="dashboard-iframe"
94
- frameborder="0"
95
- title="Dashboard"
96
- @load="onIframeLoad"
97
- />
98
- </div>
99
-
100
- <!-- Recruit Mode - Clean full-screen recruit page -->
101
- <div
102
- v-else-if="api.store.dev.mainView === 'recruit'"
103
- class="recruit-container"
104
- >
105
- <iframe
106
- :src="api.getPublicUrl('recruit.html')"
107
- class="recruit-iframe"
108
- frameborder="0"
109
- title="Recruit"
110
- />
111
- </div>
51
+ <!-- Presentation Mode - inline (shares DOM and store for dark mode sync) -->
52
+ <SmileDevPresentationView
53
+ v-if="api.store.dev.mainView === 'presentation'"
54
+ />
112
55
 
113
56
  <!-- Docs Mode - Clean full-screen documentation -->
114
57
  <div
@@ -125,6 +68,7 @@ onMounted(() => {
125
68
 
126
69
  <!-- Developer Mode - Full interface with toolbar, sidebar, console -->
127
70
  <template v-else>
71
+ <LocalDevBanner />
128
72
  <!-- Top toolbar with navigation controls -->
129
73
  <div class="toolbar">
130
74
  <DevNavBar />
@@ -135,7 +79,7 @@ onMounted(() => {
135
79
  <!-- Main content area with console -->
136
80
  <div class="content-and-console">
137
81
  <!-- Main content - scrollable experiment container -->
138
- <div class="main-content @container bg-background text-foreground">
82
+ <div class="main-content @container bg-background text-foreground relative">
139
83
  <!-- Loading state -->
140
84
  <div
141
85
  v-if="isLoading"
@@ -144,10 +88,26 @@ onMounted(() => {
144
88
  <div class="loading-spinner" />
145
89
  <p>Loading...</p>
146
90
  </div>
91
+ <!-- Route not found -->
92
+ <div
93
+ v-else-if="isRouteNotFound"
94
+ class="loading-container"
95
+ >
96
+ <p class="not-found-title">
97
+ Route Not Found
98
+ </p>
99
+ <p class="not-found-message">
100
+ The path <code>{{ api.route.path }}</code> is not registered in the timeline.
101
+ </p>
102
+ </div>
147
103
  <!-- Experiment content via slot -->
148
104
  <template v-else>
149
105
  <ResponsiveDeviceContainer>
150
- <slot />
106
+ <WindowSizerView
107
+ v-if="showAggressiveOverlay"
108
+ triggered
109
+ />
110
+ <slot v-else />
151
111
  </ResponsiveDeviceContainer>
152
112
  </template>
153
113
  </div>
@@ -155,7 +115,7 @@ onMounted(() => {
155
115
  <!-- Bottom console - can be toggled -->
156
116
  <Transition name="console-slide">
157
117
  <div
158
- v-if="api.config.mode == 'development' && api.store.dev.showConsoleBar"
118
+ v-if="api.store.dev.showConsoleBar"
159
119
  class="console"
160
120
  >
161
121
  <DevConsole />
@@ -166,7 +126,7 @@ onMounted(() => {
166
126
  <!-- Sidebar - can be toggled, transitions in/out -->
167
127
  <Transition name="sidebar-slide">
168
128
  <div
169
- v-if="api.config.mode == 'development' && api.store.dev.showSideBar"
129
+ v-if="api.store.dev.showSideBar"
170
130
  class="sidebar"
171
131
  >
172
132
  <DevSideBar />
@@ -181,9 +141,9 @@ onMounted(() => {
181
141
  </template>
182
142
 
183
143
  <style>
184
- .custom-toaster{--toast-offset-x:60px;--toast-offset-y:50px;left:var(--toast-offset-x)!important;top:var(--toast-offset-y)!important}
144
+ .custom-toaster{--toast-offset-x:60px;--toast-offset-y:50px;left:var(--toast-offset-x)!important;top:var(--toast-offset-y)!important}[data-slot=sidebar-wrapper]{height:100vh;min-height:0!important;overflow:hidden}
185
145
  </style>
186
146
 
187
147
  <style scoped>
188
- .app-container{display:flex;flex-direction:column;height:100vh;width:100%}.analyze-container,.docs-container,.recruit-container{height:100vh;overflow:hidden;width:100%}.dashboard-iframe,.docs-iframe,.recruit-iframe{border:none;height:100%;overflow:hidden;width:100%}.toolbar{background-color:var(--dev-bar-bg);height:36px;margin-bottom:auto;margin-top:auto;width:full}.content-wrapper{display:flex;flex:1;overflow:hidden;width:100%}.content-and-console{flex-direction:column;overflow:hidden}.content-and-console,.main-content{display:flex;flex:1;min-height:0;min-width:0}.main-content{flex-direction:column;overflow-x:auto;overflow-y:auto}.sidebar{background-color:var(--dev-bg);border-left:1px solid var(--border);flex:0 0 300px;height:100%;overflow-y:auto}.console{background-color:#adadad;height:v-bind(height_pct);max-width:100%;min-width:0;overflow:hidden;overflow-x:hidden;width:100%}.sidebar-slide-enter-active,.sidebar-slide-leave-active{transition:all .3s ease-in-out}.sidebar-slide-enter-from,.sidebar-slide-leave-to{flex:0 0 0px;overflow:hidden;width:0}.console-slide-enter-active,.console-slide-leave-active{transition:height .3s ease-in-out}.console-slide-enter-from,.console-slide-leave-to{height:0}.loading-container{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;min-height:200px}.loading-spinner{animation:spin 1s linear infinite;border:4px solid #f3f3f3;border-radius:50%;border-top-color:#3498db;height:40px;margin-bottom:16px;width:40px}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
148
+ .app-container{display:flex;flex-direction:column}.app-container,.docs-container{height:100vh;overflow:hidden;width:100%}.docs-iframe{border:none;height:100%;overflow:hidden;width:100%}.toolbar{background-color:var(--dev-bar-bg);height:36px;margin-bottom:auto;margin-top:auto;width:full}.content-wrapper{display:flex;flex:1;overflow:hidden;width:100%}.content-and-console{flex-direction:column;overflow:hidden}.content-and-console,.main-content{display:flex;flex:1;min-height:0;min-width:0}.main-content{flex-direction:column;overflow-x:auto;overflow-y:auto}.sidebar{background-color:var(--dev-bg);border-left:1px solid var(--dev-lines);flex:0 0 300px;height:100%;overflow-y:auto}.console{background-color:var(--muted);border-top:1px solid var(--dev-lines);height:v-bind(height_pct);max-width:100%;min-width:0;overflow:hidden;overflow-x:hidden;width:100%}.sidebar-slide-enter-active,.sidebar-slide-leave-active{transition:all .3s ease-in-out}.sidebar-slide-enter-from,.sidebar-slide-leave-to{flex:0 0 0px;overflow:hidden;width:0}.console-slide-enter-active,.console-slide-leave-active{transition:height .3s ease-in-out}.console-slide-enter-from,.console-slide-leave-to{height:0}.loading-container{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;min-height:200px}.loading-spinner{animation:spin 1s linear infinite;border-top:4px solid var(--spinner-track);border:4px solid var(--spinner-track);border-radius:50%;border-top-color:var(--spinner-active);height:40px;margin-bottom:16px;width:40px}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.not-found-title{color:var(--destructive);font-size:1.25rem;font-weight:600;margin-bottom:8px}.not-found-message{color:var(--muted-foreground);font-size:.875rem}.not-found-message code{background-color:var(--muted);border-radius:4px;font-size:.8rem;padding:2px 6px}
189
149
  </style>
@@ -1,13 +1,10 @@
1
- declare var __VLS_12: {};
2
- type __VLS_Slots = {} & {
3
- default?: (props: typeof __VLS_12) => any;
4
- };
5
- declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
1
  declare const _default: typeof __VLS_export;
8
2
  export default _default;
9
- type __VLS_WithSlots<T, S> = T & {
10
- new (): {
11
- $slots: S;
12
- };
3
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
4
+ type __VLS_WithSlots<T, S> = T & (new () => {
5
+ $slots: S;
6
+ });
7
+ declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
+ type __VLS_Slots = {
9
+ default?: ((props: {}) => any) | undefined;
13
10
  };
@@ -1,10 +1,23 @@
1
+ <script setup>
2
+ import useWindowSizer from "#smile-composables/useWindowSizer";
3
+ const { showAggressiveOverlay } = useWindowSizer();
4
+ </script>
5
+
1
6
  <template>
2
7
  <div class="@container bg-background text-foreground experiment-container flex flex-col h-screen">
3
8
  <ClientOnly>
9
+ <LocalDevBanner />
4
10
  <ExperimentStatusBar />
5
11
  </ClientOnly>
6
12
  <div class="flex-1 min-h-0 overflow-auto">
7
13
  <slot />
8
14
  </div>
15
+ <!-- Aggressive window sizer overlay -->
16
+ <div
17
+ v-if="showAggressiveOverlay"
18
+ class="fixed inset-0 z-50 bg-background/95 overflow-auto"
19
+ >
20
+ <WindowSizerView triggered />
21
+ </div>
9
22
  </div>
10
23
  </template>
@@ -1,13 +1,10 @@
1
- declare var __VLS_12: {};
2
- type __VLS_Slots = {} & {
3
- default?: (props: typeof __VLS_12) => any;
4
- };
5
- declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
1
  declare const _default: typeof __VLS_export;
8
2
  export default _default;
9
- type __VLS_WithSlots<T, S> = T & {
10
- new (): {
11
- $slots: S;
12
- };
3
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
4
+ type __VLS_WithSlots<T, S> = T & (new () => {
5
+ $slots: S;
6
+ });
7
+ declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
+ type __VLS_Slots = {
9
+ default?: ((props: {}) => any) | undefined;
13
10
  };
@@ -1,9 +1,16 @@
1
1
  <script setup>
2
- import { computed } from "vue";
2
+ import { computed, ref, onMounted } from "vue";
3
3
  import PresentationNavBar from "#smile-dev/presentation/PresentationNavBar.vue";
4
4
  const api = useAPI();
5
+ const mounted = ref(false);
6
+ onMounted(() => {
7
+ mounted.value = true;
8
+ });
5
9
  const isLoading = computed(() => {
6
- return api.currentRouteName() === void 0;
10
+ return !mounted.value;
11
+ });
12
+ const isRouteNotFound = computed(() => {
13
+ return mounted.value && api.currentRouteName() === void 0;
7
14
  });
8
15
  </script>
9
16
 
@@ -11,6 +18,8 @@ const isLoading = computed(() => {
11
18
  <ClientOnly>
12
19
  <!-- Main app container for presentation mode -->
13
20
  <div class="app-container">
21
+ <LocalDevBanner />
22
+
14
23
  <!-- Top toolbar with navigation -->
15
24
  <div class="toolbar">
16
25
  <PresentationNavBar />
@@ -29,6 +38,18 @@ const isLoading = computed(() => {
29
38
  <div class="loading-spinner" />
30
39
  <p>Loading...</p>
31
40
  </div>
41
+ <!-- Route not found -->
42
+ <div
43
+ v-else-if="isRouteNotFound"
44
+ class="loading-container"
45
+ >
46
+ <p class="not-found-title">
47
+ Route Not Found
48
+ </p>
49
+ <p class="not-found-message">
50
+ The path <code>{{ api.route.path }}</code> is not registered in the timeline.
51
+ </p>
52
+ </div>
32
53
  <!-- Main app content via slot -->
33
54
  <template v-else>
34
55
  <slot />
@@ -41,5 +62,5 @@ const isLoading = computed(() => {
41
62
  </template>
42
63
 
43
64
  <style scoped>
44
- .app-container{display:flex;flex-direction:column;height:100vh;width:100%}.toolbar{background-color:var(--dev-bar-bg);height:36px;margin-bottom:auto;margin-top:auto;width:full}.content-wrapper{display:flex;flex:1;overflow:hidden;width:100%}.content-and-console{flex-direction:column;overflow:hidden}.content-and-console,.main-content{display:flex;flex:1;min-height:0;min-width:0}.main-content{flex-direction:column;overflow-x:auto;overflow-y:auto}.loading-container{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;min-height:200px}.loading-spinner{animation:spin 1s linear infinite;border:4px solid #f3f3f3;border-radius:50%;border-top-color:#3498db;height:40px;margin-bottom:16px;width:40px}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
65
+ .app-container{display:flex;flex-direction:column;height:100vh;width:100%}.toolbar{background-color:var(--dev-bar-bg);height:36px;margin-bottom:auto;margin-top:auto;width:full}.content-wrapper{display:flex;flex:1;overflow:hidden;width:100%}.content-and-console{flex-direction:column;overflow:hidden}.content-and-console,.main-content{display:flex;flex:1;min-height:0;min-width:0}.main-content{flex-direction:column;overflow-x:auto;overflow-y:auto}.loading-container{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;min-height:200px}.loading-spinner{animation:spin 1s linear infinite;border-top:4px solid var(--spinner-track);border:4px solid var(--spinner-track);border-radius:50%;border-top-color:var(--spinner-active);height:40px;margin-bottom:16px;width:40px}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.not-found-title{color:var(--destructive);font-size:1.25rem;font-weight:600;margin-bottom:8px}.not-found-message{color:var(--muted-foreground);font-size:.875rem}.not-found-message code{background-color:var(--muted);border-radius:4px;font-size:.8rem;padding:2px 6px}
45
66
  </style>
@@ -6,15 +6,13 @@
6
6
  * route (`/:slug(.*)*`). So we look up route metadata from $timeline.routes
7
7
  * instead of Vue Router's to.meta / from.meta.
8
8
  */
9
- import * as _seedrandom from 'seedrandom'
9
+ import seedrandom from 'seedrandom'
10
10
  import { v4 as uuidv4 } from 'uuid'
11
11
  import { defineNuxtRouteMiddleware, useNuxtApp, navigateTo } from '#imports'
12
12
  import useSmileStore from '../stores/smilestore.js'
13
13
  import useLog from '../stores/log.js'
14
14
  import { getQueryParams, processQuery, initService } from '../utils/utils.js'
15
15
 
16
- const seedrandom = _seedrandom.default || _seedrandom
17
-
18
16
  /**
19
17
  * Core guard logic extracted for testability.
20
18
  * Returns the guard decision, then runs post-guard logic if navigation is allowed.
@@ -332,7 +330,7 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
332
330
  return
333
331
  }
334
332
  // Skip guards for standalone pages that aren't part of the experiment timeline
335
- if (to.path === '/info' || to.path === '/dev-login') {
333
+ if (to.path === '/dev-login') {
336
334
  return
337
335
  }
338
336
 
@@ -13,6 +13,8 @@
13
13
  </template>
14
14
 
15
15
  <script setup>
16
+ import { ref, computed, onMounted, watch } from "vue";
17
+ import { useRoute, useNuxtApp, navigateTo } from "#imports";
16
18
  const route = useRoute();
17
19
  const nuxtApp = useNuxtApp();
18
20
  const timelineReady = ref(false);
@@ -17,6 +17,8 @@
17
17
  </template>
18
18
 
19
19
  <script setup>
20
+ import { ref, computed, onMounted, watch } from "vue";
21
+ import { useRoute, useNuxtApp, navigateTo } from "#imports";
20
22
  import RecruitmentChooserView from "#smile-dev/RecruitmentChooserView.vue";
21
23
  const route = useRoute();
22
24
  const nuxtApp = useNuxtApp();
@@ -30,10 +30,12 @@
30
30
 
31
31
  <script setup>
32
32
  import { ref } from "vue";
33
- import { navigateTo } from "#imports";
33
+ import { navigateTo, useRoute } from "#imports";
34
+ const route = useRoute();
34
35
  const password = ref("");
35
36
  const error = ref("");
36
37
  const loading = ref(false);
38
+ const redirectTo = route.query.redirect || "/dev/";
37
39
  async function login() {
38
40
  error.value = "";
39
41
  loading.value = true;
@@ -42,7 +44,7 @@ async function login() {
42
44
  method: "POST",
43
45
  body: { password: password.value }
44
46
  });
45
- await navigateTo("/dev/", { replace: true });
47
+ await navigateTo(redirectTo, { replace: true, external: true });
46
48
  } catch (err) {
47
49
  error.value = err.statusCode === 401 ? "Invalid password" : "Login failed";
48
50
  } finally {
@@ -52,5 +54,5 @@ async function login() {
52
54
  </script>
53
55
 
54
56
  <style scoped>
55
- .dev-login{align-items:center;background:#f5f5f5;display:flex;font-family:system-ui,-apple-system,sans-serif;justify-content:center;min-height:100vh}.login-card{background:#fff;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.1);max-width:400px;padding:2rem;width:100%}.login-card h2{font-size:1.25rem;margin:0 0 .5rem}.login-card p{color:#666;font-size:.875rem;margin:0 0 1rem}form{display:flex;flex-direction:column;gap:.75rem}input{border:1px solid #ccc;border-radius:4px;padding:.5rem .75rem}button,input{font-size:1rem}button{background:#333;border:none;border-radius:4px;color:#fff;cursor:pointer;padding:.5rem 1rem}button:hover:not(:disabled){background:#555}button:disabled{cursor:not-allowed;opacity:.6}.error{color:#c00;margin:0}
57
+ .dev-login{align-items:center;background:var(--muted);display:flex;font-family:system-ui,-apple-system,sans-serif;justify-content:center;min-height:100vh}.login-card{background:var(--background);border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.1);max-width:400px;padding:2rem;width:100%}.login-card h2{color:var(--foreground);font-size:1.25rem;margin:0 0 .5rem}.login-card p{color:var(--muted-foreground);font-size:.875rem;margin:0 0 1rem}form{display:flex;flex-direction:column;gap:.75rem}input{background:var(--background);border:1px solid var(--border);border-radius:4px;color:var(--foreground);padding:.5rem .75rem}button,input{font-size:1rem}button{background:var(--primary);border:none;border-radius:4px;color:var(--primary-foreground);cursor:pointer;padding:.5rem 1rem}button:hover:not(:disabled){background:var(--primary);opacity:.85}button:disabled{cursor:not-allowed;opacity:.6}.error{color:var(--destructive);margin:0}
56
58
  </style>
@@ -20,6 +20,8 @@
20
20
  </template>
21
21
 
22
22
  <script setup>
23
+ import { ref, computed, onMounted, watch } from "vue";
24
+ import { useRoute, useNuxtApp, navigateTo } from "#imports";
23
25
  import PresentationModeView from "../../components/builtins/PresentationModeView.vue";
24
26
  import useSmileStore from "../../stores/smilestore";
25
27
  const route = useRoute();
@@ -9,8 +9,6 @@ import useSmileStore from '../stores/smilestore.js'
9
9
  import appconfig from '../core/config.js'
10
10
 
11
11
  export default defineNuxtPlugin(() => {
12
- if (appconfig.mode !== 'development') return
13
-
14
12
  const store = useSmileStore()
15
13
  const cookieName = `smile_${appconfig.codeName}_dev`
16
14
 
@@ -10,11 +10,9 @@
10
10
  */
11
11
  import { defineNuxtPlugin } from '#imports'
12
12
  import { v4 as uuidv4 } from 'uuid'
13
- import * as _seedrandom from 'seedrandom'
13
+ import seedrandom from 'seedrandom'
14
14
  import useSmileStore from '../stores/smilestore.js'
15
15
 
16
- const seedrandom = _seedrandom.default || _seedrandom
17
-
18
16
  export default defineNuxtPlugin(() => {
19
17
  const store = useSmileStore()
20
18
 
@@ -52,16 +52,14 @@ export default defineNuxtPlugin((nuxtApp) => {
52
52
  )
53
53
 
54
54
  // --- 3. Watch store.dev — reset to defaults if externally cleared to null ---
55
- if (appconfig.mode === 'development') {
56
- watch(
57
- () => store.dev,
58
- (val) => {
59
- if (val === null || val === undefined) {
60
- store.dev = { ...initDev }
61
- }
62
- },
63
- )
64
- }
55
+ watch(
56
+ () => store.dev,
57
+ (val) => {
58
+ if (val === null || val === undefined) {
59
+ store.dev = { ...initDev }
60
+ }
61
+ },
62
+ )
65
63
 
66
64
  // --- 4. Watch localState → localStorage ---
67
65
  watch(
@@ -0,0 +1,78 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="devmode" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 435 185">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #f3bf21;
7
+ }
8
+
9
+ .cls-2 {
10
+ fill: #cc9005;
11
+ }
12
+
13
+ .cls-3 {
14
+ fill: #43330e;
15
+ }
16
+
17
+ .cls-4 {
18
+ fill: #f2b73d;
19
+ }
20
+
21
+ .cls-5 {
22
+ fill: #fefefe;
23
+ }
24
+ </style>
25
+ </defs>
26
+ <g id="smile">
27
+ <g>
28
+ <path class="cls-5" d="M89.73,150.44c11.39-12.62,12.89-32.13,3.67-46.4-11.25-17.4-25.33-23.15-39.48-36.29-1.67-1.55-2.95-2.67-3.45-5-1.63-7.64,3.94-13.77,11.71-11.42.9.27,3.78,1.84,4.14,2.62.6,1.31-.2,4.64.21,6.26.08.3,2.92,4.48,3.36,5.09.66.91,1.3,1.89,2.27,2.51,7.87.36,15.93.35,23.8,0,.87-.37,1.1-1.32,1.2-2.18,1-8.79-3.37-23.63-7.94-31.21-11.47-19-41.2-24.67-58.13-9.78-14.08,12.39-17.58,36.13-8.45,52.4,6.23,11.09,24.81,22.52,34.93,30.98,3.05,2.55,8.18,6.54,8.81,10.62,1.25,8.06-4.37,12.97-12.18,12.18-2.45-.25-4.02-1.79-4.53-4.2-.48-2.29.01-7.12-.62-8.68-.2-.5-1.3-1.47-1.76-1.91-1.4-1.34-4.82-4.2-6.61-4.37-7.57-.71-16.25.54-23.94.03-.77.1-1.33.54-1.51,1.31-.89,11.28.75,22.23,8.12,31.12,15.42,18.59,48.78,25.79,66.36,6.31ZM378.88,55.64h27.47c.75,0,10.89-6.1,12.4-7.03,1.27-.79,1.41-1.17,1.55-2.67.75-8.03-.59-17.21,0-25.37-.23-2.52-1.18-2.79-3.52-2.96l-67.32.04c-1.28.18-9.78,5.89-11.24,7.07-.52.42-1.6,1.38-1.6,2.06v98.43h-34.65l-.34-105.69c-.23-.82-.92-1.49-1.79-1.59-8.13.63-17.65-.88-25.64-.04-1.4.15-2.01.9-2.95,1.84-1.86,1.87-3.4,4.33-5.47,6.07l-.44,1.25c-.31,42.23.57,84.55-.29,126.73-.06,2.95-1,7.92,3.24,7.49h62.85c1.63.35,4.22-2.25,5.33-2.27.15,0,.56,1.5,1.29,1.83.67.3,1.89.23,2.66.44l68.13-.07c1.78-1.28,10.92-5.22,11.41-6.9l.07-27.55c.2-.56-.94-1.54-1.28-1.54h-39.58v-18.87h18.17c3.74-2.34,9.21-3.75,12.79-6.08,1.1-.71,1.34-2.13,1.44-3.35.64-7.47-.51-15.83,0-23.4.17-.77-1.31-1.82-1.85-1.82h-30.85v-16.05ZM136.24,18.55c-.55-.48-1.02-.6-1.72-.67-9.18-.87-19.72.7-29.05,0-.6.03-1.88.77-2.05,1.33l.1,136.1c1.36,1.39,4.95,5.61,6.76,5.91,8.74-.1,17.56.29,26.25-.2l.78-.63-.14-63.93c.4-.07.37.47.49.77,5.41,13.73,9.85,27.86,15.33,41.57.22.43.46.65.95.74,1.45.28,6.8.16,8.46.02,1.49-.13,1.39-.16,1.95-1.42l15.64-42.24-.07,64.14c.4.87,1.85,1.13,2.74,1.21,8.18.72,17.37-.57,25.66,0,.42.03.8-.07,1.18-.23s5.04-4.72,5.42-5.28c.31-.45.59-.81.57-1.4-.15-45.08.28-90.22-.22-135.26-.44-.84-1.23-1.25-2.17-1.21-10.25.74-21.76-.93-31.86,0-3.51.33-2.9,3.55-4.36,6.06l-18.73,52.53-21.92-57.93ZM258.79,18.55c-.36-.45-1.18-.61-1.73-.66-8.94-.85-19.31.62-28.4.09-2.91.49-5.92,6.07-7.76,8.3l-.07,132.04c.19,2,.88,2.45,2.76,2.87l28.37.05c2.84-1.62,4.86-4.37,7.43-6.37.33-44.98-.38-89.89-.22-134.87-.02-.51-.04-1.04-.38-1.46Z"/>
29
+ <g>
30
+ <g>
31
+ <g>
32
+ <path class="cls-3" d="M89.73,150.44c-17.58,19.48-50.94,12.27-66.36-6.31-7.37-8.89-9.01-19.84-8.12-31.12.18-.77.73-1.21,1.51-1.31,7.69.51,16.37-.74,23.94-.03,1.79.17,5.21,3.04,6.61,4.37.46.44,1.55,1.4,1.76,1.91.63,1.56.14,6.39.62,8.68.5,2.42,2.08,3.96,4.53,4.2,7.82.79,13.44-4.12,12.18-12.18-.64-4.08-5.76-8.07-8.81-10.62-10.12-8.46-28.71-19.89-34.93-30.98-9.13-16.26-5.64-40,8.45-52.4,16.93-14.89,46.66-9.22,58.13,9.78,4.57,7.57,8.94,22.42,7.94,31.21-.1.86-.32,1.81-1.2,2.18-7.87.35-15.93.35-23.8,0-.98-.62-1.61-1.6-2.27-2.51-.44-.61-3.29-4.79-3.36-5.09-.42-1.63.38-4.96-.21-6.26-.36-.79-3.23-2.35-4.14-2.62-7.77-2.34-13.34,3.78-11.71,11.42.5,2.33,1.78,3.45,3.45,5,14.15,13.13,28.24,18.89,39.48,36.29,9.22,14.27,7.72,33.78-3.67,46.4ZM68.15,59.02h23.52c.31,0,.4-.69.44-.97,2.14-18.21-8.88-34.15-26.66-38.44-28.38-6.85-48.81,14.17-45.76,42.08,1.5,13.69,8.27,20.06,18.17,28.3,8.05,6.69,21.58,15.2,27.89,22.82,4.92,5.94,3.43,15.7-3.94,18.88-7.45,3.22-20.71-.65-20.71-10.01v-8.03h-24.23c-.67,11.83,1.79,24.12,10.98,32.25,13.57,11.99,38.72,12.78,52.82,1.26,18.45-15.07,16.23-41.02-.69-56.18-6.39-5.73-13.95-11.13-20.42-16.2-8.13-6.36-18.22-10.95-15.84-23.14,2.52-12.89,20.88-14.17,24.02-2.49.88,3.26.49,6.54.41,9.87ZM48.43,62.26c-.09-1.35,0-2.85,0-4.22,0-6.17,6.43-9.68,11.97-9.15,2.14.21,3.82,1.43,5.78,2.11-1.92-10.62-16.71-10.26-20.14-.7-1.45,4.05-.97,10.45,2.67,13.23.2-.48-.26-1-.28-1.27ZM95.19,66.06c.09-3.16-.06-6.29-.28-9.44l-1.13-5.21v8.03c0,1.8-4.59,1.19-5.79,1.26-.67.04-1.28.28-1.95.3-5.48.2-11.01-.17-16.49-.01-.37.34,3.08,4.52,3.52,5.07h22.11ZM87.41,149.8c7.51-7.75,10.86-18.35,10.01-29.21-.29-3.69-1.43-8.45-3.62-11.44,2.03,8.34,2.47,16.32-.8,24.41-7.28,18.02-26.24,26.05-44.9,23.1-2.14-.34-4.31-1.19-6.42-1.19,3.37,2.04,7.34,3.02,11.22,3.71,13.06,2.35,25.13.3,34.52-9.39ZM42.8,115.34v4.37c0,3.03,1.36,6.12,3.66,8.17l2.26,1.4c-1.43-3.31-1.04-6.86-1.47-10.36-.28-.64-4.07-4-4.45-3.58ZM41.39,155.06c-.4-.2-.75.18-.56.28.4.2.75-.18.56-.28Z"/>
33
+ <path class="cls-1" d="M68.15,59.02c.08-3.33.47-6.61-.41-9.87-3.14-11.68-21.5-10.4-24.02,2.49-2.38,12.19,7.71,16.78,15.84,23.14,6.47,5.06,14.03,10.47,20.42,16.2,16.92,15.17,19.14,41.11.69,56.18-14.1,11.52-39.25,10.74-52.82-1.26-9.2-8.13-11.65-20.42-10.98-32.25h24.23v8.03c0,9.35,13.27,13.22,20.71,10.01,7.37-3.19,8.86-12.94,3.94-18.88-6.31-7.62-19.84-16.12-27.89-22.82-9.9-8.24-16.68-14.61-18.17-28.3-3.05-27.91,17.37-48.93,45.76-42.08,17.77,4.29,28.79,20.23,26.66,38.44-.03.28-.13.97-.44.97h-23.52Z"/>
34
+ <path class="cls-2" d="M87.41,149.8c-9.39,9.69-21.46,11.74-34.52,9.39-3.87-.7-7.84-1.67-11.22-3.71,2.11,0,4.28.85,6.42,1.19,18.66,2.95,37.62-5.08,44.9-23.1,3.27-8.09,2.82-16.07.8-24.41,2.2,2.99,3.33,7.75,3.62,11.44.85,10.86-2.49,21.46-10.01,29.21Z"/>
35
+ <path class="cls-2" d="M48.43,62.26c.02.27.48.79.28,1.27-3.64-2.78-4.12-9.18-2.67-13.23,3.42-9.57,18.22-9.92,20.14.7-1.96-.68-3.64-1.9-5.78-2.11-5.54-.53-11.97,2.98-11.97,9.15,0,1.37-.09,2.88,0,4.22Z"/>
36
+ <path class="cls-2" d="M95.19,66.06h-22.11c-.44-.55-3.89-4.73-3.52-5.07,5.48-.16,11.01.21,16.49.01.67-.02,1.28-.27,1.95-.3,1.2-.07,5.79.54,5.79-1.26v-8.03l1.13,5.21c.22,3.15.37,6.28.28,9.44Z"/>
37
+ <path class="cls-2" d="M42.8,115.34c.39-.42,4.17,2.93,4.45,3.58.42,3.5.04,7.05,1.47,10.36l-2.26-1.4c-2.3-2.05-3.66-5.14-3.66-8.17v-4.37Z"/>
38
+ <path class="cls-4" d="M41.39,155.06c.19.1-.16.48-.56.28-.19-.1.16-.48.56-.28Z"/>
39
+ </g>
40
+ <g>
41
+ <g>
42
+ <path class="cls-3" d="M136.24,18.55l21.92,57.93,18.73-52.53c1.47-2.51.85-5.74,4.36-6.06,10.1-.94,21.61.73,31.86,0,.94-.04,1.73.37,2.17,1.21.5,45.04.06,90.18.22,135.26.02.6-.26.95-.57,1.4-.39.55-5.02,5.12-5.42,5.28s-.76.25-1.18.23c-8.29-.57-17.48.71-25.66,0-.88-.08-2.33-.33-2.74-1.21l.07-64.14-15.64,42.24c-.55,1.26-.46,1.3-1.95,1.42-1.66.14-7.01.26-8.46-.02-.48-.09-.73-.32-.95-.74-5.47-13.71-9.91-27.84-15.33-41.57-.12-.3-.08-.84-.49-.77l.14,63.93-.78.63c-8.69.48-17.51.1-26.25.2-1.81-.3-5.4-4.52-6.76-5.91l-.1-136.1c.17-.56,1.45-1.3,2.05-1.33,9.32.69,19.87-.87,29.05,0,.71.07,1.18.19,1.72.67ZM180.27,20.15l-21.16,59.53c-1.3,1.69-2.23-1.12-2.64-2.09-4.55-10.59-8.18-22.67-12.33-33.58-3.08-8.09-6.1-16.27-9.65-24.15h-29.44c-.07.21.28.34.28.42v133.07h25.64v-75.62c0-1.76,1.65-.88,1.83.43l19.62,53.46,12.08-.1c6.31-15.51,11.29-31.67,17.56-47.22.41-1.01,2.79-6.96,3.14-7.28.49-.45,1.27-.24,1.27.14v76.18h27.33l-.28-133.21h-33.24ZM181.68,90.98v66.04c.47-.48,2.94-2.31,3.07-2.72.14-.44-.21-.93-.2-1.36.07-3.05-.05-5.98-.07-9-.13-20.04.13-40.1.01-60.14l-2.81,7.18ZM135.48,156.74l-.27-65.49c.07-.7-1.57-5.19-1.84-5.19-.41,0-.41.95-.44,1.25-.87,11.64,0,25.58.03,37.48.02,9.47-.03,19.16-.03,28.73.17,1.28,1.58,2.48,2.55,3.23ZM163.65,133.65h-10.42c.23.97.97,3.9,1.89,4.17.58.17,6.78.13,7.13-.08.38-.23,1.57-3.93,1.4-4.09ZM134.64,159.28c.32-.8-2.45-3.66-2.68-3.66h-25.21c.07,1.05,1.34,1.5,1.98,2.1.31.29,1.05,1.56,1.26,1.56h24.65ZM212.11,155.62h-26.34c-.25,0-3.09,3.18-3.52,3.66h26.06c.26,0,3.33-3.18,3.8-3.66Z"/>
43
+ <path class="cls-1" d="M180.27,20.15h33.24l.28,133.21h-27.33v-76.18c0-.39-.78-.59-1.27-.14-.35.32-2.74,6.27-3.14,7.28-6.27,15.55-11.25,31.71-17.56,47.22l-12.08.1-19.62-53.46c-.17-1.31-1.83-2.19-1.83-.43v75.62h-25.64V20.3c0-.09-.36-.22-.28-.42h29.44c3.55,7.88,6.57,16.06,9.65,24.15,4.15,10.91,7.78,22.99,12.33,33.58.41.96,1.34,3.77,2.64,2.09l21.16-59.53Z"/>
44
+ <path class="cls-2" d="M181.68,90.98l2.81-7.18c.12,20.04-.14,40.09-.01,60.14.02,3.01.15,5.95.07,9-.01.44.34.92.2,1.36-.13.41-2.61,2.24-3.07,2.72v-66.04Z"/>
45
+ <path class="cls-2" d="M135.48,156.74c-.96-.75-2.37-1.95-2.55-3.23,0-9.56.04-19.25.03-28.73-.02-11.9-.9-25.84-.03-37.48.02-.3.03-1.25.44-1.25.28,0,1.92,4.49,1.84,5.19l.27,65.49Z"/>
46
+ <path class="cls-2" d="M212.11,155.62c-.47.48-3.54,3.66-3.8,3.66h-26.06c.43-.48,3.27-3.66,3.52-3.66h26.34Z"/>
47
+ <path class="cls-2" d="M134.64,159.28h-24.65c-.21,0-.94-1.27-1.26-1.56-.65-.6-1.92-1.05-1.98-2.1h25.21c.23,0,3,2.87,2.68,3.66Z"/>
48
+ <path class="cls-2" d="M163.65,133.65c.17.16-1.03,3.86-1.4,4.09s-6.55.25-7.13.08c-.92-.27-1.66-3.2-1.89-4.17h10.42Z"/>
49
+ </g>
50
+ <g>
51
+ <path class="cls-3" d="M258.79,18.55c.34.42.36.94.38,1.46-.16,44.97.56,89.89.22,134.87-2.58,2-4.59,4.75-7.43,6.37l-28.37-.05c-1.88-.42-2.57-.87-2.76-2.87l.07-132.04c1.84-2.23,4.85-7.81,7.76-8.3,9.09.53,19.46-.93,28.4-.09.55.05,1.37.22,1.73.66ZM257.47,19.86h-29.33s0,133.5,0,133.5h29.33s0-133.5,0-133.5ZM226.4,153.86c.09-21.52.15-43.05.09-64.58,0-.8-.3-1.5-.31-2.23-.07-21.55.2-43.11-.13-64.65-.79,1.55-3.29,3.18-3.53,4.92-.25,20.46.25,40.98.31,61.39.06,22.77-.08,45.54-.01,68.31.43.48,3.08-2.98,3.58-3.17ZM223.66,159.28h27.75c.51,0,4.02-2.85,4.37-3.66-7.65-.14-15.32.18-22.97,0-1.36-.03-2.71-.47-4.23-.31s-3.37,2.27-4.55,3.32c-.19.17-.54-.02-.36.64Z"/>
52
+ <rect class="cls-1" x="228.15" y="19.86" width="29.33" height="133.5"/>
53
+ <path class="cls-2" d="M226.4,153.86c-.5.19-3.15,3.65-3.58,3.17-.06-22.76.08-45.54.01-68.31-.06-20.42-.56-40.94-.31-61.39.24-1.74,2.75-3.36,3.53-4.92.32,21.54.06,43.1.13,64.65,0,.73.3,1.42.31,2.23.06,21.52,0,43.06-.09,64.58Z"/>
54
+ <path class="cls-2" d="M223.66,159.28c-.18-.66.17-.48.36-.64,1.18-1.04,3.08-3.17,4.55-3.32s2.87.28,4.23.31c7.65.17,15.32-.15,22.97,0-.35.81-3.85,3.66-4.37,3.66h-27.75Z"/>
55
+ </g>
56
+ </g>
57
+ </g>
58
+ <g>
59
+ <g>
60
+ <path class="cls-2" d="M299.72,19.87v98.16c.79,2.58-.17,5.96.28,8.44.04.23.22.7.42.7h39.02v26.05l-65.92.14.28-133.49h25.92Z"/>
61
+ <path class="cls-2" d="M267.33,157.87c-.03-26.14.03-52.3.01-78.45,0-13.89-.2-28.11,0-41.94.03-2.12-.43-10.11.25-11.29s3.51-3.18,4.52-4.35c-.47,43.66-.23,87.4-.27,131.1-.23,1.99-3.17,3.6-4.51,4.92Z"/>
62
+ <path class="cls-2" d="M268.45,159.28c-.18-.66.17-.48.36-.64.68-.6,3.48-3.08,4.07-3.23,1.41-.36,2.78.2,4.14.23,20.13.35,40.31-.29,60.44-.01l-5.49,3.66h-63.53Z"/>
63
+ </g>
64
+ <rect class="cls-1" x="273.63" y="19.7" width="27.31" height="133.95"/>
65
+ <rect class="cls-1" x="297.99" y="126.72" width="41.33" height="26.57"/>
66
+ <g>
67
+ <path class="cls-3" d="M378.88,55.64v16.05h30.85c.54,0,2.01,1.05,1.85,1.82-.51,7.57.64,15.93,0,23.4-.1,1.21-.34,2.63-1.44,3.35-3.58,2.33-9.06,3.73-12.79,6.08h-18.17v18.87h39.58c.34,0,1.48.98,1.28,1.54l-.07,27.55c-.49,1.68-9.63,5.62-11.41,6.9l-68.13.07c-.77-.21-1.99-.14-2.66-.44-.73-.33-1.13-1.84-1.29-1.83-1.11.02-3.7,2.62-5.33,2.27h-62.85c-4.24.43-3.3-4.53-3.24-7.49.85-42.18-.02-84.5.29-126.73l.44-1.25c2.08-1.75,3.61-4.2,5.47-6.07.93-.94,1.55-1.69,2.95-1.84,7.99-.85,17.5.66,25.64.04.87.1,1.56.77,1.79,1.59l.34,105.69h34.65V26.77c0-.68,1.08-1.65,1.6-2.06,1.47-1.17,9.96-6.88,11.24-7.07l67.32-.04c2.34.17,3.29.44,3.52,2.96-.59,8.16.75,17.33,0,25.37-.14,1.5-.28,1.88-1.55,2.67-1.51.94-11.65,7.03-12.4,7.03h-27.47ZM418.32,19.59h-68.88l-.14,134.05h68.6s.42-.39.42-.42v-25.77h-40.43c-.82,0-.95-1.21-1-1.82-.73-8.55.58-18.12,0-26.78-.11-.36.49-1.25.72-1.25h31.97v-23.66l-32.27-.25c-.49-.44-.64-1.76-.7-2.42-.56-6.71.43-13.61.3-20.3-.02-1.06-.8-3.4.1-4.1.12-.09,1.61-.54,1.72-.54h39.16s.42-.39.42-.42v-26.33ZM299.72,19.87h-25.92l-.28,133.49,65.92-.14v-26.05h-39.02c-.2,0-.38-.47-.42-.7-.45-2.48.51-5.86-.29-8.44V19.87ZM347.55,153.87l-.23-132.59c-2.91,1.54-5.65,3.51-8.45,5.27.1,32.85-.04,65.68-.29,98.49.07.44,2.84-.53,3.12,2.54.72,7.96-.57,17-.01,25.08-.29,2.58-2.62,3.34-2.78,3.99-.12.48.36,1.22.24,1.78.45.47,7.44-3.96,8.39-4.56ZM267.33,157.87c1.34-1.32,4.28-2.93,4.51-4.92.05-43.7-.2-87.44.27-131.1-1.01,1.17-3.84,3.17-4.52,4.35s-.22,9.17-.25,11.29c-.21,13.82-.01,28.05,0,41.94.01,26.15-.04,52.3-.01,78.45ZM415.22,48.6h-36.62v5.07h27.47l9.16-5.07ZM406.49,99.57h-27.61v4.79h18.45c.37,0,5.06-2.84,6.06-2.95l3.09-1.84ZM268.45,159.28h63.53l5.49-3.66c-20.13-.28-40.31.36-60.44.01-1.36-.02-2.73-.59-4.14-.23-.59.15-3.4,2.63-4.07,3.23-.19.17-.54-.02-.36.64ZM414.66,155.62l-21.84-.02c-14.63,0-29.5.04-44.23,0-1.59.48-3.19,1.34-4.65,2.11-.8.43-1.88.96-2.53,1.55,1.15.29,2.52-.29,3.52-.28,20.89.18,41.89.44,62.84.29l2.39-.99,4.49-2.68Z"/>
68
+ <path class="cls-1" d="M418.32,19.59v26.33s-.39.42-.42.42h-39.16c-.11,0-1.6.45-1.72.54-.9.7-.12,3.04-.1,4.1.13,6.69-.86,13.6-.3,20.3.05.66.21,1.98.7,2.42l32.27.25v23.66h-31.97c-.23,0-.83.9-.72,1.25.58,8.66-.73,18.23,0,26.78.05.61.17,1.82,1,1.82h40.43v25.77s-.39.42-.42.42h-68.6l.14-134.05h68.88Z"/>
69
+ <path class="cls-2" d="M347.55,153.87c-.95.6-7.94,5.03-8.39,4.56.12-.56-.36-1.3-.24-1.78.16-.66,2.48-1.41,2.78-3.99-.55-8.08.74-17.12.01-25.08-.28-3.07-3.05-2.1-3.12-2.54.25-32.81.38-65.64.29-98.49,2.8-1.76,5.54-3.73,8.45-5.27l.23,132.59Z"/>
70
+ <path class="cls-2" d="M414.66,155.62l-4.49,2.68-2.39.99c-20.94.15-41.94-.11-62.84-.29-1,0-2.37.57-3.52.28.65-.59,1.73-1.13,2.53-1.55,1.46-.78,3.06-1.64,4.65-2.11,14.73.03,29.6-.02,44.23,0l21.84.02Z"/>
71
+ <polygon class="cls-2" points="415.22 48.6 406.07 53.67 378.6 53.67 378.6 48.6 415.22 48.6"/>
72
+ <path class="cls-2" d="M406.49,99.57l-3.09,1.84c-1.01.11-5.69,2.95-6.06,2.95h-18.45v-4.79h27.61Z"/>
73
+ </g>
74
+ </g>
75
+ </g>
76
+ </g>
77
+ </g>
78
+ </svg>
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { defineEventHandler, readBody, createError, setCookie } from "h3";
3
3
  import { useRuntimeConfig } from "nitropack/runtime";
4
+ import bcrypt from "bcryptjs";
4
5
  import { useDB } from "../../utils/db.js";
5
6
  import { devSessions } from "../../database/schema.js";
6
7
  export default defineEventHandler(async (event) => {
@@ -10,7 +11,14 @@ export default defineEventHandler(async (event) => {
10
11
  if (!devPassword) {
11
12
  throw createError({ statusCode: 500, statusMessage: "Dev password not configured" });
12
13
  }
13
- if (body.password !== devPassword) {
14
+ let isValid;
15
+ if (devPassword.startsWith("$2")) {
16
+ isValid = await bcrypt.compare(body.password, devPassword);
17
+ } else {
18
+ console.warn("[smile] Dev password is stored in plaintext. Run `pnpm smile:hash-password` to generate a hashed version.");
19
+ isValid = body.password === devPassword;
20
+ }
21
+ if (!isValid) {
14
22
  throw createError({ statusCode: 401, statusMessage: "Invalid password" });
15
23
  }
16
24
  const db = useDB();
@@ -22,7 +30,8 @@ export default defineEventHandler(async (event) => {
22
30
  });
23
31
  setCookie(event, "smile_dev_session", token, {
24
32
  httpOnly: true,
25
- secure: process.env.NODE_ENV === "production",
33
+ secure: false,
34
+ // allow HTTP for local preview; deployed behind HTTPS proxy
26
35
  sameSite: "lax",
27
36
  path: "/",
28
37
  maxAge: 7 * 24 * 60 * 60
@@ -0,0 +1,5 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, {
2
+ type: string;
3
+ url: string;
4
+ }>;
5
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { defineEventHandler } from "h3";
2
+ export default defineEventHandler(() => {
3
+ const url = process.env.TURSO_DATABASE_URL || "file:.data/experiment.db";
4
+ const isTurso = url.startsWith("libsql://") || url.startsWith("https://");
5
+ const isLocal = url.startsWith("file:");
6
+ return {
7
+ type: isTurso ? "Turso" : isLocal ? "Local SQLite" : "LibSQL",
8
+ url: isTurso ? url.replace(/\/\/.*@/, "//***@") : url
9
+ };
10
+ });
@@ -1,6 +1,5 @@
1
- import * as _QRCode from "qrcode-svg";
1
+ import QRCode from "qrcode-svg";
2
2
  import { defineEventHandler, getQuery, getRequestURL, setResponseHeader } from "h3";
3
- const QRCode = _QRCode.default || _QRCode;
4
3
  export default defineEventHandler((event) => {
5
4
  const query = getQuery(event);
6
5
  const requestUrl = getRequestURL(event);