@coopdigital/react 1.4.0 → 1.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.
Files changed (96) hide show
  1. package/dist/components/AlertBanner/AlertBanner.d.ts +12 -2
  2. package/dist/components/AlertBanner/AlertBanner.js +3 -2
  3. package/dist/components/Author/Author.d.ts +7 -1
  4. package/dist/components/Author/Author.js +1 -0
  5. package/dist/components/Button/Button.d.ts +7 -1
  6. package/dist/components/Button/Button.js +1 -0
  7. package/dist/components/Card/Card.d.ts +40 -6
  8. package/dist/components/Card/Card.js +7 -6
  9. package/dist/components/Checkbox/Checkbox.d.ts +6 -4
  10. package/dist/components/Checkbox/Checkbox.js +9 -6
  11. package/dist/components/DatePicker/DatePicker.d.ts +8 -3
  12. package/dist/components/DatePicker/DatePicker.js +11 -11
  13. package/dist/components/Expandable/Expandable.d.ts +19 -3
  14. package/dist/components/Expandable/Expandable.js +4 -3
  15. package/dist/components/Field/Field.context.d.ts +14 -0
  16. package/dist/components/Field/Field.context.js +14 -0
  17. package/dist/components/Field/Field.d.ts +26 -4
  18. package/dist/components/Field/Field.js +33 -34
  19. package/dist/components/Field/index.js +1 -0
  20. package/dist/components/FieldMarkers/Label.js +4 -0
  21. package/dist/components/Fieldset/Fieldset.d.ts +33 -5
  22. package/dist/components/Fieldset/Fieldset.js +6 -5
  23. package/dist/components/Flourish/Flourish.d.ts +7 -1
  24. package/dist/components/Flourish/Flourish.js +1 -0
  25. package/dist/components/Form/Form.d.ts +7 -1
  26. package/dist/components/Form/Form.js +1 -0
  27. package/dist/components/Image/Image.d.ts +7 -1
  28. package/dist/components/Image/Image.js +1 -0
  29. package/dist/components/Pill/Pill.d.ts +12 -2
  30. package/dist/components/Pill/Pill.js +3 -2
  31. package/dist/components/Popover/Popover.d.ts +33 -5
  32. package/dist/components/Popover/Popover.js +6 -5
  33. package/dist/components/Popover/index.js +1 -0
  34. package/dist/components/Radio/Radio.d.ts +6 -4
  35. package/dist/components/Radio/Radio.js +9 -6
  36. package/dist/components/RootSVG/RootSVG.d.ts +7 -1
  37. package/dist/components/RootSVG/RootSVG.js +1 -0
  38. package/dist/components/Searchbox/Searchbox.context.d.ts +13 -0
  39. package/dist/components/Searchbox/Searchbox.context.js +11 -0
  40. package/dist/components/Searchbox/Searchbox.d.ts +15 -11
  41. package/dist/components/Searchbox/Searchbox.js +25 -28
  42. package/dist/components/Select/Select.d.ts +18 -5
  43. package/dist/components/Select/Select.js +9 -9
  44. package/dist/components/Signpost/Signpost.d.ts +7 -1
  45. package/dist/components/Signpost/Signpost.js +1 -0
  46. package/dist/components/SkipNav/SkipNav.d.ts +7 -1
  47. package/dist/components/SkipNav/SkipNav.js +1 -0
  48. package/dist/components/Squircle/Squircle.d.ts +7 -1
  49. package/dist/components/Squircle/Squircle.js +1 -0
  50. package/dist/components/Tag/Tag.d.ts +7 -1
  51. package/dist/components/Tag/Tag.js +1 -0
  52. package/dist/components/TextInput/TextInput.d.ts +4 -3
  53. package/dist/components/TextInput/TextInput.js +6 -6
  54. package/dist/components/Textarea/Textarea.d.ts +4 -3
  55. package/dist/components/Textarea/Textarea.js +4 -6
  56. package/dist/components/ValidationSummary/ValidationSummary.d.ts +26 -4
  57. package/dist/components/ValidationSummary/ValidationSummary.js +8 -6
  58. package/dist/hooks/useSlots.d.ts +4 -2
  59. package/dist/hooks/useSlots.js +33 -7
  60. package/dist/index.js +10 -10
  61. package/dist/types/index.d.ts +14 -14
  62. package/dist/utils/index.d.ts +1 -0
  63. package/dist/utils/index.js +9 -7
  64. package/package.json +9 -8
  65. package/src/components/AlertBanner/AlertBanner.tsx +5 -2
  66. package/src/components/Author/Author.tsx +4 -1
  67. package/src/components/Button/Button.tsx +5 -1
  68. package/src/components/Card/Card.tsx +8 -6
  69. package/src/components/Checkbox/Checkbox.tsx +13 -9
  70. package/src/components/DatePicker/DatePicker.tsx +15 -15
  71. package/src/components/Expandable/Expandable.tsx +5 -8
  72. package/src/components/Field/Field.context.ts +29 -0
  73. package/src/components/Field/Field.tsx +61 -56
  74. package/src/components/FieldMarkers/Label.tsx +4 -0
  75. package/src/components/Fieldset/Fieldset.tsx +7 -5
  76. package/src/components/Flourish/Flourish.tsx +4 -1
  77. package/src/components/Form/Form.tsx +4 -1
  78. package/src/components/Image/Image.tsx +4 -1
  79. package/src/components/Pill/Pill.tsx +4 -2
  80. package/src/components/Popover/Popover.tsx +7 -5
  81. package/src/components/Radio/Radio.tsx +12 -9
  82. package/src/components/RootSVG/RootSVG.tsx +4 -1
  83. package/src/components/Searchbox/Searchbox.context.tsx +20 -0
  84. package/src/components/Searchbox/Searchbox.tsx +55 -44
  85. package/src/components/Select/Select.tsx +11 -11
  86. package/src/components/Signpost/Signpost.tsx +4 -1
  87. package/src/components/SkipNav/SkipNav.tsx +4 -1
  88. package/src/components/Squircle/Squircle.tsx +4 -1
  89. package/src/components/Tag/Tag.tsx +4 -1
  90. package/src/components/TextInput/TextInput.tsx +8 -8
  91. package/src/components/Textarea/Textarea.tsx +7 -8
  92. package/src/components/ValidationSummary/ValidationSummary.tsx +12 -5
  93. package/src/hooks/useSlots.ts +37 -9
  94. package/src/types/index.ts +18 -14
  95. package/src/utils/index.ts +8 -6
  96. package/dist/node_modules/merge-refs/dist/index.js +0 -36
@@ -9,5 +9,11 @@ export interface SquircleProps extends HTMLAttributes<HTMLDivElement> {
9
9
  /** **(Optional)** Specify the Squircle size. */
10
10
  size?: "sm" | "md" | "lg";
11
11
  }
12
- export declare const Squircle: ({ children, className, ref, size, ...props }: SquircleProps) => JSX.Element;
12
+ declare const Squircle: {
13
+ ({ children, className, ref, size, ...props }: SquircleProps): JSX.Element;
14
+ slot: {
15
+ name: string;
16
+ };
17
+ };
13
18
  export default Squircle;
19
+ export { Squircle };
@@ -10,5 +10,6 @@ const Squircle = ({ children, className, ref, size = "md", ...props }) => {
10
10
  };
11
11
  return (jsx("figure", { ...componentProps, ref: ref, children: jsx("figcaption", { children: children }) }));
12
12
  };
13
+ Squircle.slot = { name: "Squircle" };
13
14
 
14
15
  export { Squircle, Squircle as default };
@@ -14,5 +14,11 @@ export interface TagProps extends HTMLAttributes<HTMLAnchorElement> {
14
14
  /** **(Optional)** Specify the Tag size. */
15
15
  size?: "sm" | "md";
16
16
  }
17
- export declare const Tag: ({ as, children, className, href, ref, size, ...props }: TagProps) => JSX.Element;
17
+ declare const Tag: {
18
+ ({ as, children, className, href, ref, size, ...props }: TagProps): JSX.Element;
19
+ slot: {
20
+ name: string;
21
+ };
22
+ };
18
23
  export default Tag;
24
+ export { Tag };
@@ -12,5 +12,6 @@ const Tag = ({ as, children, className, href, ref, size = "md", ...props }) => {
12
12
  };
13
13
  return React.createElement(element, { ...componentProps, ref }, children);
14
14
  };
15
+ Tag.slot = { name: "Tag" };
15
16
 
16
17
  export { Tag, Tag as default };
@@ -28,10 +28,11 @@ export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElemen
28
28
  /** **(Optional)** Specify the TextInput type. */
29
29
  type?: "text" | "email" | "number" | "password" | "search" | "tel" | "url" | "date" | "datetime-local" | "week" | "month" | "time";
30
30
  }
31
- export declare const TextInput: {
31
+ declare const TextInput: {
32
32
  ({ "aria-placeholder": ariaPlaceholder, className, disabled, error, id, name, placeholder, prefix, prefixInline, ref, size, suffix, suffixInline, type, ...props }: TextInputProps): JSX.Element;
33
- config: {
34
- isField: true;
33
+ slot: {
34
+ name: string;
35
35
  };
36
36
  };
37
37
  export default TextInput;
38
+ export { TextInput };
@@ -1,17 +1,19 @@
1
+
2
+ "use client";
1
3
  import { jsxs, jsx } from 'react/jsx-runtime';
2
4
  import clsx from 'clsx';
3
- import { useId } from '../../hooks/useId.js';
5
+ import { useField } from '../Field/Field.context.js';
4
6
 
5
7
  const TextInput = ({ "aria-placeholder": ariaPlaceholder, className, disabled, error = false, id, name, placeholder, prefix, prefixInline = false, ref, size, suffix, suffixInline = false, type = "text", ...props }) => {
6
8
  var _a;
7
- const uid = useId(id);
9
+ const field = useField();
8
10
  const componentProps = {
9
11
  "aria-placeholder": (_a = placeholder !== null && placeholder !== void 0 ? placeholder : ariaPlaceholder) !== null && _a !== void 0 ? _a : undefined,
10
12
  className: clsx("coop-text-input", "coop-field-element", className),
11
13
  "data-error": error || undefined,
12
14
  "data-size": (size === null || size === void 0 ? void 0 : size.length) ? size : undefined,
13
15
  disabled,
14
- id: uid,
16
+ id: id !== null && id !== void 0 ? id : field === null || field === void 0 ? void 0 : field.id,
15
17
  name,
16
18
  placeholder,
17
19
  type,
@@ -26,8 +28,6 @@ const TextInput = ({ "aria-placeholder": ariaPlaceholder, className, disabled, e
26
28
  //const formItemProps = { "aria-disabled": disabled ? true : undefined }
27
29
  return (jsxs("div", { className: "coop-text-input-wrapper", children: [prefix && jsx("span", { ...prefixProps, children: prefix }), jsx("input", { ...componentProps, ref: ref }), suffix && jsx("span", { ...suffixProps, children: suffix })] }));
28
30
  };
29
- TextInput.config = {
30
- isField: true,
31
- };
31
+ TextInput.slot = { name: "TextInput" };
32
32
 
33
33
  export { TextInput, TextInput as default };
@@ -31,10 +31,11 @@ export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElemen
31
31
  /** **(Optional)** Specify the Textarea size. */
32
32
  size?: StandardSizes;
33
33
  }
34
- export declare const Textarea: {
34
+ declare const Textarea: {
35
35
  ({ "aria-placeholder": ariaPlaceholder, className, cols, counter, cutoff, disabled, error, id, maxLength, name, onChange: userOnChange, placeholder, ref, rows, size, ...props }: TextareaProps): JSX.Element;
36
- config: {
37
- isField: true;
36
+ slot: {
37
+ name: string;
38
38
  };
39
39
  };
40
40
  export default Textarea;
41
+ export { Textarea };
@@ -4,7 +4,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import clsx from 'clsx';
5
5
  import { useState } from 'react';
6
6
  import { useDebounce } from '../../hooks/useDebounce.js';
7
- import { useId } from '../../hooks/useId.js';
7
+ import { useField } from '../Field/Field.context.js';
8
8
 
9
9
  const DEBOUNCE_DELAY = 750;
10
10
  const charCountMessage = (remaining) => {
@@ -12,7 +12,7 @@ const charCountMessage = (remaining) => {
12
12
  };
13
13
  const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, counter = false, cutoff = false, disabled = false, error = false, id, maxLength, name, onChange: userOnChange = undefined, placeholder, ref, rows = 4, size, ...props }) => {
14
14
  var _a;
15
- const uid = useId(id);
15
+ const field = useField();
16
16
  const componentProps = {
17
17
  "aria-placeholder": (_a = placeholder !== null && placeholder !== void 0 ? placeholder : ariaPlaceholder) !== null && _a !== void 0 ? _a : undefined,
18
18
  className: clsx("coop-textarea", "coop-field-element", className),
@@ -20,7 +20,7 @@ const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, c
20
20
  "data-error": error !== null && error !== void 0 ? error : undefined,
21
21
  "data-size": size !== null && size !== void 0 ? size : undefined,
22
22
  disabled,
23
- id: uid,
23
+ id: id !== null && id !== void 0 ? id : field === null || field === void 0 ? void 0 : field.id,
24
24
  maxLength: cutoff ? maxLength : undefined,
25
25
  name,
26
26
  placeholder,
@@ -37,8 +37,6 @@ const Textarea = ({ "aria-placeholder": ariaPlaceholder, className, cols = 30, c
37
37
  // const formItemProps = { "aria-disabled": disabled ? true : undefined }
38
38
  return (jsxs("div", { className: "coop-textarea-wrapper", children: [jsx("textarea", { ...componentProps, onChange: handleChange, ref: ref }), showCounter && (jsxs(Fragment, { children: [jsx("small", { "aria-hidden": "true", className: "coop-textarea-counter", ...(remaining < 0 && { "data-error": true }), children: charCountMessage(remaining) }), jsx("span", { "aria-live": "polite", className: "sr-only", children: charCountMessage(debouncedRemaining) })] }))] }));
39
39
  };
40
- Textarea.config = {
41
- isField: true,
42
- };
40
+ Textarea.slot = { name: "Textarea" };
43
41
 
44
42
  export { Textarea, Textarea as default };
@@ -48,25 +48,47 @@ interface ValidationSummaryErrorsProps extends HTMLAttributes<HTMLDivElement> {
48
48
  /** **(Optional)** Content inside the Errors. */
49
49
  errors?: Record<string, FieldError>;
50
50
  }
51
- export declare const ValidationSummary: {
51
+ declare const ValidationSummary: {
52
52
  ({ autoScroll, children, className, forceMount, ref, ...props }: ValidationSummaryProps): JSX.Element | null;
53
+ slot: {
54
+ name: string;
55
+ };
53
56
  Heading: {
54
57
  ({ as, children, className, }: ValidationSummaryHeadingProps): JSX.Element;
55
- config: {
58
+ slot: {
56
59
  name: string;
57
60
  };
58
61
  };
59
62
  Prompt: {
60
63
  ({ children, }: ValidationSummaryPromptProps): JSX.Element;
61
- config: {
64
+ slot: {
62
65
  name: string;
63
66
  };
64
67
  };
65
68
  Errors: {
66
69
  ({ errors }: ValidationSummaryErrorsProps): JSX.Element | null;
67
- config: {
70
+ slot: {
68
71
  name: string;
69
72
  };
70
73
  };
71
74
  };
75
+ declare const ValidationSummaryHeading: {
76
+ ({ as, children, className, }: ValidationSummaryHeadingProps): JSX.Element;
77
+ slot: {
78
+ name: string;
79
+ };
80
+ };
81
+ declare const ValidationSummaryPrompt: {
82
+ ({ children, }: ValidationSummaryPromptProps): JSX.Element;
83
+ slot: {
84
+ name: string;
85
+ };
86
+ };
87
+ declare const ValidationSummaryErrors: {
88
+ ({ errors }: ValidationSummaryErrorsProps): JSX.Element | null;
89
+ slot: {
90
+ name: string;
91
+ };
92
+ };
72
93
  export default ValidationSummary;
94
+ export { ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, };
@@ -1,11 +1,12 @@
1
+
2
+ "use client";
1
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
4
  import clsx from 'clsx';
3
- import mergeRefs from '../../node_modules/merge-refs/dist/index.js';
5
+ import mergeRefs from 'merge-refs';
4
6
  import React, { useRef, useEffect } from 'react';
5
7
  import { useSlots } from '../../hooks/useSlots.js';
6
8
  import { sanitizeFieldId, getFieldElement } from './validationsummary-utils.js';
7
9
 
8
- /* eslint-disable jsx-a11y/anchor-is-valid */
9
10
  const componentSlots = {
10
11
  Children: null,
11
12
  ValidationSummaryErrors: null,
@@ -67,11 +68,12 @@ const ValidationSummaryErrors = ({ errors }) => {
67
68
  }, children: error.message }) }, field));
68
69
  }) }) })) : null;
69
70
  };
70
- ValidationSummaryHeading.config = { name: "ValidationSummaryHeading" };
71
- ValidationSummaryPrompt.config = { name: "ValidationSummaryPrompt" };
72
- ValidationSummaryErrors.config = { name: "ValidationSummaryErrors" };
71
+ ValidationSummary.slot = { name: "ValidationSummary" };
72
+ ValidationSummaryHeading.slot = { name: "ValidationSummaryHeading" };
73
+ ValidationSummaryPrompt.slot = { name: "ValidationSummaryPrompt" };
74
+ ValidationSummaryErrors.slot = { name: "ValidationSummaryErrors" };
73
75
  ValidationSummary.Heading = ValidationSummaryHeading;
74
76
  ValidationSummary.Prompt = ValidationSummaryPrompt;
75
77
  ValidationSummary.Errors = ValidationSummaryErrors;
76
78
 
77
- export { ValidationSummary, ValidationSummary as default };
79
+ export { ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt, ValidationSummary as default };
@@ -1,8 +1,10 @@
1
1
  import React from "react";
2
- import { ReactNodeWithConfig } from "../types";
2
+ import { LazyComponent } from "../types";
3
3
  type Slots<T> = Record<keyof T, React.ReactNode>;
4
4
  export declare function isKey<T extends object>(x: T, k: PropertyKey): k is keyof T;
5
- export declare function getSlotName(node: ReactNodeWithConfig): string | false;
5
+ export declare function isLazy<T extends React.ComponentType<any>>(type: unknown): type is LazyComponent<T>;
6
+ export declare function resolveComponentName(child: React.ReactNode): string | null;
7
+ export declare function getSlotName(node: React.ReactNode): string | false;
6
8
  export declare function useSlots<T>(componentSlots: Slots<T>, children: React.ReactNode, options?: {
7
9
  collect?: string[];
8
10
  }): Slots<T>;
@@ -3,13 +3,39 @@ import React from 'react';
3
3
  function isKey(x, k) {
4
4
  return k in x;
5
5
  }
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ function isLazy(type) {
8
+ return typeof type === "object" && type !== null && "_payload" in type && "_init" in type;
9
+ }
10
+ function resolveComponentName(child) {
11
+ var _a, _b, _c, _d;
12
+ if (child && typeof child === "object" && "type" in child) {
13
+ const type = child.type;
14
+ if (isLazy(type)) {
15
+ try {
16
+ const resolved = type._init(type._payload);
17
+ if ("slot" in resolved)
18
+ return resolved.slot.name;
19
+ return (_b = (_a = resolved.displayName) !== null && _a !== void 0 ? _a : resolved.name) !== null && _b !== void 0 ? _b : null;
20
+ }
21
+ catch (_e) {
22
+ // _init throws a Promise if the payload is still pending
23
+ return null;
24
+ }
25
+ }
26
+ if (typeof type === "function") {
27
+ if ("slot" in type)
28
+ return type.slot.name;
29
+ return (_d = (_c = type.displayName) !== null && _c !== void 0 ? _c : type.name) !== null && _d !== void 0 ? _d : null;
30
+ }
31
+ }
32
+ return null;
33
+ }
6
34
  function getSlotName(node) {
7
- var _a, _b, _c;
8
- if (React.isValidElement(node) &&
9
- node.type &&
10
- typeof node.type !== "string" &&
11
- typeof node.type !== "symbol") {
12
- return (_c = (_b = (_a = node.type) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : node.type.name;
35
+ const slotName = resolveComponentName(node);
36
+ if (slotName) {
37
+ return slotName.replaceAll(".", "");
38
+ // return root && !safeName.startsWith(root) ? root + safeName : safeName
13
39
  }
14
40
  return false;
15
41
  }
@@ -32,4 +58,4 @@ function useSlots(componentSlots, children, options) {
32
58
  }, { ...componentSlots });
33
59
  }
34
60
 
35
- export { getSlotName, isKey, useSlots };
61
+ export { getSlotName, isKey, isLazy, resolveComponentName, useSlots };
package/dist/index.js CHANGED
@@ -1,25 +1,25 @@
1
- export { AlertBanner } from './components/AlertBanner/AlertBanner.js';
1
+ export { AlertBanner, AlertBannerHeading } from './components/AlertBanner/AlertBanner.js';
2
2
  export { Author } from './components/Author/Author.js';
3
3
  export { Button } from './components/Button/Button.js';
4
- export { Card } from './components/Card/Card.js';
4
+ export { Card, CardBadge, CardBody, CardHeading, CardImage, CardLabel } from './components/Card/Card.js';
5
5
  export { Checkbox } from './components/Checkbox/Checkbox.js';
6
6
  export { DatePicker } from './components/DatePicker/DatePicker.js';
7
- export { Expandable } from './components/Expandable/Expandable.js';
8
- export { Field } from './components/Field/Field.js';
9
- export { Fieldset } from './components/Fieldset/Fieldset.js';
7
+ export { Expandable, ExpandableContent, ExpandableSummary } from './components/Expandable/Expandable.js';
8
+ export { Field, FieldError, FieldHint, FieldLabel } from './components/Field/Field.js';
9
+ export { Fieldset, FieldsetError, FieldsetFields, FieldsetHint, FieldsetLegend } from './components/Fieldset/Fieldset.js';
10
10
  export { Flourish } from './components/Flourish/Flourish.js';
11
11
  export { Form } from './components/Form/Form.js';
12
12
  export { Image } from './components/Image/Image.js';
13
- export { Pill } from './components/Pill/Pill.js';
14
- export { Popover } from './components/Popover/Popover.js';
13
+ export { Pill, PillBadge } from './components/Pill/Pill.js';
14
+ export { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from './components/Popover/Popover.js';
15
15
  export { Radio } from './components/Radio/Radio.js';
16
16
  export { RootSVG } from './components/RootSVG/RootSVG.js';
17
- export { Searchbox } from './components/Searchbox/Searchbox.js';
18
- export { Select } from './components/Select/Select.js';
17
+ export { Searchbox, SearchboxButton, SearchboxInput } from './components/Searchbox/Searchbox.js';
18
+ export { Select, SelectOption, SelectOptionGroup } from './components/Select/Select.js';
19
19
  export { Signpost } from './components/Signpost/Signpost.js';
20
20
  export { SkipNav } from './components/SkipNav/SkipNav.js';
21
21
  export { Squircle } from './components/Squircle/Squircle.js';
22
22
  export { Tag } from './components/Tag/Tag.js';
23
23
  export { Textarea } from './components/Textarea/Textarea.js';
24
24
  export { TextInput } from './components/TextInput/TextInput.js';
25
- export { ValidationSummary } from './components/ValidationSummary/ValidationSummary.js';
25
+ export { ValidationSummary, ValidationSummaryErrors, ValidationSummaryHeading, ValidationSummaryPrompt } from './components/ValidationSummary/ValidationSummary.js';
@@ -1,16 +1,16 @@
1
1
  export type StandardSizes = "sm" | "md" | "lg";
2
- export type FormFieldError = {
3
- message?: string;
4
- type?: string;
5
- } | boolean | null | undefined;
6
- export type ReactNodeWithConfig = (React.ReactNode & {
7
- type?: {
8
- config?: ComponentConfig;
9
- };
10
- }) | undefined | null;
11
- export interface ComponentConfig {
12
- fieldSuffix?: string;
13
- isField?: boolean;
14
- isInline?: boolean;
15
- name?: string;
2
+ export interface SlotConfig {
3
+ field?: boolean;
4
+ inline?: boolean;
5
+ name: string;
6
+ suffix?: string;
16
7
  }
8
+ export interface LazyPayload<T> {
9
+ default: T;
10
+ }
11
+ export interface LazyComponent<T extends React.ComponentType<any>> {
12
+ _init: (payload: unknown) => T;
13
+ _payload: Promise<LazyPayload<T>> | LazyPayload<T>;
14
+ $$typeof: typeof REACT_LAZY_TYPE;
15
+ }
16
+ export declare const REACT_LAZY_TYPE: unique symbol;
@@ -2,3 +2,4 @@ export declare const bgPropToClass: (color: string, userClasses?: string) => str
2
2
  export declare const hasUserBg: (userClasses?: string) => boolean;
3
3
  export declare const hasUserBorder: (userClasses?: string) => boolean;
4
4
  export declare const bgClassToColor: (userClasses: string) => string | null;
5
+ export declare function getSlotProp<R = unknown>(slot: React.ReactNode, prop: string): R | undefined;
@@ -1,3 +1,5 @@
1
+ import { isValidElement } from 'react';
2
+
1
3
  const hasUserBg = (userClasses) => {
2
4
  return typeof userClasses === "string" && (userClasses === null || userClasses === void 0 ? void 0 : userClasses.includes("bg-")) ? true : false;
3
5
  };
@@ -7,12 +9,12 @@ const hasUserBorder = (userClasses) => {
7
9
  const bgClassToColor = (userClasses) => {
8
10
  var _a, _b;
9
11
  return (_b = (_a = /bg-([^\s]+)/.exec(userClasses)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : null;
10
- // return (
11
- // userClasses
12
- // .split(" ")
13
- // .find((c) => c.startsWith("bg"))
14
- // ?.replace("bg-", "") ?? ""
15
- // )
16
12
  };
13
+ function getSlotProp(slot, prop) {
14
+ if (isValidElement(slot) && prop in slot.props) {
15
+ return slot.props[prop];
16
+ }
17
+ return undefined;
18
+ }
17
19
 
18
- export { bgClassToColor, hasUserBg, hasUserBorder };
20
+ export { bgClassToColor, getSlotProp, hasUserBg, hasUserBorder };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coopdigital/react",
3
3
  "type": "module",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "private": false,
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -47,6 +47,7 @@
47
47
  "build": "tsx scripts build",
48
48
  "build:docs": "tsx scripts build-docs",
49
49
  "build:icons": "tsx scripts build-icons",
50
+ "build:manifest": "tsx scripts build-manifest",
50
51
  "build:storybook": "storybook build --disable-telemetry",
51
52
  "build:storybook:test": "storybook build --test --disable-telemetry --output-dir storybook-test",
52
53
  "serve:storybook:test": "serve -p 9000 ./storybook-test",
@@ -61,10 +62,10 @@
61
62
  "devDependencies": {
62
63
  "@axe-core/playwright": "^4.11.3",
63
64
  "@playwright/test": "^1.60.0",
64
- "@storybook/addon-a11y": "^10.4.0",
65
- "@storybook/addon-docs": "^10.4.0",
66
- "@storybook/addon-onboarding": "^10.4.0",
67
- "@storybook/react-vite": "^10.4.0",
65
+ "@storybook/addon-a11y": "^10.4.1",
66
+ "@storybook/addon-docs": "^10.4.1",
67
+ "@storybook/addon-onboarding": "^10.4.1",
68
+ "@storybook/react-vite": "^10.4.1",
68
69
  "@testing-library/jest-dom": "^6.9.1",
69
70
  "@testing-library/react": "^16.3.2",
70
71
  "@types/react": "^19.2.15",
@@ -73,7 +74,7 @@
73
74
  "react-dom": "^19.2.6",
74
75
  "resize-observer-polyfill": "^1.5.1",
75
76
  "serve": "^14.2.6",
76
- "storybook": "^10.4.0",
77
+ "storybook": "^10.4.1",
77
78
  "storybook-addon-tag-badges": "^3.1.0"
78
79
  },
79
80
  "peerDependencies": {
@@ -84,11 +85,11 @@
84
85
  "storybook": "$storybook"
85
86
  },
86
87
  "dependencies": {
87
- "@coopdigital/styles": "^1.3.1",
88
+ "@coopdigital/styles": "^1.3.2",
88
89
  "@radix-ui/react-popover": "^1.1.15",
89
90
  "clsx": "^2.1.1",
90
91
  "merge-refs": "^2.0.0",
91
92
  "react-day-picker": "^10.0.0"
92
93
  },
93
- "gitHead": "1f09d7d3de31cb2a72cbfbb980883feb8b9c2d22"
94
+ "gitHead": "15c4578e9debb09061027e27e0d6772c2c918d96"
94
95
  }
@@ -20,7 +20,7 @@ interface AlertBannerHeadingProps extends HTMLAttributes<HTMLHeadingElement> {
20
20
  className?: string
21
21
  }
22
22
 
23
- export const AlertBanner = ({
23
+ const AlertBanner = ({
24
24
  children,
25
25
  className,
26
26
  ref,
@@ -44,8 +44,11 @@ const AlertBannerHeading = ({ children, className }: AlertBannerHeadingProps): J
44
44
  return <h2 className={className}>{children}</h2>
45
45
  }
46
46
 
47
- AlertBannerHeading.config = { name: "AlertBannerHeading" }
47
+ AlertBanner.slot = { name: "AlertBanner" }
48
+ AlertBannerHeading.slot = { name: "AlertBannerHeading" }
48
49
 
49
50
  AlertBanner.Heading = AlertBannerHeading
50
51
 
51
52
  export default AlertBanner
53
+
54
+ export { AlertBanner, AlertBannerHeading }
@@ -21,7 +21,7 @@ export interface AuthorProps extends HTMLAttributes<HTMLDivElement> {
21
21
  size?: "sm" | "md"
22
22
  }
23
23
 
24
- export const Author = ({
24
+ const Author = ({
25
25
  author = "Co-op team",
26
26
  className,
27
27
  date,
@@ -58,4 +58,7 @@ export const Author = ({
58
58
  )
59
59
  }
60
60
 
61
+ Author.slot = { name: "Author" }
62
+
61
63
  export default Author
64
+ export { Author }
@@ -40,7 +40,7 @@ type OnClickHandler =
40
40
  | React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>
41
41
  | ((event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => Promise<void>)
42
42
 
43
- export const Button = ({
43
+ const Button = ({
44
44
  as,
45
45
  children,
46
46
  className,
@@ -102,4 +102,8 @@ export const Button = ({
102
102
 
103
103
  return React.createElement(element, { ...componentProps, ref }, finalChildren)
104
104
  }
105
+
106
+ Button.slot = { name: "Button" }
107
+
105
108
  export default Button
109
+ export { Button }
@@ -82,7 +82,7 @@ function getCardLinkElement(as: CardProps["hrefAs"], href?: string) {
82
82
  }
83
83
  }
84
84
 
85
- export const Card = ({
85
+ const Card = ({
86
86
  chevron = false,
87
87
  children,
88
88
  className,
@@ -162,11 +162,12 @@ const CardImage = (props: CardImageProps) => {
162
162
  return <Image {...{ ...props, crop: props.crop ?? "wide" }} />
163
163
  }
164
164
 
165
- CardLabel.config = { name: "CardLabel" }
166
- CardHeading.config = { name: "CardHeading" }
167
- CardBadge.config = { name: "CardBadge" }
168
- CardBody.config = { name: "CardBody" }
169
- CardImage.config = { name: "CardImage" }
165
+ Card.slot = { name: "Card" }
166
+ CardLabel.slot = { name: "CardLabel" }
167
+ CardHeading.slot = { name: "CardHeading" }
168
+ CardBadge.slot = { name: "CardBadge" }
169
+ CardBody.slot = { name: "CardBody" }
170
+ CardImage.slot = { name: "CardImage" }
170
171
 
171
172
  Card.Label = CardLabel
172
173
  Card.Heading = CardHeading
@@ -175,3 +176,4 @@ Card.Body = CardBody
175
176
  Card.Image = CardImage
176
177
 
177
178
  export default Card
179
+ export { Card, CardBadge, CardBody, CardHeading, CardImage, CardLabel }
@@ -1,9 +1,10 @@
1
+ "use client"
1
2
  import type { InputHTMLAttributes, JSX, Ref } from "react"
2
3
 
3
4
  import clsx from "clsx"
4
5
 
5
- import { ComponentConfig, StandardSizes } from "../../../src/types"
6
- import { useId } from "../../hooks/useId"
6
+ import { StandardSizes } from "../../../src/types"
7
+ import { useField } from "../Field/Field.context"
7
8
 
8
9
  export interface CheckboxProps extends Omit<
9
10
  InputHTMLAttributes<HTMLInputElement>,
@@ -25,7 +26,7 @@ export interface CheckboxProps extends Omit<
25
26
  size?: StandardSizes
26
27
  }
27
28
 
28
- export const Checkbox = ({
29
+ const Checkbox = ({
29
30
  className,
30
31
  disabled,
31
32
  error = false,
@@ -35,13 +36,14 @@ export const Checkbox = ({
35
36
  size,
36
37
  ...props
37
38
  }: CheckboxProps): JSX.Element => {
38
- const uid = useId(id)
39
+ const field = useField()
40
+
39
41
  const componentProps = {
40
42
  className: clsx("coop-checkbox", "coop-field-element", className),
41
43
  "data-error": error || undefined,
42
44
  "data-size": size ?? undefined,
43
45
  disabled,
44
- id: uid,
46
+ id: id ?? field?.id,
45
47
  name,
46
48
  type: "checkbox",
47
49
  ...props,
@@ -50,9 +52,11 @@ export const Checkbox = ({
50
52
  return <input {...componentProps} ref={ref} />
51
53
  }
52
54
 
53
- Checkbox.config = {
54
- isField: true,
55
- isInline: true,
56
- } satisfies ComponentConfig
55
+ Checkbox.slot = {
56
+ field: true,
57
+ inline: true,
58
+ name: "Checkbox",
59
+ }
57
60
 
58
61
  export default Checkbox
62
+ export { Checkbox }