@seed-design/figma 0.1.6 → 0.1.8

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 (165) hide show
  1. package/lib/codegen/index.cjs +746 -646
  2. package/lib/codegen/index.d.ts +707 -627
  3. package/lib/codegen/index.d.ts.map +1 -1
  4. package/lib/codegen/index.js +746 -646
  5. package/lib/codegen/targets/react/index.cjs +1170 -1180
  6. package/lib/codegen/targets/react/index.d.ts +20 -9
  7. package/lib/codegen/targets/react/index.d.ts.map +1 -1
  8. package/lib/codegen/targets/react/index.js +1170 -1180
  9. package/lib/index.cjs +883 -668
  10. package/lib/index.d.ts +3 -1
  11. package/lib/index.d.ts.map +1 -1
  12. package/lib/index.js +883 -668
  13. package/package.json +3 -3
  14. package/src/codegen/component-properties.ts +283 -146
  15. package/src/codegen/core/component-handler.ts +9 -3
  16. package/src/codegen/core/jsx.ts +7 -2
  17. package/src/codegen/core/value-resolver.ts +35 -21
  18. package/src/codegen/targets/figma/pipeline.ts +4 -2
  19. package/src/codegen/targets/figma/value-resolver.ts +38 -2
  20. package/src/codegen/targets/react/component/handlers/action-button.ts +69 -5
  21. package/src/codegen/targets/react/component/handlers/alert-dialog.ts +81 -0
  22. package/src/codegen/targets/react/component/handlers/app-bar.ts +93 -128
  23. package/src/codegen/targets/react/component/handlers/avatar.ts +17 -8
  24. package/src/codegen/targets/react/component/handlers/badge.ts +0 -1
  25. package/src/codegen/targets/react/component/handlers/bottom-sheet.ts +71 -0
  26. package/src/codegen/targets/react/component/handlers/callout.ts +13 -17
  27. package/src/codegen/targets/react/component/handlers/chip.ts +66 -0
  28. package/src/codegen/targets/react/component/handlers/contextual-floating-button.ts +52 -0
  29. package/src/codegen/targets/react/component/handlers/divider.ts +19 -0
  30. package/src/codegen/targets/react/component/handlers/error-state.ts +26 -23
  31. package/src/codegen/targets/react/component/handlers/floating-action-button.ts +48 -0
  32. package/src/codegen/targets/react/component/handlers/help-bubble.ts +4 -5
  33. package/src/codegen/targets/react/component/handlers/identity-placeholder.ts +3 -2
  34. package/src/codegen/targets/react/component/handlers/inline-banner.ts +7 -14
  35. package/src/codegen/targets/react/component/handlers/manner-temp.ts +18 -0
  36. package/src/codegen/targets/react/component/handlers/menu-sheet.ts +106 -0
  37. package/src/codegen/targets/react/component/handlers/multiline-text-field.ts +1 -1
  38. package/src/codegen/targets/react/component/handlers/progress-circle.ts +3 -1
  39. package/src/codegen/targets/react/component/handlers/segmented-control.ts +4 -2
  40. package/src/codegen/targets/react/component/handlers/select-box.ts +7 -4
  41. package/src/codegen/targets/react/component/handlers/snackbar.ts +2 -2
  42. package/src/codegen/targets/react/component/handlers/tabs.ts +8 -125
  43. package/src/codegen/targets/react/component/index.ts +22 -19
  44. package/src/codegen/targets/react/instance.ts +1 -1
  45. package/src/codegen/targets/react/pipeline.ts +4 -2
  46. package/src/codegen/targets/react/props.ts +11 -4
  47. package/src/codegen/targets/react/value-resolver.ts +38 -3
  48. package/src/entities/data/__generated__/component-sets/action-button.d.ts +5 -5
  49. package/src/entities/data/__generated__/component-sets/action-button.mjs +5 -5
  50. package/src/entities/data/__generated__/component-sets/alert-dialog.d.ts +26 -0
  51. package/src/entities/data/__generated__/component-sets/alert-dialog.mjs +26 -0
  52. package/src/entities/data/__generated__/component-sets/avatar-stack.d.ts +5 -18
  53. package/src/entities/data/__generated__/component-sets/avatar-stack.mjs +5 -18
  54. package/src/entities/data/__generated__/component-sets/avatar.d.ts +11 -5
  55. package/src/entities/data/__generated__/component-sets/avatar.mjs +11 -5
  56. package/src/entities/data/__generated__/component-sets/badge.d.ts +0 -7
  57. package/src/entities/data/__generated__/component-sets/badge.mjs +0 -7
  58. package/src/entities/data/__generated__/component-sets/bottom-navigation-global.d.ts +3 -0
  59. package/src/entities/data/__generated__/component-sets/bottom-navigation-global.mjs +3 -0
  60. package/src/entities/data/__generated__/component-sets/bottom-navigation-kr.d.ts +3 -0
  61. package/src/entities/data/__generated__/component-sets/bottom-navigation-kr.mjs +3 -0
  62. package/src/entities/data/__generated__/component-sets/bottom-sheet.d.ts +53 -4
  63. package/src/entities/data/__generated__/component-sets/bottom-sheet.mjs +53 -4
  64. package/src/entities/data/__generated__/component-sets/callout.d.ts +13 -22
  65. package/src/entities/data/__generated__/component-sets/callout.mjs +13 -22
  66. package/src/entities/data/__generated__/component-sets/checkbox.d.ts +3 -3
  67. package/src/entities/data/__generated__/component-sets/checkbox.mjs +3 -3
  68. package/src/entities/data/__generated__/component-sets/checkmark.d.ts +34 -0
  69. package/src/entities/data/__generated__/component-sets/checkmark.mjs +34 -0
  70. package/src/entities/data/__generated__/component-sets/chip.d.ts +86 -0
  71. package/src/entities/data/__generated__/component-sets/chip.mjs +86 -0
  72. package/src/entities/data/__generated__/component-sets/chlid.d.ts +14 -0
  73. package/src/entities/data/__generated__/component-sets/chlid.mjs +14 -0
  74. package/src/entities/data/__generated__/component-sets/{extended-floating-action-button.d.ts → contextual-floating-button.d.ts} +12 -10
  75. package/src/entities/data/__generated__/component-sets/{extended-floating-action-button.mjs → contextual-floating-button.mjs} +12 -10
  76. package/src/entities/data/__generated__/component-sets/floating-action-button.d.ts +4 -8
  77. package/src/entities/data/__generated__/component-sets/floating-action-button.mjs +4 -8
  78. package/src/entities/data/__generated__/component-sets/help-bubble.d.ts +3 -10
  79. package/src/entities/data/__generated__/component-sets/help-bubble.mjs +3 -10
  80. package/src/entities/data/__generated__/component-sets/index.d.ts +13 -13
  81. package/src/entities/data/__generated__/component-sets/index.mjs +13 -13
  82. package/src/entities/data/__generated__/component-sets/inline-banner.d.ts +3 -3
  83. package/src/entities/data/__generated__/component-sets/inline-banner.mjs +3 -3
  84. package/src/entities/data/__generated__/component-sets/main-tab-navigation-global.d.ts +2 -2
  85. package/src/entities/data/__generated__/component-sets/main-tab-navigation-global.mjs +2 -2
  86. package/src/entities/data/__generated__/component-sets/manner-temp-badge.d.ts +2 -2
  87. package/src/entities/data/__generated__/component-sets/manner-temp-badge.mjs +2 -2
  88. package/src/entities/data/__generated__/component-sets/manner-temp.d.ts +2 -2
  89. package/src/entities/data/__generated__/component-sets/manner-temp.mjs +2 -2
  90. package/src/entities/data/__generated__/component-sets/{extended-action-sheet.d.ts → menu-sheet.d.ts} +17 -13
  91. package/src/entities/data/__generated__/component-sets/{extended-action-sheet.mjs → menu-sheet.mjs} +17 -13
  92. package/src/entities/data/__generated__/component-sets/multiline-text-field.d.ts +18 -18
  93. package/src/entities/data/__generated__/component-sets/multiline-text-field.mjs +18 -18
  94. package/src/entities/data/__generated__/component-sets/progress-circle.d.ts +2 -1
  95. package/src/entities/data/__generated__/component-sets/progress-circle.mjs +2 -1
  96. package/src/entities/data/__generated__/component-sets/radio-mark.d.ts +34 -0
  97. package/src/entities/data/__generated__/component-sets/radio-mark.mjs +34 -0
  98. package/src/entities/data/__generated__/component-sets/radio.d.ts +2 -2
  99. package/src/entities/data/__generated__/component-sets/radio.mjs +2 -2
  100. package/src/entities/data/__generated__/component-sets/reaction-button.d.ts +6 -6
  101. package/src/entities/data/__generated__/component-sets/reaction-button.mjs +6 -6
  102. package/src/entities/data/__generated__/component-sets/resizable-child.d.ts +18 -0
  103. package/src/entities/data/__generated__/component-sets/resizable-child.mjs +18 -0
  104. package/src/entities/data/__generated__/component-sets/resizable-icon.d.ts +18 -0
  105. package/src/entities/data/__generated__/component-sets/resizable-icon.mjs +18 -0
  106. package/src/entities/data/__generated__/component-sets/select-box.d.ts +4 -4
  107. package/src/entities/data/__generated__/component-sets/select-box.mjs +4 -4
  108. package/src/entities/data/__generated__/component-sets/skeleton.d.ts +7 -0
  109. package/src/entities/data/__generated__/component-sets/skeleton.mjs +7 -0
  110. package/src/entities/data/__generated__/component-sets/snackbar.d.ts +4 -4
  111. package/src/entities/data/__generated__/component-sets/snackbar.mjs +4 -4
  112. package/src/entities/data/__generated__/component-sets/switch.d.ts +1 -1
  113. package/src/entities/data/__generated__/component-sets/switch.mjs +1 -1
  114. package/src/entities/data/__generated__/component-sets/tabs.d.ts +13 -0
  115. package/src/entities/data/__generated__/component-sets/tabs.mjs +13 -0
  116. package/src/entities/data/__generated__/component-sets/template-button-group.d.ts +9 -33
  117. package/src/entities/data/__generated__/component-sets/template-button-group.mjs +9 -33
  118. package/src/entities/data/__generated__/component-sets/template-chip-group.d.ts +15 -12
  119. package/src/entities/data/__generated__/component-sets/template-chip-group.mjs +15 -12
  120. package/src/entities/data/__generated__/component-sets/template-completion.d.ts +28 -0
  121. package/src/entities/data/__generated__/component-sets/template-completion.mjs +28 -0
  122. package/src/entities/data/__generated__/component-sets/{error-state.d.ts → template-error-state.d.ts} +5 -5
  123. package/src/entities/data/__generated__/component-sets/{error-state.mjs → template-error-state.mjs} +5 -5
  124. package/src/entities/data/__generated__/component-sets/template-top-navigation.d.ts +9 -7
  125. package/src/entities/data/__generated__/component-sets/template-top-navigation.mjs +9 -7
  126. package/src/entities/data/__generated__/component-sets/text-field.d.ts +35 -36
  127. package/src/entities/data/__generated__/component-sets/text-field.mjs +35 -36
  128. package/src/entities/data/__generated__/component-sets/toggle-button.d.ts +7 -7
  129. package/src/entities/data/__generated__/component-sets/toggle-button.mjs +7 -7
  130. package/src/entities/data/__generated__/component-sets/top-navigation.d.ts +42 -0
  131. package/src/entities/data/__generated__/component-sets/top-navigation.mjs +42 -0
  132. package/src/entities/data/styles.ts +94 -0
  133. package/src/entities/index.ts +5 -2
  134. package/src/normalizer/from-plugin.ts +104 -44
  135. package/src/normalizer/types.ts +3 -1
  136. package/src/utils/figma-gradient.ts +72 -0
  137. package/src/utils/figma-node.ts +4 -3
  138. package/src/codegen/targets/react/component/handlers/action-chip.ts +0 -72
  139. package/src/codegen/targets/react/component/handlers/action-sheet.ts +0 -82
  140. package/src/codegen/targets/react/component/handlers/chip-tabs.ts +0 -57
  141. package/src/codegen/targets/react/component/handlers/control-chip.ts +0 -81
  142. package/src/codegen/targets/react/component/handlers/extended-action-sheet.ts +0 -98
  143. package/src/codegen/targets/react/component/handlers/extended-fab.ts +0 -25
  144. package/src/codegen/targets/react/component/handlers/fab.ts +0 -22
  145. package/src/codegen/targets/react/component/handlers/text-button.ts +0 -49
  146. package/src/entities/data/__generated__/component-sets/action-chip.d.ts +0 -57
  147. package/src/entities/data/__generated__/component-sets/action-chip.mjs +0 -57
  148. package/src/entities/data/__generated__/component-sets/action-sheet.d.ts +0 -40
  149. package/src/entities/data/__generated__/component-sets/action-sheet.mjs +0 -40
  150. package/src/entities/data/__generated__/component-sets/chip-tablist.d.ts +0 -24
  151. package/src/entities/data/__generated__/component-sets/chip-tablist.mjs +0 -24
  152. package/src/entities/data/__generated__/component-sets/control-chip.d.ts +0 -60
  153. package/src/entities/data/__generated__/component-sets/control-chip.mjs +0 -60
  154. package/src/entities/data/__generated__/component-sets/identity-placeholder.d.ts +0 -13
  155. package/src/entities/data/__generated__/component-sets/identity-placeholder.mjs +0 -13
  156. package/src/entities/data/__generated__/component-sets/manner-temp-bar.d.ts +0 -23
  157. package/src/entities/data/__generated__/component-sets/manner-temp-bar.mjs +0 -23
  158. package/src/entities/data/__generated__/component-sets/standard-navigation.d.ts +0 -23
  159. package/src/entities/data/__generated__/component-sets/standard-navigation.mjs +0 -23
  160. package/src/entities/data/__generated__/component-sets/tablist.d.ts +0 -29
  161. package/src/entities/data/__generated__/component-sets/tablist.mjs +0 -29
  162. package/src/entities/data/__generated__/component-sets/template-bottom-fixed-bar.d.ts +0 -42
  163. package/src/entities/data/__generated__/component-sets/template-bottom-fixed-bar.mjs +0 -42
  164. package/src/entities/data/__generated__/component-sets/text-button.d.ts +0 -45
  165. package/src/entities/data/__generated__/component-sets/text-button.mjs +0 -45
@@ -2,26 +2,27 @@ import type {
2
2
  AvatarProperties,
3
3
  IdentityPlaceholderProperties,
4
4
  } from "@/codegen/component-properties";
5
- import { defineComponentHandler } from "@/codegen/core";
5
+ import { createElement, defineComponentHandler } from "@/codegen/core";
6
6
  import * as metadata from "@/entities/data/__generated__/component-sets";
7
7
  import { findAllInstances } from "@/utils/figma-node";
8
8
  import { createLocalSnippetHelper } from "../../element-factories";
9
9
  import type { ComponentHandlerDeps } from "../deps.interface";
10
10
  import { createIdentityPlaceholderHandler } from "./identity-placeholder";
11
+ import { camelCase } from "change-case";
11
12
 
12
13
  const { createLocalSnippetElement } = createLocalSnippetHelper("avatar");
13
14
 
14
15
  export const createAvatarHandler = (ctx: ComponentHandlerDeps) => {
15
16
  const identityPlaceholderHandler = createIdentityPlaceholderHandler(ctx);
16
17
 
17
- return defineComponentHandler<AvatarProperties>(metadata.avatar.key, (node) => {
18
+ return defineComponentHandler<AvatarProperties>(metadata.avatar.key, (node, traverse) => {
18
19
  const [placeholder] = findAllInstances<IdentityPlaceholderProperties>({
19
20
  node,
20
21
  key: identityPlaceholderHandler.key,
21
22
  });
22
23
  const { componentProperties: props } = node;
23
24
 
24
- const avatarHasSrc = props["Show Image#71850:57"].value;
25
+ const avatarHasSrc = props["Has Image Contents#33407:0"].value;
25
26
 
26
27
  const commonProps = {
27
28
  ...(avatarHasSrc && {
@@ -29,7 +30,10 @@ export const createAvatarHandler = (ctx: ComponentHandlerDeps) => {
29
30
  src: `https://placehold.co/${props.Size.value}x${props.Size.value}`,
30
31
  }),
31
32
  ...(placeholder && {
32
- fallback: identityPlaceholderHandler.transform(placeholder),
33
+ fallback: identityPlaceholderHandler.transform(placeholder, traverse),
34
+ }),
35
+ ...(props["Badge"].value !== "None" && {
36
+ badgeMask: camelCase(props["Badge"].value),
33
37
  }),
34
38
  size: props.Size.value,
35
39
  };
@@ -37,10 +41,15 @@ export const createAvatarHandler = (ctx: ComponentHandlerDeps) => {
37
41
  return createLocalSnippetElement(
38
42
  "Avatar",
39
43
  commonProps,
40
- props["Show Badge#1398:26"].value ? createLocalSnippetElement("AvatarBadge", {}) : undefined,
41
- {
42
- comment: avatarHasSrc ? "alt 텍스트를 제공해야 합니다." : undefined,
43
- },
44
+ props["Badge"].value === "None"
45
+ ? undefined
46
+ : createLocalSnippetElement(
47
+ "AvatarBadge",
48
+ { asChild: true },
49
+ createElement("img", { src: "https://placehold.co/20x20" }),
50
+ { comment: "뱃지를 설명하는 alt 텍스트를 제공해야 합니다." },
51
+ ),
52
+ { comment: avatarHasSrc ? "alt 텍스트를 제공해야 합니다." : undefined },
44
53
  );
45
54
  });
46
55
  };
@@ -12,7 +12,6 @@ export const createBadgeHandler = (_ctx: ComponentHandlerDeps) =>
12
12
  size: handleSizeProp(props.Size.value),
13
13
  tone: camelCase(props.Tone.value),
14
14
  variant: camelCase(props.Variant.value),
15
- shape: camelCase(props.Shape.value),
16
15
  };
17
16
 
18
17
  return createSeedReactElement("Badge", commonProps, props["Label#1584:0"].value);
@@ -0,0 +1,71 @@
1
+ import type { BottomSheetProperties } from "@/codegen/component-properties";
2
+ import { createElement, defineComponentHandler } from "@/codegen/core";
3
+ import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import { match } from "ts-pattern";
5
+ import { createLocalSnippetHelper } from "../../element-factories";
6
+ import type { ComponentHandlerDeps } from "../deps.interface";
7
+ import { findAllInstances } from "@/utils/figma-node";
8
+
9
+ const { createLocalSnippetElement } = createLocalSnippetHelper("bottom-sheet");
10
+ const { createLocalSnippetElement: createLocalSnippetElementTrigger } =
11
+ createLocalSnippetHelper("action-button");
12
+
13
+ // TODO: Bottom Action Bar (WIP) handler의 키. 해당 컴포넌트(템플릿) 핸들러 작성 시 handler.transform()으로 대체
14
+ const BOTTOM_SHEET_FOOTER_KEY = "de6c65d34cc4a01c18c9a7c0ded34635170ca11f";
15
+ const BOTTOM_SHEET_BODY_KEY = "aa9ffdd60fbfdea42f0d11162cd64f4b4389ddcc";
16
+
17
+ export const createBottomSheetHandler = (_ctx: ComponentHandlerDeps) =>
18
+ defineComponentHandler<BottomSheetProperties>(metadata.bottomSheet.key, (node, traverse) => {
19
+ const props = node.componentProperties;
20
+ const headerAlign = match(props["Header Layout"].value)
21
+ .with("Bottom Left", "Top Left", () => "left")
22
+ .with("Bottom Center", "Top Center", () => "center")
23
+ .with("None", () => undefined)
24
+ .exhaustive();
25
+
26
+ const contentProps = {
27
+ title: props["Title#19787:3"].value,
28
+ ...(props["Show Description#25192:0"].value === true && {
29
+ description: props["Description#19787:7"].value,
30
+ }),
31
+ ...(props["Show Close Button#19787:11"].value === false && {
32
+ showCloseButton: false,
33
+ }),
34
+ };
35
+
36
+ const bodyNodes = findAllInstances({
37
+ node,
38
+ key: BOTTOM_SHEET_BODY_KEY,
39
+ });
40
+
41
+ const bottomSheetBody =
42
+ bodyNodes.length === 1
43
+ ? createLocalSnippetElement("BottomSheetBody", {}, bodyNodes[0].children.map(traverse))
44
+ : createLocalSnippetElement(
45
+ "BottomSheetBody",
46
+ {},
47
+ createElement("div", undefined, "No content available"),
48
+ );
49
+
50
+ const footerNodes = findAllInstances({
51
+ node,
52
+ key: BOTTOM_SHEET_FOOTER_KEY,
53
+ });
54
+
55
+ const bottomSheetFooter =
56
+ props["Show Footer#25162:14"] && footerNodes.length === 1
57
+ ? createLocalSnippetElement("BottomSheetFooter", {}, footerNodes[0].children.map(traverse))
58
+ : undefined;
59
+
60
+ return createLocalSnippetElement("BottomSheetRoot", { defaultOpen: true, headerAlign }, [
61
+ createLocalSnippetElement(
62
+ "BottomSheetTrigger",
63
+ { asChild: true },
64
+ createLocalSnippetElementTrigger("ActionButton", {}, "BottomSheet 열기"),
65
+ ),
66
+ createLocalSnippetElement("BottomSheetContent", contentProps, [
67
+ bottomSheetBody,
68
+ bottomSheetFooter,
69
+ ]),
70
+ ]);
71
+ });
@@ -5,6 +5,7 @@ import type { NormalizedTextNode } from "@/normalizer";
5
5
  import { camelCase } from "change-case";
6
6
  import { createLocalSnippetHelper } from "../../element-factories";
7
7
  import type { ComponentHandlerDeps } from "../deps.interface";
8
+ import { match } from "ts-pattern";
8
9
 
9
10
  const { createLocalSnippetElement } = createLocalSnippetHelper("callout");
10
11
 
@@ -12,18 +13,11 @@ export const createCalloutHandler = (ctx: ComponentHandlerDeps) =>
12
13
  defineComponentHandler<CalloutProperties>(
13
14
  metadata.callout.key,
14
15
  ({ componentProperties: props, children }) => {
15
- const tag = (() => {
16
- switch (props.Interaction.value) {
17
- case "Default":
18
- return "Callout";
19
- case "Actionable":
20
- return "ActionableCallout";
21
- case "Dismissible":
22
- return "DismissibleCallout";
23
- default:
24
- return "Callout";
25
- }
26
- })();
16
+ const tag = match(props.Interaction.value)
17
+ .with("Display", () => "Callout")
18
+ .with("Actionable", () => "ActionableCallout")
19
+ .with("Dismissible", () => "DismissibleCallout")
20
+ .exhaustive();
27
21
 
28
22
  const textNode = children.find((child) => child.type === "TEXT") as NormalizedTextNode | null;
29
23
 
@@ -79,11 +73,13 @@ export const createCalloutHandler = (ctx: ComponentHandlerDeps) =>
79
73
  tone: camelCase(props.Tone.value),
80
74
  title,
81
75
  description,
82
- linkProps: {
83
- children: linkLabel,
84
- },
85
- ...(props["Icon#12598:210"].value && {
86
- prefixIcon: ctx.iconHandler.transform(props["Icon#12598:210"]),
76
+ ...(linkLabel && {
77
+ linkProps: {
78
+ children: linkLabel,
79
+ },
80
+ }),
81
+ ...(props["Show Prefix Icon#35087:1"].value && {
82
+ prefixIcon: ctx.iconHandler.transform(props["Prefix Icon#35087:0"]),
87
83
  }),
88
84
  };
89
85
 
@@ -0,0 +1,66 @@
1
+ import type { AvatarProperties, ChipProperties } from "@/codegen/component-properties";
2
+ import { defineComponentHandler } from "@/codegen/core";
3
+ import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import { match } from "ts-pattern";
5
+ import { createLocalSnippetHelper } from "../../element-factories";
6
+ import type { ComponentHandlerDeps } from "../deps.interface";
7
+ import { handleSizeProp } from "../size";
8
+ import { camelCase } from "change-case";
9
+ import { findAllInstances } from "@/utils/figma-node";
10
+ import { createAvatarHandler } from "@/codegen/targets/react/component/handlers/avatar";
11
+
12
+ const { createLocalSnippetElement } = createLocalSnippetHelper("chip");
13
+
14
+ export const createChipHandler = (ctx: ComponentHandlerDeps) => {
15
+ const avatarHandler = createAvatarHandler(ctx);
16
+
17
+ return defineComponentHandler<ChipProperties>(metadata.chip.key, (node, traverse) => {
18
+ const props = node.componentProperties;
19
+ const states = props.State.value.split("-");
20
+
21
+ const prefix = match(props["Prefix Type"].value)
22
+ .with("None", "Image", () => undefined)
23
+ .with("Icon", () =>
24
+ createLocalSnippetElement(
25
+ "Chip.PrefixIcon",
26
+ undefined,
27
+ ctx.iconHandler.transform(props["Prefix Icon#8722:0"]),
28
+ ),
29
+ )
30
+ .with("Avatar", () => {
31
+ const [avatar] = findAllInstances<AvatarProperties>({ node, key: metadata.avatar.key });
32
+ if (!avatar) return undefined;
33
+
34
+ return createLocalSnippetElement(
35
+ "Chip.PrefixAvatar",
36
+ undefined,
37
+ avatarHandler.transform(avatar, traverse),
38
+ );
39
+ })
40
+ .exhaustive();
41
+
42
+ const suffix = props["Has Suffix#32538:181"].value
43
+ ? createLocalSnippetElement(
44
+ "Chip.SuffixIcon",
45
+ undefined,
46
+ ctx.iconHandler.transform(props["Suffix Type#32538:0"]),
47
+ )
48
+ : undefined;
49
+
50
+ const commonProps = {
51
+ variant: camelCase(props.Variant.value),
52
+ size: handleSizeProp(props.Size.value),
53
+ layout: props["Label#7185:0"].value ? "withText" : "iconOnly",
54
+ ...(states.includes("Disabled") && {
55
+ disabled: true,
56
+ }),
57
+ };
58
+
59
+ return createLocalSnippetElement(
60
+ "Chip.Button",
61
+ commonProps,
62
+ [prefix, props["Label#7185:0"].value, suffix],
63
+ { comment: "목적에 따라 Chip.Toggle, Chip.RadioItem 등으로도 사용할 수 있습니다." },
64
+ );
65
+ });
66
+ };
@@ -0,0 +1,52 @@
1
+ import type { ContextualFloatingButtonProperties } from "@/codegen/component-properties";
2
+ import { defineComponentHandler } from "@/codegen/core";
3
+ import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import { match } from "ts-pattern";
5
+ import { createLocalSnippetHelper, createSeedReactElement } from "../../element-factories";
6
+ import type { ComponentHandlerDeps } from "../deps.interface";
7
+
8
+ const { createLocalSnippetElement } = createLocalSnippetHelper("contextual-floating-button");
9
+
10
+ export const createContextualFloatingButtonHandler = (ctx: ComponentHandlerDeps) =>
11
+ defineComponentHandler<ContextualFloatingButtonProperties>(
12
+ metadata.contextualFloatingButton.key,
13
+ ({ componentProperties: props }) => {
14
+ const states = props.State.value.split("-");
15
+
16
+ const { layout, children } = match(props.Layout.value)
17
+ .with("Icon Only", () => ({
18
+ layout: "iconOnly",
19
+ children: [
20
+ createSeedReactElement("Icon", {
21
+ svg: ctx.iconHandler.transform(props["Icon#28796:0"]),
22
+ }),
23
+ ],
24
+ }))
25
+ .with("Icon First", () => ({
26
+ layout: "withText",
27
+ children: [
28
+ createSeedReactElement("PrefixIcon", {
29
+ svg: ctx.iconHandler.transform(props["Icon#28796:0"]),
30
+ }),
31
+ props["Label#28936:0"].value,
32
+ ],
33
+ }))
34
+ .exhaustive();
35
+
36
+ const commonProps = {
37
+ ...(states.includes("Disabled") && {
38
+ disabled: true,
39
+ }),
40
+ ...(states.includes("Loading") && {
41
+ loading: true,
42
+ }),
43
+ variant: match(props.Variant.value)
44
+ .with("Solid", () => "solid")
45
+ .with("Layer", () => "layer")
46
+ .exhaustive(),
47
+ layout,
48
+ };
49
+
50
+ return createLocalSnippetElement("ContextualFloatingButton", commonProps, children);
51
+ },
52
+ );
@@ -0,0 +1,19 @@
1
+ import type { DividerProperties } from "@/codegen/component-properties";
2
+ import { defineComponentHandler } from "@/codegen/core";
3
+ import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import { match } from "ts-pattern";
5
+ import { createSeedReactElement } from "../../element-factories";
6
+ import type { ComponentHandlerDeps } from "../deps.interface";
7
+
8
+ export const createDividerHandler = (_ctx: ComponentHandlerDeps) =>
9
+ defineComponentHandler<DividerProperties>(
10
+ metadata.divider.key,
11
+ ({ componentProperties: props }) => {
12
+ const { color } = match(props.Tone.value)
13
+ .with("Neutral", () => ({ color: "stroke.neutral" }))
14
+ .with("Neutral Muted", () => ({ color: "stroke.neutralMuted" }))
15
+ .exhaustive();
16
+
17
+ return createSeedReactElement("Divider", { color });
18
+ },
19
+ );
@@ -12,30 +12,33 @@ const { createLocalSnippetElement } = createLocalSnippetHelper("error-state");
12
12
  export const createErrorStateHandler = (ctx: ComponentHandlerDeps) => {
13
13
  const actionButtonHandler = createActionButtonHandler(ctx);
14
14
 
15
- return defineComponentHandler<ErrorStateProperties>(metadata.errorState.key, (node) => {
16
- const props = node.componentProperties;
15
+ return defineComponentHandler<ErrorStateProperties>(
16
+ metadata.templateErrorState.key,
17
+ (node, traverse) => {
18
+ const props = node.componentProperties;
17
19
 
18
- const [actionButtonNode] = findAllInstances<ActionButtonProperties>({
19
- node,
20
- key: actionButtonHandler.key,
21
- });
20
+ const [actionButtonNode] = findAllInstances<ActionButtonProperties>({
21
+ node,
22
+ key: actionButtonHandler.key,
23
+ });
22
24
 
23
- const commonProps = {
24
- variant: camelCase(props.Variant.value),
25
- ...(props.Layout.value === "With Title" && {
26
- title: props["Title#16237:0"].value,
27
- }),
28
- description: props["Description#16237:5"].value,
29
- ...(actionButtonNode && {
30
- primaryActionProps: {
31
- children: actionButtonHandler.transform(actionButtonNode).children[0],
32
- },
33
- secondaryActionProps: {
34
- children: props["Secondary Action Label#17042:0"].value,
35
- },
36
- }),
37
- };
25
+ const commonProps = {
26
+ variant: camelCase(props.Variant.value),
27
+ ...(props.Layout.value === "With Title" && {
28
+ title: props["Title#16237:0"].value,
29
+ }),
30
+ description: props["Description#16237:5"].value,
31
+ ...(actionButtonNode && {
32
+ primaryActionProps: {
33
+ children: actionButtonHandler.transform(actionButtonNode, traverse).children[0],
34
+ },
35
+ secondaryActionProps: {
36
+ children: props["Secondary Action Label#17042:0"].value,
37
+ },
38
+ }),
39
+ };
38
40
 
39
- return createLocalSnippetElement("ErrorState", commonProps);
40
- });
41
+ return createLocalSnippetElement("ErrorState", commonProps);
42
+ },
43
+ );
41
44
  };
@@ -0,0 +1,48 @@
1
+ import type {
2
+ FloatingActionButtonButtonItemProperties,
3
+ FloatingActionButtonMenuItemProperties,
4
+ FloatingActionButtonProperties,
5
+ } from "@/codegen/component-properties";
6
+ import { defineComponentHandler } from "@/codegen/core";
7
+ import * as metadata from "@/entities/data/__generated__/component-sets";
8
+ import { createLocalSnippetHelper } from "../../element-factories";
9
+ import type { ComponentHandlerDeps } from "../deps.interface";
10
+ import { findAllInstances } from "@/utils/figma-node";
11
+
12
+ const { createLocalSnippetElement } = createLocalSnippetHelper("floating-action-button");
13
+
14
+ const BUTTON_TYPE_KEY = "8cecc85275115d653579d4c3156567ebf19f7b27";
15
+ const MENU_TYPE_KEY = "400124347392c15473f9cd2d8a6aedb64f3baf36";
16
+
17
+ export const createFloatingActionButtonHandler = (ctx: ComponentHandlerDeps) =>
18
+ defineComponentHandler<FloatingActionButtonProperties>(
19
+ metadata.floatingActionButton.key,
20
+ (node) => {
21
+ const [button] = findAllInstances<FloatingActionButtonButtonItemProperties>({
22
+ node,
23
+ key: BUTTON_TYPE_KEY,
24
+ });
25
+ const [menu] = findAllInstances<FloatingActionButtonMenuItemProperties>({
26
+ node,
27
+ key: MENU_TYPE_KEY,
28
+ });
29
+
30
+ const commonProps = (() => {
31
+ if (button)
32
+ return {
33
+ icon: ctx.iconHandler.transform(button.componentProperties["Icon#29766:18"]),
34
+ extended: button.componentProperties.Extended.value === "True",
35
+ label: button.componentProperties["Label#29808:0"].value,
36
+ };
37
+
38
+ if (menu)
39
+ return {
40
+ icon: ctx.iconHandler.transform(menu.componentProperties["Icon#29766:0"]),
41
+ extended: menu.componentProperties.Extended.value === "True",
42
+ label: menu.componentProperties["Label#29766:9"].value,
43
+ };
44
+ })();
45
+
46
+ return createLocalSnippetElement("FloatingActionButton", commonProps);
47
+ },
48
+ );
@@ -1,10 +1,12 @@
1
1
  import type { HelpBubbleProperties } from "@/codegen/component-properties";
2
- import { createElement, defineComponentHandler } from "@/codegen/core";
2
+ import { defineComponentHandler } from "@/codegen/core";
3
3
  import * as metadata from "@/entities/data/__generated__/component-sets";
4
4
  import { createLocalSnippetHelper } from "../../element-factories";
5
5
  import type { ComponentHandlerDeps } from "../deps.interface";
6
6
 
7
7
  const { createLocalSnippetElement } = createLocalSnippetHelper("help-bubble");
8
+ const { createLocalSnippetElement: createLocalSnippetElementTrigger } =
9
+ createLocalSnippetHelper("action-button");
8
10
 
9
11
  export const createHelpBubbleHandler = (_ctx: ComponentHandlerDeps) =>
10
12
  defineComponentHandler<HelpBubbleProperties>(
@@ -56,7 +58,6 @@ export const createHelpBubbleHandler = (_ctx: ComponentHandlerDeps) =>
56
58
  ...(props["Show Description#62499:0"].value && {
57
59
  description: props["Description#62535:98"].value,
58
60
  }),
59
- showCloseButton: props["Show Close Button"].value === "True",
60
61
  defaultOpen: true,
61
62
  placement,
62
63
  };
@@ -64,9 +65,7 @@ export const createHelpBubbleHandler = (_ctx: ComponentHandlerDeps) =>
64
65
  return createLocalSnippetElement(
65
66
  "HelpBubbleTrigger",
66
67
  commonProps,
67
- createElement("button", undefined, "열기", {
68
- comment: "HelpBubble을 여는 요소를 제공해주세요.",
69
- }),
68
+ createLocalSnippetElementTrigger("ActionButton", {}, "HelpBubble 열기"),
70
69
  );
71
70
  },
72
71
  );
@@ -1,13 +1,14 @@
1
1
  import type { IdentityPlaceholderProperties } from "@/codegen/component-properties";
2
2
  import { defineComponentHandler } from "@/codegen/core";
3
- import * as metadata from "@/entities/data/__generated__/component-sets";
4
3
  import { camelCase } from "change-case";
5
4
  import { createSeedReactElement } from "../../element-factories";
6
5
  import type { ComponentHandlerDeps } from "../deps.interface";
7
6
 
7
+ const IDENTITY_PLACEHOLDER_KEY = "b3563b6f16ba4cfe4240c9b33eef7edad4c304eb";
8
+
8
9
  export const createIdentityPlaceholderHandler = (_ctx: ComponentHandlerDeps) =>
9
10
  defineComponentHandler<IdentityPlaceholderProperties>(
10
- metadata.identityPlaceholder.key,
11
+ IDENTITY_PLACEHOLDER_KEY,
11
12
  ({ componentProperties: props }) => {
12
13
  const commonProps = {
13
14
  identity: camelCase(props.Identity.value),
@@ -6,6 +6,7 @@ import { findOne } from "@/utils/figma-node";
6
6
  import { camelCase } from "change-case";
7
7
  import { createLocalSnippetHelper } from "../../element-factories";
8
8
  import type { ComponentHandlerDeps } from "../deps.interface";
9
+ import { match } from "ts-pattern";
9
10
 
10
11
  const { createLocalSnippetElement } = createLocalSnippetHelper("inline-banner");
11
12
 
@@ -13,20 +14,12 @@ export const createInlineBannerHandler = (ctx: ComponentHandlerDeps) =>
13
14
  defineComponentHandler<InlineBannerProperties>(metadata.inlineBanner.key, (node) => {
14
15
  const { componentProperties: props } = node;
15
16
 
16
- const tag = (() => {
17
- switch (props.Interaction.value) {
18
- case "Default":
19
- return "InlineBanner";
20
- case "Actionable":
21
- return "ActionableInlineBanner";
22
- case "Dismissible":
23
- return "DismissibleInlineBanner";
24
- case "Link":
25
- return "InlineBanner";
26
- default:
27
- return "InlineBanner";
28
- }
29
- })();
17
+ const tag = match(props.Interaction.value)
18
+ .with("Default", () => "InlineBanner")
19
+ .with("Actionable", () => "ActionableInlineBanner")
20
+ .with("Dismissible", () => "DismissibleInlineBanner")
21
+ .with("Link", () => "InlineBanner")
22
+ .exhaustive();
30
23
 
31
24
  const textNode = findOne(
32
25
  node,
@@ -0,0 +1,18 @@
1
+ import type { MannerTempProperties } from "@/codegen/component-properties";
2
+ import { defineComponentHandler } from "@/codegen/core";
3
+ import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import { createLocalSnippetHelper } from "../../element-factories";
5
+ import type { ComponentHandlerDeps } from "../deps.interface";
6
+
7
+ const { createLocalSnippetElement } = createLocalSnippetHelper("manner-temp-badge");
8
+
9
+ export const createMannerTempHandler = (_ctx: ComponentHandlerDeps) =>
10
+ defineComponentHandler<MannerTempProperties>(metadata.mannerTemp.key, ({ children }) => {
11
+ const textNode = children.find((child) => child.type === "TEXT");
12
+
13
+ const commonProps = {
14
+ temperature: Number(textNode?.characters.replace(/[^\d.-]/g, "") ?? "-1"),
15
+ };
16
+
17
+ return createLocalSnippetElement("MannerTemp", commonProps);
18
+ });
@@ -0,0 +1,106 @@
1
+ import type {
2
+ MenuSheetGroupProperties,
3
+ MenuSheetItemProperties,
4
+ MenuSheetProperties,
5
+ } from "@/codegen/component-properties";
6
+ import { defineComponentHandler } from "@/codegen/core";
7
+ import * as metadata from "@/entities/data/__generated__/component-sets";
8
+ import { findAllInstances } from "@/utils/figma-node";
9
+ import { camelCase } from "change-case";
10
+ import { createLocalSnippetHelper, createSeedReactElement } from "../../element-factories";
11
+ import type { ComponentHandlerDeps } from "../deps.interface";
12
+ import { match } from "ts-pattern";
13
+
14
+ const { createLocalSnippetElement } = createLocalSnippetHelper("menu-sheet");
15
+ const { createLocalSnippetElement: createLocalSnippetElementTrigger } =
16
+ createLocalSnippetHelper("action-button");
17
+
18
+ const MENU_SHEET_ITEM_KEY = "057083e95466da59051119eec0b41d4ad5a07f8f";
19
+ const createMenuSheetItemHandler = (ctx: ComponentHandlerDeps) =>
20
+ defineComponentHandler<MenuSheetItemProperties>(
21
+ MENU_SHEET_ITEM_KEY,
22
+ ({ componentProperties: props }) => {
23
+ const states = props.State.value.split("-");
24
+
25
+ const commonProps = {
26
+ tone: camelCase(props.Tone.value),
27
+ ...(states.includes("Disabled") && {
28
+ disabled: true,
29
+ }),
30
+ };
31
+
32
+ return createLocalSnippetElement("MenuSheetItem", commonProps, [
33
+ props["Show Prefix Icon#17043:5"].value
34
+ ? createSeedReactElement("PrefixIcon", {
35
+ svg: ctx.iconHandler.transform(props["Prefix Icon#55948:0"]),
36
+ })
37
+ : undefined,
38
+ props["Label#55905:8"].value,
39
+ ]);
40
+ },
41
+ );
42
+
43
+ const MENU_SHEET_GROUP_KEY = "2a504a1c6b7810d5e652862dcba2cb7048f9eb16";
44
+ const createMenuSheetGroupHandler = (ctx: ComponentHandlerDeps) => {
45
+ const menuSheetItemHandler = createMenuSheetItemHandler(ctx);
46
+
47
+ return defineComponentHandler<MenuSheetGroupProperties>(
48
+ MENU_SHEET_GROUP_KEY,
49
+ (node, traverse) => {
50
+ const items = findAllInstances<MenuSheetItemProperties>({
51
+ node,
52
+ key: menuSheetItemHandler.key,
53
+ });
54
+
55
+ const contentChildren = items.map((item) => menuSheetItemHandler.transform(item, traverse));
56
+
57
+ return createLocalSnippetElement("MenuSheetGroup", undefined, contentChildren);
58
+ },
59
+ );
60
+ };
61
+
62
+ export const createMenuSheetHandler = (ctx: ComponentHandlerDeps) => {
63
+ const menuSheetGroupHandler = createMenuSheetGroupHandler(ctx);
64
+
65
+ return defineComponentHandler<MenuSheetProperties>(metadata.menuSheet.key, (node, traverse) => {
66
+ const { componentProperties: props } = node;
67
+
68
+ const groups = findAllInstances<MenuSheetGroupProperties>({
69
+ node,
70
+ key: menuSheetGroupHandler.key,
71
+ });
72
+
73
+ const contentChildren = groups.map((group) => menuSheetGroupHandler.transform(group, traverse));
74
+
75
+ const title = props["Show Header#17043:12"].value
76
+ ? props["Title Text#14599:0"].value
77
+ : undefined;
78
+
79
+ // TODO: React 구현체에 description 추가 이후
80
+ // const description = props["Description Text#21827:0"].value;
81
+
82
+ const { labelAlignment } = match(props.Layout.value)
83
+ .with("Text with Icon", () => ({ labelAlignment: undefined }))
84
+ .with("Text Only", () => ({ labelAlignment: "center" }))
85
+ .exhaustive();
86
+
87
+ const content = createLocalSnippetElement(
88
+ "MenuSheetContent",
89
+ { title, labelAlignment },
90
+ contentChildren,
91
+ {
92
+ comment: title
93
+ ? undefined
94
+ : "title을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.",
95
+ },
96
+ );
97
+
98
+ const trigger = createLocalSnippetElement(
99
+ "MenuSheetTrigger",
100
+ { asChild: true },
101
+ createLocalSnippetElementTrigger("ActionButton", {}, "MenuSheet 열기"),
102
+ );
103
+
104
+ return createLocalSnippetElement("MenuSheet", undefined, [trigger, content]);
105
+ });
106
+ };
@@ -5,7 +5,7 @@ import { createLocalSnippetHelper } from "../../element-factories";
5
5
  import type { ComponentHandlerDeps } from "../deps.interface";
6
6
  import { handleSizeProp } from "../size";
7
7
 
8
- const { createLocalSnippetElement } = createLocalSnippetHelper("multiline-text-field");
8
+ const { createLocalSnippetElement } = createLocalSnippetHelper("text-field");
9
9
 
10
10
  export const createMultilineTextFieldHandler = (_ctx: ComponentHandlerDeps) =>
11
11
  defineComponentHandler<MultilineTextFieldProperties>(