handoff-app 1.0.6 → 1.1.0-1

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 (302) hide show
  1. package/Changelog.md +60 -0
  2. package/config/config.template.js +1 -2
  3. package/config/docs/system/alert.md +0 -23
  4. package/config/docs/system/button.md +0 -27
  5. package/config/docs/system/checkbox.md +0 -23
  6. package/config/docs/system/input.md +0 -23
  7. package/config/docs/system/modal.md +0 -23
  8. package/config/docs/system/pagination.md +0 -23
  9. package/config/docs/system/radio.md +0 -23
  10. package/config/docs/system/select.md +0 -23
  11. package/config/docs/system/switch.md +1 -24
  12. package/config/docs/system/tooltip.md +0 -23
  13. package/dist/{app.d.ts → app-builder/build.d.ts} +4 -10
  14. package/dist/app-builder/build.js +207 -0
  15. package/dist/app-builder/client-config.d.ts +9 -0
  16. package/dist/app-builder/client-config.js +62 -0
  17. package/dist/app-builder/index.d.ts +2 -0
  18. package/dist/app-builder/index.js +12 -0
  19. package/dist/app-builder/paths.d.ts +19 -0
  20. package/dist/app-builder/paths.js +56 -0
  21. package/dist/app-builder/watchers.d.ts +45 -0
  22. package/dist/app-builder/watchers.js +302 -0
  23. package/dist/app-builder/websocket.d.ts +12 -0
  24. package/dist/app-builder/websocket.js +63 -0
  25. package/dist/cache/build-cache.d.ts +0 -2
  26. package/dist/cache/build-cache.js +6 -16
  27. package/dist/{create.js → cli/create.js} +2 -2
  28. package/dist/cli/eject.d.ts +2 -2
  29. package/dist/cli/eject.js +2 -2
  30. package/dist/cli/make.d.ts +0 -4
  31. package/dist/cli/make.js +14 -2
  32. package/dist/cli.js +1 -1
  33. package/dist/commands/build/components.js +1 -1
  34. package/dist/commands/init/index.js +1 -1
  35. package/dist/commands/utils.d.ts +1 -1
  36. package/dist/{config.d.ts → config/defaults.d.ts} +3 -4
  37. package/dist/{config.js → config/defaults.js} +8 -5
  38. package/dist/config/index.d.ts +5 -0
  39. package/dist/config/index.js +16 -0
  40. package/dist/config/loader.d.ts +11 -0
  41. package/dist/config/loader.js +49 -0
  42. package/dist/config/runtime.d.ts +36 -0
  43. package/dist/config/runtime.js +151 -0
  44. package/dist/config/validator.d.ts +9 -0
  45. package/dist/config/validator.js +26 -0
  46. package/dist/index.d.ts +0 -7
  47. package/dist/index.js +8 -198
  48. package/dist/pipeline/archive.d.ts +19 -0
  49. package/dist/pipeline/archive.js +80 -0
  50. package/dist/pipeline/components.d.ts +5 -0
  51. package/dist/pipeline/components.js +20 -0
  52. package/dist/{documentation-object.d.ts → pipeline/documentation.d.ts} +1 -1
  53. package/dist/{documentation-object.js → pipeline/documentation.js} +3 -3
  54. package/dist/pipeline/figma.d.ts +11 -0
  55. package/dist/pipeline/figma.js +152 -0
  56. package/dist/pipeline/index.d.ts +15 -0
  57. package/dist/pipeline/index.js +53 -0
  58. package/dist/pipeline/styles.d.ts +10 -0
  59. package/dist/pipeline/styles.js +136 -0
  60. package/dist/pipeline/validation.d.ts +6 -0
  61. package/dist/pipeline/validation.js +36 -0
  62. package/dist/transformers/docgen/index.d.ts +19 -4
  63. package/dist/transformers/docgen/index.js +226 -32
  64. package/dist/transformers/plugins/csf-render.d.ts +5 -0
  65. package/dist/transformers/plugins/csf-render.js +270 -0
  66. package/dist/transformers/plugins/handlebars-previews.js +5 -3
  67. package/dist/transformers/plugins/index.d.ts +1 -0
  68. package/dist/transformers/plugins/index.js +3 -1
  69. package/dist/transformers/plugins/ssr-render.js +7 -1
  70. package/dist/transformers/plugins.d.ts +1 -0
  71. package/dist/transformers/plugins.js +3 -1
  72. package/dist/transformers/preview/component/api.js +2 -3
  73. package/dist/transformers/preview/component/builder.js +1 -4
  74. package/dist/transformers/preview/component/css.d.ts +3 -2
  75. package/dist/transformers/preview/component/css.js +7 -12
  76. package/dist/transformers/preview/component/html.js +7 -4
  77. package/dist/transformers/preview/component/javascript.d.ts +2 -2
  78. package/dist/transformers/preview/component/javascript.js +7 -7
  79. package/dist/transformers/preview/component.d.ts +6 -6
  80. package/dist/transformers/preview/component.js +0 -46
  81. package/dist/transformers/preview/types.d.ts +3 -1
  82. package/dist/transformers/types.d.ts +0 -18
  83. package/dist/transformers/utils/handlebars.d.ts +2 -0
  84. package/dist/transformers/utils/handlebars.js +10 -4
  85. package/dist/transformers/utils/schema-loader.js +2 -2
  86. package/dist/transformers/utils/schema.d.ts +2 -2
  87. package/dist/transformers/utils/schema.js +2 -2
  88. package/dist/types/config.d.ts +16 -1
  89. package/dist/{types.d.ts → types/preview.d.ts} +5 -3
  90. package/package.json +7 -17
  91. package/src/app/components/Component/BestPracticesCard.tsx +1 -1
  92. package/src/app/components/Component/ComponentLists.tsx +1 -1
  93. package/src/app/components/Component/PageSliceResolver.tsx +1 -1
  94. package/src/app/components/Component/Preview.tsx +410 -169
  95. package/src/app/components/Component/slices/BestPracticesSlice.tsx +1 -1
  96. package/src/app/components/Component/slices/ComponentDisplaySlice.tsx +1 -1
  97. package/src/app/components/Component/slices/PropertiesSlice.tsx +1 -1
  98. package/src/app/components/Component/slices/ValidationResultsSlice.tsx +1 -1
  99. package/src/app/components/Foundations/RulesSheet.tsx +10 -4
  100. package/src/app/components/Layout/Main.tsx +1 -1
  101. package/src/app/components/Markdown/CodeHighlight.tsx +20 -39
  102. package/src/app/components/Navigation/PrevNextNav.tsx +13 -7
  103. package/src/app/components/Validation/ValidationResults.tsx +1 -1
  104. package/src/app/components/context/PreviewContext.tsx +1 -1
  105. package/src/app/components/util/index.ts +4 -4
  106. package/src/app/next.config.mjs +0 -3
  107. package/src/app/pages/system/component/[component]/index.tsx +42 -20
  108. package/src/app/pages/system/component/index.tsx +10 -87
  109. package/src/app/pages/system/index.tsx +6 -25
  110. package/src/app/pages/system/tokens/components/[component]/index.tsx +17 -4
  111. package/src/app/pages/system/tokens/index.tsx +10 -85
  112. package/src/app-builder/README.md +14 -0
  113. package/src/app-builder/build.ts +231 -0
  114. package/src/app-builder/client-config.ts +53 -0
  115. package/src/app-builder/index.ts +3 -0
  116. package/src/app-builder/paths.ts +44 -0
  117. package/src/app-builder/watchers.ts +278 -0
  118. package/src/app-builder/websocket.ts +61 -0
  119. package/src/cache/README.md +11 -0
  120. package/src/cache/build-cache.ts +1 -16
  121. package/src/cli/README.md +12 -0
  122. package/src/{create.ts → cli/create.ts} +2 -2
  123. package/src/cli/eject.ts +2 -2
  124. package/src/cli/make.ts +16 -2
  125. package/src/cli.ts +1 -1
  126. package/src/commands/README.md +23 -0
  127. package/src/commands/build/components.ts +1 -1
  128. package/src/commands/init/index.ts +1 -1
  129. package/src/config/README.md +23 -0
  130. package/src/{config.ts → config/defaults.ts} +8 -7
  131. package/src/config/index.ts +12 -0
  132. package/src/config/loader.ts +48 -0
  133. package/src/config/runtime.ts +176 -0
  134. package/src/config/validator.ts +24 -0
  135. package/src/index.ts +2 -221
  136. package/src/pipeline/README.md +20 -0
  137. package/src/pipeline/archive.ts +75 -0
  138. package/src/pipeline/components.ts +9 -0
  139. package/src/{documentation-object.ts → pipeline/documentation.ts} +6 -6
  140. package/src/pipeline/figma.ts +146 -0
  141. package/src/pipeline/index.ts +38 -0
  142. package/src/pipeline/styles.ts +152 -0
  143. package/src/pipeline/validation.ts +25 -0
  144. package/src/transformers/README.md +12 -72
  145. package/src/transformers/docgen/index.ts +279 -39
  146. package/src/transformers/plugins/csf-render.ts +315 -0
  147. package/src/transformers/plugins/handlebars-previews.ts +5 -3
  148. package/src/transformers/plugins/index.ts +1 -0
  149. package/src/transformers/plugins/ssr-render.ts +14 -2
  150. package/src/transformers/plugins.ts +1 -0
  151. package/src/transformers/preview/component/api.ts +1 -2
  152. package/src/transformers/preview/component/builder.ts +1 -5
  153. package/src/transformers/preview/component/css.ts +6 -9
  154. package/src/transformers/preview/component/html.ts +6 -3
  155. package/src/transformers/preview/component/javascript.ts +5 -4
  156. package/src/transformers/preview/component.ts +6 -45
  157. package/src/transformers/preview/types.ts +3 -1
  158. package/src/transformers/types.ts +0 -18
  159. package/src/transformers/utils/handlebars.ts +12 -3
  160. package/src/transformers/utils/schema-loader.ts +2 -2
  161. package/src/transformers/utils/schema.ts +2 -2
  162. package/src/types/README.md +11 -0
  163. package/src/types/config.ts +16 -1
  164. package/src/{types.ts → types/preview.ts} +5 -3
  165. package/src/utils/README.md +13 -0
  166. package/templates/default/handoff.config.js.tpl +6 -0
  167. package/templates/default/handoff.config.with-examples.js.tpl +6 -0
  168. package/.env.example +0 -4
  169. package/config/templates/integration/integration.config.json +0 -84
  170. package/config/templates/integration/sass/_variables-default.scss +0 -255
  171. package/config/templates/integration/sass/_variables.scss +0 -797
  172. package/config/templates/integration/sass/extended/_alert.scss +0 -20
  173. package/config/templates/integration/sass/extended/_button.scss +0 -73
  174. package/config/templates/integration/sass/extended/_checkbox.scss +0 -118
  175. package/config/templates/integration/sass/extended/_input.scss +0 -60
  176. package/config/templates/integration/sass/extended/_modal.scss +0 -46
  177. package/config/templates/integration/sass/extended/_pagination.scss +0 -3
  178. package/config/templates/integration/sass/extended/_radio.scss +0 -13
  179. package/config/templates/integration/sass/extended/_select.scss +0 -54
  180. package/config/templates/integration/sass/extended/_switch.scss +0 -22
  181. package/config/templates/integration/sass/extended/_tooltip.scss +0 -20
  182. package/config/templates/integration/sass/extended/_utilities.scss +0 -7
  183. package/config/templates/integration/sass/main.scss +0 -105
  184. package/config/templates/integration/sass/maps/_alert.scss +0 -16
  185. package/config/templates/integration/sass/maps/_button.scss +0 -77
  186. package/config/templates/integration/sass/maps/_checkbox.scss +0 -35
  187. package/config/templates/integration/sass/maps/_input.scss +0 -69
  188. package/config/templates/integration/sass/maps/_modal.scss +0 -54
  189. package/config/templates/integration/sass/maps/_pagination.scss +0 -27
  190. package/config/templates/integration/sass/maps/_radio.scss +0 -4
  191. package/config/templates/integration/sass/maps/_select.scss +0 -43
  192. package/config/templates/integration/sass/maps/_switch.scss +0 -15
  193. package/config/templates/integration/sass/maps/_tooltip.scss +0 -30
  194. package/config/templates/integration/sass/readme.md +0 -3
  195. package/config/templates/integration/templates/alert/default.html +0 -7
  196. package/config/templates/integration/templates/alert/horizontal.html +0 -12
  197. package/config/templates/integration/templates/alert/vertical.html +0 -12
  198. package/config/templates/integration/templates/alert/view.config.json +0 -10
  199. package/config/templates/integration/templates/button/default.html +0 -5
  200. package/config/templates/integration/templates/button/large.html +0 -5
  201. package/config/templates/integration/templates/button/medium.html +0 -5
  202. package/config/templates/integration/templates/button/primary/disabled.html +0 -5
  203. package/config/templates/integration/templates/button/small.html +0 -5
  204. package/config/templates/integration/templates/button/view.config.json +0 -24
  205. package/config/templates/integration/templates/checkbox/default/off.html +0 -10
  206. package/config/templates/integration/templates/checkbox/default/on.html +0 -10
  207. package/config/templates/integration/templates/checkbox/default.html +0 -22
  208. package/config/templates/integration/templates/checkbox/disabled.html +0 -16
  209. package/config/templates/integration/templates/checkbox/view.config.json +0 -26
  210. package/config/templates/integration/templates/input/complete.html +0 -14
  211. package/config/templates/integration/templates/input/default.html +0 -14
  212. package/config/templates/integration/templates/input/disabled.html +0 -14
  213. package/config/templates/integration/templates/input/error.html +0 -14
  214. package/config/templates/integration/templates/input/view.config.json +0 -33
  215. package/config/templates/integration/templates/main.js +0 -15
  216. package/config/templates/integration/templates/main.scss +0 -31
  217. package/config/templates/integration/templates/modal/default.html +0 -20
  218. package/config/templates/integration/templates/modal/view.config.json +0 -16
  219. package/config/templates/integration/templates/pagination/default.html +0 -31
  220. package/config/templates/integration/templates/pagination/lg.html +0 -31
  221. package/config/templates/integration/templates/pagination/sm.html +0 -31
  222. package/config/templates/integration/templates/pagination/view.config.json +0 -6
  223. package/config/templates/integration/templates/radio/default/off.html +0 -10
  224. package/config/templates/integration/templates/radio/default/on.html +0 -10
  225. package/config/templates/integration/templates/radio/default.html +0 -10
  226. package/config/templates/integration/templates/radio/disabled.html +0 -16
  227. package/config/templates/integration/templates/radio/view.config.json +0 -26
  228. package/config/templates/integration/templates/select/default.html +0 -10
  229. package/config/templates/integration/templates/select/disabled.html +0 -10
  230. package/config/templates/integration/templates/select/error.html +0 -10
  231. package/config/templates/integration/templates/select/view.config.json +0 -33
  232. package/config/templates/integration/templates/switch/default/off.html +0 -10
  233. package/config/templates/integration/templates/switch/default/on.html +0 -10
  234. package/config/templates/integration/templates/switch/default.html +0 -8
  235. package/config/templates/integration/templates/switch/disabled.html +0 -16
  236. package/config/templates/integration/templates/switch/view.config.json +0 -26
  237. package/config/templates/integration/templates/tooltip/default.html +0 -16
  238. package/config/templates/integration/templates/tooltip/view.config.json +0 -6
  239. package/dist/app.js +0 -617
  240. package/dist/pipeline.d.ts +0 -22
  241. package/dist/pipeline.js +0 -374
  242. package/integration/components/example/example.js +0 -70
  243. package/integration/components/example/style.scss +0 -1
  244. package/integration/components/example/template.hbs +0 -12
  245. package/integration/integration.config.json +0 -84
  246. package/integration/sass/main.scss +0 -105
  247. package/integration/sass/readme.md +0 -3
  248. package/integration/templates/alert/default.html +0 -7
  249. package/integration/templates/alert/horizontal.html +0 -12
  250. package/integration/templates/alert/vertical.html +0 -12
  251. package/integration/templates/alert/view.config.json +0 -10
  252. package/integration/templates/button/default.html +0 -5
  253. package/integration/templates/button/large.html +0 -5
  254. package/integration/templates/button/medium.html +0 -5
  255. package/integration/templates/button/primary/disabled.html +0 -5
  256. package/integration/templates/button/small.html +0 -5
  257. package/integration/templates/button/view.config.json +0 -24
  258. package/integration/templates/checkbox/default/off.html +0 -10
  259. package/integration/templates/checkbox/default/on.html +0 -10
  260. package/integration/templates/checkbox/default.html +0 -22
  261. package/integration/templates/checkbox/disabled.html +0 -16
  262. package/integration/templates/checkbox/view.config.json +0 -26
  263. package/integration/templates/input/complete.html +0 -14
  264. package/integration/templates/input/default.html +0 -14
  265. package/integration/templates/input/disabled.html +0 -14
  266. package/integration/templates/input/error.html +0 -14
  267. package/integration/templates/input/view.config.json +0 -33
  268. package/integration/templates/main.js +0 -15
  269. package/integration/templates/main.scss +0 -31
  270. package/integration/templates/modal/default.html +0 -20
  271. package/integration/templates/modal/view.config.json +0 -16
  272. package/integration/templates/pagination/default.html +0 -31
  273. package/integration/templates/pagination/lg.html +0 -31
  274. package/integration/templates/pagination/sm.html +0 -31
  275. package/integration/templates/pagination/view.config.json +0 -6
  276. package/integration/templates/radio/default/off.html +0 -10
  277. package/integration/templates/radio/default/on.html +0 -10
  278. package/integration/templates/radio/default.html +0 -10
  279. package/integration/templates/radio/disabled.html +0 -16
  280. package/integration/templates/radio/view.config.json +0 -26
  281. package/integration/templates/select/default.html +0 -10
  282. package/integration/templates/select/disabled.html +0 -10
  283. package/integration/templates/select/error.html +0 -10
  284. package/integration/templates/select/view.config.json +0 -33
  285. package/integration/templates/switch/default/off.html +0 -10
  286. package/integration/templates/switch/default/on.html +0 -10
  287. package/integration/templates/switch/default.html +0 -8
  288. package/integration/templates/switch/disabled.html +0 -16
  289. package/integration/templates/switch/view.config.json +0 -26
  290. package/integration/templates/tooltip/default.html +0 -16
  291. package/integration/templates/tooltip/view.config.json +0 -6
  292. package/src/app.ts +0 -654
  293. package/src/pipeline.ts +0 -413
  294. /package/config/templates/{integration/components/template → component}/template.hbs +0 -0
  295. /package/config/templates/{integration/components/template → component}/template.js +0 -0
  296. /package/config/templates/{integration/components/template → component}/template.json +0 -0
  297. /package/config/templates/{integration/components/template → component}/template.scss +0 -0
  298. /package/dist/{create.d.ts → cli/create.d.ts} +0 -0
  299. /package/dist/transformers/{config.d.ts → vite-config.d.ts} +0 -0
  300. /package/dist/transformers/{config.js → vite-config.js} +0 -0
  301. /package/dist/{types.js → types/preview.js} +0 -0
  302. /package/src/transformers/{config.ts → vite-config.ts} +0 -0
package/Changelog.md CHANGED
@@ -6,6 +6,66 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to
7
7
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## \[1.1.0] - 2026-03-05
10
+
11
+ This release introduces two major new features. First, handoff now can do automatic
12
+ type detection in typescript files. By using a new library we wrote to leverage the
13
+ typescript engine, we can automatically extract types from your components and give
14
+ you visiblity into the type architecture across your whole project.
15
+
16
+ Second, we've long wanted to support the Storybook component story format, and this
17
+ release provides robust support for stories expressed as tsx or js files.
18
+
19
+ This release also does significant cleanup and quality of life improvements. We've
20
+ fixed some longstanding annoyances, and continue to focus the application.
21
+
22
+ ### Automatic type documentation
23
+
24
+ * Integrated **handoff-docgen** for component documentation: props and types are
25
+ inferred from React/TSX components and merged with story data where available.
26
+ * Properties table shows inferred types, default values, and descriptions from
27
+ component source and story argTypes.
28
+ * Empty state message when no properties are documented; improved layout and
29
+ formatting for inline and default values in the Preview component.
30
+
31
+ ### CSF support
32
+
33
+ * Components can use Storybook-style Component Story Format (`.stories.tsx` / `.stories.js`).
34
+ Stories are parsed to generate variants, args, and argTypes for the component page.
35
+ * CSF parsing supports deep type nesting and correctly shows nested items for both
36
+ Handlebars and CSF components.
37
+ * New example component `example-csf` demonstrates CSF integration alongside the
38
+ existing Handlebars and React examples.
39
+
40
+ ### Component page and code display
41
+
42
+ * **Handlebars formatting:** Code highlight now supports Handlebars (`.hbs`) templates—
43
+ syntax highlighting uses the correct language instead of plain HTML.
44
+ * Handlebars components no longer show rendered HTML in the Code snippet dropdown;
45
+ the template source is shown correctly.
46
+ * Empty code tabs are filtered from the dropdown; HTML fallback for inactive states
47
+ removed for clearer code view.
48
+ * Preview dropdown shows the active variant instead of a placeholder; style loading
49
+ and incremental component summary updates fixed in watch mode.
50
+ * Prev/next navigation respects component group boundaries and hides invalid links.
51
+
52
+ ### Cleanup and internal changes
53
+
54
+ * Removed legacy integration directory and relocated component scaffolding templates
55
+ under `integration/components/` (e.g. `example`, `example-csf`, `example-react`).
56
+ * Removed legacy shared styles pipeline; `makeComponent` and config now use
57
+ `config.entries.components` consistently.
58
+ * Removed deprecated `serverRuntimeConfig` usage, outdated `.env.example` with
59
+ incorrect variable names, and the patch-package workaround where no longer needed.
60
+ * Dependencies cleanup and package updates.
61
+ * Internal reorg: new `app-builder` (build, watchers, client config, websocket),
62
+ pipeline split into `pipeline/` (archive, components, figma, styles, validation),
63
+ config split into `config/` (defaults, loader, runtime, validator), and READMEs
64
+ added for major modules.
65
+ * Global CSS/JS bundles now build on startup in dev mode; watcher added to rebuild
66
+ main bundles and components when global entry files change.
67
+ * Stale JSDoc and command descriptions updated.
68
+
9
69
  ## \[1.0.6] - 2026-02-24
10
70
 
11
71
  Version 1.0.4 fixed an issue when running Handoff in subpaths (eg.
@@ -55,8 +55,7 @@ module.exports = {
55
55
  entries: {
56
56
  scss: './sass/main.scss',
57
57
  js: './js/main.js',
58
- bundle: './js/main.js',
59
- components: ['./integration/components'],
58
+ components: ['./components'],
60
59
  },
61
60
  // These are the asset zip file download links
62
61
  assets_zip_links: {
@@ -5,26 +5,3 @@ image: component-alert
5
5
  metaTitle: 'Alerts | Handoff Design System'
6
6
  metaDescription: 'Alerts are used to communicate a state that affects a system, feature or page. They are used to provide feedback about an action that has taken place.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this alert does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with alerts
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with alerts
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -5,30 +5,3 @@ image: component-button
5
5
  metaTitle: 'Buttons | Handoff Design System'
6
6
  metaDescription: 'Buttons allow users to take actions and make choices, with a single click.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this button does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - Make it clear what this button does for the user.
19
- - Use at most two buttons in one group.
20
- - Attribute indicating if the element should be.
21
-
22
- </div>
23
- <div className="c-do-dont__dont">
24
-
25
- <X /> DON&apos;T
26
-
27
- - Use more than two words for call to action.
28
- - First letter of each sentence defaults to a capital letter.
29
- - Attribute indicating if the element should be.
30
-
31
- </div>
32
- </div>
33
-
34
- ---
@@ -5,26 +5,3 @@ image: component-checkbox
5
5
  metaTitle: 'Checkboxes | Handoff Design System'
6
6
  metaDescription: 'Checkboxes create an on/off boolean switch that can be built into array.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this checkboxes does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with checkboxes
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with checkboxes
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -6,26 +6,3 @@ image: component-input
6
6
  metaTitle: 'Inputs | Handoff Design System'
7
7
  metaDescription: 'Form input controls like <input> and <textarea>.'
8
8
  ---
9
-
10
- ### Accessibility
11
-
12
- Make it clear what this input does for the user.
13
-
14
- <div className="c-do-dont">
15
- <div className="c-do-dont__do">
16
-
17
- <Check /> DO
18
-
19
- - What to do with inputs
20
-
21
- </div>
22
- <div className="c-do-dont__dont">
23
-
24
- <X /> DON&apos;T
25
-
26
- - What not to do with inputs
27
-
28
- </div>
29
- </div>
30
-
31
- ---
@@ -7,26 +7,3 @@ metaTitle: 'Modal dialogs | Handoff Design System'
7
7
  metaDescription: 'Modal dialogs present popup information to inform users of important information
8
8
  and sometimes allow the user to take action.'
9
9
  ---
10
-
11
- ### Accessibility
12
-
13
- Make it clear what this modal does for the user.
14
-
15
- <div className="c-do-dont">
16
- <div className="c-do-dont__do">
17
-
18
- <Check /> DO
19
-
20
- - What to do with modals
21
-
22
- </div>
23
- <div className="c-do-dont__dont">
24
-
25
- <X /> DON&apos;T
26
-
27
- - What not to do with modals
28
-
29
- </div>
30
- </div>
31
-
32
- ---
@@ -5,26 +5,3 @@ image: component-pagination
5
5
  metaTitle: 'Pagination | Handoff Design System'
6
6
  metaDescription: 'Pagination provides swift access to all pages, while indicating that more pages exist.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this pagination widget does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with pagination
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with pagination
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -5,26 +5,3 @@ image: component-radio
5
5
  metaTitle: 'Radios | Handoff Design System'
6
6
  metaDescription: 'Radios create an on/off boolean switch that can be built into array.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this radio widget does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with radio
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with radio
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -5,26 +5,3 @@ image: component-select
5
5
  metaTitle: 'Selects | Handoff Design System'
6
6
  metaDescription: 'Selects create dropdowns for selecting a single entry from a list.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this select widget does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with select
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with select
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -2,29 +2,6 @@
2
2
  title: Switches
3
3
  description: Switches render a single boolean toggle that has an off state and an on state.
4
4
  image: component-switch
5
- metaTitle: 'Selects | Handoff Design System'
5
+ metaTitle: 'Switches | Handoff Design System'
6
6
  metaDescription: 'Switches render a single boolean toggle that has an off state and an on state.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this switch widget does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with switches
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with switches
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -5,26 +5,3 @@ image: component-tooltip
5
5
  metaTitle: 'Tooltips | Handoff Design System'
6
6
  metaDescription: 'Tooltips are informative message that appears when a user interacts with an element.'
7
7
  ---
8
-
9
- ### Accessibility
10
-
11
- Make it clear what this tooltip widget does for the user.
12
-
13
- <div className="c-do-dont">
14
- <div className="c-do-dont__do">
15
-
16
- <Check /> DO
17
-
18
- - What to do with tooltips
19
-
20
- </div>
21
- <div className="c-do-dont__dont">
22
-
23
- <X /> DON&apos;T
24
-
25
- - What not to do with tooltips
26
-
27
- </div>
28
- </div>
29
-
30
- ---
@@ -1,22 +1,16 @@
1
- import Handoff from '.';
1
+ import Handoff from '..';
2
2
  /**
3
- * Build the next js application
4
- * @param handoff
5
- * @returns
3
+ * Build the Next.js documentation application.
6
4
  */
7
5
  declare const buildApp: (handoff: Handoff, skipComponents?: boolean) => Promise<void>;
8
6
  /**
9
- * Watch the next js application.
7
+ * Watch the Next.js application.
10
8
  * Starts a custom dev server with Handoff-specific watchers and hot-reloading.
11
- *
12
- * @param handoff
13
9
  */
14
10
  export declare const watchApp: (handoff: Handoff) => Promise<void>;
15
11
  /**
16
- * Watch the next js application using the standard Next.js dev server.
12
+ * Watch the Next.js application using the standard Next.js dev server.
17
13
  * This is useful for debugging the Next.js app itself without the Handoff overlay.
18
- *
19
- * @param handoff
20
14
  */
21
15
  export declare const devApp: (handoff: Handoff) => Promise<void>;
22
16
  export default buildApp;
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.devApp = exports.watchApp = void 0;
16
+ const cross_spawn_1 = __importDefault(require("cross-spawn"));
17
+ const fs_extra_1 = __importDefault(require("fs-extra"));
18
+ const path_1 = __importDefault(require("path"));
19
+ const components_1 = require("../pipeline/components");
20
+ const css_1 = require("../transformers/preview/component/css");
21
+ const javascript_1 = require("../transformers/preview/component/javascript");
22
+ const builder_1 = __importDefault(require("../transformers/preview/component/builder"));
23
+ const logger_1 = require("../utils/logger");
24
+ const client_config_1 = require("./client-config");
25
+ const paths_1 = require("./paths");
26
+ const watchers_1 = require("./watchers");
27
+ const websocket_1 = require("./websocket");
28
+ /**
29
+ * Performs cleanup of the application directory by removing the existing app directory if it exists.
30
+ */
31
+ const cleanupAppDirectory = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
32
+ const appPath = (0, paths_1.getAppPath)(handoff);
33
+ // Clean project app dir
34
+ if (fs_extra_1.default.existsSync(appPath)) {
35
+ yield fs_extra_1.default.remove(appPath);
36
+ }
37
+ });
38
+ /**
39
+ * Prepares the project application by copying source files and configuring Next.js.
40
+ *
41
+ * @returns The path to the prepared application directory
42
+ */
43
+ const initializeProjectApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
44
+ var _a, _b, _c;
45
+ const srcPath = path_1.default.resolve(handoff.modulePath, 'src', 'app');
46
+ const appPath = (0, paths_1.getAppPath)(handoff);
47
+ // Publish tokens API
48
+ yield (0, client_config_1.generateTokensApi)(handoff);
49
+ // Prepare project app dir
50
+ yield fs_extra_1.default.ensureDir(appPath);
51
+ yield fs_extra_1.default.copy(srcPath, appPath, { overwrite: true, filter: (file) => !file.includes('next.config.mjs') });
52
+ yield (0, paths_1.syncPublicFiles)(handoff);
53
+ // Copy custom theme CSS if it exists in the user's project
54
+ const customThemePath = path_1.default.resolve(handoff.workingPath, 'theme.css');
55
+ if (fs_extra_1.default.existsSync(customThemePath)) {
56
+ const destPath = path_1.default.resolve(appPath, 'css', 'theme.css');
57
+ yield fs_extra_1.default.copy(customThemePath, destPath, { overwrite: true });
58
+ logger_1.Logger.success(`Custom theme.css loaded`);
59
+ }
60
+ // Prepare project app configuration
61
+ // Warning: Regex replacement is fragile and depends on exact formatting in next.config.mjs
62
+ const handoffProjectId = handoff.getProjectId();
63
+ const handoffAppBasePath = (_a = handoff.config.app.base_path) !== null && _a !== void 0 ? _a : '';
64
+ const handoffWorkingPath = path_1.default.resolve(handoff.workingPath);
65
+ const handoffModulePath = path_1.default.resolve(handoff.modulePath);
66
+ const handoffExportPath = path_1.default.resolve(handoff.workingPath, handoff.exportsDirectory, handoff.getProjectId());
67
+ const nextConfigPath = path_1.default.resolve(srcPath, 'next.config.mjs');
68
+ const targetPath = path_1.default.resolve(appPath, 'next.config.mjs');
69
+ const handoffWebsocketPort = (_c = (_b = handoff.config.app.ports) === null || _b === void 0 ? void 0 : _b.websocket) !== null && _c !== void 0 ? _c : 3001;
70
+ const nextConfigContent = (yield fs_extra_1.default.readFile(nextConfigPath, 'utf-8'))
71
+ .replace(/basePath:\s+''/g, `basePath: '${handoffAppBasePath}'`)
72
+ .replace(/HANDOFF_PROJECT_ID:\s+''/g, `HANDOFF_PROJECT_ID: '${handoffProjectId}'`)
73
+ .replace(/HANDOFF_APP_BASE_PATH:\s+''/g, `HANDOFF_APP_BASE_PATH: '${handoffAppBasePath}'`)
74
+ .replace(/HANDOFF_WORKING_PATH:\s+''/g, `HANDOFF_WORKING_PATH: '${handoffWorkingPath}'`)
75
+ .replace(/HANDOFF_MODULE_PATH:\s+''/g, `HANDOFF_MODULE_PATH: '${handoffModulePath}'`)
76
+ .replace(/HANDOFF_EXPORT_PATH:\s+''/g, `HANDOFF_EXPORT_PATH: '${handoffExportPath}'`)
77
+ .replace(/HANDOFF_WEBSOCKET_PORT:\s+''/g, `HANDOFF_WEBSOCKET_PORT: '${handoffWebsocketPort}'`)
78
+ .replace(/%HANDOFF_MODULE_PATH%/g, handoffModulePath);
79
+ yield fs_extra_1.default.writeFile(targetPath, nextConfigContent);
80
+ return appPath;
81
+ });
82
+ /**
83
+ * Build the Next.js documentation application.
84
+ */
85
+ const buildApp = (handoff, skipComponents) => __awaiter(void 0, void 0, void 0, function* () {
86
+ skipComponents = skipComponents !== null && skipComponents !== void 0 ? skipComponents : false;
87
+ // Perform cleanup
88
+ yield cleanupAppDirectory(handoff);
89
+ // Build components
90
+ if (!skipComponents) {
91
+ yield (0, components_1.buildComponents)(handoff);
92
+ }
93
+ // Prepare app
94
+ const appPath = yield initializeProjectApp(handoff);
95
+ yield (0, client_config_1.persistClientConfig)(handoff);
96
+ // Build app
97
+ const buildResult = cross_spawn_1.default.sync('npx', ['next', 'build'], {
98
+ cwd: appPath,
99
+ stdio: 'inherit',
100
+ env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'production' }),
101
+ });
102
+ if (buildResult.status !== 0) {
103
+ let errorMsg = `Next.js build failed with exit code ${buildResult.status}`;
104
+ if (buildResult.error) {
105
+ errorMsg += `\nSpawn error: ${buildResult.error.message}`;
106
+ }
107
+ throw new Error(errorMsg);
108
+ }
109
+ // Ensure output root directory exists
110
+ const outputRoot = path_1.default.resolve(handoff.workingPath, handoff.sitesDirectory);
111
+ yield fs_extra_1.default.ensureDir(outputRoot);
112
+ // Clean the project output directory (if exists)
113
+ const output = path_1.default.resolve(outputRoot, handoff.getProjectId());
114
+ if (fs_extra_1.default.existsSync(output)) {
115
+ yield fs_extra_1.default.remove(output);
116
+ }
117
+ // Copy the build files into the project output directory
118
+ yield fs_extra_1.default.copy(path_1.default.resolve(appPath, 'out'), output);
119
+ });
120
+ /**
121
+ * Watch the Next.js application.
122
+ * Starts a custom dev server with Handoff-specific watchers and hot-reloading.
123
+ */
124
+ const watchApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
125
+ var _a, _b, _c, _d;
126
+ // Initial processing of the components with caching enabled
127
+ // This will skip rebuilding components whose source files haven't changed
128
+ yield (0, builder_1.default)(handoff, undefined, undefined, { useCache: true });
129
+ yield (0, javascript_1.buildMainJS)(handoff);
130
+ yield (0, css_1.buildMainCss)(handoff);
131
+ const appPath = yield initializeProjectApp(handoff);
132
+ // Persist client configuration
133
+ yield (0, client_config_1.persistClientConfig)(handoff);
134
+ // Watch app source
135
+ (0, watchers_1.watchAppSource)(handoff, initializeProjectApp);
136
+ const hostname = 'localhost';
137
+ const port = (_b = (_a = handoff.config.app.ports) === null || _a === void 0 ? void 0 : _a.app) !== null && _b !== void 0 ? _b : 3000;
138
+ // purge out cache
139
+ const moduleOutput = path_1.default.resolve(appPath, 'out');
140
+ if (fs_extra_1.default.existsSync(moduleOutput)) {
141
+ yield fs_extra_1.default.remove(moduleOutput);
142
+ // create empty directory
143
+ yield fs_extra_1.default.ensureDir(moduleOutput);
144
+ }
145
+ const nextProcess = (0, cross_spawn_1.default)('npx', ['next', 'dev', '--turbopack', '--port', String(port)], {
146
+ cwd: appPath,
147
+ stdio: 'inherit',
148
+ env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'development' }),
149
+ });
150
+ logger_1.Logger.success(`Ready on http://${hostname}:${port}`);
151
+ nextProcess.on('error', (error) => {
152
+ logger_1.Logger.error(`Next.js dev process error: ${error}`);
153
+ process.exit(1);
154
+ });
155
+ nextProcess.on('close', (code) => {
156
+ logger_1.Logger.success(`Next.js dev process closed with code ${code}`);
157
+ process.exit(code);
158
+ });
159
+ const wss = yield (0, websocket_1.createWebSocketServer)((_d = (_c = handoff.config.app.ports) === null || _c === void 0 ? void 0 : _c.websocket) !== null && _d !== void 0 ? _d : 3001);
160
+ const chokidarConfig = {
161
+ ignored: /(^|[\/\\])\../, // ignore dotfiles
162
+ persistent: true,
163
+ ignoreInitial: true,
164
+ };
165
+ const state = {
166
+ debounce: false,
167
+ runtimeComponentsWatcher: null,
168
+ runtimeConfigurationWatcher: null,
169
+ };
170
+ (0, watchers_1.watchPublicDirectory)(handoff, wss, state, chokidarConfig);
171
+ (0, watchers_1.watchRuntimeComponents)(handoff, state, (0, watchers_1.getRuntimeComponentsPathsToWatch)(handoff));
172
+ (0, watchers_1.watchRuntimeConfiguration)(handoff, state);
173
+ (0, watchers_1.watchGlobalEntries)(handoff, state, chokidarConfig);
174
+ (0, watchers_1.watchPages)(handoff, chokidarConfig);
175
+ });
176
+ exports.watchApp = watchApp;
177
+ /**
178
+ * Watch the Next.js application using the standard Next.js dev server.
179
+ * This is useful for debugging the Next.js app itself without the Handoff overlay.
180
+ */
181
+ const devApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
182
+ var _a, _b;
183
+ // Prepare app
184
+ const appPath = yield initializeProjectApp(handoff);
185
+ // Purge app cache
186
+ const moduleOutput = path_1.default.resolve(appPath, 'out');
187
+ if (fs_extra_1.default.existsSync(moduleOutput)) {
188
+ yield fs_extra_1.default.remove(moduleOutput);
189
+ }
190
+ // Persist client configuration
191
+ yield (0, client_config_1.persistClientConfig)(handoff);
192
+ // Run
193
+ const devResult = cross_spawn_1.default.sync('npx', ['next', 'dev', '--turbopack', '--port', String((_b = (_a = handoff.config.app.ports) === null || _a === void 0 ? void 0 : _a.app) !== null && _b !== void 0 ? _b : 3000)], {
194
+ cwd: appPath,
195
+ stdio: 'inherit',
196
+ env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'development' }),
197
+ });
198
+ if (devResult.status !== 0) {
199
+ let errorMsg = `Next.js dev failed with exit code ${devResult.status}`;
200
+ if (devResult.error) {
201
+ errorMsg += `\nSpawn error: ${devResult.error.message}`;
202
+ }
203
+ throw new Error(errorMsg);
204
+ }
205
+ });
206
+ exports.devApp = devApp;
207
+ exports.default = buildApp;
@@ -0,0 +1,9 @@
1
+ import Handoff from '..';
2
+ /**
3
+ * Publishes the tokens API files to the public directory.
4
+ */
5
+ export declare const generateTokensApi: (handoff: Handoff) => Promise<void>;
6
+ /**
7
+ * Persists the client config to a JSON file.
8
+ */
9
+ export declare const persistClientConfig: (handoff: Handoff) => Promise<void>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.persistClientConfig = exports.generateTokensApi = void 0;
16
+ const fs_extra_1 = __importDefault(require("fs-extra"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const config_1 = require("../config");
19
+ const paths_1 = require("./paths");
20
+ /**
21
+ * Publishes the tokens API files to the public directory.
22
+ */
23
+ const generateTokensApi = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const apiPath = path_1.default.resolve(path_1.default.join(handoff.workingPath, 'public/api'));
25
+ yield fs_extra_1.default.ensureDir(apiPath);
26
+ const tokens = yield handoff.getDocumentationObject();
27
+ // Early return if no tokens
28
+ if (!tokens) {
29
+ // Write empty tokens.json for API consistency
30
+ yield fs_extra_1.default.writeJson(path_1.default.join(apiPath, 'tokens.json'), {}, { spaces: 2 });
31
+ return;
32
+ }
33
+ yield fs_extra_1.default.writeJson(path_1.default.join(apiPath, 'tokens.json'), tokens, { spaces: 2 });
34
+ const tokensDir = path_1.default.join(apiPath, 'tokens');
35
+ yield fs_extra_1.default.ensureDir(tokensDir);
36
+ // Only iterate if tokens has properties
37
+ if (tokens && typeof tokens === 'object') {
38
+ const promises = [];
39
+ for (const type in tokens) {
40
+ if (type === 'timestamp' || !tokens[type] || typeof tokens[type] !== 'object')
41
+ continue;
42
+ for (const group in tokens[type]) {
43
+ if (tokens[type][group]) {
44
+ promises.push(fs_extra_1.default.writeJson(path_1.default.join(tokensDir, `${group}.json`), tokens[type][group], { spaces: 2 }));
45
+ }
46
+ }
47
+ }
48
+ yield Promise.all(promises);
49
+ }
50
+ });
51
+ exports.generateTokensApi = generateTokensApi;
52
+ /**
53
+ * Persists the client config to a JSON file.
54
+ */
55
+ const persistClientConfig = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
56
+ const appPath = (0, paths_1.getAppPath)(handoff);
57
+ const destination = path_1.default.resolve(appPath, 'client.config.json');
58
+ // Ensure directory exists
59
+ yield fs_extra_1.default.ensureDir(appPath);
60
+ yield fs_extra_1.default.writeJson(destination, { config: (0, config_1.getClientConfig)(handoff.config) }, { spaces: 2 });
61
+ });
62
+ exports.persistClientConfig = persistClientConfig;
@@ -0,0 +1,2 @@
1
+ export { buildComponents } from '../pipeline/components';
2
+ export { default, devApp, watchApp } from './build';