@carrier-dpx/air-react-library 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Air React Library
2
+
3
+ Air web React component library for Figma Make integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @carrier-dpx/air-react-library
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ This library requires the following peer dependencies:
14
+
15
+ ```bash
16
+ npm install react react-dom @mui/material @emotion/react @emotion/styled
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Button Component
22
+
23
+ ```tsx
24
+ import { Button } from '@carrier-dpx/air-react-library';
25
+
26
+ function App() {
27
+ return (
28
+ <Button
29
+ variant="contained"
30
+ color="primary"
31
+ size="large"
32
+ onClick={() => console.log('clicked')}
33
+ >
34
+ Get Started
35
+ </Button>
36
+ );
37
+ }
38
+ ```
39
+
40
+ ### Available Props
41
+
42
+ #### Button
43
+
44
+ - `variant`: `"contained"` | `"outlined"` | `"text"` (default: `"contained"`)
45
+ - `color`: `"base"` | `"primary"` | `"secondary"` | `"error"` | `"warning"` | `"success"` | `"info"` (default: `"primary"`)
46
+ - `size`: `"xlarge"` | `"large"` | `"medium"` | `"small"` | `"xsmall"`
47
+ - `shape`: `"rounded"` | `"circular"` (default: `"rounded"`)
48
+ - `disabled`: `boolean`
49
+ - `startIcon`: `ReactNode` - Icon to display before the button text
50
+ - `endIcon`: `ReactNode` - Icon to display after the button text
51
+ - `onClick`: `() => void` - Click handler
52
+ - All standard Material-UI Button props
53
+
54
+ ## Figma Integration
55
+
56
+ This library is integrated with Figma Code Connect. When using Figma Make, components from this library will be automatically suggested and used in generated code.
57
+
58
+ ## Components
59
+
60
+ Currently available components:
61
+
62
+ - **Button** - Material-UI based button component with Carrier DPX design system styling
63
+
64
+ More components coming soon!
65
+
66
+ ## License
67
+
68
+ MIT
69
+
70
+ ## Repository
71
+
72
+ [https://github.com/Carrier-DPX/air-react-library](https://github.com/Carrier-DPX/air-react-library)
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@carrier-dpx/air-react-library",
3
+ "version": "0.1.0",
4
+ "description": "Air web React component library for Figma Make",
5
+ "main": "src/index.ts",
6
+ "types": "src/index.ts",
7
+ "files": [
8
+ "src",
9
+ "README.md"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/Carrier-DPX/air-react-library.git"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "scripts": {
19
+ "figma:connect": "figma connect",
20
+ "figma:publish": "figma connect publish"
21
+ },
22
+ "keywords": [
23
+ "react",
24
+ "components",
25
+ "figma",
26
+ "code-connect",
27
+ "carrier",
28
+ "design-system",
29
+ "ui",
30
+ "material-ui"
31
+ ],
32
+ "author": "Carrier DPX",
33
+ "license": "MIT",
34
+ "peerDependencies": {
35
+ "react": "^18.0.0",
36
+ "react-dom": "^18.0.0",
37
+ "@mui/material": "^5.0.0",
38
+ "@emotion/react": "^11.0.0",
39
+ "@emotion/styled": "^11.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@figma/code-connect": "^1.0.0",
43
+ "@mui/material": "^5.15.0",
44
+ "@emotion/react": "^11.11.0",
45
+ "@emotion/styled": "^11.11.0",
46
+ "@types/react": "^18.0.0",
47
+ "@types/react-dom": "^18.0.0",
48
+ "typescript": "^5.0.0"
49
+ }
50
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Button Component
3
+ *
4
+ * This file creates the bridge between your Figma Button component
5
+ * and your React Button component. It tells Figma Make:
6
+ * 1. Which React component corresponds to which Figma component
7
+ * 2. How Figma properties/variants map to React props
8
+ * 3. How to generate code examples
9
+ */
10
+
11
+ import figma from "@figma/code-connect";
12
+ import Button from "./Button";
13
+
14
+ /**
15
+ * figma.connect() creates the connection between Figma and React
16
+ *
17
+ * Parameters:
18
+ * 1. Button - Your React component
19
+ * 2. Figma URL - Points to your specific component in Figma
20
+ * 3. Configuration object - Defines the prop mappings
21
+ */
22
+ figma.connect(
23
+ Button,
24
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=20456-152342",
25
+ {
26
+ /**
27
+ * PROPS MAPPING
28
+ *
29
+ * This section maps Figma properties to React props.
30
+ *
31
+ * Format options:
32
+ * - figma.enum("PropertyName", { ... }) - for variant/dropdown properties
33
+ * - figma.boolean("PropertyName") - for boolean properties
34
+ * - figma.string("PropertyName") - for text properties
35
+ * - figma.children("LayerName") - for nested content/children
36
+ * - figma.instance("LayerName") - for nested component instances
37
+ */
38
+ props: {
39
+ /**
40
+ * VARIANT MAPPING
41
+ * Maps Figma's "variant" property to React's "variant" prop
42
+ *
43
+ * Figma: filled, outlined, text
44
+ * React: contained, outlined, text
45
+ *
46
+ * Note: "filled" in Figma maps to "contained" in Material-UI
47
+ */
48
+ variant: figma.enum("variant", {
49
+ filled: "contained",
50
+ outlined: "outlined",
51
+ text: "text",
52
+ }),
53
+
54
+ /**
55
+ * SIZE MAPPING
56
+ * Maps Figma's "size" property to React's "size" prop
57
+ *
58
+ * Figma size names include pixel values (e.g., "xlarge-56px")
59
+ * React expects just the size name (e.g., "xlarge")
60
+ */
61
+ size: figma.enum("size", {
62
+ "xlarge-56px": "xlarge",
63
+ "large-48px": "large",
64
+ "medium-40px": "medium",
65
+ "small-32px": "small",
66
+ "xsmall-24px": "xsmall",
67
+ }),
68
+
69
+ /**
70
+ * COLOR MAPPING
71
+ * Maps Figma's "color" property to React's "color" prop
72
+ *
73
+ * Note: "base" is a custom color in the Carrier DPX theme palette
74
+ * It's an extension of the standard Material-UI colors and provides
75
+ * the foundation colors for the design system
76
+ */
77
+ color: figma.enum("color", {
78
+ base: "base",
79
+ primary: "primary",
80
+ secondary: "secondary",
81
+ error: "error",
82
+ warning: "warning",
83
+ success: "success",
84
+ info: "info",
85
+ }),
86
+
87
+ /**
88
+ * DISABLED STATE
89
+ * Maps Figma's "disabled" boolean property to React's "disabled" prop
90
+ */
91
+ disabled: figma.boolean("disabled"),
92
+
93
+ /**
94
+ * BUTTON TEXT/CHILDREN
95
+ * Maps the text content from the "Button Label" layer
96
+ * Uses figma.children() to capture nested text content
97
+ */
98
+ children: figma.children("Button Label"),
99
+
100
+ /**
101
+ * START ICON
102
+ * Maps Figma's "startIcon" layer (when visible) to React's startIcon prop
103
+ *
104
+ * figma.instance() connects to nested component instances in Figma
105
+ * The "startIcon" boolean property controls visibility in Figma
106
+ */
107
+ startIcon: figma.instance("startIcon"),
108
+
109
+ /**
110
+ * END ICON
111
+ * Maps Figma's "endIcon" layer (when visible) to React's endIcon prop
112
+ */
113
+ endIcon: figma.instance("endIcon"),
114
+ },
115
+
116
+ /**
117
+ * EXAMPLE CODE TEMPLATE
118
+ *
119
+ * This defines how the component should appear in generated code.
120
+ * The template uses the props mapped above.
121
+ *
122
+ * When Figma Make generates code, it will substitute the actual
123
+ * values based on the component instance properties.
124
+ *
125
+ * Note: We're ignoring the "state" and "label" properties because:
126
+ * - "state" (enabled/hover/focus) is a visual state in Figma, not a prop
127
+ * - "label" is just a boolean to show/hide the text layer
128
+ */
129
+ example: ({ variant, color, size, disabled, startIcon, endIcon, children }) => (
130
+ <Button
131
+ variant={variant}
132
+ color={color}
133
+ size={size}
134
+ disabled={disabled}
135
+ startIcon={startIcon}
136
+ endIcon={endIcon}
137
+ >
138
+ {children}
139
+ </Button>
140
+ ),
141
+ }
142
+ );
@@ -0,0 +1,104 @@
1
+ import { ElementType, forwardRef, Ref } from "react";
2
+
3
+ import MuiButton, { ButtonProps as MuiButtonProps } from "@mui/material/Button";
4
+ import { TouchRippleActions } from "@mui/material/ButtonBase/TouchRipple";
5
+ import { CSSObject, Theme } from "@mui/material/styles";
6
+
7
+ import { getSxStyles } from "../utils/styles";
8
+ import { styleTokens } from "../theme/constants/styleTokens";
9
+
10
+ declare module "@mui/material/Button" {
11
+ interface ButtonPropsSizeOverrides {
12
+ xlarge: true;
13
+ xsmall: true;
14
+ }
15
+ }
16
+
17
+ export interface ButtonProps extends MuiButtonProps {
18
+ /**
19
+ * A ref that points to the TouchRipple element.
20
+ */
21
+ touchRippleRef?: Ref<TouchRippleActions>;
22
+ /**
23
+ * The component used for the root node. Either a string to use a HTML element or a component.
24
+ */
25
+ component?: ElementType;
26
+ /**
27
+ * The border radius of the button.
28
+ * @default "rounded"
29
+ */
30
+ shape?: "rounded" | "circular";
31
+ }
32
+
33
+ const getHoverOverrides = (theme: Theme): CSSObject => ({
34
+ "&.MuiButton-containedPrimary:hover": {
35
+ backgroundColor: theme.palette.primary?.containedHoverBackground,
36
+ },
37
+ "&.MuiButton-containedSecondary:hover": {
38
+ backgroundColor: theme.palette.secondary?.containedHoverBackground,
39
+ },
40
+ "&.MuiButton-containedError:hover": {
41
+ backgroundColor: theme.palette.error?.containedHoverBackground,
42
+ },
43
+ "&.MuiButton-containedWarning:hover": {
44
+ backgroundColor: theme.palette.warning?.containedHoverBackground,
45
+ },
46
+ "&.MuiButton-containedSuccess:hover": {
47
+ backgroundColor: theme.palette.success?.containedHoverBackground,
48
+ },
49
+ "&.MuiButton-containedInfo:hover": {
50
+ backgroundColor: theme.palette.info?.containedHoverBackground,
51
+ },
52
+ });
53
+
54
+ /** The Button component allows users to take action which is communicated through a text label and optional icons.
55
+ *
56
+ * // Default import
57
+ * import Button from '@carrier-io/air-react/Button'
58
+ *
59
+ * // Named import
60
+ * import { Button } from '@carrier-io/air-react'
61
+ */
62
+ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
63
+ (
64
+ {
65
+ color = "primary",
66
+ size,
67
+ variant = "contained",
68
+ disableElevation = true,
69
+ shape = "rounded",
70
+ sx,
71
+ ...rest
72
+ },
73
+ ref
74
+ ) => {
75
+ return (
76
+ <MuiButton
77
+ ref={ref}
78
+ color={color}
79
+ size={size}
80
+ variant={variant}
81
+ disableElevation={disableElevation}
82
+ sx={(theme) =>
83
+ ({
84
+ borderRadius:
85
+ shape === "rounded"
86
+ ? styleTokens.borderRadius.large
87
+ : styleTokens.borderRadius.circular,
88
+ ...getHoverOverrides(theme),
89
+ ...getSxStyles(theme, sx),
90
+ } as CSSObject)
91
+ }
92
+ style={{
93
+ textTransform: "unset",
94
+ border: variant === "text" ? "none" : "",
95
+ }}
96
+ {...rest}
97
+ />
98
+ );
99
+ }
100
+ );
101
+
102
+ Button.displayName = "Button";
103
+
104
+ export default Button;
@@ -0,0 +1,3 @@
1
+ export { default } from "./Button";
2
+ export * from "./Button";
3
+ export type { ButtonProps } from "./Button";
@@ -0,0 +1,6 @@
1
+ export const styleTokens = {
2
+ borderRadius: {
3
+ large: "8px",
4
+ circular: "50%",
5
+ },
6
+ };
@@ -0,0 +1,8 @@
1
+ import { SxProps, Theme } from "@mui/material/styles";
2
+
3
+ export const getSxStyles = (theme: Theme, sx?: SxProps<Theme>) => {
4
+ if (typeof sx === "function") {
5
+ return sx(theme);
6
+ }
7
+ return sx || {};
8
+ };
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as Button } from "./components/Button";
2
+ export type { ButtonProps } from "./components/Button";