@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.
- package/lib/codegen/index.cjs +8019 -0
- package/lib/codegen/index.d.ts +1827 -0
- package/lib/codegen/index.js +7989 -0
- package/lib/codegen/targets/react/index.cjs +12205 -0
- package/lib/codegen/targets/react/index.d.ts +270 -0
- package/lib/codegen/targets/react/index.js +12187 -0
- package/lib/index.cjs +86 -2741
- package/lib/index.d.ts +18 -1933
- package/lib/index.js +68 -2715
- package/package.json +18 -9
- package/src/codegen/{targets/react/component/properties.type.ts → component-properties.ts} +43 -43
- package/src/codegen/core/codegen.ts +24 -9
- package/src/codegen/core/{component.ts → component-handler.ts} +3 -3
- package/src/codegen/core/component-type-helper.ts +35 -0
- package/src/codegen/core/context.ts +20 -0
- package/src/codegen/core/index.ts +16 -14
- package/src/codegen/core/infer-layout.test.ts +17 -16
- package/src/codegen/core/infer-layout.ts +1 -1
- package/src/codegen/core/{props.ts → props-converter.ts} +10 -13
- package/src/codegen/core/{value.ts → value-resolver.ts} +90 -52
- package/src/codegen/default-services.ts +44 -0
- package/src/codegen/index.ts +1 -44
- package/src/codegen/targets/figma/frame.ts +8 -8
- package/src/codegen/targets/figma/index.ts +1 -1
- package/src/codegen/targets/figma/pipeline.ts +71 -0
- package/src/codegen/targets/figma/props.ts +59 -70
- package/src/codegen/targets/figma/shape.ts +18 -18
- package/src/codegen/targets/figma/text.ts +6 -6
- package/src/codegen/targets/figma/value-resolver.ts +22 -0
- package/src/codegen/targets/react/component/deps.interface.ts +5 -4
- package/src/codegen/targets/react/component/{transformers → handlers}/action-button.ts +8 -14
- package/src/codegen/targets/react/component/{transformers → handlers}/action-chip.ts +10 -20
- package/src/codegen/targets/react/component/{transformers → handlers}/action-sheet.ts +13 -10
- package/src/codegen/targets/react/component/{transformers → handlers}/app-bar.ts +28 -36
- package/src/codegen/targets/react/component/handlers/avatar-stack.ts +29 -0
- package/src/codegen/targets/react/component/{transformers → handlers}/avatar.ts +12 -9
- package/src/codegen/targets/react/component/handlers/badge.ts +18 -0
- package/src/codegen/targets/react/component/{transformers → handlers}/callout.ts +6 -8
- package/src/codegen/targets/react/component/{transformers → handlers}/checkbox.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/chip-tabs.ts +10 -10
- package/src/codegen/targets/react/component/{transformers → handlers}/control-chip.ts +10 -20
- package/src/codegen/targets/react/component/{transformers → handlers}/error-state.ts +9 -9
- package/src/codegen/targets/react/component/{transformers → handlers}/extended-action-sheet.ts +16 -18
- package/src/codegen/targets/react/component/{transformers → handlers}/extended-fab.ts +6 -6
- package/src/codegen/targets/react/component/handlers/fab.ts +18 -0
- package/src/codegen/targets/react/component/{transformers → handlers}/help-bubble.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/identity-placeholder.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/inline-banner.ts +7 -10
- package/src/codegen/targets/react/component/{transformers → handlers}/manner-temp-badge.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/multiline-text-field.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/progress-circle.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/reaction-button.ts +6 -6
- package/src/codegen/targets/react/component/{transformers → handlers}/segmented-control.ts +10 -10
- package/src/codegen/targets/react/component/{transformers → handlers}/select-box.ts +10 -10
- package/src/codegen/targets/react/component/handlers/skeleton.ts +25 -0
- package/src/codegen/targets/react/component/{transformers → handlers}/snackbar.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/switch.ts +5 -5
- package/src/codegen/targets/react/component/{transformers → handlers}/tabs.ts +15 -15
- package/src/codegen/targets/react/component/{transformers → handlers}/text-button.ts +7 -13
- package/src/codegen/targets/react/component/{transformers → handlers}/text-field.ts +9 -9
- package/src/codegen/targets/react/component/{transformers → handlers}/toggle-button.ts +7 -11
- package/src/codegen/targets/react/component/index.ts +79 -75
- package/src/codegen/targets/react/frame.ts +8 -8
- package/src/codegen/targets/react/icon.ts +50 -0
- package/src/codegen/targets/react/index.ts +1 -1
- package/src/codegen/targets/react/instance.ts +19 -50
- package/src/codegen/targets/react/pipeline.ts +108 -0
- package/src/codegen/targets/react/props.ts +95 -73
- package/src/codegen/targets/react/shape.ts +5 -5
- package/src/codegen/targets/react/text.ts +6 -6
- package/src/codegen/targets/react/value-resolver.ts +35 -0
- package/src/entities/icon.repository.ts +2 -2
- package/src/entities/icon.service.ts +9 -20
- package/src/entities/style.service.ts +5 -17
- package/src/entities/variable.service.ts +36 -68
- package/src/normalizer/from-plugin.ts +3 -0
- package/src/normalizer/from-rest.ts +6 -0
- package/src/normalizer/types.ts +4 -1
- package/src/utils/figma-variable.ts +39 -3
- package/src/codegen/core/component.types.ts +0 -29
- package/src/codegen/targets/figma/context.ts +0 -139
- package/src/codegen/targets/react/component/transformers/avatar-stack.ts +0 -29
- package/src/codegen/targets/react/component/transformers/badge.ts +0 -21
- package/src/codegen/targets/react/component/transformers/fab.ts +0 -18
- package/src/codegen/targets/react/component/transformers/skeleton.ts +0 -51
- package/src/codegen/targets/react/context.ts +0 -176
- /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.
|
|
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
|
-
"@
|
|
32
|
-
"
|
|
33
|
-
"
|
|
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.
|
|
38
|
-
"@figma/rest-api-spec": "^0.
|
|
39
|
-
"@seed-design/figma-extractor": "^0.0.
|
|
40
|
-
"typescript": "^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 {
|
|
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 =
|
|
4
|
+
export type ActionButtonProperties = InferComponentDefinition<
|
|
5
5
|
typeof metadata.actionButton.componentPropertyDefinitions
|
|
6
6
|
>;
|
|
7
7
|
|
|
8
|
-
export type ActionChipProperties =
|
|
8
|
+
export type ActionChipProperties = InferComponentDefinition<
|
|
9
9
|
typeof metadata.actionChip.componentPropertyDefinitions
|
|
10
10
|
>;
|
|
11
11
|
|
|
12
|
-
export type ActionSheetProperties =
|
|
12
|
+
export type ActionSheetProperties = InferComponentDefinition<
|
|
13
13
|
typeof metadata.actionSheet.componentPropertyDefinitions
|
|
14
14
|
>;
|
|
15
15
|
|
|
16
|
-
export type ActionSheetItemProperties =
|
|
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 =
|
|
33
|
+
export type AvatarProperties = InferComponentDefinition<
|
|
34
34
|
typeof metadata.avatar.componentPropertyDefinitions
|
|
35
35
|
>;
|
|
36
36
|
|
|
37
|
-
export type AvatarStackProperties =
|
|
37
|
+
export type AvatarStackProperties = InferComponentDefinition<
|
|
38
38
|
typeof metadata.avatarStack.componentPropertyDefinitions
|
|
39
39
|
>;
|
|
40
40
|
|
|
41
|
-
export type BadgeProperties =
|
|
41
|
+
export type BadgeProperties = InferComponentDefinition<
|
|
42
42
|
typeof metadata.badge.componentPropertyDefinitions
|
|
43
43
|
>;
|
|
44
44
|
|
|
45
|
-
export type CalloutProperties =
|
|
45
|
+
export type CalloutProperties = InferComponentDefinition<
|
|
46
46
|
typeof metadata.callout.componentPropertyDefinitions
|
|
47
47
|
>;
|
|
48
48
|
|
|
49
|
-
export type CheckboxProperties =
|
|
49
|
+
export type CheckboxProperties = InferComponentDefinition<
|
|
50
50
|
typeof metadata.checkbox.componentPropertyDefinitions
|
|
51
51
|
>;
|
|
52
52
|
|
|
53
|
-
export type ChipTabsProperties =
|
|
53
|
+
export type ChipTabsProperties = InferComponentDefinition<
|
|
54
54
|
typeof metadata.chipTablist.componentPropertyDefinitions
|
|
55
55
|
>;
|
|
56
56
|
|
|
57
|
-
export type ChipTabsItemProperties =
|
|
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 =
|
|
81
|
+
export type ControlChipProperties = InferComponentDefinition<
|
|
82
82
|
typeof metadata.controlChip.componentPropertyDefinitions
|
|
83
83
|
>;
|
|
84
84
|
|
|
85
|
-
export type ErrorStateProperties =
|
|
85
|
+
export type ErrorStateProperties = InferComponentDefinition<
|
|
86
86
|
typeof metadata.errorState.componentPropertyDefinitions
|
|
87
87
|
>;
|
|
88
88
|
|
|
89
|
-
export type ExtendedActionSheetProperties =
|
|
89
|
+
export type ExtendedActionSheetProperties = InferComponentDefinition<
|
|
90
90
|
typeof metadata.extendedActionSheet.componentPropertyDefinitions
|
|
91
91
|
>;
|
|
92
92
|
|
|
93
|
-
export type ExtendedActionSheetGroupProperties =
|
|
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 =
|
|
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 =
|
|
127
|
+
export type ExtendedFabProperties = InferComponentDefinition<
|
|
128
128
|
typeof metadata.extendedFloatingActionButton.componentPropertyDefinitions
|
|
129
129
|
>;
|
|
130
130
|
|
|
131
|
-
export type FabProperties =
|
|
131
|
+
export type FabProperties = InferComponentDefinition<
|
|
132
132
|
typeof metadata.floatingActionButton.componentPropertyDefinitions
|
|
133
133
|
>;
|
|
134
134
|
|
|
135
|
-
export type HelpBubbleProperties =
|
|
135
|
+
export type HelpBubbleProperties = InferComponentDefinition<
|
|
136
136
|
typeof metadata.helpBubble.componentPropertyDefinitions
|
|
137
137
|
>;
|
|
138
138
|
|
|
139
|
-
export type IdentityPlaceholderProperties =
|
|
139
|
+
export type IdentityPlaceholderProperties = InferComponentDefinition<
|
|
140
140
|
typeof metadata.identityPlaceholder.componentPropertyDefinitions
|
|
141
141
|
>;
|
|
142
142
|
|
|
143
|
-
export type InlineBannerProperties =
|
|
143
|
+
export type InlineBannerProperties = InferComponentDefinition<
|
|
144
144
|
typeof metadata.inlineBanner.componentPropertyDefinitions
|
|
145
145
|
>;
|
|
146
146
|
|
|
147
|
-
export type MannerTempBadgeProperties =
|
|
147
|
+
export type MannerTempBadgeProperties = InferComponentDefinition<
|
|
148
148
|
typeof metadata.mannerTempBadge.componentPropertyDefinitions
|
|
149
149
|
>;
|
|
150
150
|
|
|
151
|
-
export type MultilineTextFieldProperties =
|
|
151
|
+
export type MultilineTextFieldProperties = InferComponentDefinition<
|
|
152
152
|
typeof metadata.multilineTextField.componentPropertyDefinitions
|
|
153
153
|
>;
|
|
154
154
|
|
|
155
|
-
export type ProgressCircleProperties =
|
|
155
|
+
export type ProgressCircleProperties = InferComponentDefinition<
|
|
156
156
|
typeof metadata.progressCircle.componentPropertyDefinitions
|
|
157
157
|
>;
|
|
158
158
|
|
|
159
|
-
export type ReactionButtonProperties =
|
|
159
|
+
export type ReactionButtonProperties = InferComponentDefinition<
|
|
160
160
|
typeof metadata.reactionButton.componentPropertyDefinitions
|
|
161
161
|
>;
|
|
162
162
|
|
|
163
|
-
export type SegmentedControlProperties =
|
|
163
|
+
export type SegmentedControlProperties = InferComponentDefinition<
|
|
164
164
|
typeof metadata.segmentedControl.componentPropertyDefinitions
|
|
165
165
|
>;
|
|
166
166
|
|
|
167
|
-
export type SegmentedControlItemProperties =
|
|
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 =
|
|
186
|
+
export type SelectBoxGroupProperties = InferComponentDefinition<
|
|
187
187
|
typeof metadata.templateSelectBoxGroup.componentPropertyDefinitions
|
|
188
188
|
>;
|
|
189
189
|
|
|
190
|
-
export type SelectBoxProperties =
|
|
190
|
+
export type SelectBoxProperties = InferComponentDefinition<
|
|
191
191
|
typeof metadata.selectBox.componentPropertyDefinitions
|
|
192
192
|
>;
|
|
193
193
|
|
|
194
|
-
export type SkeletonProperties =
|
|
194
|
+
export type SkeletonProperties = InferComponentDefinition<
|
|
195
195
|
typeof metadata.skeleton.componentPropertyDefinitions
|
|
196
196
|
>;
|
|
197
197
|
|
|
198
|
-
export type SnackbarProperties =
|
|
198
|
+
export type SnackbarProperties = InferComponentDefinition<
|
|
199
199
|
typeof metadata.snackbar.componentPropertyDefinitions
|
|
200
200
|
>;
|
|
201
201
|
|
|
202
|
-
export type SwitchProperties =
|
|
202
|
+
export type SwitchProperties = InferComponentDefinition<
|
|
203
203
|
typeof metadata.switch.componentPropertyDefinitions
|
|
204
204
|
>;
|
|
205
205
|
|
|
206
|
-
export type TabsProperties =
|
|
206
|
+
export type TabsProperties = InferComponentDefinition<
|
|
207
207
|
typeof metadata.tablist.componentPropertyDefinitions
|
|
208
208
|
>;
|
|
209
209
|
|
|
210
|
-
export type TabsHugItemProperties =
|
|
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 =
|
|
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 =
|
|
254
|
+
export type TextButtonProperties = InferComponentDefinition<
|
|
255
255
|
typeof metadata.textButton.componentPropertyDefinitions
|
|
256
256
|
>;
|
|
257
257
|
|
|
258
|
-
export type TextFieldProperties =
|
|
258
|
+
export type TextFieldProperties = InferComponentDefinition<
|
|
259
259
|
typeof metadata.textField.componentPropertyDefinitions
|
|
260
260
|
>;
|
|
261
261
|
|
|
262
|
-
export type ToggleButtonProperties =
|
|
262
|
+
export type ToggleButtonProperties = InferComponentDefinition<
|
|
263
263
|
typeof metadata.toggleButton.componentPropertyDefinitions
|
|
264
264
|
>;
|
|
265
265
|
|
|
266
|
-
export type AppBarProperties =
|
|
266
|
+
export type AppBarProperties = InferComponentDefinition<
|
|
267
267
|
typeof metadata.standardNavigation.componentPropertyDefinitions
|
|
268
268
|
>;
|
|
269
269
|
|
|
270
|
-
export type AppBarMainProperties =
|
|
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 =
|
|
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 =
|
|
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 {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
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
|
|
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
|
|
28
|
+
export function createCodeGenerator({
|
|
29
29
|
frameTransformer,
|
|
30
30
|
textTransformer,
|
|
31
31
|
rectangleTransformer,
|
|
32
32
|
instanceTransformer,
|
|
33
33
|
vectorTransformer,
|
|
34
34
|
booleanOperationTransformer,
|
|
35
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
12
|
+
export function defineComponentHandler<T extends NormalizedInstanceNode["componentProperties"]>(
|
|
13
13
|
key: string,
|
|
14
14
|
transform: (node: NormalizedInstanceNode & { componentProperties: T }) => ElementNode,
|
|
15
|
-
):
|
|
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 {
|
|
2
|
-
export type {
|
|
1
|
+
export type { CodeGeneratorDeps } from "./codegen";
|
|
2
|
+
export type { ComponentHandler } from "./component-handler";
|
|
3
3
|
export type {
|
|
4
4
|
ComponentPropertyDefinition,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "./component
|
|
8
|
-
export type {
|
|
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 {
|
|
11
|
-
export type {
|
|
11
|
+
export type { PropsConverter } from "./props-converter";
|
|
12
|
+
export type { ValueResolver } from "./value-resolver";
|
|
12
13
|
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
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 {
|
|
18
|
-
export {
|
|
19
|
-
export {
|
|
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");
|