@seed-design/figma 0.0.6 → 0.0.15

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 (195) hide show
  1. package/lib/index.cjs +5548 -4901
  2. package/lib/index.d.ts +489 -189
  3. package/lib/index.js +5535 -4888
  4. package/package.json +3 -2
  5. package/src/codegen/core/codegen.ts +65 -0
  6. package/src/codegen/core/component.ts +15 -27
  7. package/src/codegen/core/component.types.ts +29 -0
  8. package/src/codegen/core/element.ts +13 -0
  9. package/src/codegen/core/index.ts +13 -8
  10. package/src/codegen/core/infer-layout.test.ts +285 -0
  11. package/src/codegen/core/infer-layout.ts +416 -0
  12. package/src/codegen/core/jsx.ts +12 -0
  13. package/src/codegen/core/props.ts +81 -0
  14. package/src/codegen/core/value.ts +289 -0
  15. package/src/codegen/index.ts +39 -6
  16. package/src/codegen/targets/figma/context.ts +139 -0
  17. package/src/codegen/targets/figma/frame.ts +37 -0
  18. package/src/codegen/targets/figma/index.ts +6 -0
  19. package/src/codegen/targets/figma/instance.ts +16 -0
  20. package/src/codegen/targets/figma/props.ts +244 -0
  21. package/src/codegen/targets/figma/shape.ts +62 -0
  22. package/src/codegen/targets/figma/text.ts +33 -0
  23. package/src/codegen/targets/index.ts +2 -0
  24. package/src/codegen/{domain/seed-component → targets/react/component}/deps.interface.ts +2 -2
  25. package/src/codegen/{domain/seed-component → targets/react/component}/index.ts +36 -34
  26. package/src/codegen/{domain/seed-component → targets/react/component}/properties.type.ts +2 -2
  27. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/action-button.ts +4 -5
  28. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/action-chip.ts +3 -4
  29. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/action-sheet.ts +4 -5
  30. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/app-bar.ts +5 -6
  31. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/avatar-stack.ts +4 -5
  32. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/avatar.ts +4 -5
  33. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/badge.ts +4 -5
  34. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/callout.ts +4 -5
  35. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/checkbox.ts +4 -5
  36. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/chip-tabs.ts +4 -5
  37. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/control-chip.ts +4 -5
  38. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/error-state.ts +4 -5
  39. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/extended-action-sheet.ts +4 -5
  40. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/extended-fab.ts +4 -5
  41. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/fab.ts +2 -2
  42. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/help-bubble.ts +2 -2
  43. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/identity-placeholder.ts +2 -2
  44. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/inline-banner.ts +5 -6
  45. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/manner-temp-badge.ts +3 -4
  46. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/multiline-text-field.ts +4 -5
  47. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/progress-circle.ts +3 -4
  48. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/reaction-button.ts +4 -5
  49. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/segmented-control.ts +4 -5
  50. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/select-box.ts +4 -5
  51. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/skeleton.ts +3 -4
  52. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/snackbar.ts +3 -4
  53. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/switch.ts +4 -5
  54. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/tabs.ts +5 -6
  55. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/text-button.ts +6 -7
  56. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/text-field.ts +4 -5
  57. package/src/codegen/{domain/seed-component → targets/react/component}/transformers/toggle-button.ts +4 -5
  58. package/src/codegen/targets/react/context.ts +170 -0
  59. package/src/codegen/targets/react/frame.ts +75 -0
  60. package/src/codegen/targets/react/index.ts +7 -0
  61. package/src/codegen/{domain/instance.service.ts → targets/react/instance.ts} +20 -33
  62. package/src/codegen/targets/react/props.ts +361 -0
  63. package/src/codegen/targets/react/shape.ts +36 -0
  64. package/src/codegen/targets/react/text.ts +33 -0
  65. package/src/{codegen → entities}/data/icons.ts +1 -1
  66. package/src/{codegen → entities}/data/styles.ts +1 -1
  67. package/src/{codegen → entities}/data/variable-collections.ts +1 -1
  68. package/src/{codegen → entities}/data/variables.ts +1 -1
  69. package/src/entities/index.ts +41 -0
  70. package/src/{codegen/domain → entities}/style.repository.ts +6 -2
  71. package/src/{codegen/domain → entities}/style.service.ts +1 -1
  72. package/src/{codegen/domain → entities}/variable.repository.ts +17 -4
  73. package/src/{codegen/domain → entities}/variable.service.ts +47 -9
  74. package/src/index.ts +1 -0
  75. package/src/normalizer/from-plugin.ts +3 -0
  76. package/src/normalizer/types.ts +28 -24
  77. package/src/utils/common.ts +4 -0
  78. package/src/utils/css.ts +10 -4
  79. package/src/utils/figma-node.ts +42 -2
  80. package/src/codegen/context.ts +0 -148
  81. package/src/codegen/core/transformer.ts +0 -40
  82. package/src/codegen/domain/codegen.service.ts +0 -69
  83. package/src/codegen/domain/figma-component.service.ts +0 -21
  84. package/src/codegen/domain/frame.service.ts +0 -108
  85. package/src/codegen/domain/index.ts +0 -22
  86. package/src/codegen/domain/props/container-layout-props.service.ts +0 -248
  87. package/src/codegen/domain/props/fill-props.service.ts +0 -75
  88. package/src/codegen/domain/props/radius-props.service.ts +0 -105
  89. package/src/codegen/domain/props/self-layout-props.service.ts +0 -127
  90. package/src/codegen/domain/props/stroke-props.service.ts +0 -45
  91. package/src/codegen/domain/props/type-style-props.service.ts +0 -31
  92. package/src/codegen/domain/rectangle.service.ts +0 -31
  93. package/src/codegen/domain/text.service.ts +0 -62
  94. /package/src/codegen/{domain/seed-component → targets/react/component}/size.ts +0 -0
  95. /package/src/{codegen → entities}/data/__generated__/component-sets/action-button.d.ts +0 -0
  96. /package/src/{codegen → entities}/data/__generated__/component-sets/action-button.mjs +0 -0
  97. /package/src/{codegen → entities}/data/__generated__/component-sets/action-chip.d.ts +0 -0
  98. /package/src/{codegen → entities}/data/__generated__/component-sets/action-chip.mjs +0 -0
  99. /package/src/{codegen → entities}/data/__generated__/component-sets/action-sheet.d.ts +0 -0
  100. /package/src/{codegen → entities}/data/__generated__/component-sets/action-sheet.mjs +0 -0
  101. /package/src/{codegen → entities}/data/__generated__/component-sets/avatar-stack.d.ts +0 -0
  102. /package/src/{codegen → entities}/data/__generated__/component-sets/avatar-stack.mjs +0 -0
  103. /package/src/{codegen → entities}/data/__generated__/component-sets/avatar.d.ts +0 -0
  104. /package/src/{codegen → entities}/data/__generated__/component-sets/avatar.mjs +0 -0
  105. /package/src/{codegen → entities}/data/__generated__/component-sets/badge.d.ts +0 -0
  106. /package/src/{codegen → entities}/data/__generated__/component-sets/badge.mjs +0 -0
  107. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-navigation-global.d.ts +0 -0
  108. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-navigation-global.mjs +0 -0
  109. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-navigation-kr.d.ts +0 -0
  110. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-navigation-kr.mjs +0 -0
  111. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-sheet.d.ts +0 -0
  112. /package/src/{codegen → entities}/data/__generated__/component-sets/bottom-sheet.mjs +0 -0
  113. /package/src/{codegen → entities}/data/__generated__/component-sets/callout.d.ts +0 -0
  114. /package/src/{codegen → entities}/data/__generated__/component-sets/callout.mjs +0 -0
  115. /package/src/{codegen → entities}/data/__generated__/component-sets/checkbox.d.ts +0 -0
  116. /package/src/{codegen → entities}/data/__generated__/component-sets/checkbox.mjs +0 -0
  117. /package/src/{codegen → entities}/data/__generated__/component-sets/chip-tablist.d.ts +0 -0
  118. /package/src/{codegen → entities}/data/__generated__/component-sets/chip-tablist.mjs +0 -0
  119. /package/src/{codegen → entities}/data/__generated__/component-sets/control-chip.d.ts +0 -0
  120. /package/src/{codegen → entities}/data/__generated__/component-sets/control-chip.mjs +0 -0
  121. /package/src/{codegen → entities}/data/__generated__/component-sets/divider.d.ts +0 -0
  122. /package/src/{codegen → entities}/data/__generated__/component-sets/divider.mjs +0 -0
  123. /package/src/{codegen → entities}/data/__generated__/component-sets/error-state.d.ts +0 -0
  124. /package/src/{codegen → entities}/data/__generated__/component-sets/error-state.mjs +0 -0
  125. /package/src/{codegen → entities}/data/__generated__/component-sets/extended-action-sheet.d.ts +0 -0
  126. /package/src/{codegen → entities}/data/__generated__/component-sets/extended-action-sheet.mjs +0 -0
  127. /package/src/{codegen → entities}/data/__generated__/component-sets/extended-floating-action-button.d.ts +0 -0
  128. /package/src/{codegen → entities}/data/__generated__/component-sets/extended-floating-action-button.mjs +0 -0
  129. /package/src/{codegen → entities}/data/__generated__/component-sets/floating-action-button.d.ts +0 -0
  130. /package/src/{codegen → entities}/data/__generated__/component-sets/floating-action-button.mjs +0 -0
  131. /package/src/{codegen → entities}/data/__generated__/component-sets/help-bubble.d.ts +0 -0
  132. /package/src/{codegen → entities}/data/__generated__/component-sets/help-bubble.mjs +0 -0
  133. /package/src/{codegen → entities}/data/__generated__/component-sets/identity-placeholder.d.ts +0 -0
  134. /package/src/{codegen → entities}/data/__generated__/component-sets/identity-placeholder.mjs +0 -0
  135. /package/src/{codegen → entities}/data/__generated__/component-sets/index.d.ts +0 -0
  136. /package/src/{codegen → entities}/data/__generated__/component-sets/index.mjs +0 -0
  137. /package/src/{codegen → entities}/data/__generated__/component-sets/inline-banner.d.ts +0 -0
  138. /package/src/{codegen → entities}/data/__generated__/component-sets/inline-banner.mjs +0 -0
  139. /package/src/{codegen → entities}/data/__generated__/component-sets/main-tab-navigation-global.d.ts +0 -0
  140. /package/src/{codegen → entities}/data/__generated__/component-sets/main-tab-navigation-global.mjs +0 -0
  141. /package/src/{codegen → entities}/data/__generated__/component-sets/main-tab-navigation-kr.d.ts +0 -0
  142. /package/src/{codegen → entities}/data/__generated__/component-sets/main-tab-navigation-kr.mjs +0 -0
  143. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp-badge.d.ts +0 -0
  144. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp-badge.mjs +0 -0
  145. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp-bar.d.ts +0 -0
  146. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp-bar.mjs +0 -0
  147. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp.d.ts +0 -0
  148. /package/src/{codegen → entities}/data/__generated__/component-sets/manner-temp.mjs +0 -0
  149. /package/src/{codegen → entities}/data/__generated__/component-sets/multiline-text-field.d.ts +0 -0
  150. /package/src/{codegen → entities}/data/__generated__/component-sets/multiline-text-field.mjs +0 -0
  151. /package/src/{codegen → entities}/data/__generated__/component-sets/progress-circle.d.ts +0 -0
  152. /package/src/{codegen → entities}/data/__generated__/component-sets/progress-circle.mjs +0 -0
  153. /package/src/{codegen → entities}/data/__generated__/component-sets/radio.d.ts +0 -0
  154. /package/src/{codegen → entities}/data/__generated__/component-sets/radio.mjs +0 -0
  155. /package/src/{codegen → entities}/data/__generated__/component-sets/range-slider.d.ts +0 -0
  156. /package/src/{codegen → entities}/data/__generated__/component-sets/range-slider.mjs +0 -0
  157. /package/src/{codegen → entities}/data/__generated__/component-sets/reaction-button.d.ts +0 -0
  158. /package/src/{codegen → entities}/data/__generated__/component-sets/reaction-button.mjs +0 -0
  159. /package/src/{codegen → entities}/data/__generated__/component-sets/segmented-control.d.ts +0 -0
  160. /package/src/{codegen → entities}/data/__generated__/component-sets/segmented-control.mjs +0 -0
  161. /package/src/{codegen → entities}/data/__generated__/component-sets/select-box.d.ts +0 -0
  162. /package/src/{codegen → entities}/data/__generated__/component-sets/select-box.mjs +0 -0
  163. /package/src/{codegen → entities}/data/__generated__/component-sets/skeleton.d.ts +0 -0
  164. /package/src/{codegen → entities}/data/__generated__/component-sets/skeleton.mjs +0 -0
  165. /package/src/{codegen → entities}/data/__generated__/component-sets/slider.d.ts +0 -0
  166. /package/src/{codegen → entities}/data/__generated__/component-sets/slider.mjs +0 -0
  167. /package/src/{codegen → entities}/data/__generated__/component-sets/snackbar.d.ts +0 -0
  168. /package/src/{codegen → entities}/data/__generated__/component-sets/snackbar.mjs +0 -0
  169. /package/src/{codegen → entities}/data/__generated__/component-sets/standard-navigation.d.ts +0 -0
  170. /package/src/{codegen → entities}/data/__generated__/component-sets/standard-navigation.mjs +0 -0
  171. /package/src/{codegen → entities}/data/__generated__/component-sets/switch.d.ts +0 -0
  172. /package/src/{codegen → entities}/data/__generated__/component-sets/switch.mjs +0 -0
  173. /package/src/{codegen → entities}/data/__generated__/component-sets/tablist.d.ts +0 -0
  174. /package/src/{codegen → entities}/data/__generated__/component-sets/tablist.mjs +0 -0
  175. /package/src/{codegen → entities}/data/__generated__/component-sets/template-bottom-fixed-bar.d.ts +0 -0
  176. /package/src/{codegen → entities}/data/__generated__/component-sets/template-bottom-fixed-bar.mjs +0 -0
  177. /package/src/{codegen → entities}/data/__generated__/component-sets/template-button-group.d.ts +0 -0
  178. /package/src/{codegen → entities}/data/__generated__/component-sets/template-button-group.mjs +0 -0
  179. /package/src/{codegen → entities}/data/__generated__/component-sets/template-chip-group.d.ts +0 -0
  180. /package/src/{codegen → entities}/data/__generated__/component-sets/template-chip-group.mjs +0 -0
  181. /package/src/{codegen → entities}/data/__generated__/component-sets/template-select-box-group.d.ts +0 -0
  182. /package/src/{codegen → entities}/data/__generated__/component-sets/template-select-box-group.mjs +0 -0
  183. /package/src/{codegen → entities}/data/__generated__/component-sets/template-top-navigation.d.ts +0 -0
  184. /package/src/{codegen → entities}/data/__generated__/component-sets/template-top-navigation.mjs +0 -0
  185. /package/src/{codegen → entities}/data/__generated__/component-sets/text-button.d.ts +0 -0
  186. /package/src/{codegen → entities}/data/__generated__/component-sets/text-button.mjs +0 -0
  187. /package/src/{codegen → entities}/data/__generated__/component-sets/text-field.d.ts +0 -0
  188. /package/src/{codegen → entities}/data/__generated__/component-sets/text-field.mjs +0 -0
  189. /package/src/{codegen → entities}/data/__generated__/component-sets/toggle-button.d.ts +0 -0
  190. /package/src/{codegen → entities}/data/__generated__/component-sets/toggle-button.mjs +0 -0
  191. /package/src/{codegen/domain → entities}/icon.interface.ts +0 -0
  192. /package/src/{codegen/domain → entities}/icon.repository.ts +0 -0
  193. /package/src/{codegen/domain → entities}/icon.service.ts +0 -0
  194. /package/src/{codegen/domain → entities}/style.interface.ts +0 -0
  195. /package/src/{codegen/domain → entities}/variable.interface.ts +0 -0
@@ -0,0 +1,289 @@
1
+ import type {
2
+ NormalizedCornerTrait,
3
+ NormalizedHasFramePropertiesTrait,
4
+ NormalizedHasGeometryTrait,
5
+ NormalizedHasLayoutTrait,
6
+ NormalizedIsLayerTrait,
7
+ NormalizedTypePropertiesTrait,
8
+ } from "@/normalizer";
9
+ import {
10
+ getFirstFillVariable,
11
+ getFirstSolidFill,
12
+ getFirstStroke,
13
+ getFirstStrokeVariable,
14
+ } from "@/utils/figma-node";
15
+ import type { RGBA } from "@figma/rest-api-spec";
16
+ import type { VariableService } from "../../entities/variable.service";
17
+
18
+ export interface ValueTransformer<TColor, TDimension, TFontDimension, TFontWeight> {
19
+ getFormattedValue: {
20
+ frameFill: (
21
+ node: NormalizedHasGeometryTrait & NormalizedIsLayerTrait,
22
+ ) => string | TColor | undefined;
23
+ shapeFill: (
24
+ node: NormalizedHasGeometryTrait & NormalizedIsLayerTrait,
25
+ ) => string | TColor | undefined;
26
+ textFill: (
27
+ node: NormalizedHasGeometryTrait & NormalizedIsLayerTrait,
28
+ ) => string | TColor | undefined;
29
+ stroke: (
30
+ node: NormalizedHasGeometryTrait & NormalizedIsLayerTrait,
31
+ ) => string | TColor | undefined;
32
+ width: (
33
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
34
+ ) => string | TDimension | undefined;
35
+ height: (
36
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
37
+ ) => string | TDimension | undefined;
38
+ minWidth: (
39
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
40
+ ) => string | TDimension | undefined;
41
+ minHeight: (
42
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
43
+ ) => string | TDimension | undefined;
44
+ maxWidth: (
45
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
46
+ ) => string | TDimension | undefined;
47
+ maxHeight: (
48
+ node: NormalizedHasLayoutTrait & NormalizedIsLayerTrait,
49
+ ) => string | TDimension | undefined;
50
+ paddingLeft: (
51
+ node: NormalizedHasFramePropertiesTrait & NormalizedIsLayerTrait,
52
+ ) => string | TDimension | undefined;
53
+ paddingRight: (
54
+ node: NormalizedHasFramePropertiesTrait & NormalizedIsLayerTrait,
55
+ ) => string | TDimension | undefined;
56
+ paddingTop: (
57
+ node: NormalizedHasFramePropertiesTrait & NormalizedIsLayerTrait,
58
+ ) => string | TDimension | undefined;
59
+ paddingBottom: (
60
+ node: NormalizedHasFramePropertiesTrait & NormalizedIsLayerTrait,
61
+ ) => string | TDimension | undefined;
62
+ itemSpacing: (
63
+ node: NormalizedHasFramePropertiesTrait & NormalizedIsLayerTrait,
64
+ ) => string | TDimension | undefined;
65
+ topLeftRadius: (
66
+ node: NormalizedCornerTrait & NormalizedIsLayerTrait,
67
+ ) => string | TDimension | undefined;
68
+ topRightRadius: (
69
+ node: NormalizedCornerTrait & NormalizedIsLayerTrait,
70
+ ) => string | TDimension | undefined;
71
+ bottomLeftRadius: (
72
+ node: NormalizedCornerTrait & NormalizedIsLayerTrait,
73
+ ) => string | TDimension | undefined;
74
+ bottomRightRadius: (
75
+ node: NormalizedCornerTrait & NormalizedIsLayerTrait,
76
+ ) => string | TDimension | undefined;
77
+ fontSize: (
78
+ node: NormalizedTypePropertiesTrait & NormalizedIsLayerTrait,
79
+ ) => string | TFontDimension | undefined;
80
+ fontWeight: (
81
+ node: NormalizedTypePropertiesTrait & NormalizedIsLayerTrait,
82
+ ) => string | TFontWeight | undefined;
83
+ lineHeight: (
84
+ node: NormalizedTypePropertiesTrait & NormalizedIsLayerTrait,
85
+ ) => string | TFontDimension | undefined;
86
+ };
87
+ }
88
+
89
+ export interface ValueTransformerDeps<TColor, TDimension, TFontDimension, TFontWeight> {
90
+ variableService: VariableService;
91
+ formatters: {
92
+ color: (value: RGBA) => string | TColor;
93
+ dimension: (value: number) => string | TDimension;
94
+ fontDimension: (value: number) => string | TFontDimension;
95
+ fontWeight: (value: number) => string | TFontWeight;
96
+ };
97
+ shouldInferVariableName: boolean;
98
+ }
99
+
100
+ export function createValueTransformer<TColor, TDimension, TFontDimension, TFontWeight>({
101
+ variableService,
102
+ formatters,
103
+ shouldInferVariableName,
104
+ }: ValueTransformerDeps<TColor, TDimension, TFontDimension, TFontWeight>): ValueTransformer<
105
+ TColor,
106
+ TDimension,
107
+ TFontDimension,
108
+ TFontWeight
109
+ > {
110
+ function processColor(
111
+ key: string | undefined,
112
+ value: RGBA | undefined,
113
+ scope: "FRAME_FILL" | "SHAPE_FILL" | "STROKE_COLOR" | "TEXT_FILL",
114
+ ) {
115
+ if (key) {
116
+ return variableService.getVariableName(key);
117
+ }
118
+
119
+ if (value) {
120
+ if (shouldInferVariableName) {
121
+ return variableService.inferVariableName(value, scope) ?? formatters.color(value);
122
+ }
123
+
124
+ return formatters.color(value);
125
+ }
126
+
127
+ return undefined;
128
+ }
129
+
130
+ function processDimension(
131
+ key: string | undefined,
132
+ value: number | undefined,
133
+ scope: "WIDTH_HEIGHT" | "GAP" | "CORNER_RADIUS",
134
+ ) {
135
+ if (key) {
136
+ return variableService.getVariableName(key);
137
+ }
138
+
139
+ if (value) {
140
+ if (shouldInferVariableName) {
141
+ return variableService.inferVariableName(value, scope) ?? formatters.dimension(value);
142
+ }
143
+
144
+ return formatters.dimension(value);
145
+ }
146
+
147
+ return undefined;
148
+ }
149
+
150
+ function processFontDimension(
151
+ key: string | undefined,
152
+ value: number | undefined,
153
+ scope: "FONT_SIZE" | "LINE_HEIGHT",
154
+ ) {
155
+ if (key) {
156
+ return variableService.getVariableName(key);
157
+ }
158
+
159
+ if (value) {
160
+ if (shouldInferVariableName) {
161
+ return variableService.inferVariableName(value, scope) ?? formatters.fontDimension(value);
162
+ }
163
+
164
+ return formatters.fontDimension(value);
165
+ }
166
+
167
+ return undefined;
168
+ }
169
+
170
+ function processFontWeight(key: string | undefined, value: number | undefined) {
171
+ if (key) {
172
+ return variableService.getVariableName(key);
173
+ }
174
+
175
+ if (value) {
176
+ if (shouldInferVariableName) {
177
+ const fontWeightToString: Record<number, string> = {
178
+ 100: "thin",
179
+ 200: "extra-light",
180
+ 300: "light",
181
+ 400: "regular",
182
+ 500: "medium",
183
+ 600: "semi-bold",
184
+ 700: "bold",
185
+ 800: "extra-bold",
186
+ 900: "black",
187
+ };
188
+
189
+ return (
190
+ variableService.inferVariableName(value, "FONT_WEIGHT") ??
191
+ variableService.inferVariableName(fontWeightToString[value], "FONT_STYLE") ??
192
+ formatters.fontWeight(value)
193
+ );
194
+ }
195
+
196
+ return formatters.fontWeight(value);
197
+ }
198
+
199
+ return undefined;
200
+ }
201
+
202
+ const getFormattedValue: ValueTransformer<
203
+ TColor,
204
+ TDimension,
205
+ TFontDimension,
206
+ TFontWeight
207
+ >["getFormattedValue"] = {
208
+ width: (node) =>
209
+ processDimension(
210
+ node.boundVariables?.size?.x?.id,
211
+ node.absoluteBoundingBox?.width,
212
+ "WIDTH_HEIGHT",
213
+ ),
214
+ height: (node) =>
215
+ processDimension(
216
+ node.boundVariables?.size?.y?.id,
217
+ node.absoluteBoundingBox?.height,
218
+ "WIDTH_HEIGHT",
219
+ ),
220
+ minWidth: (node) =>
221
+ processDimension(node.boundVariables?.minWidth?.id, node.minWidth, "WIDTH_HEIGHT"),
222
+ minHeight: (node) =>
223
+ processDimension(node.boundVariables?.minHeight?.id, node.minHeight, "WIDTH_HEIGHT"),
224
+ maxWidth: (node) =>
225
+ processDimension(node.boundVariables?.maxWidth?.id, node.maxWidth, "WIDTH_HEIGHT"),
226
+ maxHeight: (node) =>
227
+ processDimension(node.boundVariables?.maxHeight?.id, node.maxHeight, "WIDTH_HEIGHT"),
228
+ paddingLeft: (node) =>
229
+ processDimension(node.boundVariables?.paddingLeft?.id, node.paddingLeft, "GAP"),
230
+ paddingRight: (node) =>
231
+ processDimension(node.boundVariables?.paddingRight?.id, node.paddingRight, "GAP"),
232
+ paddingTop: (node) =>
233
+ processDimension(node.boundVariables?.paddingTop?.id, node.paddingTop, "GAP"),
234
+ paddingBottom: (node) =>
235
+ processDimension(node.boundVariables?.paddingBottom?.id, node.paddingBottom, "GAP"),
236
+ itemSpacing: (node) =>
237
+ processDimension(node.boundVariables?.itemSpacing?.id, node.itemSpacing, "GAP"),
238
+ frameFill: (node) =>
239
+ processColor(getFirstFillVariable(node)?.id, getFirstSolidFill(node)?.color, "FRAME_FILL"),
240
+ shapeFill: (node) =>
241
+ processColor(getFirstFillVariable(node)?.id, getFirstSolidFill(node)?.color, "SHAPE_FILL"),
242
+ textFill: (node) =>
243
+ processColor(getFirstFillVariable(node)?.id, getFirstSolidFill(node)?.color, "TEXT_FILL"),
244
+ stroke: (node) =>
245
+ processColor(getFirstStrokeVariable(node)?.id, getFirstStroke(node)?.color, "STROKE_COLOR"),
246
+ topLeftRadius: (node) =>
247
+ processDimension(
248
+ node.boundVariables?.topLeftRadius?.id,
249
+ node.rectangleCornerRadii?.[0] ?? node.cornerRadius,
250
+ "CORNER_RADIUS",
251
+ ),
252
+ topRightRadius: (node) =>
253
+ processDimension(
254
+ node.boundVariables?.topRightRadius?.id,
255
+ node.rectangleCornerRadii?.[1] ?? node.cornerRadius,
256
+ "CORNER_RADIUS",
257
+ ),
258
+ bottomLeftRadius: (node) =>
259
+ processDimension(
260
+ node.boundVariables?.bottomLeftRadius?.id,
261
+ node.rectangleCornerRadii?.[2] ?? node.cornerRadius,
262
+ "CORNER_RADIUS",
263
+ ),
264
+ bottomRightRadius: (node) =>
265
+ processDimension(
266
+ node.boundVariables?.bottomRightRadius?.id,
267
+ node.rectangleCornerRadii?.[3] ?? node.cornerRadius,
268
+ "CORNER_RADIUS",
269
+ ),
270
+ fontSize: (node) =>
271
+ processFontDimension(
272
+ node.boundVariables?.fontSize?.[0]?.id,
273
+ node.style.fontSize,
274
+ "FONT_SIZE",
275
+ ),
276
+ fontWeight: (node) =>
277
+ processFontWeight(node.boundVariables?.fontWeight?.[0]?.id, node.style.fontWeight),
278
+ lineHeight: (node) =>
279
+ processFontDimension(
280
+ node.boundVariables?.lineHeight?.[0]?.id,
281
+ node.style.lineHeightPx,
282
+ "LINE_HEIGHT",
283
+ ),
284
+ };
285
+
286
+ return {
287
+ getFormattedValue,
288
+ };
289
+ }
@@ -1,13 +1,46 @@
1
1
  export * from "./core";
2
- export * from "./domain";
2
+ export * from "./targets";
3
3
 
4
4
  import type { NormalizedSceneNode } from "@/normalizer";
5
- import { codegenService, devCodegenService } from "./context";
5
+ import { stringifyElement } from "./core/jsx";
6
+ import { figma, react } from "./targets";
6
7
 
7
- export function generateJsxTree(node: NormalizedSceneNode) {
8
- return codegenService.transform(node);
8
+ export function generateJsxTree(
9
+ node: NormalizedSceneNode,
10
+ options: Partial<react.CreateContextOptions> = {},
11
+ ) {
12
+ const { shouldInferVariableName = true, shouldInferAutoLayout = true } = options;
13
+ const codegen = react.createContext({
14
+ shouldInferVariableName,
15
+ shouldInferAutoLayout,
16
+ });
17
+
18
+ return codegen(node);
19
+ }
20
+
21
+ export function generateCode(
22
+ node: NormalizedSceneNode,
23
+ options: Partial<react.CreateContextOptions> & { shouldPrintSource?: boolean } = {},
24
+ ) {
25
+ const result = generateJsxTree(node, options);
26
+ return result ? stringifyElement(result, { printSource: options.shouldPrintSource }) : undefined;
9
27
  }
10
28
 
11
- export function generateCode(node: NormalizedSceneNode, { dev }: { dev?: boolean } = {}) {
12
- return dev ? devCodegenService.transformToString(node) : codegenService.transformToString(node);
29
+ export function generateFigmaSummary(
30
+ node: NormalizedSceneNode,
31
+ options: Partial<figma.CreateContextOptions> & { shouldPrintSource?: boolean } = {},
32
+ ) {
33
+ const {
34
+ shouldInferVariableName = false,
35
+ shouldPrintSource = false,
36
+ shouldInferAutoLayout = false,
37
+ } = options;
38
+ const codegen = figma.createContext({
39
+ shouldInferVariableName,
40
+ shouldInferAutoLayout,
41
+ });
42
+
43
+ const result = codegen(node);
44
+
45
+ return result ? stringifyElement(result, { printSource: shouldPrintSource }) : undefined;
13
46
  }
@@ -0,0 +1,139 @@
1
+ import { createCodegenTransformer, createValueTransformer } from "@/codegen/core";
2
+ import {
3
+ createStyleService,
4
+ createVariableService,
5
+ styleRepository,
6
+ variableRepository,
7
+ } from "@/entities";
8
+ import { toCssRgba } from "@/utils/css";
9
+ import { createFrameTransformer } from "./frame";
10
+ import { createInstanceTransformer } from "./instance";
11
+ import {
12
+ createContainerLayoutPropsTransformer,
13
+ createFrameFillPropsTransformer,
14
+ createRadiusPropsTransformer,
15
+ createSelfLayoutPropsTransformer,
16
+ createShapeFillPropsTransformer,
17
+ createStrokePropsTransformer,
18
+ createTextFillPropsTransformer,
19
+ createTypeStylePropsTransformer,
20
+ } from "./props";
21
+ import {
22
+ createBooleanOperationTransformer,
23
+ createRectangleTransformer,
24
+ createVectorTransformer,
25
+ } from "./shape";
26
+ import { createTextTransformer } from "./text";
27
+
28
+ export interface CreateContextOptions {
29
+ ignoredComponentKeys?: Set<string>;
30
+ shouldInferVariableName: boolean;
31
+ shouldInferAutoLayout: boolean;
32
+ }
33
+
34
+ const styleService = createStyleService({
35
+ styleRepository,
36
+ styleNameTransformer: ({ slug }) => slug[slug.length - 1]!,
37
+ });
38
+ const variableService = createVariableService({
39
+ variableRepository,
40
+ variableNameTransformer: ({ slug }) =>
41
+ slug
42
+ .filter((s) => s !== "dimension")
43
+ .map((s) => s.replaceAll(",", "_"))
44
+ .join("/"),
45
+ inferCompareFunction: (name1: string, name2: string) => {
46
+ const scoreFn = (name: string) => {
47
+ let score = 0;
48
+ if (name.includes("bg")) {
49
+ score += 100;
50
+ }
51
+ if (name.includes("fg")) {
52
+ score += 100;
53
+ }
54
+ if (name.includes("stroke")) {
55
+ score += 100;
56
+ }
57
+ if (name.includes("spacing-x")) {
58
+ score -= 100;
59
+ }
60
+ if (name.includes("spacing-y")) {
61
+ score -= 100;
62
+ }
63
+ if (name.endsWith("pressed")) {
64
+ score -= 100;
65
+ }
66
+ return score;
67
+ };
68
+
69
+ return scoreFn(name2) - scoreFn(name1);
70
+ },
71
+ });
72
+
73
+ export function createContext(options: CreateContextOptions) {
74
+ const { shouldInferVariableName, shouldInferAutoLayout } = options;
75
+
76
+ const valueTransformer = createValueTransformer({
77
+ variableService,
78
+ formatters: {
79
+ color: (value: RGBA) => toCssRgba(value),
80
+ dimension: (value: number) => value,
81
+ fontDimension: (value: number) => value,
82
+ fontWeight: (value: number) => value,
83
+ },
84
+ shouldInferVariableName,
85
+ });
86
+
87
+ const containerLayoutPropsTransformer = createContainerLayoutPropsTransformer(valueTransformer);
88
+ const selfLayoutPropsTransformer = createSelfLayoutPropsTransformer(valueTransformer);
89
+ const frameFillPropsTransformer = createFrameFillPropsTransformer(valueTransformer);
90
+ const shapeFillPropsTransformer = createShapeFillPropsTransformer(valueTransformer);
91
+ const textFillPropsTransformer = createTextFillPropsTransformer(valueTransformer);
92
+ const radiusPropsTransformer = createRadiusPropsTransformer(valueTransformer);
93
+ const strokePropsTransformer = createStrokePropsTransformer(valueTransformer);
94
+ const typeStylePropsTransformer = createTypeStylePropsTransformer({
95
+ valueTransformer,
96
+ styleService,
97
+ });
98
+ const propsTransformers = {
99
+ containerLayout: containerLayoutPropsTransformer,
100
+ selfLayout: selfLayoutPropsTransformer,
101
+ frameFill: frameFillPropsTransformer,
102
+ shapeFill: shapeFillPropsTransformer,
103
+ textFill: textFillPropsTransformer,
104
+ radius: radiusPropsTransformer,
105
+ stroke: strokePropsTransformer,
106
+ typeStyle: typeStylePropsTransformer,
107
+ };
108
+
109
+ const frameTransformer = createFrameTransformer({
110
+ propsTransformers,
111
+ });
112
+ const instanceTransformer = createInstanceTransformer({
113
+ frameTransformer,
114
+ });
115
+ const textTransformer = createTextTransformer({
116
+ propsTransformers,
117
+ });
118
+ const rectangleTransformer = createRectangleTransformer({
119
+ propsTransformers,
120
+ });
121
+ const vectorTransformer = createVectorTransformer({
122
+ propsTransformers,
123
+ });
124
+ const booleanOperationTransformer = createBooleanOperationTransformer({
125
+ propsTransformers,
126
+ });
127
+
128
+ const codegenTransformer = createCodegenTransformer({
129
+ frameTransformer,
130
+ textTransformer,
131
+ rectangleTransformer,
132
+ instanceTransformer,
133
+ vectorTransformer,
134
+ booleanOperationTransformer,
135
+ shouldInferAutoLayout,
136
+ });
137
+
138
+ return codegenTransformer;
139
+ }
@@ -0,0 +1,37 @@
1
+ import type {
2
+ NormalizedComponentNode,
3
+ NormalizedFrameNode,
4
+ NormalizedInstanceNode,
5
+ } from "@/normalizer";
6
+ import { createElement, defineElementTransformer, type ElementTransformer } from "../../core";
7
+ import type { PropsTransformers } from "./props";
8
+
9
+ export interface FrameTransformerDeps {
10
+ propsTransformers: PropsTransformers;
11
+ }
12
+
13
+ export function createFrameTransformer({
14
+ propsTransformers,
15
+ }: FrameTransformerDeps): ElementTransformer<
16
+ NormalizedFrameNode | NormalizedInstanceNode | NormalizedComponentNode
17
+ > {
18
+ return defineElementTransformer(
19
+ (node: NormalizedFrameNode | NormalizedInstanceNode | NormalizedComponentNode, traverse) => {
20
+ const children = node.children;
21
+
22
+ const props = {
23
+ ...propsTransformers.radius(node, traverse),
24
+ ...propsTransformers.containerLayout(node, traverse),
25
+ ...propsTransformers.selfLayout(node, traverse),
26
+ ...propsTransformers.frameFill(node, traverse),
27
+ ...propsTransformers.stroke(node, traverse),
28
+ };
29
+
30
+ return createElement(
31
+ "Frame",
32
+ props,
33
+ children.map((child) => traverse(child)),
34
+ );
35
+ },
36
+ );
37
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./context";
2
+ export * from "./frame";
3
+ export * from "./instance";
4
+ export * from "./props";
5
+ export * from "./shape";
6
+ export * from "./text";
@@ -0,0 +1,16 @@
1
+ import type { NormalizedInstanceNode } from "@/normalizer";
2
+ import { defineElementTransformer, type ElementTransformer } from "../../core";
3
+
4
+ export interface InstanceTransformerDeps {
5
+ frameTransformer: ElementTransformer<NormalizedInstanceNode>;
6
+ }
7
+
8
+ export function createInstanceTransformer({
9
+ frameTransformer,
10
+ }: InstanceTransformerDeps): ElementTransformer<NormalizedInstanceNode> {
11
+ const transform = defineElementTransformer((node: NormalizedInstanceNode, traverse) => {
12
+ return frameTransformer(node, traverse);
13
+ });
14
+
15
+ return transform;
16
+ }