@scaffold-ui-kit/preview 0.0.0-stage → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1868 -2
  3. package/application/host/bootstrap.ts +43 -0
  4. package/application/host/main.ts +31 -0
  5. package/application/host/shell-host.ts +47 -0
  6. package/application/index.html +12 -0
  7. package/application/lib/base-url.ts +15 -0
  8. package/application/lib/no-code-block.ts +7 -0
  9. package/application/lib/no-setup.ts +3 -0
  10. package/application/lib/no-views.ts +6 -0
  11. package/application/preview/code/code.html +12 -0
  12. package/application/preview/code/main.ts +89 -0
  13. package/application/preview/globals.ts +254 -0
  14. package/application/preview/html/main.ts +93 -0
  15. package/application/preview/html/preview.html +12 -0
  16. package/application/preview/react/main.tsx +146 -0
  17. package/application/preview/react/preview.html +12 -0
  18. package/application/preview/svelte/Preview.svelte +104 -0
  19. package/application/preview/svelte/main.ts +13 -0
  20. package/application/preview/svelte/preview.html +12 -0
  21. package/application/preview/svelte/story-props.ts +172 -0
  22. package/application/preview/view/main.ts +124 -0
  23. package/application/preview/view/view.html +12 -0
  24. package/application/preview/vue/main.ts +145 -0
  25. package/application/preview/vue/preview.html +12 -0
  26. package/application/shells/charcell/components/Application/index.css +37 -0
  27. package/application/shells/charcell/components/Application/index.tsx +65 -0
  28. package/application/shells/charcell/components/Bar/index.css +68 -0
  29. package/application/shells/charcell/components/Bar/index.tsx +60 -0
  30. package/application/shells/charcell/components/CodePane/index.css +60 -0
  31. package/application/shells/charcell/components/CodePane/index.tsx +113 -0
  32. package/application/shells/charcell/components/ComponentStage/index.css +26 -0
  33. package/application/shells/charcell/components/ComponentStage/index.tsx +110 -0
  34. package/application/shells/charcell/components/Control/index.css +20 -0
  35. package/application/shells/charcell/components/Control/index.tsx +118 -0
  36. package/application/shells/charcell/components/CopyLink/index.tsx +35 -0
  37. package/application/shells/charcell/components/Description/index.css +6 -0
  38. package/application/shells/charcell/components/Description/index.tsx +24 -0
  39. package/application/shells/charcell/components/EditorAddDialog/index.css +9 -0
  40. package/application/shells/charcell/components/EditorAddDialog/index.tsx +158 -0
  41. package/application/shells/charcell/components/EditorPanel/index.css +48 -0
  42. package/application/shells/charcell/components/EditorPanel/index.tsx +496 -0
  43. package/application/shells/charcell/components/EventsRow/index.css +42 -0
  44. package/application/shells/charcell/components/EventsRow/index.tsx +68 -0
  45. package/application/shells/charcell/components/HeadingRow/index.css +11 -0
  46. package/application/shells/charcell/components/HeadingRow/index.tsx +16 -0
  47. package/application/shells/charcell/components/Hint/index.css +16 -0
  48. package/application/shells/charcell/components/Hint/index.tsx +81 -0
  49. package/application/shells/charcell/components/HtmlWarnings/index.tsx +45 -0
  50. package/application/shells/charcell/components/KeyHints/index.css +27 -0
  51. package/application/shells/charcell/components/KeyHints/index.tsx +106 -0
  52. package/application/shells/charcell/components/KitCodeBlock/index.css +55 -0
  53. package/application/shells/charcell/components/KitCodeBlock/index.tsx +18 -0
  54. package/application/shells/charcell/components/Markdown/index.tsx +16 -0
  55. package/application/shells/charcell/components/Navigation/index.css +13 -0
  56. package/application/shells/charcell/components/Navigation/index.tsx +98 -0
  57. package/application/shells/charcell/components/NavigationSplit/index.css +16 -0
  58. package/application/shells/charcell/components/NavigationSplit/index.tsx +82 -0
  59. package/application/shells/charcell/components/OptionControls/index.tsx +93 -0
  60. package/application/shells/charcell/components/PaneStatus/index.css +7 -0
  61. package/application/shells/charcell/components/PaneStatus/index.tsx +47 -0
  62. package/application/shells/charcell/components/PaneWidth/index.tsx +45 -0
  63. package/application/shells/charcell/components/PreviewGrid/index.css +39 -0
  64. package/application/shells/charcell/components/PreviewGrid/index.tsx +344 -0
  65. package/application/shells/charcell/components/PreviewPane/index.css +127 -0
  66. package/application/shells/charcell/components/PreviewPane/index.tsx +182 -0
  67. package/application/shells/charcell/components/PromptBar/index.tsx +133 -0
  68. package/application/shells/charcell/components/ScenarioRow/index.css +36 -0
  69. package/application/shells/charcell/components/ScenarioRow/index.tsx +71 -0
  70. package/application/shells/charcell/components/Select/index.tsx +48 -0
  71. package/application/shells/charcell/components/SlotOutlet/index.css +7 -0
  72. package/application/shells/charcell/components/SlotOutlet/index.tsx +25 -0
  73. package/application/shells/charcell/components/StageBar/index.css +7 -0
  74. package/application/shells/charcell/components/StageBar/index.tsx +109 -0
  75. package/application/shells/charcell/components/StageSplit/index.css +11 -0
  76. package/application/shells/charcell/components/StageSplit/index.tsx +99 -0
  77. package/application/shells/charcell/components/StatusBar/index.tsx +30 -0
  78. package/application/shells/charcell/components/ViewControls/index.css +15 -0
  79. package/application/shells/charcell/components/ViewControls/index.tsx +58 -0
  80. package/application/shells/charcell/components/ViewHeading/index.css +13 -0
  81. package/application/shells/charcell/components/ViewHeading/index.tsx +8 -0
  82. package/application/shells/charcell/components/ViewStage/index.css +9 -0
  83. package/application/shells/charcell/components/ViewStage/index.tsx +25 -0
  84. package/application/shells/charcell/components/WrapToggle/index.tsx +27 -0
  85. package/application/shells/charcell/configuration.ts +45 -0
  86. package/application/shells/charcell/controller-context.ts +27 -0
  87. package/application/shells/charcell/fit-labels.ts +42 -0
  88. package/application/shells/charcell/html-warnings.ts +18 -0
  89. package/application/shells/charcell/index.tsx +82 -0
  90. package/application/shells/charcell/page-loading.html +57 -0
  91. package/application/shells/charcell/placement.ts +24 -0
  92. package/application/shells/charcell/shell-options.ts +23 -0
  93. package/application/shells/charcell/shell.css +37 -0
  94. package/application/shells/charcell/shell.tsx +25 -0
  95. package/application/shells/charcell/split-reset.ts +47 -0
  96. package/application/shells/charcell/stacked-rows.ts +117 -0
  97. package/application/shells/charcell/stage-toggles.ts +93 -0
  98. package/application/types/manifest.d.ts +6 -0
  99. package/application/types/preview-configuration.d.ts +10 -0
  100. package/application/types/preview-shell.d.ts +7 -0
  101. package/application/types/react-registry.d.ts +15 -0
  102. package/application/types/vue-registry.d.ts +6 -0
  103. package/dist/build.d.ts +24 -0
  104. package/dist/build.js +34 -0
  105. package/dist/check.d.ts +48 -0
  106. package/dist/check.js +781 -0
  107. package/dist/cli.d.ts +2 -0
  108. package/dist/cli.js +88 -0
  109. package/dist/context.d.ts +179 -0
  110. package/dist/context.js +783 -0
  111. package/dist/controller/catalog.d.ts +339 -0
  112. package/dist/controller/catalog.js +367 -0
  113. package/dist/controller/create-preview-controller.d.ts +532 -0
  114. package/dist/controller/create-preview-controller.js +1707 -0
  115. package/dist/controller/editor-tree.d.ts +161 -0
  116. package/dist/controller/editor-tree.js +373 -0
  117. package/dist/controller/html-source.d.ts +62 -0
  118. package/dist/controller/html-source.js +61 -0
  119. package/dist/controller/index.d.ts +9 -0
  120. package/dist/controller/index.js +12 -0
  121. package/dist/controller/persistence.d.ts +191 -0
  122. package/dist/controller/persistence.js +315 -0
  123. package/dist/controller/regeneration.d.ts +30 -0
  124. package/dist/controller/regeneration.js +27 -0
  125. package/dist/controller/source.d.ts +80 -0
  126. package/dist/controller/source.js +236 -0
  127. package/dist/controller/store.d.ts +27 -0
  128. package/dist/controller/store.js +40 -0
  129. package/dist/declarations/application/shells/charcell/components/Application/index.d.ts +2 -0
  130. package/dist/declarations/application/shells/charcell/components/Bar/index.d.ts +11 -0
  131. package/dist/declarations/application/shells/charcell/components/CodePane/index.d.ts +5 -0
  132. package/dist/declarations/application/shells/charcell/components/ComponentStage/index.d.ts +2 -0
  133. package/dist/declarations/application/shells/charcell/components/Control/index.d.ts +9 -0
  134. package/dist/declarations/application/shells/charcell/components/CopyLink/index.d.ts +1 -0
  135. package/dist/declarations/application/shells/charcell/components/Description/index.d.ts +5 -0
  136. package/dist/declarations/application/shells/charcell/components/EditorAddDialog/index.d.ts +6 -0
  137. package/dist/declarations/application/shells/charcell/components/EditorPanel/index.d.ts +2 -0
  138. package/dist/declarations/application/shells/charcell/components/EventsRow/index.d.ts +4 -0
  139. package/dist/declarations/application/shells/charcell/components/HeadingRow/index.d.ts +6 -0
  140. package/dist/declarations/application/shells/charcell/components/Hint/index.d.ts +11 -0
  141. package/dist/declarations/application/shells/charcell/components/HtmlWarnings/index.d.ts +5 -0
  142. package/dist/declarations/application/shells/charcell/components/KeyHints/index.d.ts +2 -0
  143. package/dist/declarations/application/shells/charcell/components/KitCodeBlock/index.d.ts +5 -0
  144. package/dist/declarations/application/shells/charcell/components/Markdown/index.d.ts +3 -0
  145. package/dist/declarations/application/shells/charcell/components/Navigation/index.d.ts +8 -0
  146. package/dist/declarations/application/shells/charcell/components/NavigationSplit/index.d.ts +7 -0
  147. package/dist/declarations/application/shells/charcell/components/OptionControls/index.d.ts +7 -0
  148. package/dist/declarations/application/shells/charcell/components/PaneStatus/index.d.ts +2 -0
  149. package/dist/declarations/application/shells/charcell/components/PaneWidth/index.d.ts +4 -0
  150. package/dist/declarations/application/shells/charcell/components/PreviewGrid/index.d.ts +7 -0
  151. package/dist/declarations/application/shells/charcell/components/PreviewPane/index.d.ts +9 -0
  152. package/dist/declarations/application/shells/charcell/components/PromptBar/index.d.ts +1 -0
  153. package/dist/declarations/application/shells/charcell/components/ScenarioRow/index.d.ts +2 -0
  154. package/dist/declarations/application/shells/charcell/components/Select/index.d.ts +16 -0
  155. package/dist/declarations/application/shells/charcell/components/SlotOutlet/index.d.ts +5 -0
  156. package/dist/declarations/application/shells/charcell/components/StageBar/index.d.ts +2 -0
  157. package/dist/declarations/application/shells/charcell/components/StageSplit/index.d.ts +17 -0
  158. package/dist/declarations/application/shells/charcell/components/StatusBar/index.d.ts +1 -0
  159. package/dist/declarations/application/shells/charcell/components/ViewControls/index.d.ts +9 -0
  160. package/dist/declarations/application/shells/charcell/components/ViewHeading/index.d.ts +4 -0
  161. package/dist/declarations/application/shells/charcell/components/ViewStage/index.d.ts +4 -0
  162. package/dist/declarations/application/shells/charcell/components/WrapToggle/index.d.ts +1 -0
  163. package/dist/declarations/application/shells/charcell/configuration.d.ts +31 -0
  164. package/dist/declarations/application/shells/charcell/controller-context.d.ts +9 -0
  165. package/dist/declarations/application/shells/charcell/fit-labels.d.ts +18 -0
  166. package/dist/declarations/application/shells/charcell/html-warnings.d.ts +5 -0
  167. package/dist/declarations/application/shells/charcell/index.d.ts +39 -0
  168. package/dist/declarations/application/shells/charcell/placement.d.ts +7 -0
  169. package/dist/declarations/application/shells/charcell/shell-options.d.ts +15 -0
  170. package/dist/declarations/application/shells/charcell/shell.d.ts +9 -0
  171. package/dist/declarations/application/shells/charcell/split-reset.d.ts +30 -0
  172. package/dist/declarations/application/shells/charcell/stacked-rows.d.ts +58 -0
  173. package/dist/declarations/application/shells/charcell/stage-toggles.d.ts +28 -0
  174. package/dist/declarations/src/controller/catalog.d.ts +339 -0
  175. package/dist/declarations/src/controller/create-preview-controller.d.ts +532 -0
  176. package/dist/declarations/src/controller/editor-tree.d.ts +161 -0
  177. package/dist/declarations/src/controller/html-source.d.ts +62 -0
  178. package/dist/declarations/src/controller/index.d.ts +9 -0
  179. package/dist/declarations/src/controller/persistence.d.ts +191 -0
  180. package/dist/declarations/src/controller/regeneration.d.ts +30 -0
  181. package/dist/declarations/src/controller/source.d.ts +80 -0
  182. package/dist/declarations/src/controller/store.d.ts +27 -0
  183. package/dist/declarations/src/emit/common.d.ts +103 -0
  184. package/dist/declarations/src/emit/manifest.d.ts +138 -0
  185. package/dist/declarations/src/emit/source.d.ts +87 -0
  186. package/dist/declarations/src/lib/jsx-roots.d.ts +22 -0
  187. package/dist/declarations/src/lib/module-of-source.d.ts +18 -0
  188. package/dist/declarations/src/lib/naming.d.ts +29 -0
  189. package/dist/declarations/src/lib/react-spelling.d.ts +68 -0
  190. package/dist/declarations/src/lib/scenario-story.d.ts +41 -0
  191. package/dist/declarations/src/lib/slot-fill.d.ts +15 -0
  192. package/dist/declarations/src/lib/types.d.ts +741 -0
  193. package/dist/declarations/src/options.d.ts +224 -0
  194. package/dist/declarations/src/protocol.d.ts +541 -0
  195. package/dist/declarations/src/react-view.d.ts +22 -0
  196. package/dist/declarations/src/react.d.ts +17 -0
  197. package/dist/declarations/src/shell.d.ts +99 -0
  198. package/dist/declarations/src/views.d.ts +152 -0
  199. package/dist/development-server.d.ts +121 -0
  200. package/dist/development-server.js +331 -0
  201. package/dist/emit/common.d.ts +103 -0
  202. package/dist/emit/common.js +170 -0
  203. package/dist/emit/html-source.d.ts +46 -0
  204. package/dist/emit/html-source.js +322 -0
  205. package/dist/emit/manifest.d.ts +138 -0
  206. package/dist/emit/manifest.js +74 -0
  207. package/dist/emit/react.d.ts +16 -0
  208. package/dist/emit/react.js +210 -0
  209. package/dist/emit/scratch.d.ts +40 -0
  210. package/dist/emit/scratch.js +116 -0
  211. package/dist/emit/source.d.ts +87 -0
  212. package/dist/emit/source.js +789 -0
  213. package/dist/emit/svelte.d.ts +9 -0
  214. package/dist/emit/svelte.js +177 -0
  215. package/dist/emit/vue.d.ts +2 -0
  216. package/dist/emit/vue.js +152 -0
  217. package/dist/enumerate.d.ts +2 -0
  218. package/dist/enumerate.js +162 -0
  219. package/dist/generate.d.ts +43 -0
  220. package/dist/generate.js +302 -0
  221. package/dist/html-stylesheet.d.ts +43 -0
  222. package/dist/html-stylesheet.js +145 -0
  223. package/dist/index.d.ts +18 -0
  224. package/dist/index.js +21 -0
  225. package/dist/landing.d.ts +16 -0
  226. package/dist/landing.js +45 -0
  227. package/dist/lib/exported-types.d.ts +42 -0
  228. package/dist/lib/exported-types.js +86 -0
  229. package/dist/lib/html-attributes.d.ts +2 -0
  230. package/dist/lib/html-attributes.js +111 -0
  231. package/dist/lib/html-warnings.d.ts +19 -0
  232. package/dist/lib/html-warnings.js +79 -0
  233. package/dist/lib/jsx-roots.d.ts +22 -0
  234. package/dist/lib/jsx-roots.js +243 -0
  235. package/dist/lib/module-of-source.d.ts +18 -0
  236. package/dist/lib/module-of-source.js +24 -0
  237. package/dist/lib/naming.d.ts +29 -0
  238. package/dist/lib/naming.js +56 -0
  239. package/dist/lib/parse-type.d.ts +32 -0
  240. package/dist/lib/parse-type.js +103 -0
  241. package/dist/lib/react-spelling.d.ts +68 -0
  242. package/dist/lib/react-spelling.js +197 -0
  243. package/dist/lib/scenario-story.d.ts +41 -0
  244. package/dist/lib/scenario-story.js +84 -0
  245. package/dist/lib/slot-fill.d.ts +15 -0
  246. package/dist/lib/slot-fill.js +92 -0
  247. package/dist/lib/template-files.d.ts +14 -0
  248. package/dist/lib/template-files.js +25 -0
  249. package/dist/lib/types.d.ts +741 -0
  250. package/dist/lib/types.js +13 -0
  251. package/dist/lib/void-elements.d.ts +7 -0
  252. package/dist/lib/void-elements.js +13 -0
  253. package/dist/load.d.ts +37 -0
  254. package/dist/load.js +82 -0
  255. package/dist/model.d.ts +44 -0
  256. package/dist/model.js +464 -0
  257. package/dist/options.d.ts +224 -0
  258. package/dist/options.js +223 -0
  259. package/dist/prop-types.d.ts +26 -0
  260. package/dist/prop-types.js +102 -0
  261. package/dist/props-from.d.ts +84 -0
  262. package/dist/props-from.js +510 -0
  263. package/dist/protocol.d.ts +541 -0
  264. package/dist/protocol.js +819 -0
  265. package/dist/react-view.d.ts +22 -0
  266. package/dist/react-view.js +36 -0
  267. package/dist/react.d.ts +17 -0
  268. package/dist/react.js +23 -0
  269. package/dist/sass-importers.d.ts +26 -0
  270. package/dist/sass-importers.js +32 -0
  271. package/dist/shell-acceptance.d.ts +21 -0
  272. package/dist/shell-acceptance.js +37 -0
  273. package/dist/shell-page.d.ts +36 -0
  274. package/dist/shell-page.js +90 -0
  275. package/dist/shell-peers.d.ts +38 -0
  276. package/dist/shell-peers.js +61 -0
  277. package/dist/shell.d.ts +99 -0
  278. package/dist/shell.js +52 -0
  279. package/dist/shells/charcell/page.d.ts +8 -0
  280. package/dist/shells/charcell/page.js +69 -0
  281. package/dist/story-source.d.ts +113 -0
  282. package/dist/story-source.js +271 -0
  283. package/dist/story.d.ts +5 -0
  284. package/dist/story.js +28 -0
  285. package/dist/testing.d.ts +218 -0
  286. package/dist/testing.js +284 -0
  287. package/dist/views.d.ts +152 -0
  288. package/dist/views.js +7 -0
  289. package/dist/vite-configuration.d.ts +114 -0
  290. package/dist/vite-configuration.js +578 -0
  291. package/package.json +123 -3
  292. package/src/build.ts +51 -0
  293. package/src/check.ts +1062 -0
  294. package/src/cli.ts +123 -0
  295. package/src/context.ts +1168 -0
  296. package/src/controller/catalog.ts +719 -0
  297. package/src/controller/create-preview-controller.ts +2683 -0
  298. package/src/controller/editor-tree.ts +530 -0
  299. package/src/controller/html-source.ts +114 -0
  300. package/src/controller/index.ts +105 -0
  301. package/src/controller/persistence.ts +403 -0
  302. package/src/controller/regeneration.ts +55 -0
  303. package/src/controller/source.ts +333 -0
  304. package/src/controller/store.ts +55 -0
  305. package/src/development-server.ts +442 -0
  306. package/src/emit/common.ts +201 -0
  307. package/src/emit/html-source.ts +402 -0
  308. package/src/emit/manifest.ts +241 -0
  309. package/src/emit/react.ts +263 -0
  310. package/src/emit/scratch.ts +175 -0
  311. package/src/emit/source.ts +1094 -0
  312. package/src/emit/svelte.ts +230 -0
  313. package/src/emit/vue.ts +194 -0
  314. package/src/enumerate.ts +220 -0
  315. package/src/generate.ts +443 -0
  316. package/src/html-stylesheet.ts +173 -0
  317. package/src/index.ts +60 -0
  318. package/src/landing.ts +58 -0
  319. package/src/lib/exported-types.ts +114 -0
  320. package/src/lib/html-attributes.ts +113 -0
  321. package/src/lib/html-warnings.ts +81 -0
  322. package/src/lib/jsx-roots.ts +238 -0
  323. package/src/lib/module-of-source.ts +26 -0
  324. package/src/lib/naming.ts +65 -0
  325. package/src/lib/parse-type.ts +143 -0
  326. package/src/lib/react-spelling.ts +235 -0
  327. package/src/lib/scenario-story.ts +97 -0
  328. package/src/lib/slot-fill.ts +102 -0
  329. package/src/lib/template-files.ts +31 -0
  330. package/src/lib/types.ts +778 -0
  331. package/src/lib/void-elements.ts +15 -0
  332. package/src/load.ts +144 -0
  333. package/src/model.ts +568 -0
  334. package/src/options.ts +435 -0
  335. package/src/prop-types.ts +133 -0
  336. package/src/props-from.ts +678 -0
  337. package/src/protocol.ts +1135 -0
  338. package/src/react-view.ts +45 -0
  339. package/src/react.ts +34 -0
  340. package/src/sass-importers.ts +45 -0
  341. package/src/shell-acceptance.ts +45 -0
  342. package/src/shell-page.ts +133 -0
  343. package/src/shell-peers.ts +70 -0
  344. package/src/shell.ts +194 -0
  345. package/src/shells/charcell/page.ts +82 -0
  346. package/src/story-source.ts +391 -0
  347. package/src/story.ts +42 -0
  348. package/src/testing.ts +497 -0
  349. package/src/views.ts +183 -0
  350. package/src/vite-configuration.ts +675 -0
@@ -0,0 +1,145 @@
1
+ // Vue preview entry. Mounts a generated render unit (components + template) with
2
+ // a single reactive `props` object that is mutated in place on each update, so
3
+ // v-bind="props" re-renders the same component instance - the Zag driver machine
4
+ // stays alive across prop changes. Remounts each time the host sets a story or scenario.
5
+ import { createApp, h, reactive, shallowRef, type App } from 'vue';
6
+ import { registry } from '@preview-generated/vue/registry';
7
+ // The scenario editor's regenerated scratch story, merged under its reserved id.
8
+ import { registry as scratchRegistry } from '@preview-generated/scratch/vue';
9
+ // The kit's per-target setup module (side effects only) - see react/main.tsx.
10
+ import '@preview-setup/vue';
11
+ import { applyGlobals } from '../globals';
12
+ import {
13
+ announcePreviewReady,
14
+ announcePreviewShown,
15
+ announcePreviewStories,
16
+ announceStoryMounted,
17
+ PREVIEW_MESSAGE,
18
+ PREVIEW_MOUNT_ELEMENT_ID,
19
+ readPreviewMessage,
20
+ reportContentSize,
21
+ reportRenderError,
22
+ withEventRecorders,
23
+ withWriteBacks,
24
+ PendingWriteBacks,
25
+ type PreviewWriteBack,
26
+ } from '../../../src/protocol';
27
+
28
+ let props = reactive<Record<string, unknown>>({});
29
+ let application: App | null = null;
30
+ // The story's events, recorded with each set of props it gets.
31
+ let events: string[] = [];
32
+ // The story's two-way props, each written back as its event reports a value.
33
+ let bindings: PreviewWriteBack[] = [];
34
+ // The host's mount of the story, which each recorded event carries.
35
+ let mount: number | undefined;
36
+ // The values this pane has written back itself and the host has not yet
37
+ // answered: props the host sent before it took the newest keep that value.
38
+ const pending = new PendingWriteBacks();
39
+
40
+ // A controlled story takes a two-way prop's new value here, in the event
41
+ // that reports it, before the component puts a controlled input back to its
42
+ // prop's value at Vue's next tick: the prop holds the new value by then, so
43
+ // typing mid-text keeps the caret where it is. The host's write-back follows
44
+ // with the same value. Each write is numbered, the event reporting it
45
+ // carries the number, and props the host sent before it took the newest
46
+ // keep the pane's own value (`pending`).
47
+ function setProps(given: Record<string, unknown>) {
48
+ const next = withWriteBacks(withEventRecorders(given, events, window, mount, pending), bindings, (prop, value) => {
49
+ pending.wrote(prop, value);
50
+ if (props[prop] !== undefined) props[prop] = value;
51
+ });
52
+ for (const key of Object.keys(props)) if (!(key in next)) delete props[key];
53
+ Object.assign(props, next);
54
+ }
55
+
56
+ function errorMessage(error: unknown): string {
57
+ return error instanceof Error ? error.message : String(error);
58
+ }
59
+
60
+ // Each story or scenario the host sets mounts fresh, so uncontrolled state
61
+ // never carries over from the last one; live prop edits update in place.
62
+ function setStory(id: string, nextProps?: Record<string, unknown>) {
63
+ // Each mount reads props of its own: an application that failed to mount
64
+ // cannot be unmounted, and would re-render on what it subscribed to.
65
+ props = reactive({});
66
+ setProps(nextProps ?? {});
67
+ reportRenderError();
68
+ // No longer current before it unmounts, so nothing it throws from here on
69
+ // counts against the story mounted next.
70
+ const previous = application;
71
+ application = null;
72
+ if (previous) previous.unmount();
73
+ // An application that could not mount left only its error message behind.
74
+ else document.getElementById(PREVIEW_MOUNT_ELEMENT_ID)!.replaceChildren();
75
+ const unit = { ...registry, ...scratchRegistry }[id];
76
+ if (!unit) return;
77
+ // The story's components are values its template's expressions read
78
+ // (`:as="Button"`), as a script-setup import is in an SFC, as well as tags.
79
+ const story = {
80
+ components: unit.components,
81
+ setup: () => ({ ...unit.components, props }),
82
+ template: unit.template,
83
+ };
84
+ // The root stands apart from the story, so it can still show the error the
85
+ // story throws as it sets up or renders.
86
+ // The message of an error the story throws, shown in its place - the way
87
+ // the React page's error boundary shows one - rather than an empty pane,
88
+ // and told to the host, as each story mounted since is.
89
+ const renderError = shallowRef<string | null>(null);
90
+ const current = createApp({
91
+ render: () => (renderError.value === null ? h(story) : h('pre', `render error: ${renderError.value}`)),
92
+ });
93
+ current.config.errorHandler = (error) => {
94
+ // A late error from a story since replaced says nothing of this one.
95
+ if (application !== current) return;
96
+ console.error(error);
97
+ renderError.value = errorMessage(error);
98
+ reportRenderError(renderError.value);
99
+ };
100
+ application = current;
101
+ const container = document.getElementById(PREVIEW_MOUNT_ELEMENT_ID)!;
102
+ try {
103
+ current.mount(container);
104
+ } catch (error) {
105
+ // A failure the application could not handle itself leaves it unusable.
106
+ console.error(error);
107
+ application = null;
108
+ reportRenderError(errorMessage(error));
109
+ const message = document.createElement('pre');
110
+ message.textContent = `render error: ${errorMessage(error)}`;
111
+ container.replaceChildren(message);
112
+ }
113
+ }
114
+
115
+ window.addEventListener('message', (event: MessageEvent) => {
116
+ const message = readPreviewMessage(event.data);
117
+ if (!message) return;
118
+ if (message.type === PREVIEW_MESSAGE.setStory) {
119
+ events = message.events ?? [];
120
+ bindings = message.bindings ?? [];
121
+ mount = message.mount;
122
+ pending.clear();
123
+ setStory(message.id, message.props);
124
+ // The first story, once painted, lets the host show the pane.
125
+ announcePreviewShown();
126
+ announceStoryMounted(message.id);
127
+ }
128
+ else if (message.type === PREVIEW_MESSAGE.props) setProps(pending.reconcile(message.props, message.answers));
129
+ else if (message.type === PREVIEW_MESSAGE.globals) applyGlobals(message.options);
130
+ });
131
+
132
+ announcePreviewStories(Object.keys({ ...registry, ...scratchRegistry }));
133
+ announcePreviewReady();
134
+ // The story's size reaches the host on each change, so a shell can size the pane to it.
135
+ reportContentSize(document.getElementById(PREVIEW_MOUNT_ELEMENT_ID)!);
136
+
137
+ // The editor regenerates .preview-generated/scratch/vue.ts on each edit. Self-accept
138
+ // that dep (a no-op) so Vite scopes the change to *this* iframe instead of
139
+ // broadcasting a full-reload to every client on the shared dev server - which
140
+ // would wipe the host's editor state. The actual refresh is host-driven: after a
141
+ // regeneration it bumps this iframe's src, reloading it to pick up the new (invalidated)
142
+ // scratch module - deterministic, unlike relying on Vite's HMR event delivery.
143
+ if (import.meta.hot) {
144
+ import.meta.hot.accept('@preview-generated/scratch/vue', () => {});
145
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>preview - vue</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="./main.ts"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,37 @@
1
+ @layer charcell.components {
2
+ /* The terminal screen: the shell is letterboxed to whole cells (round() snaps
3
+ both axes; older browsers fall back to the full viewport). Its ring is a
4
+ quiet charcell Frame, so the bars aren't edge to edge;
5
+ the Frame fills the screen as its one grid cell. The screen sits centered
6
+ in what is left over, by margins rounded down to whole pixels, so every
7
+ cell still starts on a whole pixel. */
8
+ .Application {
9
+ width: 100vw;
10
+ height: 100vh;
11
+ width: round(down, 100vw, 1ch);
12
+ height: round(down, 100vh, var(--charcell-row));
13
+ margin-left: round(down, calc((100vw - round(down, 100vw, 1ch)) / 2), 1px);
14
+ margin-top: round(down, calc((100vh - round(down, 100vh, var(--charcell-row))) / 2), 1px);
15
+ overflow: hidden;
16
+ display: grid;
17
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
18
+ }
19
+ .Application__layout {
20
+ height: 100%;
21
+ display: grid;
22
+ grid-template-rows: auto 1fr auto;
23
+ }
24
+ /* The stage, a cell in from the ring at its sides; beside the navigation, the
25
+ split's handle is the cell at its start. */
26
+ .Application__main {
27
+ flex: 1 1 auto;
28
+ display: flex;
29
+ flex-direction: column;
30
+ min-width: 0;
31
+ min-height: 0;
32
+ padding: 0 1ch;
33
+ }
34
+ .Application__main--beside {
35
+ padding-left: 0;
36
+ }
37
+ }
@@ -0,0 +1,65 @@
1
+ // The shell's interface: the terminal screen, letterboxed to whole cells, and
2
+ // inside its ring the prompt bar (the top bar: the kit, its settings, and the
3
+ // view and target toggles), the navigation beside the stage in a split the
4
+ // reader can drag (NavigationSplit), and the status bar. The navigation is the
5
+ // shell's `navigation` option, toggled from the prompt bar, so the address keeps
6
+ // it; hidden, the stage takes the body's width, and shown again, its groups
7
+ // are open and collapsed as they were left. The stage keeps a cell from
8
+ // the ring at its sides; beside the navigation, the split's handle is the cell at
9
+ // its start. The page's title names what the preview shows and the kit, so
10
+ // each tab and history entry says which it is.
11
+ // Styled in its index.css.
12
+ import { Frame } from 'charcell/react/unlinked';
13
+ import { useEffect, useState } from 'react';
14
+ import { usePreviewController, usePreviewState } from '../../controller-context';
15
+ import { ComponentStage } from '../ComponentStage';
16
+ import { PromptBar } from '../PromptBar';
17
+ import { NAVIGATION_OPTION } from '../../shell-options';
18
+ import { Navigation } from '../Navigation';
19
+ import { NavigationSplit } from '../NavigationSplit';
20
+ import { StatusBar } from '../StatusBar';
21
+ import { ViewStage } from '../ViewStage';
22
+ import './index.css';
23
+
24
+ export function Application() {
25
+ const { catalog } = usePreviewController();
26
+ const selection = usePreviewState((state) => state.selection);
27
+ const shown =
28
+ selection.kind === 'view'
29
+ ? catalog.views.find((view) => view.id === selection.id)?.label
30
+ : catalog.components.find((component) => component.id === selection.id)?.shortTitle;
31
+ useEffect(() => {
32
+ document.title = shown ? `${shown} · ${catalog.kitName} preview` : `${catalog.kitName} preview`;
33
+ }, [shown, catalog.kitName]);
34
+ const navigationShown = usePreviewState((state) => state.options[NAVIGATION_OPTION] !== false);
35
+ // The navigation's collapsed groups, kept here while it is hidden.
36
+ const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(() => new Set());
37
+ return (
38
+ <div className="Application">
39
+ {/* The terminal screen: the outermost ring, faint, so it groups everything
40
+ without outshining the content it groups. */}
41
+ <Frame as="div" quiet flush>
42
+ <div className="Application__layout">
43
+ <PromptBar />
44
+ <NavigationSplit
45
+ shown={navigationShown}
46
+ navigation={<Navigation collapsed={collapsed} onCollapsedChange={setCollapsed} />}
47
+ main={
48
+ <main className={`Application__main${navigationShown ? ' Application__main--beside' : ''}`}>
49
+ {selection.kind === 'view' ? (
50
+ // A custom view renders through the generic view iframe; the
51
+ // controller drives only its globals (the ready handshake delivers
52
+ // the current options, replayed on reload).
53
+ <ViewStage viewId={selection.id} />
54
+ ) : (
55
+ <ComponentStage />
56
+ )}
57
+ </main>
58
+ }
59
+ />
60
+ <StatusBar />
61
+ </div>
62
+ </Frame>
63
+ </div>
64
+ );
65
+ }
@@ -0,0 +1,68 @@
1
+ @layer charcell.components {
2
+ /* The bands: a content row and a rule row, the stroke centered in
3
+ its own row and the text on the other. The rule is `faint`, a separator.
4
+ When the zones do not fit on one row the content wraps onto more, a whole
5
+ row at a time, so no control is ever cut off; the rule row stays where it
6
+ was against the content, under it in a header and over it in a status
7
+ bar. */
8
+ .Bar {
9
+ display: flex;
10
+ flex-direction: column;
11
+ min-width: 0;
12
+ }
13
+ .Bar--status {
14
+ color: var(--charcell-mid);
15
+ }
16
+ /* An unruled band's empty rule row. */
17
+ .Bar__space {
18
+ height: var(--charcell-row);
19
+ }
20
+ /* The two zones on one row while they fit: the start packed from the
21
+ start, the end against the end. Crowded,
22
+ the zones wrap, the end zone keeping to the end of its row, and a zone
23
+ that does not fit a row by itself wraps its own items. Items sit a row
24
+ tall and rows stack with no gap, so every line stays on the cell grid. */
25
+ .Bar__content {
26
+ padding: 0 1ch;
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ align-items: center;
30
+ column-gap: 2ch;
31
+ row-gap: 0;
32
+ min-width: 0;
33
+ min-height: var(--charcell-row);
34
+ white-space: nowrap;
35
+ }
36
+ .Bar--flush .Bar__content {
37
+ padding: 0;
38
+ }
39
+ .Bar__start,
40
+ .Bar__end {
41
+ display: flex;
42
+ flex-wrap: wrap;
43
+ align-items: center;
44
+ column-gap: 2ch;
45
+ row-gap: 0;
46
+ min-width: 0;
47
+ min-height: var(--charcell-row);
48
+ }
49
+ .Bar__end {
50
+ margin-left: auto;
51
+ justify-content: flex-end;
52
+ }
53
+ /* A bar's start zone cluster: the lead and a picker sit a cell apart, tighter
54
+ than the 2ch the band's zones space their items by. */
55
+ .Bar__cluster {
56
+ display: flex;
57
+ flex-wrap: wrap;
58
+ align-items: center;
59
+ column-gap: 1ch;
60
+ row-gap: 0;
61
+ min-width: 0;
62
+ }
63
+ /* The bold word leading a bar - the prompt, the selected component. charcell's
64
+ reset flattens <strong>, so the weight is stated here. */
65
+ .Bar__lead {
66
+ font-weight: 700;
67
+ }
68
+ }
@@ -0,0 +1,60 @@
1
+ // The preview's bands: the prompt bar, the stage bar and the status bar. Two
2
+ // rows, each with one job, the way a terminal prints them: `header` is a
3
+ // content row over a rule row, `status` a rule row over a content row. The
4
+ // content row has two zones - the children pack from the start, `end` packs
5
+ // against the end. When they do not fit, the content wraps onto further rows, a whole row at a
6
+ // time, so a control is never cut off.
7
+ // `lead` is the bold word that opens the start zone (the prompt), the children beside it a cell apart. The rule row is a charcell
8
+ // Separator across the band's full width; `joined` runs its ends on to meet
9
+ // the lines beside the band (the frame's ring, a divider), as ├ and ┤.
10
+ // `unruled`, the rule row is left empty: a band that sits inside a place with
11
+ // edges of its own (the stage, beside the navigation's line), where a rule across
12
+ // it would cross them. `flush`, the content row takes no cells at its sides,
13
+ // the place around the band holding them.
14
+ // Styled in its index.css.
15
+ import { Separator } from 'charcell/react/unlinked';
16
+ import type { ReactNode } from 'react';
17
+ import './index.css';
18
+
19
+ export function Bar({
20
+ variant = 'header',
21
+ joined,
22
+ unruled,
23
+ flush,
24
+ lead,
25
+ end,
26
+ children,
27
+ }: {
28
+ variant?: 'header' | 'status';
29
+ joined?: boolean;
30
+ unruled?: boolean;
31
+ flush?: boolean;
32
+ lead?: ReactNode;
33
+ end?: ReactNode;
34
+ children?: ReactNode;
35
+ }) {
36
+ const rule = unruled ? (
37
+ <div className="Bar__space" />
38
+ ) : (
39
+ <Separator decorative join={joined ? 'both' : undefined} />
40
+ );
41
+ return (
42
+ <div className={`Bar Bar--${variant}${flush ? ' Bar--flush' : ''}`}>
43
+ {variant === 'status' && rule}
44
+ <div className="Bar__content">
45
+ <div className="Bar__start">
46
+ {lead === undefined ? (
47
+ children
48
+ ) : (
49
+ <div className="Bar__cluster">
50
+ <strong className="Bar__lead">{lead}</strong>
51
+ {children}
52
+ </div>
53
+ )}
54
+ </div>
55
+ {end !== undefined && <div className="Bar__end">{end}</div>}
56
+ </div>
57
+ {variant === 'header' && rule}
58
+ </div>
59
+ );
60
+ }
@@ -0,0 +1,60 @@
1
+ @layer charcell.components {
2
+ /* A code pane: a quiet charcell Frame titled with its
3
+ target, filling its cell of the grid (PreviewGrid), which holds its
4
+ height in whole rows. Inside, a row saying what the pane holds, with the
5
+ copy button at its end, over the source. */
6
+ .CodePane {
7
+ flex: 1;
8
+ display: flex;
9
+ flex-direction: column;
10
+ min-width: 0;
11
+ min-height: 0;
12
+ }
13
+ .CodePane__content {
14
+ height: 100%;
15
+ display: flex;
16
+ flex-direction: column;
17
+ min-height: 0;
18
+ }
19
+ /* In a pane too narrow for both, the actions wrap under the note, a whole
20
+ row down, rather than cutting the note short. */
21
+ /* The Frame is flush, so the scrollbars run beside its
22
+ ring: the row and the source each keep a cell from it. */
23
+ .CodePane__row {
24
+ padding: 0 1ch;
25
+ display: flex;
26
+ flex-wrap: wrap;
27
+ align-items: center;
28
+ column-gap: 2ch;
29
+ row-gap: 0;
30
+ min-height: var(--charcell-row);
31
+ }
32
+ .CodePane__note {
33
+ flex: 1 0 auto;
34
+ white-space: nowrap;
35
+ color: var(--charcell-mid);
36
+ }
37
+ /* How many warnings the html has, beside the note at its tone, the
38
+ count opening them (HtmlWarnings). */
39
+ .CodePane__warnings {
40
+ white-space: nowrap;
41
+ color: var(--charcell-mid);
42
+ }
43
+ .CodePane__actions {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 1ch;
47
+ margin-left: auto;
48
+ }
49
+ /* The source: pre-formatted in the shell's one monospace, in the charcell
50
+ ScrollArea that takes the rows the pane's row leaves, so
51
+ a long line never widens the stage and a long source never lengthens it.
52
+ Its lines keep to themselves, scrolling sideways, or wrap at the pane's
53
+ edge while the shell's wrap option is on. */
54
+ /* Why a pane has no source, in the box the source would fill. */
55
+ .CodePane__reason {
56
+ margin: 0;
57
+ padding: 0 1ch;
58
+ color: var(--charcell-mid);
59
+ }
60
+ }
@@ -0,0 +1,113 @@
1
+ // One code pane, under a target's preview pane in the stage's grid
2
+ // (PreviewGrid): the story's source as a consumer writes it for that
3
+ // target, in a quiet charcell Frame titled with the target. A row says what
4
+ // the pane holds, with a copy button at its end, over the source in a
5
+ // charcell CodeBlock that fills the rest of the pane and scrolls a whole row
6
+ // (and column) at a time. Wrapping is the
7
+ // shell's `wrap` option, toggled for every pane from the code view's heading
8
+ // row (WrapToggle): on, a long line wraps at the pane's edge and the source
9
+ // scrolls only down; off, a long line runs on and the source scrolls across
10
+ // too. A kit that names its own code block (KitCodeBlock) shows the source
11
+ // there instead, the row's note and copy button kept, and the block follows
12
+ // the same option. Without
13
+ // source, the row says so in a word (`printing`, `unavailable`) and the box
14
+ // says why, the copy button disabled. html that leaves out what it cannot
15
+ // evaluate at rest (script-held state) says how many warnings beside the
16
+ // note, the count opening them, one to a line, in a popover
17
+ // (HtmlWarnings), as the html pane's legend does. The
18
+ // code is the controller's (`state.code`), printed as the panes change,
19
+ // so the pane follows a scenario pick, a prop edit and the editor's tree.
20
+ // The scroll area takes keyboard focus and shows it as charcell's do, its
21
+ // scrollbar's thumb climbing to the foreground. The Frame is flush, so the scroll area's bars
22
+ // run beside its ring; the row and the source keep their own cell from it.
23
+ // Styled in its index.css.
24
+ import { useEffect, useState } from 'react';
25
+ import { Button, CodeBlock, Frame, ScrollArea } from 'charcell/react/unlinked';
26
+ import type { PreviewTarget } from '../../../../../src/shell';
27
+ import { usePreviewController, usePreviewState } from '../../controller-context';
28
+ import { KitCodeBlock } from '../KitCodeBlock';
29
+ import { WRAP_OPTION } from '../../shell-options';
30
+ import { HtmlWarnings } from '../HtmlWarnings';
31
+ import './index.css';
32
+
33
+ /** How long the copy button's confirmation shows, in milliseconds. */
34
+ const COPIED_MILLISECONDS = 1500;
35
+
36
+ /** What a code pane shows: the source, or, without it, a word and why. */
37
+ interface Shown {
38
+ text?: string;
39
+ status?: string;
40
+ reason?: string;
41
+ /** What the html leaves out at rest. */
42
+ warnings?: string[];
43
+ }
44
+
45
+ export function CodePane({ target }: { target: PreviewTarget }) {
46
+ const code = usePreviewState((state) => state.code);
47
+ // A kit's own code block shows the source in its place.
48
+ const kitBlock = usePreviewController().catalog.codeBlock !== undefined;
49
+ const wrapped = usePreviewState((state) => state.options[WRAP_OPTION] !== false);
50
+ const [copied, setCopied] = useState(false);
51
+ useEffect(() => {
52
+ if (!copied) return;
53
+ const timer = setTimeout(() => setCopied(false), COPIED_MILLISECONDS);
54
+ return () => clearTimeout(timer);
55
+ }, [copied]);
56
+ // html is printed apart from the other targets, so it can be on its way or
57
+ // not to be had; another target's code is always there.
58
+ const { text, status, reason, warnings }: Shown = !code
59
+ ? {}
60
+ : target !== 'html'
61
+ ? { text: code.targets[target] }
62
+ : code.html.status === 'ready'
63
+ ? { text: code.html.source, warnings: code.html.warnings }
64
+ : code.html.status === 'loading'
65
+ ? { status: 'printing' }
66
+ : { status: 'unavailable', reason: code.html.reason };
67
+ const copy = () => {
68
+ if (text === undefined) return;
69
+ navigator.clipboard?.writeText(text).then(
70
+ () => setCopied(true),
71
+ () => undefined,
72
+ );
73
+ };
74
+ const lines = text === undefined ? 0 : text.split('\n').length - 1;
75
+ return (
76
+ <div className="CodePane" data-preview-code={target}>
77
+ <Frame title={target} quiet flush fill>
78
+ <div className="CodePane__content">
79
+ <div className="CodePane__row">
80
+ {/* The live region says how the code stands and that it was
81
+ copied; the line count, which follows every edit, sits
82
+ beside it, read but not announced. */}
83
+ <span className="CodePane__note">
84
+ <span role="status">{text === undefined ? (status ?? '') : copied ? `${target} copied` : ''}</span>
85
+ {text !== undefined && !copied ? `${lines} ${lines === 1 ? 'line' : 'lines'}` : null}
86
+ </span>
87
+ {warnings && warnings.length > 0 ? (
88
+ <HtmlWarnings warnings={warnings} className="CodePane__warnings" />
89
+ ) : null}
90
+ <span className="CodePane__actions">
91
+ <Button variant="dense" label="copy" disabled={text === undefined} onClick={copy} />
92
+ </span>
93
+ </div>
94
+ {kitBlock ? (
95
+ <KitCodeBlock target={target} />
96
+ ) : text !== undefined ? (
97
+ <CodeBlock
98
+ label={`${target} code`}
99
+ code={text}
100
+ wrap={wrapped}
101
+ orientation="both"
102
+ fill
103
+ />
104
+ ) : (
105
+ <ScrollArea label={`${target} code`} overscroll="none" fill>
106
+ <p className="CodePane__reason">{reason}</p>
107
+ </ScrollArea>
108
+ )}
109
+ </div>
110
+ </Frame>
111
+ </div>
112
+ );
113
+ }
@@ -0,0 +1,26 @@
1
+ @layer charcell.components {
2
+ /* A component story's stage: its bar, and its body
3
+ taking the rest of the height - the grid of panes, under the scenario row
4
+ while it shows, in a stacked charcell Splitter (StageSplit) that
5
+ fills the body. The body ends on a whole row, as everything above it
6
+ does, so the split's rows and the grid's do too. */
7
+ .ComponentStage {
8
+ flex: 1;
9
+ display: flex;
10
+ flex-direction: column;
11
+ min-width: 0;
12
+ min-height: 0;
13
+ }
14
+ .ComponentStage__body {
15
+ flex: 1;
16
+ display: flex;
17
+ flex-direction: column;
18
+ min-width: 0;
19
+ min-height: 0;
20
+ }
21
+ /* What the body says while no view shows. */
22
+ .ComponentStage__note {
23
+ margin: 0;
24
+ color: var(--charcell-mid);
25
+ }
26
+ }