@seed-design/figma 0.0.2 → 0.0.4

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 (53) hide show
  1. package/lib/index.cjs +556 -471
  2. package/lib/index.d.ts +29 -4
  3. package/lib/index.js +556 -471
  4. package/package.json +2 -2
  5. package/src/component/handlers/action-button.ts +66 -0
  6. package/src/component/handlers/action-chip.ts +71 -0
  7. package/src/component/handlers/action-sheet.ts +74 -0
  8. package/src/component/handlers/app-bar.ts +183 -0
  9. package/src/component/handlers/avatar-stack.ts +35 -0
  10. package/src/component/handlers/avatar.ts +37 -0
  11. package/src/component/handlers/badge.ts +20 -0
  12. package/src/component/handlers/callout.ts +87 -0
  13. package/src/component/handlers/checkbox.ts +32 -0
  14. package/src/component/handlers/chip-tabs.ts +51 -0
  15. package/src/component/handlers/control-chip.ts +75 -0
  16. package/src/component/handlers/error-state.ts +37 -0
  17. package/src/component/handlers/extended-action-sheet.ts +86 -0
  18. package/src/component/handlers/extended-fab.ts +24 -0
  19. package/src/component/handlers/fab.ts +17 -0
  20. package/src/component/handlers/help-bubble.ts +66 -0
  21. package/src/component/handlers/identity-placeholder.ts +16 -0
  22. package/src/component/handlers/inline-banner.ts +83 -0
  23. package/src/component/handlers/manner-temp-badge.ts +17 -0
  24. package/src/component/handlers/multiline-text-field.ts +80 -0
  25. package/src/component/handlers/progress-circle.ts +49 -0
  26. package/src/component/handlers/reaction-button.ts +36 -0
  27. package/src/component/handlers/segmented-control.ts +51 -0
  28. package/src/component/handlers/select-box.ts +76 -0
  29. package/src/component/handlers/skeleton.ts +51 -0
  30. package/src/component/handlers/snackbar.ts +21 -0
  31. package/src/component/handlers/switch.ts +29 -0
  32. package/src/component/handlers/tabs.ts +107 -0
  33. package/src/component/handlers/text-button.ts +57 -0
  34. package/src/component/handlers/text-field.ts +108 -0
  35. package/src/component/handlers/toggle-button.ts +44 -0
  36. package/src/component/index.ts +32 -1644
  37. package/src/component/type-helper.ts +11 -0
  38. package/src/generate-code.ts +183 -145
  39. package/src/icon.ts +2 -2
  40. package/src/index.ts +1 -2
  41. package/src/jsx.ts +1 -1
  42. package/src/layout.ts +23 -281
  43. package/src/normalizer/from-plugin.ts +24 -4
  44. package/src/normalizer/from-rest.ts +22 -4
  45. package/src/normalizer/index.ts +3 -0
  46. package/src/normalizer/types.ts +3 -1
  47. package/src/{color.ts → props/color.ts} +1 -1
  48. package/src/props/layout.ts +292 -0
  49. package/src/{sizing.ts → props/sizing.ts} +17 -17
  50. package/src/{text.ts → props/text.ts} +2 -1
  51. package/src/{variable.ts → props/variable.ts} +1 -1
  52. package/src/{util.ts → utils/common.ts} +0 -2
  53. package/src/{node-util.ts → utils/figma-node.ts} +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-design/figma",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/daangn/seed-design.git",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@create-figma-plugin/utilities": "^3.0.2",
32
- "@seed-design/css": "0.0.10",
32
+ "@seed-design/css": "0.0.12",
33
33
  "change-case": "^5.2.0",
34
34
  "ts-pattern": "^5.2.0"
35
35
  },
@@ -0,0 +1,66 @@
1
+ import { camelCase } from "change-case";
2
+ import { match } from "ts-pattern";
3
+ import * as metadata from "../../data/__generated__/component-sets";
4
+ import { createIconTagNameFromKey } from "../../icon";
5
+ import { createElement } from "../../jsx";
6
+ import { handleSize } from "../properties";
7
+ import type { ActionButtonProperties } from "../type";
8
+ import type { ComponentHandler } from "../type-helper";
9
+
10
+ export const actionButtonHandler: ComponentHandler<ActionButtonProperties> = {
11
+ key: metadata.actionButton.key,
12
+ codegen: async ({ componentProperties: props }) => {
13
+ const states = props.State.value.split("-");
14
+
15
+ const { layout, children } = await match(props.Layout.value)
16
+ .with("Icon Only", async () => ({
17
+ layout: "iconOnly",
18
+ children: [
19
+ createElement("Icon", {
20
+ svg: createElement(createIconTagNameFromKey(props["Icon#7574:0"].componentKey)),
21
+ }),
22
+ ],
23
+ }))
24
+ .with("Icon First", async () => ({
25
+ layout: "withText",
26
+ children: [
27
+ createElement("PrefixIcon", {
28
+ svg: createElement(
29
+ createIconTagNameFromKey(props["Prefix Icon#5987:305"].componentKey),
30
+ ),
31
+ }),
32
+ props["Label#5987:61"].value,
33
+ ],
34
+ }))
35
+ .with("Icon Last", async () => ({
36
+ layout: "withText",
37
+ children: [
38
+ props["Label#5987:61"].value,
39
+ createElement("SuffixIcon", {
40
+ svg: createElement(
41
+ createIconTagNameFromKey(props["Suffix Icon#5987:244"].componentKey),
42
+ ),
43
+ }),
44
+ ],
45
+ }))
46
+ .with("Text Only", () => ({
47
+ layout: "withText",
48
+ children: props["Label#5987:61"].value,
49
+ }))
50
+ .exhaustive();
51
+
52
+ const commonProps = {
53
+ ...(states.includes("Disabled") && {
54
+ disabled: true,
55
+ }),
56
+ ...(states.includes("Loading") && {
57
+ loading: true,
58
+ }),
59
+ size: handleSize(props.Size.value),
60
+ variant: camelCase(props.Variant.value),
61
+ layout,
62
+ };
63
+
64
+ return createElement("ActionButton", commonProps, children);
65
+ },
66
+ };
@@ -0,0 +1,71 @@
1
+ import { match } from "ts-pattern";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createIconTagNameFromKey } from "../../icon";
4
+ import { createElement } from "../../jsx";
5
+ import { handleSize } from "../properties";
6
+ import type { ActionChipProperties } from "../type";
7
+ import type { ComponentHandler } from "../type-helper";
8
+
9
+ export const actionChipHandler: ComponentHandler<ActionChipProperties> = {
10
+ key: metadata.actionChip.key,
11
+ codegen: async ({ componentProperties: props }) => {
12
+ const states = props.State.value.split("-");
13
+
14
+ const { layout, children } = await match(props.Layout.value)
15
+ .with("Icon Only", async () => ({
16
+ layout: "iconOnly",
17
+ children: [
18
+ createElement("Icon", {
19
+ svg: createElement(createIconTagNameFromKey(props["Icon#8714:0"].componentKey)),
20
+ }),
21
+ ],
22
+ }))
23
+ .with("Icon First", async () => ({
24
+ layout: "withText",
25
+ children: [
26
+ createElement("PrefixIcon", {
27
+ svg: createElement(createIconTagNameFromKey(props["Prefix Icon#8711:0"].componentKey)),
28
+ }),
29
+ props["Label#7185:0"].value,
30
+ ],
31
+ }))
32
+ .with("Icon Last", async () => ({
33
+ layout: "withText",
34
+ children: [
35
+ props["Label#7185:0"].value,
36
+ createElement("SuffixIcon", {
37
+ svg: createElement(createIconTagNameFromKey(props["Suffix Icon#8711:3"].componentKey)),
38
+ }),
39
+ ],
40
+ }))
41
+ .with("Icon Both", async () => ({
42
+ layout: "withText",
43
+ children: [
44
+ createElement("PrefixIcon", {
45
+ svg: createElement(createIconTagNameFromKey(props["Prefix Icon#8711:0"].componentKey)),
46
+ }),
47
+ props["Label#7185:0"].value,
48
+ createElement("SuffixIcon", {
49
+ svg: createElement(createIconTagNameFromKey(props["Suffix Icon#8711:3"].componentKey)),
50
+ }),
51
+ ],
52
+ }))
53
+ .with("Text Only", () => ({
54
+ layout: "withText",
55
+ children: props["Label#7185:0"].value,
56
+ }))
57
+ .exhaustive();
58
+
59
+ const commonProps = {
60
+ size: handleSize(props.Size.value),
61
+ layout,
62
+ ...(states.includes("Disabled") && {
63
+ disabled: true,
64
+ }),
65
+ ...(props["Show Count#7185:42"].value && {
66
+ count: Number(props["Count#7185:21"].value),
67
+ }),
68
+ };
69
+ return createElement("ActionChip", commonProps, children);
70
+ },
71
+ };
@@ -0,0 +1,74 @@
1
+ import { camelCase } from "change-case";
2
+ import { match } from "ts-pattern";
3
+ import * as metadata from "../../data/__generated__/component-sets";
4
+ import { createElement } from "../../jsx";
5
+ import { findAllInstances } from "../../utils/figma-node";
6
+ import type { ActionSheetItemProperties, ActionSheetProperties } from "../type";
7
+ import type { ComponentHandler } from "../type-helper";
8
+
9
+ export const actionSheetHandler: ComponentHandler<ActionSheetProperties> = {
10
+ key: metadata.actionSheet.key,
11
+ codegen: async (node) => {
12
+ const { componentProperties: props } = node;
13
+
14
+ const contentProps = match(props.Header.value)
15
+ .with("None", () => ({
16
+ title: undefined,
17
+ description: undefined,
18
+ }))
19
+ .with("Title Only", () => ({
20
+ title: props["Title#15641:37"].value,
21
+ description: undefined,
22
+ }))
23
+ .with("Description Only", () => ({
24
+ title: undefined,
25
+ description: props["Description#15641:70"].value,
26
+ }))
27
+ .with("Title With Description", () => ({
28
+ title: props["Title#15641:37"].value,
29
+ description: props["Description#15641:70"].value,
30
+ }))
31
+ .exhaustive();
32
+
33
+ const items = await findAllInstances<ActionSheetItemProperties>({
34
+ node,
35
+ key: actionSheetItemHandler.key,
36
+ });
37
+
38
+ const contentChildren = await Promise.all(items.map(actionSheetItemHandler.codegen));
39
+
40
+ const content = createElement(
41
+ "ActionSheetContent",
42
+ contentProps,
43
+ contentChildren,
44
+ contentProps.title
45
+ ? ""
46
+ : "title을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.",
47
+ );
48
+
49
+ const trigger = createElement(
50
+ "ActionSheetTrigger",
51
+ { asChild: true },
52
+ createElement("ActionButton", undefined, "열기", "ActionSheet을 여는 요소를 제공해주세요."),
53
+ );
54
+
55
+ return createElement("ActionSheet", undefined, [trigger, content]);
56
+ },
57
+ };
58
+
59
+ const actionSheetItemHandler: ComponentHandler<ActionSheetItemProperties> = {
60
+ key: "c3cafd3a3fdcd45fecb6971019d88eaf39a2e381",
61
+ codegen: async ({ componentProperties: props }) => {
62
+ const states = props.State.value.split("-");
63
+
64
+ const commonProps = {
65
+ label: props["Label#15420:4"].value,
66
+ tone: camelCase(props.Tone.value),
67
+ ...(states.includes("Disabled") && {
68
+ disabled: true,
69
+ }),
70
+ };
71
+
72
+ return createElement("ActionSheetItem", commonProps);
73
+ },
74
+ };
@@ -0,0 +1,183 @@
1
+ import { match } from "ts-pattern";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createIconTagNameFromKey } from "../../icon";
4
+ import { createElement } from "../../jsx";
5
+ import { findAll, findAllInstances, findOne } from "../../utils/figma-node";
6
+ import type { NormalizedInstanceNode, NormalizedTextNode } from "../../normalizer";
7
+ import type {
8
+ AppBarLeftProperties,
9
+ AppBarMainProperties,
10
+ AppBarProperties,
11
+ AppBarRightProperties,
12
+ } from "../type";
13
+ import type { ComponentHandler } from "../type-helper";
14
+
15
+ export const appBarHandler: ComponentHandler<AppBarProperties> = {
16
+ key: metadata.standardNavigation.key,
17
+ codegen: async (node) => {
18
+ const props = node.componentProperties;
19
+
20
+ const theme = (() => {
21
+ switch (props.OS.value) {
22
+ case "Android":
23
+ return "android";
24
+ case "iOS":
25
+ return "cupertino";
26
+ }
27
+ })();
28
+
29
+ const tone = (() => {
30
+ switch (props.Variant.value) {
31
+ case "Layer Default":
32
+ return "layer";
33
+ case "Transparent":
34
+ return "transparent";
35
+ }
36
+ })();
37
+
38
+ const mainNode = await findAllInstances<AppBarMainProperties>({
39
+ key: appBarMainHandler.key,
40
+ node,
41
+ });
42
+ const onlyMainNode = mainNode.length === 1 ? mainNode[0] : undefined;
43
+ const main = onlyMainNode ? await appBarMainHandler.codegen(onlyMainNode) : undefined;
44
+
45
+ const leftNode = await findAllInstances<AppBarLeftProperties>({
46
+ key: appBarLeftHandler.key,
47
+ node,
48
+ });
49
+ const onlyLeftNode = leftNode.length === 1 ? leftNode[0] : undefined;
50
+ const left = onlyLeftNode ? await appBarLeftHandler.codegen(onlyLeftNode) : undefined;
51
+
52
+ const rightNode = await findAllInstances<AppBarRightProperties>({
53
+ key: appBarRightHandler.key,
54
+ node,
55
+ });
56
+ const onlyRightNode = rightNode.length === 1 ? rightNode[0] : undefined;
57
+ const right = onlyRightNode ? await appBarRightHandler.codegen(onlyRightNode) : undefined;
58
+
59
+ return createElement(
60
+ "AppBar",
61
+ { theme, tone },
62
+ [left, main, right].filter(Boolean),
63
+ tone === "transparent"
64
+ ? `<AppScreen layerOffsetTop="none">으로 상단 패딩을 제거할 수 있습니다.`
65
+ : undefined,
66
+ );
67
+ },
68
+ };
69
+
70
+ const appBarMainHandler: ComponentHandler<AppBarMainProperties> = {
71
+ key: "336b49b26c3933485d87cc460b06c390976ea58e",
72
+ codegen: async ({ componentProperties: props }) => {
73
+ const { title, subtitle, layout } = match(props.Type.value)
74
+ .with("Title", () => ({
75
+ title: props["Title#16944:0"].value,
76
+ subtitle: undefined,
77
+ layout: undefined,
78
+ }))
79
+ .with("Title-Subtitle", () => ({
80
+ title: props["Title#16944:0"].value,
81
+ subtitle: props["Subtitle#16958:9"].value,
82
+ layout: "withSubtitle",
83
+ }))
84
+ .otherwise(() => ({
85
+ title: undefined,
86
+ subtitle: undefined,
87
+ layout: undefined,
88
+ }));
89
+
90
+ const commonProps = {
91
+ title,
92
+ subtitle,
93
+ layout,
94
+ };
95
+
96
+ return createElement(
97
+ "AppBarMain",
98
+ commonProps,
99
+ undefined,
100
+ title === undefined ? "Title을 제공해주세요." : undefined,
101
+ );
102
+ },
103
+ };
104
+
105
+ const appBarLeftHandler: ComponentHandler<AppBarLeftProperties> = {
106
+ key: "e5d2e47052a22395db79f195a0991a570dc1b6c9",
107
+ codegen: async (node) => {
108
+ const props = node.componentProperties;
109
+
110
+ const children = await (async () => {
111
+ switch (props.Action.value) {
112
+ case "Back":
113
+ return createElement("AppBarBackButton", undefined);
114
+ case "Close":
115
+ return createElement("AppBarCloseButton", undefined);
116
+ case "Other": {
117
+ const iconNode = findOne(
118
+ node,
119
+ (child) => child.type === "INSTANCE" && child.name === "Icon",
120
+ ) as NormalizedInstanceNode | null;
121
+
122
+ const iconComponentKey = iconNode?.componentKey ?? undefined;
123
+
124
+ return createElement(
125
+ "AppBarIconButton",
126
+ undefined,
127
+ iconComponentKey
128
+ ? createElement(createIconTagNameFromKey(iconComponentKey))
129
+ : undefined,
130
+ iconComponentKey === undefined
131
+ ? "아이콘과, aria-label 또는 aria-labelledby를 제공해주세요."
132
+ : "aria-label 또는 aria-labelledby를 제공해주세요.",
133
+ );
134
+ }
135
+ }
136
+ })();
137
+
138
+ return createElement("AppBarLeft", undefined, children);
139
+ },
140
+ };
141
+
142
+ const appBarRightHandler: ComponentHandler<AppBarRightProperties> = {
143
+ key: "9e157fc2d1f89ffee938a5bc62f4a58064fec44e",
144
+ codegen: async (node) => {
145
+ const props = node.componentProperties;
146
+
147
+ const children = await (async () => {
148
+ switch (props.Type.value) {
149
+ case "1 Text": {
150
+ const textNode = findOne(
151
+ node,
152
+ (child) => child.type === "TEXT",
153
+ ) as NormalizedTextNode | null;
154
+
155
+ return textNode?.characters;
156
+ }
157
+ default: {
158
+ const iconNodes = findAll(
159
+ node,
160
+ (child) => child.type === "INSTANCE" && child.name === "Icon",
161
+ ) as NormalizedInstanceNode[];
162
+
163
+ const iconComponentKeys = iconNodes.map((iconNode) => iconNode.componentKey);
164
+
165
+ return iconComponentKeys.map((iconComponentKey) =>
166
+ createElement(
167
+ "AppBarIconButton",
168
+ undefined,
169
+ iconComponentKey
170
+ ? createElement(createIconTagNameFromKey(iconComponentKey))
171
+ : undefined,
172
+ iconComponentKey === undefined
173
+ ? "아이콘과, aria-label 또는 aria-labelledby를 제공해주세요."
174
+ : "aria-label 또는 aria-labelledby를 제공해주세요.",
175
+ ),
176
+ );
177
+ }
178
+ }
179
+ })();
180
+
181
+ return createElement("AppBarRight", undefined, children);
182
+ },
183
+ };
@@ -0,0 +1,35 @@
1
+ import * as metadata from "../../data/__generated__/component-sets";
2
+ import { createElement } from "../../jsx";
3
+ import { findAllInstances } from "../../utils/figma-node";
4
+ import type { AvatarProperties, AvatarStackProperties } from "../type";
5
+ import type { ComponentHandler } from "../type-helper";
6
+ import { avatarHandler } from "./avatar";
7
+
8
+ export const avatarStackHandler: ComponentHandler<AvatarStackProperties> = {
9
+ key: metadata.avatarStack.key,
10
+ codegen: async (node) => {
11
+ const avatarNodes = await findAllInstances<AvatarProperties>({
12
+ node,
13
+ key: avatarHandler.key,
14
+ });
15
+
16
+ const { componentProperties: props } = node;
17
+
18
+ const commonProps = {
19
+ size: props.Size.value,
20
+ // TODO: 구현될 예정
21
+ // topItem: camelCase(props["Top Item"].value),
22
+ };
23
+
24
+ const avatarStackChildren = (await Promise.all(avatarNodes.map(avatarHandler.codegen))).map(
25
+ (avatar) => {
26
+ return {
27
+ ...avatar,
28
+ props: { ...avatar.props, size: undefined },
29
+ };
30
+ },
31
+ );
32
+
33
+ return createElement("AvatarStack", commonProps, avatarStackChildren);
34
+ },
35
+ };
@@ -0,0 +1,37 @@
1
+ import * as metadata from "../../data/__generated__/component-sets";
2
+ import { createElement } from "../../jsx";
3
+ import { findAllInstances } from "../../utils/figma-node";
4
+ import type { AvatarProperties, IdentityPlaceholderProperties } from "../type";
5
+ import type { ComponentHandler } from "../type-helper";
6
+ import { identityPlaceholderHandler } from "./identity-placeholder";
7
+
8
+ export const avatarHandler: ComponentHandler<AvatarProperties> = {
9
+ key: metadata.avatar.key,
10
+ codegen: async (node) => {
11
+ const [placeholder] = findAllInstances<IdentityPlaceholderProperties>({
12
+ node,
13
+ key: identityPlaceholderHandler.key,
14
+ });
15
+ const { componentProperties: props } = node;
16
+
17
+ const avatarHasSrc = props["Show Image#71850:57"].value;
18
+
19
+ const commonProps = {
20
+ ...(avatarHasSrc && {
21
+ // Placeholder
22
+ src: `https://placehold.co/${props.Size.value}x${props.Size.value}`,
23
+ }),
24
+ ...(placeholder && {
25
+ fallback: await identityPlaceholderHandler.codegen(placeholder),
26
+ }),
27
+ size: props.Size.value,
28
+ };
29
+
30
+ return createElement(
31
+ "Avatar",
32
+ commonProps,
33
+ props["Show Badge#1398:26"].value ? createElement("AvatarBadge", {}) : undefined,
34
+ avatarHasSrc ? "alt 텍스트를 제공해야 합니다." : undefined,
35
+ );
36
+ },
37
+ };
@@ -0,0 +1,20 @@
1
+ import { camelCase } from "change-case";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createElement } from "../../jsx";
4
+ import { handleSize } from "../properties";
5
+ import type { BadgeProperties } from "../type";
6
+ import type { ComponentHandler } from "../type-helper";
7
+
8
+ export const badgeHandler: ComponentHandler<BadgeProperties> = {
9
+ key: metadata.badge.key,
10
+ codegen: async ({ componentProperties: props }) => {
11
+ const commonProps = {
12
+ size: handleSize(props.Size.value),
13
+ tone: camelCase(props.Tone.value),
14
+ variant: camelCase(props.Variant.value),
15
+ shape: camelCase(props.Shape.value),
16
+ };
17
+
18
+ return createElement("Badge", commonProps, props["Label#1584:0"].value);
19
+ },
20
+ };
@@ -0,0 +1,87 @@
1
+ import { camelCase } from "change-case";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createIconTagNameFromKey } from "../../icon";
4
+ import { createElement } from "../../jsx";
5
+ import type { NormalizedTextNode } from "../../normalizer";
6
+ import type { ComponentHandler } from "../type-helper";
7
+ import type { CalloutProperties } from "../type";
8
+
9
+ export const calloutHandler: ComponentHandler<CalloutProperties> = {
10
+ key: metadata.callout.key,
11
+ codegen: async ({ componentProperties: props, children }) => {
12
+ const tag = (() => {
13
+ switch (props.Interaction.value) {
14
+ case "Default":
15
+ return "Callout";
16
+ case "Actionable":
17
+ return "ActionableCallout";
18
+ case "Dismissible":
19
+ return "DismissibleCallout";
20
+ default:
21
+ return "Callout";
22
+ }
23
+ })();
24
+
25
+ const textNode = children.find((child) => child.type === "TEXT") as NormalizedTextNode | null;
26
+
27
+ if (!textNode) {
28
+ return createElement(tag, undefined, undefined, "내용을 제공해주세요.");
29
+ }
30
+
31
+ const slices = textNode.segments;
32
+
33
+ let title: string | undefined;
34
+ let description: string | undefined;
35
+ let linkLabel: string | undefined;
36
+
37
+ switch (slices.length) {
38
+ case 1: {
39
+ description = slices[0]?.characters.trim();
40
+
41
+ break;
42
+ }
43
+ case 2: {
44
+ const firstSlice = slices[0];
45
+ const secondSlice = slices[1];
46
+
47
+ if (firstSlice?.style.fontWeight === 700) {
48
+ title = firstSlice?.characters.trim();
49
+ description = secondSlice?.characters.trim();
50
+ break;
51
+ }
52
+
53
+ description = firstSlice?.characters.trim();
54
+
55
+ if (tag !== "ActionableCallout") {
56
+ linkLabel = secondSlice?.characters.trim();
57
+ }
58
+
59
+ break;
60
+ }
61
+ case 3: {
62
+ title = slices[0]?.characters.trim();
63
+ description = slices[1]?.characters.trim();
64
+
65
+ if (tag !== "ActionableCallout") {
66
+ linkLabel = slices[2]?.characters.trim();
67
+ }
68
+
69
+ break;
70
+ }
71
+ }
72
+
73
+ const commonProps = {
74
+ tone: camelCase(props.Tone.value),
75
+ title,
76
+ description,
77
+ linkProps: {
78
+ children: linkLabel,
79
+ },
80
+ ...(props["Icon#12598:210"].value && {
81
+ prefixIcon: createElement(createIconTagNameFromKey(props["Icon#12598:210"].componentKey)),
82
+ }),
83
+ };
84
+
85
+ return createElement(tag, commonProps);
86
+ },
87
+ };
@@ -0,0 +1,32 @@
1
+ import { camelCase } from "change-case";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createElement } from "../../jsx";
4
+ import { handleSize } from "../properties";
5
+ import type { CheckboxProperties } from "../type";
6
+ import type { ComponentHandler } from "../type-helper";
7
+
8
+ export const checkboxHandler: ComponentHandler<CheckboxProperties> = {
9
+ key: metadata.checkbox.key,
10
+ codegen: async ({ componentProperties: props }) => {
11
+ const states = props.State.value.split("-");
12
+
13
+ const commonProps = {
14
+ label: props["Label#49990:0"].value,
15
+ weight: camelCase(props.Weight.value),
16
+ variant: camelCase(props.Shape.value),
17
+ size: handleSize(props.Size.value),
18
+ ...(states.includes("Selected") && {
19
+ defaultChecked: true,
20
+ }),
21
+ ...(states.includes("Indeterminate") && {
22
+ defaultChecked: true,
23
+ indeterminate: true,
24
+ }),
25
+ ...(states.includes("Disabled") && {
26
+ disabled: true,
27
+ }),
28
+ };
29
+
30
+ return createElement("Checkbox", commonProps);
31
+ },
32
+ };
@@ -0,0 +1,51 @@
1
+ import { camelCase } from "change-case";
2
+ import * as metadata from "../../data/__generated__/component-sets";
3
+ import { createElement } from "../../jsx";
4
+ import { findAllInstances } from "../../utils/figma-node";
5
+ import type { ChipTabsItemProperties, ChipTabsProperties } from "../type";
6
+ import type { ComponentHandler } from "../type-helper";
7
+
8
+ export const chipTabsHandler: ComponentHandler<ChipTabsProperties> = {
9
+ key: metadata.chipTablist.key,
10
+ codegen: async (node) => {
11
+ const chipTabsItems = findAllInstances<ChipTabsItemProperties>({
12
+ node,
13
+ key: chipTabsItemHandler.key,
14
+ });
15
+
16
+ const selectedChipTabsItem = chipTabsItems.find((chipTabsItem) =>
17
+ chipTabsItem.componentProperties.State.value.split("-").includes("Selected"),
18
+ );
19
+
20
+ const chipTabsList = createElement(
21
+ "ChipTabsList",
22
+ undefined,
23
+ await Promise.all(chipTabsItems.map(chipTabsItemHandler.codegen)),
24
+ );
25
+
26
+ const commonProps = {
27
+ variant: camelCase(node.componentProperties.Variant.value),
28
+ ...(selectedChipTabsItem && {
29
+ defaultValue: selectedChipTabsItem.componentProperties["Label#8876:0"].value,
30
+ }),
31
+ };
32
+
33
+ return createElement("ChipTabs", commonProps, chipTabsList);
34
+ },
35
+ };
36
+
37
+ const chipTabsItemHandler: ComponentHandler<ChipTabsItemProperties> = {
38
+ key: "fa80168b02051fbb0ba032238bd76d840dbe2e15",
39
+ codegen: async ({ componentProperties: props }) => {
40
+ const states = props.State.value.split("-");
41
+
42
+ const commonProps = {
43
+ value: props["Label#8876:0"].value,
44
+ ...(states.includes("Disabled") && {
45
+ disabled: true,
46
+ }),
47
+ };
48
+
49
+ return createElement("ChipTabsTrigger", commonProps, props["Label#8876:0"].value);
50
+ },
51
+ };