@sarjallab09/figma-intelligence 1.0.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 (286) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +327 -0
  3. package/bin/cli.js +859 -0
  4. package/design-bridge/.env.example +5 -0
  5. package/design-bridge/bridge.js +196 -0
  6. package/design-bridge/lib/assets.js +367 -0
  7. package/design-bridge/lib/prompt.js +85 -0
  8. package/design-bridge/lib/server.js +66 -0
  9. package/design-bridge/lib/stitch.js +37 -0
  10. package/design-bridge/lib/tokens.js +82 -0
  11. package/design-bridge/package-lock.json +579 -0
  12. package/design-bridge/package.json +19 -0
  13. package/figma-bridge-plugin/README.md +97 -0
  14. package/figma-bridge-plugin/anthropic-chat-runner.js +192 -0
  15. package/figma-bridge-plugin/bridge-relay.js +2363 -0
  16. package/figma-bridge-plugin/chat-runner.js +459 -0
  17. package/figma-bridge-plugin/code.js +1528 -0
  18. package/figma-bridge-plugin/codex-runner.js +505 -0
  19. package/figma-bridge-plugin/component-schemas.js +110 -0
  20. package/figma-bridge-plugin/content-context.js +869 -0
  21. package/figma-bridge-plugin/create-button.js +216 -0
  22. package/figma-bridge-plugin/gemini-cli-runner.js +291 -0
  23. package/figma-bridge-plugin/gemini-runner.js +187 -0
  24. package/figma-bridge-plugin/html-to-figma.js +927 -0
  25. package/figma-bridge-plugin/knowledge-hub/.gitkeep +0 -0
  26. package/figma-bridge-plugin/knowledge-hub/uspec-references/anatomy-spec.md +159 -0
  27. package/figma-bridge-plugin/knowledge-hub/uspec-references/api-spec.md +162 -0
  28. package/figma-bridge-plugin/knowledge-hub/uspec-references/color-spec.md +148 -0
  29. package/figma-bridge-plugin/knowledge-hub/uspec-references/full-spec-template.md +314 -0
  30. package/figma-bridge-plugin/knowledge-hub/uspec-references/property-spec.md +175 -0
  31. package/figma-bridge-plugin/knowledge-hub/uspec-references/screen-reader-spec.md +180 -0
  32. package/figma-bridge-plugin/knowledge-hub/uspec-references/structure-spec.md +165 -0
  33. package/figma-bridge-plugin/manifest.json +21 -0
  34. package/figma-bridge-plugin/package-lock.json +1936 -0
  35. package/figma-bridge-plugin/package.json +20 -0
  36. package/figma-bridge-plugin/perplexity-runner.js +188 -0
  37. package/figma-bridge-plugin/references/SKILL.md +178 -0
  38. package/figma-bridge-plugin/references/anatomy-spec.md +159 -0
  39. package/figma-bridge-plugin/references/api-spec.md +162 -0
  40. package/figma-bridge-plugin/references/color-spec.md +148 -0
  41. package/figma-bridge-plugin/references/full-spec-template.md +314 -0
  42. package/figma-bridge-plugin/references/property-spec.md +175 -0
  43. package/figma-bridge-plugin/references/screen-reader-spec.md +180 -0
  44. package/figma-bridge-plugin/references/structure-spec.md +165 -0
  45. package/figma-bridge-plugin/shared-prompt-config.js +604 -0
  46. package/figma-bridge-plugin/spec-helpers/build-table.js +269 -0
  47. package/figma-bridge-plugin/spec-helpers/classify-elements.js +189 -0
  48. package/figma-bridge-plugin/spec-helpers/index.js +35 -0
  49. package/figma-bridge-plugin/spec-helpers/parse-figma-link.js +49 -0
  50. package/figma-bridge-plugin/spec-helpers/position-markers.js +158 -0
  51. package/figma-bridge-plugin/stitch-auth.js +322 -0
  52. package/figma-bridge-plugin/stitch-runner.js +1427 -0
  53. package/figma-bridge-plugin/token-resolver.js +107 -0
  54. package/figma-bridge-plugin/ui.html +4467 -0
  55. package/figma-intelligence-layer/.env.example +39 -0
  56. package/figma-intelligence-layer/docs/local-image-generation.md +60 -0
  57. package/figma-intelligence-layer/examples/comfyui-workflow-template.example.json +101 -0
  58. package/figma-intelligence-layer/jest.config.js +14 -0
  59. package/figma-intelligence-layer/mcp-config.json +19 -0
  60. package/figma-intelligence-layer/package-lock.json +5892 -0
  61. package/figma-intelligence-layer/package.json +48 -0
  62. package/figma-intelligence-layer/scripts/setup-comfyui-local.sh +67 -0
  63. package/figma-intelligence-layer/scripts/start-comfyui.sh +33 -0
  64. package/figma-intelligence-layer/src/index.ts +2233 -0
  65. package/figma-intelligence-layer/src/shared/auto-layout-validator.ts +404 -0
  66. package/figma-intelligence-layer/src/shared/cache.ts +187 -0
  67. package/figma-intelligence-layer/src/shared/color-operations.ts +533 -0
  68. package/figma-intelligence-layer/src/shared/color-utils.ts +138 -0
  69. package/figma-intelligence-layer/src/shared/component-script-builder.ts +413 -0
  70. package/figma-intelligence-layer/src/shared/component-templates.ts +2767 -0
  71. package/figma-intelligence-layer/src/shared/concept-taxonomy.ts +694 -0
  72. package/figma-intelligence-layer/src/shared/decision-log.ts +128 -0
  73. package/figma-intelligence-layer/src/shared/design-system-context.ts +568 -0
  74. package/figma-intelligence-layer/src/shared/design-system-intelligence.ts +131 -0
  75. package/figma-intelligence-layer/src/shared/design-system-matcher.ts +184 -0
  76. package/figma-intelligence-layer/src/shared/design-system-normalizers.ts +196 -0
  77. package/figma-intelligence-layer/src/shared/design-system-tokens.ts +295 -0
  78. package/figma-intelligence-layer/src/shared/dtcg-validator.ts +530 -0
  79. package/figma-intelligence-layer/src/shared/enrichment-pipeline.ts +671 -0
  80. package/figma-intelligence-layer/src/shared/figma-bridge.ts +1408 -0
  81. package/figma-intelligence-layer/src/shared/font-config.ts +126 -0
  82. package/figma-intelligence-layer/src/shared/icon-catalog.ts +360 -0
  83. package/figma-intelligence-layer/src/shared/icon-fetch.ts +80 -0
  84. package/figma-intelligence-layer/src/shared/prototype-script-builder.ts +162 -0
  85. package/figma-intelligence-layer/src/shared/response-compression.ts +440 -0
  86. package/figma-intelligence-layer/src/shared/semantic-token-catalog.ts +324 -0
  87. package/figma-intelligence-layer/src/shared/token-binder.ts +505 -0
  88. package/figma-intelligence-layer/src/shared/token-math.ts +427 -0
  89. package/figma-intelligence-layer/src/shared/token-naming.ts +468 -0
  90. package/figma-intelligence-layer/src/shared/token-utils.ts +420 -0
  91. package/figma-intelligence-layer/src/shared/types.ts +346 -0
  92. package/figma-intelligence-layer/src/shared/typography-presets.ts +94 -0
  93. package/figma-intelligence-layer/src/shared/unsplash.ts +165 -0
  94. package/figma-intelligence-layer/src/shared/vision-client.ts +607 -0
  95. package/figma-intelligence-layer/src/shared/vision-provider-anthropic.ts +334 -0
  96. package/figma-intelligence-layer/src/shared/vision-provider-openai.ts +446 -0
  97. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-handler.ts +782 -0
  98. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-renderer.ts +496 -0
  99. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotation-kit.ts +230 -0
  100. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/colorblind-sim.ts +66 -0
  101. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/index.ts +810 -0
  102. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-analyzer.ts +1191 -0
  103. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-figma-page.ts +1346 -0
  104. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-handler.ts +148 -0
  105. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-figma-page.ts +499 -0
  106. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-report.ts +910 -0
  107. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-checker.ts +989 -0
  108. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-criteria.ts +1160 -0
  109. package/figma-intelligence-layer/src/tools/phase1-vision/design-from-ref/index.ts +424 -0
  110. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/component-recognizer.ts +38 -0
  111. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/ds-matcher.ts +111 -0
  112. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/font-matcher.ts +114 -0
  113. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/icon-resolver.ts +103 -0
  114. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/index.ts +1060 -0
  115. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/layout-segmenter.ts +18 -0
  116. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/token-inferencer.ts +39 -0
  117. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/vision-pipeline.ts +58 -0
  118. package/figma-intelligence-layer/src/tools/phase1-vision/sketch-to-design/index.ts +298 -0
  119. package/figma-intelligence-layer/src/tools/phase1-vision/visual-audit/index.ts +197 -0
  120. package/figma-intelligence-layer/src/tools/phase2-accuracy/component-audit/index.ts +494 -0
  121. package/figma-intelligence-layer/src/tools/phase2-accuracy/intent-translator/index.ts +356 -0
  122. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/container-patterns.ts +123 -0
  123. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/index.ts +663 -0
  124. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/built-in-rules.yaml +56 -0
  125. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/index.ts +614 -0
  126. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/rule-engine.ts +113 -0
  127. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/color-theory.ts +178 -0
  128. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/index.ts +470 -0
  129. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/index.ts +429 -0
  130. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/token-override-maps.ts +226 -0
  131. package/figma-intelligence-layer/src/tools/phase3-generation/ai-image-insert/index.ts +535 -0
  132. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/index.ts +660 -0
  133. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/pattern-fingerprints.ts +209 -0
  134. package/figma-intelligence-layer/src/tools/phase3-generation/composition-builder/index.ts +540 -0
  135. package/figma-intelligence-layer/src/tools/phase3-generation/figma-animated-build.ts +391 -0
  136. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/index.ts +2019 -0
  137. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/screen-templates.ts +131 -0
  138. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-map/index.ts +381 -0
  139. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-wire/index.ts +565 -0
  140. package/figma-intelligence-layer/src/tools/phase3-generation/swarm-build/index.ts +764 -0
  141. package/figma-intelligence-layer/src/tools/phase3-generation/system-drift/index.ts +535 -0
  142. package/figma-intelligence-layer/src/tools/phase3-generation/unsplash-search/index.ts +84 -0
  143. package/figma-intelligence-layer/src/tools/phase3-generation/url-to-frame/index.ts +401 -0
  144. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/css-animations.ts +68 -0
  145. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/framer-motion.ts +78 -0
  146. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/swift-animations.ts +93 -0
  147. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/index.ts +596 -0
  148. package/figma-intelligence-layer/src/tools/phase4-sync/ci-check/index.ts +462 -0
  149. package/figma-intelligence-layer/src/tools/phase4-sync/export-tokens/index.ts +1470 -0
  150. package/figma-intelligence-layer/src/tools/phase4-sync/generate-component-code/index.ts +829 -0
  151. package/figma-intelligence-layer/src/tools/phase4-sync/handoff-spec/index.ts +702 -0
  152. package/figma-intelligence-layer/src/tools/phase4-sync/icon-library-sync/index.ts +483 -0
  153. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/index.ts +501 -0
  154. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/storybook-parser.ts +106 -0
  155. package/figma-intelligence-layer/src/tools/phase4-sync/watch-docs/index.ts +676 -0
  156. package/figma-intelligence-layer/src/tools/phase4-sync/webhook-listener/index.ts +560 -0
  157. package/figma-intelligence-layer/src/tools/phase5-governance/apg-doc/index.ts +1043 -0
  158. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/component-detection.ts +620 -0
  159. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/anatomy.ts +331 -0
  160. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/color-tokens.ts +77 -0
  161. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/properties.ts +54 -0
  162. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/snapshot.ts +287 -0
  163. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/spacing.ts +71 -0
  164. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/states.ts +43 -0
  165. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/typography.ts +71 -0
  166. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/index.ts +221 -0
  167. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/_default.ts +166 -0
  168. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/accordion.ts +232 -0
  169. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/alert.ts +234 -0
  170. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar-group.ts +270 -0
  171. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar.ts +249 -0
  172. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/badge.ts +231 -0
  173. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/banner.ts +293 -0
  174. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/breadcrumb.ts +240 -0
  175. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/button.ts +243 -0
  176. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/calendar.ts +307 -0
  177. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/card.ts +143 -0
  178. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/checkbox.ts +227 -0
  179. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/chip.ts +233 -0
  180. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/combobox.ts +282 -0
  181. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/datepicker.ts +276 -0
  182. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/divider.ts +223 -0
  183. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/drawer.ts +255 -0
  184. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/dropdown-menu.ts +289 -0
  185. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/empty-state.ts +261 -0
  186. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/file-uploader.ts +290 -0
  187. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/form.ts +265 -0
  188. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/grid.ts +238 -0
  189. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/icon.ts +255 -0
  190. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/index.ts +128 -0
  191. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-edit.ts +286 -0
  192. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-message.ts +255 -0
  193. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/input.ts +330 -0
  194. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/link.ts +247 -0
  195. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/list.ts +250 -0
  196. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/menu.ts +247 -0
  197. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/modal.ts +144 -0
  198. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navbar.ts +264 -0
  199. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navigation.ts +251 -0
  200. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/number-input.ts +261 -0
  201. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/pagination.ts +248 -0
  202. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/popover.ts +270 -0
  203. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/progress.ts +251 -0
  204. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/radio.ts +142 -0
  205. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/range-slider.ts +282 -0
  206. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/rating.ts +250 -0
  207. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/search.ts +258 -0
  208. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/segmented-control.ts +265 -0
  209. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/select.ts +319 -0
  210. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/skeleton.ts +256 -0
  211. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/slider.ts +232 -0
  212. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/spinner.ts +239 -0
  213. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/status-dot.ts +252 -0
  214. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/stepper.ts +270 -0
  215. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/table.ts +244 -0
  216. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tabs.ts +143 -0
  217. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tag.ts +243 -0
  218. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/textarea.ts +259 -0
  219. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/time-picker.ts +293 -0
  220. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toast.ts +144 -0
  221. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toggle.ts +289 -0
  222. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toolbar.ts +267 -0
  223. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tooltip.ts +232 -0
  224. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/treeview.ts +257 -0
  225. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/typography.ts +319 -0
  226. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/legacy-compat.ts +121 -0
  227. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/anatomy-diagram.ts +430 -0
  228. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/figma-page.ts +312 -0
  229. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/json.ts +129 -0
  230. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/markdown.ts +78 -0
  231. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/visual-doc.ts +2333 -0
  232. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/accessibility.ts +100 -0
  233. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/anatomy.ts +32 -0
  234. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/color-tokens.ts +59 -0
  235. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/content-guidance.ts +18 -0
  236. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/design-tokens.ts +53 -0
  237. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/interaction-rules.ts +19 -0
  238. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/overview.ts +91 -0
  239. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/properties-api.ts +71 -0
  240. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/qa-criteria.ts +19 -0
  241. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/related-components.ts +110 -0
  242. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/responsive.ts +19 -0
  243. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/size-specs.ts +67 -0
  244. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/spacing-structure.ts +58 -0
  245. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/state-specs.ts +79 -0
  246. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/states.ts +50 -0
  247. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/type-hierarchy.ts +33 -0
  248. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/typography.ts +55 -0
  249. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/usage-guidelines.ts +73 -0
  250. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/variants.ts +81 -0
  251. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/types.ts +409 -0
  252. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/index.ts +198 -0
  253. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/renderer.ts +701 -0
  254. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/types.ts +88 -0
  255. package/figma-intelligence-layer/src/tools/phase5-governance/decision-log/index.ts +135 -0
  256. package/figma-intelligence-layer/src/tools/phase5-governance/design-decision-log/index.ts +491 -0
  257. package/figma-intelligence-layer/src/tools/phase5-governance/ds-primitives/index.ts +416 -0
  258. package/figma-intelligence-layer/src/tools/phase5-governance/ds-scaffolder/index.ts +722 -0
  259. package/figma-intelligence-layer/src/tools/phase5-governance/ds-variables/index.ts +449 -0
  260. package/figma-intelligence-layer/src/tools/phase5-governance/health-report/index.ts +393 -0
  261. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/index.ts +406 -0
  262. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/figma-page.ts +292 -0
  263. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/json.ts +24 -0
  264. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/markdown.ts +172 -0
  265. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/naming-guide.ts +409 -0
  266. package/figma-intelligence-layer/src/tools/phase5-governance/token-analytics/index.ts +594 -0
  267. package/figma-intelligence-layer/src/tools/phase5-governance/token-docs/index.ts +710 -0
  268. package/figma-intelligence-layer/src/tools/phase5-governance/token-migrate/index.ts +458 -0
  269. package/figma-intelligence-layer/src/tools/phase5-governance/token-naming/index.ts +134 -0
  270. package/figma-intelligence-layer/tests/apg-doc.test.ts +101 -0
  271. package/figma-intelligence-layer/tests/design-system-context.test.ts +152 -0
  272. package/figma-intelligence-layer/tests/design-system-matcher.test.ts +144 -0
  273. package/figma-intelligence-layer/tests/figma-bridge.test.ts +83 -0
  274. package/figma-intelligence-layer/tests/generate-image-and-insert.test.ts +56 -0
  275. package/figma-intelligence-layer/tests/screen-cloner-regression.test.ts +69 -0
  276. package/figma-intelligence-layer/tests/smoke.test.ts +174 -0
  277. package/figma-intelligence-layer/tests/spec-generator.test.ts +127 -0
  278. package/figma-intelligence-layer/tests/token-migrate.test.ts +21 -0
  279. package/figma-intelligence-layer/tests/token-naming.test.ts +30 -0
  280. package/figma-intelligence-layer/tsconfig.json +19 -0
  281. package/package.json +35 -0
  282. package/scripts/clean-existing-chunks.js +179 -0
  283. package/scripts/connect-ai-tool.js +490 -0
  284. package/scripts/convert-hub-pdfs.js +425 -0
  285. package/scripts/figma-mcp-status.js +349 -0
  286. package/scripts/register-codex-mcp.js +96 -0
@@ -0,0 +1,722 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // DS Scaffolder
3
+ // Generates a complete Design System foundation in Figma from brand colors:
4
+ // color palettes, semantic tokens, typography, spacing, dark mode support,
5
+ // component stubs, and W3C DTCG token export.
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+
8
+ import { getBridge } from "../../../shared/figma-bridge.js";
9
+ import { decisionLog } from "../../../shared/decision-log.js";
10
+ import { hexToRgb, rgbToHex } from "../../../shared/token-utils.js";
11
+ import { FontConfig, resolveFontConfig, generateFontLoadScript, fontNameLiteral } from "../../../shared/font-config.js";
12
+ import { SEMANTIC_TOKEN_CATALOG, getColorSemanticTokens } from "../../../shared/semantic-token-catalog.js";
13
+ import { getBlueprintsByCategory, ComponentBlueprint } from "../../../shared/component-templates.js";
14
+ import { buildAllComponentsScript } from "../../../shared/component-script-builder.js";
15
+
16
+ // ─── Public types ─────────────────────────────────────────────────────────────
17
+
18
+ export interface DsScaffolderArgs {
19
+ brandColors: {
20
+ primary: string;
21
+ secondary?: string;
22
+ neutral?: string;
23
+ accent?: string;
24
+ };
25
+ productType: "web-app" | "mobile-app" | "both" | "marketing";
26
+ brandName: string;
27
+ includeComponents: Array<"core" | "forms" | "navigation" | "data" | "feedback" | "overlay">;
28
+ generateDarkMode: boolean;
29
+ dtcgExport: boolean;
30
+ fonts?: Partial<FontConfig>;
31
+ }
32
+
33
+ export interface ColorShade {
34
+ step: number;
35
+ hex: string;
36
+ lightHex?: string;
37
+ darkHex?: string;
38
+ }
39
+
40
+ export interface ColorPalette {
41
+ name: string;
42
+ base: string;
43
+ shades: ColorShade[];
44
+ }
45
+
46
+ export interface TokenDefinition {
47
+ name: string;
48
+ value: string | number;
49
+ type: "COLOR" | "FLOAT" | "STRING";
50
+ description?: string;
51
+ darkValue?: string | number;
52
+ }
53
+
54
+ export interface DsScaffolderResult {
55
+ pageIds: {
56
+ foundations?: string;
57
+ components?: string;
58
+ templates?: string;
59
+ };
60
+ tokenCounts: {
61
+ colors: number;
62
+ typography: number;
63
+ spacing: number;
64
+ semantic: number;
65
+ total: number;
66
+ };
67
+ palettes: ColorPalette[];
68
+ dtcgTokens?: Record<string, unknown>;
69
+ }
70
+
71
+ // ─── Color palette generation ─────────────────────────────────────────────────
72
+
73
+ // Shade steps and their target lightness (0–1 in HSL)
74
+ const SHADE_STEPS: Array<{ step: number; lightness: number }> = [
75
+ { step: 50, lightness: 0.97 },
76
+ { step: 100, lightness: 0.94 },
77
+ { step: 200, lightness: 0.86 },
78
+ { step: 300, lightness: 0.74 },
79
+ { step: 400, lightness: 0.62 },
80
+ { step: 500, lightness: 0.50 },
81
+ { step: 600, lightness: 0.40 },
82
+ { step: 700, lightness: 0.30 },
83
+ { step: 800, lightness: 0.22 },
84
+ { step: 900, lightness: 0.14 },
85
+ { step: 950, lightness: 0.08 },
86
+ ];
87
+
88
+ function rgbToHsl(r: number, g: number, b: number): { h: number; s: number; l: number } {
89
+ const rn = r / 255, gn = g / 255, bn = b / 255;
90
+ const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn);
91
+ const l = (max + min) / 2;
92
+ if (max === min) return { h: 0, s: 0, l };
93
+ const d = max - min;
94
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
95
+ let h = 0;
96
+ switch (max) {
97
+ case rn: h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6; break;
98
+ case gn: h = ((bn - rn) / d + 2) / 6; break;
99
+ case bn: h = ((rn - gn) / d + 4) / 6; break;
100
+ }
101
+ return { h: h * 360, s, l };
102
+ }
103
+
104
+ function hslToHex(h: number, s: number, l: number): string {
105
+ let r: number, g: number, b: number;
106
+ if (s === 0) {
107
+ r = g = b = l;
108
+ } else {
109
+ const hue2rgb = (p: number, q: number, t: number) => {
110
+ if (t < 0) t += 1;
111
+ if (t > 1) t -= 1;
112
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
113
+ if (t < 1 / 2) return q;
114
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
115
+ return p;
116
+ };
117
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
118
+ const p = 2 * l - q;
119
+ r = hue2rgb(p, q, h / 360 + 1 / 3);
120
+ g = hue2rgb(p, q, h / 360);
121
+ b = hue2rgb(p, q, h / 360 - 1 / 3);
122
+ }
123
+ return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
124
+ }
125
+
126
+ function generatePalette(name: string, baseHex: string): ColorPalette {
127
+ const rgb = hexToRgb(baseHex);
128
+ if (!rgb) {
129
+ return {
130
+ name,
131
+ base: baseHex,
132
+ shades: SHADE_STEPS.map((s) => ({ step: s.step, hex: baseHex })),
133
+ };
134
+ }
135
+
136
+ const { h, s } = rgbToHsl(rgb.r, rgb.g, rgb.b);
137
+
138
+ const shades: ColorShade[] = SHADE_STEPS.map(({ step, lightness }) => {
139
+ // Adjust saturation: midtones keep full saturation, extremes reduce slightly
140
+ const adjustedS = lightness < 0.15 || lightness > 0.92 ? s * 0.7 : s;
141
+ const hex = hslToHex(h, adjustedS, lightness);
142
+ return { step, hex };
143
+ });
144
+
145
+ return { name, base: baseHex, shades };
146
+ }
147
+
148
+ function generateStatusPalettes(): ColorPalette[] {
149
+ return [
150
+ generatePalette("success", "#16a34a"),
151
+ generatePalette("warning", "#d97706"),
152
+ generatePalette("danger", "#dc2626"),
153
+ generatePalette("info", "#2563eb"),
154
+ ];
155
+ }
156
+
157
+ // ─── Token builders ───────────────────────────────────────────────────────────
158
+
159
+ function getShadeHex(palette: ColorPalette, step: number): string {
160
+ return palette.shades.find((s) => s.step === step)?.hex ?? palette.base;
161
+ }
162
+
163
+ function buildColorTokens(
164
+ palettes: ColorPalette[],
165
+ generateDarkMode: boolean
166
+ ): TokenDefinition[] {
167
+ const tokens: TokenDefinition[] = [];
168
+
169
+ // Raw palette tokens
170
+ for (const palette of palettes) {
171
+ for (const shade of palette.shades) {
172
+ const darkHex = generateDarkMode
173
+ ? getShadeHex(palette, 950 - shade.step === 950 ? 50 : Math.min(950, Math.max(50, 950 - shade.step)))
174
+ : undefined;
175
+ tokens.push({
176
+ name: `color/${palette.name}/${shade.step}`,
177
+ value: shade.hex,
178
+ type: "COLOR",
179
+ darkValue: darkHex,
180
+ });
181
+ }
182
+ }
183
+
184
+ return tokens;
185
+ }
186
+
187
+ function buildSemanticTokens(
188
+ palettes: ColorPalette[],
189
+ generateDarkMode: boolean
190
+ ): TokenDefinition[] {
191
+ const tokens: TokenDefinition[] = [];
192
+
193
+ // Helper: resolve a primitive ref like "color/primitive/brand/500" to a hex
194
+ // by looking up the palette name and shade step
195
+ const resolveRef = (ref: string): string => {
196
+ // Parse: "color/primitive/{paletteName}/{step}"
197
+ const parts = ref.split("/");
198
+ const paletteName = parts[2] ?? "neutral"; // brand, secondary, neutral, etc.
199
+ const step = parseInt(parts[3] ?? "500", 10);
200
+
201
+ // Map palette names: "brand" → primary palette (first), others by name
202
+ let palette: ColorPalette | undefined;
203
+ if (paletteName === "brand") {
204
+ palette = palettes[0]; // primary is always first
205
+ } else {
206
+ palette = palettes.find((p) => p.name.toLowerCase() === paletteName.toLowerCase());
207
+ }
208
+ if (!palette) palette = palettes.find((p) => p.name === "neutral") ?? palettes[0];
209
+
210
+ return getShadeHex(palette, step);
211
+ };
212
+
213
+ // Use the semantic token catalog for COLOR tokens
214
+ const colorEntries = getColorSemanticTokens();
215
+ for (const entry of colorEntries) {
216
+ const lightHex = resolveRef(entry.lightRef);
217
+ const darkHex = generateDarkMode ? resolveRef(entry.darkRef) : undefined;
218
+ tokens.push({
219
+ name: entry.name,
220
+ value: lightHex,
221
+ type: "COLOR",
222
+ description: entry.description,
223
+ darkValue: darkHex,
224
+ });
225
+ }
226
+
227
+ // Legacy compat: also emit the old semantic names so existing bindings don't break
228
+ const primaryPalette = palettes[0];
229
+ const neutralPalette = palettes.find((p) => p.name === "neutral") ?? palettes[1];
230
+
231
+ const legacyEntries: Array<{
232
+ name: string;
233
+ lightStep: number;
234
+ darkStep?: number;
235
+ palette: ColorPalette;
236
+ description: string;
237
+ }> = [
238
+ { name: "color/semantic/primary", lightStep: 500, darkStep: 400, palette: primaryPalette, description: "Primary brand color" },
239
+ { name: "color/semantic/primary-hover", lightStep: 600, darkStep: 300, palette: primaryPalette, description: "Primary hover state" },
240
+ { name: "color/semantic/primary-subtle", lightStep: 100, darkStep: 900, palette: primaryPalette, description: "Subtle primary tint" },
241
+ { name: "color/semantic/primary-on", lightStep: 50, darkStep: 950, palette: primaryPalette, description: "Text on primary background" },
242
+
243
+ { name: "color/surface/default", lightStep: 50, darkStep: 950, palette: neutralPalette, description: "Default surface background" },
244
+ { name: "color/surface/raised", lightStep: 50, darkStep: 900, palette: neutralPalette, description: "Raised/card surface" },
245
+ { name: "color/surface/overlay", lightStep: 100, darkStep: 800, palette: neutralPalette, description: "Overlay surface" },
246
+
247
+ { name: "color/border/default", lightStep: 200, darkStep: 700, palette: neutralPalette, description: "Default border color" },
248
+ { name: "color/border/strong", lightStep: 400, darkStep: 500, palette: neutralPalette, description: "Strong/emphasis border" },
249
+
250
+ { name: "color/text/primary", lightStep: 900, darkStep: 50, palette: neutralPalette, description: "Primary text color" },
251
+ { name: "color/text/secondary", lightStep: 600, darkStep: 300, palette: neutralPalette, description: "Secondary text color" },
252
+ { name: "color/text/disabled", lightStep: 400, darkStep: 600, palette: neutralPalette, description: "Disabled text color" },
253
+ { name: "color/text/on-primary", lightStep: 50, darkStep: 950, palette: primaryPalette, description: "Text on primary background" },
254
+ ];
255
+
256
+ for (const entry of legacyEntries) {
257
+ // Skip if already added by catalog (avoid duplicates)
258
+ if (tokens.some((t) => t.name === entry.name)) continue;
259
+
260
+ const lightHex = getShadeHex(entry.palette, entry.lightStep);
261
+ const darkHex = generateDarkMode && entry.darkStep !== undefined
262
+ ? getShadeHex(entry.palette, entry.darkStep)
263
+ : undefined;
264
+
265
+ tokens.push({
266
+ name: entry.name,
267
+ value: lightHex,
268
+ type: "COLOR",
269
+ description: entry.description,
270
+ darkValue: darkHex,
271
+ });
272
+ }
273
+
274
+ return tokens;
275
+ }
276
+
277
+ function buildTypographyTokens(): TokenDefinition[] {
278
+ const sizes: Array<[string, number]> = [
279
+ ["xs", 12], ["sm", 14], ["base", 16], ["lg", 18], ["xl", 20],
280
+ ["2xl", 24], ["3xl", 30], ["4xl", 36], ["5xl", 48],
281
+ ];
282
+
283
+ const lineHeights: Array<[string, number]> = [
284
+ ["xs", 16], ["sm", 20], ["base", 24], ["lg", 28], ["xl", 28],
285
+ ["2xl", 32], ["3xl", 36], ["4xl", 40], ["5xl", 52],
286
+ ];
287
+
288
+ const weights: Array<[string, number]> = [
289
+ ["light", 300], ["regular", 400], ["medium", 500], ["semibold", 600], ["bold", 700],
290
+ ];
291
+
292
+ const tokens: TokenDefinition[] = [];
293
+
294
+ for (const [name, value] of sizes) {
295
+ tokens.push({ name: `typography/size/${name}`, value, type: "FLOAT", description: `Font size ${name}` });
296
+ }
297
+ for (const [name, value] of lineHeights) {
298
+ tokens.push({ name: `typography/line-height/${name}`, value, type: "FLOAT", description: `Line height ${name}` });
299
+ }
300
+ for (const [name, value] of weights) {
301
+ tokens.push({ name: `typography/weight/${name}`, value, type: "FLOAT", description: `Font weight ${name}` });
302
+ }
303
+
304
+ // Letter spacing
305
+ tokens.push({ name: "typography/tracking/tight", value: -0.025, type: "FLOAT" });
306
+ tokens.push({ name: "typography/tracking/normal", value: 0, type: "FLOAT" });
307
+ tokens.push({ name: "typography/tracking/wide", value: 0.025, type: "FLOAT" });
308
+ tokens.push({ name: "typography/tracking/wider", value: 0.05, type: "FLOAT" });
309
+
310
+ return tokens;
311
+ }
312
+
313
+ function buildSpacingTokens(): TokenDefinition[] {
314
+ const spacingScale: Array<[string, number]> = [
315
+ ["0", 0], ["px", 1], ["0.5", 2], ["1", 4], ["1.5", 6],
316
+ ["2", 8], ["2.5", 10], ["3", 12], ["4", 16], ["5", 20],
317
+ ["6", 24], ["7", 28], ["8", 32], ["9", 36], ["10", 40],
318
+ ["11", 44], ["12", 48], ["14", 56], ["16", 64], ["20", 80],
319
+ ["24", 96], ["28", 112], ["32", 128],
320
+ ];
321
+
322
+ return spacingScale.map(([name, value]) => ({
323
+ name: `spacing/${name}`,
324
+ value,
325
+ type: "FLOAT" as const,
326
+ description: `Spacing ${name} = ${value}px`,
327
+ }));
328
+ }
329
+
330
+ function buildRadiusTokens(): TokenDefinition[] {
331
+ const radii: Array<[string, number]> = [
332
+ ["none", 0], ["sm", 2], ["base", 4], ["md", 6], ["lg", 8],
333
+ ["xl", 12], ["2xl", 16], ["3xl", 24], ["full", 9999],
334
+ ];
335
+ return radii.map(([name, value]) => ({
336
+ name: `radius/${name}`,
337
+ value,
338
+ type: "FLOAT" as const,
339
+ description: `Border radius ${name}`,
340
+ }));
341
+ }
342
+
343
+ // ─── DTCG export ──────────────────────────────────────────────────────────────
344
+
345
+ function tokenToDtcg(token: TokenDefinition): Record<string, unknown> {
346
+ const dtcgType = token.type === "COLOR" ? "color"
347
+ : token.type === "FLOAT" ? "dimension"
348
+ : "string";
349
+
350
+ return {
351
+ $value: token.type === "FLOAT" ? `${token.value}px` : token.value,
352
+ $type: dtcgType,
353
+ ...(token.description ? { $description: token.description } : {}),
354
+ };
355
+ }
356
+
357
+ function buildDtcgExport(tokens: TokenDefinition[]): Record<string, unknown> {
358
+ const root: Record<string, unknown> = {};
359
+
360
+ for (const token of tokens) {
361
+ const parts = token.name.split("/");
362
+ let current = root;
363
+
364
+ for (let i = 0; i < parts.length - 1; i++) {
365
+ const part = parts[i];
366
+ if (!(part in current)) current[part] = {};
367
+ current = current[part] as Record<string, unknown>;
368
+ }
369
+
370
+ const leafKey = parts[parts.length - 1];
371
+ current[leafKey] = tokenToDtcg(token);
372
+ }
373
+
374
+ return root;
375
+ }
376
+
377
+ // ─── Figma script builders (split into small chunks to avoid timeouts) ─────
378
+
379
+ function buildCreatePageAndTokensScript(
380
+ brandName: string,
381
+ allTokens: TokenDefinition[],
382
+ generateDarkMode: boolean
383
+ ): string {
384
+ return `
385
+ (async () => {
386
+ const foundationsPage = figma.createPage();
387
+ foundationsPage.name = ${JSON.stringify(`${brandName} – Foundations`)};
388
+ figma.currentPage = foundationsPage;
389
+
390
+ const collection = figma.variables.createVariableCollection(${JSON.stringify(`${brandName} Tokens`)});
391
+ const lightModeId = collection.defaultModeId;
392
+ collection.renameMode(lightModeId, 'Light');
393
+ ${generateDarkMode ? "const darkModeId = collection.addMode('Dark');" : ""}
394
+
395
+ var created = 0;
396
+ var allTokens = ${JSON.stringify(allTokens)};
397
+ for (var i = 0; i < allTokens.length; i++) {
398
+ var token = allTokens[i];
399
+ var resolvedType = token.type === 'COLOR' ? 'COLOR' : token.type === 'FLOAT' ? 'FLOAT' : 'STRING';
400
+ var variable;
401
+ try {
402
+ variable = figma.variables.createVariable(token.name, collection, resolvedType);
403
+ } catch (e) { continue; }
404
+ if (token.description) variable.description = token.description;
405
+ var lightVal = token.value;
406
+ if (resolvedType === 'COLOR') {
407
+ var hex = String(token.value).replace('#', '');
408
+ lightVal = { r: parseInt(hex.slice(0, 2), 16) / 255, g: parseInt(hex.slice(2, 4), 16) / 255, b: parseInt(hex.slice(4, 6), 16) / 255, a: 1 };
409
+ }
410
+ variable.setValueForMode(lightModeId, lightVal);
411
+ ${generateDarkMode ? `
412
+ if (token.darkValue !== undefined) {
413
+ var darkVal = token.darkValue;
414
+ if (resolvedType === 'COLOR') {
415
+ var dhex = String(token.darkValue).replace('#', '');
416
+ darkVal = { r: parseInt(dhex.slice(0, 2), 16) / 255, g: parseInt(dhex.slice(2, 4), 16) / 255, b: parseInt(dhex.slice(4, 6), 16) / 255, a: 1 };
417
+ }
418
+ variable.setValueForMode(darkModeId, darkVal);
419
+ } else { variable.setValueForMode(darkModeId, lightVal); }
420
+ ` : ""}
421
+ created++;
422
+ }
423
+
424
+ return { pageId: foundationsPage.id, collectionId: collection.id, tokenCount: created };
425
+ })();
426
+ `.trim();
427
+ }
428
+
429
+ function buildSwatchesScript(allTokens: TokenDefinition[]): string {
430
+ return `
431
+ (async () => {
432
+ var swatchFrame = figma.createFrame();
433
+ swatchFrame.name = "Color Swatches";
434
+ swatchFrame.layoutMode = "VERTICAL";
435
+ swatchFrame.primaryAxisSizingMode = "AUTO";
436
+ swatchFrame.counterAxisSizingMode = "AUTO";
437
+ swatchFrame.itemSpacing = 16;
438
+ swatchFrame.paddingLeft = swatchFrame.paddingRight = 24;
439
+ swatchFrame.paddingTop = swatchFrame.paddingBottom = 24;
440
+ swatchFrame.x = 0; swatchFrame.y = 0;
441
+ figma.currentPage.appendChild(swatchFrame);
442
+
443
+ var allTokens = ${JSON.stringify(allTokens)};
444
+ var colorTokensOnly = allTokens.filter(function(t) { return t.type === 'COLOR' && !t.name.startsWith('color/semantic'); });
445
+ var groups = {};
446
+ for (var i = 0; i < colorTokensOnly.length; i++) {
447
+ var parts = colorTokensOnly[i].name.split('/');
448
+ var pName = parts[1] || 'unknown';
449
+ if (!groups[pName]) groups[pName] = [];
450
+ groups[pName].push(colorTokensOnly[i]);
451
+ }
452
+ var keys = Object.keys(groups);
453
+ for (var k = 0; k < keys.length; k++) {
454
+ var row = figma.createFrame();
455
+ row.name = keys[k];
456
+ row.layoutMode = "HORIZONTAL";
457
+ row.primaryAxisSizingMode = "AUTO";
458
+ row.counterAxisSizingMode = "AUTO";
459
+ row.itemSpacing = 4;
460
+ swatchFrame.appendChild(row);
461
+ var tokens = groups[keys[k]];
462
+ for (var j = 0; j < tokens.length; j++) {
463
+ var swatch = figma.createRectangle();
464
+ swatch.resize(48, 48);
465
+ swatch.name = tokens[j].name.split('/').pop() || tokens[j].name;
466
+ var hex = String(tokens[j].value).replace('#', '');
467
+ swatch.fills = [{ type: 'SOLID', color: { r: parseInt(hex.slice(0, 2), 16) / 255, g: parseInt(hex.slice(2, 4), 16) / 255, b: parseInt(hex.slice(4, 6), 16) / 255 } }];
468
+ row.appendChild(swatch);
469
+ }
470
+ }
471
+ return { swatches: keys.length };
472
+ })();
473
+ `.trim();
474
+ }
475
+
476
+ function buildTypeAndSpacingScript(fontConfig: FontConfig): string {
477
+ const fontLoads = generateFontLoadScript(fontConfig);
478
+ const bodyFont = fontNameLiteral("body", "Regular", fontConfig);
479
+
480
+ return `
481
+ (async () => {
482
+ ${fontLoads}
483
+
484
+ var typeFrame = figma.createFrame();
485
+ typeFrame.name = "Type Scale";
486
+ typeFrame.layoutMode = "VERTICAL";
487
+ typeFrame.primaryAxisSizingMode = "AUTO";
488
+ typeFrame.counterAxisSizingMode = "AUTO";
489
+ typeFrame.itemSpacing = 12;
490
+ typeFrame.paddingLeft = typeFrame.paddingRight = 24;
491
+ typeFrame.paddingTop = typeFrame.paddingBottom = 24;
492
+ typeFrame.x = 700; typeFrame.y = 0;
493
+ figma.currentPage.appendChild(typeFrame);
494
+
495
+ var typeSizes = [['xs', 12], ['sm', 14], ['base', 16], ['lg', 18], ['xl', 20], ['2xl', 24], ['3xl', 30], ['4xl', 36], ['5xl', 48]];
496
+ for (var i = 0; i < typeSizes.length; i++) {
497
+ var textNode = figma.createText();
498
+ textNode.fontName = ${bodyFont};
499
+ textNode.fontSize = typeSizes[i][1];
500
+ textNode.characters = typeSizes[i][0] + ' — The quick brown fox';
501
+ typeFrame.appendChild(textNode);
502
+ }
503
+
504
+ var spacingFrame = figma.createFrame();
505
+ spacingFrame.name = "Spacing Scale";
506
+ spacingFrame.layoutMode = "HORIZONTAL";
507
+ spacingFrame.primaryAxisSizingMode = "AUTO";
508
+ spacingFrame.counterAxisSizingMode = "AUTO";
509
+ spacingFrame.itemSpacing = 8;
510
+ spacingFrame.paddingLeft = spacingFrame.paddingRight = 24;
511
+ spacingFrame.paddingTop = spacingFrame.paddingBottom = 24;
512
+ spacingFrame.x = 0; spacingFrame.y = 700;
513
+ figma.currentPage.appendChild(spacingFrame);
514
+
515
+ var spacingScaleDisplay = [4, 8, 12, 16, 24, 32, 40, 48, 64, 80];
516
+ for (var j = 0; j < spacingScaleDisplay.length; j++) {
517
+ var bar = figma.createRectangle();
518
+ bar.resize(spacingScaleDisplay[j], spacingScaleDisplay[j]);
519
+ bar.name = spacingScaleDisplay[j] + 'px';
520
+ bar.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.4, b: 1 } }];
521
+ spacingFrame.appendChild(bar);
522
+ }
523
+
524
+ return { ok: true };
525
+ })();
526
+ `.trim();
527
+ }
528
+
529
+ /**
530
+ * Build the components page script using blueprint-driven generation.
531
+ * Creates all 51 professional component stubs with auto-layout, typography
532
+ * presets, and token bindings.
533
+ */
534
+ function buildComponentsScriptFromBlueprints(
535
+ brandName: string,
536
+ includeComponents: DsScaffolderArgs["includeComponents"],
537
+ fontConfig: FontConfig,
538
+ collectionId?: string
539
+ ): string {
540
+ const blueprints = getBlueprintsByCategory(includeComponents);
541
+ return buildAllComponentsScript(blueprints, brandName, fontConfig, collectionId);
542
+ }
543
+
544
+ function buildTemplatesScript(brandName: string, fontConfig: FontConfig): string {
545
+ const fontLoads = generateFontLoadScript(fontConfig);
546
+
547
+ return `
548
+ (async () => {
549
+ ${fontLoads}
550
+
551
+ const page = figma.createPage();
552
+ page.name = ${JSON.stringify(`${brandName} – Templates`)};
553
+ figma.currentPage = page;
554
+
555
+ // ── Login template ───────────────────────────────────────────────────────
556
+ const loginFrame = figma.createFrame();
557
+ loginFrame.name = 'Login Screen';
558
+ loginFrame.resize(1440, 900);
559
+ loginFrame.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.98 } }];
560
+ loginFrame.x = 0; loginFrame.y = 0;
561
+ page.appendChild(loginFrame);
562
+
563
+ const loginCard = figma.createFrame();
564
+ loginCard.name = 'Login Card';
565
+ loginCard.resize(400, 480);
566
+ loginCard.layoutMode = 'VERTICAL';
567
+ loginCard.primaryAxisAlignItems = 'MIN';
568
+ loginCard.paddingLeft = loginCard.paddingRight = 32;
569
+ loginCard.paddingTop = loginCard.paddingBottom = 32;
570
+ loginCard.itemSpacing = 20;
571
+ loginCard.cornerRadius = 12;
572
+ loginCard.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
573
+ loginCard.x = 520; loginCard.y = 210;
574
+ loginFrame.appendChild(loginCard);
575
+
576
+ // ── Dashboard template ────────────────────────────────────────────────────
577
+ const dashFrame = figma.createFrame();
578
+ dashFrame.name = 'Dashboard';
579
+ dashFrame.resize(1440, 900);
580
+ dashFrame.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.98 } }];
581
+ dashFrame.x = 1500; dashFrame.y = 0;
582
+ page.appendChild(dashFrame);
583
+
584
+ const sidebar = figma.createFrame();
585
+ sidebar.name = 'Sidebar';
586
+ sidebar.resize(240, 900);
587
+ sidebar.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }];
588
+ dashFrame.appendChild(sidebar);
589
+
590
+ const content = figma.createFrame();
591
+ content.name = 'Content';
592
+ content.resize(1200, 900);
593
+ content.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.98 } }];
594
+ content.x = 240;
595
+ dashFrame.appendChild(content);
596
+
597
+ // ── Settings template ─────────────────────────────────────────────────────
598
+ const settingsFrame = figma.createFrame();
599
+ settingsFrame.name = 'Settings';
600
+ settingsFrame.resize(1440, 900);
601
+ settingsFrame.fills = [{ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.98 } }];
602
+ settingsFrame.x = 3000; settingsFrame.y = 0;
603
+ page.appendChild(settingsFrame);
604
+
605
+ return {
606
+ pageId: page.id,
607
+ templateIds: [loginFrame.id, dashFrame.id, settingsFrame.id],
608
+ };
609
+ })();
610
+ `.trim();
611
+ }
612
+
613
+ // ─── Main handler ─────────────────────────────────────────────────────────────
614
+
615
+ export async function dsScaffolderHandler(
616
+ args: DsScaffolderArgs
617
+ ): Promise<DsScaffolderResult> {
618
+ const { brandColors, brandName, includeComponents, generateDarkMode, dtcgExport } = args;
619
+ const fontConfig = resolveFontConfig(args.fonts);
620
+
621
+ const bridge = await getBridge();
622
+
623
+ // 1. Generate color palettes
624
+ const primaryPalette = generatePalette("primary", brandColors.primary);
625
+
626
+ const neutralBase = brandColors.neutral ?? "#6b7280";
627
+ const neutralPalette = generatePalette("neutral", neutralBase);
628
+
629
+ const palettes: ColorPalette[] = [primaryPalette, neutralPalette];
630
+
631
+ if (brandColors.secondary) {
632
+ palettes.push(generatePalette("secondary", brandColors.secondary));
633
+ }
634
+ if (brandColors.accent) {
635
+ palettes.push(generatePalette("accent", brandColors.accent));
636
+ }
637
+
638
+ palettes.push(...generateStatusPalettes());
639
+
640
+ // 2. Build all token sets
641
+ const colorTokens = buildColorTokens(palettes, generateDarkMode);
642
+ const semanticTokens = buildSemanticTokens(palettes, generateDarkMode);
643
+ const typographyTokens = buildTypographyTokens();
644
+ const spacingTokens = buildSpacingTokens();
645
+ const radiusTokens = buildRadiusTokens();
646
+
647
+ // 3. Create Foundations page + tokens (split into 3 smaller calls)
648
+ const allTokens = [...colorTokens, ...semanticTokens, ...typographyTokens, ...spacingTokens, ...radiusTokens];
649
+
650
+ const pageAndTokensScript = buildCreatePageAndTokensScript(brandName, allTokens, generateDarkMode);
651
+ const pageResult = await bridge.execute(pageAndTokensScript);
652
+ const pageResultData = pageResult.success
653
+ ? (pageResult.result as Record<string, unknown>)
654
+ : undefined;
655
+ const foundationsPageId = pageResultData
656
+ ? String(pageResultData["pageId"] ?? "")
657
+ : undefined;
658
+ const collectionId = pageResultData
659
+ ? String(pageResultData["collectionId"] ?? "")
660
+ : undefined;
661
+
662
+ // 3b. Build color swatches (on the same page — already set as currentPage)
663
+ if (foundationsPageId) {
664
+ await bridge.execute(buildSwatchesScript(allTokens));
665
+ }
666
+
667
+ // 3c. Build type scale + spacing frames
668
+ if (foundationsPageId) {
669
+ await bridge.execute(buildTypeAndSpacingScript(fontConfig));
670
+ }
671
+
672
+ // 4. Create Components page (pass collectionId so stubs get variable bindings)
673
+ const componentsScript = buildComponentsScriptFromBlueprints(brandName, includeComponents, fontConfig, collectionId);
674
+ const componentsResult = await bridge.execute(componentsScript);
675
+ const componentsPageId = componentsResult.success
676
+ ? String((componentsResult.result as Record<string, unknown>)["pageId"] ?? "")
677
+ : undefined;
678
+
679
+ // 5. Create Templates page
680
+ const templatesScript = buildTemplatesScript(brandName, fontConfig);
681
+ const templatesResult = await bridge.execute(templatesScript);
682
+ const templatesPageId = templatesResult.success
683
+ ? String((templatesResult.result as Record<string, unknown>)["pageId"] ?? "")
684
+ : undefined;
685
+
686
+ // 6. DTCG export if requested
687
+ const dtcgTokens = dtcgExport ? buildDtcgExport(allTokens) : undefined;
688
+
689
+ // 7. Log the action
690
+ await decisionLog.log({
691
+ tool: "ds-scaffolder",
692
+ nodeIds: [foundationsPageId, componentsPageId, templatesPageId].filter(Boolean) as string[],
693
+ rationale: `Scaffolded design system "${brandName}" with ${allTokens.length} tokens (${colorTokens.length + semanticTokens.length} color, ${typographyTokens.length} typography, ${spacingTokens.length} spacing). Components: ${includeComponents.join(", ")}. Dark mode: ${generateDarkMode}. DTCG: ${dtcgExport}.`,
694
+ tokens: allTokens.slice(0, 20).map((t) => t.name),
695
+ reversible: false,
696
+ metadata: {
697
+ brandName,
698
+ productType: args.productType,
699
+ generateDarkMode,
700
+ dtcgExport,
701
+ includeComponents,
702
+ totalTokens: allTokens.length,
703
+ },
704
+ });
705
+
706
+ return {
707
+ pageIds: {
708
+ foundations: foundationsPageId,
709
+ components: componentsPageId,
710
+ templates: templatesPageId,
711
+ },
712
+ tokenCounts: {
713
+ colors: colorTokens.length + semanticTokens.length,
714
+ typography: typographyTokens.length,
715
+ spacing: spacingTokens.length + radiusTokens.length,
716
+ semantic: semanticTokens.length,
717
+ total: allTokens.length,
718
+ },
719
+ palettes,
720
+ dtcgTokens,
721
+ };
722
+ }