@seed-design/figma 0.0.0-alpha-20260324091316
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 +23543 -0
- package/lib/codegen/index.d.ts +2957 -0
- package/lib/codegen/index.d.ts.map +1 -0
- package/lib/codegen/index.js +23514 -0
- package/lib/codegen/targets/react/index.cjs +31980 -0
- package/lib/codegen/targets/react/index.d.ts +308 -0
- package/lib/codegen/targets/react/index.d.ts.map +1 -0
- package/lib/codegen/targets/react/index.js +31961 -0
- package/lib/index.cjs +26905 -0
- package/lib/index.d.ts +221 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +26884 -0
- package/package.json +56 -0
- package/src/codegen/component-properties.archive.ts +1019 -0
- package/src/codegen/component-properties.ts +369 -0
- package/src/codegen/core/codegen.ts +112 -0
- package/src/codegen/core/component-handler.ts +23 -0
- package/src/codegen/core/component-type-helper.ts +35 -0
- package/src/codegen/core/element-transformer.ts +13 -0
- package/src/codegen/core/index.ts +19 -0
- package/src/codegen/core/infer-layout.test.ts +286 -0
- package/src/codegen/core/infer-layout.ts +416 -0
- package/src/codegen/core/jsx.ts +174 -0
- package/src/codegen/core/props-converter.ts +78 -0
- package/src/codegen/core/value-resolver.ts +381 -0
- package/src/codegen/default-services.ts +44 -0
- package/src/codegen/index.ts +3 -0
- package/src/codegen/skip-components.ts +7 -0
- package/src/codegen/targets/figma/frame.ts +38 -0
- package/src/codegen/targets/figma/index.ts +6 -0
- package/src/codegen/targets/figma/instance.ts +36 -0
- package/src/codegen/targets/figma/pipeline.ts +106 -0
- package/src/codegen/targets/figma/props.ts +262 -0
- package/src/codegen/targets/figma/shape.ts +65 -0
- package/src/codegen/targets/figma/text.ts +30 -0
- package/src/codegen/targets/figma/value-resolver.ts +75 -0
- package/src/codegen/targets/index.ts +2 -0
- package/src/codegen/targets/react/component/deps.interface.ts +7 -0
- package/src/codegen/targets/react/component/handlers/action-button.ts +149 -0
- package/src/codegen/targets/react/component/handlers/alert-dialog.ts +120 -0
- package/src/codegen/targets/react/component/handlers/app-bar.ts +169 -0
- package/src/codegen/targets/react/component/handlers/archive/action-button.ts +144 -0
- package/src/codegen/targets/react/component/handlers/archive/alert-dialog.ts +122 -0
- package/src/codegen/targets/react/component/handlers/archive/app-bar.ts +149 -0
- package/src/codegen/targets/react/component/handlers/archive/avatar-stack.ts +35 -0
- package/src/codegen/targets/react/component/handlers/archive/avatar.ts +55 -0
- package/src/codegen/targets/react/component/handlers/archive/badge.ts +18 -0
- package/src/codegen/targets/react/component/handlers/archive/bottom-sheet.ts +70 -0
- package/src/codegen/targets/react/component/handlers/archive/callout.ts +88 -0
- package/src/codegen/targets/react/component/handlers/archive/checkbox.ts +43 -0
- package/src/codegen/targets/react/component/handlers/archive/checkmark.ts +29 -0
- package/src/codegen/targets/react/component/handlers/archive/chip.ts +90 -0
- package/src/codegen/targets/react/component/handlers/archive/contextual-floating-button.ts +52 -0
- package/src/codegen/targets/react/component/handlers/archive/divider.ts +25 -0
- package/src/codegen/targets/react/component/handlers/archive/field-button.ts +197 -0
- package/src/codegen/targets/react/component/handlers/archive/field.ts +167 -0
- package/src/codegen/targets/react/component/handlers/archive/floating-action-button.ts +48 -0
- package/src/codegen/targets/react/component/handlers/archive/help-bubble.ts +73 -0
- package/src/codegen/targets/react/component/handlers/archive/identity-placeholder.ts +21 -0
- package/src/codegen/targets/react/component/handlers/archive/index.ts +40 -0
- package/src/codegen/targets/react/component/handlers/archive/legacy-select-box.ts +89 -0
- package/src/codegen/targets/react/component/handlers/archive/legacy-text-field.ts +198 -0
- package/src/codegen/targets/react/component/handlers/archive/list-header.ts +20 -0
- package/src/codegen/targets/react/component/handlers/archive/list-item.ts +162 -0
- package/src/codegen/targets/react/component/handlers/archive/manner-temp-badge.ts +21 -0
- package/src/codegen/targets/react/component/handlers/archive/manner-temp.ts +18 -0
- package/src/codegen/targets/react/component/handlers/archive/menu-sheet.ts +108 -0
- package/src/codegen/targets/react/component/handlers/archive/page-banner.ts +101 -0
- package/src/codegen/targets/react/component/handlers/archive/progress-circle.ts +55 -0
- package/src/codegen/targets/react/component/handlers/archive/radio-group.ts +31 -0
- package/src/codegen/targets/react/component/handlers/archive/radiomark.ts +27 -0
- package/src/codegen/targets/react/component/handlers/archive/reaction-button.ts +37 -0
- package/src/codegen/targets/react/component/handlers/archive/result-section.ts +67 -0
- package/src/codegen/targets/react/component/handlers/archive/segmented-control.ts +64 -0
- package/src/codegen/targets/react/component/handlers/archive/skeleton.ts +26 -0
- package/src/codegen/targets/react/component/handlers/archive/slider.ts +114 -0
- package/src/codegen/targets/react/component/handlers/archive/snackbar.ts +25 -0
- package/src/codegen/targets/react/component/handlers/archive/switch.ts +39 -0
- package/src/codegen/targets/react/component/handlers/archive/switchmark.ts +26 -0
- package/src/codegen/targets/react/component/handlers/archive/tabs.ts +297 -0
- package/src/codegen/targets/react/component/handlers/archive/tag-group.ts +86 -0
- package/src/codegen/targets/react/component/handlers/archive/text-field.ts +264 -0
- package/src/codegen/targets/react/component/handlers/archive/toggle-button.ts +43 -0
- package/src/codegen/targets/react/component/handlers/avatar-stack.ts +38 -0
- package/src/codegen/targets/react/component/handlers/avatar.ts +58 -0
- package/src/codegen/targets/react/component/handlers/badge.ts +18 -0
- package/src/codegen/targets/react/component/handlers/bottom-sheet.ts +74 -0
- package/src/codegen/targets/react/component/handlers/callout.ts +88 -0
- package/src/codegen/targets/react/component/handlers/checkbox.ts +129 -0
- package/src/codegen/targets/react/component/handlers/checkmark.ts +29 -0
- package/src/codegen/targets/react/component/handlers/chip.ts +93 -0
- package/src/codegen/targets/react/component/handlers/content-placeholder.ts +20 -0
- package/src/codegen/targets/react/component/handlers/contextual-floating-button.ts +52 -0
- package/src/codegen/targets/react/component/handlers/divider.ts +25 -0
- package/src/codegen/targets/react/component/handlers/field-button.ts +192 -0
- package/src/codegen/targets/react/component/handlers/field.ts +164 -0
- package/src/codegen/targets/react/component/handlers/floating-action-button.ts +45 -0
- package/src/codegen/targets/react/component/handlers/help-bubble.ts +73 -0
- package/src/codegen/targets/react/component/handlers/identity-placeholder.ts +20 -0
- package/src/codegen/targets/react/component/handlers/image-frame.ts +147 -0
- package/src/codegen/targets/react/component/handlers/index.ts +43 -0
- package/src/codegen/targets/react/component/handlers/legacy-select-box.ts +87 -0
- package/src/codegen/targets/react/component/handlers/legacy-text-field.ts +196 -0
- package/src/codegen/targets/react/component/handlers/list-header.ts +20 -0
- package/src/codegen/targets/react/component/handlers/list-item.ts +163 -0
- package/src/codegen/targets/react/component/handlers/manner-temp-badge.ts +21 -0
- package/src/codegen/targets/react/component/handlers/manner-temp.ts +18 -0
- package/src/codegen/targets/react/component/handlers/menu-sheet.ts +111 -0
- package/src/codegen/targets/react/component/handlers/page-banner.ts +106 -0
- package/src/codegen/targets/react/component/handlers/progress-circle.ts +55 -0
- package/src/codegen/targets/react/component/handlers/radio-group.ts +109 -0
- package/src/codegen/targets/react/component/handlers/radiomark.ts +27 -0
- package/src/codegen/targets/react/component/handlers/reaction-button.ts +37 -0
- package/src/codegen/targets/react/component/handlers/result-section.ts +67 -0
- package/src/codegen/targets/react/component/handlers/segmented-control.ts +63 -0
- package/src/codegen/targets/react/component/handlers/select-box.ts +333 -0
- package/src/codegen/targets/react/component/handlers/skeleton.ts +26 -0
- package/src/codegen/targets/react/component/handlers/slider.ts +117 -0
- package/src/codegen/targets/react/component/handlers/snackbar.ts +25 -0
- package/src/codegen/targets/react/component/handlers/switch.ts +35 -0
- package/src/codegen/targets/react/component/handlers/switchmark.ts +26 -0
- package/src/codegen/targets/react/component/handlers/tabs.ts +298 -0
- package/src/codegen/targets/react/component/handlers/tag-group.ts +90 -0
- package/src/codegen/targets/react/component/handlers/text-field.ts +253 -0
- package/src/codegen/targets/react/component/handlers/toggle-button.ts +43 -0
- package/src/codegen/targets/react/component/index.ts +24 -0
- package/src/codegen/targets/react/component/size.ts +22 -0
- package/src/codegen/targets/react/element-factories.ts +59 -0
- package/src/codegen/targets/react/frame.ts +96 -0
- package/src/codegen/targets/react/icon.ts +55 -0
- package/src/codegen/targets/react/index.ts +7 -0
- package/src/codegen/targets/react/instance.ts +82 -0
- package/src/codegen/targets/react/pipeline.ts +133 -0
- package/src/codegen/targets/react/props.ts +417 -0
- package/src/codegen/targets/react/shape.ts +47 -0
- package/src/codegen/targets/react/text.ts +31 -0
- package/src/codegen/targets/react/value-resolver.ts +93 -0
- package/src/entities/component.interface.ts +7 -0
- package/src/entities/component.repository.ts +16 -0
- package/src/entities/data/__generated__/archive/component-sets/index.d.ts +2074 -0
- package/src/entities/data/__generated__/archive/component-sets/index.mjs +2074 -0
- package/src/entities/data/__generated__/archive/components/index.d.ts +116 -0
- package/src/entities/data/__generated__/archive/components/index.mjs +116 -0
- package/src/entities/data/__generated__/archive/styles/index.d.ts +3 -0
- package/src/entities/data/__generated__/archive/styles/index.mjs +429 -0
- package/src/entities/data/__generated__/archive/variable-collections/index.d.ts +3 -0
- package/src/entities/data/__generated__/archive/variable-collections/index.mjs +501 -0
- package/src/entities/data/__generated__/archive/variables/index.d.ts +3 -0
- package/src/entities/data/__generated__/archive/variables/index.mjs +7019 -0
- package/src/entities/data/__generated__/component-sets/index.d.ts +4325 -0
- package/src/entities/data/__generated__/component-sets/index.mjs +4325 -0
- package/src/entities/data/__generated__/components/index.d.ts +378 -0
- package/src/entities/data/__generated__/components/index.mjs +378 -0
- package/src/entities/data/__generated__/icons/index.d.ts +3 -0
- package/src/entities/data/__generated__/icons/index.mjs +3476 -0
- package/src/entities/data/__generated__/styles/index.d.ts +3 -0
- package/src/entities/data/__generated__/styles/index.mjs +436 -0
- package/src/entities/data/__generated__/variable-collections/index.d.ts +3 -0
- package/src/entities/data/__generated__/variable-collections/index.mjs +479 -0
- package/src/entities/data/__generated__/variables/index.d.ts +3 -0
- package/src/entities/data/__generated__/variables/index.mjs +6969 -0
- package/src/entities/icon.interface.ts +5 -0
- package/src/entities/icon.repository.ts +11 -0
- package/src/entities/icon.service.ts +26 -0
- package/src/entities/index.ts +60 -0
- package/src/entities/style.interface.ts +5 -0
- package/src/entities/style.repository.ts +27 -0
- package/src/entities/style.service.ts +36 -0
- package/src/entities/variable.interface.ts +18 -0
- package/src/entities/variable.repository.ts +57 -0
- package/src/entities/variable.service.ts +101 -0
- package/src/index.ts +3 -0
- package/src/normalizer/from-plugin.ts +602 -0
- package/src/normalizer/from-rest.ts +577 -0
- package/src/normalizer/index.ts +3 -0
- package/src/normalizer/types.ts +208 -0
- package/src/utils/common.ts +38 -0
- package/src/utils/css.ts +19 -0
- package/src/utils/figma-gradient.ts +72 -0
- package/src/utils/figma-node.ts +95 -0
- package/src/utils/figma-variable.ts +49 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { createPropsConverter, definePropsConverter, type PropsConverter } from "@/codegen/core";
|
|
2
|
+
import type {
|
|
3
|
+
NormalizedCornerTrait,
|
|
4
|
+
NormalizedHasChildrenTrait,
|
|
5
|
+
NormalizedHasEffectsTrait,
|
|
6
|
+
NormalizedHasFramePropertiesTrait,
|
|
7
|
+
NormalizedHasGeometryTrait,
|
|
8
|
+
NormalizedHasLayoutTrait,
|
|
9
|
+
NormalizedIsLayerTrait,
|
|
10
|
+
NormalizedTypePropertiesTrait,
|
|
11
|
+
} from "@/normalizer";
|
|
12
|
+
import { match } from "ts-pattern";
|
|
13
|
+
import type { ReactValueResolver } from "./value-resolver";
|
|
14
|
+
|
|
15
|
+
export interface PropsConverters {
|
|
16
|
+
containerLayout: PropsConverter<ContainerLayoutTrait, ContainerLayoutProps>;
|
|
17
|
+
selfLayout: PropsConverter<SelfLayoutTrait, SelfLayoutProps>;
|
|
18
|
+
iconSelfLayout: PropsConverter<SelfLayoutTrait, IconSelfLayoutProps>;
|
|
19
|
+
radius: PropsConverter<RadiusTrait, RadiusProps>;
|
|
20
|
+
frameFill: PropsConverter<FillTrait, FrameFillProps>;
|
|
21
|
+
shapeFill: PropsConverter<FillTrait, ShapeFillProps>;
|
|
22
|
+
textFill: PropsConverter<FillTrait, TextFillProps>;
|
|
23
|
+
vectorChildrenFill: PropsConverter<ContainerLayoutTrait, VectorChildrenFillProps>;
|
|
24
|
+
stroke: PropsConverter<StrokeTrait, StrokeProps>;
|
|
25
|
+
shadow: PropsConverter<ShadowTrait, ShadowProps>;
|
|
26
|
+
typeStyle: PropsConverter<TypeStyleTrait, TypeStyleProps>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ContainerLayoutTrait = NormalizedHasFramePropertiesTrait &
|
|
30
|
+
NormalizedHasChildrenTrait &
|
|
31
|
+
NormalizedHasLayoutTrait &
|
|
32
|
+
NormalizedIsLayerTrait;
|
|
33
|
+
|
|
34
|
+
export type SelfLayoutTrait = NormalizedIsLayerTrait & NormalizedHasLayoutTrait;
|
|
35
|
+
|
|
36
|
+
export type RadiusTrait = NormalizedCornerTrait & NormalizedIsLayerTrait;
|
|
37
|
+
|
|
38
|
+
export type FillTrait = NormalizedIsLayerTrait & NormalizedHasGeometryTrait;
|
|
39
|
+
|
|
40
|
+
export type StrokeTrait = NormalizedIsLayerTrait & NormalizedHasGeometryTrait;
|
|
41
|
+
|
|
42
|
+
export type ShadowTrait = NormalizedIsLayerTrait & NormalizedHasEffectsTrait;
|
|
43
|
+
|
|
44
|
+
export type TypeStyleTrait = NormalizedTypePropertiesTrait & NormalizedIsLayerTrait;
|
|
45
|
+
|
|
46
|
+
export interface ContainerLayoutProps {
|
|
47
|
+
direction?: "row" | "column";
|
|
48
|
+
justify?: "flex-start" | "center" | "flex-end" | "space-between";
|
|
49
|
+
align?: "stretch" | "flex-start" | "center" | "flex-end" | "baseline";
|
|
50
|
+
wrap?: "wrap" | "nowrap" | true;
|
|
51
|
+
gap?: string | 0;
|
|
52
|
+
pb?: string | 0;
|
|
53
|
+
pl?: string | 0;
|
|
54
|
+
pr?: string | 0;
|
|
55
|
+
pt?: string | 0;
|
|
56
|
+
px?: string | 0;
|
|
57
|
+
py?: string | 0;
|
|
58
|
+
p?: string | 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createContainerLayoutPropsConverter(
|
|
62
|
+
valueResolver: ReactValueResolver,
|
|
63
|
+
): PropsConverter<ContainerLayoutTrait, ContainerLayoutProps> {
|
|
64
|
+
return createPropsConverter({
|
|
65
|
+
_types: {
|
|
66
|
+
trait: {} as ContainerLayoutTrait,
|
|
67
|
+
props: {} as ContainerLayoutProps,
|
|
68
|
+
},
|
|
69
|
+
handlers: {
|
|
70
|
+
direction: ({ layoutMode }) =>
|
|
71
|
+
match(layoutMode)
|
|
72
|
+
.with("HORIZONTAL", () => "row" as const)
|
|
73
|
+
.with("VERTICAL", () => "column" as const)
|
|
74
|
+
.with("GRID", () => undefined)
|
|
75
|
+
.with("NONE", () => undefined)
|
|
76
|
+
.with(undefined, () => undefined)
|
|
77
|
+
.exhaustive(),
|
|
78
|
+
justify: ({ primaryAxisAlignItems }) =>
|
|
79
|
+
match(primaryAxisAlignItems)
|
|
80
|
+
.with("MIN", () => "flex-start" as const)
|
|
81
|
+
.with("CENTER", () => "center" as const)
|
|
82
|
+
.with("MAX", () => "flex-end" as const)
|
|
83
|
+
.with("SPACE_BETWEEN", () => "space-between" as const)
|
|
84
|
+
.with(undefined, () => undefined)
|
|
85
|
+
.exhaustive(),
|
|
86
|
+
align: ({ counterAxisAlignItems, children }) => {
|
|
87
|
+
const isStretch = children.every((child) => {
|
|
88
|
+
if (!("layoutAlign" in child)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return child.layoutAlign === "STRETCH";
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (isStretch) {
|
|
96
|
+
return "stretch";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return match(counterAxisAlignItems)
|
|
100
|
+
.with("MIN", () => "flex-start" as const)
|
|
101
|
+
.with("CENTER", () => "center" as const)
|
|
102
|
+
.with("MAX", () => "flex-end" as const)
|
|
103
|
+
.with("BASELINE", () => "baseline" as const)
|
|
104
|
+
.with(undefined, () => undefined)
|
|
105
|
+
.exhaustive();
|
|
106
|
+
},
|
|
107
|
+
wrap: ({ layoutWrap }) =>
|
|
108
|
+
match(layoutWrap)
|
|
109
|
+
.with("WRAP", () => true as const)
|
|
110
|
+
.with("NO_WRAP", () => "nowrap" as const)
|
|
111
|
+
.with(undefined, () => undefined)
|
|
112
|
+
.exhaustive(),
|
|
113
|
+
gap: (node) => {
|
|
114
|
+
if (node.children.length <= 1) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (node.primaryAxisAlignItems === "SPACE_BETWEEN") {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return valueResolver.getFormattedValue.itemSpacing(node);
|
|
123
|
+
},
|
|
124
|
+
pt: (node) => valueResolver.getFormattedValue.paddingTop(node),
|
|
125
|
+
pb: (node) => valueResolver.getFormattedValue.paddingBottom(node),
|
|
126
|
+
pl: (node) => valueResolver.getFormattedValue.paddingLeft(node),
|
|
127
|
+
pr: (node) => valueResolver.getFormattedValue.paddingRight(node),
|
|
128
|
+
},
|
|
129
|
+
shorthands: {
|
|
130
|
+
p: ["pt", "pb", "pl", "pr"],
|
|
131
|
+
px: ["pl", "pr"],
|
|
132
|
+
py: ["pt", "pb"],
|
|
133
|
+
},
|
|
134
|
+
defaults: {
|
|
135
|
+
justify: "flex-start",
|
|
136
|
+
align: "stretch",
|
|
137
|
+
wrap: "nowrap",
|
|
138
|
+
gap: "0px",
|
|
139
|
+
p: "0px",
|
|
140
|
+
px: "0px",
|
|
141
|
+
py: "0px",
|
|
142
|
+
pb: "0px",
|
|
143
|
+
pl: "0px",
|
|
144
|
+
pr: "0px",
|
|
145
|
+
pt: "0px",
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface SelfLayoutProps {
|
|
151
|
+
flexGrow?: 0 | 1 | true;
|
|
152
|
+
alignSelf?: "stretch";
|
|
153
|
+
width?: string | number;
|
|
154
|
+
height?: string | number;
|
|
155
|
+
minWidth?: string | number;
|
|
156
|
+
minHeight?: string | number;
|
|
157
|
+
maxWidth?: string | number;
|
|
158
|
+
maxHeight?: string | number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function createSelfLayoutPropsConverter(
|
|
162
|
+
valueResolver: ReactValueResolver,
|
|
163
|
+
): PropsConverter<SelfLayoutTrait, SelfLayoutProps> {
|
|
164
|
+
return createPropsConverter({
|
|
165
|
+
_types: {
|
|
166
|
+
trait: {} as SelfLayoutTrait,
|
|
167
|
+
props: {} as SelfLayoutProps,
|
|
168
|
+
},
|
|
169
|
+
handlers: {
|
|
170
|
+
flexGrow: ({ layoutGrow }) => (layoutGrow === 1 ? true : layoutGrow),
|
|
171
|
+
alignSelf: ({ layoutAlign }) =>
|
|
172
|
+
match(layoutAlign)
|
|
173
|
+
.with("STRETCH", () => "stretch" as const)
|
|
174
|
+
.with("INHERIT", () => undefined)
|
|
175
|
+
.with("MIN", () => undefined) // Deprecated in Figma
|
|
176
|
+
.with("CENTER", () => undefined) // Deprecated in Figma
|
|
177
|
+
.with("MAX", () => undefined) // Deprecated in Figma
|
|
178
|
+
.with(undefined, () => undefined)
|
|
179
|
+
.exhaustive(),
|
|
180
|
+
height: (node) =>
|
|
181
|
+
node.layoutSizingVertical === "FIXED"
|
|
182
|
+
? valueResolver.getFormattedValue.height(node)
|
|
183
|
+
: undefined,
|
|
184
|
+
width: (node) =>
|
|
185
|
+
node.layoutSizingHorizontal === "FIXED"
|
|
186
|
+
? valueResolver.getFormattedValue.width(node)
|
|
187
|
+
: undefined,
|
|
188
|
+
minHeight: (node) =>
|
|
189
|
+
node.layoutSizingVertical === "HUG"
|
|
190
|
+
? valueResolver.getFormattedValue.minHeight(node)
|
|
191
|
+
: undefined,
|
|
192
|
+
maxHeight: (node) =>
|
|
193
|
+
node.layoutSizingVertical === "HUG"
|
|
194
|
+
? valueResolver.getFormattedValue.maxHeight(node)
|
|
195
|
+
: undefined,
|
|
196
|
+
minWidth: (node) =>
|
|
197
|
+
node.layoutSizingHorizontal === "HUG"
|
|
198
|
+
? valueResolver.getFormattedValue.minWidth(node)
|
|
199
|
+
: undefined,
|
|
200
|
+
maxWidth: (node) =>
|
|
201
|
+
node.layoutSizingHorizontal === "HUG"
|
|
202
|
+
? valueResolver.getFormattedValue.maxWidth(node)
|
|
203
|
+
: undefined,
|
|
204
|
+
},
|
|
205
|
+
defaults: {
|
|
206
|
+
flexGrow: 0,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface IconSelfLayoutProps {
|
|
212
|
+
size?: string | number;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function createIconSelfLayoutPropsConverter(valueResolver: ReactValueResolver) {
|
|
216
|
+
return createPropsConverter({
|
|
217
|
+
_types: {
|
|
218
|
+
trait: {} as SelfLayoutTrait,
|
|
219
|
+
props: {} as IconSelfLayoutProps,
|
|
220
|
+
},
|
|
221
|
+
handlers: {
|
|
222
|
+
size: (node) => valueResolver.getFormattedValue.width(node),
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface RadiusProps {
|
|
228
|
+
borderRadius?: string | 0;
|
|
229
|
+
borderTopLeftRadius?: string | 0;
|
|
230
|
+
borderTopRightRadius?: string | 0;
|
|
231
|
+
borderBottomLeftRadius?: string | 0;
|
|
232
|
+
borderBottomRightRadius?: string | 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function createRadiusPropsConverter(valueResolver: ReactValueResolver) {
|
|
236
|
+
return createPropsConverter({
|
|
237
|
+
_types: {
|
|
238
|
+
trait: {} as RadiusTrait,
|
|
239
|
+
props: {} as RadiusProps,
|
|
240
|
+
},
|
|
241
|
+
handlers: {
|
|
242
|
+
borderTopLeftRadius: (node) => valueResolver.getFormattedValue.topLeftRadius(node),
|
|
243
|
+
borderTopRightRadius: (node) => valueResolver.getFormattedValue.topRightRadius(node),
|
|
244
|
+
borderBottomLeftRadius: (node) => valueResolver.getFormattedValue.bottomLeftRadius(node),
|
|
245
|
+
borderBottomRightRadius: (node) => valueResolver.getFormattedValue.bottomRightRadius(node),
|
|
246
|
+
},
|
|
247
|
+
shorthands: {
|
|
248
|
+
borderRadius: [
|
|
249
|
+
"borderTopLeftRadius",
|
|
250
|
+
"borderTopRightRadius",
|
|
251
|
+
"borderBottomLeftRadius",
|
|
252
|
+
"borderBottomRightRadius",
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
defaults: {
|
|
256
|
+
borderRadius: "0px",
|
|
257
|
+
borderTopLeftRadius: "0px",
|
|
258
|
+
borderTopRightRadius: "0px",
|
|
259
|
+
borderBottomLeftRadius: "0px",
|
|
260
|
+
borderBottomRightRadius: "0px",
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface TypeStyleProps {
|
|
266
|
+
textStyle?: string;
|
|
267
|
+
fontSize?: string;
|
|
268
|
+
fontWeight?: string | number;
|
|
269
|
+
lineHeight?: string;
|
|
270
|
+
maxLines?: number;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function createTypeStylePropsConverter({
|
|
274
|
+
valueResolver,
|
|
275
|
+
}: {
|
|
276
|
+
valueResolver: ReactValueResolver;
|
|
277
|
+
}): PropsConverter<TypeStyleTrait, TypeStyleProps> {
|
|
278
|
+
return definePropsConverter((node) => {
|
|
279
|
+
const styleName = valueResolver.getTextStyleValue(node);
|
|
280
|
+
const maxLines =
|
|
281
|
+
node.style.textTruncation === "ENDING" ? (node.style.maxLines ?? undefined) : undefined;
|
|
282
|
+
|
|
283
|
+
if (styleName) {
|
|
284
|
+
return {
|
|
285
|
+
textStyle: styleName,
|
|
286
|
+
maxLines,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
fontSize: valueResolver.getFormattedValue.fontSize(node),
|
|
292
|
+
fontWeight: valueResolver.getFormattedValue.fontWeight(node),
|
|
293
|
+
lineHeight: valueResolver.getFormattedValue.lineHeight(node),
|
|
294
|
+
maxLines,
|
|
295
|
+
};
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export type FrameFillProps =
|
|
300
|
+
| { bg?: string | undefined; bgGradient?: never; bgGradientDirection?: never }
|
|
301
|
+
| { bg?: never; bgGradient: string; bgGradientDirection?: string };
|
|
302
|
+
|
|
303
|
+
export function createFrameFillPropsConverter(valueResolver: ReactValueResolver) {
|
|
304
|
+
return definePropsConverter<FillTrait, FrameFillProps>((node) => {
|
|
305
|
+
const bg = valueResolver.getFormattedValue.frameFill(node);
|
|
306
|
+
|
|
307
|
+
if (bg === undefined || typeof bg === "string") {
|
|
308
|
+
return {
|
|
309
|
+
bg,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
bgGradient: bg.value,
|
|
315
|
+
...(bg.direction && { bgGradientDirection: bg.direction }),
|
|
316
|
+
};
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export interface ShapeFillProps {
|
|
321
|
+
color?: string;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function createShapeFillPropsConverter(valueResolver: ReactValueResolver) {
|
|
325
|
+
return definePropsConverter<FillTrait, ShapeFillProps>((node) => {
|
|
326
|
+
const color = valueResolver.getFormattedValue.shapeFill(node);
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
color,
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface TextFillProps {
|
|
335
|
+
color?: string;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function createTextFillPropsConverter(valueResolver: ReactValueResolver) {
|
|
339
|
+
return definePropsConverter<FillTrait, TextFillProps>((node) => {
|
|
340
|
+
const color = valueResolver.getFormattedValue.textFill(node);
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
color,
|
|
344
|
+
};
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface VectorChildrenFillProps {
|
|
349
|
+
color?: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function createVectorChildrenFillPropsConverter(valueResolver: ReactValueResolver) {
|
|
353
|
+
return definePropsConverter<ContainerLayoutTrait, VectorChildrenFillProps>((node) => {
|
|
354
|
+
if (node.children.length === 0) {
|
|
355
|
+
console.warn(
|
|
356
|
+
`createVectorChildrenFillPropsConverter: Node has no children. Name:${node.name}, ID:${node.id}`,
|
|
357
|
+
);
|
|
358
|
+
return {};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const vectors = node.children.filter(
|
|
362
|
+
(child) => child.type === "VECTOR" || child.type === "BOOLEAN_OPERATION",
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const colors = vectors.map((vector) => valueResolver.getFormattedValue.shapeFill(vector));
|
|
366
|
+
|
|
367
|
+
const fills = new Set(colors.filter((color) => color !== undefined));
|
|
368
|
+
|
|
369
|
+
// If there are more than 1 color, colors are likely pre-defined in the icon component; we should ignore the color prop.
|
|
370
|
+
if (fills.size > 1) {
|
|
371
|
+
return {};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return { color: fills.values().next().value };
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export interface StrokeProps {
|
|
379
|
+
borderWidth?: string;
|
|
380
|
+
borderColor?: string;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function createStrokePropsConverter(
|
|
384
|
+
valueResolver: ReactValueResolver,
|
|
385
|
+
): PropsConverter<StrokeTrait, StrokeProps> {
|
|
386
|
+
return definePropsConverter((node) => {
|
|
387
|
+
const borderColor = valueResolver.getFormattedValue.stroke(node);
|
|
388
|
+
const borderWidth = borderColor && node.strokeWeight ? `${node.strokeWeight}` : undefined;
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
borderColor,
|
|
392
|
+
borderWidth,
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export interface ShadowProps {
|
|
398
|
+
boxShadow?: string;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export function createShadowPropsConverter(
|
|
402
|
+
valueResolver: ReactValueResolver,
|
|
403
|
+
): PropsConverter<ShadowTrait, ShadowProps> {
|
|
404
|
+
return definePropsConverter((node: ShadowTrait) => {
|
|
405
|
+
const effectStyleName = valueResolver.getEffectStyleValue(node);
|
|
406
|
+
if (effectStyleName) {
|
|
407
|
+
return {
|
|
408
|
+
boxShadow: effectStyleName,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const boxShadow = valueResolver.getFormattedValue.boxShadow(node);
|
|
413
|
+
return {
|
|
414
|
+
boxShadow,
|
|
415
|
+
};
|
|
416
|
+
});
|
|
417
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NormalizedBooleanOperationNode,
|
|
3
|
+
NormalizedRectangleNode,
|
|
4
|
+
NormalizedVectorNode,
|
|
5
|
+
} from "@/normalizer";
|
|
6
|
+
import { createElement, defineElementTransformer, type ElementTransformer } from "../../core";
|
|
7
|
+
import { createSeedReactElement } from "./element-factories";
|
|
8
|
+
import type { PropsConverters } from "./props";
|
|
9
|
+
|
|
10
|
+
export interface RectangleTransformerDeps {
|
|
11
|
+
propsConverters: PropsConverters;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createRectangleTransformer({
|
|
15
|
+
propsConverters,
|
|
16
|
+
}: RectangleTransformerDeps): ElementTransformer<NormalizedRectangleNode> {
|
|
17
|
+
return defineElementTransformer((node: NormalizedRectangleNode) => {
|
|
18
|
+
return createSeedReactElement(
|
|
19
|
+
"Box",
|
|
20
|
+
{
|
|
21
|
+
...propsConverters.selfLayout(node),
|
|
22
|
+
...propsConverters.shadow(node),
|
|
23
|
+
background: "palette.gray200",
|
|
24
|
+
},
|
|
25
|
+
undefined,
|
|
26
|
+
{
|
|
27
|
+
comment: "Rectangle Node Placeholder",
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createVectorTransformer(): ElementTransformer<NormalizedVectorNode> {
|
|
34
|
+
return defineElementTransformer(() => {
|
|
35
|
+
return createElement("svg", {}, [], {
|
|
36
|
+
comment: "Vector Node Placeholder",
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createBooleanOperationTransformer(): ElementTransformer<NormalizedBooleanOperationNode> {
|
|
42
|
+
return defineElementTransformer(() => {
|
|
43
|
+
return createElement("svg", {}, [], {
|
|
44
|
+
comment: "Boolean Operation Node Placeholder",
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { NormalizedTextNode } from "@/normalizer";
|
|
2
|
+
import { compactObject } from "@/utils/common";
|
|
3
|
+
import { defineElementTransformer, type ElementTransformer } from "../../core";
|
|
4
|
+
import { createSeedReactElement } from "./element-factories";
|
|
5
|
+
import type { PropsConverters } from "./props";
|
|
6
|
+
|
|
7
|
+
export interface TextTransformerDeps {
|
|
8
|
+
propsConverters: PropsConverters;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function createTextTransformer({
|
|
12
|
+
propsConverters,
|
|
13
|
+
}: TextTransformerDeps): ElementTransformer<NormalizedTextNode> {
|
|
14
|
+
return defineElementTransformer((node: NormalizedTextNode) => {
|
|
15
|
+
const hasMultipleFills = node.fills.length > 1;
|
|
16
|
+
|
|
17
|
+
const fillProps = propsConverters.textFill(node);
|
|
18
|
+
const typeStyleProps = propsConverters.typeStyle(node);
|
|
19
|
+
|
|
20
|
+
const props = compactObject({
|
|
21
|
+
...typeStyleProps,
|
|
22
|
+
...fillProps,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return createSeedReactElement("Text", props, node.characters.replace(/\n/g, "<br />"), {
|
|
26
|
+
comment: hasMultipleFills
|
|
27
|
+
? "Multiple fills in Text node encountered, only the first fill is used."
|
|
28
|
+
: undefined,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { ValueResolver } from "@/codegen/core";
|
|
2
|
+
import { camelCasePreserveUnderscoreBetweenNumbers } from "@/utils/common";
|
|
3
|
+
import { toCssPixel, toCssRgba } from "@/utils/css";
|
|
4
|
+
import type { RGBA } from "@figma/rest-api-spec";
|
|
5
|
+
import { camelCase } from "change-case";
|
|
6
|
+
|
|
7
|
+
export type ReactValueResolver = ValueResolver<
|
|
8
|
+
string,
|
|
9
|
+
{ value: string; direction?: string },
|
|
10
|
+
string,
|
|
11
|
+
string,
|
|
12
|
+
number
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
export const defaultVariableNameFormatter = ({ slug }: { slug: string[] }) =>
|
|
16
|
+
slug
|
|
17
|
+
.filter(
|
|
18
|
+
(s) =>
|
|
19
|
+
!(
|
|
20
|
+
s === "dimension" ||
|
|
21
|
+
s === "radius" ||
|
|
22
|
+
s === "font-size" ||
|
|
23
|
+
s === "font-weight" ||
|
|
24
|
+
s === "line-height"
|
|
25
|
+
),
|
|
26
|
+
)
|
|
27
|
+
.map((s) => s.replaceAll(",", "_"))
|
|
28
|
+
.map(camelCasePreserveUnderscoreBetweenNumbers)
|
|
29
|
+
.join(".");
|
|
30
|
+
|
|
31
|
+
export const defaultTextStyleNameFormatter = ({ slug }: { slug: string[] }) => {
|
|
32
|
+
return camelCase(slug[slug.length - 1]!, { mergeAmbiguousCharacters: true });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const defaultEffectStyleNameFormatter = ({ slug }: { slug: string[] }) => {
|
|
36
|
+
return camelCase(slug[slug.length - 1]!, { mergeAmbiguousCharacters: true });
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const defaultFillStyleResolver = ({ slug }: { slug: string[] }) => {
|
|
40
|
+
const [, ...rest] = slug;
|
|
41
|
+
|
|
42
|
+
if (rest[0] === "fade") {
|
|
43
|
+
// ["fade", "layer-default", "↓(to-bottom)"]
|
|
44
|
+
|
|
45
|
+
const last = rest[rest.length - 1];
|
|
46
|
+
|
|
47
|
+
const direction = (() => {
|
|
48
|
+
if (last.startsWith("↓")) return "to bottom";
|
|
49
|
+
if (last.startsWith("↑")) return "to top";
|
|
50
|
+
if (last.startsWith("→")) return "to right";
|
|
51
|
+
if (last.startsWith("←")) return "to left";
|
|
52
|
+
|
|
53
|
+
return "unknown";
|
|
54
|
+
})();
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
value: camelCase(rest.slice(0, -1).join("-"), { mergeAmbiguousCharacters: true }),
|
|
58
|
+
direction,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
value: camelCase(rest.join("-"), { mergeAmbiguousCharacters: true }),
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function formatBoxShadow({
|
|
68
|
+
type,
|
|
69
|
+
color,
|
|
70
|
+
offset,
|
|
71
|
+
radius,
|
|
72
|
+
spread,
|
|
73
|
+
}: {
|
|
74
|
+
type: "DROP_SHADOW" | "INNER_SHADOW";
|
|
75
|
+
color: RGBA;
|
|
76
|
+
offset: { x: number; y: number };
|
|
77
|
+
radius: number;
|
|
78
|
+
spread?: number;
|
|
79
|
+
}): string {
|
|
80
|
+
const inset = type === "INNER_SHADOW" ? "inset " : "";
|
|
81
|
+
const colorStr = toCssRgba(color);
|
|
82
|
+
const spreadStr = spread ? ` ${spread}px` : "";
|
|
83
|
+
|
|
84
|
+
return `${inset}${offset.x}px ${offset.y}px ${radius}px${spreadStr} ${colorStr}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const defaultRawValueFormatters = {
|
|
88
|
+
color: (value: RGBA) => toCssRgba(value),
|
|
89
|
+
dimension: (value: number) => toCssPixel(value),
|
|
90
|
+
fontDimension: (value: number) => toCssPixel(value),
|
|
91
|
+
fontWeight: (value: number) => value,
|
|
92
|
+
boxShadow: formatBoxShadow,
|
|
93
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentMetadata } from "./component.interface";
|
|
2
|
+
|
|
3
|
+
export interface ComponentRepository {
|
|
4
|
+
getOne(key: string): ComponentMetadata | undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function createStaticComponentRepository(data: Record<string, ComponentMetadata>) {
|
|
8
|
+
const componentRecord: Record<string, ComponentMetadata> = {};
|
|
9
|
+
Object.values(data).forEach((component) => {
|
|
10
|
+
componentRecord[component.key] = component;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
getOne: (key: string) => componentRecord[key],
|
|
15
|
+
};
|
|
16
|
+
}
|