@windstream/react-shared-components 0.0.22 → 0.0.24

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.
@@ -1,29 +1,29 @@
1
- import { CSSProperties, HTMLAttributes, ReactNode } from "react";
2
-
3
- export type ListType = "ul" | "ol";
4
- export type ListVariant = "default" | "unstyled";
5
-
6
- export type ListItem = {
7
- id: string | number;
8
- content: ReactNode;
9
- className?: string;
10
- [key: string]: any;
11
- };
12
-
13
- export interface ListProps
14
- extends Omit<HTMLAttributes<HTMLUListElement | HTMLOListElement>, "type"> {
15
- /** List type - unordered (ul) or ordered (ol) */
16
- type?: ListType;
17
- /** Array of items to render */
18
- items?: ListItem[];
19
- /** Custom className for the list */
20
- className?: string;
21
- /** Custom item renderer function */
22
- renderItem?: (item: ListItem, index: number) => ReactNode;
23
- /** Children to render instead of items */
24
- children?: ReactNode;
25
- /** Additional styling options */
26
- variant?: ListVariant;
27
- /** Custom styles */
28
- style?: CSSProperties;
29
- }
1
+ import { CSSProperties, HTMLAttributes, ReactNode } from "react";
2
+
3
+ export type ListType = "ul" | "ol";
4
+ export type ListVariant = "default" | "unstyled";
5
+
6
+ export type ListItem = {
7
+ id: string | number;
8
+ content: ReactNode;
9
+ className?: string;
10
+ [key: string]: any;
11
+ };
12
+
13
+ export interface ListProps
14
+ extends Omit<HTMLAttributes<HTMLUListElement | HTMLOListElement>, "type"> {
15
+ /** List type - unordered (ul) or ordered (ol) */
16
+ type?: ListType;
17
+ /** Array of items to render */
18
+ items?: ListItem[];
19
+ /** Custom className for the list */
20
+ className?: string;
21
+ /** Custom item renderer function */
22
+ renderItem?: (item: ListItem, index: number) => ReactNode;
23
+ /** Children to render instead of items */
24
+ children?: ReactNode;
25
+ /** Additional styling options */
26
+ variant?: ListVariant;
27
+ /** Custom styles */
28
+ style?: CSSProperties;
29
+ }
@@ -1,44 +1,44 @@
1
- import React from "react";
2
- import { cx } from "../../utils";
3
- import type { IconProps } from "./types";
4
-
5
- const MaterialIcon: React.FC<IconProps> = ({
6
- name,
7
- fill = 0,
8
- opticalSize = "48dp",
9
- weight = "200",
10
- emphasis = 145,
11
- size = 24,
12
- color = "currentColor",
13
- style = {},
14
- className,
15
- onClick,
16
- dataTestId,
17
- }) => {
18
- const fontVariationSettings = `'FILL' ${fill}, 'wght' ${weight}, 'GRAD' ${emphasis}, 'opsz' ${opticalSize.substring(0, 2)}`;
19
-
20
- const combinedStyle: React.CSSProperties = {
21
- fontVariationSettings,
22
- fontSize: `${size}px`,
23
- fontFamily: "'Material Symbols Rounded'",
24
- color: color || "currentColor",
25
- ...style,
26
- };
27
-
28
- return (
29
- <span
30
- style={combinedStyle}
31
- className={cx("material-symbols-rounded", className)}
32
- onClick={onClick}
33
- data-testid={dataTestId}
34
- >
35
- {name}
36
- </span>
37
- );
38
- };
39
-
40
- export { MaterialIcon };
41
-
42
- MaterialIcon.displayName = "MaterialIcon";
43
-
44
- export type { IconProps, IconName } from "./types";
1
+ import React from "react";
2
+ import { cx } from "../../utils";
3
+ import type { IconProps } from "./types";
4
+
5
+ const MaterialIcon: React.FC<IconProps> = ({
6
+ name,
7
+ fill = 0,
8
+ opticalSize = "48dp",
9
+ weight = "200",
10
+ emphasis = 145,
11
+ size = 24,
12
+ color = "currentColor",
13
+ style = {},
14
+ className,
15
+ onClick,
16
+ dataTestId,
17
+ }) => {
18
+ const fontVariationSettings = `'FILL' ${fill}, 'wght' ${weight}, 'GRAD' ${emphasis}, 'opsz' ${opticalSize.substring(0, 2)}`;
19
+
20
+ const combinedStyle: React.CSSProperties = {
21
+ fontVariationSettings,
22
+ fontSize: `${size}px`,
23
+ fontFamily: "'Material Symbols Rounded'",
24
+ color: color || "currentColor",
25
+ ...style,
26
+ };
27
+
28
+ return (
29
+ <span
30
+ style={combinedStyle}
31
+ className={cx("material-symbols-rounded", className)}
32
+ onClick={onClick}
33
+ data-testid={dataTestId}
34
+ >
35
+ {name}
36
+ </span>
37
+ );
38
+ };
39
+
40
+ export { MaterialIcon };
41
+
42
+ MaterialIcon.displayName = "MaterialIcon";
43
+
44
+ export type { IconProps, IconName } from "./types";
@@ -1,31 +1,31 @@
1
- import type { CSSProperties } from "react";
2
- import {
3
- emphasis,
4
- iconNameList,
5
- OpticalSizes,
6
- sizes,
7
- weights,
8
- } from "./constants";
9
-
10
- export type Fill = 1 | 0;
11
-
12
- export type IconName = (typeof iconNameList)[number];
13
-
14
- export type OpticalSize = (typeof OpticalSizes)[number];
15
- export type Weight = (typeof weights)[number];
16
- export type Emphasis = (typeof emphasis)[number];
17
- export type Size = (typeof sizes)[number];
18
-
19
- export type IconProps = {
20
- name: IconName;
21
- fill?: Fill;
22
- opticalSize?: OpticalSize;
23
- weight?: Weight;
24
- emphasis?: Emphasis;
25
- size?: Size;
26
- color?: string;
27
- style?: CSSProperties;
28
- className?: string;
29
- onClick?: () => void;
30
- dataTestId?: string;
31
- };
1
+ import type { CSSProperties } from "react";
2
+ import {
3
+ emphasis,
4
+ iconNameList,
5
+ OpticalSizes,
6
+ sizes,
7
+ weights,
8
+ } from "./constants";
9
+
10
+ export type Fill = 1 | 0;
11
+
12
+ export type IconName = (typeof iconNameList)[number];
13
+
14
+ export type OpticalSize = (typeof OpticalSizes)[number];
15
+ export type Weight = (typeof weights)[number];
16
+ export type Emphasis = (typeof emphasis)[number];
17
+ export type Size = (typeof sizes)[number];
18
+
19
+ export type IconProps = {
20
+ name: IconName;
21
+ fill?: Fill;
22
+ opticalSize?: OpticalSize;
23
+ weight?: Weight;
24
+ emphasis?: Emphasis;
25
+ size?: Size;
26
+ color?: string;
27
+ style?: CSSProperties;
28
+ className?: string;
29
+ onClick?: () => void;
30
+ dataTestId?: string;
31
+ };
@@ -1,61 +1,61 @@
1
- import { FC } from "react";
2
- import { SkeletonProps } from "./types";
3
-
4
- export const Skeleton: FC<SkeletonProps> = ({ className = "", count = 1 }) => {
5
- return (
6
- <div className="animate-pulse space-y-4">
7
- {Array.from({ length: count }).map((_, index) => (
8
- <div
9
- key={index}
10
- className={`h-8 rounded bg-skeleton-bg-start ${className}`}
11
- style={{ opacity: 1 - index * 0.1 }}
12
- />
13
- ))}
14
- </div>
15
- );
16
- };
17
-
18
- Skeleton.displayName = "Skeleton";
19
-
20
- export type { SkeletonProps };
21
-
22
- export const PageSkeleton: FC = () => {
23
- return (
24
- <div
25
- className="item-center mx-auto mt-4 flex animate-pulse flex-col justify-center gap-10 px-1 md:max-w-[48.375rem] md:gap-16 md:px-0"
26
- data-testid="generic-skeleton"
27
- >
28
- {/* Title */}
29
- <div
30
- className="h-12 w-full rounded-lg bg-skeleton-bg-start"
31
- data-testid="title"
32
- />
33
-
34
- {/* Subtitle */}
35
- <div className="item-center flex flex-col gap-6" data-testid="subtitle">
36
- <div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
37
- <div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
38
- </div>
39
-
40
- {/* Content */}
41
- <div className="item-center flex flex-col gap-3" data-testid="content">
42
- <div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
43
- <div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
44
- </div>
45
-
46
- {/* Additional Information */}
47
- <div
48
- className="item-center flex flex-col gap-6"
49
- data-testid="additional-info"
50
- >
51
- <div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
52
- <div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
53
- </div>
54
-
55
- {/* CTA button */}
56
- <div className="item-center flex justify-center" data-testid="cta-button">
57
- <div className="h-12 w-full rounded-lg bg-skeleton-bg-end md:w-[22.125rem]" />
58
- </div>
59
- </div>
60
- );
61
- };
1
+ import { FC } from "react";
2
+ import { SkeletonProps } from "./types";
3
+
4
+ export const Skeleton: FC<SkeletonProps> = ({ className = "", count = 1 }) => {
5
+ return (
6
+ <div className="animate-pulse space-y-4">
7
+ {Array.from({ length: count }).map((_, index) => (
8
+ <div
9
+ key={index}
10
+ className={`h-8 rounded bg-skeleton-bg-start ${className}`}
11
+ style={{ opacity: 1 - index * 0.1 }}
12
+ />
13
+ ))}
14
+ </div>
15
+ );
16
+ };
17
+
18
+ Skeleton.displayName = "Skeleton";
19
+
20
+ export type { SkeletonProps };
21
+
22
+ export const PageSkeleton: FC = () => {
23
+ return (
24
+ <div
25
+ className="item-center mx-auto mt-4 flex animate-pulse flex-col justify-center gap-10 px-1 md:max-w-[48.375rem] md:gap-16 md:px-0"
26
+ data-testid="generic-skeleton"
27
+ >
28
+ {/* Title */}
29
+ <div
30
+ className="h-12 w-full rounded-lg bg-skeleton-bg-start"
31
+ data-testid="title"
32
+ />
33
+
34
+ {/* Subtitle */}
35
+ <div className="item-center flex flex-col gap-6" data-testid="subtitle">
36
+ <div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
37
+ <div className="h-5 w-full rounded-lg bg-skeleton-bg-start" />
38
+ </div>
39
+
40
+ {/* Content */}
41
+ <div className="item-center flex flex-col gap-3" data-testid="content">
42
+ <div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
43
+ <div className="h-12 w-full rounded-lg bg-skeleton-bg-start" />
44
+ </div>
45
+
46
+ {/* Additional Information */}
47
+ <div
48
+ className="item-center flex flex-col gap-6"
49
+ data-testid="additional-info"
50
+ >
51
+ <div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
52
+ <div className="h-5 w-full rounded-lg bg-skeleton-bg-end" />
53
+ </div>
54
+
55
+ {/* CTA button */}
56
+ <div className="item-center flex justify-center" data-testid="cta-button">
57
+ <div className="h-12 w-full rounded-lg bg-skeleton-bg-end md:w-[22.125rem]" />
58
+ </div>
59
+ </div>
60
+ );
61
+ };
@@ -1,45 +1,45 @@
1
- import { type CSSProperties, type HTMLAttributes, type ReactNode } from "react";
2
-
3
- export type TextVariant =
4
- | "heading1"
5
- | "heading2"
6
- | "heading3"
7
- | "heading4"
8
- | "heading5"
9
- | "heading6"
10
- | "subheading1"
11
- | "subheading2"
12
- | "subheading3"
13
- | "subheading4"
14
- | "subheading5"
15
- | "subheading6"
16
- | "body1"
17
- | "body2"
18
- | "body3"
19
- | "footnote"
20
- | "micro"
21
- | "label1"
22
- | "label2"
23
- | "label3"
24
- | "label4"
25
- | "error"
26
- | "unstyled";
27
- export type TextWeight =
28
- | "thin"
29
- | "normal"
30
- | "medium"
31
- | "semibold"
32
- | "bold"
33
- | "extrabold"
34
- | "black"
35
- | undefined;
36
- export interface TextProps extends HTMLAttributes<HTMLElement> {
37
- /** Content to render inside the text element */
38
- children?: ReactNode;
39
- /** Custom HTML element to render as */
40
- as?: keyof import("react").JSX.IntrinsicElements;
41
- /** Custom className for the text */
42
- className?: string;
43
- /** Custom styles */
44
- style?: CSSProperties;
45
- }
1
+ import { type CSSProperties, type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ export type TextVariant =
4
+ | "heading1"
5
+ | "heading2"
6
+ | "heading3"
7
+ | "heading4"
8
+ | "heading5"
9
+ | "heading6"
10
+ | "subheading1"
11
+ | "subheading2"
12
+ | "subheading3"
13
+ | "subheading4"
14
+ | "subheading5"
15
+ | "subheading6"
16
+ | "body1"
17
+ | "body2"
18
+ | "body3"
19
+ | "footnote"
20
+ | "micro"
21
+ | "label1"
22
+ | "label2"
23
+ | "label3"
24
+ | "label4"
25
+ | "error"
26
+ | "unstyled";
27
+ export type TextWeight =
28
+ | "thin"
29
+ | "normal"
30
+ | "medium"
31
+ | "semibold"
32
+ | "bold"
33
+ | "extrabold"
34
+ | "black"
35
+ | undefined;
36
+ export interface TextProps extends HTMLAttributes<HTMLElement> {
37
+ /** Content to render inside the text element */
38
+ children?: ReactNode;
39
+ /** Custom HTML element to render as */
40
+ as?: keyof import("react").JSX.IntrinsicElements;
41
+ /** Custom className for the text */
42
+ className?: string;
43
+ /** Custom styles */
44
+ style?: CSSProperties;
45
+ }
@@ -16,7 +16,18 @@ const meta: Meta<typeof FloatingBanner> = {
16
16
  },
17
17
  },
18
18
  },
19
- args: { fields: {} },
19
+ args: {
20
+ title: "test",
21
+ enableHeading: false,
22
+ subtitle: "Test",
23
+ icon: "https://images.ctfassets.net/lefc0joykfg0/xt7XD2oCXK79H8pyMyMb8/18aead59bc97d624b5bd91b2f9f04352/banner_call_icon.svg",
24
+ description: <p>test</p>,
25
+ cta: null,
26
+ disclaimer: <p>test</p>,
27
+ background: "green",
28
+ color: "white",
29
+ maxWidth: true,
30
+ },
20
31
  };
21
32
  export default meta;
22
33
  type Story = StoryObj<typeof meta>;
@@ -1,11 +1,99 @@
1
- import { FloatingBannerProps } from "./types";
1
+ import React from "react";
2
+ import { FloatingBannerProps, ThemeKey } from "./types";
2
3
 
4
+ import { NextImage } from "@shared/components/next-image";
3
5
  import { Text } from "@shared/components/text";
6
+ import { Button } from "@shared/contentful/blocks/button";
4
7
 
5
- export const FloatingBanner: React.FC<{ fields: FloatingBannerProps }> = ({
6
- fields,
8
+ export const FloatingBanner: React.FC<FloatingBannerProps> = ({
9
+ title,
10
+ subtitle,
11
+ description,
12
+ disclaimer,
13
+ icon,
14
+ cta,
15
+ background = "navy",
16
+ color = "white",
17
+ enableHeading,
18
+ maxWidth = true,
7
19
  }) => {
8
- return <Text>FloatingBanner</Text>;
20
+ const textColorClasses: Record<ThemeKey, string> = {
21
+ blue: "text-[#07B2E2]",
22
+ green: "text-[#26B170]",
23
+ yellow: "text-[#F5FF1E]",
24
+ purple: "text-[#931D69]",
25
+ white: "text-white",
26
+ navy: "text-[#00002D]",
27
+ };
28
+
29
+ const bgColorClasses: Record<ThemeKey, string> = {
30
+ blue: "bg-[#07B2E2]",
31
+ green: "bg-[#26B170]",
32
+ yellow: "bg-[#F5FF1E]",
33
+ purple: "bg-[#931D69]",
34
+ white: "bg-white",
35
+ navy: "bg-[#00002D]",
36
+ };
37
+
38
+ return (
39
+ <div className="component-container">
40
+ <div
41
+ className={`mx-5 my-8 lg:mx-20 lg:my-12 lg:rounded-[40px] xl:mx-auto ${maxWidth ? "mx-auto max-w-120" : ""}`}
42
+ >
43
+ <div
44
+ className={`flex flex-col rounded-[28px] px-5 py-7 lg:flex-row lg:rounded-[40px] lg:px-16 lg:py-9 ${bgColorClasses[background]} ${textColorClasses[color]} `}
45
+ >
46
+ {icon && (
47
+ <div className="floating-banner-icon mb-5 flex justify-center lg:mb-0 lg:items-center">
48
+ <div className="h-[80px] w-[80px] overflow-hidden">
49
+ <NextImage
50
+ width={80}
51
+ height={80}
52
+ alt="icon"
53
+ src={icon}
54
+ ></NextImage>
55
+ </div>
56
+ </div>
57
+ )}
58
+ <div className="flex flex-col justify-center lg:mx-5">
59
+ {title && (
60
+ <Text
61
+ as={enableHeading ? "h1" : "h2"}
62
+ className={`heading2 mb-3 lg:w-[90%] text-center lg:text-left`}
63
+ >
64
+ {title}
65
+ </Text>
66
+ )}
67
+ {subtitle && (
68
+ <Text
69
+ as={"h3"}
70
+ className={`heading3 mb-3 text-center lg:text-left`}
71
+ >
72
+ {subtitle}
73
+ </Text>
74
+ )}
75
+ {description && (
76
+ <Text as="div" className="body1 lg:w-[90%] text-center lg:text-left">
77
+ {description}
78
+ </Text>
79
+ )}
80
+ </div>
81
+ {cta && (
82
+ <div className="mt-5 flex justify-center lg:mt-0 lg:w-[500px] lg:items-center">
83
+ <Button {...cta}></Button>
84
+ </div>
85
+ )}
86
+ </div>
87
+ {disclaimer && (
88
+ <div>
89
+ <Text as="div" className="body3 mt-3 text-center">
90
+ {disclaimer}
91
+ </Text>
92
+ </div>
93
+ )}
94
+ </div>
95
+ </div>
96
+ );
9
97
  };
10
98
 
11
99
  export default FloatingBanner;
@@ -1 +1,22 @@
1
- export type FloatingBannerProps = {};
1
+ import React from "react";
2
+
3
+ export type FloatingBannerProps = {
4
+ title?: string;
5
+ enableHeading?: boolean;
6
+ subtitle?: string;
7
+ icon?: string;
8
+ description?: React.ReactNode;
9
+ cta?: any | null;
10
+ disclaimer?: React.ReactNode;
11
+ background?: "green" | "navy" | "white";
12
+ color?: "navy" | "white";
13
+ maxWidth?: boolean;
14
+ };
15
+
16
+ export type ThemeKey =
17
+ | "blue"
18
+ | "green"
19
+ | "yellow"
20
+ | "purple"
21
+ | "white"
22
+ | "navy";
package/src/setupTests.ts CHANGED
@@ -1,46 +1,46 @@
1
- import "@testing-library/jest-dom";
2
-
3
- // Mock window.matchMedia
4
- Object.defineProperty(window, "matchMedia", {
5
- writable: true,
6
- value: (query: string) => ({
7
- matches: false,
8
- media: query,
9
- onchange: null,
10
- addListener: () => {}, // deprecated
11
- removeListener: () => {}, // deprecated
12
- addEventListener: () => {},
13
- removeEventListener: () => {},
14
- dispatchEvent: () => true,
15
- }),
16
- });
17
-
18
- // Mock ResizeObserver
19
- global.ResizeObserver = class ResizeObserver {
20
- observe = () => {};
21
- unobserve = () => {};
22
- disconnect = () => {};
23
- constructor(_callback: ResizeObserverCallback) {}
24
- } as unknown as typeof ResizeObserver;
25
-
26
- // Mock IntersectionObserver
27
- global.IntersectionObserver = class IntersectionObserver {
28
- observe = () => {};
29
- unobserve = () => {};
30
- disconnect = () => {};
31
- constructor(_callback: IntersectionObserverCallback) {}
32
- } as unknown as typeof IntersectionObserver;
33
-
34
- // Mock scrollTo
35
- Object.defineProperty(window, "scrollTo", {
36
- writable: true,
37
- value: () => {},
38
- });
39
-
40
- // Mock getComputedStyle
41
- Object.defineProperty(window, "getComputedStyle", {
42
- writable: true,
43
- value: () => ({
44
- getPropertyValue: () => "",
45
- }),
46
- });
1
+ import "@testing-library/jest-dom";
2
+
3
+ // Mock window.matchMedia
4
+ Object.defineProperty(window, "matchMedia", {
5
+ writable: true,
6
+ value: (query: string) => ({
7
+ matches: false,
8
+ media: query,
9
+ onchange: null,
10
+ addListener: () => {}, // deprecated
11
+ removeListener: () => {}, // deprecated
12
+ addEventListener: () => {},
13
+ removeEventListener: () => {},
14
+ dispatchEvent: () => true,
15
+ }),
16
+ });
17
+
18
+ // Mock ResizeObserver
19
+ global.ResizeObserver = class ResizeObserver {
20
+ observe = () => {};
21
+ unobserve = () => {};
22
+ disconnect = () => {};
23
+ constructor(_callback: ResizeObserverCallback) {}
24
+ } as unknown as typeof ResizeObserver;
25
+
26
+ // Mock IntersectionObserver
27
+ global.IntersectionObserver = class IntersectionObserver {
28
+ observe = () => {};
29
+ unobserve = () => {};
30
+ disconnect = () => {};
31
+ constructor(_callback: IntersectionObserverCallback) {}
32
+ } as unknown as typeof IntersectionObserver;
33
+
34
+ // Mock scrollTo
35
+ Object.defineProperty(window, "scrollTo", {
36
+ writable: true,
37
+ value: () => {},
38
+ });
39
+
40
+ // Mock getComputedStyle
41
+ Object.defineProperty(window, "getComputedStyle", {
42
+ writable: true,
43
+ value: () => ({
44
+ getPropertyValue: () => "",
45
+ }),
46
+ });