@seed-design/figma 0.0.20 → 0.0.22

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 (87) hide show
  1. package/lib/codegen/index.cjs +8019 -0
  2. package/lib/codegen/index.d.ts +1827 -0
  3. package/lib/codegen/index.js +7989 -0
  4. package/lib/codegen/targets/react/index.cjs +12205 -0
  5. package/lib/codegen/targets/react/index.d.ts +270 -0
  6. package/lib/codegen/targets/react/index.js +12187 -0
  7. package/lib/index.cjs +86 -2741
  8. package/lib/index.d.ts +18 -1933
  9. package/lib/index.js +68 -2715
  10. package/package.json +18 -9
  11. package/src/codegen/{targets/react/component/properties.type.ts → component-properties.ts} +43 -43
  12. package/src/codegen/core/codegen.ts +24 -9
  13. package/src/codegen/core/{component.ts → component-handler.ts} +3 -3
  14. package/src/codegen/core/component-type-helper.ts +35 -0
  15. package/src/codegen/core/context.ts +20 -0
  16. package/src/codegen/core/index.ts +16 -14
  17. package/src/codegen/core/infer-layout.test.ts +17 -16
  18. package/src/codegen/core/infer-layout.ts +1 -1
  19. package/src/codegen/core/{props.ts → props-converter.ts} +10 -13
  20. package/src/codegen/core/{value.ts → value-resolver.ts} +90 -52
  21. package/src/codegen/default-services.ts +44 -0
  22. package/src/codegen/index.ts +1 -44
  23. package/src/codegen/targets/figma/frame.ts +8 -8
  24. package/src/codegen/targets/figma/index.ts +1 -1
  25. package/src/codegen/targets/figma/pipeline.ts +71 -0
  26. package/src/codegen/targets/figma/props.ts +59 -70
  27. package/src/codegen/targets/figma/shape.ts +18 -18
  28. package/src/codegen/targets/figma/text.ts +6 -6
  29. package/src/codegen/targets/figma/value-resolver.ts +22 -0
  30. package/src/codegen/targets/react/component/deps.interface.ts +5 -4
  31. package/src/codegen/targets/react/component/{transformers → handlers}/action-button.ts +8 -14
  32. package/src/codegen/targets/react/component/{transformers → handlers}/action-chip.ts +10 -20
  33. package/src/codegen/targets/react/component/{transformers → handlers}/action-sheet.ts +13 -10
  34. package/src/codegen/targets/react/component/{transformers → handlers}/app-bar.ts +28 -36
  35. package/src/codegen/targets/react/component/handlers/avatar-stack.ts +29 -0
  36. package/src/codegen/targets/react/component/{transformers → handlers}/avatar.ts +12 -9
  37. package/src/codegen/targets/react/component/handlers/badge.ts +18 -0
  38. package/src/codegen/targets/react/component/{transformers → handlers}/callout.ts +6 -8
  39. package/src/codegen/targets/react/component/{transformers → handlers}/checkbox.ts +5 -5
  40. package/src/codegen/targets/react/component/{transformers → handlers}/chip-tabs.ts +10 -10
  41. package/src/codegen/targets/react/component/{transformers → handlers}/control-chip.ts +10 -20
  42. package/src/codegen/targets/react/component/{transformers → handlers}/error-state.ts +9 -9
  43. package/src/codegen/targets/react/component/{transformers → handlers}/extended-action-sheet.ts +16 -18
  44. package/src/codegen/targets/react/component/{transformers → handlers}/extended-fab.ts +6 -6
  45. package/src/codegen/targets/react/component/handlers/fab.ts +18 -0
  46. package/src/codegen/targets/react/component/{transformers → handlers}/help-bubble.ts +5 -5
  47. package/src/codegen/targets/react/component/{transformers → handlers}/identity-placeholder.ts +5 -5
  48. package/src/codegen/targets/react/component/{transformers → handlers}/inline-banner.ts +7 -10
  49. package/src/codegen/targets/react/component/{transformers → handlers}/manner-temp-badge.ts +5 -5
  50. package/src/codegen/targets/react/component/{transformers → handlers}/multiline-text-field.ts +5 -5
  51. package/src/codegen/targets/react/component/{transformers → handlers}/progress-circle.ts +5 -5
  52. package/src/codegen/targets/react/component/{transformers → handlers}/reaction-button.ts +6 -6
  53. package/src/codegen/targets/react/component/{transformers → handlers}/segmented-control.ts +10 -10
  54. package/src/codegen/targets/react/component/{transformers → handlers}/select-box.ts +10 -10
  55. package/src/codegen/targets/react/component/handlers/skeleton.ts +25 -0
  56. package/src/codegen/targets/react/component/{transformers → handlers}/snackbar.ts +5 -5
  57. package/src/codegen/targets/react/component/{transformers → handlers}/switch.ts +5 -5
  58. package/src/codegen/targets/react/component/{transformers → handlers}/tabs.ts +15 -15
  59. package/src/codegen/targets/react/component/{transformers → handlers}/text-button.ts +7 -13
  60. package/src/codegen/targets/react/component/{transformers → handlers}/text-field.ts +9 -9
  61. package/src/codegen/targets/react/component/{transformers → handlers}/toggle-button.ts +7 -11
  62. package/src/codegen/targets/react/component/index.ts +79 -75
  63. package/src/codegen/targets/react/frame.ts +8 -8
  64. package/src/codegen/targets/react/icon.ts +50 -0
  65. package/src/codegen/targets/react/index.ts +1 -1
  66. package/src/codegen/targets/react/instance.ts +19 -50
  67. package/src/codegen/targets/react/pipeline.ts +108 -0
  68. package/src/codegen/targets/react/props.ts +95 -73
  69. package/src/codegen/targets/react/shape.ts +5 -5
  70. package/src/codegen/targets/react/text.ts +6 -6
  71. package/src/codegen/targets/react/value-resolver.ts +35 -0
  72. package/src/entities/icon.repository.ts +2 -2
  73. package/src/entities/icon.service.ts +9 -20
  74. package/src/entities/style.service.ts +5 -17
  75. package/src/entities/variable.service.ts +36 -68
  76. package/src/normalizer/from-plugin.ts +3 -0
  77. package/src/normalizer/from-rest.ts +6 -0
  78. package/src/normalizer/types.ts +4 -1
  79. package/src/utils/figma-variable.ts +39 -3
  80. package/src/codegen/core/component.types.ts +0 -29
  81. package/src/codegen/targets/figma/context.ts +0 -139
  82. package/src/codegen/targets/react/component/transformers/avatar-stack.ts +0 -29
  83. package/src/codegen/targets/react/component/transformers/badge.ts +0 -21
  84. package/src/codegen/targets/react/component/transformers/fab.ts +0 -18
  85. package/src/codegen/targets/react/component/transformers/skeleton.ts +0 -51
  86. package/src/codegen/targets/react/context.ts +0 -176
  87. /package/src/codegen/core/{element.ts → element-transformer.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-design/figma",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/daangn/seed-design.git",
@@ -14,6 +14,16 @@
14
14
  "types": "./lib/index.d.ts",
15
15
  "import": "./lib/index.js",
16
16
  "require": "./lib/index.cjs"
17
+ },
18
+ "./codegen": {
19
+ "types": "./lib/codegen/index.d.ts",
20
+ "import": "./lib/codegen/index.js",
21
+ "require": "./lib/codegen/index.cjs"
22
+ },
23
+ "./codegen/targets/react": {
24
+ "types": "./lib/codegen/targets/react/index.d.ts",
25
+ "import": "./lib/codegen/targets/react/index.js",
26
+ "require": "./lib/codegen/targets/react/index.cjs"
17
27
  }
18
28
  },
19
29
  "main": "./lib/index.cjs",
@@ -28,16 +38,15 @@
28
38
  "lint:publish": "bun publint"
29
39
  },
30
40
  "dependencies": {
31
- "@create-figma-plugin/utilities": "^3.0.2",
32
- "@seed-design/css": "0.0.19",
33
- "change-case": "^5.2.0",
34
- "ts-pattern": "^5.2.0"
41
+ "@seed-design/css": "0.0.21",
42
+ "change-case": "^5.4.4",
43
+ "ts-pattern": "^5.7.0"
35
44
  },
36
45
  "devDependencies": {
37
- "@figma/plugin-typings": "^1.108.0",
38
- "@figma/rest-api-spec": "^0.23.0",
39
- "@seed-design/figma-extractor": "^0.0.3",
40
- "typescript": "^5.4.5"
46
+ "@figma/plugin-typings": "^1.110.0",
47
+ "@figma/rest-api-spec": "^0.29.0",
48
+ "@seed-design/figma-extractor": "^0.0.4",
49
+ "typescript": "^5.8.3"
41
50
  },
42
51
  "publishConfig": {
43
52
  "access": "public"
@@ -1,19 +1,19 @@
1
- import type { InferFromDefinition } from "@/codegen/core";
1
+ import type { InferComponentDefinition } from "@/codegen/core";
2
2
  import type * as metadata from "@/entities/data/__generated__/component-sets";
3
3
 
4
- export type ActionButtonProperties = InferFromDefinition<
4
+ export type ActionButtonProperties = InferComponentDefinition<
5
5
  typeof metadata.actionButton.componentPropertyDefinitions
6
6
  >;
7
7
 
8
- export type ActionChipProperties = InferFromDefinition<
8
+ export type ActionChipProperties = InferComponentDefinition<
9
9
  typeof metadata.actionChip.componentPropertyDefinitions
10
10
  >;
11
11
 
12
- export type ActionSheetProperties = InferFromDefinition<
12
+ export type ActionSheetProperties = InferComponentDefinition<
13
13
  typeof metadata.actionSheet.componentPropertyDefinitions
14
14
  >;
15
15
 
16
- export type ActionSheetItemProperties = InferFromDefinition<{
16
+ export type ActionSheetItemProperties = InferComponentDefinition<{
17
17
  "Label#15420:4": {
18
18
  type: "TEXT";
19
19
  defaultValue: "액션 버튼";
@@ -30,31 +30,31 @@ export type ActionSheetItemProperties = InferFromDefinition<{
30
30
  };
31
31
  }>;
32
32
 
33
- export type AvatarProperties = InferFromDefinition<
33
+ export type AvatarProperties = InferComponentDefinition<
34
34
  typeof metadata.avatar.componentPropertyDefinitions
35
35
  >;
36
36
 
37
- export type AvatarStackProperties = InferFromDefinition<
37
+ export type AvatarStackProperties = InferComponentDefinition<
38
38
  typeof metadata.avatarStack.componentPropertyDefinitions
39
39
  >;
40
40
 
41
- export type BadgeProperties = InferFromDefinition<
41
+ export type BadgeProperties = InferComponentDefinition<
42
42
  typeof metadata.badge.componentPropertyDefinitions
43
43
  >;
44
44
 
45
- export type CalloutProperties = InferFromDefinition<
45
+ export type CalloutProperties = InferComponentDefinition<
46
46
  typeof metadata.callout.componentPropertyDefinitions
47
47
  >;
48
48
 
49
- export type CheckboxProperties = InferFromDefinition<
49
+ export type CheckboxProperties = InferComponentDefinition<
50
50
  typeof metadata.checkbox.componentPropertyDefinitions
51
51
  >;
52
52
 
53
- export type ChipTabsProperties = InferFromDefinition<
53
+ export type ChipTabsProperties = InferComponentDefinition<
54
54
  typeof metadata.chipTablist.componentPropertyDefinitions
55
55
  >;
56
56
 
57
- export type ChipTabsItemProperties = InferFromDefinition<{
57
+ export type ChipTabsItemProperties = InferComponentDefinition<{
58
58
  "Label#8876:0": {
59
59
  type: "TEXT";
60
60
  defaultValue: "라벨";
@@ -78,19 +78,19 @@ export type ChipTabsItemProperties = InferFromDefinition<{
78
78
  };
79
79
  }>;
80
80
 
81
- export type ControlChipProperties = InferFromDefinition<
81
+ export type ControlChipProperties = InferComponentDefinition<
82
82
  typeof metadata.controlChip.componentPropertyDefinitions
83
83
  >;
84
84
 
85
- export type ErrorStateProperties = InferFromDefinition<
85
+ export type ErrorStateProperties = InferComponentDefinition<
86
86
  typeof metadata.errorState.componentPropertyDefinitions
87
87
  >;
88
88
 
89
- export type ExtendedActionSheetProperties = InferFromDefinition<
89
+ export type ExtendedActionSheetProperties = InferComponentDefinition<
90
90
  typeof metadata.extendedActionSheet.componentPropertyDefinitions
91
91
  >;
92
92
 
93
- export type ExtendedActionSheetGroupProperties = InferFromDefinition<{
93
+ export type ExtendedActionSheetGroupProperties = InferComponentDefinition<{
94
94
  "Action Count": {
95
95
  type: "VARIANT";
96
96
  defaultValue: "8";
@@ -98,7 +98,7 @@ export type ExtendedActionSheetGroupProperties = InferFromDefinition<{
98
98
  };
99
99
  }>;
100
100
 
101
- export type ExtendedActionSheetItemProperties = InferFromDefinition<{
101
+ export type ExtendedActionSheetItemProperties = InferComponentDefinition<{
102
102
  "Show Prefix Icon#17043:5": {
103
103
  type: "BOOLEAN";
104
104
  defaultValue: true;
@@ -124,47 +124,47 @@ export type ExtendedActionSheetItemProperties = InferFromDefinition<{
124
124
  };
125
125
  }>;
126
126
 
127
- export type ExtendedFabProperties = InferFromDefinition<
127
+ export type ExtendedFabProperties = InferComponentDefinition<
128
128
  typeof metadata.extendedFloatingActionButton.componentPropertyDefinitions
129
129
  >;
130
130
 
131
- export type FabProperties = InferFromDefinition<
131
+ export type FabProperties = InferComponentDefinition<
132
132
  typeof metadata.floatingActionButton.componentPropertyDefinitions
133
133
  >;
134
134
 
135
- export type HelpBubbleProperties = InferFromDefinition<
135
+ export type HelpBubbleProperties = InferComponentDefinition<
136
136
  typeof metadata.helpBubble.componentPropertyDefinitions
137
137
  >;
138
138
 
139
- export type IdentityPlaceholderProperties = InferFromDefinition<
139
+ export type IdentityPlaceholderProperties = InferComponentDefinition<
140
140
  typeof metadata.identityPlaceholder.componentPropertyDefinitions
141
141
  >;
142
142
 
143
- export type InlineBannerProperties = InferFromDefinition<
143
+ export type InlineBannerProperties = InferComponentDefinition<
144
144
  typeof metadata.inlineBanner.componentPropertyDefinitions
145
145
  >;
146
146
 
147
- export type MannerTempBadgeProperties = InferFromDefinition<
147
+ export type MannerTempBadgeProperties = InferComponentDefinition<
148
148
  typeof metadata.mannerTempBadge.componentPropertyDefinitions
149
149
  >;
150
150
 
151
- export type MultilineTextFieldProperties = InferFromDefinition<
151
+ export type MultilineTextFieldProperties = InferComponentDefinition<
152
152
  typeof metadata.multilineTextField.componentPropertyDefinitions
153
153
  >;
154
154
 
155
- export type ProgressCircleProperties = InferFromDefinition<
155
+ export type ProgressCircleProperties = InferComponentDefinition<
156
156
  typeof metadata.progressCircle.componentPropertyDefinitions
157
157
  >;
158
158
 
159
- export type ReactionButtonProperties = InferFromDefinition<
159
+ export type ReactionButtonProperties = InferComponentDefinition<
160
160
  typeof metadata.reactionButton.componentPropertyDefinitions
161
161
  >;
162
162
 
163
- export type SegmentedControlProperties = InferFromDefinition<
163
+ export type SegmentedControlProperties = InferComponentDefinition<
164
164
  typeof metadata.segmentedControl.componentPropertyDefinitions
165
165
  >;
166
166
 
167
- export type SegmentedControlItemProperties = InferFromDefinition<{
167
+ export type SegmentedControlItemProperties = InferComponentDefinition<{
168
168
  "Label#11366:15": {
169
169
  type: "TEXT";
170
170
  defaultValue: "라벨";
@@ -183,31 +183,31 @@ export type SegmentedControlItemProperties = InferFromDefinition<{
183
183
  };
184
184
  }>;
185
185
 
186
- export type SelectBoxGroupProperties = InferFromDefinition<
186
+ export type SelectBoxGroupProperties = InferComponentDefinition<
187
187
  typeof metadata.templateSelectBoxGroup.componentPropertyDefinitions
188
188
  >;
189
189
 
190
- export type SelectBoxProperties = InferFromDefinition<
190
+ export type SelectBoxProperties = InferComponentDefinition<
191
191
  typeof metadata.selectBox.componentPropertyDefinitions
192
192
  >;
193
193
 
194
- export type SkeletonProperties = InferFromDefinition<
194
+ export type SkeletonProperties = InferComponentDefinition<
195
195
  typeof metadata.skeleton.componentPropertyDefinitions
196
196
  >;
197
197
 
198
- export type SnackbarProperties = InferFromDefinition<
198
+ export type SnackbarProperties = InferComponentDefinition<
199
199
  typeof metadata.snackbar.componentPropertyDefinitions
200
200
  >;
201
201
 
202
- export type SwitchProperties = InferFromDefinition<
202
+ export type SwitchProperties = InferComponentDefinition<
203
203
  typeof metadata.switch.componentPropertyDefinitions
204
204
  >;
205
205
 
206
- export type TabsProperties = InferFromDefinition<
206
+ export type TabsProperties = InferComponentDefinition<
207
207
  typeof metadata.tablist.componentPropertyDefinitions
208
208
  >;
209
209
 
210
- export type TabsHugItemProperties = InferFromDefinition<{
210
+ export type TabsHugItemProperties = InferComponentDefinition<{
211
211
  "Label#4478:2": {
212
212
  type: "TEXT";
213
213
  defaultValue: "라벨";
@@ -229,7 +229,7 @@ export type TabsHugItemProperties = InferFromDefinition<{
229
229
  };
230
230
  }>;
231
231
 
232
- export type TabsFillItemProperties = InferFromDefinition<{
232
+ export type TabsFillItemProperties = InferComponentDefinition<{
233
233
  "Label#4478:2": {
234
234
  type: "TEXT";
235
235
  defaultValue: "라벨";
@@ -251,23 +251,23 @@ export type TabsFillItemProperties = InferFromDefinition<{
251
251
  };
252
252
  }>;
253
253
 
254
- export type TextButtonProperties = InferFromDefinition<
254
+ export type TextButtonProperties = InferComponentDefinition<
255
255
  typeof metadata.textButton.componentPropertyDefinitions
256
256
  >;
257
257
 
258
- export type TextFieldProperties = InferFromDefinition<
258
+ export type TextFieldProperties = InferComponentDefinition<
259
259
  typeof metadata.textField.componentPropertyDefinitions
260
260
  >;
261
261
 
262
- export type ToggleButtonProperties = InferFromDefinition<
262
+ export type ToggleButtonProperties = InferComponentDefinition<
263
263
  typeof metadata.toggleButton.componentPropertyDefinitions
264
264
  >;
265
265
 
266
- export type AppBarProperties = InferFromDefinition<
266
+ export type AppBarProperties = InferComponentDefinition<
267
267
  typeof metadata.standardNavigation.componentPropertyDefinitions
268
268
  >;
269
269
 
270
- export type AppBarMainProperties = InferFromDefinition<{
270
+ export type AppBarMainProperties = InferComponentDefinition<{
271
271
  "Show Right#16958:13": {
272
272
  type: "BOOLEAN";
273
273
  defaultValue: false;
@@ -301,7 +301,7 @@ export type AppBarMainProperties = InferFromDefinition<{
301
301
  };
302
302
  }>;
303
303
 
304
- export type AppBarLeftProperties = InferFromDefinition<{
304
+ export type AppBarLeftProperties = InferComponentDefinition<{
305
305
  Action: {
306
306
  type: "VARIANT";
307
307
  defaultValue: "Back";
@@ -309,7 +309,7 @@ export type AppBarLeftProperties = InferFromDefinition<{
309
309
  };
310
310
  }>;
311
311
 
312
- export type AppBarRightProperties = InferFromDefinition<{
312
+ export type AppBarRightProperties = InferComponentDefinition<{
313
313
  Type: {
314
314
  type: "VARIANT";
315
315
  defaultValue: "1 Icon";
@@ -9,11 +9,12 @@ import type {
9
9
  NormalizedVectorNode,
10
10
  } from "@/normalizer";
11
11
  import { match } from "ts-pattern";
12
- import { inferLayout, type ElementNode, type ElementTransformer } from "../core";
13
- import { appendSource, createElement } from "../core/jsx";
14
- import { applyInferredLayout } from "./infer-layout";
12
+ import { appendSource, createElement, stringifyElement, type ElementNode } from "../core/jsx";
13
+ import { codegenOptionsContext, useCodegenOptions, type CodegenOptions } from "./context";
14
+ import type { ElementTransformer } from "./element-transformer";
15
+ import { applyInferredLayout, inferLayout } from "./infer-layout";
15
16
 
16
- export interface CodegenTransformerDeps {
17
+ export interface CodeGeneratorDeps {
17
18
  frameTransformer: ElementTransformer<
18
19
  NormalizedFrameNode | NormalizedComponentNode | NormalizedInstanceNode
19
20
  >;
@@ -22,23 +23,23 @@ export interface CodegenTransformerDeps {
22
23
  instanceTransformer: ElementTransformer<NormalizedInstanceNode>;
23
24
  vectorTransformer: ElementTransformer<NormalizedVectorNode>;
24
25
  booleanOperationTransformer: ElementTransformer<NormalizedBooleanOperationNode>;
25
- shouldInferAutoLayout: boolean;
26
26
  }
27
27
 
28
- export function createCodegenTransformer({
28
+ export function createCodeGenerator({
29
29
  frameTransformer,
30
30
  textTransformer,
31
31
  rectangleTransformer,
32
32
  instanceTransformer,
33
33
  vectorTransformer,
34
34
  booleanOperationTransformer,
35
- shouldInferAutoLayout,
36
- }: CodegenTransformerDeps): (node: NormalizedSceneNode) => ElementNode | undefined {
35
+ }: CodeGeneratorDeps) {
37
36
  function traverse(node: NormalizedSceneNode): ElementNode | undefined {
38
37
  if ("visible" in node && !node.visible) {
39
38
  return;
40
39
  }
41
40
 
41
+ const { shouldInferAutoLayout } = useCodegenOptions();
42
+
42
43
  const result = match(node)
43
44
  .with({ type: "FRAME" }, (node) =>
44
45
  shouldInferAutoLayout
@@ -61,5 +62,19 @@ export function createCodegenTransformer({
61
62
  return;
62
63
  }
63
64
 
64
- return (node) => traverse(node);
65
+ function generateJsxTree(node: NormalizedSceneNode, options: CodegenOptions) {
66
+ return codegenOptionsContext.run(options, () => traverse(node));
67
+ }
68
+
69
+ function generateCode(
70
+ node: NormalizedSceneNode,
71
+ options: CodegenOptions & { shouldPrintSource: boolean },
72
+ ) {
73
+ const jsxTree = generateJsxTree(node, options);
74
+ return jsxTree
75
+ ? stringifyElement(jsxTree, { printSource: options.shouldPrintSource })
76
+ : undefined;
77
+ }
78
+
79
+ return { generateJsxTree, generateCode };
65
80
  }
@@ -1,7 +1,7 @@
1
1
  import type { NormalizedInstanceNode } from "@/normalizer";
2
2
  import type { ElementNode } from "./jsx";
3
3
 
4
- export interface ComponentTransformer<
4
+ export interface ComponentHandler<
5
5
  T extends
6
6
  NormalizedInstanceNode["componentProperties"] = NormalizedInstanceNode["componentProperties"],
7
7
  > {
@@ -9,9 +9,9 @@ export interface ComponentTransformer<
9
9
  transform: (node: NormalizedInstanceNode & { componentProperties: T }) => ElementNode;
10
10
  }
11
11
 
12
- export function defineComponentTransformer<T extends NormalizedInstanceNode["componentProperties"]>(
12
+ export function defineComponentHandler<T extends NormalizedInstanceNode["componentProperties"]>(
13
13
  key: string,
14
14
  transform: (node: NormalizedInstanceNode & { componentProperties: T }) => ElementNode,
15
- ): ComponentTransformer<T> {
15
+ ): ComponentHandler<T> {
16
16
  return { key, transform };
17
17
  }
@@ -0,0 +1,35 @@
1
+ import type { ComponentPropertyType, InstanceSwapPreferredValue } from "@figma/rest-api-spec";
2
+
3
+ export interface ComponentPropertyDefinition {
4
+ type: ComponentPropertyType;
5
+ preferredValues?: InstanceSwapPreferredValue[];
6
+ variantOptions?: string[];
7
+ }
8
+
9
+ export type InferComponentPropertyType<T extends ComponentPropertyDefinition> =
10
+ T["type"] extends "TEXT"
11
+ ? string
12
+ : T["type"] extends "BOOLEAN"
13
+ ? boolean
14
+ : T["type"] extends "INSTANCE_SWAP"
15
+ ? string
16
+ : T["type"] extends "VARIANT"
17
+ ? T["variantOptions"] extends string[]
18
+ ? T["variantOptions"][number]
19
+ : never
20
+ : never;
21
+
22
+ export type InferComponentDefinition<T extends Record<string, ComponentPropertyDefinition>> = {
23
+ [K in keyof T]: {
24
+ type: T[K]["type"];
25
+ value: InferComponentPropertyType<T[K]>;
26
+ readonly boundVariables?: {
27
+ [field in VariableBindableComponentPropertyField]?: VariableAlias;
28
+ };
29
+ } & (T[K]["type"] extends "INSTANCE_SWAP"
30
+ ? {
31
+ componentKey: string;
32
+ preferredValues: InstanceSwapPreferredValue[];
33
+ }
34
+ : {});
35
+ };
@@ -0,0 +1,20 @@
1
+ import { AsyncLocalStorage } from "async_hooks";
2
+
3
+ export interface CodegenOptions {
4
+ shouldInferAutoLayout: boolean;
5
+ shouldInferVariableName: boolean;
6
+ }
7
+
8
+ export const codegenOptionsContext = new AsyncLocalStorage<CodegenOptions>();
9
+
10
+ export function useCodegenOptions(): CodegenOptions {
11
+ const options = codegenOptionsContext.getStore();
12
+
13
+ if (!options) {
14
+ throw new Error(
15
+ "Trying to get codegen options outside of codegen context. Did you forget to call `codegenOptionsContext.run`?",
16
+ );
17
+ }
18
+
19
+ return options;
20
+ }
@@ -1,19 +1,21 @@
1
- export type { CodegenTransformerDeps } from "./codegen";
2
- export type { ComponentTransformer } from "./component";
1
+ export type { CodeGeneratorDeps } from "./codegen";
2
+ export type { ComponentHandler } from "./component-handler";
3
3
  export type {
4
4
  ComponentPropertyDefinition,
5
- InferFromDefinition,
6
- InferPropertyType,
7
- } from "./component.types";
8
- export type { ElementTransformer } from "./element";
5
+ InferComponentDefinition,
6
+ InferComponentPropertyType,
7
+ } from "./component-type-helper";
8
+ export type { CodegenOptions } from "./context";
9
+ export type { ElementTransformer } from "./element-transformer";
9
10
  export type { ElementNode } from "./jsx";
10
- export type { PropsTransformer } from "./props";
11
- export type { ValueTransformer } from "./value";
11
+ export type { PropsConverter } from "./props-converter";
12
+ export type { ValueResolver } from "./value-resolver";
12
13
 
13
- export { createCodegenTransformer } from "./codegen";
14
- export { defineComponentTransformer } from "./component";
15
- export { defineElementTransformer } from "./element";
14
+ export { createCodeGenerator } from "./codegen";
15
+ export { defineComponentHandler } from "./component-handler";
16
+ export { useCodegenOptions } from "./context";
17
+ export { defineElementTransformer } from "./element-transformer";
16
18
  export { inferLayout } from "./infer-layout";
17
- export { createElement, cloneElement } from "./jsx";
18
- export { createPropsTransformer, definePropsTransformer } from "./props";
19
- export { createValueTransformer } from "./value";
19
+ export { cloneElement, createElement } from "./jsx";
20
+ export { createPropsConverter, definePropsConverter } from "./props-converter";
21
+ export { createValueResolver } from "./value-resolver";
@@ -10,6 +10,7 @@ function createTestNode(
10
10
  ): NormalizedFrameTrait {
11
11
  return {
12
12
  id,
13
+ layoutMode: "NONE",
13
14
  absoluteBoundingBox: boundingBox,
14
15
  children,
15
16
  } as NormalizedFrameTrait;
@@ -20,7 +21,7 @@ describe("inferLayout", () => {
20
21
  it("should return NONE layout mode for a parent with no children", () => {
21
22
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 100, height: 100 });
22
23
 
23
- const result = inferLayout(parentNode);
24
+ const result = inferLayout(parentNode).properties;
24
25
 
25
26
  expect(result.layoutMode).toBe("NONE");
26
27
  });
@@ -32,7 +33,7 @@ describe("inferLayout", () => {
32
33
  childNode,
33
34
  ]);
34
35
 
35
- const result = inferLayout(parentNode);
36
+ const result = inferLayout(parentNode).properties;
36
37
 
37
38
  expect(result.layoutMode).toBe("HORIZONTAL");
38
39
  expect(result.primaryAxisSizingMode).toBe("AUTO");
@@ -55,7 +56,7 @@ describe("inferLayout", () => {
55
56
  ];
56
57
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
57
58
 
58
- const result = inferLayout(parentNode);
59
+ const result = inferLayout(parentNode).properties;
59
60
 
60
61
  expect(result.layoutMode).toBe("HORIZONTAL");
61
62
  expect(result.primaryAxisSizingMode).toBe("AUTO");
@@ -76,7 +77,7 @@ describe("inferLayout", () => {
76
77
  ];
77
78
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 100, height: 200 }, children);
78
79
 
79
- const result = inferLayout(parentNode);
80
+ const result = inferLayout(parentNode).properties;
80
81
 
81
82
  expect(result.layoutMode).toBe("VERTICAL");
82
83
  expect(result.primaryAxisSizingMode).toBe("AUTO");
@@ -97,7 +98,7 @@ describe("inferLayout", () => {
97
98
  ];
98
99
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
99
100
 
100
- const result = inferLayout(parentNode);
101
+ const result = inferLayout(parentNode).properties;
101
102
 
102
103
  expect(result.layoutMode).toBe("HORIZONTAL");
103
104
  expect(result.primaryAxisAlignItems).toBe("SPACE_BETWEEN");
@@ -114,7 +115,7 @@ describe("inferLayout", () => {
114
115
  ];
115
116
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
116
117
 
117
- const result = inferLayout(parentNode);
118
+ const result = inferLayout(parentNode).properties;
118
119
 
119
120
  expect(result.layoutMode).toBe("HORIZONTAL");
120
121
  expect(result.counterAxisAlignItems).toBe("CENTER");
@@ -129,7 +130,7 @@ describe("inferLayout", () => {
129
130
  ];
130
131
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 60 }, children);
131
132
 
132
- const result = inferLayout(parentNode);
133
+ const result = inferLayout(parentNode).properties;
133
134
 
134
135
  expect(result.layoutMode).toBe("HORIZONTAL");
135
136
  expect(result.counterAxisAlignItems).toBe("MAX");
@@ -143,7 +144,7 @@ describe("inferLayout", () => {
143
144
  ];
144
145
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
145
146
 
146
- const result = inferLayout(parentNode);
147
+ const result = inferLayout(parentNode).properties;
147
148
 
148
149
  // Based on the implementation, this actually returns "FIXED" not "AUTO"
149
150
  expect(result.counterAxisSizingMode).toBe("FIXED");
@@ -160,7 +161,7 @@ describe("inferLayout", () => {
160
161
  ];
161
162
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 100, height: 200 }, children);
162
163
 
163
- const result = inferLayout(parentNode);
164
+ const result = inferLayout(parentNode).properties;
164
165
 
165
166
  // Based on the implementation, this actually returns "HORIZONTAL" not "VERTICAL"
166
167
  // This could be due to the specific layout of the test nodes or other factors
@@ -175,7 +176,7 @@ describe("inferLayout", () => {
175
176
  ];
176
177
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 200, height: 100 }, children);
177
178
 
178
- const result = inferLayout(parentNode);
179
+ const result = inferLayout(parentNode).properties;
179
180
 
180
181
  expect(result.layoutMode).toBe("HORIZONTAL");
181
182
  // Should handle negative spacing by clamping to 0 if it's small
@@ -187,7 +188,7 @@ describe("inferLayout", () => {
187
188
  const childNode = createTestNode("child", { x: 0, y: 0, width: 50, height: 40 });
188
189
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 0, height: 0 }, [childNode]);
189
190
 
190
- const result = inferLayout(parentNode);
191
+ const result = inferLayout(parentNode).properties;
191
192
 
192
193
  // Should still give reasonable results
193
194
  expect(result.layoutMode).toBe("HORIZONTAL");
@@ -204,7 +205,7 @@ describe("inferLayout", () => {
204
205
  ];
205
206
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
206
207
 
207
- const result = inferLayout(parentNode);
208
+ const result = inferLayout(parentNode).properties;
208
209
 
209
210
  expect(result.layoutMode).toBe("HORIZONTAL");
210
211
  // Should use median of [10, 20] which is 15
@@ -220,7 +221,7 @@ describe("inferLayout", () => {
220
221
  ];
221
222
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 500, height: 100 }, children);
222
223
 
223
- const result = inferLayout(parentNode);
224
+ const result = inferLayout(parentNode).properties;
224
225
 
225
226
  expect(result.layoutMode).toBe("HORIZONTAL");
226
227
  // Check that we got some reasonable values despite the variety
@@ -237,7 +238,7 @@ describe("inferLayout", () => {
237
238
  // Container with height 200, content height 60 (2 * 20 + 20 spacing), centered at middle
238
239
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 100, height: 200 }, children);
239
240
 
240
- const result = inferLayout(parentNode);
241
+ const result = inferLayout(parentNode).properties;
241
242
 
242
243
  expect(result.layoutMode).toBe("VERTICAL");
243
244
  // While the example is set up with items that appear centered, the algorithm
@@ -261,7 +262,7 @@ describe("inferLayout", () => {
261
262
  }
262
263
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 700, height: 100 }, children);
263
264
 
264
- const result = inferLayout(parentNode);
265
+ const result = inferLayout(parentNode).properties;
265
266
 
266
267
  expect(result.layoutMode).toBe("HORIZONTAL");
267
268
  expect(result.itemSpacing).toBe(10);
@@ -276,7 +277,7 @@ describe("inferLayout", () => {
276
277
  ];
277
278
  const parentNode = createTestNode("parent", { x: 0, y: 0, width: 200, height: 200 }, children);
278
279
 
279
- const result = inferLayout(parentNode);
280
+ const result = inferLayout(parentNode).properties;
280
281
 
281
282
  // The algorithm should still pick a layout direction, likely based on bounding box
282
283
  expect(result.layoutMode).not.toBe("NONE");
@@ -107,7 +107,7 @@ export function inferLayout(parentNode: LayoutNode): InferResult {
107
107
 
108
108
  if (children.length === 0) {
109
109
  return {
110
- properties: {},
110
+ properties: result,
111
111
  childProperties: {},
112
112
  }; // Cannot infer layout for no children
113
113
  }