@seed-design/figma 0.1.7 → 0.1.9

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 (166) hide show
  1. package/lib/codegen/index.cjs +773 -660
  2. package/lib/codegen/index.d.ts +725 -625
  3. package/lib/codegen/index.d.ts.map +1 -1
  4. package/lib/codegen/index.js +773 -660
  5. package/lib/codegen/targets/react/index.cjs +1242 -1226
  6. package/lib/codegen/targets/react/index.d.ts +22 -11
  7. package/lib/codegen/targets/react/index.d.ts.map +1 -1
  8. package/lib/codegen/targets/react/index.js +1242 -1226
  9. package/lib/index.cjs +899 -671
  10. package/lib/index.d.ts +3 -1
  11. package/lib/index.d.ts.map +1 -1
  12. package/lib/index.js +899 -671
  13. package/package.json +3 -3
  14. package/src/codegen/component-properties.ts +289 -144
  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 +88 -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 +7 -4
  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 +11 -8
  41. package/src/codegen/targets/react/component/handlers/snackbar.ts +2 -2
  42. package/src/codegen/targets/react/component/handlers/switch.ts +2 -7
  43. package/src/codegen/targets/react/component/handlers/tabs.ts +8 -125
  44. package/src/codegen/targets/react/component/index.ts +22 -19
  45. package/src/codegen/targets/react/instance.ts +1 -1
  46. package/src/codegen/targets/react/pipeline.ts +4 -2
  47. package/src/codegen/targets/react/props.ts +16 -9
  48. package/src/codegen/targets/react/value-resolver.ts +38 -3
  49. package/src/entities/data/__generated__/component-sets/action-button.d.ts +5 -5
  50. package/src/entities/data/__generated__/component-sets/action-button.mjs +5 -5
  51. package/src/entities/data/__generated__/component-sets/alert-dialog.d.ts +26 -0
  52. package/src/entities/data/__generated__/component-sets/alert-dialog.mjs +26 -0
  53. package/src/entities/data/__generated__/component-sets/avatar-stack.d.ts +5 -18
  54. package/src/entities/data/__generated__/component-sets/avatar-stack.mjs +5 -18
  55. package/src/entities/data/__generated__/component-sets/avatar.d.ts +11 -5
  56. package/src/entities/data/__generated__/component-sets/avatar.mjs +11 -5
  57. package/src/entities/data/__generated__/component-sets/badge.d.ts +0 -7
  58. package/src/entities/data/__generated__/component-sets/badge.mjs +0 -7
  59. package/src/entities/data/__generated__/component-sets/bottom-navigation-global.d.ts +3 -0
  60. package/src/entities/data/__generated__/component-sets/bottom-navigation-global.mjs +3 -0
  61. package/src/entities/data/__generated__/component-sets/bottom-navigation-kr.d.ts +3 -0
  62. package/src/entities/data/__generated__/component-sets/bottom-navigation-kr.mjs +3 -0
  63. package/src/entities/data/__generated__/component-sets/bottom-sheet.d.ts +53 -4
  64. package/src/entities/data/__generated__/component-sets/bottom-sheet.mjs +53 -4
  65. package/src/entities/data/__generated__/component-sets/callout.d.ts +13 -22
  66. package/src/entities/data/__generated__/component-sets/callout.mjs +13 -22
  67. package/src/entities/data/__generated__/component-sets/checkbox.d.ts +3 -3
  68. package/src/entities/data/__generated__/component-sets/checkbox.mjs +3 -3
  69. package/src/entities/data/__generated__/component-sets/checkmark.d.ts +34 -0
  70. package/src/entities/data/__generated__/component-sets/checkmark.mjs +34 -0
  71. package/src/entities/data/__generated__/component-sets/chip.d.ts +90 -0
  72. package/src/entities/data/__generated__/component-sets/chip.mjs +90 -0
  73. package/src/entities/data/__generated__/component-sets/chlid.d.ts +14 -0
  74. package/src/entities/data/__generated__/component-sets/chlid.mjs +14 -0
  75. package/src/entities/data/__generated__/component-sets/{extended-floating-action-button.d.ts → contextual-floating-button.d.ts} +12 -10
  76. package/src/entities/data/__generated__/component-sets/{extended-floating-action-button.mjs → contextual-floating-button.mjs} +12 -10
  77. package/src/entities/data/__generated__/component-sets/floating-action-button.d.ts +4 -8
  78. package/src/entities/data/__generated__/component-sets/floating-action-button.mjs +4 -8
  79. package/src/entities/data/__generated__/component-sets/help-bubble.d.ts +3 -10
  80. package/src/entities/data/__generated__/component-sets/help-bubble.mjs +3 -10
  81. package/src/entities/data/__generated__/component-sets/index.d.ts +13 -13
  82. package/src/entities/data/__generated__/component-sets/index.mjs +13 -13
  83. package/src/entities/data/__generated__/component-sets/inline-banner.d.ts +3 -3
  84. package/src/entities/data/__generated__/component-sets/inline-banner.mjs +3 -3
  85. package/src/entities/data/__generated__/component-sets/main-tab-navigation-global.d.ts +2 -2
  86. package/src/entities/data/__generated__/component-sets/main-tab-navigation-global.mjs +2 -2
  87. package/src/entities/data/__generated__/component-sets/manner-temp-badge.d.ts +2 -2
  88. package/src/entities/data/__generated__/component-sets/manner-temp-badge.mjs +2 -2
  89. package/src/entities/data/__generated__/component-sets/manner-temp.d.ts +2 -2
  90. package/src/entities/data/__generated__/component-sets/manner-temp.mjs +2 -2
  91. package/src/entities/data/__generated__/component-sets/{extended-action-sheet.d.ts → menu-sheet.d.ts} +17 -13
  92. package/src/entities/data/__generated__/component-sets/{extended-action-sheet.mjs → menu-sheet.mjs} +17 -13
  93. package/src/entities/data/__generated__/component-sets/multiline-text-field.d.ts +18 -18
  94. package/src/entities/data/__generated__/component-sets/multiline-text-field.mjs +18 -18
  95. package/src/entities/data/__generated__/component-sets/progress-circle.d.ts +2 -1
  96. package/src/entities/data/__generated__/component-sets/progress-circle.mjs +2 -1
  97. package/src/entities/data/__generated__/component-sets/radio-mark.d.ts +34 -0
  98. package/src/entities/data/__generated__/component-sets/radio-mark.mjs +34 -0
  99. package/src/entities/data/__generated__/component-sets/radio.d.ts +2 -2
  100. package/src/entities/data/__generated__/component-sets/radio.mjs +2 -2
  101. package/src/entities/data/__generated__/component-sets/reaction-button.d.ts +6 -6
  102. package/src/entities/data/__generated__/component-sets/reaction-button.mjs +6 -6
  103. package/src/entities/data/__generated__/component-sets/resizable-child.d.ts +18 -0
  104. package/src/entities/data/__generated__/component-sets/resizable-child.mjs +18 -0
  105. package/src/entities/data/__generated__/component-sets/resizable-icon.d.ts +18 -0
  106. package/src/entities/data/__generated__/component-sets/resizable-icon.mjs +18 -0
  107. package/src/entities/data/__generated__/component-sets/select-box.d.ts +4 -4
  108. package/src/entities/data/__generated__/component-sets/select-box.mjs +4 -4
  109. package/src/entities/data/__generated__/component-sets/skeleton.d.ts +7 -0
  110. package/src/entities/data/__generated__/component-sets/skeleton.mjs +7 -0
  111. package/src/entities/data/__generated__/component-sets/snackbar.d.ts +4 -4
  112. package/src/entities/data/__generated__/component-sets/snackbar.mjs +4 -4
  113. package/src/entities/data/__generated__/component-sets/switch.d.ts +15 -6
  114. package/src/entities/data/__generated__/component-sets/switch.mjs +15 -6
  115. package/src/entities/data/__generated__/component-sets/tabs.d.ts +13 -0
  116. package/src/entities/data/__generated__/component-sets/tabs.mjs +13 -0
  117. package/src/entities/data/__generated__/component-sets/template-button-group.d.ts +9 -33
  118. package/src/entities/data/__generated__/component-sets/template-button-group.mjs +9 -33
  119. package/src/entities/data/__generated__/component-sets/template-chip-group.d.ts +15 -12
  120. package/src/entities/data/__generated__/component-sets/template-chip-group.mjs +15 -12
  121. package/src/entities/data/__generated__/component-sets/template-completion.d.ts +28 -0
  122. package/src/entities/data/__generated__/component-sets/template-completion.mjs +28 -0
  123. package/src/entities/data/__generated__/component-sets/{error-state.d.ts → template-error-state.d.ts} +5 -5
  124. package/src/entities/data/__generated__/component-sets/{error-state.mjs → template-error-state.mjs} +5 -5
  125. package/src/entities/data/__generated__/component-sets/template-top-navigation.d.ts +9 -7
  126. package/src/entities/data/__generated__/component-sets/template-top-navigation.mjs +9 -7
  127. package/src/entities/data/__generated__/component-sets/text-field.d.ts +35 -36
  128. package/src/entities/data/__generated__/component-sets/text-field.mjs +35 -36
  129. package/src/entities/data/__generated__/component-sets/toggle-button.d.ts +7 -7
  130. package/src/entities/data/__generated__/component-sets/toggle-button.mjs +7 -7
  131. package/src/entities/data/__generated__/component-sets/top-navigation.d.ts +42 -0
  132. package/src/entities/data/__generated__/component-sets/top-navigation.mjs +42 -0
  133. package/src/entities/data/styles.ts +94 -0
  134. package/src/entities/index.ts +5 -2
  135. package/src/normalizer/from-plugin.ts +104 -44
  136. package/src/normalizer/types.ts +3 -1
  137. package/src/utils/figma-gradient.ts +72 -0
  138. package/src/utils/figma-node.ts +4 -3
  139. package/src/codegen/targets/react/component/handlers/action-chip.ts +0 -72
  140. package/src/codegen/targets/react/component/handlers/action-sheet.ts +0 -82
  141. package/src/codegen/targets/react/component/handlers/chip-tabs.ts +0 -57
  142. package/src/codegen/targets/react/component/handlers/control-chip.ts +0 -81
  143. package/src/codegen/targets/react/component/handlers/extended-action-sheet.ts +0 -98
  144. package/src/codegen/targets/react/component/handlers/extended-fab.ts +0 -25
  145. package/src/codegen/targets/react/component/handlers/fab.ts +0 -22
  146. package/src/codegen/targets/react/component/handlers/text-button.ts +0 -49
  147. package/src/entities/data/__generated__/component-sets/action-chip.d.ts +0 -57
  148. package/src/entities/data/__generated__/component-sets/action-chip.mjs +0 -57
  149. package/src/entities/data/__generated__/component-sets/action-sheet.d.ts +0 -40
  150. package/src/entities/data/__generated__/component-sets/action-sheet.mjs +0 -40
  151. package/src/entities/data/__generated__/component-sets/chip-tablist.d.ts +0 -24
  152. package/src/entities/data/__generated__/component-sets/chip-tablist.mjs +0 -24
  153. package/src/entities/data/__generated__/component-sets/control-chip.d.ts +0 -60
  154. package/src/entities/data/__generated__/component-sets/control-chip.mjs +0 -60
  155. package/src/entities/data/__generated__/component-sets/identity-placeholder.d.ts +0 -13
  156. package/src/entities/data/__generated__/component-sets/identity-placeholder.mjs +0 -13
  157. package/src/entities/data/__generated__/component-sets/manner-temp-bar.d.ts +0 -23
  158. package/src/entities/data/__generated__/component-sets/manner-temp-bar.mjs +0 -23
  159. package/src/entities/data/__generated__/component-sets/standard-navigation.d.ts +0 -23
  160. package/src/entities/data/__generated__/component-sets/standard-navigation.mjs +0 -23
  161. package/src/entities/data/__generated__/component-sets/tablist.d.ts +0 -29
  162. package/src/entities/data/__generated__/component-sets/tablist.mjs +0 -29
  163. package/src/entities/data/__generated__/component-sets/template-bottom-fixed-bar.d.ts +0 -42
  164. package/src/entities/data/__generated__/component-sets/template-bottom-fixed-bar.mjs +0 -42
  165. package/src/entities/data/__generated__/component-sets/text-button.d.ts +0 -45
  166. 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,88 @@
1
+ import type {
2
+ AvatarProperties,
3
+ ChipIconSuffixProperties,
4
+ ChipProperties,
5
+ } from "@/codegen/component-properties";
6
+ import { defineComponentHandler } from "@/codegen/core";
7
+ import * as metadata from "@/entities/data/__generated__/component-sets";
8
+ import { match } from "ts-pattern";
9
+ import { createLocalSnippetHelper, createSeedReactElement } from "../../element-factories";
10
+ import type { ComponentHandlerDeps } from "../deps.interface";
11
+ import { handleSizeProp } from "../size";
12
+ import { camelCase } from "change-case";
13
+ import { findAllInstances } from "@/utils/figma-node";
14
+ import { createAvatarHandler } from "@/codegen/targets/react/component/handlers/avatar";
15
+
16
+ const { createLocalSnippetElement } = createLocalSnippetHelper("chip");
17
+
18
+ const CHIP_ICON_SUFFIX_KEY = "27343e0e5ab2c66948e9b10fde03d58b5e037212";
19
+ const createChipIconSuffixHandler = (ctx: ComponentHandlerDeps) => {
20
+ return defineComponentHandler<ChipIconSuffixProperties>(
21
+ CHIP_ICON_SUFFIX_KEY,
22
+ ({ componentProperties }) => {
23
+ return createLocalSnippetElement(
24
+ "Chip.SuffixIcon",
25
+ undefined,
26
+ createSeedReactElement("Icon", {
27
+ svg: ctx.iconHandler.transform(componentProperties["Icon#33203:0"]),
28
+ }),
29
+ );
30
+ },
31
+ );
32
+ };
33
+
34
+ export const createChipHandler = (ctx: ComponentHandlerDeps) => {
35
+ const avatarHandler = createAvatarHandler(ctx);
36
+ const iconSuffixHandler = createChipIconSuffixHandler(ctx);
37
+
38
+ return defineComponentHandler<ChipProperties>(metadata.chip.key, (node, traverse) => {
39
+ const props = node.componentProperties;
40
+ const states = props.State.value.split("-");
41
+
42
+ const prefix = match(props["Prefix Type"].value)
43
+ .with("None", "Image", () => undefined)
44
+ .with("Icon", () =>
45
+ createLocalSnippetElement(
46
+ "Chip.PrefixIcon",
47
+ undefined,
48
+ createSeedReactElement("Icon", {
49
+ svg: ctx.iconHandler.transform(props["Prefix Icon#8722:0"]),
50
+ }),
51
+ ),
52
+ )
53
+ .with("Avatar", () => {
54
+ const [avatar] = findAllInstances<AvatarProperties>({ node, key: metadata.avatar.key });
55
+ if (!avatar) return undefined;
56
+
57
+ return createLocalSnippetElement(
58
+ "Chip.PrefixAvatar",
59
+ undefined,
60
+ avatarHandler.transform(avatar, traverse),
61
+ );
62
+ })
63
+ .exhaustive();
64
+
65
+ const label = createLocalSnippetElement("Chip.Label", undefined, props["Label#7185:0"].value);
66
+
67
+ const [suffixIcon] = findAllInstances<ChipIconSuffixProperties>({
68
+ node,
69
+ key: CHIP_ICON_SUFFIX_KEY,
70
+ });
71
+
72
+ const commonProps = {
73
+ variant: camelCase(props.Variant.value),
74
+ size: handleSizeProp(props.Size.value),
75
+ layout: props["Label#7185:0"].value ? "withText" : "iconOnly",
76
+ ...(states.includes("Disabled") && {
77
+ disabled: true,
78
+ }),
79
+ };
80
+
81
+ return createLocalSnippetElement(
82
+ "Chip.Button",
83
+ commonProps,
84
+ [prefix, label, suffixIcon ? iconSuffixHandler.transform(suffixIcon, traverse) : undefined],
85
+ { comment: "목적에 따라 Chip.Toggle, Chip.RadioItem 등으로 바꿔 사용하세요." },
86
+ );
87
+ });
88
+ };
@@ -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,18 +1,21 @@
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
- import { createSeedReactElement } from "../../element-factories";
4
+ import { createLocalSnippetHelper } from "../../element-factories";
6
5
  import type { ComponentHandlerDeps } from "../deps.interface";
7
6
 
7
+ const IDENTITY_PLACEHOLDER_KEY = "b3563b6f16ba4cfe4240c9b33eef7edad4c304eb";
8
+
9
+ const { createLocalSnippetElement } = createLocalSnippetHelper("identity-placeholder");
10
+
8
11
  export const createIdentityPlaceholderHandler = (_ctx: ComponentHandlerDeps) =>
9
12
  defineComponentHandler<IdentityPlaceholderProperties>(
10
- metadata.identityPlaceholder.key,
13
+ IDENTITY_PLACEHOLDER_KEY,
11
14
  ({ componentProperties: props }) => {
12
15
  const commonProps = {
13
16
  identity: camelCase(props.Identity.value),
14
17
  };
15
18
 
16
- return createSeedReactElement("IdentityPlaceholder", commonProps);
19
+ return createLocalSnippetElement("IdentityPlaceholder", commonProps);
17
20
  },
18
21
  );
@@ -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");
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
+ });