@seed-design/figma 0.0.0-alpha-20260324091316

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/lib/codegen/index.cjs +23543 -0
  2. package/lib/codegen/index.d.ts +2957 -0
  3. package/lib/codegen/index.d.ts.map +1 -0
  4. package/lib/codegen/index.js +23514 -0
  5. package/lib/codegen/targets/react/index.cjs +31980 -0
  6. package/lib/codegen/targets/react/index.d.ts +308 -0
  7. package/lib/codegen/targets/react/index.d.ts.map +1 -0
  8. package/lib/codegen/targets/react/index.js +31961 -0
  9. package/lib/index.cjs +26905 -0
  10. package/lib/index.d.ts +221 -0
  11. package/lib/index.d.ts.map +1 -0
  12. package/lib/index.js +26884 -0
  13. package/package.json +56 -0
  14. package/src/codegen/component-properties.archive.ts +1019 -0
  15. package/src/codegen/component-properties.ts +369 -0
  16. package/src/codegen/core/codegen.ts +112 -0
  17. package/src/codegen/core/component-handler.ts +23 -0
  18. package/src/codegen/core/component-type-helper.ts +35 -0
  19. package/src/codegen/core/element-transformer.ts +13 -0
  20. package/src/codegen/core/index.ts +19 -0
  21. package/src/codegen/core/infer-layout.test.ts +286 -0
  22. package/src/codegen/core/infer-layout.ts +416 -0
  23. package/src/codegen/core/jsx.ts +174 -0
  24. package/src/codegen/core/props-converter.ts +78 -0
  25. package/src/codegen/core/value-resolver.ts +381 -0
  26. package/src/codegen/default-services.ts +44 -0
  27. package/src/codegen/index.ts +3 -0
  28. package/src/codegen/skip-components.ts +7 -0
  29. package/src/codegen/targets/figma/frame.ts +38 -0
  30. package/src/codegen/targets/figma/index.ts +6 -0
  31. package/src/codegen/targets/figma/instance.ts +36 -0
  32. package/src/codegen/targets/figma/pipeline.ts +106 -0
  33. package/src/codegen/targets/figma/props.ts +262 -0
  34. package/src/codegen/targets/figma/shape.ts +65 -0
  35. package/src/codegen/targets/figma/text.ts +30 -0
  36. package/src/codegen/targets/figma/value-resolver.ts +75 -0
  37. package/src/codegen/targets/index.ts +2 -0
  38. package/src/codegen/targets/react/component/deps.interface.ts +7 -0
  39. package/src/codegen/targets/react/component/handlers/action-button.ts +149 -0
  40. package/src/codegen/targets/react/component/handlers/alert-dialog.ts +120 -0
  41. package/src/codegen/targets/react/component/handlers/app-bar.ts +169 -0
  42. package/src/codegen/targets/react/component/handlers/archive/action-button.ts +144 -0
  43. package/src/codegen/targets/react/component/handlers/archive/alert-dialog.ts +122 -0
  44. package/src/codegen/targets/react/component/handlers/archive/app-bar.ts +149 -0
  45. package/src/codegen/targets/react/component/handlers/archive/avatar-stack.ts +35 -0
  46. package/src/codegen/targets/react/component/handlers/archive/avatar.ts +55 -0
  47. package/src/codegen/targets/react/component/handlers/archive/badge.ts +18 -0
  48. package/src/codegen/targets/react/component/handlers/archive/bottom-sheet.ts +70 -0
  49. package/src/codegen/targets/react/component/handlers/archive/callout.ts +88 -0
  50. package/src/codegen/targets/react/component/handlers/archive/checkbox.ts +43 -0
  51. package/src/codegen/targets/react/component/handlers/archive/checkmark.ts +29 -0
  52. package/src/codegen/targets/react/component/handlers/archive/chip.ts +90 -0
  53. package/src/codegen/targets/react/component/handlers/archive/contextual-floating-button.ts +52 -0
  54. package/src/codegen/targets/react/component/handlers/archive/divider.ts +25 -0
  55. package/src/codegen/targets/react/component/handlers/archive/field-button.ts +197 -0
  56. package/src/codegen/targets/react/component/handlers/archive/field.ts +167 -0
  57. package/src/codegen/targets/react/component/handlers/archive/floating-action-button.ts +48 -0
  58. package/src/codegen/targets/react/component/handlers/archive/help-bubble.ts +73 -0
  59. package/src/codegen/targets/react/component/handlers/archive/identity-placeholder.ts +21 -0
  60. package/src/codegen/targets/react/component/handlers/archive/index.ts +40 -0
  61. package/src/codegen/targets/react/component/handlers/archive/legacy-select-box.ts +89 -0
  62. package/src/codegen/targets/react/component/handlers/archive/legacy-text-field.ts +198 -0
  63. package/src/codegen/targets/react/component/handlers/archive/list-header.ts +20 -0
  64. package/src/codegen/targets/react/component/handlers/archive/list-item.ts +162 -0
  65. package/src/codegen/targets/react/component/handlers/archive/manner-temp-badge.ts +21 -0
  66. package/src/codegen/targets/react/component/handlers/archive/manner-temp.ts +18 -0
  67. package/src/codegen/targets/react/component/handlers/archive/menu-sheet.ts +108 -0
  68. package/src/codegen/targets/react/component/handlers/archive/page-banner.ts +101 -0
  69. package/src/codegen/targets/react/component/handlers/archive/progress-circle.ts +55 -0
  70. package/src/codegen/targets/react/component/handlers/archive/radio-group.ts +31 -0
  71. package/src/codegen/targets/react/component/handlers/archive/radiomark.ts +27 -0
  72. package/src/codegen/targets/react/component/handlers/archive/reaction-button.ts +37 -0
  73. package/src/codegen/targets/react/component/handlers/archive/result-section.ts +67 -0
  74. package/src/codegen/targets/react/component/handlers/archive/segmented-control.ts +64 -0
  75. package/src/codegen/targets/react/component/handlers/archive/skeleton.ts +26 -0
  76. package/src/codegen/targets/react/component/handlers/archive/slider.ts +114 -0
  77. package/src/codegen/targets/react/component/handlers/archive/snackbar.ts +25 -0
  78. package/src/codegen/targets/react/component/handlers/archive/switch.ts +39 -0
  79. package/src/codegen/targets/react/component/handlers/archive/switchmark.ts +26 -0
  80. package/src/codegen/targets/react/component/handlers/archive/tabs.ts +297 -0
  81. package/src/codegen/targets/react/component/handlers/archive/tag-group.ts +86 -0
  82. package/src/codegen/targets/react/component/handlers/archive/text-field.ts +264 -0
  83. package/src/codegen/targets/react/component/handlers/archive/toggle-button.ts +43 -0
  84. package/src/codegen/targets/react/component/handlers/avatar-stack.ts +38 -0
  85. package/src/codegen/targets/react/component/handlers/avatar.ts +58 -0
  86. package/src/codegen/targets/react/component/handlers/badge.ts +18 -0
  87. package/src/codegen/targets/react/component/handlers/bottom-sheet.ts +74 -0
  88. package/src/codegen/targets/react/component/handlers/callout.ts +88 -0
  89. package/src/codegen/targets/react/component/handlers/checkbox.ts +129 -0
  90. package/src/codegen/targets/react/component/handlers/checkmark.ts +29 -0
  91. package/src/codegen/targets/react/component/handlers/chip.ts +93 -0
  92. package/src/codegen/targets/react/component/handlers/content-placeholder.ts +20 -0
  93. package/src/codegen/targets/react/component/handlers/contextual-floating-button.ts +52 -0
  94. package/src/codegen/targets/react/component/handlers/divider.ts +25 -0
  95. package/src/codegen/targets/react/component/handlers/field-button.ts +192 -0
  96. package/src/codegen/targets/react/component/handlers/field.ts +164 -0
  97. package/src/codegen/targets/react/component/handlers/floating-action-button.ts +45 -0
  98. package/src/codegen/targets/react/component/handlers/help-bubble.ts +73 -0
  99. package/src/codegen/targets/react/component/handlers/identity-placeholder.ts +20 -0
  100. package/src/codegen/targets/react/component/handlers/image-frame.ts +147 -0
  101. package/src/codegen/targets/react/component/handlers/index.ts +43 -0
  102. package/src/codegen/targets/react/component/handlers/legacy-select-box.ts +87 -0
  103. package/src/codegen/targets/react/component/handlers/legacy-text-field.ts +196 -0
  104. package/src/codegen/targets/react/component/handlers/list-header.ts +20 -0
  105. package/src/codegen/targets/react/component/handlers/list-item.ts +163 -0
  106. package/src/codegen/targets/react/component/handlers/manner-temp-badge.ts +21 -0
  107. package/src/codegen/targets/react/component/handlers/manner-temp.ts +18 -0
  108. package/src/codegen/targets/react/component/handlers/menu-sheet.ts +111 -0
  109. package/src/codegen/targets/react/component/handlers/page-banner.ts +106 -0
  110. package/src/codegen/targets/react/component/handlers/progress-circle.ts +55 -0
  111. package/src/codegen/targets/react/component/handlers/radio-group.ts +109 -0
  112. package/src/codegen/targets/react/component/handlers/radiomark.ts +27 -0
  113. package/src/codegen/targets/react/component/handlers/reaction-button.ts +37 -0
  114. package/src/codegen/targets/react/component/handlers/result-section.ts +67 -0
  115. package/src/codegen/targets/react/component/handlers/segmented-control.ts +63 -0
  116. package/src/codegen/targets/react/component/handlers/select-box.ts +333 -0
  117. package/src/codegen/targets/react/component/handlers/skeleton.ts +26 -0
  118. package/src/codegen/targets/react/component/handlers/slider.ts +117 -0
  119. package/src/codegen/targets/react/component/handlers/snackbar.ts +25 -0
  120. package/src/codegen/targets/react/component/handlers/switch.ts +35 -0
  121. package/src/codegen/targets/react/component/handlers/switchmark.ts +26 -0
  122. package/src/codegen/targets/react/component/handlers/tabs.ts +298 -0
  123. package/src/codegen/targets/react/component/handlers/tag-group.ts +90 -0
  124. package/src/codegen/targets/react/component/handlers/text-field.ts +253 -0
  125. package/src/codegen/targets/react/component/handlers/toggle-button.ts +43 -0
  126. package/src/codegen/targets/react/component/index.ts +24 -0
  127. package/src/codegen/targets/react/component/size.ts +22 -0
  128. package/src/codegen/targets/react/element-factories.ts +59 -0
  129. package/src/codegen/targets/react/frame.ts +96 -0
  130. package/src/codegen/targets/react/icon.ts +55 -0
  131. package/src/codegen/targets/react/index.ts +7 -0
  132. package/src/codegen/targets/react/instance.ts +82 -0
  133. package/src/codegen/targets/react/pipeline.ts +133 -0
  134. package/src/codegen/targets/react/props.ts +417 -0
  135. package/src/codegen/targets/react/shape.ts +47 -0
  136. package/src/codegen/targets/react/text.ts +31 -0
  137. package/src/codegen/targets/react/value-resolver.ts +93 -0
  138. package/src/entities/component.interface.ts +7 -0
  139. package/src/entities/component.repository.ts +16 -0
  140. package/src/entities/data/__generated__/archive/component-sets/index.d.ts +2074 -0
  141. package/src/entities/data/__generated__/archive/component-sets/index.mjs +2074 -0
  142. package/src/entities/data/__generated__/archive/components/index.d.ts +116 -0
  143. package/src/entities/data/__generated__/archive/components/index.mjs +116 -0
  144. package/src/entities/data/__generated__/archive/styles/index.d.ts +3 -0
  145. package/src/entities/data/__generated__/archive/styles/index.mjs +429 -0
  146. package/src/entities/data/__generated__/archive/variable-collections/index.d.ts +3 -0
  147. package/src/entities/data/__generated__/archive/variable-collections/index.mjs +501 -0
  148. package/src/entities/data/__generated__/archive/variables/index.d.ts +3 -0
  149. package/src/entities/data/__generated__/archive/variables/index.mjs +7019 -0
  150. package/src/entities/data/__generated__/component-sets/index.d.ts +4325 -0
  151. package/src/entities/data/__generated__/component-sets/index.mjs +4325 -0
  152. package/src/entities/data/__generated__/components/index.d.ts +378 -0
  153. package/src/entities/data/__generated__/components/index.mjs +378 -0
  154. package/src/entities/data/__generated__/icons/index.d.ts +3 -0
  155. package/src/entities/data/__generated__/icons/index.mjs +3476 -0
  156. package/src/entities/data/__generated__/styles/index.d.ts +3 -0
  157. package/src/entities/data/__generated__/styles/index.mjs +436 -0
  158. package/src/entities/data/__generated__/variable-collections/index.d.ts +3 -0
  159. package/src/entities/data/__generated__/variable-collections/index.mjs +479 -0
  160. package/src/entities/data/__generated__/variables/index.d.ts +3 -0
  161. package/src/entities/data/__generated__/variables/index.mjs +6969 -0
  162. package/src/entities/icon.interface.ts +5 -0
  163. package/src/entities/icon.repository.ts +11 -0
  164. package/src/entities/icon.service.ts +26 -0
  165. package/src/entities/index.ts +60 -0
  166. package/src/entities/style.interface.ts +5 -0
  167. package/src/entities/style.repository.ts +27 -0
  168. package/src/entities/style.service.ts +36 -0
  169. package/src/entities/variable.interface.ts +18 -0
  170. package/src/entities/variable.repository.ts +57 -0
  171. package/src/entities/variable.service.ts +101 -0
  172. package/src/index.ts +3 -0
  173. package/src/normalizer/from-plugin.ts +602 -0
  174. package/src/normalizer/from-rest.ts +577 -0
  175. package/src/normalizer/index.ts +3 -0
  176. package/src/normalizer/types.ts +208 -0
  177. package/src/utils/common.ts +38 -0
  178. package/src/utils/css.ts +19 -0
  179. package/src/utils/figma-gradient.ts +72 -0
  180. package/src/utils/figma-node.ts +95 -0
  181. package/src/utils/figma-variable.ts +49 -0
@@ -0,0 +1,87 @@
1
+ import type {
2
+ LegacySelectBoxGroupProperties,
3
+ LegacySelectBoxProperties,
4
+ } from "@/codegen/component-properties";
5
+ import { defineComponentHandler } from "@/codegen/core";
6
+ import * as metadata from "@/entities/data/__generated__/component-sets";
7
+ import { findAllInstances } from "@/utils/figma-node";
8
+ import { match } from "ts-pattern";
9
+ import { createLocalSnippetHelper, createSeedReactElement } from "../../element-factories";
10
+ import type { ComponentHandlerDeps } from "../deps.interface";
11
+
12
+ const { createLocalSnippetElement } = createLocalSnippetHelper("select-box");
13
+
14
+ const createLegacySelectBoxHandler = (_ctx: ComponentHandlerDeps) =>
15
+ defineComponentHandler<LegacySelectBoxProperties>(
16
+ metadata.componentDeprecatedSelectBox.key,
17
+ ({ componentProperties: props }) => {
18
+ const tag = match(props.Control.value)
19
+ .with("Checkbox", () => "CheckSelectBox")
20
+ .with("Radio", () => "RadioSelectBoxItem")
21
+ .exhaustive();
22
+
23
+ const commonProps = {
24
+ label: props["Label#3635:0"].value,
25
+ ...(props["Show Description#3033:0"].value && {
26
+ description: props["Description #3033:5"].value,
27
+ }),
28
+ ...(tag === "RadioSelectBoxItem" && {
29
+ value: props["Label#3635:0"].value,
30
+ }),
31
+ ...(tag === "CheckSelectBox" &&
32
+ props.Selected.value === "True" && {
33
+ defaultChecked: true,
34
+ }),
35
+ };
36
+
37
+ return createLocalSnippetElement(tag, commonProps, undefined, {
38
+ comment:
39
+ "이 Figma 컴포넌트는 @seed-design/react@1.2보다 낮은 버전의 SelectBox입니다. 신규 컴포넌트로 교체할 수 있습니다.",
40
+ });
41
+ },
42
+ );
43
+
44
+ export const createLegacySelectBoxGroupHandler = (ctx: ComponentHandlerDeps) => {
45
+ const selectBoxHandler = createLegacySelectBoxHandler(ctx);
46
+
47
+ return defineComponentHandler<LegacySelectBoxGroupProperties>(
48
+ metadata.componentDeprecatedSelectBoxGroup.key,
49
+ (node, traverse) => {
50
+ const props = node.componentProperties;
51
+
52
+ const tag = match(props.Control.value)
53
+ .with("Checkbox", () => "CheckSelectBoxGroup")
54
+ .with("Radio", () => "RadioSelectBoxRoot")
55
+ .exhaustive();
56
+
57
+ const selectBoxes = findAllInstances<LegacySelectBoxProperties>({
58
+ node,
59
+ key: selectBoxHandler.key,
60
+ });
61
+
62
+ const selectedSelectBox = selectBoxes.find(
63
+ (selectBox) => selectBox.componentProperties.Selected.value === "True",
64
+ );
65
+
66
+ // traverse the container like it's a frame
67
+ const vStackProps = traverse({ ...node, type: "FRAME" })?.props;
68
+
69
+ const stack = createSeedReactElement(
70
+ "VStack",
71
+ vStackProps,
72
+ selectBoxes.map((box) => selectBoxHandler.transform(box, traverse)),
73
+ );
74
+
75
+ const commonProps = {
76
+ ...(tag === "RadioSelectBoxRoot" && {
77
+ defaultValue: selectedSelectBox?.componentProperties["Label#3635:0"].value,
78
+ }),
79
+ };
80
+
81
+ return createLocalSnippetElement(tag, commonProps, stack, {
82
+ comment:
83
+ "이 Figma 컴포넌트는 @seed-design/react@1.2보다 낮은 버전의 SelectBox입니다. 신규 컴포넌트로 교체할 수 있습니다.",
84
+ });
85
+ },
86
+ );
87
+ };
@@ -0,0 +1,196 @@
1
+ import type {
2
+ LegacyMultilineTextFieldProperties,
3
+ LegacyTextFieldProperties,
4
+ } from "@/codegen/component-properties";
5
+ import { defineComponentHandler } from "@/codegen/core";
6
+ import * as metadata from "@/entities/data/__generated__/component-sets";
7
+ import { createLocalSnippetHelper } from "../../element-factories";
8
+ import type { ComponentHandlerDeps } from "../deps.interface";
9
+ import { handleSizeProp } from "../size";
10
+
11
+ const { createLocalSnippetElement } = createLocalSnippetHelper("text-field");
12
+
13
+ export const createLegacyTextFieldHandler = (ctx: ComponentHandlerDeps) =>
14
+ defineComponentHandler<LegacyTextFieldProperties>(
15
+ metadata.componentDeprecatedTextField.key,
16
+ ({ componentProperties: props }) => {
17
+ const {
18
+ Size: { value: size },
19
+ State: { value: state },
20
+ Filled: { value: filled },
21
+ "Show Header#870:0": { value: showHeader },
22
+ "Label#14964:0": { value: label },
23
+ "Show Indicator#1259:0": { value: showIndicator },
24
+ "Indicator#15327:249": { value: indicator },
25
+ "Show Prefix#958:125": { value: showPrefix },
26
+ "Show Prefix Icon#1267:50": { value: showPrefixIcon },
27
+ "Prefix Icon#1267:25": prefixIcon,
28
+ "Show Prefix Text#1267:0": { value: showPrefixText },
29
+ "Prefix Text#15327:101": { value: prefix },
30
+ "Placeholder#958:0": { value: placeholder },
31
+ "Filled Text#1304:0": { value: defaultValue },
32
+ "Show Suffix#958:100": { value: showSuffix },
33
+ "Show Suffix Icon#1267:75": { value: showSuffixIcon },
34
+ "Suffix Icon #1267:100": suffixIcon,
35
+ "Show Suffix Text#1267:125": { value: showSuffixText },
36
+ "Suffix Text#15327:138": { value: suffix },
37
+ "Show Footer#958:25": { value: showFooter },
38
+ "Show Description#958:50": { value: showDescription },
39
+ "Description#12626:5": { value: description },
40
+ "Show Character Count#958:75": { value: showCharacterCount },
41
+ "Character Count#15327:64": { value: _characterCount },
42
+ "Max Character Count#15327:27": { value: maxCharacterCount },
43
+ } = props;
44
+
45
+ const states = state.split("-");
46
+
47
+ const commonProps = {
48
+ size: handleSizeProp(size),
49
+ // header
50
+ ...(showHeader && {
51
+ label,
52
+ }),
53
+ ...(showHeader &&
54
+ showIndicator && {
55
+ indicator,
56
+ }),
57
+ // input affixes
58
+ ...(showPrefix &&
59
+ showPrefixIcon && {
60
+ prefixIcon: ctx.iconHandler.transform(prefixIcon),
61
+ }),
62
+ ...(showPrefix &&
63
+ showPrefixText && {
64
+ prefix,
65
+ }),
66
+ ...(showSuffix &&
67
+ showSuffixIcon && {
68
+ suffixIcon: ctx.iconHandler.transform(suffixIcon),
69
+ }),
70
+ ...(showSuffix &&
71
+ showSuffixText && {
72
+ suffix,
73
+ }),
74
+ // input
75
+ ...(filled === "True" && {
76
+ defaultValue,
77
+ }),
78
+ ...(states.includes("Invalid") && {
79
+ invalid: true,
80
+ }),
81
+ ...(states.includes("Disabled") && {
82
+ disabled: true,
83
+ }),
84
+ ...(states.includes("Read Only") && {
85
+ readOnly: true,
86
+ }),
87
+ // footer
88
+ ...(showFooter &&
89
+ showDescription &&
90
+ states.includes("Invalid") && {
91
+ // invalid인 경우 description을 error로 사용
92
+ errorMessage: description,
93
+ }),
94
+ ...(showFooter &&
95
+ showDescription &&
96
+ !states.includes("Invalid") && {
97
+ // invalid가 아닌 경우 description을 description으로 사용
98
+ description,
99
+ }),
100
+ ...(showFooter &&
101
+ showCharacterCount && {
102
+ maxGraphemeCount: Number(maxCharacterCount),
103
+ }),
104
+ };
105
+
106
+ const inputProps = {
107
+ placeholder,
108
+ };
109
+
110
+ const TextFieldChildren = createLocalSnippetElement("TextFieldInput", inputProps);
111
+
112
+ return createLocalSnippetElement("TextField", commonProps, TextFieldChildren, {
113
+ comment:
114
+ "이 Figma 컴포넌트는 @seed-design/react@1.1보다 낮은 버전의 TextField입니다. 신규 컴포넌트로 교체할 수 있습니다.",
115
+ });
116
+ },
117
+ );
118
+
119
+ export const createLegacyMultilineTextFieldHandler = (_ctx: ComponentHandlerDeps) =>
120
+ defineComponentHandler<LegacyMultilineTextFieldProperties>(
121
+ metadata.componentDeprecatedMultilineTextField.key,
122
+ ({ componentProperties: props }) => {
123
+ const {
124
+ Size: { value: size },
125
+ State: { value: state },
126
+ Filled: { value: filled },
127
+ "Show Header#870:0": { value: showHeader },
128
+ "Label#15327:323": { value: label },
129
+ "Show Indicator#1259:0": { value: showIndicator },
130
+ "Indicator#15327:286": { value: indicator },
131
+ "Placeholder#958:0": { value: placeholder },
132
+ "Filled Text#1304:0": { value: defaultValue },
133
+ "Show Footer#958:25": { value: showFooter },
134
+ "Show Description#958:50": { value: showDescription },
135
+ "Description#15327:212": { value: description },
136
+ "Show Character count#958:75": { value: showCharacterCount },
137
+ "Character Count#15327:360": { value: _characterCount },
138
+ "Max Character Count#15327:175": { value: maxCharacterCount },
139
+ } = props;
140
+
141
+ const states = state.split("-");
142
+
143
+ const commonProps = {
144
+ size: handleSizeProp(size),
145
+ // header
146
+ ...(showHeader && {
147
+ label,
148
+ }),
149
+ ...(showHeader &&
150
+ showIndicator && {
151
+ indicator,
152
+ }),
153
+ // input
154
+ ...(filled === "True" && {
155
+ defaultValue,
156
+ }),
157
+ ...(states.includes("Invalid") && {
158
+ invalid: true,
159
+ }),
160
+ ...(states.includes("Disabled") && {
161
+ disabled: true,
162
+ }),
163
+ ...(states.includes("Read Only") && {
164
+ readOnly: true,
165
+ }),
166
+ // footer
167
+ ...(showFooter &&
168
+ showDescription &&
169
+ states.includes("Invalid") && {
170
+ // invalid인 경우 description을 error로 사용
171
+ errorMessage: description,
172
+ }),
173
+ ...(showFooter &&
174
+ showDescription &&
175
+ !states.includes("Invalid") && {
176
+ // invalid가 아닌 경우 description을 description으로 사용
177
+ description,
178
+ }),
179
+ ...(showFooter &&
180
+ showCharacterCount && {
181
+ maxGraphemeCount: Number(maxCharacterCount),
182
+ }),
183
+ };
184
+
185
+ const inputProps = {
186
+ placeholder,
187
+ };
188
+
189
+ const TextFieldChildren = createLocalSnippetElement("TextFieldTextarea", inputProps);
190
+
191
+ return createLocalSnippetElement("TextField", commonProps, TextFieldChildren, {
192
+ comment:
193
+ "이 Figma 컴포넌트는 @seed-design/react@1.1보다 낮은 버전의 TextField입니다. 신규 컴포넌트로 교체할 수 있습니다.",
194
+ });
195
+ },
196
+ );
@@ -0,0 +1,20 @@
1
+ import type { ListHeaderProperties } 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
+ import { camelCase } from "change-case";
7
+
8
+ const { createLocalSnippetElement } = createLocalSnippetHelper("list-header");
9
+
10
+ export const createListHeaderHandler = (_ctx: ComponentHandlerDeps) =>
11
+ defineComponentHandler<ListHeaderProperties>(
12
+ metadata.componentListHeader.key,
13
+ ({ componentProperties: props }) => {
14
+ const commonProps = {
15
+ variant: camelCase(props["Variant"].value),
16
+ };
17
+
18
+ return createLocalSnippetElement("ListHeader", commonProps, props["Title#28588:0"].value);
19
+ },
20
+ );
@@ -0,0 +1,163 @@
1
+ import type {
2
+ ListItemSuffixIconProperties,
3
+ ListItemPrefixIconProperties,
4
+ ListItemProperties,
5
+ } from "@/codegen/component-properties";
6
+ import { createElement, defineComponentHandler } from "@/codegen/core";
7
+ import * as metadata from "@/entities/data/__generated__/component-sets";
8
+ import * as components from "@/entities/data/__generated__/components";
9
+ import type { NormalizedTextNode } from "@/normalizer";
10
+ import { findAllInstances, findOne } from "@/utils/figma-node";
11
+ import { createLocalSnippetHelper, createSeedReactElement } from "../../element-factories";
12
+ import type { ComponentHandlerDeps } from "../deps.interface";
13
+ import { match } from "ts-pattern";
14
+
15
+ const { createLocalSnippetElement } = createLocalSnippetHelper("list");
16
+
17
+ const PREFIX_KEYS = [
18
+ components.componentListItemPrefixCheckbox.key,
19
+ components.componentListItemPrefixRadiomark.key,
20
+ components.componentListItemPrefixIcon.key,
21
+ components.componentListItemPrefixAvatar.key,
22
+ components.componentListItemPrefixImage.key,
23
+ components.componentListItemPrefixCustom.key,
24
+ ];
25
+
26
+ const SUFFIX_KEYS = [
27
+ components.componentListItemSuffixCheckbox.key,
28
+ components.componentListItemSuffixRadiomark.key,
29
+ components.componentListItemSuffixChevron.key,
30
+ components.componentListItemSuffixSwitch.key,
31
+ components.componentListItemSuffixCustom.key,
32
+ components.componentListItemSuffixIcon.key,
33
+ components.componentListItemSuffixChevronWithText.key,
34
+ metadata.componentListItemSuffixIconButton.key,
35
+ metadata.componentListItemSuffixActionButton.key,
36
+ ];
37
+
38
+ export const createListItemHandler = (ctx: ComponentHandlerDeps) =>
39
+ defineComponentHandler<ListItemProperties>(metadata.componentListItem.key, (node, traverse) => {
40
+ const { componentProperties: props } = node;
41
+
42
+ const { alignItems, title } = match(props.Variants.value)
43
+ .with("Single Line", () => ({ alignItems: undefined, title: props["Title#28452:21"].value }))
44
+ .with("Multi Line", () => ({
45
+ alignItems: "flex-start",
46
+ title: props["Title #28487:0"].value,
47
+ }))
48
+ .exhaustive();
49
+
50
+ const detailNode = findOne(
51
+ node,
52
+ (node) => node.type === "TEXT" && node.name === "Sub Text",
53
+ ) as NormalizedTextNode | null;
54
+
55
+ const prefixNode = (() => {
56
+ if (props["Has Prefix#28452:85"].value === false) return null;
57
+
58
+ for (const key of PREFIX_KEYS) {
59
+ const [found] = findAllInstances<ListItemPrefixIconProperties | {}>({ node, key });
60
+
61
+ if (found) return found;
62
+ }
63
+
64
+ return null;
65
+ })();
66
+
67
+ const prefix = (() => {
68
+ if (!prefixNode) return undefined;
69
+
70
+ if ("Icon#28452:111" in prefixNode.componentProperties) {
71
+ return createSeedReactElement("Icon", {
72
+ svg: ctx.iconHandler.transform(prefixNode.componentProperties["Icon#28452:111"]),
73
+ });
74
+ }
75
+
76
+ return traverse(prefixNode.children[0]);
77
+ })();
78
+
79
+ const suffixNode = (() => {
80
+ if (props["Has Suffix#28452:64"].value === false) return null;
81
+
82
+ for (const key of SUFFIX_KEYS) {
83
+ const [found] = findAllInstances<ListItemSuffixIconProperties | {}>({ node, key });
84
+
85
+ if (found) return found;
86
+ }
87
+
88
+ return null;
89
+ })();
90
+
91
+ const suffix = (() => {
92
+ if (!suffixNode) return undefined;
93
+
94
+ if ("Icon#28347:9" in suffixNode.componentProperties) {
95
+ return createSeedReactElement("Icon", {
96
+ svg: ctx.iconHandler.transform(suffixNode.componentProperties["Icon#28347:9"]),
97
+ });
98
+ }
99
+
100
+ return traverse(suffixNode.children[0]);
101
+ })();
102
+
103
+ const disabled = props.State.value === "Disabled";
104
+
105
+ const tag = (() => {
106
+ if (suffix?.tag === "Switchmark") {
107
+ return "ListSwitchItem";
108
+ }
109
+
110
+ if (prefix?.tag === "Checkmark" || suffix?.tag === "Checkmark") {
111
+ return "ListCheckItem";
112
+ }
113
+
114
+ if (prefix?.tag === "Radiomark" || suffix?.tag === "Radiomark") {
115
+ return "ListRadioItem";
116
+ }
117
+
118
+ // checkmark/radiomark 없는데 disabled인 경우 Button으로 추측
119
+ if (disabled) {
120
+ return "ListButtonItem";
121
+ }
122
+
123
+ return "ListItem";
124
+ })();
125
+
126
+ const commonProps = {
127
+ ...(tag === "ListRadioItem" && {
128
+ value: title,
129
+ }),
130
+ alignItems,
131
+ title,
132
+ ...(props["Has Detail#28469:1"].value &&
133
+ detailNode && {
134
+ detail: detailNode.characters,
135
+ }),
136
+ ...(prefix && { prefix }),
137
+ ...(suffix && { suffix }),
138
+ ...(disabled &&
139
+ (tag === "ListButtonItem" ||
140
+ tag === "ListCheckItem" ||
141
+ tag === "ListRadioItem" ||
142
+ tag === "ListSwitchItem") && {
143
+ disabled: true,
144
+ }),
145
+ ...(props.Highlighted.value === "True" && {
146
+ highlighted: true,
147
+ }),
148
+ };
149
+
150
+ const comment = match(tag)
151
+ .with("ListItem", () => "목적에 따라 ListButtonItem이나 ListLinkItem으로 바꿔 사용하세요.")
152
+ .with("ListCheckItem", () => `<List as="fieldset">과 함께 사용하세요.`)
153
+ .with("ListRadioItem", () => "<RadioGroup.Root>와 함께 사용하세요.")
154
+ .otherwise(() => undefined);
155
+
156
+ const list = createLocalSnippetElement(tag, commonProps, undefined, { comment });
157
+
158
+ if (props["Divider#28441:0"].value) {
159
+ return createElement("", {}, [list, createLocalSnippetElement("ListDivider")]);
160
+ }
161
+
162
+ return list;
163
+ });
@@ -0,0 +1,21 @@
1
+ import type { MannerTempBadgeProperties } 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 createMannerTempBadgeHandler = (_ctx: ComponentHandlerDeps) =>
10
+ defineComponentHandler<MannerTempBadgeProperties>(
11
+ metadata.componentMannerTempBadge.key,
12
+ ({ children }) => {
13
+ const textNode = children.find((child) => child.type === "TEXT");
14
+
15
+ const commonProps = {
16
+ temperature: Number(textNode?.characters.replace(/[^\d.-]/g, "") ?? "-1"),
17
+ };
18
+
19
+ return createLocalSnippetElement("MannerTempBadge", commonProps);
20
+ },
21
+ );
@@ -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.componentMannerTemp.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,111 @@
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 } 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 createMenuSheetItemHandler = (ctx: ComponentHandlerDeps) =>
19
+ defineComponentHandler<MenuSheetItemProperties>(
20
+ metadata.privateComponentMenuSheetMenuItem.key,
21
+ ({ componentProperties: props }) => {
22
+ const states = props.State.value.split("-");
23
+
24
+ const commonProps = {
25
+ tone: camelCase(props.Tone.value),
26
+ ...(states.includes("Disabled") && {
27
+ disabled: true,
28
+ }),
29
+ ...(props["Show Prefix Icon#17043:5"].value && {
30
+ prefixIcon: ctx.iconHandler.transform(props["Prefix Icon#55948:0"]),
31
+ }),
32
+ label: props["Label#55905:8"].value,
33
+ ...(props["Show Item Description#51411:19"].value && {
34
+ description: props["Sub Text#51411:0"].value,
35
+ }),
36
+ };
37
+
38
+ return createLocalSnippetElement("MenuSheetItem", commonProps);
39
+ },
40
+ );
41
+
42
+ const createMenuSheetGroupHandler = (ctx: ComponentHandlerDeps) => {
43
+ const menuSheetItemHandler = createMenuSheetItemHandler(ctx);
44
+
45
+ return defineComponentHandler<MenuSheetGroupProperties>(
46
+ metadata.privateComponentMenuSheetMenuGroup.key,
47
+ (node, traverse) => {
48
+ const items = findAllInstances<MenuSheetItemProperties>({
49
+ node,
50
+ key: menuSheetItemHandler.key,
51
+ });
52
+
53
+ const contentChildren = items.map((item) => menuSheetItemHandler.transform(item, traverse));
54
+
55
+ return createLocalSnippetElement("MenuSheetGroup", undefined, contentChildren);
56
+ },
57
+ );
58
+ };
59
+
60
+ export const createMenuSheetHandler = (ctx: ComponentHandlerDeps) => {
61
+ const menuSheetGroupHandler = createMenuSheetGroupHandler(ctx);
62
+
63
+ return defineComponentHandler<MenuSheetProperties>(
64
+ metadata.componentMenuSheet.key,
65
+ (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) =>
74
+ menuSheetGroupHandler.transform(group, traverse),
75
+ );
76
+
77
+ const title = props["Show Header#17043:12"].value
78
+ ? props["Title Text#14599:0"].value
79
+ : undefined;
80
+
81
+ const description =
82
+ props["Show Header#17043:12"].value && props["Show Header Description#32984:0"].value
83
+ ? props["Description Text#21827:0"].value
84
+ : undefined;
85
+
86
+ const { labelAlign } = match(props.Layout.value)
87
+ .with("Text with Icon", () => ({ labelAlign: "left" }))
88
+ .with("Text Only", () => ({ labelAlign: "center" }))
89
+ .exhaustive();
90
+
91
+ const content = createLocalSnippetElement(
92
+ "MenuSheetContent",
93
+ { title, description, labelAlign },
94
+ contentChildren,
95
+ {
96
+ comment: title
97
+ ? undefined
98
+ : "title을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.",
99
+ },
100
+ );
101
+
102
+ const trigger = createLocalSnippetElement(
103
+ "MenuSheetTrigger",
104
+ { asChild: true },
105
+ createLocalSnippetElementTrigger("ActionButton", {}, "MenuSheet 열기"),
106
+ );
107
+
108
+ return createLocalSnippetElement("MenuSheetRoot", undefined, [trigger, content]);
109
+ },
110
+ );
111
+ };