@seed-design/figma 0.0.21 → 0.0.22

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 (82) hide show
  1. package/lib/codegen/index.cjs +8019 -0
  2. package/lib/codegen/index.d.ts +1827 -0
  3. package/lib/codegen/index.js +7989 -0
  4. package/lib/codegen/targets/react/index.cjs +12205 -0
  5. package/lib/codegen/targets/react/index.d.ts +270 -0
  6. package/lib/codegen/targets/react/index.js +12187 -0
  7. package/lib/index.cjs +79 -2741
  8. package/lib/index.d.ts +17 -1937
  9. package/lib/index.js +61 -2715
  10. package/package.json +11 -1
  11. package/src/codegen/{targets/react/component/properties.type.ts → component-properties.ts} +43 -43
  12. package/src/codegen/core/codegen.ts +23 -8
  13. package/src/codegen/core/{component.ts → component-handler.ts} +3 -3
  14. package/src/codegen/core/component-type-helper.ts +35 -0
  15. package/src/codegen/core/context.ts +20 -0
  16. package/src/codegen/core/index.ts +16 -14
  17. package/src/codegen/core/{props.ts → props-converter.ts} +10 -13
  18. package/src/codegen/core/{value.ts → value-resolver.ts} +90 -52
  19. package/src/codegen/default-services.ts +44 -0
  20. package/src/codegen/index.ts +1 -44
  21. package/src/codegen/targets/figma/frame.ts +8 -8
  22. package/src/codegen/targets/figma/index.ts +1 -1
  23. package/src/codegen/targets/figma/pipeline.ts +71 -0
  24. package/src/codegen/targets/figma/props.ts +59 -70
  25. package/src/codegen/targets/figma/shape.ts +18 -18
  26. package/src/codegen/targets/figma/text.ts +6 -6
  27. package/src/codegen/targets/figma/value-resolver.ts +22 -0
  28. package/src/codegen/targets/react/component/deps.interface.ts +5 -4
  29. package/src/codegen/targets/react/component/{transformers → handlers}/action-button.ts +8 -14
  30. package/src/codegen/targets/react/component/{transformers → handlers}/action-chip.ts +10 -20
  31. package/src/codegen/targets/react/component/{transformers → handlers}/action-sheet.ts +13 -10
  32. package/src/codegen/targets/react/component/{transformers → handlers}/app-bar.ts +28 -36
  33. package/src/codegen/targets/react/component/handlers/avatar-stack.ts +29 -0
  34. package/src/codegen/targets/react/component/{transformers → handlers}/avatar.ts +12 -9
  35. package/src/codegen/targets/react/component/handlers/badge.ts +18 -0
  36. package/src/codegen/targets/react/component/{transformers → handlers}/callout.ts +6 -8
  37. package/src/codegen/targets/react/component/{transformers → handlers}/checkbox.ts +5 -5
  38. package/src/codegen/targets/react/component/{transformers → handlers}/chip-tabs.ts +10 -10
  39. package/src/codegen/targets/react/component/{transformers → handlers}/control-chip.ts +10 -20
  40. package/src/codegen/targets/react/component/{transformers → handlers}/error-state.ts +9 -9
  41. package/src/codegen/targets/react/component/{transformers → handlers}/extended-action-sheet.ts +16 -18
  42. package/src/codegen/targets/react/component/{transformers → handlers}/extended-fab.ts +6 -6
  43. package/src/codegen/targets/react/component/handlers/fab.ts +18 -0
  44. package/src/codegen/targets/react/component/{transformers → handlers}/help-bubble.ts +5 -5
  45. package/src/codegen/targets/react/component/{transformers → handlers}/identity-placeholder.ts +5 -5
  46. package/src/codegen/targets/react/component/{transformers → handlers}/inline-banner.ts +7 -10
  47. package/src/codegen/targets/react/component/{transformers → handlers}/manner-temp-badge.ts +5 -5
  48. package/src/codegen/targets/react/component/{transformers → handlers}/multiline-text-field.ts +5 -5
  49. package/src/codegen/targets/react/component/{transformers → handlers}/progress-circle.ts +5 -5
  50. package/src/codegen/targets/react/component/{transformers → handlers}/reaction-button.ts +6 -6
  51. package/src/codegen/targets/react/component/{transformers → handlers}/segmented-control.ts +10 -10
  52. package/src/codegen/targets/react/component/{transformers → handlers}/select-box.ts +10 -10
  53. package/src/codegen/targets/react/component/handlers/skeleton.ts +25 -0
  54. package/src/codegen/targets/react/component/{transformers → handlers}/snackbar.ts +5 -5
  55. package/src/codegen/targets/react/component/{transformers → handlers}/switch.ts +5 -5
  56. package/src/codegen/targets/react/component/{transformers → handlers}/tabs.ts +15 -15
  57. package/src/codegen/targets/react/component/{transformers → handlers}/text-button.ts +7 -13
  58. package/src/codegen/targets/react/component/{transformers → handlers}/text-field.ts +9 -9
  59. package/src/codegen/targets/react/component/{transformers → handlers}/toggle-button.ts +7 -11
  60. package/src/codegen/targets/react/component/index.ts +79 -75
  61. package/src/codegen/targets/react/frame.ts +8 -8
  62. package/src/codegen/targets/react/icon.ts +50 -0
  63. package/src/codegen/targets/react/index.ts +1 -1
  64. package/src/codegen/targets/react/instance.ts +19 -50
  65. package/src/codegen/targets/react/pipeline.ts +108 -0
  66. package/src/codegen/targets/react/props.ts +95 -73
  67. package/src/codegen/targets/react/shape.ts +5 -5
  68. package/src/codegen/targets/react/text.ts +6 -6
  69. package/src/codegen/targets/react/value-resolver.ts +35 -0
  70. package/src/entities/icon.repository.ts +2 -2
  71. package/src/entities/icon.service.ts +9 -20
  72. package/src/entities/style.service.ts +5 -17
  73. package/src/entities/variable.service.ts +36 -68
  74. package/src/utils/figma-variable.ts +39 -3
  75. package/src/codegen/core/component.types.ts +0 -29
  76. package/src/codegen/targets/figma/context.ts +0 -139
  77. package/src/codegen/targets/react/component/transformers/avatar-stack.ts +0 -29
  78. package/src/codegen/targets/react/component/transformers/badge.ts +0 -21
  79. package/src/codegen/targets/react/component/transformers/fab.ts +0 -18
  80. package/src/codegen/targets/react/component/transformers/skeleton.ts +0 -51
  81. package/src/codegen/targets/react/context.ts +0 -176
  82. /package/src/codegen/core/{element.ts → element-transformer.ts} +0 -0
@@ -1,24 +1,22 @@
1
- import { createElement, defineComponentTransformer } from "@/codegen/core";
1
+ import type { TextButtonProperties } from "@/codegen/component-properties";
2
+ import { createElement, defineComponentHandler } from "@/codegen/core";
2
3
  import * as metadata from "@/entities/data/__generated__/component-sets";
3
4
  import type { NormalizedInstanceNode } from "@/normalizer";
4
5
  import { findOne } from "@/utils/figma-node";
5
6
  import { camelCase } from "change-case";
6
7
  import { match } from "ts-pattern";
7
- import type { SeedComponentTransformerDeps } from "../deps.interface";
8
- import type { TextButtonProperties } from "../properties.type";
8
+ import type { ComponentHandlerDeps } from "../deps.interface";
9
9
  import { handleSizeProp } from "../size";
10
10
 
11
- export const createTextButtonTransformer = (ctx: SeedComponentTransformerDeps) =>
12
- defineComponentTransformer<TextButtonProperties>(metadata.textButton.key, (node) => {
11
+ export const createTextButtonHandler = (ctx: ComponentHandlerDeps) =>
12
+ defineComponentHandler<TextButtonProperties>(metadata.textButton.key, (node) => {
13
13
  const { componentProperties: props } = node;
14
14
 
15
15
  const states = props.State.value.split("-");
16
16
 
17
17
  const { prefixIcon, suffixIcon, children } = match(props.Layout.value)
18
18
  .with("Icon First", () => ({
19
- prefixIcon: createElement(
20
- ctx.iconService.createIconTagName(props["Prefix Icon#7561:0"].componentKey),
21
- ),
19
+ prefixIcon: ctx.iconHandler.transform(props["Prefix Icon#7561:0"]),
22
20
  suffixIcon: undefined,
23
21
  children: props["Label#6148:0"].value,
24
22
  }))
@@ -28,13 +26,9 @@ export const createTextButtonTransformer = (ctx: SeedComponentTransformerDeps) =
28
26
  (node) => node.type === "INSTANCE" && node.name === "Suffix Icon",
29
27
  ) as NormalizedInstanceNode | null;
30
28
 
31
- const suffixIconComponentKey = suffixIconNode?.componentKey;
32
-
33
29
  return {
34
30
  prefixIcon: undefined,
35
- suffixIcon: suffixIconComponentKey
36
- ? createElement(ctx.iconService.createIconTagName(suffixIconComponentKey))
37
- : undefined,
31
+ suffixIcon: suffixIconNode ? ctx.iconHandler.transform(suffixIconNode) : undefined,
38
32
  children: props["Label#6148:0"].value,
39
33
  };
40
34
  })
@@ -1,11 +1,11 @@
1
- import { createElement, defineComponentTransformer } from "@/codegen/core";
1
+ import { createElement, defineComponentHandler } from "@/codegen/core";
2
2
  import * as metadata from "@/entities/data/__generated__/component-sets";
3
- import type { SeedComponentTransformerDeps } from "../deps.interface";
4
- import type { TextFieldProperties } from "../properties.type";
3
+ import type { ComponentHandlerDeps } from "../deps.interface";
4
+ import type { TextFieldProperties } from "@/codegen/component-properties";
5
5
  import { handleSizeProp } from "../size";
6
6
 
7
- export const createTextFieldTransformer = (ctx: SeedComponentTransformerDeps) =>
8
- defineComponentTransformer<TextFieldProperties>(
7
+ export const createTextFieldHandler = (ctx: ComponentHandlerDeps) =>
8
+ defineComponentHandler<TextFieldProperties>(
9
9
  metadata.textField.key,
10
10
  ({ componentProperties: props }) => {
11
11
  const {
@@ -18,14 +18,14 @@ export const createTextFieldTransformer = (ctx: SeedComponentTransformerDeps) =>
18
18
  "Indicator#15327:249": { value: indicator },
19
19
  "Show Prefix#958:125": { value: showPrefix },
20
20
  "Show Prefix Icon#1267:50": { value: showPrefixIcon },
21
- "Prefix Icon#1267:25": { componentKey: prefixIcon },
21
+ "Prefix Icon#1267:25": prefixIcon,
22
22
  "Show Prefix Text#1267:0": { value: showPrefixText },
23
23
  "Prefix Text#15327:101": { value: prefix },
24
24
  "Placeholder#958:0": { value: placeholder },
25
25
  "Filled Text#1304:0": { value: defaultValue },
26
26
  "Show Suffix#958:100": { value: showSuffix },
27
27
  "Show Suffix Icon#1267:75": { value: showSuffixIcon },
28
- "Suffix Icon #1267:100": { componentKey: suffixIcon },
28
+ "Suffix Icon #1267:100": suffixIcon,
29
29
  "Show Suffix Text#1267:125": { value: showSuffixText },
30
30
  "Suffix Text#15327:138": { value: suffix },
31
31
  "Show Footer#958:25": { value: showFooter },
@@ -51,7 +51,7 @@ export const createTextFieldTransformer = (ctx: SeedComponentTransformerDeps) =>
51
51
  // input affixes
52
52
  ...(showPrefix &&
53
53
  showPrefixIcon && {
54
- prefixIcon: createElement(ctx.iconService.createIconTagName(prefixIcon)),
54
+ prefixIcon: ctx.iconHandler.transform(prefixIcon),
55
55
  }),
56
56
  ...(showPrefix &&
57
57
  showPrefixText && {
@@ -59,7 +59,7 @@ export const createTextFieldTransformer = (ctx: SeedComponentTransformerDeps) =>
59
59
  }),
60
60
  ...(showSuffix &&
61
61
  showSuffixIcon && {
62
- suffixIcon: createElement(ctx.iconService.createIconTagName(suffixIcon)),
62
+ suffixIcon: ctx.iconHandler.transform(suffixIcon),
63
63
  }),
64
64
  ...(showSuffix &&
65
65
  showSuffixText && {
@@ -1,12 +1,12 @@
1
- import { createElement, defineComponentTransformer } from "@/codegen/core";
1
+ import { createElement, defineComponentHandler } from "@/codegen/core";
2
2
  import * as metadata from "@/entities/data/__generated__/component-sets";
3
3
  import { camelCase } from "change-case";
4
- import type { SeedComponentTransformerDeps } from "../deps.interface";
5
- import type { ToggleButtonProperties } from "../properties.type";
4
+ import type { ComponentHandlerDeps } from "../deps.interface";
5
+ import type { ToggleButtonProperties } from "@/codegen/component-properties";
6
6
  import { handleSizeProp } from "../size";
7
7
 
8
- export const createToggleButtonTransformer = (ctx: SeedComponentTransformerDeps) =>
9
- defineComponentTransformer<ToggleButtonProperties>(
8
+ export const createToggleButtonHandler = (ctx: ComponentHandlerDeps) =>
9
+ defineComponentHandler<ToggleButtonProperties>(
10
10
  metadata.toggleButton.key,
11
11
  ({ componentProperties: props }) => {
12
12
  const states = props.State.value.split("-");
@@ -28,17 +28,13 @@ export const createToggleButtonTransformer = (ctx: SeedComponentTransformerDeps)
28
28
  return createElement("ToggleButton", commonProps, [
29
29
  props["Show Prefix Icon#6122:392"].value
30
30
  ? createElement("PrefixIcon", {
31
- svg: createElement(
32
- ctx.iconService.createIconTagName(props["Prefix Icon#6122:98"].componentKey),
33
- ),
31
+ svg: ctx.iconHandler.transform(props["Prefix Icon#6122:98"]),
34
32
  })
35
33
  : undefined,
36
34
  props["Label#6122:49"].value,
37
35
  props["Show Suffix Icon#6122:147"].value
38
36
  ? createElement("SuffixIcon", {
39
- svg: createElement(
40
- ctx.iconService.createIconTagName(props["Suffix Icon#6122:343"].componentKey),
41
- ),
37
+ svg: ctx.iconHandler.transform(props["Suffix Icon#6122:343"]),
42
38
  })
43
39
  : undefined,
44
40
  ]);
@@ -1,77 +1,81 @@
1
- import type { ComponentTransformer } from "@/codegen/core";
2
- import type { SeedComponentTransformerDeps } from "./deps.interface";
3
- import { createActionButtonTransformer } from "./transformers/action-button";
4
- import { createActionChipTransformer } from "./transformers/action-chip";
5
- import { createActionSheetTransformer } from "./transformers/action-sheet";
6
- import { createAppBarTransformer } from "./transformers/app-bar";
7
- import { createAvatarTransformer } from "./transformers/avatar";
8
- import { createAvatarStackTransformer } from "./transformers/avatar-stack";
9
- import { createBadgeTransformer } from "./transformers/badge";
10
- import { createCalloutTransformer } from "./transformers/callout";
11
- import { createCheckboxTransformer } from "./transformers/checkbox";
12
- import { createChipTabsTransformer } from "./transformers/chip-tabs";
13
- import { createControlChipTransformer } from "./transformers/control-chip";
14
- import { createErrorStateTransformer } from "./transformers/error-state";
15
- import { createExtendedActionSheetTransformer } from "./transformers/extended-action-sheet";
16
- import { createExtendedFabTransformer } from "./transformers/extended-fab";
17
- import { createFabTransformer } from "./transformers/fab";
18
- import { createHelpBubbleTransformer } from "./transformers/help-bubble";
19
- import { createIdentityPlaceholderTransformer } from "./transformers/identity-placeholder";
20
- import { createInlineBannerTransformer } from "./transformers/inline-banner";
21
- import { createMannerTempBadgeTransformer } from "./transformers/manner-temp-badge";
22
- import { createMultilineTextFieldTransformer } from "./transformers/multiline-text-field";
23
- import { createProgressCircleTransformer } from "./transformers/progress-circle";
24
- import { createReactionButtonTransformer } from "./transformers/reaction-button";
25
- import { createSegmentedControlTransformer } from "./transformers/segmented-control";
26
- import {
27
- createSelectBoxGroupTransformer,
28
- createSelectBoxTransformer,
29
- } from "./transformers/select-box";
30
- import { createSkeletonTransformer } from "./transformers/skeleton";
31
- import { createSnackbarTransformer } from "./transformers/snackbar";
32
- import { createSwitchTransformer } from "./transformers/switch";
33
- import { createTabsTransformer } from "./transformers/tabs";
34
- import { createTextButtonTransformer } from "./transformers/text-button";
35
- import { createTextFieldTransformer } from "./transformers/text-field";
36
- import { createToggleButtonTransformer } from "./transformers/toggle-button";
1
+ import type { ComponentHandler } from "@/codegen/core";
2
+ import type { NormalizedInstanceNode } from "@/normalizer";
3
+ import type { ComponentHandlerDeps } from "./deps.interface";
4
+ import { createActionButtonHandler } from "./handlers/action-button";
5
+ import { createActionChipHandler } from "./handlers/action-chip";
6
+ import { createActionSheetHandler } from "./handlers/action-sheet";
7
+ import { createAppBarHandler } from "./handlers/app-bar";
8
+ import { createAvatarHandler } from "./handlers/avatar";
9
+ import { createAvatarStackHandler } from "./handlers/avatar-stack";
10
+ import { createBadgeHandler } from "./handlers/badge";
11
+ import { createCalloutHandler } from "./handlers/callout";
12
+ import { createCheckboxHandler } from "./handlers/checkbox";
13
+ import { createChipTabsHandler } from "./handlers/chip-tabs";
14
+ import { createControlChipHandler } from "./handlers/control-chip";
15
+ import { createErrorStateHandler } from "./handlers/error-state";
16
+ import { createExtendedActionSheetHandler } from "./handlers/extended-action-sheet";
17
+ import { createExtendedFabHandler } from "./handlers/extended-fab";
18
+ import { createFabHandler } from "./handlers/fab";
19
+ import { createHelpBubbleHandler } from "./handlers/help-bubble";
20
+ import { createIdentityPlaceholderHandler } from "./handlers/identity-placeholder";
21
+ import { createInlineBannerHandler } from "./handlers/inline-banner";
22
+ import { createMannerTempBadgeHandler } from "./handlers/manner-temp-badge";
23
+ import { createMultilineTextFieldHandler } from "./handlers/multiline-text-field";
24
+ import { createProgressCircleHandler } from "./handlers/progress-circle";
25
+ import { createReactionButtonHandler } from "./handlers/reaction-button";
26
+ import { createSegmentedControlHandler } from "./handlers/segmented-control";
27
+ import { createSelectBoxGroupHandler, createSelectBoxHandler } from "./handlers/select-box";
28
+ import { createSkeletonHandler } from "./handlers/skeleton";
29
+ import { createSnackbarHandler } from "./handlers/snackbar";
30
+ import { createSwitchHandler } from "./handlers/switch";
31
+ import { createTabsHandler } from "./handlers/tabs";
32
+ import { createTextButtonHandler } from "./handlers/text-button";
33
+ import { createTextFieldHandler } from "./handlers/text-field";
34
+ import { createToggleButtonHandler } from "./handlers/toggle-button";
37
35
 
38
- export type { SeedComponentTransformerDeps };
39
- export type * from "./properties.type";
36
+ export type { ComponentHandlerDeps };
37
+ export type UnboundComponentHandler<T extends NormalizedInstanceNode["componentProperties"]> = (
38
+ deps: ComponentHandlerDeps,
39
+ ) => ComponentHandler<T>;
40
40
 
41
- export const createSeedComponentTransformers = (ctx: SeedComponentTransformerDeps) =>
42
- Object.fromEntries(
43
- [
44
- createActionButtonTransformer(ctx),
45
- createActionChipTransformer(ctx),
46
- createActionSheetTransformer(ctx),
47
- createAppBarTransformer(ctx),
48
- createAvatarTransformer(ctx),
49
- createAvatarStackTransformer(ctx),
50
- createBadgeTransformer(ctx),
51
- createCalloutTransformer(ctx),
52
- createCheckboxTransformer(ctx),
53
- createChipTabsTransformer(ctx),
54
- createControlChipTransformer(ctx),
55
- createErrorStateTransformer(ctx),
56
- createExtendedActionSheetTransformer(ctx),
57
- createExtendedFabTransformer(ctx),
58
- createFabTransformer(ctx),
59
- createHelpBubbleTransformer(ctx),
60
- createIdentityPlaceholderTransformer(ctx),
61
- createInlineBannerTransformer(ctx),
62
- createMannerTempBadgeTransformer(ctx),
63
- createMultilineTextFieldTransformer(ctx),
64
- createProgressCircleTransformer(ctx),
65
- createReactionButtonTransformer(ctx),
66
- createSegmentedControlTransformer(ctx),
67
- createSelectBoxGroupTransformer(ctx),
68
- createSelectBoxTransformer(ctx),
69
- createSkeletonTransformer(ctx),
70
- createSnackbarTransformer(ctx),
71
- createSwitchTransformer(ctx),
72
- createTabsTransformer(ctx),
73
- createTextButtonTransformer(ctx),
74
- createTextFieldTransformer(ctx),
75
- createToggleButtonTransformer(ctx),
76
- ].map((x) => [x.key, x]) as Array<[string, ComponentTransformer]>,
77
- );
41
+ export function bindComponentHandler<T extends NormalizedInstanceNode["componentProperties"]>(
42
+ unbound: UnboundComponentHandler<T>,
43
+ deps: ComponentHandlerDeps,
44
+ ): ComponentHandler<T> {
45
+ return unbound(deps);
46
+ }
47
+
48
+ export const unboundSeedComponentHandlers: Array<UnboundComponentHandler<any>> = [
49
+ createActionButtonHandler,
50
+ createActionChipHandler,
51
+ createActionSheetHandler,
52
+ createAppBarHandler,
53
+ createAvatarHandler,
54
+ createAvatarStackHandler,
55
+ createBadgeHandler,
56
+ createCalloutHandler,
57
+ createCheckboxHandler,
58
+ createChipTabsHandler,
59
+ createControlChipHandler,
60
+ createErrorStateHandler,
61
+ createExtendedActionSheetHandler,
62
+ createExtendedFabHandler,
63
+ createFabHandler,
64
+ createHelpBubbleHandler,
65
+ createIdentityPlaceholderHandler,
66
+ createInlineBannerHandler,
67
+ createMannerTempBadgeHandler,
68
+ createMultilineTextFieldHandler,
69
+ createProgressCircleHandler,
70
+ createReactionButtonHandler,
71
+ createSegmentedControlHandler,
72
+ createSelectBoxGroupHandler,
73
+ createSelectBoxHandler,
74
+ createSkeletonHandler,
75
+ createSnackbarHandler,
76
+ createSwitchHandler,
77
+ createTabsHandler,
78
+ createTextButtonHandler,
79
+ createTextFieldHandler,
80
+ createToggleButtonHandler,
81
+ ];
@@ -9,14 +9,14 @@ import {
9
9
  defineElementTransformer,
10
10
  type ElementTransformer,
11
11
  } from "../../core";
12
- import type { ContainerLayoutProps, PropsTransformers } from "./props";
12
+ import type { ContainerLayoutProps, PropsConverters } from "./props";
13
13
 
14
14
  export interface FrameTransformerDeps {
15
- propsTransformers: PropsTransformers;
15
+ propsConverters: PropsConverters;
16
16
  }
17
17
 
18
18
  export function createFrameTransformer({
19
- propsTransformers,
19
+ propsConverters,
20
20
  }: FrameTransformerDeps): ElementTransformer<
21
21
  NormalizedFrameNode | NormalizedInstanceNode | NormalizedComponentNode
22
22
  > {
@@ -39,11 +39,11 @@ export function createFrameTransformer({
39
39
  const isFlex = node.layoutMode === "HORIZONTAL" || node.layoutMode === "VERTICAL";
40
40
 
41
41
  const props = {
42
- ...propsTransformers.radius(node, traverse),
43
- ...(isFlex ? propsTransformers.containerLayout(node, traverse) : {}),
44
- ...propsTransformers.selfLayout(node, traverse),
45
- ...propsTransformers.frameFill(node, traverse),
46
- ...propsTransformers.stroke(node, traverse),
42
+ ...propsConverters.radius(node),
43
+ ...(isFlex ? propsConverters.containerLayout(node) : {}),
44
+ ...propsConverters.selfLayout(node),
45
+ ...propsConverters.frameFill(node),
46
+ ...propsConverters.stroke(node),
47
47
  };
48
48
 
49
49
  const isStretch = props.align === undefined || props.align === "stretch";
@@ -0,0 +1,50 @@
1
+ import type { IconService } from "@/entities";
2
+ import { pascalCase } from "change-case";
3
+ import { type ElementNode, createElement } from "../../core";
4
+
5
+ export interface IconHandler {
6
+ isIconInstance: (node: { componentKey: string }) => boolean;
7
+ transform: (node: { componentKey: string }) => ElementNode;
8
+ }
9
+
10
+ export interface IconHandlerDeps {
11
+ iconService: IconService;
12
+ iconNameFormatter?: (props: { name: string; weight?: string }) => string;
13
+ }
14
+
15
+ const defaultIconNameFormatter = ({ name, weight }: { name: string; weight?: string }) =>
16
+ pascalCase(`${name}${weight ? weight : ""}`);
17
+
18
+ export function createIconHandler({
19
+ iconService,
20
+ iconNameFormatter = defaultIconNameFormatter,
21
+ }: IconHandlerDeps): IconHandler {
22
+ function isIconInstance(node: { componentKey: string }): boolean {
23
+ const key = node.componentKey;
24
+
25
+ if (!key) {
26
+ return false;
27
+ }
28
+
29
+ return iconService.isAvailable(key);
30
+ }
31
+
32
+ function transform(node: { componentKey: string }): ElementNode {
33
+ const key = node.componentKey;
34
+ const iconData = iconService.getOne(key);
35
+ if (!iconData) {
36
+ return createElement("UnknownIcon");
37
+ }
38
+
39
+ const { name, weight } = iconData;
40
+
41
+ const tagName = iconNameFormatter({ name, weight });
42
+
43
+ return createElement(tagName);
44
+ }
45
+
46
+ return {
47
+ isIconInstance,
48
+ transform,
49
+ };
50
+ }
@@ -4,4 +4,4 @@ export * from "./frame";
4
4
  export * from "./instance";
5
5
  export * from "./text";
6
6
  export * from "./component";
7
- export * from "./context";
7
+ export * from "./pipeline";
@@ -1,74 +1,43 @@
1
- import type { IconService } from "@/entities";
2
- import type { NormalizedFrameTrait, NormalizedInstanceNode } from "@/normalizer";
1
+ import type { NormalizedInstanceNode } from "@/normalizer";
3
2
  import {
4
3
  createElement,
5
4
  defineElementTransformer,
6
- definePropsTransformer,
7
- type ComponentTransformer,
5
+ type ComponentHandler,
8
6
  type ElementTransformer,
9
7
  } from "../../core";
10
- import type { PropsTransformers } from "./props";
8
+ import type { IconHandler } from "./icon";
9
+ import type { PropsConverters } from "./props";
11
10
 
12
11
  export interface InstanceTransformerDeps {
13
- iconService?: IconService;
14
- ignoredComponentKeys?: Set<string>;
15
- propsTransformers: PropsTransformers;
16
- componentTransformers: Record<string, ComponentTransformer>;
12
+ iconHandler?: IconHandler;
13
+ propsConverters: PropsConverters;
14
+ componentHandlers: Record<string, ComponentHandler>;
17
15
  frameTransformer: ElementTransformer<NormalizedInstanceNode>;
18
16
  }
19
17
 
20
18
  export function createInstanceTransformer({
21
- iconService,
22
- ignoredComponentKeys,
23
- propsTransformers,
24
- componentTransformers,
19
+ iconHandler,
20
+ propsConverters,
21
+ componentHandlers,
25
22
  frameTransformer,
26
23
  }: InstanceTransformerDeps): ElementTransformer<NormalizedInstanceNode> {
27
- const transformIconColorProps = definePropsTransformer((node: NormalizedFrameTrait, traverse) => {
28
- if (node.children.length === 0) {
29
- throw new Error("Node has no children");
30
- }
31
-
32
- const vectors = node.children.filter(
33
- (child) => child.type === "VECTOR" || child.type === "BOOLEAN_OPERATION",
34
- );
35
-
36
- const colorProps = vectors.map((vector) => propsTransformers.shapeFill(vector, traverse));
37
-
38
- const fills = new Set(
39
- colorProps.map((props) => props.color).filter((color) => color !== undefined),
40
- );
41
-
42
- // If there are more than 1 color, colors are likely pre-defined in the icon component; we should ignore the color prop.
43
- if (fills.size > 1) {
44
- return {};
45
- }
46
-
47
- return { color: fills.values().next().value };
48
- });
49
-
50
24
  const transform = defineElementTransformer((node: NormalizedInstanceNode, traverse) => {
51
25
  const { componentKey, componentSetKey } = node;
52
26
 
53
- if (ignoredComponentKeys?.has(componentKey)) {
54
- return undefined;
55
- }
56
-
57
- if (iconService?.isIconComponent(componentKey)) {
58
- const tagName = iconService.createIconTagName(componentKey);
27
+ if (iconHandler?.isIconInstance(node)) {
59
28
  const props = {
60
- ...propsTransformers.iconSelfLayout(node, traverse),
61
- ...transformIconColorProps(node, traverse),
29
+ ...propsConverters.iconSelfLayout(node),
30
+ ...propsConverters.vectorChildrenFill(node),
62
31
  };
63
- return createElement("Icon", { svg: createElement(tagName), ...props });
32
+ return createElement("Icon", { svg: iconHandler.transform(node), ...props });
64
33
  }
65
34
 
66
- const componentTransformer = componentSetKey
67
- ? componentTransformers[componentSetKey]
68
- : componentTransformers[componentKey];
35
+ const componentHandler = componentSetKey
36
+ ? componentHandlers[componentSetKey]
37
+ : componentHandlers[componentKey];
69
38
 
70
- if (componentTransformer) {
71
- return componentTransformer.transform(node);
39
+ if (componentHandler) {
40
+ return componentHandler.transform(node);
72
41
  }
73
42
 
74
43
  return frameTransformer(node, traverse);
@@ -0,0 +1,108 @@
1
+ import { createCodeGenerator } from "@/codegen/core";
2
+ import { iconService } from "@/codegen/default-services";
3
+ import {
4
+ type UnboundComponentHandler,
5
+ bindComponentHandler,
6
+ unboundSeedComponentHandlers,
7
+ } from "./component";
8
+ import { createFrameTransformer } from "./frame";
9
+ import { createIconHandler } from "./icon";
10
+ import { createInstanceTransformer } from "./instance";
11
+ import {
12
+ createContainerLayoutPropsConverter,
13
+ createFrameFillPropsConverter,
14
+ createIconSelfLayoutPropsConverter,
15
+ createRadiusPropsConverter,
16
+ createSelfLayoutPropsConverter,
17
+ createShapeFillPropsConverter,
18
+ createStrokePropsConverter,
19
+ createTextFillPropsConverter,
20
+ createTypeStylePropsConverter,
21
+ createVectorChildrenFillPropsConverter,
22
+ } from "./props";
23
+ import {
24
+ createBooleanOperationTransformer,
25
+ createRectangleTransformer,
26
+ createVectorTransformer,
27
+ } from "./shape";
28
+ import { createTextTransformer } from "./text";
29
+ import { valueResolver } from "./value-resolver";
30
+
31
+ export interface CreatePipelineConfig {
32
+ extend?: {
33
+ componentHandlers?: Array<UnboundComponentHandler<any>>;
34
+ };
35
+ }
36
+
37
+ const iconHandler = createIconHandler({
38
+ iconService,
39
+ });
40
+
41
+ export function createPipeline(options: CreatePipelineConfig = {}) {
42
+ const { extend = {} } = options;
43
+
44
+ const containerLayoutPropsConverter = createContainerLayoutPropsConverter(valueResolver);
45
+ const selfLayoutPropsConverter = createSelfLayoutPropsConverter(valueResolver);
46
+ const iconSelfLayoutPropsConverter = createIconSelfLayoutPropsConverter(valueResolver);
47
+ const frameFillPropsConverter = createFrameFillPropsConverter(valueResolver);
48
+ const shapeFillPropsConverter = createShapeFillPropsConverter(valueResolver);
49
+ const textFillPropsConverter = createTextFillPropsConverter(valueResolver);
50
+ const vectorChildrenFillPropsConverter = createVectorChildrenFillPropsConverter(valueResolver);
51
+ const radiusPropsConverter = createRadiusPropsConverter(valueResolver);
52
+ const strokePropsConverter = createStrokePropsConverter(valueResolver);
53
+ const typeStylePropsConverter = createTypeStylePropsConverter({
54
+ valueResolver,
55
+ });
56
+ const propsConverters = {
57
+ containerLayout: containerLayoutPropsConverter,
58
+ selfLayout: selfLayoutPropsConverter,
59
+ iconSelfLayout: iconSelfLayoutPropsConverter,
60
+ frameFill: frameFillPropsConverter,
61
+ shapeFill: shapeFillPropsConverter,
62
+ textFill: textFillPropsConverter,
63
+ vectorChildrenFill: vectorChildrenFillPropsConverter,
64
+ radius: radiusPropsConverter,
65
+ stroke: strokePropsConverter,
66
+ typeStyle: typeStylePropsConverter,
67
+ };
68
+
69
+ const componentHandlers = Object.fromEntries(
70
+ [...unboundSeedComponentHandlers, ...(extend.componentHandlers ?? [])]
71
+ .map((h) =>
72
+ bindComponentHandler(h, {
73
+ valueResolver,
74
+ iconHandler,
75
+ }),
76
+ )
77
+ .map((t) => [t.key, t]),
78
+ );
79
+
80
+ const frameTransformer = createFrameTransformer({
81
+ propsConverters,
82
+ });
83
+ const instanceTransformer = createInstanceTransformer({
84
+ iconHandler,
85
+ propsConverters,
86
+ componentHandlers,
87
+ frameTransformer,
88
+ });
89
+ const textTransformer = createTextTransformer({
90
+ propsConverters,
91
+ });
92
+ const rectangleTransformer = createRectangleTransformer({
93
+ propsConverters,
94
+ });
95
+ const vectorTransformer = createVectorTransformer();
96
+ const booleanOperationTransformer = createBooleanOperationTransformer();
97
+
98
+ const codeGenerator = createCodeGenerator({
99
+ frameTransformer,
100
+ textTransformer,
101
+ rectangleTransformer,
102
+ instanceTransformer,
103
+ vectorTransformer,
104
+ booleanOperationTransformer,
105
+ });
106
+
107
+ return codeGenerator;
108
+ }