@coopdigital/react 0.6.0 → 0.6.1

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
@@ -7,7 +7,7 @@
7
7
  # Experience Kit for React
8
8
 
9
9
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
10
- [all_contributors_badge]: https://img.shields.io/badge/all_contributors-16-C08A00.svg ''
10
+ [all_contributors_badge]: https://img.shields.io/badge/all_contributors-17-C08A00.svg ''
11
11
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
12
12
 
13
13
  <a href="https://www.npmjs.com/package/@coopdigital/react"><img src="https://img.shields.io/npm/v/%40coopdigital%2Freact?color=E85A00" alt="npm version" /></a>
@@ -113,19 +113,24 @@ Thanks goes to these wonderful people:
113
113
  <div><img src="https://secure.gravatar.com/avatar/faf90b70d749cf9460eb603fa1700add94fd7d3a32645b4be6fa12eb45c4ffa3?s=80&d=identicon" width="200px;" alt=""/></div>
114
114
  <small>Omid Kashan</small>
115
115
  <div><a href="#a11y-omid.kashan" title="Accessibility">️️️️♿️</a> <a href="#code-omid.kashan" title="Code">💻</a> <a href="#doc-omid.kashan" title="Documentation">📖</a> <a href="#test-omid.kashan" title="Tests">⚠️</a></div>
116
+ </a></td>
117
+ <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/phil.wolstenholme">
118
+ <div><img src="https://gitlab.com/uploads/-/system/user/avatar/25900363/avatar.png" width="200px;" alt=""/></div>
119
+ <small>Phil Wolstenholme</small>
120
+ <div><a href="#a11y-phil.wolstenholme" title="Accessibility">️️️️♿️</a></div>
116
121
  </a></td>
117
122
  <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/romain.chen">
118
123
  <div><img src="https://s3.eu-west-1.amazonaws.com/assets.digital.coop.co.uk/oneweb/blank.jpg" width="200px;" alt=""/></div>
119
124
  <small>Romain Chen</small>
120
125
  <div><a href="#design-romain.chen" title="Design">🎨</a></div>
121
126
  </a></td>
127
+ </tr><br />
128
+ <tr>
122
129
  <td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/sam.harden">
123
130
  <div><img src="https://ca.slack-edge.com/T0C9E3ZF0-U03NT7D39L6-2fc82e7f7c6e-150" width="200px;" alt=""/></div>
124
131
  <small>Sam Harden</small>
125
132
  <div><a href="#a11y-sam.harden" title="Accessibility">️️️️♿️</a> <a href="#code-sam.harden" title="Code">💻</a> <a href="#doc-sam.harden" title="Documentation">📖</a> <a href="#test-sam.harden" title="Tests">⚠️</a></div>
126
133
  </a></td>
127
- </tr><br />
128
- <tr>
129
134
  <td align="center" valign="top" width="14.28%"><a href="">
130
135
  <div><img src="https://s3.eu-west-1.amazonaws.com/assets.digital.coop.co.uk/oneweb/blank.jpg" width="200px;" alt=""/></div>
131
136
  <small>Shweta Jaju</small>
@@ -1,4 +1,4 @@
1
- import type { ReactNode, JSX } from "react";
1
+ import type { JSX, ReactNode } from "react";
2
2
  export interface AlertBannerProps {
3
3
  /** **(Optional)** Specifies a custom aria-label. */
4
4
  ariaLabel?: string;
@@ -16,7 +16,7 @@ const AlertBanner = ({ ariaLabel, children, className = "", title, variant = "de
16
16
  className: `coop-alert-banner ${className}`,
17
17
  "data-variant": variant,
18
18
  };
19
- return (jsx("aside", Object.assign({}, componentProps, { children: jsxs("div", { className: "coop-alert-banner--inner", children: [jsx("h3", { id: "coop-alert-banner--headline", children: title }), children] }) })));
19
+ return (jsx("aside", Object.assign({}, componentProps, { children: jsxs("div", { className: "coop-alert-banner--inner", children: [jsx("h2", { id: "coop-alert-banner--headline", children: title }), children] }) })));
20
20
  };
21
21
 
22
22
  export { AlertBanner, AlertBanner as default };
@@ -1,21 +1,23 @@
1
- import { ImageProps } from "../Image";
2
1
  import type { AnchorHTMLAttributes, ForwardRefExoticComponent, JSX } from "react";
3
2
  import React from "react";
3
+ import { ImageProps } from "../Image";
4
4
  export interface EditorialCardProps {
5
- /** Specifies the custom element to override default `a` or `span` */
5
+ /** **(Optional)** Specifies the custom element to override default `a` */
6
6
  as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string;
7
- /** **(Optional)** Represents the content inside the Pill component. It can be any valid JSX or string. */
7
+ /** **(Optional)** Represents the content inside the EditorialCard component. It can be any valid JSX or string. */
8
8
  children?: React.ReactNode;
9
- /** Specifies the URL that the EditorialCard component will link to when clicked. */
9
+ /** **(Optional)** Specifies the heading level of the card's title. */
10
+ headingLevel?: "h2" | "h3" | "h4" | "h5" | "h6";
11
+ /** **(Optional)** Specifies the URL that the EditorialCard component will link to when clicked. */
10
12
  href?: string;
11
- /** Specifies the image URL and alt text of the editorial card */
13
+ /** Specifies the image URL and alt text of the EditorialCard */
12
14
  image: ImageProps;
13
- /** Specifies the label of the editorial card */
15
+ /** **(Optional)** Specifies the label of the EditorialCard */
14
16
  label?: string;
15
- /** Specifies the layout of the editorial card */
16
- layout?: string;
17
- /** Specifies the title of the editorial card */
17
+ /** **(Optional)** Specifies the layout of the EditorialCard */
18
+ layout?: "vertical" | "horizontal";
19
+ /** Specifies the title of the EditorialCard */
18
20
  title: string;
19
21
  }
20
- export declare const EditorialCard: ({ as, children, href, label, layout, image, title, }: EditorialCardProps) => JSX.Element;
22
+ export declare const EditorialCard: ({ as, children, headingLevel, href, image, label, layout, title, }: EditorialCardProps) => JSX.Element;
21
23
  export default EditorialCard;
@@ -1,8 +1,8 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { Image } from '../Image/Image.js';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
2
  import React from 'react';
3
+ import { Image } from '../Image/Image.js';
4
4
 
5
- function getCardContainer(as, href) {
5
+ function getCardLinkElement(as, href) {
6
6
  let element = href ? "a" : "div";
7
7
  if (as) {
8
8
  element = as;
@@ -11,19 +11,17 @@ function getCardContainer(as, href) {
11
11
  element,
12
12
  props: {
13
13
  href,
14
- className: "coop-editorial-card--inner",
15
14
  },
16
15
  };
17
16
  }
18
- const EditorialCard = ({ as, children, href, label = "", layout, image, title, }) => {
19
- const container = getCardContainer(as, href);
17
+ const EditorialCard = ({ as, children, headingLevel = "h3", href, image, label = "", layout = "vertical", title, }) => {
18
+ const linkElement = getCardLinkElement(as, href);
20
19
  const imageProps = Object.assign({ crop: "wide" }, image);
21
20
  const componentProps = {
22
21
  className: "coop-editorial-card",
23
22
  "data-layout": layout,
24
23
  };
25
- const cardInner = (jsxs(Fragment, { children: [jsx(Image, Object.assign({}, imageProps)), jsxs("div", { className: "coop-editorial-card--content", children: [label && jsx("span", { children: label }), jsx("h3", { children: title }), children] })] }));
26
- return (jsx("article", Object.assign({}, componentProps, { children: React.createElement(container.element, container.props, cardInner) })));
24
+ return (jsxs("article", Object.assign({}, componentProps, { children: [jsx(Image, Object.assign({}, imageProps)), jsxs("div", { className: "coop-editorial-card--content", children: [label && jsx("span", { children: label }), React.createElement(linkElement.element, linkElement.props, React.createElement(headingLevel, {}, title)), children] })] })));
27
25
  };
28
26
 
29
27
  export { EditorialCard, EditorialCard as default };
@@ -1,15 +1,15 @@
1
1
  import type { JSX } from "react";
2
2
  export interface ImageProps {
3
- /** Specifies text that can replace the image in the page */
3
+ /** Specifies text that can replace the Image in the page */
4
4
  alt: string;
5
- /** Specifies the image URL */
5
+ /** **(Optional)** Specifies the Image crop mode */
6
+ crop?: "square" | "wide" | "none";
7
+ /** **(Optional)** Specifies height of the Image */
8
+ height?: string;
9
+ /** Specifies the Image URL */
6
10
  src: string;
7
- /** Specifies width of the image */
11
+ /** **(Optional)** Specifies width of the Image */
8
12
  width?: string;
9
- /** Specifies height of the image */
10
- height?: string;
11
- /** Specifies the image crop mode */
12
- crop?: "square" | "wide" | "none";
13
13
  }
14
- export declare const Image: ({ src, alt, width, height, crop }: ImageProps) => JSX.Element;
14
+ export declare const Image: ({ alt, crop, height, src, width }: ImageProps) => JSX.Element;
15
15
  export default Image;
@@ -15,22 +15,22 @@ const getContentfulParams = (src, width, height) => {
15
15
  (_a = url.searchParams.get(k)) !== null && _a !== void 0 ? _a : url.searchParams.set(k, v);
16
16
  });
17
17
  return {
18
+ height: (_a = url.searchParams.get("h")) !== null && _a !== void 0 ? _a : height,
18
19
  src: url.toString(),
19
- width: (_a = url.searchParams.get("w")) !== null && _a !== void 0 ? _a : width,
20
- height: (_b = url.searchParams.get("h")) !== null && _b !== void 0 ? _b : height,
20
+ width: (_b = url.searchParams.get("w")) !== null && _b !== void 0 ? _b : width,
21
21
  };
22
22
  };
23
- const Image = ({ src, alt, width = "640", height, crop }) => {
24
- let params = { src, width, height };
23
+ const Image = ({ alt, crop, height, src, width = "640" }) => {
24
+ let params = { height, src, width };
25
25
  if (src.includes("images.ctfassets.net")) {
26
26
  params = getContentfulParams(src, width, height);
27
27
  }
28
28
  const dimensions = {
29
- width: params.width,
30
- height: params.height,
31
29
  "data-crop": crop,
30
+ height: params.height,
31
+ width: params.width,
32
32
  };
33
- return (jsx("picture", { children: jsx("img", Object.assign({ loading: "lazy", alt: alt, src: params.src }, dimensions)) }));
33
+ return (jsx("picture", { children: jsx("img", Object.assign({ alt: alt, loading: "lazy", src: params.src }, dimensions)) }));
34
34
  };
35
35
 
36
36
  export { Image, Image as default };
@@ -1,10 +1,10 @@
1
1
  import type { AnchorHTMLAttributes, ForwardRefExoticComponent, JSX } from "react";
2
2
  import React from "react";
3
3
  export interface PillProps {
4
- /** **(Optional)** Specifies the custom element to override default `a` or `span`. */
5
- as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string;
6
4
  /** **(Optional)** Specifies a custom aria-label. */
7
5
  ariaLabel?: string;
6
+ /** **(Optional)** Specifies the custom element to override default `a` or `span`. */
7
+ as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string;
8
8
  /** **(Optional)** Specifies what text Pill should display on the badge. */
9
9
  badge?: string;
10
10
  /** **(Optional)** Specifies the badge background color from the available options. */
@@ -20,12 +20,12 @@ const defaultLinks = [{ href: "#main", title: "Skip to main content" }];
20
20
  */
21
21
  const SkipNav = ({ ariaLabel = "", className = "", isVisible = false, links = defaultLinks, }) => {
22
22
  const navLinks = links.length > 0 ? links : defaultLinks;
23
- return (jsx("nav", { className: "coop-skip-nav", "aria-label": ariaLabel, children: jsx("ul", { children: navLinks.map((link) => {
23
+ return (jsx("nav", { "aria-label": ariaLabel, className: "coop-skip-nav", children: jsx("ul", { children: navLinks.map((link) => {
24
24
  const linkProps = {
25
- href: link.href,
26
- title: link.title,
27
25
  className: `${className}`,
28
26
  "data-visible": isVisible,
27
+ href: link.href,
28
+ title: link.title,
29
29
  };
30
30
  return (jsx("li", { children: jsx("a", Object.assign({}, linkProps, { children: link.title })) }, link.href));
31
31
  }) }) }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coopdigital/react",
3
3
  "type": "module",
4
- "version": "0.6.0",
4
+ "version": "0.6.1",
5
5
  "main": "dist/index.js",
6
6
  "private": false,
7
7
  "publishConfig": {
@@ -39,7 +39,7 @@
39
39
  "description": "",
40
40
  "devDependencies": {
41
41
  "@axe-core/playwright": "^4.10.1",
42
- "@coopdigital/styles": "^0.5.7",
42
+ "@coopdigital/styles": "^0.5.8",
43
43
  "@playwright/test": "^1.51.1",
44
44
  "@rollup/plugin-node-resolve": "^16.0.1",
45
45
  "@rollup/plugin-typescript": "^12.1.2",
@@ -65,5 +65,5 @@
65
65
  "react": "^19.0.0",
66
66
  "react-dom": "^19.0.0"
67
67
  },
68
- "gitHead": "618022f347d8099ec9aed4413057ed91cce96778"
68
+ "gitHead": "60cbbc73c648be7d728d36a700bcf2761579548f"
69
69
  }
@@ -1,4 +1,4 @@
1
- import type { ReactNode, JSX } from "react"
1
+ import type { JSX, ReactNode } from "react"
2
2
 
3
3
  export interface AlertBannerProps {
4
4
  /** **(Optional)** Specifies a custom aria-label. */
@@ -38,7 +38,7 @@ export const AlertBanner = ({
38
38
  return (
39
39
  <aside {...componentProps}>
40
40
  <div className="coop-alert-banner--inner">
41
- <h3 id="coop-alert-banner--headline">{title}</h3>
41
+ <h2 id="coop-alert-banner--headline">{title}</h2>
42
42
  {children}
43
43
  </div>
44
44
  </aside>
@@ -1,26 +1,30 @@
1
- import { Image, ImageProps } from "../Image"
2
1
  import type { AnchorHTMLAttributes, ForwardRefExoticComponent, JSX } from "react"
2
+
3
3
  import React from "react"
4
4
 
5
+ import { Image, ImageProps } from "../Image"
6
+
5
7
  export interface EditorialCardProps {
6
- /** Specifies the custom element to override default `a` or `span` */
8
+ /** **(Optional)** Specifies the custom element to override default `a` */
7
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
10
  as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string
9
- /** **(Optional)** Represents the content inside the Pill component. It can be any valid JSX or string. */
11
+ /** **(Optional)** Represents the content inside the EditorialCard component. It can be any valid JSX or string. */
10
12
  children?: React.ReactNode
11
- /** Specifies the URL that the EditorialCard component will link to when clicked. */
13
+ /** **(Optional)** Specifies the heading level of the card's title. */
14
+ headingLevel?: "h2" | "h3" | "h4" | "h5" | "h6"
15
+ /** **(Optional)** Specifies the URL that the EditorialCard component will link to when clicked. */
12
16
  href?: string
13
- /** Specifies the image URL and alt text of the editorial card */
17
+ /** Specifies the image URL and alt text of the EditorialCard */
14
18
  image: ImageProps
15
- /** Specifies the label of the editorial card */
19
+ /** **(Optional)** Specifies the label of the EditorialCard */
16
20
  label?: string
17
- /** Specifies the layout of the editorial card */
18
- layout?: string
19
- /** Specifies the title of the editorial card */
21
+ /** **(Optional)** Specifies the layout of the EditorialCard */
22
+ layout?: "vertical" | "horizontal"
23
+ /** Specifies the title of the EditorialCard */
20
24
  title: string
21
25
  }
22
26
 
23
- function getCardContainer(as: EditorialCardProps["as"], href?: string) {
27
+ function getCardLinkElement(as: EditorialCardProps["as"], href?: string) {
24
28
  let element: EditorialCardProps["as"] = href ? "a" : "div"
25
29
 
26
30
  if (as) {
@@ -31,7 +35,6 @@ function getCardContainer(as: EditorialCardProps["as"], href?: string) {
31
35
  element,
32
36
  props: {
33
37
  href,
34
- className: "coop-editorial-card--inner",
35
38
  },
36
39
  }
37
40
  }
@@ -39,13 +42,14 @@ function getCardContainer(as: EditorialCardProps["as"], href?: string) {
39
42
  export const EditorialCard = ({
40
43
  as,
41
44
  children,
45
+ headingLevel = "h3",
42
46
  href,
43
- label = "",
44
- layout,
45
47
  image,
48
+ label = "",
49
+ layout = "vertical",
46
50
  title,
47
51
  }: EditorialCardProps): JSX.Element => {
48
- const container = getCardContainer(as, href)
52
+ const linkElement = getCardLinkElement(as, href)
49
53
 
50
54
  const imageProps: ImageProps = {
51
55
  crop: "wide",
@@ -57,20 +61,18 @@ export const EditorialCard = ({
57
61
  "data-layout": layout,
58
62
  }
59
63
 
60
- const cardInner = (
61
- <>
64
+ return (
65
+ <article {...componentProps}>
62
66
  <Image {...imageProps} />
63
67
  <div className="coop-editorial-card--content">
64
68
  {label && <span>{label}</span>}
65
- <h3>{title}</h3>
69
+ {React.createElement(
70
+ linkElement.element,
71
+ linkElement.props,
72
+ React.createElement(headingLevel, {}, title)
73
+ )}
66
74
  {children}
67
75
  </div>
68
- </>
69
- )
70
-
71
- return (
72
- <article {...componentProps}>
73
- {React.createElement(container.element, container.props, cardInner)}
74
76
  </article>
75
77
  )
76
78
  }
@@ -1,16 +1,16 @@
1
1
  import type { JSX } from "react"
2
2
 
3
3
  export interface ImageProps {
4
- /** Specifies text that can replace the image in the page */
4
+ /** Specifies text that can replace the Image in the page */
5
5
  alt: string
6
- /** Specifies the image URL */
6
+ /** **(Optional)** Specifies the Image crop mode */
7
+ crop?: "square" | "wide" | "none"
8
+ /** **(Optional)** Specifies height of the Image */
9
+ height?: string
10
+ /** Specifies the Image URL */
7
11
  src: string
8
- /** Specifies width of the image */
12
+ /** **(Optional)** Specifies width of the Image */
9
13
  width?: string
10
- /** Specifies height of the image */
11
- height?: string
12
- /** Specifies the image crop mode */
13
- crop?: "square" | "wide" | "none"
14
14
  }
15
15
 
16
16
  const getContentfulParams = (src: string, width: string, height: string | undefined) => {
@@ -28,28 +28,28 @@ const getContentfulParams = (src: string, width: string, height: string | undefi
28
28
  })
29
29
 
30
30
  return {
31
+ height: url.searchParams.get("h") ?? height,
31
32
  src: url.toString(),
32
33
  width: url.searchParams.get("w") ?? width,
33
- height: url.searchParams.get("h") ?? height,
34
34
  }
35
35
  }
36
36
 
37
- export const Image = ({ src, alt, width = "640", height, crop }: ImageProps): JSX.Element => {
38
- let params = { src, width, height }
37
+ export const Image = ({ alt, crop, height, src, width = "640" }: ImageProps): JSX.Element => {
38
+ let params = { height, src, width }
39
39
 
40
40
  if (src.includes("images.ctfassets.net")) {
41
41
  params = getContentfulParams(src, width, height)
42
42
  }
43
43
 
44
44
  const dimensions = {
45
- width: params.width,
46
- height: params.height,
47
45
  "data-crop": crop,
46
+ height: params.height,
47
+ width: params.width,
48
48
  }
49
49
 
50
50
  return (
51
51
  <picture>
52
- <img loading="lazy" alt={alt} src={params.src} {...dimensions} />
52
+ <img alt={alt} loading="lazy" src={params.src} {...dimensions} />
53
53
  </picture>
54
54
  )
55
55
  }
@@ -1,12 +1,13 @@
1
1
  import type { AnchorHTMLAttributes, ForwardRefExoticComponent, JSX } from "react"
2
+
2
3
  import React from "react"
3
4
 
4
5
  export interface PillProps {
6
+ /** **(Optional)** Specifies a custom aria-label. */
7
+ ariaLabel?: string
5
8
  /** **(Optional)** Specifies the custom element to override default `a` or `span`. */
6
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
10
  as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string
8
- /** **(Optional)** Specifies a custom aria-label. */
9
- ariaLabel?: string
10
11
  /** **(Optional)** Specifies what text Pill should display on the badge. */
11
12
  badge?: string
12
13
  /** **(Optional)** Specifies the badge background color from the available options. */
@@ -46,14 +46,14 @@ export const SkipNav = ({
46
46
  }: SkipNavProps): JSX.Element => {
47
47
  const navLinks = links.length > 0 ? links : defaultLinks
48
48
  return (
49
- <nav className="coop-skip-nav" aria-label={ariaLabel}>
49
+ <nav aria-label={ariaLabel} className="coop-skip-nav">
50
50
  <ul>
51
51
  {navLinks.map((link) => {
52
52
  const linkProps = {
53
- href: link.href,
54
- title: link.title,
55
53
  className: `${className}`,
56
54
  "data-visible": isVisible,
55
+ href: link.href,
56
+ title: link.title,
57
57
  }
58
58
  return (
59
59
  <li key={link.href}>