@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
@@ -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
- getIconData(key: string): IconData;
4
+ getOne(key: string): IconData;
5
5
  }
6
6
 
7
7
  export function createStaticIconRepository(iconRecord: Record<string, IconData>) {
8
8
  return {
9
- getIconData: (key: string) => iconRecord[key],
9
+ getOne: (key: string) => iconRecord[key],
10
10
  };
11
11
  }
@@ -1,35 +1,24 @@
1
- import { pascalCase } from "change-case";
1
+ import type { IconData } from "./icon.interface";
2
2
  import type { IconRepository } from "./icon.repository";
3
3
 
4
4
  export interface IconService {
5
- isIconComponent: (componentKey: string) => boolean;
6
- createIconTagName: (key?: string) => string;
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 isIconComponent(componentKey: string) {
13
- return iconRepository.getIconData(componentKey) !== undefined;
12
+ function isAvailable(componentKey: string) {
13
+ return iconRepository.getOne(componentKey) !== undefined;
14
14
  }
15
15
 
16
- function createIconTagName(key?: string) {
17
- if (!key) {
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
- isIconComponent,
33
- createIconTagName,
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
- getStyleName: (id: string) => string | undefined;
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 getFigmaStyleName(id: string) {
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 getFigmaStyleSlug(id: string): string[] | undefined {
26
- const name = getFigmaStyleName(id);
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
- getStyleName,
34
+ getSlug,
47
35
  };
48
36
  }
@@ -1,42 +1,41 @@
1
- import { isVariableAlias, sanitizeVariableId } from "@/utils/figma-variable";
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
- getVariableName: (id: string) => string;
7
- inferVariableName: (value: VariableValueResolved, scope: VariableScope) => string | undefined;
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
- variableNameTransformer: ({ slug }: { slug: string[] }) => string;
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 getFigmaVariableName(key: string) {
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 "UNKNOWN_VARIABLE";
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
- function resolveVariableValue(id: string, mode: string): VariableValueResolved {
54
- const variable = variableRepository.findVariableById(id);
55
- if (!variable) {
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 (isVariableAlias(value)) {
66
- return resolveVariableValue(value.id, mode);
56
+ if (!name) {
57
+ return undefined;
67
58
  }
68
59
 
69
- return value;
60
+ return name.split("/");
70
61
  }
71
62
 
72
- function isIdenticalVariableValue(value1: VariableValueResolved, value2: VariableValueResolved) {
73
- if (typeof value1 !== typeof value2) {
74
- return false;
75
- }
63
+ function resolveValue(variable: Variable, mode: string): VariableValueResolved {
64
+ const value = variable.valuesByMode[mode];
76
65
 
77
- if (typeof value1 === "string" || typeof value1 === "number" || typeof value1 === "boolean") {
78
- return value1 === value2;
66
+ if (value === undefined) {
67
+ throw new Error(`Variable value not found: ${variable.id} ${mode}`);
79
68
  }
80
69
 
81
- return (
82
- value1.r === (value2 as RGBA).r &&
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
- if (variable.scopes.includes("ALL_FILLS")) {
95
- if (scope === "FRAME_FILL" || scope === "SHAPE_FILL" || scope === "TEXT_FILL") {
96
- return true;
73
+ if (!resolvedVariable) {
74
+ throw new Error(`Variable not found: ${value.id}`);
97
75
  }
98
- }
99
76
 
100
- return variable.scopes.includes(scope);
101
- }
77
+ return resolveValue(resolvedVariable, mode);
78
+ }
102
79
 
103
- // public
104
- function getVariableName(key: string) {
105
- const slug = getFigmaVariableSlug(key);
106
- return variableNameTransformer({ slug });
80
+ return value;
107
81
  }
108
82
 
109
- function inferVariableName(value: VariableValueResolved, scope: VariableScope) {
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 sortedVariableNames = inferredVariableNames.sort(inferCompareFunction);
91
+ const sortedVariables = inferredVariables.sort(inferCompareFunction);
125
92
 
126
- return sortedVariableNames[0];
93
+ return sortedVariables[0];
127
94
  }
128
95
 
129
96
  return {
130
- getVariableName,
131
- inferVariableName,
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
 
@@ -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 & { componentKey?: string };
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
- // boundVariable.id is formatted as "VariableID:{key}/{localId}", we have to extract the key
11
- export function sanitizeVariableId(id: string) {
12
- return id.replace("VariableID:", "").split("/")[0]!;
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
- );