@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,333 @@
1
+ // A story's source printed in the browser from the catalog: the code a
2
+ // consumer writes per target, importing from the kit's package entries,
3
+ // with the props a person sets and the slot content the story or the editor's
4
+ // tree holds. The printers are pure, so the source follows every change
5
+ // without a round trip; the html source, which renders the kit's templates,
6
+ // is the server's (html-source.ts). Browser-safe.
7
+
8
+ import {
9
+ inDeclarationOrder,
10
+ SOURCE_PRINTERS,
11
+ type SourceBinding,
12
+ type SourceStory,
13
+ } from '../emit/source.js';
14
+ import { collectSlotComponents } from '../lib/slot-fill.js';
15
+ import { moduleOfSource } from '../lib/module-of-source.js';
16
+ import type { JsonValue, SlotFill, StoryAround } from '../lib/types.js';
17
+ import type { PreviewScriptedTarget } from '../protocol.js';
18
+ import {
19
+ defaultScenarioId,
20
+ type PreviewCatalog,
21
+ type PreviewComponent,
22
+ type PreviewScenario,
23
+ type PreviewStoryReference,
24
+ } from './catalog.js';
25
+ import { cleanRecord, toPayload, type EditorState } from './editor-tree.js';
26
+
27
+ /** A story's source, by scripted target: what a consumer writes. */
28
+ export type PreviewTargetCode = Partial<Record<PreviewScriptedTarget, string>>;
29
+
30
+ /** A story resolved for printing: its component, the props to print and its
31
+ * slot content. */
32
+ export interface ResolvedSourceStory {
33
+ /** The root component's name. */
34
+ component: string;
35
+ /** The props a consumer writes: those that differ from what the component
36
+ * and the preview start from. */
37
+ props: Record<string, JsonValue>;
38
+ /** Default-slot content. */
39
+ children?: SlotFill;
40
+ /** Named-slot content, by slot name. */
41
+ named: Record<string, SlotFill>;
42
+ /** The content beside the component, as its siblings. */
43
+ around?: StoryAround;
44
+ /** The two-way props the story gives, which the printed source binds to
45
+ * state of its own. Absent when it gives none. */
46
+ bindings?: SourceBinding[];
47
+ }
48
+
49
+ /** The catalog fields the printing reads. */
50
+ export type SourceCatalog = Pick<
51
+ PreviewCatalog,
52
+ 'imports' | 'sources' | 'kitName'
53
+ > &
54
+ Partial<Pick<PreviewCatalog, 'svelteMode' | 'reactAttributeNames'>>;
55
+
56
+ function withoutUndefined(
57
+ props: Record<string, unknown>
58
+ ): Record<string, JsonValue> {
59
+ const out: Record<string, JsonValue> = {};
60
+ for (const [name, value] of Object.entries(props))
61
+ if (value !== undefined) out[name] = value as JsonValue;
62
+ return out;
63
+ }
64
+
65
+ /**
66
+ * Whether a story's default-slot text is the component's name the preview
67
+ * shows in a default slot the story leaves unfilled, which a consumer never
68
+ * writes: the preview's own starting text, while the scenario does not give
69
+ * `children` itself.
70
+ */
71
+ export function isPlaceholder(
72
+ component: PreviewComponent,
73
+ text: string,
74
+ input: { scenario?: PreviewScenario }
75
+ ): boolean {
76
+ return (
77
+ component.previewDefaults.children === text &&
78
+ !('children' in (input.scenario?.props ?? {}))
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Resolve what a story's source prints. Without a tree, the slot content is
84
+ * the story's own and a string `children` is its default-slot text; with the
85
+ * editor's tree, the root's props and content are the tree's. A prop is left
86
+ * out while it holds the component's declared default, or the preview's own
87
+ * starting value that the scenario does not set, as is the component's name
88
+ * the preview shows in a default slot the story leaves unfilled.
89
+ */
90
+ export function resolveSourceStory(
91
+ component: PreviewComponent,
92
+ input: {
93
+ props: Record<string, unknown>;
94
+ scenario?: PreviewScenario;
95
+ tree?: EditorState;
96
+ }
97
+ ): ResolvedSourceStory {
98
+ let props: Record<string, JsonValue>;
99
+ let children: SlotFill | undefined;
100
+ let named: Record<string, SlotFill>;
101
+ if (input.tree) {
102
+ const payload = toPayload(input.tree);
103
+ const { children: _children, ...rootProps } = input.props;
104
+ props = cleanRecord(rootProps);
105
+ children = payload.slots?.default;
106
+ named = payload.slots?.named ?? {};
107
+ } else {
108
+ const { children: text, ...rest } = input.props;
109
+ props = withoutUndefined(rest);
110
+ // A scenario with content of its own shows that in place of the story's.
111
+ const content = input.scenario?.content ?? component.content;
112
+ children =
113
+ content?.default ??
114
+ (typeof text === 'string' && !isPlaceholder(component, text, input)
115
+ ? { kind: 'text', value: text }
116
+ : undefined);
117
+ named = content?.named ?? {};
118
+ }
119
+ const declared = new Map(
120
+ component.propTypes.map((propType) => [propType.name, propType])
121
+ );
122
+ const scenarioProps = input.scenario?.props ?? {};
123
+ for (const [name, value] of Object.entries(props)) {
124
+ const declaredDefault = declared.get(name)?.declaredDefault;
125
+ const previewDefault = component.previewDefaults[name];
126
+ if (
127
+ (declaredDefault !== undefined &&
128
+ JSON.stringify(declaredDefault) === JSON.stringify(value)) ||
129
+ (previewDefault !== undefined &&
130
+ !(name in scenarioProps) &&
131
+ JSON.stringify(previewDefault) === JSON.stringify(value))
132
+ )
133
+ delete props[name];
134
+ }
135
+ props = inDeclarationOrder(
136
+ props,
137
+ component.propTypes.map((propType) => propType.name)
138
+ );
139
+ // A two-way prop the story gives is controlled: its source binds it.
140
+ const bindings = (component.bindings ?? [])
141
+ .filter((binding) => binding.prop in props)
142
+ .map((binding) => {
143
+ const declaredType = declared.get(binding.prop)?.declaredType;
144
+ return {
145
+ prop: binding.prop,
146
+ ...(binding.changeProp !== undefined
147
+ ? { changeProp: binding.changeProp }
148
+ : {}),
149
+ ...(binding.defaultProp !== undefined
150
+ ? { defaultProp: binding.defaultProp }
151
+ : {}),
152
+ ...(binding.vueModel ? { vueModel: true } : {}),
153
+ ...(binding.generic ? { generic: true } : {}),
154
+ ...(declaredType !== undefined ? { declaredType } : {}),
155
+ };
156
+ });
157
+ // The content beside the component is the story's, with or without the
158
+ // editor's tree: no edit reaches it.
159
+ const around = component.around;
160
+ return {
161
+ component: component.name,
162
+ props,
163
+ ...(children ? { children } : {}),
164
+ named,
165
+ ...(around ? { around } : {}),
166
+ ...(bindings.length > 0 ? { bindings } : {}),
167
+ };
168
+ }
169
+
170
+ /** The import of each component a story names, for one target: its root,
171
+ * then what its slot content holds, in order. */
172
+ function importsFor(
173
+ catalog: SourceCatalog,
174
+ story: ResolvedSourceStory,
175
+ target: PreviewScriptedTarget
176
+ ): SourceStory['imports'] {
177
+ const names = new Set<string>();
178
+ collectSlotComponents(story.children, names);
179
+ for (const fill of [
180
+ ...Object.values(story.named),
181
+ story.around?.before,
182
+ story.around?.after,
183
+ ])
184
+ collectSlotComponents(fill, names);
185
+ const base = catalog.sources[0]?.moduleBase ?? catalog.kitName;
186
+ const imports: SourceStory['imports'] = new Map();
187
+ for (const name of [story.component, ...names]) {
188
+ if (imports.has(name)) continue;
189
+ const known = catalog.imports[name];
190
+ imports.set(name, {
191
+ module: known?.modules[target] ?? moduleOfSource(base, target),
192
+ exported: known?.exportName ?? name,
193
+ ...(known?.declaredAttributes
194
+ ? { declaredAttributes: known.declaredAttributes }
195
+ : {}),
196
+ });
197
+ }
198
+ return imports;
199
+ }
200
+
201
+ /** The type names the kit's components' modules export, for one target,
202
+ * each with the module a consumer imports it from: the story's own
203
+ * component's, then the first other component's to export it. A name a
204
+ * component is imported under is a value, never a type here. */
205
+ function exportedTypesFor(
206
+ catalog: SourceCatalog,
207
+ target: PreviewScriptedTarget,
208
+ component: string
209
+ ): Map<string, string> {
210
+ const base = catalog.sources[0]?.moduleBase ?? catalog.kitName;
211
+ // A component's own name, or the name it is exported under, is a value.
212
+ const values = new Set(
213
+ Object.entries(catalog.imports).flatMap(([name, known]) => [
214
+ name,
215
+ known.exportName,
216
+ ])
217
+ );
218
+ const types = new Map<string, string>();
219
+ // The story's own component first, so its type wins a name another
220
+ // component's module exports too.
221
+ const own = catalog.imports[component];
222
+ const entries = [
223
+ ...(own ? [own] : []),
224
+ ...Object.entries(catalog.imports)
225
+ .filter(([name]) => name !== component)
226
+ .map(([, known]) => known),
227
+ ];
228
+ for (const known of entries)
229
+ for (const type of known.types?.[target] ?? [])
230
+ if (!types.has(type) && !values.has(type))
231
+ types.set(type, known.modules[target] ?? moduleOfSource(base, target));
232
+ return types;
233
+ }
234
+
235
+ /**
236
+ * Print a resolved story in each of `targets`: a two-way prop it gives
237
+ * bound to state of the source's own, in the catalog's Svelte mode.
238
+ *
239
+ * @param catalog - The catalog the components' imports are read from.
240
+ * @param story - The story, resolved.
241
+ * @param targets - The targets to print.
242
+ * @returns The source per target.
243
+ */
244
+ export function printSourceStory(
245
+ catalog: SourceCatalog,
246
+ story: ResolvedSourceStory,
247
+ targets: readonly PreviewScriptedTarget[]
248
+ ): PreviewTargetCode {
249
+ const sources: PreviewTargetCode = {};
250
+ for (const target of targets) {
251
+ sources[target] = SOURCE_PRINTERS[target]({
252
+ component: story.component,
253
+ props: story.props,
254
+ ...(story.children ? { children: story.children } : {}),
255
+ named: story.named,
256
+ ...(story.around ? { around: story.around } : {}),
257
+ imports: importsFor(catalog, story, target),
258
+ ...(story.bindings ? { bindings: story.bindings } : {}),
259
+ ...(catalog.svelteMode ? { svelteMode: catalog.svelteMode } : {}),
260
+ ...(catalog.reactAttributeNames
261
+ ? { reactAttributeNames: catalog.reactAttributeNames }
262
+ : {}),
263
+ exportedTypes: exportedTypesFor(catalog, target, story.component),
264
+ });
265
+ }
266
+ return sources;
267
+ }
268
+
269
+ /**
270
+ * Print any story of the catalog as the source a consumer writes, per
271
+ * target the component renders in: the component with the props of the
272
+ * scenario over its defaults and `props` over those, its slot content, and
273
+ * imports from the kit's package entry for each target. A prop is left
274
+ * out while it holds the component's declared default. It takes the story
275
+ * reference `frames.mountStory` takes, so a shell can show the code beside a
276
+ * detached pane. The html source is the preview's own (`state.code.html`)
277
+ * and is not printed here.
278
+ *
279
+ * @param catalog - The controller's catalog.
280
+ * @param story - The story: a component's id, a scenario (omitted, the one
281
+ * the story starts on; `''`, the anonymous default) and props over its own.
282
+ * @returns The source per target, in the component's targets.
283
+ * @throws When the component or the scenario is unknown.
284
+ * @example
285
+ * ```ts
286
+ * const { react } = printStorySource(controller.catalog, { component: 'components-button', scenario: 'ghost' });
287
+ * ```
288
+ */
289
+ export function printStorySource(
290
+ catalog: PreviewCatalog,
291
+ story: PreviewStoryReference
292
+ ): PreviewTargetCode {
293
+ const component = catalog.components.find(
294
+ (candidate) => candidate.id === story.component
295
+ );
296
+ if (!component)
297
+ throw new Error(
298
+ `The catalog has no component "${story.component}" to print.`
299
+ );
300
+ const scenarioId = story.scenario ?? defaultScenarioId(component);
301
+ const scenario = component.scenarios.find(
302
+ (candidate) => candidate.id === scenarioId
303
+ );
304
+ if (scenarioId !== '' && !scenario)
305
+ throw new Error(
306
+ `The story "${component.id}" has no scenario "${scenarioId}".`
307
+ );
308
+ const seeded = { ...component.defaultProps, ...(scenario?.props ?? {}) };
309
+ // The Empty scenario is the story's props with no slot content.
310
+ const props = {
311
+ ...(scenario?.empty ? withoutChildren(seeded) : seeded),
312
+ ...withoutUndefined(story.props ?? {}),
313
+ };
314
+ const resolved = scenario?.empty
315
+ ? resolveSourceStory(component, {
316
+ props,
317
+ scenario,
318
+ tree: {
319
+ root: component.name,
320
+ props: withoutChildren(props),
321
+ slots: {},
322
+ },
323
+ })
324
+ : resolveSourceStory(component, { props, scenario });
325
+ return printSourceStory(catalog, resolved, component.targets);
326
+ }
327
+
328
+ function withoutChildren(
329
+ props: Record<string, unknown>
330
+ ): Record<string, unknown> {
331
+ const { children: _children, ...rest } = props;
332
+ return rest;
333
+ }
@@ -0,0 +1,55 @@
1
+ // A store view of the preview controller: an object with one `subscribe`
2
+ // method that calls its listener with the current value at once and again
3
+ // whenever the value changes. That is the Svelte store contract, so a Svelte
4
+ // shell reads it with `$store` or `fromStore`, and it suits any other
5
+ // store-shaped consumer. Framework-neutral and browser-safe.
6
+
7
+ import type {
8
+ PreviewController,
9
+ PreviewState,
10
+ } from './create-preview-controller.js';
11
+
12
+ /** A readable store: `subscribe` calls `listener` with the current value
13
+ * immediately, then with each new value, until the returned function is called. */
14
+ export interface PreviewStore<Value> {
15
+ subscribe(listener: (value: Value) => void): () => void;
16
+ }
17
+
18
+ /**
19
+ * A store of the controller's state, or of a slice of it. Each subscriber is
20
+ * called with the current slice when it subscribes, and again only when the
21
+ * slice changes by identity, so `selector` returns a field of the state (or a
22
+ * primitive derived from it) rather than a fresh object or array.
23
+ *
24
+ * @param controller - The controller to read.
25
+ * @param selector - Picks the slice; the whole state when omitted.
26
+ * @returns The store.
27
+ * @example
28
+ * ```svelte
29
+ * <script lang="ts">
30
+ * import { previewStore } from '@scaffold-ui-kit/preview/shell';
31
+ * const preview = previewStore(controller);
32
+ * const scenario = previewStore(controller, (state) => state.scenario);
33
+ * </script>
34
+ *
35
+ * <p>{$preview.selection.id}: {$scenario}</p>
36
+ * ```
37
+ */
38
+ export function previewStore<Selected = PreviewState>(
39
+ controller: Pick<PreviewController, 'getState' | 'subscribe'>,
40
+ selector: (state: PreviewState) => Selected = (state) =>
41
+ state as unknown as Selected
42
+ ): PreviewStore<Selected> {
43
+ return {
44
+ subscribe(listener) {
45
+ let current = selector(controller.getState());
46
+ listener(current);
47
+ return controller.subscribe((state) => {
48
+ const next = selector(state);
49
+ if (Object.is(next, current)) return;
50
+ current = next;
51
+ listener(next);
52
+ });
53
+ },
54
+ };
55
+ }