@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,391 @@
1
+ // A story as consumer source per target, for a kit's docs: the component,
2
+ // the props its story file curates (and a scenario's), and its slot content,
3
+ // importing from the kit's package entry for each target - and the markup the
4
+ // story renders to, as html. Read from the same story files the preview renders,
5
+ // so the snippets follow them.
6
+
7
+ import { REACT_ATTRIBUTE_NAMES } from '@js-template-engine/extension-react';
8
+ import type { ConfigurationLookupOptions } from 'scaffold-ui-kit';
9
+ import { loadPreviewContext, type PreviewContext } from './context.js';
10
+ import { loadKit } from './load.js';
11
+ import { storyOnScenario } from './lib/scenario-story.js';
12
+ import { resolveStory } from './model.js';
13
+ import { declaredAttributes } from './lib/react-spelling.js';
14
+ import { moduleOfSource } from './lib/module-of-source.js';
15
+ import { htmlSource, type HtmlSourceResult } from './emit/html-source.js';
16
+ import {
17
+ inDeclarationOrder,
18
+ SOURCE_PRINTERS,
19
+ type SourceStory,
20
+ } from './emit/source.js';
21
+ import { exportedTypesOf } from './lib/exported-types.js';
22
+ import { summarizeHtmlWarnings } from './lib/html-warnings.js';
23
+ import type {
24
+ EnumeratedComponent,
25
+ JsonValue,
26
+ Scenario,
27
+ Story,
28
+ SlotFill,
29
+ StoryAround,
30
+ ResolvedStory,
31
+ Target,
32
+ } from './lib/types.js';
33
+
34
+ /** What `storySource` prints: a framework's source, or the rendered markup. */
35
+ export type SourceTarget = Target | 'html';
36
+
37
+ /**
38
+ * What `storySource` returns: the source per target, and, when the `html`
39
+ * leaves something out, the warnings naming it.
40
+ */
41
+ export type StorySource = Partial<Record<SourceTarget, string>> & {
42
+ /** What the `html` could not work out at rest and left out, such as an
43
+ * expression reading the component's script state; the markup shows that
44
+ * part at a default. Absent when there is nothing to name. */
45
+ htmlWarnings?: string[];
46
+ };
47
+
48
+ export interface StorySourceOptions extends ConfigurationLookupOptions {
49
+ /** A scenario id (curated or generated); its props apply over the story's. */
50
+ scenario?: string;
51
+ /** The targets to print. Defaults to every target the component renders
52
+ * into, and `html`. */
53
+ targets?: SourceTarget[];
54
+ }
55
+
56
+ /**
57
+ * Prints a component's story as the source a consumer would write per target:
58
+ * a React component, a Vue single-file component, a Svelte component. Imports
59
+ * name the kit's package entry for each target (`<package>/react`); props are
60
+ * those the story file sets (`defaultProps`, `fixed`) and the scenario's, leaving
61
+ * out values equal to the template's declared default. A default slot the
62
+ * story leaves unfilled prints no content. A two-way prop the story gives
63
+ * is bound to state of the source's own, as a consumer controls
64
+ * it: React's `useState` with the value and the change prop, Vue's `v-model`
65
+ * or `v-model:<prop>`, Svelte's `bind:<prop>` on `$state` in runes mode or a
66
+ * plain `let` in legacy mode, as the kit builds Svelte, its state typed by
67
+ * the prop's declared type where that names types the kit's package entry
68
+ * exports, imported from it. The prop its value starts from otherwise (its
69
+ * default prop) is left out, as is a prop the scenario gives `null`, unless
70
+ * it is a two-way prop the source binds. The `html` is the markup at the
71
+ * given value.
72
+ *
73
+ * `html` is the markup the story renders to, at rest: the template rendered
74
+ * once for those props and slot content, components it references rendered
75
+ * inline, and assumes the kit's stylesheet. A component written by hand
76
+ * renders as `handWrittenComponents` maps it - its content, or the template
77
+ * it renders - inside one comment saying its behavior is not included, and
78
+ * slot content written per framework renders its `html`. A story with any
79
+ * other part that has no markup gets no `html`, with a warning naming it.
80
+ * What the markup cannot work out at rest, such as an expression reading the
81
+ * component's script state, is left out, shows at a default, and is named
82
+ * once in `htmlWarnings` and a printed warning.
83
+ *
84
+ * @param kitRoot - The kit root (where its package.json lives)
85
+ * @param componentName - The component, by name
86
+ * @param options - The scenario and the targets to print, and the kit
87
+ * configuration file when it is not the one the kit root gives
88
+ * @returns The source per target, and the html's warnings
89
+ * @example
90
+ * ```ts
91
+ * const { react } = await storySource(kitRoot, 'Button', { scenario: 'variant-dense' });
92
+ * ```
93
+ */
94
+ export async function storySource(
95
+ kitRoot: string,
96
+ componentName: string,
97
+ options: StorySourceOptions = {}
98
+ ): Promise<StorySource> {
99
+ const context = loadPreviewContext(kitRoot, {
100
+ configuration: options.configuration,
101
+ workingDirectory: options.workingDirectory,
102
+ });
103
+ const { components } = await loadKit(context);
104
+ const loaded = components.find(
105
+ (entry) => entry.component.name === componentName
106
+ );
107
+ if (!loaded) {
108
+ throw new Error(
109
+ `[preview] no component named ${componentName} in ${kitRoot}`
110
+ );
111
+ }
112
+ const { component, story } = loaded;
113
+ const model = resolveStory(
114
+ component,
115
+ story,
116
+ context.configuration.controlHints ?? {},
117
+ context.configuration.labels,
118
+ context.omitPattern,
119
+ context.targets
120
+ );
121
+
122
+ let scenarioProps: Record<string, JsonValue> = {};
123
+ let scenario: Scenario | undefined;
124
+ if (options.scenario !== undefined) {
125
+ scenario = model.scenarios.find((entry) => entry.id === options.scenario);
126
+ if (!scenario) {
127
+ throw new Error(
128
+ `[preview] ${componentName} has no scenario '${options.scenario}'; it has ${model.scenarios.map((entry) => `'${entry.id}'`).join(', ') || 'none'}`
129
+ );
130
+ }
131
+ scenarioProps = scenario.props ?? {};
132
+ }
133
+ // A scenario with slot content of its own prints that over the story's.
134
+ const { props, children, named, around } = sourceStoryOf(
135
+ component,
136
+ story,
137
+ storyOnScenario(model, scenario),
138
+ scenarioProps
139
+ );
140
+
141
+ // Each component imports from its source's package entry, as generation does.
142
+ const loadedByName = new Map(
143
+ components.map((entry) => [entry.component.name, entry])
144
+ );
145
+ const defaultModule = context.sources[0].moduleBase;
146
+ const importsFor = (target: Target): SourceStory['imports'] => {
147
+ const imports: SourceStory['imports'] = new Map();
148
+ for (const name of [model.name, ...model.slotComponents]) {
149
+ const entry = loadedByName.get(name);
150
+ imports.set(name, {
151
+ module:
152
+ entry?.component.importModule?.[target] ??
153
+ moduleOfSource(entry?.source.moduleBase ?? defaultModule, target),
154
+ exported: entry?.component.exportName ?? name,
155
+ ...(entry
156
+ ? {
157
+ declaredAttributes: declaredAttributes(
158
+ Object.keys(entry.component.props),
159
+ REACT_ATTRIBUTE_NAMES
160
+ ),
161
+ }
162
+ : {}),
163
+ });
164
+ }
165
+ return imports;
166
+ };
167
+ // The types each component's module exports, which a bound prop's state
168
+ // is typed by where its declared type names them.
169
+ const exportedTypesFor = (target: Target): Map<string, string> => {
170
+ const types = new Map<string, string>();
171
+ // A component's own name, or the name it is exported under, is a value.
172
+ const values = new Set(
173
+ components.flatMap((entry) => [
174
+ entry.component.name,
175
+ entry.component.exportName ?? entry.component.name,
176
+ ])
177
+ );
178
+ // The story's own component first, so its type wins a name another
179
+ // component's module exports too.
180
+ const ordered = [
181
+ ...components.filter((entry) => entry.component.name === componentName),
182
+ ...components.filter((entry) => entry.component.name !== componentName),
183
+ ];
184
+ for (const entry of ordered)
185
+ for (const type of exportedTypesOf(entry.component, [target])?.[target] ??
186
+ [])
187
+ if (!types.has(type) && !values.has(type))
188
+ types.set(
189
+ type,
190
+ entry.component.importModule?.[target] ??
191
+ moduleOfSource(entry.source.moduleBase ?? defaultModule, target)
192
+ );
193
+ return types;
194
+ };
195
+
196
+ // A two-way prop the story gives is controlled: its source binds it.
197
+ const declaredTypes = new Map(
198
+ model.propTypes.map((propType) => [propType.name, propType.declaredType])
199
+ );
200
+ const bindings = (model.bindings ?? [])
201
+ .filter((binding) => binding.prop in props)
202
+ .map((binding) => {
203
+ const declaredType = declaredTypes.get(binding.prop);
204
+ return { ...binding, ...(declaredType ? { declaredType } : {}) };
205
+ });
206
+
207
+ const requested = options.targets ?? [...model.targets, 'html'];
208
+ const sources: StorySource = {};
209
+ for (const target of requested) {
210
+ if (target === 'html') {
211
+ const result = await printHtmlSource(
212
+ context,
213
+ components.map((entry) => entry.component),
214
+ { component, props, children, named, around }
215
+ );
216
+ if (result.markup !== undefined) {
217
+ sources.html = result.markup;
218
+ if (result.warnings.length > 0) {
219
+ sources.htmlWarnings = result.warnings;
220
+ console.warn(
221
+ `[preview] ${htmlWarningLine(componentName, result.warnings)}`
222
+ );
223
+ }
224
+ } else {
225
+ console.warn(
226
+ `[preview] ${componentName} has no html source: it holds ${result.missing.join('; ')}`
227
+ );
228
+ }
229
+ continue;
230
+ }
231
+ if (!model.targets.includes(target)) continue;
232
+ sources[target] = SOURCE_PRINTERS[target]({
233
+ component: model.name,
234
+ props,
235
+ children,
236
+ named,
237
+ ...(around ? { around } : {}),
238
+ imports: importsFor(target),
239
+ ...(bindings.length > 0 ? { bindings } : {}),
240
+ svelteMode: context.svelteMode,
241
+ reactAttributeNames: REACT_ATTRIBUTE_NAMES,
242
+ exportedTypes: exportedTypesFor(target),
243
+ });
244
+ }
245
+ return sources;
246
+ }
247
+
248
+ /** A story as its source prints it: the props a consumer writes and its slot content. */
249
+ export interface SourceStoryContent {
250
+ props: Record<string, JsonValue>;
251
+ children?: SlotFill;
252
+ named: Record<string, SlotFill>;
253
+ /** The content beside the component, as its siblings. */
254
+ around?: StoryAround;
255
+ }
256
+
257
+ /**
258
+ * What a story's source prints for a scenario's props: the props the story file
259
+ * sets (`defaultProps`, `fixed`) and the scenario's, less those equal to the
260
+ * component's declared default, and the story file's slot content, or its
261
+ * `children` text where it curates none. A default slot the story leaves
262
+ * unfilled prints no content: the component's name the preview shows there
263
+ * is the preview's own, which a consumer never writes, unless `placeholder`
264
+ * asks for it, as the html the panes render does.
265
+ *
266
+ * @param component - The component.
267
+ * @param story - Its story file, when it has one.
268
+ * @param model - Its resolved story.
269
+ * @param scenarioProps - The scenario's props.
270
+ * @param options - `placeholder` keeps the preview's text in an unfilled default slot.
271
+ * @returns The props and slot content to print.
272
+ */
273
+ export function sourceStoryOf(
274
+ component: EnumeratedComponent,
275
+ story: Story | undefined,
276
+ model: ResolvedStory,
277
+ scenarioProps: Record<string, JsonValue>,
278
+ options: { placeholder?: boolean } = {}
279
+ ): SourceStoryContent {
280
+ // What the story file and scenario set, not the preview's own control defaults.
281
+ const props: Record<string, JsonValue> = {
282
+ ...(story?.defaultProps ?? {}),
283
+ ...(story?.fixed ?? {}),
284
+ ...scenarioProps,
285
+ };
286
+ let children: SlotFill | undefined = model.slots?.default;
287
+ const childrenText =
288
+ 'children' in props
289
+ ? props.children
290
+ : options.placeholder
291
+ ? model.defaultProps.children
292
+ : undefined;
293
+ delete props.children;
294
+ if (!children && typeof childrenText === 'string')
295
+ children = { kind: 'text', value: childrenText };
296
+ for (const [name, value] of Object.entries(props)) {
297
+ const declared = component.props[name]?.default;
298
+ if (
299
+ value === undefined ||
300
+ (declared !== undefined &&
301
+ JSON.stringify(declared) === JSON.stringify(value))
302
+ ) {
303
+ delete props[name];
304
+ }
305
+ }
306
+ return {
307
+ props: inDeclarationOrder(props, Object.keys(component.props)),
308
+ children,
309
+ named: model.slots?.named ?? {},
310
+ ...(model.around ? { around: model.around } : {}),
311
+ };
312
+ }
313
+
314
+ /**
315
+ * The lines that report what a story's html leaves out, once per story: a
316
+ * heading, then each evaluation warning indented on a line of its own, a
317
+ * warning about the story's own component without its name, and the
318
+ * warnings one component gives for one reason as a single line counting
319
+ * them (see `summarizeHtmlWarnings`).
320
+ *
321
+ * @param componentName - The story's component.
322
+ * @param warnings - The expressions the html could not evaluate at rest.
323
+ * @returns The lines, joined, without a prefix.
324
+ */
325
+ export function htmlWarningLine(
326
+ componentName: string,
327
+ warnings: readonly string[]
328
+ ): string {
329
+ const own = `${componentName}: `;
330
+ return [
331
+ `${componentName}'s html leaves out what it cannot evaluate at rest:`,
332
+ ...summarizeHtmlWarnings(warnings).map(
333
+ (warning) =>
334
+ ` ${warning.startsWith(own) ? warning.slice(own.length) : warning}`
335
+ ),
336
+ ].join('\n');
337
+ }
338
+
339
+ /**
340
+ * Renders a story to the markup it shows at rest, with the kit's shared
341
+ * modules in scope and its styling, as `storySource`'s `html` does.
342
+ *
343
+ * @param context - The kit's preview context.
344
+ * @param components - Every component of the kit.
345
+ * @param story - The component, its props and its slot content.
346
+ * @returns The markup, or what the story holds that has none.
347
+ */
348
+ export async function printHtmlSource(
349
+ context: PreviewContext,
350
+ components: readonly EnumeratedComponent[],
351
+ story: SourceStoryContent & { component: EnumeratedComponent }
352
+ ): Promise<HtmlSourceResult> {
353
+ return htmlSource({
354
+ scope: await sharedScope(context),
355
+ component: story.component,
356
+ props: story.props,
357
+ children: story.children,
358
+ named: story.named,
359
+ ...(story.around ? { around: story.around } : {}),
360
+ components,
361
+ styling: context.styling,
362
+ handWrittenComponents: context.configuration.handWrittenComponents ?? {},
363
+ });
364
+ }
365
+
366
+ /**
367
+ * The exports of `@scaffold-ui-kit/helpers`' framework-free entries and of
368
+ * the kit's shared modules - the helpers its templates import by specifier -
369
+ * under their names, later modules winning a clash, so a kit's own module
370
+ * wins over the package. A module that fails to load contributes nothing; an
371
+ * expression naming one of its exports is then a comment in the markup.
372
+ */
373
+ async function sharedScope(
374
+ context: PreviewContext
375
+ ): Promise<Record<string, unknown>> {
376
+ const scope: Record<string, unknown> = {};
377
+ for (const modulePath of [
378
+ ...context.helperModulesAbsolute,
379
+ ...context.sharedModulesAbsolute,
380
+ ]) {
381
+ try {
382
+ Object.assign(
383
+ scope,
384
+ (await context.importModule(modulePath)) as Record<string, unknown>
385
+ );
386
+ } catch {
387
+ // Left out: the markup marks what depends on it.
388
+ }
389
+ }
390
+ return scope;
391
+ }
package/src/story.ts ADDED
@@ -0,0 +1,42 @@
1
+ // Load a component's story file (stories/<Name>.story.ts, default export) if
2
+ // present. Also decides the omit by name: a kit whose naming marks a compound's
3
+ // parts declares the pattern (`preview.omitPattern`), and a matching
4
+ // component gets no story of its own.
5
+
6
+ import { existsSync } from 'node:fs';
7
+ import { resolve } from 'node:path';
8
+ import type { Story } from './lib/types.js';
9
+ import type { ModuleImporter } from './lib/types.js';
10
+
11
+ /** Whether the kit's `omitPattern` leaves this component out by its name. */
12
+ export function isStructurallyOmitted(
13
+ name: string,
14
+ omitPattern?: RegExp
15
+ ): boolean {
16
+ return omitPattern?.test(name) ?? false;
17
+ }
18
+
19
+ export async function loadStory(
20
+ name: string,
21
+ storiesDirectory: string | undefined,
22
+ importModule: ModuleImporter
23
+ ): Promise<Story | undefined> {
24
+ if (!storiesDirectory) return undefined;
25
+ const file = resolve(storiesDirectory, `${name}.story.ts`);
26
+ if (!existsSync(file)) return undefined;
27
+ const mod = (await importModule(file)) as { default?: Story };
28
+ // A story file that exports nothing would silently drop the component's
29
+ // curation (its defaults, slots and scenarios), so it is an error. The module
30
+ // importer's interop answers `default` even when none is exported, so the
31
+ // export is looked for among the module's own keys.
32
+ if (
33
+ !Object.keys(mod).includes('default') ||
34
+ !mod.default ||
35
+ typeof mod.default !== 'object'
36
+ ) {
37
+ throw new Error(
38
+ `[preview] ${file} must default-export the ${name} story object`
39
+ );
40
+ }
41
+ return mod.default;
42
+ }