@carrier-dpx/air-react-library 0.4.0 → 0.5.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 CHANGED
@@ -154,6 +154,9 @@ Currently available components:
154
154
  - **Button** - Material-UI based button component with Carrier DPX design system styling
155
155
  - **Typography** - Text component with all Carrier DPX typography variants (h1-h6, body1-3, caps, etc.)
156
156
  - **TextField** - Input field component with Carrier DPX styling (supports multiple sizes, colors, validation states)
157
+ - **Link** - Hyperlink component with typography variants and underline options
158
+ - **Divider** - Horizontal and vertical divider lines (with optional text labels)
159
+ - **Copyright** - Copyright notice component (automatically adds © and current year)
157
160
 
158
161
  More components coming soon!
159
162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carrier-dpx/air-react-library",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Air web React component library for Figma Make",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -32,19 +32,22 @@
32
32
  "author": "Carrier DPX",
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "react": "^18.0.0",
36
- "react-dom": "^18.0.0",
37
- "@mui/material": "^5.0.0",
38
35
  "@emotion/react": "^11.0.0",
39
- "@emotion/styled": "^11.0.0"
36
+ "@emotion/styled": "^11.0.0",
37
+ "@mui/material": "^5.0.0",
38
+ "react": "^18.0.0",
39
+ "react-dom": "^18.0.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@figma/code-connect": "^1.0.0",
43
- "@mui/material": "^5.15.0",
44
42
  "@emotion/react": "^11.11.0",
45
43
  "@emotion/styled": "^11.11.0",
44
+ "@figma/code-connect": "^1.0.0",
45
+ "@mui/material": "^5.15.0",
46
46
  "@types/react": "^18.0.0",
47
47
  "@types/react-dom": "^18.0.0",
48
48
  "typescript": "^5.0.0"
49
+ },
50
+ "dependencies": {
51
+ "clsx": "^2.1.1"
49
52
  }
50
53
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Copyright Component
3
+ */
4
+
5
+ import figma from "@figma/code-connect";
6
+ import Copyright from "./Copyright";
7
+
8
+ figma.connect(
9
+ Copyright,
10
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=37592-67050",
11
+ {
12
+ props: {
13
+ /**
14
+ * TEXT CONTENT
15
+ * Copyright component shows © {year} {text}
16
+ * The year is automatically generated, so we just need the text
17
+ */
18
+ text: figma.string("*"),
19
+ },
20
+
21
+ /**
22
+ * CODE EXAMPLE TEMPLATE
23
+ * Copyright automatically adds © symbol and current year
24
+ */
25
+ example: ({ text }) => <Copyright text={text || "Carrier"} />,
26
+ }
27
+ );
@@ -0,0 +1,36 @@
1
+ import { FC, useMemo } from "react";
2
+ import { CSSObject, styled } from "@mui/material/styles";
3
+ import Typography from "../Typography";
4
+ import { CopyrightProps } from "./types";
5
+ import clsx from "clsx";
6
+ import styles from "./styles";
7
+ import { getSxStyles } from "../utils/styles";
8
+
9
+ const CopyrightStyled = styled(Typography)(styles);
10
+ const baseClassName = "copyright";
11
+
12
+ /** The Copyright pattern provides legal confirmation for time of ownership.
13
+ * //Default Import
14
+ * `import Copyright from '@carrier-io/air-react/Copyright'`
15
+ * //Named Import
16
+ * `import { Copyright } from '@carrier-io/air-react'`
17
+ */
18
+ const Copyright: FC<CopyrightProps> = ({ text, sx, className }) => {
19
+ const currentYear = useMemo(() => {
20
+ return new Date().getFullYear();
21
+ }, []);
22
+
23
+ return (
24
+ <CopyrightStyled
25
+ variant="body3"
26
+ sx={(theme) =>
27
+ ({ fontSize: "12px", ...getSxStyles(theme, sx) } as CSSObject)
28
+ }
29
+ className={clsx(baseClassName, className)}
30
+ >
31
+ © {currentYear} {text}
32
+ </CopyrightStyled>
33
+ );
34
+ };
35
+
36
+ export default Copyright;
@@ -0,0 +1,3 @@
1
+ export * from "./Copyright";
2
+ export * from "./types";
3
+ export { default } from "./Copyright";
@@ -0,0 +1,8 @@
1
+ import { lighten } from "@mui/material";
2
+ import { StyledComponentDefaultProps } from "../types/common";
3
+
4
+ const styles = ({ theme }: StyledComponentDefaultProps) => ({
5
+ color: lighten(theme.palette.common.black, 0.6),
6
+ });
7
+
8
+ export default styles;
@@ -0,0 +1,8 @@
1
+ import { StylesExtendable } from "../types/props";
2
+
3
+ export interface CopyrightProps extends StylesExtendable {
4
+ /**
5
+ * The content rendered within the component.
6
+ */
7
+ text: string;
8
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Divider Component (Horizontal)
3
+ */
4
+
5
+ import figma from "@figma/code-connect";
6
+ import Divider from "./Divider";
7
+
8
+ figma.connect(
9
+ Divider,
10
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=15518-67418",
11
+ {
12
+ props: {
13
+ /**
14
+ * VARIANT MAPPING
15
+ */
16
+ variant: figma.enum("variant", {
17
+ full: "full",
18
+ padded: "padded",
19
+ }),
20
+
21
+ /**
22
+ * TEXT ALIGN MAPPING
23
+ */
24
+ textAlign: figma.enum("textAlign", {
25
+ center: "center",
26
+ left: "left",
27
+ right: "right",
28
+ }),
29
+
30
+ /**
31
+ * TEXT CONTENT
32
+ * When text boolean is true, shows Typography children
33
+ */
34
+ children: figma.boolean("text") ? figma.children("*") : undefined,
35
+ },
36
+
37
+ /**
38
+ * CODE EXAMPLE TEMPLATE
39
+ * Horizontal divider (default orientation)
40
+ */
41
+ example: ({ variant, textAlign, children }) =>
42
+ children ? (
43
+ <Divider variant={variant} textAlign={textAlign}>
44
+ {children}
45
+ </Divider>
46
+ ) : (
47
+ <Divider variant={variant} />
48
+ ),
49
+ }
50
+ );
@@ -0,0 +1,57 @@
1
+ import { forwardRef } from "react";
2
+
3
+ import MuiDivider, {
4
+ DividerProps as MuiDividerProps,
5
+ } from "@mui/material/Divider";
6
+ import { styled } from "@mui/material/styles";
7
+
8
+ import { styleTokens } from "../theme/constants/styleTokens";
9
+
10
+ export interface DividerProps extends Omit<MuiDividerProps, "light"> {}
11
+
12
+ declare module "@mui/material/Divider" {
13
+ interface DividerPropsVariantOverrides {
14
+ padded: true;
15
+ middle: false;
16
+ full: true;
17
+ fullWidth: false;
18
+ inset: false;
19
+ }
20
+ }
21
+
22
+ /** The Divider component is a thin line that groups content in lists and layouts.
23
+ *
24
+ * // Default import
25
+ * import Divider from '@carrier-io/air-react/Divider'
26
+ *
27
+ * // Named import
28
+ * import { Divider } from '@carrier-io/air-react'
29
+ */
30
+
31
+ const MuiDividerStyled = styled(MuiDivider)(({ theme }) => ({
32
+ "&.MuiDivider-padded": {
33
+ marginLeft: styleTokens.margin.large,
34
+ marginRight: styleTokens.margin.large,
35
+ paddingTop: "8px",
36
+ paddingBottom: "8px",
37
+ },
38
+ "& .MuiDivider-wrapper": {
39
+ paddingLeft: styleTokens.padding.xsmall,
40
+ paddingRight: styleTokens.padding.xsmall,
41
+ color: theme.palette.base?.text.primary,
42
+ },
43
+ "&.MuiDivider-root": {
44
+ borderColor: theme.palette.base?.divider,
45
+ "&:before, &:after": {
46
+ borderTop: `thin solid ${theme.palette.base?.divider}`,
47
+ },
48
+ },
49
+ }));
50
+
51
+ const Divider = forwardRef<HTMLHRElement, DividerProps>((props, ref) => {
52
+ return <MuiDividerStyled {...props} ref={ref} />;
53
+ });
54
+
55
+ Divider.displayName = "Divider";
56
+
57
+ export default Divider;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Divider Component (Vertical)
3
+ */
4
+
5
+ import figma from "@figma/code-connect";
6
+ import Divider from "./Divider";
7
+
8
+ figma.connect(
9
+ Divider,
10
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=15556-68596",
11
+ {
12
+ props: {
13
+ /**
14
+ * VARIANT MAPPING
15
+ */
16
+ variant: figma.enum("variant", {
17
+ full: "full",
18
+ padded: "padded",
19
+ }),
20
+
21
+ /**
22
+ * TEXT ALIGN MAPPING
23
+ */
24
+ textAlign: figma.enum("textAlign", {
25
+ center: "center",
26
+ left: "left",
27
+ right: "right",
28
+ }),
29
+
30
+ /**
31
+ * TEXT CONTENT
32
+ * When text boolean is true, shows Typography children
33
+ */
34
+ children: figma.boolean("text") ? figma.children("*") : undefined,
35
+ },
36
+
37
+ /**
38
+ * CODE EXAMPLE TEMPLATE
39
+ * Vertical divider - sets orientation="vertical"
40
+ */
41
+ example: ({ variant, textAlign, children }) =>
42
+ children ? (
43
+ <Divider
44
+ orientation="vertical"
45
+ variant={variant}
46
+ textAlign={textAlign}
47
+ >
48
+ {children}
49
+ </Divider>
50
+ ) : (
51
+ <Divider orientation="vertical" variant={variant} />
52
+ ),
53
+ }
54
+ );
@@ -0,0 +1,3 @@
1
+ export { default } from "./Divider";
2
+ export * from "./Divider";
3
+ export type { DividerProps } from "./Divider";
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Figma Code Connect Configuration for Link Component
3
+ */
4
+
5
+ import figma from "@figma/code-connect";
6
+ import Link from "./Link";
7
+
8
+ figma.connect(
9
+ Link,
10
+ "https://www.figma.com/design/vkoHdM6rchIhH9IWetZeP0/Air--Components?node-id=6574-50682",
11
+ {
12
+ props: {
13
+ /**
14
+ * VARIANT MAPPING
15
+ * Same variants as Typography component
16
+ */
17
+ variant: figma.enum("variant", {
18
+ body1: "body1",
19
+ "body1 semibold": "body1Semibold",
20
+ "body1 bold": "body1Bold",
21
+ body2: "body2",
22
+ "body2 semibold": "body2Semibold",
23
+ "body2 bold": "body2Bold",
24
+ body3: "body3",
25
+ "body3 semibold": "body3Semibold",
26
+ "body3 bold": "body3Bold",
27
+ h1: "h1",
28
+ h2: "h2",
29
+ h3: "h3",
30
+ h4: "h4",
31
+ h5: "h5",
32
+ h6: "h6",
33
+ caps1: "caps1",
34
+ "caps1 bold": "caps1Bold",
35
+ caps2: "caps2",
36
+ "caps2 bold": "caps2Bold",
37
+ caps3: "caps3",
38
+ "caps3 bold": "caps3Bold",
39
+ caps4: "caps4",
40
+ "caps4 bold": "caps4Bold",
41
+ }),
42
+
43
+ /**
44
+ * UNDERLINE MAPPING
45
+ * Maps Figma underline style to React underline prop
46
+ */
47
+ underline: figma.enum("underline", {
48
+ always: "always",
49
+ hover: "hover",
50
+ none: "none",
51
+ }),
52
+
53
+ /**
54
+ * TEXT CONTENT
55
+ * Maps the link text from "Label" layer
56
+ */
57
+ children: figma.children("Label"),
58
+ },
59
+
60
+ /**
61
+ * CODE EXAMPLE TEMPLATE
62
+ * Note: href is a runtime prop, not configured in static Figma component
63
+ */
64
+ example: ({ variant, underline, children }) => (
65
+ <Link variant={variant} underline={underline} href="#">
66
+ {children}
67
+ </Link>
68
+ ),
69
+ }
70
+ );
@@ -0,0 +1,69 @@
1
+ import { forwardRef } from "react";
2
+
3
+ import MuiLink, { LinkProps as MuiLinkProps } from "@mui/material/Link";
4
+ import { AllSystemCSSProperties, ResponsiveStyleValue } from "@mui/system";
5
+ import { useTheme } from "@mui/material";
6
+ import { TypographyProps } from "@mui/material/Typography";
7
+
8
+ // List of variants we want to exclude
9
+ type ExcludedVariants =
10
+ | "overline"
11
+ | "avatarLetter"
12
+ | "buttonLarge"
13
+ | "buttonMedium"
14
+ | "buttonSmall"
15
+ | "caption"
16
+ | "inputLabel"
17
+ | "inputText1"
18
+ | "inputText2"
19
+ | "helperText"
20
+ | "alertTitle"
21
+ | "tableHeader1"
22
+ | "tableHeader2"
23
+ | "badge"
24
+ | "chip"
25
+ | "tooltip";
26
+
27
+ // Get all valid variant options from MUI's Typography component
28
+ type MUIValidVariants = Exclude<TypographyProps["variant"], ExcludedVariants>;
29
+
30
+ export interface LinkProps extends Omit<MuiLinkProps, "variant"> {
31
+ /**
32
+ * Specifies how to capitalize an element's text
33
+ */
34
+ textTransform?: ResponsiveStyleValue<AllSystemCSSProperties["textTransform"]>;
35
+ /**
36
+ * The target attribute specifies where to open the linked document:
37
+ */
38
+ target?: string;
39
+ /**
40
+ * Applies the theme typography styles.
41
+ */
42
+ variant?: MUIValidVariants;
43
+ }
44
+
45
+ /** The Link component allows you to easily customize anchor elements with your theme colors and typography styles.
46
+ *
47
+ * `import Link from '@carrier-io/air-react/Link'`
48
+ */
49
+
50
+ const Link = forwardRef<HTMLAnchorElement, LinkProps>(
51
+ ({ color, variant = "body2", ...rest }, ref) => {
52
+ const theme = useTheme();
53
+ const resolvedColor = color ?? theme.palette.primary.main;
54
+
55
+ return (
56
+ <MuiLink
57
+ {...rest}
58
+ color={resolvedColor}
59
+ ref={ref}
60
+ variant={variant}
61
+ sx={{ cursor: "pointer", textUnderlineOffset: "4px" }}
62
+ />
63
+ );
64
+ }
65
+ );
66
+
67
+ Link.displayName = "Link";
68
+
69
+ export default Link;
@@ -0,0 +1,3 @@
1
+ export { default } from "./Link";
2
+ export * from "./Link";
3
+ export type { LinkProps } from "./Link";
@@ -1,6 +1,42 @@
1
+ import { Theme } from "@mui/material";
2
+
1
3
  export const styleTokens = {
2
4
  borderRadius: {
5
+ small: "2px",
6
+ medium: "4px",
3
7
  large: "8px",
4
- circular: "50%",
8
+ xlarge: "10px",
9
+ none: "0px",
10
+ circular: "999px",
5
11
  },
12
+ border: {
13
+ standard: (theme: Theme) =>
14
+ `1px solid ${theme.palette.base?.filledInput.outlinedBorder}`,
15
+ divider: (theme: Theme) => `1px solid ${theme.palette.base?.divider}`,
16
+ },
17
+ padding: {
18
+ none: "0px",
19
+ xsmall: "8px",
20
+ small: "10px",
21
+ medium: "12px",
22
+ large: "14px",
23
+ xlarge: "16px",
24
+ },
25
+
26
+ margin: {
27
+ none: "0px",
28
+ xsmall: "8px",
29
+ small: "10px",
30
+ medium: "12px",
31
+ large: "16px",
32
+ xlarge: "20px",
33
+ },
34
+ height: {
35
+ large: "20px",
36
+ xlarge: "24px",
37
+ },
38
+ paddingTop: {
39
+ large: "18px",
40
+ },
41
+ paddingItem: "4px",
6
42
  };
@@ -0,0 +1,5 @@
1
+ import { Theme } from "@mui/material/styles";
2
+
3
+ export interface StyledComponentDefaultProps {
4
+ theme: Theme;
5
+ }
@@ -0,0 +1,6 @@
1
+ import { SxProps, Theme } from "@mui/material/styles";
2
+
3
+ export interface StylesExtendable {
4
+ sx?: SxProps<Theme>;
5
+ className?: string;
6
+ }
package/src/index.ts CHANGED
@@ -4,4 +4,10 @@ export { default as Typography } from "./components/Typography";
4
4
  export type { TypographyProps } from "./components/Typography";
5
5
  export { default as TextField } from "./components/TextField";
6
6
  export type { TextFieldProps, TextFieldInputProps } from "./components/TextField";
7
+ export { default as Link } from "./components/Link";
8
+ export type { LinkProps } from "./components/Link";
9
+ export { default as Divider } from "./components/Divider";
10
+ export type { DividerProps } from "./components/Divider";
11
+ export { default as Copyright } from "./components/Copyright";
12
+ export type { CopyrightProps } from "./components/Copyright";
7
13
  export * from "./components/theme";