@sarjallab09/figma-intelligence 1.1.0 → 1.2.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.
- package/README.md +67 -36
- package/dist/bin/cli.js +2 -0
- package/dist/design-bridge/bridge.js +2 -0
- package/dist/figma-bridge-plugin/bridge-relay.js +2 -0
- package/dist/figma-bridge-plugin/code.js +1 -0
- package/{figma-bridge-plugin → dist/figma-bridge-plugin}/package-lock.json +0 -3
- package/dist/figma-bridge-plugin/ui.html +4970 -0
- package/dist/figma-intelligence-layer/dist/index.js +2 -0
- package/dist/scripts/clean-existing-chunks.js +2 -0
- package/dist/scripts/connect-ai-tool.js +2 -0
- package/dist/scripts/convert-hub-pdfs.js +2 -0
- package/dist/scripts/figma-mcp-status.js +2 -0
- package/dist/scripts/register-codex-mcp.js +2 -0
- package/dist/scripts/test-copilot-chat.js +2 -0
- package/package.json +11 -8
- package/bin/cli.js +0 -859
- package/design-bridge/bridge.js +0 -196
- package/design-bridge/lib/assets.js +0 -367
- package/design-bridge/lib/prompt.js +0 -85
- package/design-bridge/lib/server.js +0 -66
- package/design-bridge/lib/stitch.js +0 -37
- package/design-bridge/lib/tokens.js +0 -82
- package/design-bridge/package-lock.json +0 -579
- package/figma-bridge-plugin/README.md +0 -97
- package/figma-bridge-plugin/anthropic-chat-runner.js +0 -192
- package/figma-bridge-plugin/bridge-relay.js +0 -2505
- package/figma-bridge-plugin/chat-runner.js +0 -485
- package/figma-bridge-plugin/code.js +0 -1534
- package/figma-bridge-plugin/codex-runner.js +0 -505
- package/figma-bridge-plugin/component-schemas.js +0 -110
- package/figma-bridge-plugin/content-context.js +0 -869
- package/figma-bridge-plugin/create-button.js +0 -216
- package/figma-bridge-plugin/gemini-cli-runner.js +0 -291
- package/figma-bridge-plugin/gemini-runner.js +0 -187
- package/figma-bridge-plugin/html-to-figma.js +0 -927
- package/figma-bridge-plugin/knowledge-hub/.gitkeep +0 -0
- package/figma-bridge-plugin/knowledge-hub/uspec-references/anatomy-spec.md +0 -159
- package/figma-bridge-plugin/knowledge-hub/uspec-references/api-spec.md +0 -162
- package/figma-bridge-plugin/knowledge-hub/uspec-references/color-spec.md +0 -148
- package/figma-bridge-plugin/knowledge-hub/uspec-references/full-spec-template.md +0 -314
- package/figma-bridge-plugin/knowledge-hub/uspec-references/property-spec.md +0 -175
- package/figma-bridge-plugin/knowledge-hub/uspec-references/screen-reader-spec.md +0 -180
- package/figma-bridge-plugin/knowledge-hub/uspec-references/structure-spec.md +0 -165
- package/figma-bridge-plugin/perplexity-runner.js +0 -188
- package/figma-bridge-plugin/references/SKILL.md +0 -178
- package/figma-bridge-plugin/references/anatomy-spec.md +0 -159
- package/figma-bridge-plugin/references/api-spec.md +0 -162
- package/figma-bridge-plugin/references/color-spec.md +0 -148
- package/figma-bridge-plugin/references/full-spec-template.md +0 -314
- package/figma-bridge-plugin/references/property-spec.md +0 -175
- package/figma-bridge-plugin/references/screen-reader-spec.md +0 -180
- package/figma-bridge-plugin/references/structure-spec.md +0 -165
- package/figma-bridge-plugin/shared-prompt-config.js +0 -645
- package/figma-bridge-plugin/spec-helpers/build-table.js +0 -269
- package/figma-bridge-plugin/spec-helpers/classify-elements.js +0 -189
- package/figma-bridge-plugin/spec-helpers/index.js +0 -35
- package/figma-bridge-plugin/spec-helpers/parse-figma-link.js +0 -49
- package/figma-bridge-plugin/spec-helpers/position-markers.js +0 -158
- package/figma-bridge-plugin/stitch-auth.js +0 -322
- package/figma-bridge-plugin/stitch-runner.js +0 -1427
- package/figma-bridge-plugin/token-resolver.js +0 -107
- package/figma-bridge-plugin/ui.html +0 -4542
- package/figma-intelligence-layer/.env.example +0 -39
- package/figma-intelligence-layer/docs/local-image-generation.md +0 -60
- package/figma-intelligence-layer/examples/comfyui-workflow-template.example.json +0 -101
- package/figma-intelligence-layer/jest.config.js +0 -14
- package/figma-intelligence-layer/mcp-config.json +0 -19
- package/figma-intelligence-layer/package-lock.json +0 -5892
- package/figma-intelligence-layer/scripts/setup-comfyui-local.sh +0 -67
- package/figma-intelligence-layer/scripts/start-comfyui.sh +0 -33
- package/figma-intelligence-layer/src/index.ts +0 -2233
- package/figma-intelligence-layer/src/shared/auto-layout-validator.ts +0 -404
- package/figma-intelligence-layer/src/shared/cache.ts +0 -187
- package/figma-intelligence-layer/src/shared/color-operations.ts +0 -533
- package/figma-intelligence-layer/src/shared/color-utils.ts +0 -138
- package/figma-intelligence-layer/src/shared/component-script-builder.ts +0 -413
- package/figma-intelligence-layer/src/shared/component-templates.ts +0 -2767
- package/figma-intelligence-layer/src/shared/concept-taxonomy.ts +0 -694
- package/figma-intelligence-layer/src/shared/decision-log.ts +0 -128
- package/figma-intelligence-layer/src/shared/design-system-context.ts +0 -568
- package/figma-intelligence-layer/src/shared/design-system-intelligence.ts +0 -131
- package/figma-intelligence-layer/src/shared/design-system-matcher.ts +0 -184
- package/figma-intelligence-layer/src/shared/design-system-normalizers.ts +0 -196
- package/figma-intelligence-layer/src/shared/design-system-tokens.ts +0 -295
- package/figma-intelligence-layer/src/shared/dtcg-validator.ts +0 -530
- package/figma-intelligence-layer/src/shared/enrichment-pipeline.ts +0 -671
- package/figma-intelligence-layer/src/shared/figma-bridge.ts +0 -1418
- package/figma-intelligence-layer/src/shared/font-config.ts +0 -126
- package/figma-intelligence-layer/src/shared/icon-catalog.ts +0 -360
- package/figma-intelligence-layer/src/shared/icon-fetch.ts +0 -80
- package/figma-intelligence-layer/src/shared/prototype-script-builder.ts +0 -162
- package/figma-intelligence-layer/src/shared/response-compression.ts +0 -440
- package/figma-intelligence-layer/src/shared/semantic-token-catalog.ts +0 -324
- package/figma-intelligence-layer/src/shared/token-binder.ts +0 -505
- package/figma-intelligence-layer/src/shared/token-math.ts +0 -427
- package/figma-intelligence-layer/src/shared/token-naming.ts +0 -468
- package/figma-intelligence-layer/src/shared/token-utils.ts +0 -420
- package/figma-intelligence-layer/src/shared/types.ts +0 -346
- package/figma-intelligence-layer/src/shared/typography-presets.ts +0 -94
- package/figma-intelligence-layer/src/shared/unsplash.ts +0 -165
- package/figma-intelligence-layer/src/shared/vision-client.ts +0 -607
- package/figma-intelligence-layer/src/shared/vision-provider-anthropic.ts +0 -334
- package/figma-intelligence-layer/src/shared/vision-provider-openai.ts +0 -446
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-handler.ts +0 -782
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-renderer.ts +0 -496
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotation-kit.ts +0 -230
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/colorblind-sim.ts +0 -66
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/index.ts +0 -810
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-analyzer.ts +0 -1191
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-figma-page.ts +0 -1346
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-handler.ts +0 -148
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-figma-page.ts +0 -499
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-report.ts +0 -910
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-checker.ts +0 -989
- package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-criteria.ts +0 -1160
- package/figma-intelligence-layer/src/tools/phase1-vision/design-from-ref/index.ts +0 -424
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/component-recognizer.ts +0 -38
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/ds-matcher.ts +0 -111
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/font-matcher.ts +0 -114
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/icon-resolver.ts +0 -103
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/index.ts +0 -1060
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/layout-segmenter.ts +0 -18
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/token-inferencer.ts +0 -39
- package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/vision-pipeline.ts +0 -58
- package/figma-intelligence-layer/src/tools/phase1-vision/sketch-to-design/index.ts +0 -298
- package/figma-intelligence-layer/src/tools/phase1-vision/visual-audit/index.ts +0 -197
- package/figma-intelligence-layer/src/tools/phase2-accuracy/component-audit/index.ts +0 -494
- package/figma-intelligence-layer/src/tools/phase2-accuracy/intent-translator/index.ts +0 -356
- package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/container-patterns.ts +0 -123
- package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/index.ts +0 -663
- package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/built-in-rules.yaml +0 -56
- package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/index.ts +0 -614
- package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/rule-engine.ts +0 -113
- package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/color-theory.ts +0 -178
- package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/index.ts +0 -470
- package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/index.ts +0 -429
- package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/token-override-maps.ts +0 -226
- package/figma-intelligence-layer/src/tools/phase3-generation/ai-image-insert/index.ts +0 -535
- package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/index.ts +0 -660
- package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/pattern-fingerprints.ts +0 -209
- package/figma-intelligence-layer/src/tools/phase3-generation/composition-builder/index.ts +0 -540
- package/figma-intelligence-layer/src/tools/phase3-generation/figma-animated-build.ts +0 -391
- package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/index.ts +0 -2019
- package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/screen-templates.ts +0 -131
- package/figma-intelligence-layer/src/tools/phase3-generation/prototype-map/index.ts +0 -381
- package/figma-intelligence-layer/src/tools/phase3-generation/prototype-wire/index.ts +0 -565
- package/figma-intelligence-layer/src/tools/phase3-generation/swarm-build/index.ts +0 -764
- package/figma-intelligence-layer/src/tools/phase3-generation/system-drift/index.ts +0 -535
- package/figma-intelligence-layer/src/tools/phase3-generation/unsplash-search/index.ts +0 -84
- package/figma-intelligence-layer/src/tools/phase3-generation/url-to-frame/index.ts +0 -401
- package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/css-animations.ts +0 -68
- package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/framer-motion.ts +0 -78
- package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/swift-animations.ts +0 -93
- package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/index.ts +0 -596
- package/figma-intelligence-layer/src/tools/phase4-sync/ci-check/index.ts +0 -462
- package/figma-intelligence-layer/src/tools/phase4-sync/export-tokens/index.ts +0 -1470
- package/figma-intelligence-layer/src/tools/phase4-sync/generate-component-code/index.ts +0 -829
- package/figma-intelligence-layer/src/tools/phase4-sync/handoff-spec/index.ts +0 -702
- package/figma-intelligence-layer/src/tools/phase4-sync/icon-library-sync/index.ts +0 -483
- package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/index.ts +0 -501
- package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/storybook-parser.ts +0 -106
- package/figma-intelligence-layer/src/tools/phase4-sync/watch-docs/index.ts +0 -676
- package/figma-intelligence-layer/src/tools/phase4-sync/webhook-listener/index.ts +0 -560
- package/figma-intelligence-layer/src/tools/phase5-governance/apg-doc/index.ts +0 -1043
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/component-detection.ts +0 -620
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/anatomy.ts +0 -331
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/color-tokens.ts +0 -77
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/properties.ts +0 -54
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/snapshot.ts +0 -287
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/spacing.ts +0 -71
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/states.ts +0 -43
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/typography.ts +0 -71
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/index.ts +0 -221
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/_default.ts +0 -166
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/accordion.ts +0 -232
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/alert.ts +0 -234
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar-group.ts +0 -270
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar.ts +0 -249
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/badge.ts +0 -231
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/banner.ts +0 -293
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/breadcrumb.ts +0 -240
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/button.ts +0 -243
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/calendar.ts +0 -307
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/card.ts +0 -143
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/checkbox.ts +0 -227
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/chip.ts +0 -233
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/combobox.ts +0 -282
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/datepicker.ts +0 -276
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/divider.ts +0 -223
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/drawer.ts +0 -255
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/dropdown-menu.ts +0 -289
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/empty-state.ts +0 -261
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/file-uploader.ts +0 -290
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/form.ts +0 -265
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/grid.ts +0 -238
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/icon.ts +0 -255
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/index.ts +0 -128
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-edit.ts +0 -286
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-message.ts +0 -255
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/input.ts +0 -330
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/link.ts +0 -247
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/list.ts +0 -250
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/menu.ts +0 -247
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/modal.ts +0 -144
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navbar.ts +0 -264
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navigation.ts +0 -251
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/number-input.ts +0 -261
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/pagination.ts +0 -248
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/popover.ts +0 -270
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/progress.ts +0 -251
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/radio.ts +0 -142
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/range-slider.ts +0 -282
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/rating.ts +0 -250
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/search.ts +0 -258
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/segmented-control.ts +0 -265
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/select.ts +0 -319
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/skeleton.ts +0 -256
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/slider.ts +0 -232
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/spinner.ts +0 -239
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/status-dot.ts +0 -252
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/stepper.ts +0 -270
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/table.ts +0 -244
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tabs.ts +0 -143
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tag.ts +0 -243
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/textarea.ts +0 -259
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/time-picker.ts +0 -293
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toast.ts +0 -144
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toggle.ts +0 -289
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toolbar.ts +0 -267
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tooltip.ts +0 -232
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/treeview.ts +0 -257
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/typography.ts +0 -319
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/legacy-compat.ts +0 -121
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/anatomy-diagram.ts +0 -430
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/figma-page.ts +0 -312
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/json.ts +0 -129
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/markdown.ts +0 -78
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/visual-doc.ts +0 -2333
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/accessibility.ts +0 -100
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/anatomy.ts +0 -32
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/color-tokens.ts +0 -59
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/content-guidance.ts +0 -18
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/design-tokens.ts +0 -53
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/interaction-rules.ts +0 -19
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/overview.ts +0 -91
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/properties-api.ts +0 -71
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/qa-criteria.ts +0 -19
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/related-components.ts +0 -110
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/responsive.ts +0 -19
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/size-specs.ts +0 -67
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/spacing-structure.ts +0 -58
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/state-specs.ts +0 -79
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/states.ts +0 -50
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/type-hierarchy.ts +0 -33
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/typography.ts +0 -55
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/usage-guidelines.ts +0 -73
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/variants.ts +0 -81
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/types.ts +0 -409
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/index.ts +0 -198
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/renderer.ts +0 -701
- package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/types.ts +0 -88
- package/figma-intelligence-layer/src/tools/phase5-governance/decision-log/index.ts +0 -135
- package/figma-intelligence-layer/src/tools/phase5-governance/design-decision-log/index.ts +0 -491
- package/figma-intelligence-layer/src/tools/phase5-governance/ds-primitives/index.ts +0 -416
- package/figma-intelligence-layer/src/tools/phase5-governance/ds-scaffolder/index.ts +0 -722
- package/figma-intelligence-layer/src/tools/phase5-governance/ds-variables/index.ts +0 -449
- package/figma-intelligence-layer/src/tools/phase5-governance/health-report/index.ts +0 -393
- package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/index.ts +0 -406
- package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/figma-page.ts +0 -292
- package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/json.ts +0 -24
- package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/markdown.ts +0 -172
- package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/naming-guide.ts +0 -409
- package/figma-intelligence-layer/src/tools/phase5-governance/token-analytics/index.ts +0 -594
- package/figma-intelligence-layer/src/tools/phase5-governance/token-docs/index.ts +0 -710
- package/figma-intelligence-layer/src/tools/phase5-governance/token-migrate/index.ts +0 -458
- package/figma-intelligence-layer/src/tools/phase5-governance/token-naming/index.ts +0 -134
- package/figma-intelligence-layer/tests/apg-doc.test.ts +0 -101
- package/figma-intelligence-layer/tests/design-system-context.test.ts +0 -152
- package/figma-intelligence-layer/tests/design-system-matcher.test.ts +0 -144
- package/figma-intelligence-layer/tests/figma-bridge.test.ts +0 -83
- package/figma-intelligence-layer/tests/generate-image-and-insert.test.ts +0 -56
- package/figma-intelligence-layer/tests/screen-cloner-regression.test.ts +0 -69
- package/figma-intelligence-layer/tests/smoke.test.ts +0 -174
- package/figma-intelligence-layer/tests/spec-generator.test.ts +0 -127
- package/figma-intelligence-layer/tests/token-migrate.test.ts +0 -21
- package/figma-intelligence-layer/tests/token-naming.test.ts +0 -30
- package/figma-intelligence-layer/tsconfig.json +0 -19
- package/scripts/clean-existing-chunks.js +0 -179
- package/scripts/connect-ai-tool.js +0 -490
- package/scripts/convert-hub-pdfs.js +0 -425
- package/scripts/figma-mcp-status.js +0 -349
- package/scripts/register-codex-mcp.js +0 -96
- /package/{design-bridge → dist/design-bridge}/.env.example +0 -0
- /package/{design-bridge → dist/design-bridge}/package.json +0 -0
- /package/{figma-bridge-plugin → dist/figma-bridge-plugin}/manifest.json +0 -0
- /package/{figma-bridge-plugin → dist/figma-bridge-plugin}/package.json +0 -0
- /package/{figma-intelligence-layer → dist/figma-intelligence-layer}/package.json +0 -0
|
@@ -1,829 +0,0 @@
|
|
|
1
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
// figma_generate_component_code — Figma component → production code
|
|
3
|
-
//
|
|
4
|
-
// Takes a Figma component (or component set) and generates production-ready
|
|
5
|
-
// code: React TSX, Vue SFC, Svelte, or HTML. Also generates CSS Module,
|
|
6
|
-
// Storybook stories, and a barrel index file.
|
|
7
|
-
//
|
|
8
|
-
// Data sources (in priority order):
|
|
9
|
-
// 1. Live Figma component via bridge (spec extraction)
|
|
10
|
-
// 2. Built-in component templates (blueprint catalog)
|
|
11
|
-
//
|
|
12
|
-
// The generated code mirrors the Figma component 1:1:
|
|
13
|
-
// - Variant axes → typed union props
|
|
14
|
-
// - Boolean toggles → boolean props
|
|
15
|
-
// - Instance swaps → slot/children props
|
|
16
|
-
// - Semantic tokens → CSS custom properties
|
|
17
|
-
// - States → CSS pseudo-classes and variant classes
|
|
18
|
-
// - Sizes → dimension presets
|
|
19
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
import { getBridge } from "../../../shared/figma-bridge.js";
|
|
22
|
-
import { componentSpecHandler } from "../../phase5-governance/component-spec/index.js";
|
|
23
|
-
import { COMPONENT_BLUEPRINTS, ComponentBlueprint, VariantProperty } from "../../../shared/component-templates.js";
|
|
24
|
-
|
|
25
|
-
import type {
|
|
26
|
-
ExtractionResult,
|
|
27
|
-
VariantAxis,
|
|
28
|
-
BooleanToggle,
|
|
29
|
-
InstanceSwap,
|
|
30
|
-
SpacingEntry,
|
|
31
|
-
ColorTokenEntry,
|
|
32
|
-
TypographyEntry,
|
|
33
|
-
} from "../../phase5-governance/component-spec/types.js";
|
|
34
|
-
|
|
35
|
-
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
export interface GenerateComponentCodeArgs {
|
|
38
|
-
/** Figma node ID of the component or component set */
|
|
39
|
-
nodeId?: string;
|
|
40
|
-
/** Component name — used to match built-in templates when no nodeId given */
|
|
41
|
-
componentName?: string;
|
|
42
|
-
/** Target framework */
|
|
43
|
-
framework: "react" | "vue" | "svelte" | "html";
|
|
44
|
-
/** Include Storybook stories file */
|
|
45
|
-
includeStories?: boolean;
|
|
46
|
-
/** Include CSS Module file */
|
|
47
|
-
includeStyles?: boolean;
|
|
48
|
-
/** CSS approach */
|
|
49
|
-
cssStrategy?: "css-modules" | "tailwind" | "styled-components";
|
|
50
|
-
/** TypeScript (default true for React/Vue) */
|
|
51
|
-
typescript?: boolean;
|
|
52
|
-
/** Token import path in generated CSS (default "../../tokens.css") */
|
|
53
|
-
tokenImportPath?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
interface ComponentData {
|
|
57
|
-
name: string;
|
|
58
|
-
description: string;
|
|
59
|
-
variantAxes: VariantAxis[];
|
|
60
|
-
booleanToggles: BooleanToggle[];
|
|
61
|
-
instanceSwaps: InstanceSwap[];
|
|
62
|
-
textProps: Array<{ name: string; value: string }>;
|
|
63
|
-
spacing: SpacingEntry[];
|
|
64
|
-
colorTokens: ColorTokenEntry[];
|
|
65
|
-
typography: TypographyEntry[];
|
|
66
|
-
states: string[];
|
|
67
|
-
source: "figma" | "blueprint";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// ─── Naming helpers ─────────────────────────────────────────────────────────
|
|
71
|
-
|
|
72
|
-
function pascalCase(s: string): string {
|
|
73
|
-
return s
|
|
74
|
-
.replace(/[^a-zA-Z0-9]+/g, " ")
|
|
75
|
-
.split(" ")
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
|
78
|
-
.join("");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function camelCase(s: string): string {
|
|
82
|
-
const p = pascalCase(s);
|
|
83
|
-
return p.charAt(0).toLowerCase() + p.slice(1);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function kebabCase(s: string): string {
|
|
87
|
-
return s
|
|
88
|
-
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
89
|
-
.replace(/[^a-zA-Z0-9]+/g, "-")
|
|
90
|
-
.toLowerCase()
|
|
91
|
-
.replace(/^-|-$/g, "");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function tokenToCssVar(token: string): string {
|
|
95
|
-
return "var(--" + token.replace(/\//g, "-").toLowerCase() + ")";
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// ─── Data extraction ────────────────────────────────────────────────────────
|
|
99
|
-
|
|
100
|
-
async function extractFromFigma(nodeId: string): Promise<ComponentData> {
|
|
101
|
-
const specResult = await componentSpecHandler({
|
|
102
|
-
nodeId,
|
|
103
|
-
outputFormat: "json",
|
|
104
|
-
sections: ["variants", "states", "properties", "spacing", "color-tokens", "typography"],
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const ext = specResult.spec.extraction;
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
name: specResult.spec.componentName,
|
|
111
|
-
description: specResult.spec.description ?? "",
|
|
112
|
-
variantAxes: ext.properties.variantAxes,
|
|
113
|
-
booleanToggles: ext.properties.booleanToggles,
|
|
114
|
-
instanceSwaps: ext.properties.instanceSwaps,
|
|
115
|
-
textProps: ext.properties.textProperties,
|
|
116
|
-
spacing: ext.spacing,
|
|
117
|
-
colorTokens: ext.colorTokens,
|
|
118
|
-
typography: ext.typography,
|
|
119
|
-
states: ext.states.states.map((s) => s.name),
|
|
120
|
-
source: "figma",
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function extractFromBlueprint(blueprint: ComponentBlueprint): ComponentData {
|
|
125
|
-
return {
|
|
126
|
-
name: blueprint.name,
|
|
127
|
-
description: blueprint.description,
|
|
128
|
-
variantAxes: blueprint.variantProperties.map((vp) => ({
|
|
129
|
-
name: vp.name,
|
|
130
|
-
values: vp.values,
|
|
131
|
-
defaultValue: vp.defaultValue,
|
|
132
|
-
})),
|
|
133
|
-
booleanToggles: (blueprint.iconSlots ?? []).map((slot) => ({
|
|
134
|
-
name: slot.propName,
|
|
135
|
-
defaultValue: !slot.required,
|
|
136
|
-
controlsElement: slot.nodePath,
|
|
137
|
-
})),
|
|
138
|
-
instanceSwaps: [],
|
|
139
|
-
textProps: [],
|
|
140
|
-
spacing: [],
|
|
141
|
-
colorTokens: [],
|
|
142
|
-
typography: [],
|
|
143
|
-
states: blueprint.variantProperties
|
|
144
|
-
.find((vp) => vp.name.toLowerCase() === "state")?.values ?? [],
|
|
145
|
-
source: "blueprint",
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// ─── Code generators ────────────────────────────────────────────────────────
|
|
150
|
-
|
|
151
|
-
function generateReact(data: ComponentData, args: GenerateComponentCodeArgs): Record<string, string> {
|
|
152
|
-
const name = pascalCase(data.name);
|
|
153
|
-
const ts = args.typescript !== false;
|
|
154
|
-
const ext = ts ? "tsx" : "jsx";
|
|
155
|
-
const cssModule = args.cssStrategy !== "tailwind" && args.cssStrategy !== "styled-components";
|
|
156
|
-
const files: Record<string, string> = {};
|
|
157
|
-
|
|
158
|
-
// ── Build prop types ──
|
|
159
|
-
const propLines: string[] = [];
|
|
160
|
-
const defaultProps: string[] = [];
|
|
161
|
-
|
|
162
|
-
// Variant axes → union types (skip "State" — handled via CSS states)
|
|
163
|
-
const stateAxis = data.variantAxes.find(
|
|
164
|
-
(a) => a.name.toLowerCase() === "state"
|
|
165
|
-
);
|
|
166
|
-
const propAxes = data.variantAxes.filter(
|
|
167
|
-
(a) => a.name.toLowerCase() !== "state"
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
for (const axis of propAxes) {
|
|
171
|
-
const propName = camelCase(axis.name);
|
|
172
|
-
const unionType = axis.values.map((v) => `'${v.toLowerCase()}'`).join(" | ");
|
|
173
|
-
propLines.push(` /** ${axis.name} variant */`);
|
|
174
|
-
propLines.push(` ${propName}?: ${unionType};`);
|
|
175
|
-
defaultProps.push(` ${propName} = '${axis.defaultValue.toLowerCase()}',`);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Boolean toggles
|
|
179
|
-
for (const toggle of data.booleanToggles) {
|
|
180
|
-
const propName = camelCase(toggle.name);
|
|
181
|
-
propLines.push(` /** Toggle ${toggle.name} visibility */`);
|
|
182
|
-
propLines.push(` ${propName}?: boolean;`);
|
|
183
|
-
defaultProps.push(` ${propName} = ${toggle.defaultValue},`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Standard props
|
|
187
|
-
propLines.push(` /** Button label / content */`);
|
|
188
|
-
propLines.push(` children: React.ReactNode;`);
|
|
189
|
-
|
|
190
|
-
// Loading state (if component has Loading state)
|
|
191
|
-
const hasLoading = data.states.some((s) => s.toLowerCase() === "loading");
|
|
192
|
-
if (hasLoading) {
|
|
193
|
-
propLines.push(` /** Loading state — disables interaction and shows spinner */`);
|
|
194
|
-
propLines.push(` loading?: boolean;`);
|
|
195
|
-
defaultProps.push(` loading = false,`);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Disabled
|
|
199
|
-
const hasDisabled = data.states.some((s) => s.toLowerCase() === "disabled");
|
|
200
|
-
if (hasDisabled) {
|
|
201
|
-
propLines.push(` /** Disabled state */`);
|
|
202
|
-
propLines.push(` disabled?: boolean;`);
|
|
203
|
-
defaultProps.push(` disabled = false,`);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
propLines.push(` /** Additional CSS class */`);
|
|
207
|
-
propLines.push(` className?: string;`);
|
|
208
|
-
|
|
209
|
-
// ── Determine HTML element ──
|
|
210
|
-
const isButton = data.name.toLowerCase().includes("button");
|
|
211
|
-
const isInput = data.name.toLowerCase().includes("input") || data.name.toLowerCase().includes("text-field");
|
|
212
|
-
const isToggle = data.name.toLowerCase().includes("toggle") || data.name.toLowerCase().includes("switch");
|
|
213
|
-
const isCheckbox = data.name.toLowerCase().includes("checkbox");
|
|
214
|
-
const isRadio = data.name.toLowerCase().includes("radio");
|
|
215
|
-
|
|
216
|
-
let htmlTag = "div";
|
|
217
|
-
let extendsType = "HTMLDivElement";
|
|
218
|
-
let htmlAttrsType = "React.HTMLAttributes<HTMLDivElement>";
|
|
219
|
-
|
|
220
|
-
if (isButton) {
|
|
221
|
-
htmlTag = "button";
|
|
222
|
-
extendsType = "HTMLButtonElement";
|
|
223
|
-
htmlAttrsType = "React.ButtonHTMLAttributes<HTMLButtonElement>";
|
|
224
|
-
} else if (isInput) {
|
|
225
|
-
htmlTag = "input";
|
|
226
|
-
extendsType = "HTMLInputElement";
|
|
227
|
-
htmlAttrsType = "React.InputHTMLAttributes<HTMLInputElement>";
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// ── Component file ──
|
|
231
|
-
const importLines: string[] = [];
|
|
232
|
-
importLines.push(`import React, { forwardRef } from 'react';`);
|
|
233
|
-
if (cssModule) {
|
|
234
|
-
importLines.push(`import styles from './${name}.module.css';`);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Build className logic
|
|
238
|
-
const classExprParts: string[] = [];
|
|
239
|
-
if (cssModule) {
|
|
240
|
-
classExprParts.push(`styles.${camelCase(data.name)}`);
|
|
241
|
-
for (const axis of propAxes) {
|
|
242
|
-
const propName = camelCase(axis.name);
|
|
243
|
-
classExprParts.push(`styles[\`${axis.name.toLowerCase()}-\${${propName}}\`]`);
|
|
244
|
-
}
|
|
245
|
-
if (hasDisabled) classExprParts.push(`disabled ? styles.disabled : ''`);
|
|
246
|
-
if (hasLoading) classExprParts.push(`loading ? styles.loading : ''`);
|
|
247
|
-
classExprParts.push(`className || ''`);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const classExpr = classExprParts.length > 0
|
|
251
|
-
? `[${classExprParts.join(", ")}].filter(Boolean).join(' ')`
|
|
252
|
-
: `className || ''`;
|
|
253
|
-
|
|
254
|
-
// Destructured props
|
|
255
|
-
const destructuredProps = [
|
|
256
|
-
...propAxes.map((a) => camelCase(a.name)),
|
|
257
|
-
...data.booleanToggles.map((t) => camelCase(t.name)),
|
|
258
|
-
"children",
|
|
259
|
-
...(hasLoading ? ["loading"] : []),
|
|
260
|
-
...(hasDisabled ? ["disabled"] : []),
|
|
261
|
-
"className",
|
|
262
|
-
"...rest",
|
|
263
|
-
];
|
|
264
|
-
|
|
265
|
-
const componentCode = `${importLines.join("\n")}
|
|
266
|
-
|
|
267
|
-
${ts ? `export interface ${name}Props extends ${htmlAttrsType} {
|
|
268
|
-
${propLines.join("\n")}
|
|
269
|
-
}` : ""}
|
|
270
|
-
|
|
271
|
-
const ${name} = forwardRef${ts ? `<${extendsType}, ${name}Props>` : ""}(
|
|
272
|
-
(
|
|
273
|
-
{
|
|
274
|
-
${defaultProps.join("\n")}
|
|
275
|
-
children,
|
|
276
|
-
className,
|
|
277
|
-
...rest
|
|
278
|
-
},
|
|
279
|
-
ref
|
|
280
|
-
) => {
|
|
281
|
-
const classNames = ${classExpr};
|
|
282
|
-
|
|
283
|
-
return (
|
|
284
|
-
<${htmlTag}
|
|
285
|
-
ref={ref}
|
|
286
|
-
className={classNames}
|
|
287
|
-
${hasDisabled || hasLoading ? ` disabled={${hasDisabled ? "disabled" : "false"} || ${hasLoading ? "loading" : "false"}}` : ""}
|
|
288
|
-
{...rest}
|
|
289
|
-
>
|
|
290
|
-
{children}
|
|
291
|
-
</${htmlTag}>
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
${name}.displayName = '${name}';
|
|
297
|
-
export default ${name};
|
|
298
|
-
`;
|
|
299
|
-
|
|
300
|
-
files[`${name}.${ext}`] = componentCode;
|
|
301
|
-
|
|
302
|
-
// ── CSS Module ──
|
|
303
|
-
if (args.includeStyles !== false && cssModule) {
|
|
304
|
-
files[`${name}.module.css`] = generateCSS(data, args);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// ── Stories ──
|
|
308
|
-
if (args.includeStories !== false) {
|
|
309
|
-
files[`${name}.stories.${ext}`] = generateStories(data, name, ext, propAxes);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// ── Index barrel ──
|
|
313
|
-
files[`index.${ts ? "ts" : "js"}`] = `export { default as ${name} } from './${name}';\nexport type { ${name}Props } from './${name}';\n`;
|
|
314
|
-
|
|
315
|
-
return files;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function generateVue(data: ComponentData, args: GenerateComponentCodeArgs): Record<string, string> {
|
|
319
|
-
const name = pascalCase(data.name);
|
|
320
|
-
const files: Record<string, string> = {};
|
|
321
|
-
|
|
322
|
-
const stateAxis = data.variantAxes.find((a) => a.name.toLowerCase() === "state");
|
|
323
|
-
const propAxes = data.variantAxes.filter((a) => a.name.toLowerCase() !== "state");
|
|
324
|
-
const hasLoading = data.states.some((s) => s.toLowerCase() === "loading");
|
|
325
|
-
const hasDisabled = data.states.some((s) => s.toLowerCase() === "disabled");
|
|
326
|
-
|
|
327
|
-
const propDefs: string[] = [];
|
|
328
|
-
for (const axis of propAxes) {
|
|
329
|
-
const propName = camelCase(axis.name);
|
|
330
|
-
propDefs.push(` ${propName}: {\n type: String as PropType<${axis.values.map((v) => `'${v.toLowerCase()}'`).join(" | ")}>,\n default: '${axis.defaultValue.toLowerCase()}',\n },`);
|
|
331
|
-
}
|
|
332
|
-
for (const toggle of data.booleanToggles) {
|
|
333
|
-
propDefs.push(` ${camelCase(toggle.name)}: {\n type: Boolean,\n default: ${toggle.defaultValue},\n },`);
|
|
334
|
-
}
|
|
335
|
-
if (hasLoading) {
|
|
336
|
-
propDefs.push(` loading: {\n type: Boolean,\n default: false,\n },`);
|
|
337
|
-
}
|
|
338
|
-
if (hasDisabled) {
|
|
339
|
-
propDefs.push(` disabled: {\n type: Boolean,\n default: false,\n },`);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const classBindings = propAxes
|
|
343
|
-
.map((a) => `[$style[\`${a.name.toLowerCase()}-\${${camelCase(a.name)}}\`]]: true`)
|
|
344
|
-
.join(",\n ");
|
|
345
|
-
|
|
346
|
-
const sfcCode = `<script setup lang="ts">
|
|
347
|
-
import type { PropType } from 'vue';
|
|
348
|
-
|
|
349
|
-
defineProps({
|
|
350
|
-
${propDefs.join("\n")}
|
|
351
|
-
});
|
|
352
|
-
</script>
|
|
353
|
-
|
|
354
|
-
<template>
|
|
355
|
-
<div
|
|
356
|
-
:class="{
|
|
357
|
-
[$style.${camelCase(data.name)}]: true,
|
|
358
|
-
${classBindings}${hasDisabled ? `,\n [$style.disabled]: disabled` : ""}${hasLoading ? `,\n [$style.loading]: loading` : ""}
|
|
359
|
-
}"
|
|
360
|
-
v-bind="$attrs"
|
|
361
|
-
>
|
|
362
|
-
<slot />
|
|
363
|
-
</div>
|
|
364
|
-
</template>
|
|
365
|
-
|
|
366
|
-
<style module>
|
|
367
|
-
${generateCSSBody(data, args)}
|
|
368
|
-
</style>
|
|
369
|
-
`;
|
|
370
|
-
|
|
371
|
-
files[`${name}.vue`] = sfcCode;
|
|
372
|
-
|
|
373
|
-
if (args.includeStories !== false) {
|
|
374
|
-
files[`${name}.stories.ts`] = generateVueStories(data, name, propAxes);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return files;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function generateSvelte(data: ComponentData, args: GenerateComponentCodeArgs): Record<string, string> {
|
|
381
|
-
const name = pascalCase(data.name);
|
|
382
|
-
const files: Record<string, string> = {};
|
|
383
|
-
|
|
384
|
-
const propAxes = data.variantAxes.filter((a) => a.name.toLowerCase() !== "state");
|
|
385
|
-
const hasLoading = data.states.some((s) => s.toLowerCase() === "loading");
|
|
386
|
-
const hasDisabled = data.states.some((s) => s.toLowerCase() === "disabled");
|
|
387
|
-
|
|
388
|
-
const propDecls: string[] = [];
|
|
389
|
-
for (const axis of propAxes) {
|
|
390
|
-
propDecls.push(` export let ${camelCase(axis.name)}: ${axis.values.map((v) => `'${v.toLowerCase()}'`).join(" | ")} = '${axis.defaultValue.toLowerCase()}';`);
|
|
391
|
-
}
|
|
392
|
-
for (const toggle of data.booleanToggles) {
|
|
393
|
-
propDecls.push(` export let ${camelCase(toggle.name)}: boolean = ${toggle.defaultValue};`);
|
|
394
|
-
}
|
|
395
|
-
if (hasLoading) propDecls.push(` export let loading: boolean = false;`);
|
|
396
|
-
if (hasDisabled) propDecls.push(` export let disabled: boolean = false;`);
|
|
397
|
-
|
|
398
|
-
const classExpr = [
|
|
399
|
-
`'${kebabCase(data.name)}'`,
|
|
400
|
-
...propAxes.map((a) => `\`${a.name.toLowerCase()}-\${${camelCase(a.name)}}\``),
|
|
401
|
-
...(hasDisabled ? [`disabled ? 'disabled' : ''`] : []),
|
|
402
|
-
...(hasLoading ? [`loading ? 'loading' : ''`] : []),
|
|
403
|
-
].join(", ");
|
|
404
|
-
|
|
405
|
-
const svelteCode = `<script lang="ts">
|
|
406
|
-
${propDecls.join("\n")}
|
|
407
|
-
</script>
|
|
408
|
-
|
|
409
|
-
<div
|
|
410
|
-
class={[${classExpr}].filter(Boolean).join(' ')}
|
|
411
|
-
{...$$restProps}
|
|
412
|
-
>
|
|
413
|
-
<slot />
|
|
414
|
-
</div>
|
|
415
|
-
|
|
416
|
-
<style>
|
|
417
|
-
${generateCSSBody(data, args)}
|
|
418
|
-
</style>
|
|
419
|
-
`;
|
|
420
|
-
|
|
421
|
-
files[`${name}.svelte`] = svelteCode;
|
|
422
|
-
return files;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function generateHTML(data: ComponentData, args: GenerateComponentCodeArgs): Record<string, string> {
|
|
426
|
-
const name = pascalCase(data.name);
|
|
427
|
-
const files: Record<string, string> = {};
|
|
428
|
-
|
|
429
|
-
const css = generateCSS(data, args);
|
|
430
|
-
const kebab = kebabCase(data.name);
|
|
431
|
-
|
|
432
|
-
const html = `<!DOCTYPE html>
|
|
433
|
-
<html lang="en">
|
|
434
|
-
<head>
|
|
435
|
-
<meta charset="UTF-8" />
|
|
436
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
437
|
-
<title>${name} Component</title>
|
|
438
|
-
<style>
|
|
439
|
-
${generateCSSBody(data, args).split("\n").map((l) => " " + l).join("\n")}
|
|
440
|
-
</style>
|
|
441
|
-
</head>
|
|
442
|
-
<body>
|
|
443
|
-
<h2>${name} Component</h2>
|
|
444
|
-
|
|
445
|
-
<!-- Default -->
|
|
446
|
-
<div class="${kebab}">
|
|
447
|
-
${name}
|
|
448
|
-
</div>
|
|
449
|
-
|
|
450
|
-
${data.variantAxes
|
|
451
|
-
.filter((a) => a.name.toLowerCase() !== "state")
|
|
452
|
-
.map((axis) =>
|
|
453
|
-
axis.values
|
|
454
|
-
.map((v) => ` <!-- ${axis.name}: ${v} -->\n <div class="${kebab} ${axis.name.toLowerCase()}-${v.toLowerCase()}">${name} (${v})</div>`)
|
|
455
|
-
.join("\n")
|
|
456
|
-
)
|
|
457
|
-
.join("\n\n")}
|
|
458
|
-
</body>
|
|
459
|
-
</html>
|
|
460
|
-
`;
|
|
461
|
-
|
|
462
|
-
files[`${name}.html`] = html;
|
|
463
|
-
files[`${name}.css`] = css;
|
|
464
|
-
return files;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// ─── CSS generation ─────────────────────────────────────────────────────────
|
|
468
|
-
|
|
469
|
-
function generateCSS(data: ComponentData, args: GenerateComponentCodeArgs): string {
|
|
470
|
-
const tokenPath = args.tokenImportPath ?? "../../tokens.css";
|
|
471
|
-
return `/* ============================================================
|
|
472
|
-
${data.name} — Generated from Figma Component
|
|
473
|
-
Source: ${data.source === "figma" ? "Live Figma extraction" : "Blueprint catalog"}
|
|
474
|
-
============================================================ */
|
|
475
|
-
|
|
476
|
-
@import '${tokenPath}';
|
|
477
|
-
|
|
478
|
-
${generateCSSBody(data, args)}`;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
function generateCSSBody(data: ComponentData, _args: GenerateComponentCodeArgs): string {
|
|
482
|
-
const base = kebabCase(data.name);
|
|
483
|
-
const propAxes = data.variantAxes.filter((a) => a.name.toLowerCase() !== "state");
|
|
484
|
-
const stateAxis = data.variantAxes.find((a) => a.name.toLowerCase() === "state");
|
|
485
|
-
const lines: string[] = [];
|
|
486
|
-
|
|
487
|
-
// ── Token custom properties ──
|
|
488
|
-
lines.push(`/* --- Design Tokens --- */`);
|
|
489
|
-
if (data.colorTokens.length > 0) {
|
|
490
|
-
lines.push(`:root {`);
|
|
491
|
-
const seen = new Set<string>();
|
|
492
|
-
for (const ct of data.colorTokens) {
|
|
493
|
-
const varName = `--${base}-${ct.element.toLowerCase()}-${ct.property}`;
|
|
494
|
-
if (seen.has(varName)) continue;
|
|
495
|
-
seen.add(varName);
|
|
496
|
-
lines.push(` ${varName}: ${ct.tokenName ? tokenToCssVar(ct.tokenName) : ct.colorHex};`);
|
|
497
|
-
}
|
|
498
|
-
lines.push(`}`);
|
|
499
|
-
lines.push(``);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// ── Base styles ──
|
|
503
|
-
lines.push(`/* --- Base --- */`);
|
|
504
|
-
lines.push(`.${base} {`);
|
|
505
|
-
lines.push(` display: inline-flex;`);
|
|
506
|
-
lines.push(` align-items: center;`);
|
|
507
|
-
lines.push(` justify-content: center;`);
|
|
508
|
-
|
|
509
|
-
if (data.spacing.length > 0) {
|
|
510
|
-
const root = data.spacing[0];
|
|
511
|
-
if (root.layoutMode === "HORIZONTAL" || root.layoutMode === "VERTICAL") {
|
|
512
|
-
lines.push(` flex-direction: ${root.layoutMode === "VERTICAL" ? "column" : "row"};`);
|
|
513
|
-
}
|
|
514
|
-
if (root.itemSpacing > 0) lines.push(` gap: ${root.itemSpacing}px;`);
|
|
515
|
-
if (root.paddingTop > 0 || root.paddingRight > 0 || root.paddingBottom > 0 || root.paddingLeft > 0) {
|
|
516
|
-
lines.push(` padding: ${root.paddingTop}px ${root.paddingRight}px ${root.paddingBottom}px ${root.paddingLeft}px;`);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
if (data.typography.length > 0) {
|
|
521
|
-
const firstText = data.typography[0];
|
|
522
|
-
lines.push(` font-family: '${firstText.fontFamily}', sans-serif;`);
|
|
523
|
-
lines.push(` font-size: ${firstText.fontSize}px;`);
|
|
524
|
-
if (firstText.lineHeightPx) lines.push(` line-height: ${firstText.lineHeightPx}px;`);
|
|
525
|
-
lines.push(` font-weight: ${firstText.fontStyle?.includes("Bold") ? 700 : firstText.fontStyle?.includes("Medium") ? 500 : 400};`);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
lines.push(` border: none;`);
|
|
529
|
-
lines.push(` cursor: pointer;`);
|
|
530
|
-
lines.push(` box-sizing: border-box;`);
|
|
531
|
-
lines.push(` transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;`);
|
|
532
|
-
lines.push(`}`);
|
|
533
|
-
lines.push(``);
|
|
534
|
-
|
|
535
|
-
lines.push(`.${base}:focus-visible {`);
|
|
536
|
-
lines.push(` outline: 2px solid var(--color-semantic-border-focus, #2563eb);`);
|
|
537
|
-
lines.push(` outline-offset: 2px;`);
|
|
538
|
-
lines.push(`}`);
|
|
539
|
-
lines.push(``);
|
|
540
|
-
|
|
541
|
-
// ── Size variants ──
|
|
542
|
-
const sizeAxis = propAxes.find(
|
|
543
|
-
(a) => a.name.toLowerCase() === "size"
|
|
544
|
-
);
|
|
545
|
-
if (sizeAxis) {
|
|
546
|
-
lines.push(`/* --- Sizes --- */`);
|
|
547
|
-
const sizeMap: Record<string, { height: number; paddingX: number; paddingY: number; fontSize: number }> = {
|
|
548
|
-
sm: { height: 32, paddingX: 12, paddingY: 6, fontSize: 12 },
|
|
549
|
-
md: { height: 40, paddingX: 16, paddingY: 10, fontSize: 14 },
|
|
550
|
-
lg: { height: 48, paddingX: 20, paddingY: 12, fontSize: 16 },
|
|
551
|
-
};
|
|
552
|
-
for (const size of sizeAxis.values) {
|
|
553
|
-
const s = sizeMap[size.toLowerCase()] ?? sizeMap.md;
|
|
554
|
-
lines.push(`.size-${size.toLowerCase()} {`);
|
|
555
|
-
lines.push(` height: ${s.height}px;`);
|
|
556
|
-
lines.push(` padding: ${s.paddingY}px ${s.paddingX}px;`);
|
|
557
|
-
lines.push(` font-size: ${s.fontSize}px;`);
|
|
558
|
-
lines.push(`}`);
|
|
559
|
-
}
|
|
560
|
-
lines.push(``);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// ── Type/variant variants ──
|
|
564
|
-
const typeAxis = propAxes.find(
|
|
565
|
-
(a) => a.name.toLowerCase() === "type" || a.name.toLowerCase() === "variant"
|
|
566
|
-
);
|
|
567
|
-
if (typeAxis) {
|
|
568
|
-
lines.push(`/* --- ${typeAxis.name} Variants --- */`);
|
|
569
|
-
for (const variant of typeAxis.values) {
|
|
570
|
-
const cls = `${typeAxis.name.toLowerCase()}-${variant.toLowerCase()}`;
|
|
571
|
-
lines.push(`.${cls} {`);
|
|
572
|
-
|
|
573
|
-
// Try to find matching color tokens
|
|
574
|
-
const variantTokens = data.colorTokens.filter(
|
|
575
|
-
(ct) => ct.tokenName?.toLowerCase().includes(variant.toLowerCase())
|
|
576
|
-
);
|
|
577
|
-
if (variantTokens.length > 0) {
|
|
578
|
-
const bgToken = variantTokens.find((t) => t.property === "fill");
|
|
579
|
-
const textToken = variantTokens.find((t) => t.property === "stroke") ?? variantTokens.find((t) => t.element.toLowerCase().includes("text") || t.element.toLowerCase().includes("label"));
|
|
580
|
-
if (bgToken) lines.push(` background-color: ${bgToken.tokenName ? tokenToCssVar(bgToken.tokenName) : bgToken.colorHex};`);
|
|
581
|
-
if (textToken) lines.push(` color: ${textToken.tokenName ? tokenToCssVar(textToken.tokenName) : textToken.colorHex};`);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
lines.push(`}`);
|
|
585
|
-
|
|
586
|
-
// Hover / active states
|
|
587
|
-
lines.push(`.${cls}:hover:not(:disabled) {`);
|
|
588
|
-
lines.push(` opacity: 0.9;`);
|
|
589
|
-
lines.push(`}`);
|
|
590
|
-
lines.push(`.${cls}:active:not(:disabled) {`);
|
|
591
|
-
lines.push(` opacity: 0.8;`);
|
|
592
|
-
lines.push(`}`);
|
|
593
|
-
}
|
|
594
|
-
lines.push(``);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// ── Disabled ──
|
|
598
|
-
if (data.states.some((s) => s.toLowerCase() === "disabled")) {
|
|
599
|
-
lines.push(`/* --- Disabled --- */`);
|
|
600
|
-
lines.push(`.disabled,`);
|
|
601
|
-
lines.push(`.${base}:disabled {`);
|
|
602
|
-
lines.push(` opacity: 0.4;`);
|
|
603
|
-
lines.push(` cursor: not-allowed;`);
|
|
604
|
-
lines.push(` pointer-events: none;`);
|
|
605
|
-
lines.push(`}`);
|
|
606
|
-
lines.push(``);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// ── Loading ──
|
|
610
|
-
if (data.states.some((s) => s.toLowerCase() === "loading")) {
|
|
611
|
-
lines.push(`/* --- Loading --- */`);
|
|
612
|
-
lines.push(`.loading {`);
|
|
613
|
-
lines.push(` pointer-events: none;`);
|
|
614
|
-
lines.push(` position: relative;`);
|
|
615
|
-
lines.push(`}`);
|
|
616
|
-
lines.push(``);
|
|
617
|
-
lines.push(`@keyframes spin {`);
|
|
618
|
-
lines.push(` to { transform: rotate(360deg); }`);
|
|
619
|
-
lines.push(`}`);
|
|
620
|
-
lines.push(``);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
return lines.join("\n");
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// ─── Storybook generation ───────────────────────────────────────────────────
|
|
627
|
-
|
|
628
|
-
function generateStories(
|
|
629
|
-
data: ComponentData,
|
|
630
|
-
name: string,
|
|
631
|
-
ext: string,
|
|
632
|
-
propAxes: VariantAxis[]
|
|
633
|
-
): string {
|
|
634
|
-
const typeAxis = propAxes.find(
|
|
635
|
-
(a) => a.name.toLowerCase() === "type" || a.name.toLowerCase() === "variant"
|
|
636
|
-
);
|
|
637
|
-
const sizeAxis = propAxes.find((a) => a.name.toLowerCase() === "size");
|
|
638
|
-
const hasLoading = data.states.some((s) => s.toLowerCase() === "loading");
|
|
639
|
-
const hasDisabled = data.states.some((s) => s.toLowerCase() === "disabled");
|
|
640
|
-
|
|
641
|
-
const argTypes: string[] = [];
|
|
642
|
-
for (const axis of propAxes) {
|
|
643
|
-
argTypes.push(` ${camelCase(axis.name)}: {\n control: 'select',\n options: [${axis.values.map((v) => `'${v.toLowerCase()}'`).join(", ")}],\n },`);
|
|
644
|
-
}
|
|
645
|
-
for (const toggle of data.booleanToggles) {
|
|
646
|
-
argTypes.push(` ${camelCase(toggle.name)}: { control: 'boolean' },`);
|
|
647
|
-
}
|
|
648
|
-
if (hasDisabled) argTypes.push(` disabled: { control: 'boolean' },`);
|
|
649
|
-
if (hasLoading) argTypes.push(` loading: { control: 'boolean' },`);
|
|
650
|
-
|
|
651
|
-
const defaultArgs: string[] = [
|
|
652
|
-
` children: '${name}',`,
|
|
653
|
-
...propAxes.map((a) => ` ${camelCase(a.name)}: '${a.defaultValue.toLowerCase()}',`),
|
|
654
|
-
...data.booleanToggles.map((t) => ` ${camelCase(t.name)}: ${t.defaultValue},`),
|
|
655
|
-
...(hasDisabled ? [` disabled: false,`] : []),
|
|
656
|
-
...(hasLoading ? [` loading: false,`] : []),
|
|
657
|
-
];
|
|
658
|
-
|
|
659
|
-
let allVariantsStory = "";
|
|
660
|
-
if (typeAxis && sizeAxis) {
|
|
661
|
-
allVariantsStory = `
|
|
662
|
-
export const AllVariants: Story = {
|
|
663
|
-
render: () => (
|
|
664
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
|
|
665
|
-
{(${JSON.stringify(typeAxis.values.map((v) => v.toLowerCase()))} as const).map((variant) => (
|
|
666
|
-
<div key={variant} style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
|
|
667
|
-
<span style={{ width: 100, fontSize: 12, color: '#64748b', textTransform: 'capitalize' }}>{variant}</span>
|
|
668
|
-
{(${JSON.stringify(sizeAxis.values.map((v) => v.toLowerCase()))} as const).map((size) => (
|
|
669
|
-
<${name} key={\`\${variant}-\${size}\`} ${camelCase(typeAxis.name)}={variant} ${camelCase(sizeAxis.name)}={size}>${name}</${name}>
|
|
670
|
-
))}
|
|
671
|
-
<${name} ${camelCase(typeAxis.name)}={variant} disabled>${name}</${name}>
|
|
672
|
-
</div>
|
|
673
|
-
))}
|
|
674
|
-
</div>
|
|
675
|
-
),
|
|
676
|
-
};`;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
return `import type { Meta, StoryObj } from '@storybook/react';
|
|
680
|
-
import ${name} from './${name}';
|
|
681
|
-
|
|
682
|
-
const meta: Meta<typeof ${name}> = {
|
|
683
|
-
title: 'Components/${name}',
|
|
684
|
-
component: ${name},
|
|
685
|
-
argTypes: {
|
|
686
|
-
${argTypes.join("\n")}
|
|
687
|
-
},
|
|
688
|
-
args: {
|
|
689
|
-
${defaultArgs.join("\n")}
|
|
690
|
-
},
|
|
691
|
-
};
|
|
692
|
-
|
|
693
|
-
export default meta;
|
|
694
|
-
type Story = StoryObj<typeof ${name}>;
|
|
695
|
-
|
|
696
|
-
export const Default: Story = {};
|
|
697
|
-
${allVariantsStory}
|
|
698
|
-
|
|
699
|
-
export const Disabled: Story = {
|
|
700
|
-
args: { disabled: true },
|
|
701
|
-
};
|
|
702
|
-
${hasLoading ? `
|
|
703
|
-
export const Loading: Story = {
|
|
704
|
-
args: { loading: true },
|
|
705
|
-
};` : ""}
|
|
706
|
-
`;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
function generateVueStories(data: ComponentData, name: string, propAxes: VariantAxis[]): string {
|
|
710
|
-
const defaultArgs: string[] = propAxes.map(
|
|
711
|
-
(a) => ` ${camelCase(a.name)}: '${a.defaultValue.toLowerCase()}',`
|
|
712
|
-
);
|
|
713
|
-
|
|
714
|
-
return `import type { Meta, StoryObj } from '@storybook/vue3';
|
|
715
|
-
import ${name} from './${name}.vue';
|
|
716
|
-
|
|
717
|
-
const meta: Meta<typeof ${name}> = {
|
|
718
|
-
title: 'Components/${name}',
|
|
719
|
-
component: ${name},
|
|
720
|
-
args: {
|
|
721
|
-
${defaultArgs.join("\n")}
|
|
722
|
-
},
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
export default meta;
|
|
726
|
-
type Story = StoryObj<typeof ${name}>;
|
|
727
|
-
|
|
728
|
-
export const Default: Story = {
|
|
729
|
-
render: (args) => ({
|
|
730
|
-
components: { ${name} },
|
|
731
|
-
setup() { return { args }; },
|
|
732
|
-
template: '<${name} v-bind="args">${name}</${name}>',
|
|
733
|
-
}),
|
|
734
|
-
};
|
|
735
|
-
`;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// ─── Main handler ───────────────────────────────────────────────────────────
|
|
739
|
-
|
|
740
|
-
export async function generateComponentCodeHandler(
|
|
741
|
-
args: GenerateComponentCodeArgs
|
|
742
|
-
): Promise<unknown> {
|
|
743
|
-
let data: ComponentData;
|
|
744
|
-
|
|
745
|
-
// 1. Try live Figma extraction
|
|
746
|
-
if (args.nodeId) {
|
|
747
|
-
try {
|
|
748
|
-
data = await extractFromFigma(args.nodeId);
|
|
749
|
-
} catch (err) {
|
|
750
|
-
return {
|
|
751
|
-
error: `Failed to extract component data from Figma: ${err instanceof Error ? err.message : String(err)}`,
|
|
752
|
-
hint: "Ensure Figma is open with the bridge plugin running, and the nodeId points to a Component or ComponentSet.",
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
} else if (args.componentName) {
|
|
756
|
-
// 2. Fall back to blueprint catalog
|
|
757
|
-
const blueprint = COMPONENT_BLUEPRINTS.find(
|
|
758
|
-
(b) => b.name.toLowerCase() === args.componentName!.toLowerCase()
|
|
759
|
-
);
|
|
760
|
-
if (!blueprint) {
|
|
761
|
-
return {
|
|
762
|
-
error: `No blueprint found for component "${args.componentName}".`,
|
|
763
|
-
availableBlueprints: COMPONENT_BLUEPRINTS.map((b) => b.name),
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
data = extractFromBlueprint(blueprint);
|
|
767
|
-
} else {
|
|
768
|
-
// 3. Try current selection
|
|
769
|
-
try {
|
|
770
|
-
const bridge = await getBridge();
|
|
771
|
-
const selection = (await bridge.getSelection()) as Array<{ id: string }>;
|
|
772
|
-
if (!selection?.length) {
|
|
773
|
-
return {
|
|
774
|
-
error: "No nodeId or componentName provided, and nothing is selected in Figma.",
|
|
775
|
-
hint: "Select a component in Figma, or pass nodeId or componentName.",
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
data = await extractFromFigma(selection[0].id);
|
|
779
|
-
} catch {
|
|
780
|
-
return {
|
|
781
|
-
error: "No nodeId or componentName provided, and Figma bridge is not connected.",
|
|
782
|
-
hint: "Pass nodeId (from Figma) or componentName (to use built-in blueprints).",
|
|
783
|
-
availableBlueprints: COMPONENT_BLUEPRINTS.map((b) => b.name),
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
// Generate code for the requested framework
|
|
789
|
-
let files: Record<string, string>;
|
|
790
|
-
|
|
791
|
-
switch (args.framework) {
|
|
792
|
-
case "react":
|
|
793
|
-
files = generateReact(data, args);
|
|
794
|
-
break;
|
|
795
|
-
case "vue":
|
|
796
|
-
files = generateVue(data, args);
|
|
797
|
-
break;
|
|
798
|
-
case "svelte":
|
|
799
|
-
files = generateSvelte(data, args);
|
|
800
|
-
break;
|
|
801
|
-
case "html":
|
|
802
|
-
files = generateHTML(data, args);
|
|
803
|
-
break;
|
|
804
|
-
default:
|
|
805
|
-
return { error: `Unsupported framework: ${args.framework}` };
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
return {
|
|
809
|
-
component: data.name,
|
|
810
|
-
framework: args.framework,
|
|
811
|
-
source: data.source,
|
|
812
|
-
files,
|
|
813
|
-
summary: {
|
|
814
|
-
totalFiles: Object.keys(files).length,
|
|
815
|
-
props: [
|
|
816
|
-
...data.variantAxes
|
|
817
|
-
.filter((a) => a.name.toLowerCase() !== "state")
|
|
818
|
-
.map((a) => ({ name: camelCase(a.name), type: "variant", values: a.values })),
|
|
819
|
-
...data.booleanToggles.map((t) => ({ name: camelCase(t.name), type: "boolean" })),
|
|
820
|
-
...(data.states.some((s) => s.toLowerCase() === "loading") ? [{ name: "loading", type: "boolean" }] : []),
|
|
821
|
-
...(data.states.some((s) => s.toLowerCase() === "disabled") ? [{ name: "disabled", type: "boolean" }] : []),
|
|
822
|
-
],
|
|
823
|
-
states: data.states,
|
|
824
|
-
variantCombinations: data.variantAxes.reduce((acc, a) => acc * a.values.length, 1),
|
|
825
|
-
tokenCount: data.colorTokens.length,
|
|
826
|
-
},
|
|
827
|
-
usage: `Copy the files to your components directory:\n ${Object.keys(files).join("\n ")}`,
|
|
828
|
-
};
|
|
829
|
-
}
|