@seed-design/figma 1.2.1 → 1.3.2

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 (31) hide show
  1. package/lib/codegen/index.cjs +201 -163
  2. package/lib/codegen/index.js +201 -163
  3. package/lib/codegen/targets/react/index.cjs +980 -573
  4. package/lib/codegen/targets/react/index.js +980 -573
  5. package/lib/index.cjs +201 -163
  6. package/lib/index.js +201 -163
  7. package/package.json +1 -1
  8. package/src/codegen/component-properties.ts +34 -6
  9. package/src/codegen/core/infer-layout.test.ts +1 -1
  10. package/src/codegen/targets/react/component/handlers/archive/checkbox.ts +3 -1
  11. package/src/codegen/targets/react/component/handlers/archive/field-button.ts +2 -2
  12. package/src/codegen/targets/react/component/handlers/archive/index.ts +0 -1
  13. package/src/codegen/targets/react/component/handlers/archive/slider.ts +2 -2
  14. package/src/codegen/targets/react/component/handlers/bottom-sheet.ts +4 -6
  15. package/src/codegen/targets/react/component/handlers/checkbox.ts +90 -2
  16. package/src/codegen/targets/react/component/handlers/chip.ts +1 -1
  17. package/src/codegen/targets/react/component/handlers/field-button.ts +10 -17
  18. package/src/codegen/targets/react/component/handlers/field.ts +4 -4
  19. package/src/codegen/targets/react/component/handlers/index.ts +1 -1
  20. package/src/codegen/targets/react/component/handlers/legacy-select-box.ts +1 -1
  21. package/src/codegen/targets/react/component/handlers/list-item.ts +22 -22
  22. package/src/codegen/targets/react/component/handlers/radio-group.ts +98 -20
  23. package/src/codegen/targets/react/component/handlers/select-box.ts +333 -0
  24. package/src/codegen/targets/react/component/handlers/slider.ts +5 -5
  25. package/src/codegen/targets/react/component/handlers/tabs.ts +5 -5
  26. package/src/codegen/targets/react/component/handlers/tag-group.ts +2 -2
  27. package/src/codegen/targets/react/component/handlers/text-field.ts +7 -7
  28. package/src/entities/data/__generated__/component-sets/index.d.ts +199 -161
  29. package/src/entities/data/__generated__/component-sets/index.mjs +199 -161
  30. package/src/entities/data/__generated__/components/index.d.ts +260 -0
  31. package/src/entities/data/__generated__/components/index.mjs +260 -0
@@ -1,6 +1,7 @@
1
1
  import type { BottomSheetProperties } from "@/codegen/component-properties";
2
2
  import { createElement, defineComponentHandler } from "@/codegen/core";
3
3
  import * as metadata from "@/entities/data/__generated__/component-sets";
4
+ import * as components from "@/entities/data/__generated__/components";
4
5
  import { match } from "ts-pattern";
5
6
  import { createLocalSnippetHelper } from "../../element-factories";
6
7
  import type { ComponentHandlerDeps } from "../deps.interface";
@@ -10,10 +11,6 @@ const { createLocalSnippetElement } = createLocalSnippetHelper("bottom-sheet");
10
11
  const { createLocalSnippetElement: createLocalSnippetElementTrigger } =
11
12
  createLocalSnippetHelper("action-button");
12
13
 
13
- // TODO: Bottom Action Bar (WIP) handler의 키. 해당 컴포넌트(템플릿) 핸들러 작성 시 handler.transform()으로 대체
14
- const BOTTOM_SHEET_FOOTER_KEY = "6475aac366b2b18edf8cbabff4f84a9f1619253a";
15
- const BOTTOM_SHEET_BODY_KEY = "e68b006d572300d3c987776192c8ab387fa45e05";
16
-
17
14
  export const createBottomSheetHandler = (_ctx: ComponentHandlerDeps) =>
18
15
  defineComponentHandler<BottomSheetProperties>(
19
16
  metadata.componentBottomSheet.key,
@@ -36,7 +33,7 @@ export const createBottomSheetHandler = (_ctx: ComponentHandlerDeps) =>
36
33
 
37
34
  const bodyNodes = findAllInstances({
38
35
  node,
39
- key: BOTTOM_SHEET_BODY_KEY,
36
+ key: components.privateComponentBottomSheetContentsPlaceholder.key,
40
37
  });
41
38
 
42
39
  const bottomSheetBody =
@@ -50,7 +47,8 @@ export const createBottomSheetHandler = (_ctx: ComponentHandlerDeps) =>
50
47
 
51
48
  const footerNodes = findAllInstances({
52
49
  node,
53
- key: BOTTOM_SHEET_FOOTER_KEY,
50
+ // TODO: Bottom Action Bar (WIP) handler의 키. 해당 컴포넌트(템플릿) 핸들러 작성 시 handler.transform()으로 대체
51
+ key: metadata.componentBottomActionBarFigmaOnly.key,
54
52
  });
55
53
 
56
54
  const bottomSheetFooter =
@@ -1,4 +1,9 @@
1
- import type { CheckboxProperties } from "@/codegen/component-properties";
1
+ import type {
2
+ CheckboxGroupFieldProperties,
3
+ CheckboxProperties,
4
+ FieldFooterProperties,
5
+ FieldHeaderProperties,
6
+ } from "@/codegen/component-properties";
2
7
  import { defineComponentHandler } from "@/codegen/core";
3
8
  import * as metadata from "@/entities/data/__generated__/component-sets";
4
9
  import { camelCase } from "change-case";
@@ -6,6 +11,13 @@ import { createLocalSnippetHelper } from "../../element-factories";
6
11
  import type { ComponentHandlerDeps } from "../deps.interface";
7
12
  import { handleSizeProp } from "../size";
8
13
  import { match } from "ts-pattern";
14
+ import {
15
+ createFieldFooterHandler,
16
+ createFieldHeaderHandler,
17
+ type FieldFooterProps,
18
+ type FieldHeaderProps,
19
+ } from "@/codegen/targets/react/component/handlers/field";
20
+ import { findAllInstances } from "@/utils/figma-node";
9
21
 
10
22
  const { createLocalSnippetElement } = createLocalSnippetHelper("checkbox");
11
23
 
@@ -36,6 +48,82 @@ export const createCheckboxHandler = (_ctx: ComponentHandlerDeps) =>
36
48
  }),
37
49
  };
38
50
 
39
- return createLocalSnippetElement("Checkbox", commonProps);
51
+ return createLocalSnippetElement("Checkbox", commonProps, undefined, {
52
+ comment: "CheckboxGroup으로 묶어서 사용하는 것을 권장합니다.",
53
+ });
40
54
  },
41
55
  );
56
+
57
+ export const createCheckboxGroupFieldHandler = (ctx: ComponentHandlerDeps) => {
58
+ const checkboxHandler = createCheckboxHandler(ctx);
59
+ const fieldHeaderHandler = createFieldHeaderHandler(ctx);
60
+ const fieldFooterHandler = createFieldFooterHandler(ctx);
61
+
62
+ return defineComponentHandler<CheckboxGroupFieldProperties>(
63
+ metadata.templateCheckboxField.key,
64
+ (node, traverse) => {
65
+ const { componentProperties: props } = node;
66
+
67
+ const items = findAllInstances<CheckboxProperties>({
68
+ node,
69
+ key: checkboxHandler.key,
70
+ });
71
+ const [fieldHeader] = findAllInstances<FieldHeaderProperties>({
72
+ node,
73
+ key: fieldHeaderHandler.key,
74
+ });
75
+ const [fieldFooter] = findAllInstances<FieldFooterProperties>({
76
+ node,
77
+ key: fieldFooterHandler.key,
78
+ });
79
+
80
+ // maxGraphemeCount / required / invalid can't be props of CheckboxGroup
81
+ const { required: _required, ...headerProps } =
82
+ props["Show Header#40606:8"].value && fieldHeader
83
+ ? (fieldHeaderHandler.transform(fieldHeader, traverse).props as FieldHeaderProps)
84
+ : {};
85
+ const {
86
+ maxGraphemeCount: _maxGraphemeCount,
87
+ invalid: _invalid,
88
+ ...footerProps
89
+ } = props["Show Footer#40606:9"].value && fieldFooter
90
+ ? (fieldFooterHandler.transform(fieldFooter, traverse).props as FieldFooterProps)
91
+ : {};
92
+
93
+ const commonProps = {
94
+ ...headerProps,
95
+ ...footerProps,
96
+ };
97
+
98
+ return createLocalSnippetElement(
99
+ "CheckboxGroup",
100
+ commonProps,
101
+ items.map((item) => {
102
+ const result = checkboxHandler.transform(item, traverse);
103
+
104
+ return {
105
+ ...result,
106
+ meta: {
107
+ ...result.meta,
108
+
109
+ // remove comment from individual Checkbox items
110
+ comment: undefined,
111
+ },
112
+ };
113
+ }),
114
+ {
115
+ comment: [
116
+ headerProps.label
117
+ ? undefined
118
+ : "label을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.",
119
+ footerProps.errorMessage
120
+ ? "errorMessage를 표시하는 경우, 접근성을 위해 개별 Checkbox 중 무효한 항목에 invalid를 설정해주세요."
121
+ : undefined,
122
+ ]
123
+ .filter(Boolean)
124
+ .join(" "),
125
+ },
126
+ );
127
+ },
128
+ );
129
+ };
@@ -52,7 +52,7 @@ export const createChipHandler = (ctx: ComponentHandlerDeps) => {
52
52
  .with("Avatar", () => {
53
53
  const [avatar] = findAllInstances<AvatarProperties>({
54
54
  node,
55
- key: metadata.componentAvatar.key,
55
+ key: avatarHandler.key,
56
56
  });
57
57
  if (!avatar) return undefined;
58
58
 
@@ -1,5 +1,6 @@
1
1
  import { defineComponentHandler } from "@/codegen/core";
2
2
  import * as sets from "@/entities/data/__generated__/component-sets";
3
+ import * as components from "@/entities/data/__generated__/components";
3
4
  import { createLocalSnippetHelper } from "../../element-factories";
4
5
  import type { ComponentHandlerDeps } from "../deps.interface";
5
6
  import {
@@ -23,14 +24,6 @@ import type { NormalizedTextNode } from "@/normalizer";
23
24
 
24
25
  const { createLocalSnippetElement } = createLocalSnippetHelper("field-button");
25
26
 
26
- // published but taken down now
27
- const FIELD_BUTTON_KEYS = {
28
- selectField: "a2138764f60a9b5a35e22ff40bc6cd701c660260",
29
- datePickerField: "c161d1326a1087258e4f762aa3c378c098308d98",
30
- timePickerField: "e38df17cf1e0f96e09774b015739dfde30d46115",
31
- addressPickerField: "4af06df28eca43fe2be5fe5ba5e6019587de9fac",
32
- } as const;
33
-
34
27
  export const createFieldButtonHandler = (ctx: ComponentHandlerDeps) => {
35
28
  const fieldHeaderHandler = createFieldHeaderHandler(ctx);
36
29
  const fieldFooterHandler = createFieldFooterHandler(ctx);
@@ -42,7 +35,7 @@ export const createFieldButtonHandler = (ctx: ComponentHandlerDeps) => {
42
35
 
43
36
  const [inputButton] = findAllInstances<InputButtonProperties>({
44
37
  node,
45
- key: sets.privateComponentInputButton.key,
38
+ key: sets.componentInputButton.key,
46
39
  });
47
40
 
48
41
  const [clearButton] = findAllInstances<ActionButtonGhostProperties>({
@@ -52,19 +45,19 @@ export const createFieldButtonHandler = (ctx: ComponentHandlerDeps) => {
52
45
 
53
46
  const [fieldHeader] = findAllInstances<FieldHeaderProperties>({
54
47
  node,
55
- key: sets.privateComponentFieldHeader.key,
48
+ key: sets.componentFieldHeader.key,
56
49
  });
57
50
  const [fieldFooter] = findAllInstances<FieldFooterProperties>({
58
51
  node,
59
- key: sets.privateComponentFieldFooter.key,
52
+ key: sets.componentFieldFooter.key,
60
53
  });
61
54
 
62
55
  // maxGraphemeCount and required can't be props of FieldButton
63
- const { required: __required, ...headerProps } =
56
+ const { required: _required, ...headerProps } =
64
57
  props["Show Header#40606:8"].value && fieldHeader
65
58
  ? (fieldHeaderHandler.transform(fieldHeader, traverse).props as FieldHeaderProps)
66
59
  : {};
67
- const { maxGraphemeCount: __maxGraphemeCount, ...footerProps } =
60
+ const { maxGraphemeCount: _maxGraphemeCount, ...footerProps } =
68
61
  props["Show Footer#40606:9"].value && fieldFooter
69
62
  ? (fieldFooterHandler.transform(fieldFooter, traverse).props as FieldFooterProps)
70
63
  : {};
@@ -138,7 +131,7 @@ export const createSelectFieldHandler = (ctx: ComponentHandlerDeps) => {
138
131
  const fieldButtonHandler = createFieldButtonHandler(ctx);
139
132
 
140
133
  return defineComponentHandler<GenericFieldButtonProps>(
141
- FIELD_BUTTON_KEYS.selectField,
134
+ components.privateTemplateSelectField.key,
142
135
  (node, traverse) => {
143
136
  const [fieldButton] = findAllInstances<FieldButtonProperties>({
144
137
  node,
@@ -154,7 +147,7 @@ export const createDatePickerFieldHandler = (ctx: ComponentHandlerDeps) => {
154
147
  const fieldButtonHandler = createFieldButtonHandler(ctx);
155
148
 
156
149
  return defineComponentHandler<GenericFieldButtonProps>(
157
- FIELD_BUTTON_KEYS.datePickerField,
150
+ components.privateTemplateDatePickerField.key,
158
151
  (node, traverse) => {
159
152
  const [fieldButton] = findAllInstances<FieldButtonProperties>({
160
153
  node,
@@ -170,7 +163,7 @@ export const createTimePickerFieldHandler = (ctx: ComponentHandlerDeps) => {
170
163
  const fieldButtonHandler = createFieldButtonHandler(ctx);
171
164
 
172
165
  return defineComponentHandler<GenericFieldButtonProps>(
173
- FIELD_BUTTON_KEYS.timePickerField,
166
+ components.privateTemplateTimePickerField.key,
174
167
  (node, traverse) => {
175
168
  const [fieldButton] = findAllInstances<FieldButtonProperties>({
176
169
  node,
@@ -186,7 +179,7 @@ export const createAddressFieldHandler = (ctx: ComponentHandlerDeps) => {
186
179
  const fieldButtonHandler = createFieldButtonHandler(ctx);
187
180
 
188
181
  return defineComponentHandler<GenericFieldButtonProps>(
189
- FIELD_BUTTON_KEYS.addressPickerField,
182
+ components.privateTemplateAddressPickerField.key,
190
183
  (node, traverse) => {
191
184
  const [fieldButton] = findAllInstances<FieldButtonProperties>({
192
185
  node,
@@ -24,13 +24,13 @@ export const createFieldHeaderHandler = (ctx: ComponentHandlerDeps) => {
24
24
  const indicatorHandler = createFieldIndicatorHandler(ctx);
25
25
 
26
26
  return defineComponentHandler<FieldHeaderProperties>(
27
- metadata.privateComponentFieldHeader.key,
27
+ metadata.componentFieldHeader.key,
28
28
  (node, traverse) => {
29
29
  const { componentProperties: props } = node;
30
30
 
31
31
  const [indicator] = findAllInstances<FieldIndicatorProperties>({
32
32
  node,
33
- key: metadata.privateComponentFieldHeaderIndicator.key,
33
+ key: indicatorHandler.key,
34
34
  });
35
35
 
36
36
  // only returns some nice common props for Slider, TextField and more
@@ -94,7 +94,7 @@ export const createFieldFooterHandler = (ctx: ComponentHandlerDeps) => {
94
94
  const characterCountHandler = createFieldCharacterCountHandler(ctx);
95
95
 
96
96
  return defineComponentHandler<FieldFooterProperties>(
97
- metadata.privateComponentFieldFooter.key,
97
+ metadata.componentFieldFooter.key,
98
98
  (node, traverse) => {
99
99
  const { componentProperties: props } = node;
100
100
 
@@ -110,7 +110,7 @@ export const createFieldFooterHandler = (ctx: ComponentHandlerDeps) => {
110
110
  .with("Character Count", () => {
111
111
  const [characterCount] = findAllInstances<FieldCharacterCountProperties>({
112
112
  node,
113
- key: metadata.privateComponentFieldFooterCharacterCount.key,
113
+ key: characterCountHandler.key,
114
114
  });
115
115
 
116
116
  return {
@@ -11,7 +11,6 @@ export * from "./checkmark";
11
11
  export * from "./chip";
12
12
  export * from "./contextual-floating-button";
13
13
  export * from "./divider";
14
- export * from "./field";
15
14
  export * from "./field-button";
16
15
  export * from "./floating-action-button";
17
16
  export * from "./help-bubble";
@@ -30,6 +29,7 @@ export * from "./radiomark";
30
29
  export * from "./reaction-button";
31
30
  export * from "./result-section";
32
31
  export * from "./segmented-control";
32
+ export * from "./select-box";
33
33
  export * from "./skeleton";
34
34
  export * from "./slider";
35
35
  export * from "./snackbar";
@@ -11,7 +11,7 @@ import type { ComponentHandlerDeps } from "../deps.interface";
11
11
 
12
12
  const { createLocalSnippetElement } = createLocalSnippetHelper("select-box");
13
13
 
14
- export const createLegacySelectBoxHandler = (_ctx: ComponentHandlerDeps) =>
14
+ const createLegacySelectBoxHandler = (_ctx: ComponentHandlerDeps) =>
15
15
  defineComponentHandler<LegacySelectBoxProperties>(
16
16
  metadata.componentDeprecatedSelectBox.key,
17
17
  ({ componentProperties: props }) => {
@@ -14,26 +14,26 @@ import { match } from "ts-pattern";
14
14
 
15
15
  const { createLocalSnippetElement } = createLocalSnippetHelper("list");
16
16
 
17
- const PREFIX_KEYS = {
18
- checkmark: "563275de82ea1282cece0c35c0cd8d1625bc3a9d",
19
- radiomark: "51f7c0917ebc559d81e63d0639cb632a792f40de",
20
- icon: components.componentListItemPrefixIcon.key,
21
- avatar: "27e33754113178be97e07195528c4ea020b3d3b7",
22
- image: "d06216ff143a960844799c0b8f9212628f78c69d",
23
- custom: "b8059f5e0f85e0745fc61ff70f04571177c2cdfc",
24
- };
25
-
26
- const SUFFIX_KEYS = {
27
- checkmark: "385ba8d607029e15e0d38ab415f783016488b185",
28
- radiomark: "09871d64c5c30407da586fb34425c2e83e147c81",
29
- chevron: components.componentListItemSuffixChevron.key,
30
- switch: "0c26bd64e117e168b06eea69be903e4be762a728",
31
- custom: "26b86c9f8965d38aa5a1181a5cdc89fa487988d1",
32
- icon: components.componentListItemSuffixIcon.key,
33
- chevronWithText: components.componentListItemSuffixChevronWithText.key,
34
- iconButton: metadata.componentListItemSuffixIconButton.key,
35
- actionButton: metadata.componentListItemSuffixActionButton.key,
36
- };
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
37
 
38
38
  export const createListItemHandler = (ctx: ComponentHandlerDeps) =>
39
39
  defineComponentHandler<ListItemProperties>(metadata.componentListItem.key, (node, traverse) => {
@@ -55,7 +55,7 @@ export const createListItemHandler = (ctx: ComponentHandlerDeps) =>
55
55
  const prefixNode = (() => {
56
56
  if (props["Has Prefix#28452:85"].value === false) return null;
57
57
 
58
- for (const key of Object.values(PREFIX_KEYS)) {
58
+ for (const key of PREFIX_KEYS) {
59
59
  const [found] = findAllInstances<ListItemPrefixIconProperties | {}>({ node, key });
60
60
 
61
61
  if (found) return found;
@@ -79,7 +79,7 @@ export const createListItemHandler = (ctx: ComponentHandlerDeps) =>
79
79
  const suffixNode = (() => {
80
80
  if (props["Has Suffix#28452:64"].value === false) return null;
81
81
 
82
- for (const key of Object.values(SUFFIX_KEYS)) {
82
+ for (const key of SUFFIX_KEYS) {
83
83
  const [found] = findAllInstances<ListItemSuffixIconProperties | {}>({ node, key });
84
84
 
85
85
  if (found) return found;
@@ -1,4 +1,4 @@
1
- import type { RadioProperties } from "@/codegen/component-properties";
1
+ import type { RadioGroupFieldProperties, RadioProperties } from "@/codegen/component-properties";
2
2
  import { defineComponentHandler } from "@/codegen/core";
3
3
  import * as metadata from "@/entities/data/__generated__/component-sets";
4
4
  import { createLocalSnippetHelper } from "../../element-factories";
@@ -6,26 +6,104 @@ import type { ComponentHandlerDeps } from "../deps.interface";
6
6
  import { handleSizeProp } from "../size";
7
7
  import { camelCase } from "change-case";
8
8
  import { match } from "ts-pattern";
9
+ import {
10
+ createFieldFooterHandler,
11
+ createFieldHeaderHandler,
12
+ type FieldFooterProps,
13
+ type FieldHeaderProps,
14
+ } from "@/codegen/targets/react/component/handlers/field";
15
+ import { findAllInstances } from "@/utils/figma-node";
16
+ import type { FieldFooterProperties, FieldHeaderProperties } from "@/codegen/component-properties";
9
17
 
10
18
  const { createLocalSnippetElement } = createLocalSnippetHelper("radio-group");
11
19
 
12
20
  export const createRadioGroupItemHandler = (_ctx: ComponentHandlerDeps) =>
13
- defineComponentHandler<RadioProperties>(metadata.componentRadio.key, ({ componentProperties: props }) => {
14
- const tone = match(props.Tone.value)
15
- .with("Neutral", () => "neutral")
16
- .with("🚫[Deprecated]Brand", () => "brand")
17
- .exhaustive();
18
-
19
- const commonProps = {
20
- ...(props.State.value === "Disabled" && {
21
- disabled: true,
22
- }),
23
- label: props["Label#49990:171"].value,
24
- value: props["Label#49990:171"].value,
25
- size: handleSizeProp(props.Size.value),
26
- tone,
27
- weight: camelCase(props.Weight.value),
28
- };
29
-
30
- return createLocalSnippetElement("RadioGroupItem", commonProps);
31
- });
21
+ defineComponentHandler<RadioProperties>(
22
+ metadata.componentRadio.key,
23
+ ({ componentProperties: props }) => {
24
+ const tone = match(props.Tone.value)
25
+ .with("Neutral", () => "neutral")
26
+ .with("🚫[Deprecated]Brand", () => "brand")
27
+ .exhaustive();
28
+
29
+ const commonProps = {
30
+ ...(props.State.value === "Disabled" && {
31
+ disabled: true,
32
+ }),
33
+ label: props["Label#49990:171"].value,
34
+ value: props["Label#49990:171"].value,
35
+ size: handleSizeProp(props.Size.value),
36
+ tone,
37
+ weight: camelCase(props.Weight.value),
38
+ };
39
+
40
+ return createLocalSnippetElement("RadioGroupItem", commonProps, undefined, {
41
+ comment: "RadioGroup으로 묶어서 사용하세요.",
42
+ });
43
+ },
44
+ );
45
+
46
+ export const createRadioGroupFieldHandler = (ctx: ComponentHandlerDeps) => {
47
+ const radioItemHandler = createRadioGroupItemHandler(ctx);
48
+ const fieldHeaderHandler = createFieldHeaderHandler(ctx);
49
+ const fieldFooterHandler = createFieldFooterHandler(ctx);
50
+
51
+ return defineComponentHandler<RadioGroupFieldProperties>(
52
+ metadata.templateRadioField.key,
53
+ (node, traverse) => {
54
+ const { componentProperties: props } = node;
55
+
56
+ const items = findAllInstances<RadioProperties>({
57
+ node,
58
+ key: radioItemHandler.key,
59
+ });
60
+ const [fieldHeader] = findAllInstances<FieldHeaderProperties>({
61
+ node,
62
+ key: fieldHeaderHandler.key,
63
+ });
64
+ const [fieldFooter] = findAllInstances<FieldFooterProperties>({
65
+ node,
66
+ key: fieldFooterHandler.key,
67
+ });
68
+
69
+ // maxGraphemeCount and required can't be props of RadioGroup
70
+ const { required: _required, ...headerProps } =
71
+ props["Show Header#40606:8"].value && fieldHeader
72
+ ? (fieldHeaderHandler.transform(fieldHeader, traverse).props as FieldHeaderProps)
73
+ : {};
74
+ const { maxGraphemeCount: _maxGraphemeCount, ...footerProps } =
75
+ props["Show Footer#40606:9"].value && fieldFooter
76
+ ? (fieldFooterHandler.transform(fieldFooter, traverse).props as FieldFooterProps)
77
+ : {};
78
+
79
+ const selectedItem = items.find((item) => item.componentProperties.Selected.value === "True");
80
+
81
+ const commonProps = {
82
+ ...headerProps,
83
+ ...footerProps,
84
+
85
+ ...(selectedItem && {
86
+ defaultValue: selectedItem.componentProperties["Label#49990:171"].value,
87
+ }),
88
+ };
89
+
90
+ return createLocalSnippetElement(
91
+ "RadioGroup",
92
+ commonProps,
93
+ items.map((item) => {
94
+ const result = radioItemHandler.transform(item, traverse);
95
+
96
+ return {
97
+ ...result,
98
+ meta: {
99
+ ...result.meta,
100
+
101
+ // remove comment from individual RadioGroupItem items
102
+ comment: undefined,
103
+ },
104
+ };
105
+ }),
106
+ );
107
+ },
108
+ );
109
+ };