@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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createValueResolver, type ValueResolver } from "@/codegen/core";
|
|
2
|
+
import { styleService, variableService } from "@/codegen/default-services";
|
|
3
|
+
import { camelCasePreserveUnderscoreBetweenNumbers } from "@/utils/common";
|
|
4
|
+
import { toCssPixel, toCssRgba } from "@/utils/css";
|
|
5
|
+
import { camelCase } from "change-case";
|
|
6
|
+
|
|
7
|
+
export type ReactValueResolver = ValueResolver<string, string, string, number>;
|
|
8
|
+
|
|
9
|
+
export const valueResolver = createValueResolver({
|
|
10
|
+
variableService,
|
|
11
|
+
variableNameFormatter: ({ slug }) =>
|
|
12
|
+
slug
|
|
13
|
+
.filter(
|
|
14
|
+
(s) =>
|
|
15
|
+
!(
|
|
16
|
+
s === "dimension" ||
|
|
17
|
+
s === "radius" ||
|
|
18
|
+
s === "font-size" ||
|
|
19
|
+
s === "font-weight" ||
|
|
20
|
+
s === "line-height"
|
|
21
|
+
),
|
|
22
|
+
)
|
|
23
|
+
.map((s) => s.replaceAll(",", "_"))
|
|
24
|
+
.map(camelCasePreserveUnderscoreBetweenNumbers)
|
|
25
|
+
.join("."),
|
|
26
|
+
styleService,
|
|
27
|
+
styleNameFormatter: ({ slug }) =>
|
|
28
|
+
camelCase(slug[slug.length - 1]!, { mergeAmbiguousCharacters: true }),
|
|
29
|
+
rawValueFormatters: {
|
|
30
|
+
color: (value: RGBA) => toCssRgba(value),
|
|
31
|
+
dimension: (value: number) => toCssPixel(value),
|
|
32
|
+
fontDimension: (value: number) => toCssPixel(value),
|
|
33
|
+
fontWeight: (value: number) => value,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { IconData } from "./icon.interface";
|
|
2
2
|
|
|
3
3
|
export interface IconRepository {
|
|
4
|
-
|
|
4
|
+
getOne(key: string): IconData;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export function createStaticIconRepository(iconRecord: Record<string, IconData>) {
|
|
8
8
|
return {
|
|
9
|
-
|
|
9
|
+
getOne: (key: string) => iconRecord[key],
|
|
10
10
|
};
|
|
11
11
|
}
|
|
@@ -1,35 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IconData } from "./icon.interface";
|
|
2
2
|
import type { IconRepository } from "./icon.repository";
|
|
3
3
|
|
|
4
4
|
export interface IconService {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
isAvailable: (componentKey: string) => boolean;
|
|
6
|
+
getOne: (componentKey: string) => IconData;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function createIconService({
|
|
10
10
|
iconRepository,
|
|
11
11
|
}: { iconRepository: IconRepository }): IconService {
|
|
12
|
-
function
|
|
13
|
-
return iconRepository.
|
|
12
|
+
function isAvailable(componentKey: string) {
|
|
13
|
+
return iconRepository.getOne(componentKey) !== undefined;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
return "UnknownIcon";
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const iconData = iconRepository.getIconData(key);
|
|
22
|
-
if (!iconData) {
|
|
23
|
-
return "UnknownIcon";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const { name, weight } = iconData;
|
|
27
|
-
|
|
28
|
-
return pascalCase(`${name}${weight ? weight : ""}`);
|
|
16
|
+
function getOne(componentKey: string) {
|
|
17
|
+
return iconRepository.getOne(componentKey);
|
|
29
18
|
}
|
|
30
19
|
|
|
31
20
|
return {
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
isAvailable,
|
|
22
|
+
getOne,
|
|
34
23
|
};
|
|
35
24
|
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import type { StyleRepository } from "./style.repository";
|
|
2
2
|
|
|
3
3
|
export interface StyleService {
|
|
4
|
-
|
|
4
|
+
getSlug: (id: string) => string[] | undefined;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
// TODO: inferStyleName 추가해야 함, rest api에서 style value가 제공되지 않고 있어 보류
|
|
8
8
|
export function createStyleService({
|
|
9
9
|
styleRepository,
|
|
10
|
-
styleNameTransformer,
|
|
11
10
|
}: {
|
|
12
11
|
styleRepository: StyleRepository;
|
|
13
|
-
styleNameTransformer: ({ slug }: { slug: string[] }) => string;
|
|
14
12
|
}): StyleService {
|
|
15
|
-
function
|
|
13
|
+
function getName(id: string) {
|
|
16
14
|
const style = styleRepository.findOneByKey(id);
|
|
17
15
|
|
|
18
16
|
if (!style) {
|
|
@@ -22,8 +20,8 @@ export function createStyleService({
|
|
|
22
20
|
return style.name;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
function
|
|
26
|
-
const name =
|
|
23
|
+
function getSlug(id: string): string[] | undefined {
|
|
24
|
+
const name = getName(id);
|
|
27
25
|
|
|
28
26
|
if (!name) {
|
|
29
27
|
return undefined;
|
|
@@ -32,17 +30,7 @@ export function createStyleService({
|
|
|
32
30
|
return name.split("/");
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
function getStyleName(id: string) {
|
|
36
|
-
const slug = getFigmaStyleSlug(id);
|
|
37
|
-
|
|
38
|
-
if (!slug) {
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return styleNameTransformer({ slug });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
33
|
return {
|
|
46
|
-
|
|
34
|
+
getSlug,
|
|
47
35
|
};
|
|
48
36
|
}
|
|
@@ -1,42 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isIdenticalVariableValue,
|
|
3
|
+
isInsideScope,
|
|
4
|
+
isVariableAlias,
|
|
5
|
+
sanitizeVariableId,
|
|
6
|
+
} from "@/utils/figma-variable";
|
|
2
7
|
import type { Variable, VariableScope, VariableValueResolved } from "./variable.interface";
|
|
3
8
|
import type { VariableRepository } from "./variable.repository";
|
|
4
9
|
|
|
5
10
|
export interface VariableService {
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
getSlug: (id: string) => string[] | undefined;
|
|
12
|
+
resolveValue: (variable: Variable, mode: string) => VariableValueResolved;
|
|
13
|
+
infer: (value: VariableValueResolved, scope: VariableScope) => Variable | undefined;
|
|
8
14
|
}
|
|
9
15
|
|
|
10
16
|
export interface VariableServiceDeps {
|
|
11
17
|
variableRepository: VariableRepository;
|
|
12
|
-
|
|
13
|
-
inferCompareFunction: (name1: string, name2: string) => number;
|
|
18
|
+
inferCompareFunction: (a: Variable, b: Variable) => number;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
export function createVariableService({
|
|
17
22
|
variableRepository,
|
|
18
|
-
variableNameTransformer,
|
|
19
23
|
inferCompareFunction,
|
|
20
24
|
}: VariableServiceDeps): VariableService {
|
|
21
25
|
const variables = variableRepository.getVariableList();
|
|
22
26
|
|
|
23
27
|
// private
|
|
24
|
-
function
|
|
28
|
+
function getName(key: string) {
|
|
25
29
|
const sanitizedId = sanitizeVariableId(key);
|
|
26
30
|
const variable = variableRepository.findVariableByKey(sanitizedId);
|
|
27
31
|
|
|
28
32
|
if (!variable) {
|
|
29
|
-
return
|
|
33
|
+
return undefined;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
return variable.name;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
function getFigmaVariableSlug(key: string): string[] {
|
|
36
|
-
const name = getFigmaVariableName(key);
|
|
37
|
-
return name.split("/");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
39
|
function getDefaultModeId(variable: Variable) {
|
|
41
40
|
const variableCollection = variableRepository.findVariableCollectionById(
|
|
42
41
|
variable.variableCollectionId,
|
|
@@ -50,84 +49,53 @@ export function createVariableService({
|
|
|
50
49
|
return variableCollection.defaultModeId;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
throw new Error(`Variable not found: ${id}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const value = variable.valuesByMode[mode];
|
|
60
|
-
|
|
61
|
-
if (value === undefined) {
|
|
62
|
-
throw new Error(`Variable value not found: ${id} ${mode}`);
|
|
63
|
-
}
|
|
52
|
+
// public
|
|
53
|
+
function getSlug(key: string): string[] | undefined {
|
|
54
|
+
const name = getName(key);
|
|
64
55
|
|
|
65
|
-
if (
|
|
66
|
-
return
|
|
56
|
+
if (!name) {
|
|
57
|
+
return undefined;
|
|
67
58
|
}
|
|
68
59
|
|
|
69
|
-
return
|
|
60
|
+
return name.split("/");
|
|
70
61
|
}
|
|
71
62
|
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
63
|
+
function resolveValue(variable: Variable, mode: string): VariableValueResolved {
|
|
64
|
+
const value = variable.valuesByMode[mode];
|
|
76
65
|
|
|
77
|
-
if (
|
|
78
|
-
|
|
66
|
+
if (value === undefined) {
|
|
67
|
+
throw new Error(`Variable value not found: ${variable.id} ${mode}`);
|
|
79
68
|
}
|
|
80
69
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
value1.g === (value2 as RGBA).g &&
|
|
84
|
-
value1.b === (value2 as RGBA).b &&
|
|
85
|
-
value1.a === (value2 as RGBA).a
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function isInsideScope(variable: Variable, scope: VariableScope) {
|
|
90
|
-
if (variable.scopes.includes("ALL_SCOPES")) {
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
70
|
+
if (isVariableAlias(value)) {
|
|
71
|
+
const resolvedVariable = variableRepository.findVariableById(value.id);
|
|
93
72
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return true;
|
|
73
|
+
if (!resolvedVariable) {
|
|
74
|
+
throw new Error(`Variable not found: ${value.id}`);
|
|
97
75
|
}
|
|
98
|
-
}
|
|
99
76
|
|
|
100
|
-
|
|
101
|
-
|
|
77
|
+
return resolveValue(resolvedVariable, mode);
|
|
78
|
+
}
|
|
102
79
|
|
|
103
|
-
|
|
104
|
-
function getVariableName(key: string) {
|
|
105
|
-
const slug = getFigmaVariableSlug(key);
|
|
106
|
-
return variableNameTransformer({ slug });
|
|
80
|
+
return value;
|
|
107
81
|
}
|
|
108
82
|
|
|
109
|
-
function
|
|
83
|
+
function infer(value: VariableValueResolved, scope: VariableScope) {
|
|
110
84
|
// NOTE: We assume that the variable is in the default mode or value is equal between all modes for simplicity.
|
|
111
85
|
const inferredVariables = variables.filter(
|
|
112
86
|
(variable) =>
|
|
113
87
|
isInsideScope(variable, scope) &&
|
|
114
|
-
isIdenticalVariableValue(
|
|
115
|
-
resolveVariableValue(variable.id, getDefaultModeId(variable)),
|
|
116
|
-
value,
|
|
117
|
-
),
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const inferredVariableNames = inferredVariables.map((variable) =>
|
|
121
|
-
getVariableName(variable.key),
|
|
88
|
+
isIdenticalVariableValue(resolveValue(variable, getDefaultModeId(variable)), value),
|
|
122
89
|
);
|
|
123
90
|
|
|
124
|
-
const
|
|
91
|
+
const sortedVariables = inferredVariables.sort(inferCompareFunction);
|
|
125
92
|
|
|
126
|
-
return
|
|
93
|
+
return sortedVariables[0];
|
|
127
94
|
}
|
|
128
95
|
|
|
129
96
|
return {
|
|
130
|
-
|
|
131
|
-
|
|
97
|
+
getSlug,
|
|
98
|
+
resolveValue,
|
|
99
|
+
infer,
|
|
132
100
|
};
|
|
133
101
|
}
|
|
@@ -206,6 +206,9 @@ export function createPluginNormalizer() {
|
|
|
206
206
|
)) as ComponentNode;
|
|
207
207
|
if (mainComponent) {
|
|
208
208
|
componentProperties[key].componentKey = mainComponent.key;
|
|
209
|
+
if (mainComponent.parent?.type === "COMPONENT_SET") {
|
|
210
|
+
componentProperties[key].componentSetKey = mainComponent.parent.key;
|
|
211
|
+
}
|
|
209
212
|
}
|
|
210
213
|
}
|
|
211
214
|
}
|
|
@@ -184,6 +184,12 @@ export function createRestNormalizer(ctx: RestNormalizerContext) {
|
|
|
184
184
|
if (mainComponent) {
|
|
185
185
|
componentProperties[key].componentKey = mainComponent.key;
|
|
186
186
|
}
|
|
187
|
+
const mainComponentSet = mainComponent.componentSetId
|
|
188
|
+
? ctx.componentSets[mainComponent.componentSetId]
|
|
189
|
+
: undefined;
|
|
190
|
+
if (mainComponentSet) {
|
|
191
|
+
componentProperties[key].componentSetKey = mainComponentSet.key;
|
|
192
|
+
}
|
|
187
193
|
}
|
|
188
194
|
}
|
|
189
195
|
|
package/src/normalizer/types.ts
CHANGED
|
@@ -109,7 +109,10 @@ export interface NormalizedInstanceNode extends NormalizedFrameTrait {
|
|
|
109
109
|
type: FigmaRestSpec.InstanceNode["type"];
|
|
110
110
|
|
|
111
111
|
componentProperties: {
|
|
112
|
-
[key: string]: FigmaRestSpec.ComponentProperty & {
|
|
112
|
+
[key: string]: FigmaRestSpec.ComponentProperty & {
|
|
113
|
+
componentKey?: string;
|
|
114
|
+
componentSetKey?: string;
|
|
115
|
+
};
|
|
113
116
|
};
|
|
114
117
|
|
|
115
118
|
componentKey: string;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import type { VariableScope } from "@figma/rest-api-spec";
|
|
2
|
+
|
|
3
|
+
// boundVariable.id is formatted as "VariableID:{key}/{localId}", we have to extract the key
|
|
4
|
+
export function sanitizeVariableId(id: string) {
|
|
5
|
+
return id.replace("VariableID:", "").split("/")[0]!;
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
export function isVariableAlias(value: unknown): value is VariableAlias {
|
|
2
9
|
return (
|
|
3
10
|
typeof value === "object" &&
|
|
@@ -7,7 +14,36 @@ export function isVariableAlias(value: unknown): value is VariableAlias {
|
|
|
7
14
|
);
|
|
8
15
|
}
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
export function isIdenticalVariableValue(
|
|
18
|
+
value1: string | number | boolean | RGBA,
|
|
19
|
+
value2: string | number | boolean | RGBA,
|
|
20
|
+
) {
|
|
21
|
+
if (typeof value1 !== typeof value2) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (typeof value1 === "string" || typeof value1 === "number" || typeof value1 === "boolean") {
|
|
26
|
+
return value1 === value2;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
value1.r === (value2 as RGBA).r &&
|
|
31
|
+
value1.g === (value2 as RGBA).g &&
|
|
32
|
+
value1.b === (value2 as RGBA).b &&
|
|
33
|
+
value1.a === (value2 as RGBA).a
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isInsideScope(variable: { scopes: VariableScope[] }, scope: VariableScope) {
|
|
38
|
+
if (variable.scopes.includes("ALL_SCOPES")) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (variable.scopes.includes("ALL_FILLS")) {
|
|
43
|
+
if (scope === "FRAME_FILL" || scope === "SHAPE_FILL" || scope === "TEXT_FILL") {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return variable.scopes.includes(scope);
|
|
13
49
|
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export interface ComponentPropertyDefinition {
|
|
2
|
-
type: ComponentPropertyType;
|
|
3
|
-
preferredValues?: InstanceSwapPreferredValue[];
|
|
4
|
-
variantOptions?: string[];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export type InferPropertyType<T extends ComponentPropertyDefinition> = T["type"] extends "TEXT"
|
|
8
|
-
? string
|
|
9
|
-
: T["type"] extends "BOOLEAN"
|
|
10
|
-
? boolean
|
|
11
|
-
: T["type"] extends "INSTANCE_SWAP"
|
|
12
|
-
? string
|
|
13
|
-
: T["type"] extends "VARIANT"
|
|
14
|
-
? T["variantOptions"] extends string[]
|
|
15
|
-
? T["variantOptions"][number]
|
|
16
|
-
: never
|
|
17
|
-
: never;
|
|
18
|
-
|
|
19
|
-
export type InferFromDefinition<T extends Record<string, ComponentPropertyDefinition>> = {
|
|
20
|
-
[K in keyof T]: {
|
|
21
|
-
type: T[K]["type"];
|
|
22
|
-
value: InferPropertyType<T[K]>;
|
|
23
|
-
componentKey?: string;
|
|
24
|
-
preferredValues?: InstanceSwapPreferredValue[];
|
|
25
|
-
readonly boundVariables?: {
|
|
26
|
-
[field in VariableBindableComponentPropertyField]?: VariableAlias;
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
};
|
|
@@ -1,139 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { createElement, defineComponentTransformer } from "@/codegen/core";
|
|
2
|
-
import * as metadata from "@/entities/data/__generated__/component-sets";
|
|
3
|
-
import { findAllInstances } from "@/utils/figma-node";
|
|
4
|
-
import type { SeedComponentTransformerDeps } from "../deps.interface";
|
|
5
|
-
import type { AvatarProperties, AvatarStackProperties } from "../properties.type";
|
|
6
|
-
import { createAvatarTransformer } from "./avatar";
|
|
7
|
-
|
|
8
|
-
export const createAvatarStackTransformer = (ctx: SeedComponentTransformerDeps) => {
|
|
9
|
-
const avatarTransformer = createAvatarTransformer(ctx);
|
|
10
|
-
|
|
11
|
-
return defineComponentTransformer<AvatarStackProperties>(metadata.avatarStack.key, (node) => {
|
|
12
|
-
const avatarNodes = findAllInstances<AvatarProperties>({
|
|
13
|
-
node,
|
|
14
|
-
key: avatarTransformer.key,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const { componentProperties: props } = node;
|
|
18
|
-
|
|
19
|
-
const commonProps = {
|
|
20
|
-
size: props.Size.value,
|
|
21
|
-
// TODO: 구현될 예정
|
|
22
|
-
// topItem: camelCase(props["Top Item"].value),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const avatarStackChildren = avatarNodes.map(avatarTransformer.transform);
|
|
26
|
-
|
|
27
|
-
return createElement("AvatarStack", commonProps, avatarStackChildren);
|
|
28
|
-
});
|
|
29
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { createElement, defineComponentTransformer } from "@/codegen/core";
|
|
2
|
-
import * as metadata from "@/entities/data/__generated__/component-sets";
|
|
3
|
-
import { camelCase } from "change-case";
|
|
4
|
-
import type { SeedComponentTransformerDeps } from "../deps.interface";
|
|
5
|
-
import type { BadgeProperties } from "../properties.type";
|
|
6
|
-
import { handleSizeProp } from "../size";
|
|
7
|
-
|
|
8
|
-
export const createBadgeTransformer = (_ctx: SeedComponentTransformerDeps) =>
|
|
9
|
-
defineComponentTransformer<BadgeProperties>(
|
|
10
|
-
metadata.badge.key,
|
|
11
|
-
({ componentProperties: props }) => {
|
|
12
|
-
const commonProps = {
|
|
13
|
-
size: handleSizeProp(props.Size.value),
|
|
14
|
-
tone: camelCase(props.Tone.value),
|
|
15
|
-
variant: camelCase(props.Variant.value),
|
|
16
|
-
shape: camelCase(props.Shape.value),
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return createElement("Badge", commonProps, props["Label#1584:0"].value);
|
|
20
|
-
},
|
|
21
|
-
);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { defineComponentTransformer } from "@/codegen/core";
|
|
2
|
-
import * as metadata from "@/entities/data/__generated__/component-sets";
|
|
3
|
-
import { createElement } from "@/codegen/core";
|
|
4
|
-
import type { FabProperties } from "../properties.type";
|
|
5
|
-
import type { SeedComponentTransformerDeps } from "../deps.interface";
|
|
6
|
-
|
|
7
|
-
export const createFabTransformer = (ctx: SeedComponentTransformerDeps) =>
|
|
8
|
-
defineComponentTransformer<FabProperties>(
|
|
9
|
-
metadata.floatingActionButton.key,
|
|
10
|
-
({ componentProperties: props }) => {
|
|
11
|
-
return createElement(
|
|
12
|
-
"Fab",
|
|
13
|
-
undefined,
|
|
14
|
-
createElement(ctx.iconService.createIconTagName(props["Icon#28796:0"].componentKey)),
|
|
15
|
-
"aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.",
|
|
16
|
-
);
|
|
17
|
-
},
|
|
18
|
-
);
|