@coopdigital/react 1.4.1 → 1.5.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.
Files changed (205) 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 -1
  7. package/dist/components/Card/Card.d.ts +41 -7
  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 +8 -6
  11. package/dist/components/DatePicker/DatePicker.d.ts +8 -3
  12. package/dist/components/DatePicker/DatePicker.js +11 -12
  13. package/dist/components/Expandable/Expandable.d.ts +21 -5
  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 +13 -0
  17. package/dist/components/Field/Field.d.ts +30 -8
  18. package/dist/components/Field/Field.js +32 -34
  19. package/dist/components/Field/index.js +1 -0
  20. package/dist/components/FieldMarkers/Label.d.ts +1 -1
  21. package/dist/components/FieldMarkers/Label.js +4 -0
  22. package/dist/components/FieldMarkers/Legend.d.ts +1 -1
  23. package/dist/components/Fieldset/Fieldset.d.ts +36 -8
  24. package/dist/components/Fieldset/Fieldset.js +6 -5
  25. package/dist/components/Flourish/Flourish.d.ts +7 -1
  26. package/dist/components/Flourish/Flourish.js +1 -0
  27. package/dist/components/Form/Form.d.ts +7 -1
  28. package/dist/components/Form/Form.js +1 -0
  29. package/dist/components/Image/Image.d.ts +7 -1
  30. package/dist/components/Image/Image.js +1 -0
  31. package/dist/components/Pill/Pill.d.ts +13 -3
  32. package/dist/components/Pill/Pill.js +3 -2
  33. package/dist/components/Popover/Popover.d.ts +33 -5
  34. package/dist/components/Popover/Popover.js +6 -5
  35. package/dist/components/Popover/index.js +1 -0
  36. package/dist/components/Radio/Radio.d.ts +6 -4
  37. package/dist/components/Radio/Radio.js +8 -6
  38. package/dist/components/RootSVG/RootSVG.d.ts +7 -1
  39. package/dist/components/RootSVG/RootSVG.js +1 -0
  40. package/dist/components/Searchbox/Searchbox.context.d.ts +13 -0
  41. package/dist/components/Searchbox/Searchbox.context.js +11 -0
  42. package/dist/components/Searchbox/Searchbox.d.ts +16 -12
  43. package/dist/components/Searchbox/Searchbox.js +25 -29
  44. package/dist/components/Select/Select.d.ts +18 -5
  45. package/dist/components/Select/Select.js +8 -9
  46. package/dist/components/Signpost/Signpost.d.ts +7 -1
  47. package/dist/components/Signpost/Signpost.js +1 -0
  48. package/dist/components/SkipNav/SkipNav.d.ts +7 -1
  49. package/dist/components/SkipNav/SkipNav.js +1 -0
  50. package/dist/components/Squircle/Squircle.d.ts +7 -1
  51. package/dist/components/Squircle/Squircle.js +1 -0
  52. package/dist/components/Tag/Tag.d.ts +7 -1
  53. package/dist/components/Tag/Tag.js +1 -0
  54. package/dist/components/TextInput/TextInput.d.ts +4 -3
  55. package/dist/components/TextInput/TextInput.js +5 -6
  56. package/dist/components/Textarea/Textarea.d.ts +4 -3
  57. package/dist/components/Textarea/Textarea.js +4 -7
  58. package/dist/components/ValidationSummary/ValidationSummary.d.ts +26 -4
  59. package/dist/components/ValidationSummary/ValidationSummary.js +7 -6
  60. package/dist/components/icons/AccountCircleFilledIcon.d.ts +1 -1
  61. package/dist/components/icons/AccountCircleIcon.d.ts +1 -1
  62. package/dist/components/icons/AccountFilledIcon.d.ts +1 -1
  63. package/dist/components/icons/AccountIcon.d.ts +1 -1
  64. package/dist/components/icons/AddIcon.d.ts +1 -1
  65. package/dist/components/icons/AppsFilledIcon.d.ts +1 -1
  66. package/dist/components/icons/AppsIcon.d.ts +1 -1
  67. package/dist/components/icons/ArrowDownIcon.d.ts +1 -1
  68. package/dist/components/icons/ArrowLeftIcon.d.ts +1 -1
  69. package/dist/components/icons/ArrowRightIcon.d.ts +1 -1
  70. package/dist/components/icons/ArrowUpIcon.d.ts +1 -1
  71. package/dist/components/icons/BackspaceFilledIcon.d.ts +1 -1
  72. package/dist/components/icons/BackspaceIcon.d.ts +1 -1
  73. package/dist/components/icons/BasketFilledIcon.d.ts +1 -1
  74. package/dist/components/icons/BasketIcon.d.ts +1 -1
  75. package/dist/components/icons/BellFilledIcon.d.ts +1 -1
  76. package/dist/components/icons/BellIcon.d.ts +1 -1
  77. package/dist/components/icons/BroomIcon.d.ts +1 -1
  78. package/dist/components/icons/CalendarFilledIcon.d.ts +1 -1
  79. package/dist/components/icons/CalendarIcon.d.ts +1 -1
  80. package/dist/components/icons/CashFilledIcon.d.ts +1 -1
  81. package/dist/components/icons/CashIcon.d.ts +1 -1
  82. package/dist/components/icons/ChevronDownIcon.d.ts +1 -1
  83. package/dist/components/icons/ChevronLeftIcon.d.ts +1 -1
  84. package/dist/components/icons/ChevronRightIcon.d.ts +1 -1
  85. package/dist/components/icons/ChevronUpIcon.d.ts +1 -1
  86. package/dist/components/icons/CircleBurgerFilledIcon.d.ts +1 -1
  87. package/dist/components/icons/CircleBurgerIcon.d.ts +1 -1
  88. package/dist/components/icons/ClipboardFilledIcon.d.ts +1 -1
  89. package/dist/components/icons/ClipboardIcon.d.ts +1 -1
  90. package/dist/components/icons/ClockFilledIcon.d.ts +1 -1
  91. package/dist/components/icons/ClockIcon.d.ts +1 -1
  92. package/dist/components/icons/CloseAltFilledIcon.d.ts +1 -1
  93. package/dist/components/icons/CloseAltIcon.d.ts +1 -1
  94. package/dist/components/icons/CogIcon.d.ts +1 -1
  95. package/dist/components/icons/CommunityFilledIcon.d.ts +1 -1
  96. package/dist/components/icons/CommunityIcon.d.ts +1 -1
  97. package/dist/components/icons/ComputerIcon.d.ts +1 -1
  98. package/dist/components/icons/ContactFilledIcon.d.ts +1 -1
  99. package/dist/components/icons/ContactIcon.d.ts +1 -1
  100. package/dist/components/icons/ContactlessFilledIcon.d.ts +1 -1
  101. package/dist/components/icons/ContactlessIcon.d.ts +1 -1
  102. package/dist/components/icons/CoopLiveIcon.d.ts +1 -1
  103. package/dist/components/icons/CoopLocationFilledIcon.d.ts +1 -1
  104. package/dist/components/icons/CoopLogoIcon.d.ts +1 -1
  105. package/dist/components/icons/CoopMembershipCardFilledIcon.d.ts +1 -1
  106. package/dist/components/icons/CreditCardFilledIcon.d.ts +1 -1
  107. package/dist/components/icons/CreditCardIcon.d.ts +1 -1
  108. package/dist/components/icons/CrossIcon.d.ts +1 -1
  109. package/dist/components/icons/DocumentIcon.d.ts +1 -1
  110. package/dist/components/icons/DownloadIcon.d.ts +1 -1
  111. package/dist/components/icons/EnterStoreIcon.d.ts +1 -1
  112. package/dist/components/icons/ExitStoreIcon.d.ts +1 -1
  113. package/dist/components/icons/EyeFilledIcon.d.ts +1 -1
  114. package/dist/components/icons/EyeIcon.d.ts +1 -1
  115. package/dist/components/icons/EyeStrikeFilledIcon.d.ts +1 -1
  116. package/dist/components/icons/EyeStrikeIcon.d.ts +1 -1
  117. package/dist/components/icons/FeedbackFilledIcon.d.ts +1 -1
  118. package/dist/components/icons/FeedbackIcon.d.ts +1 -1
  119. package/dist/components/icons/FilterIcon.d.ts +1 -1
  120. package/dist/components/icons/GiftCardFilledIcon.d.ts +1 -1
  121. package/dist/components/icons/GiftCardIcon.d.ts +1 -1
  122. package/dist/components/icons/GiftFilledIcon.d.ts +1 -1
  123. package/dist/components/icons/GiftIcon.d.ts +1 -1
  124. package/dist/components/icons/HelpFilledIcon.d.ts +1 -1
  125. package/dist/components/icons/HelpIcon.d.ts +1 -1
  126. package/dist/components/icons/HomeFilledIcon.d.ts +1 -1
  127. package/dist/components/icons/HomeIcon.d.ts +1 -1
  128. package/dist/components/icons/HowDoIAssistantIcon.d.ts +1 -1
  129. package/dist/components/icons/InfoIcon.d.ts +1 -1
  130. package/dist/components/icons/KebabIcon.d.ts +1 -1
  131. package/dist/components/icons/LoadingIcon.d.ts +1 -1
  132. package/dist/components/icons/LocationFilledIcon.d.ts +1 -1
  133. package/dist/components/icons/LocationIcon.d.ts +1 -1
  134. package/dist/components/icons/LogoutIcon.d.ts +1 -1
  135. package/dist/components/icons/MailIcon.d.ts +1 -1
  136. package/dist/components/icons/MenuIcon.d.ts +1 -1
  137. package/dist/components/icons/MessageIcon.d.ts +1 -1
  138. package/dist/components/icons/MinusIcon.d.ts +1 -1
  139. package/dist/components/icons/NotesFilledIcon.d.ts +1 -1
  140. package/dist/components/icons/NotesIcon.d.ts +1 -1
  141. package/dist/components/icons/OpenNewIcon.d.ts +1 -1
  142. package/dist/components/icons/OwnBagIcon.d.ts +1 -1
  143. package/dist/components/icons/PadlockIcon.d.ts +1 -1
  144. package/dist/components/icons/PencilIcon.d.ts +1 -1
  145. package/dist/components/icons/PhoneIcon.d.ts +1 -1
  146. package/dist/components/icons/PowerIcon.d.ts +1 -1
  147. package/dist/components/icons/SaveFilledIcon.d.ts +1 -1
  148. package/dist/components/icons/SaveIcon.d.ts +1 -1
  149. package/dist/components/icons/ScooterIcon.d.ts +1 -1
  150. package/dist/components/icons/SearchFilledIcon.d.ts +1 -1
  151. package/dist/components/icons/SearchIcon.d.ts +1 -1
  152. package/dist/components/icons/SendIcon.d.ts +1 -1
  153. package/dist/components/icons/SpannerIcon.d.ts +1 -1
  154. package/dist/components/icons/StarFilledIcon.d.ts +1 -1
  155. package/dist/components/icons/StarIcon.d.ts +1 -1
  156. package/dist/components/icons/TickAltFilledIcon.d.ts +1 -1
  157. package/dist/components/icons/TickAltIcon.d.ts +1 -1
  158. package/dist/components/icons/TickIcon.d.ts +1 -1
  159. package/dist/components/icons/TruckIcon.d.ts +1 -1
  160. package/dist/components/icons/UserWipeIcon.d.ts +1 -1
  161. package/dist/components/icons/VoucherFilledIcon.d.ts +1 -1
  162. package/dist/components/icons/VoucherIcon.d.ts +1 -1
  163. package/dist/components/icons/WarningFilledIcon.d.ts +1 -1
  164. package/dist/components/icons/WarningIcon.d.ts +1 -1
  165. package/dist/components/icons/WifiIcon.d.ts +1 -1
  166. package/dist/components/icons/WriteIcon.d.ts +1 -1
  167. package/dist/hooks/useSlots.d.ts +4 -2
  168. package/dist/hooks/useSlots.js +33 -7
  169. package/dist/index.js +10 -10
  170. package/dist/types/index.d.ts +14 -14
  171. package/dist/utils/index.d.ts +1 -0
  172. package/dist/utils/index.js +9 -7
  173. package/package.json +12 -11
  174. package/src/components/AlertBanner/AlertBanner.tsx +5 -2
  175. package/src/components/Author/Author.tsx +4 -1
  176. package/src/components/Button/Button.tsx +5 -1
  177. package/src/components/Card/Card.tsx +8 -6
  178. package/src/components/Checkbox/Checkbox.tsx +13 -9
  179. package/src/components/DatePicker/DatePicker.tsx +15 -15
  180. package/src/components/Expandable/Expandable.tsx +5 -8
  181. package/src/components/Field/Field.context.ts +29 -0
  182. package/src/components/Field/Field.tsx +61 -56
  183. package/src/components/FieldMarkers/Label.tsx +4 -0
  184. package/src/components/Fieldset/Fieldset.tsx +7 -5
  185. package/src/components/Flourish/Flourish.tsx +4 -1
  186. package/src/components/Form/Form.tsx +4 -1
  187. package/src/components/Image/Image.tsx +4 -1
  188. package/src/components/Pill/Pill.tsx +4 -2
  189. package/src/components/Popover/Popover.tsx +7 -5
  190. package/src/components/Radio/Radio.tsx +12 -9
  191. package/src/components/RootSVG/RootSVG.tsx +4 -1
  192. package/src/components/Searchbox/Searchbox.context.tsx +20 -0
  193. package/src/components/Searchbox/Searchbox.tsx +55 -44
  194. package/src/components/Select/Select.tsx +11 -11
  195. package/src/components/Signpost/Signpost.tsx +4 -1
  196. package/src/components/SkipNav/SkipNav.tsx +4 -1
  197. package/src/components/Squircle/Squircle.tsx +4 -1
  198. package/src/components/Tag/Tag.tsx +4 -1
  199. package/src/components/TextInput/TextInput.tsx +8 -8
  200. package/src/components/Textarea/Textarea.tsx +7 -8
  201. package/src/components/ValidationSummary/ValidationSummary.tsx +12 -5
  202. package/src/hooks/useSlots.ts +37 -9
  203. package/src/types/index.ts +18 -14
  204. package/src/utils/index.ts +8 -6
  205. package/dist/node_modules/merge-refs/dist/index.js +0 -36
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.1",
4
+ "version": "1.5.1",
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,19 +62,19 @@
61
62
  "devDependencies": {
62
63
  "@axe-core/playwright": "^4.11.3",
63
64
  "@playwright/test": "^1.60.0",
64
- "@storybook/addon-a11y": "^10.4.1",
65
- "@storybook/addon-docs": "^10.4.1",
66
- "@storybook/addon-onboarding": "^10.4.1",
67
- "@storybook/react-vite": "^10.4.1",
65
+ "@storybook/addon-a11y": "^10.4.4",
66
+ "@storybook/addon-docs": "^10.4.4",
67
+ "@storybook/addon-onboarding": "^10.4.4",
68
+ "@storybook/react-vite": "^10.4.4",
68
69
  "@testing-library/jest-dom": "^6.9.1",
69
70
  "@testing-library/react": "^16.3.2",
70
- "@types/react": "^19.2.15",
71
+ "@types/react": "^19.2.17",
71
72
  "@types/react-dom": "^19.2.3",
72
- "react": "^19.2.6",
73
- "react-dom": "^19.2.6",
73
+ "react": "^19.2.7",
74
+ "react-dom": "^19.2.7",
74
75
  "resize-observer-polyfill": "^1.5.1",
75
76
  "serve": "^14.2.6",
76
- "storybook": "^10.4.1",
77
+ "storybook": "^10.4.4",
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.3",
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": "653928f1dfd07fa4db9b09e897be07d191d7bb1b"
94
+ "gitHead": "002d135011d4864e286bc1f8e7f0e23a394e5e33"
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 }
@@ -13,7 +13,7 @@ import clsx from "clsx"
13
13
  import { useCallback, useMemo, useReducer } from "react"
14
14
  import { DayPicker } from "react-day-picker"
15
15
 
16
- import type { ComponentConfig, StandardSizes } from "../../types"
16
+ import type { StandardSizes } from "../../types"
17
17
  import type {
18
18
  DateRange,
19
19
  DateRangeStr,
@@ -23,8 +23,8 @@ import type {
23
23
  TDateSingle,
24
24
  } from "./datepicker-utils"
25
25
 
26
- import { useId } from "../../hooks/useId"
27
26
  import Button from "../Button"
27
+ import { useField } from "../Field/Field.context"
28
28
  import { CalendarIcon, CrossIcon, TickIcon } from "../icons"
29
29
  import Popover from "../Popover"
30
30
  import TextInput from "../TextInput"
@@ -108,11 +108,6 @@ export interface DatePickerProps extends Omit<
108
108
 
109
109
  const now = new Date()
110
110
 
111
- const componentConfig: ComponentConfig = {
112
- fieldSuffix: "_display",
113
- isField: true,
114
- }
115
-
116
111
  const baseValueProps = {
117
112
  readOnly: true,
118
113
  type: "hidden",
@@ -162,7 +157,7 @@ const Calendar = ({
162
157
  )
163
158
  }
164
159
 
165
- export const DatePicker = ({
160
+ const DatePicker = ({
166
161
  className,
167
162
  closeOnSelect = true,
168
163
  dateFormat = "dd/MM/yyyy",
@@ -183,7 +178,7 @@ export const DatePicker = ({
183
178
  startDate,
184
179
  ...props
185
180
  }: DatePickerProps): JSX.Element => {
186
- const uid = useId(id)
181
+ const field = useField()
187
182
 
188
183
  initialDate = getInitialDate(mode, initialDate)
189
184
 
@@ -285,7 +280,7 @@ export const DatePicker = ({
285
280
 
286
281
  const valueProps = {
287
282
  ...baseValueProps,
288
- id: uid,
283
+ id: id ?? field?.id,
289
284
  name: name,
290
285
  }
291
286
 
@@ -309,9 +304,9 @@ export const DatePicker = ({
309
304
  autoComplete="off"
310
305
  className="coop-datepicker-input"
311
306
  disabled={disabled}
312
- id={uid + componentConfig.fieldSuffix}
307
+ id={valueProps.id + "_display"}
313
308
  //maxLength={dateFormat.length}
314
- name={name + componentConfig.fieldSuffix}
309
+ name={name + "_display"}
315
310
  onChange={updateFromInput}
316
311
  placeholder={getPlaceholder()}
317
312
  ref={ref}
@@ -381,13 +376,13 @@ export const DatePicker = ({
381
376
  <>
382
377
  <input
383
378
  {...baseValueProps}
384
- id={`${uid}_start`}
379
+ id={`${valueProps.id}_start`}
385
380
  name={`${name}_start`}
386
381
  value={state.range?.field?.from ?? state.range?.input ?? ""}
387
382
  />
388
383
  <input
389
384
  {...baseValueProps}
390
- id={`${uid}_end`}
385
+ id={`${valueProps.id}_end`}
391
386
  name={`${name}_end`}
392
387
  value={state.range?.field?.to ?? state.range?.input ?? ""}
393
388
  />
@@ -397,6 +392,11 @@ export const DatePicker = ({
397
392
  )
398
393
  }
399
394
 
400
- DatePicker.config = componentConfig
395
+ DatePicker.slot = {
396
+ field: true,
397
+ name: "DatePicker",
398
+ suffix: "_display",
399
+ }
401
400
 
402
401
  export default DatePicker
402
+ export { DatePicker }
@@ -34,12 +34,7 @@ const componentSlots = {
34
34
  ExpandableSummary: null,
35
35
  }
36
36
 
37
- export const Expandable = ({
38
- children,
39
- className,
40
- ref,
41
- ...props
42
- }: ExpandableProps): JSX.Element => {
37
+ const Expandable = ({ children, className, ref, ...props }: ExpandableProps): JSX.Element => {
43
38
  const slots = useSlots(componentSlots, children)
44
39
 
45
40
  const componentProps = {
@@ -76,10 +71,12 @@ const ExpandableContent = ({ children, className, ...props }: ExpandableContentP
76
71
  )
77
72
  }
78
73
 
79
- ExpandableSummary.config = { name: "ExpandableSummary" }
80
- ExpandableContent.config = { name: "ExpandableContent" }
74
+ Expandable.slot = { name: "Expandable" }
75
+ ExpandableSummary.slot = { name: "ExpandableSummary" }
76
+ ExpandableContent.slot = { name: "ExpandableContent" }
81
77
 
82
78
  Expandable.Summary = ExpandableSummary
83
79
  Expandable.Content = ExpandableContent
84
80
 
85
81
  export default Expandable
82
+ export { Expandable, ExpandableContent, ExpandableSummary }
@@ -0,0 +1,29 @@
1
+ "use client"
2
+ import { createContext, useContext } from "react"
3
+
4
+ export interface FieldConfig {
5
+ disabled: boolean
6
+ id: string
7
+ inline?: boolean
8
+ suffix?: string
9
+ }
10
+
11
+ export interface FieldContextValue {
12
+ // register: ({ control, inline, suffix, uid }: FieldConfig) => void
13
+ disabled?: boolean
14
+ id?: string
15
+ inline?: boolean
16
+ suffix?: string
17
+ }
18
+
19
+ export const FieldContext = createContext<FieldContextValue | null>(null)
20
+
21
+ export const useField = () => {
22
+ const context = useContext(FieldContext)
23
+
24
+ if (!context) {
25
+ return null
26
+ }
27
+
28
+ return context
29
+ }
@@ -1,14 +1,17 @@
1
- import type { HTMLAttributes, HTMLProps, Ref } from "react"
1
+ "use client"
2
+ import type { HTMLAttributes, Ref } from "react"
2
3
 
3
4
  import clsx from "clsx"
4
5
  import React from "react"
5
6
 
6
7
  import { useId } from "../../hooks/useId"
7
8
  import { useSlots } from "../../hooks/useSlots"
8
- import { ReactNodeWithConfig } from "../../types"
9
+ import { SlotConfig } from "../../types"
10
+ import { getSlotProp } from "../../utils"
9
11
  import { Error as BaseError, type ErrorProps } from "../FieldMarkers/Error"
10
12
  import { Hint as BaseHint, type HintProps } from "../FieldMarkers/Hint"
11
13
  import { Label as BaseLabel, type LabelProps } from "../FieldMarkers/Label"
14
+ import { FieldConfig, FieldContext } from "./Field.context"
12
15
 
13
16
  const componentSlots = {
14
17
  Children: null,
@@ -35,7 +38,7 @@ interface FieldProps extends HTMLAttributes<HTMLDivElement> {
35
38
  ref?: Ref<HTMLDivElement>
36
39
  }
37
40
 
38
- export const Field = ({
41
+ const Field = ({
39
42
  boxed = false,
40
43
  children,
41
44
  className,
@@ -47,85 +50,87 @@ export const Field = ({
47
50
  const slots = { ...useSlots(componentSlots, children) }
48
51
  const hasMarkers = !!(slots.FieldLabel ?? slots.FieldError ?? slots.FieldHint)
49
52
 
50
- let isInline = false
51
- let control: ReactNodeWithConfig
52
- let controlSuffix = ""
53
- let controlId = useId()
54
- let controlDisabled = false
53
+ const internalId = useId()
55
54
 
56
- if (Array.isArray(slots.Children)) {
57
- slots.Children = slots.Children.filter((child: ReactNodeWithConfig) => {
58
- if (child?.type?.config?.isField) {
59
- control = child
60
- return false
61
- }
62
- return true
63
- })
55
+ const controlProps: FieldConfig = {
56
+ disabled: false,
57
+ id: internalId,
64
58
  }
65
59
 
66
- if (React.isValidElement(control)) {
67
- const controlProps = control.props as HTMLProps<HTMLElement>
60
+ if (Array.isArray(slots.Children)) {
61
+ slots.Children = slots.Children.filter((child: React.ReactNode) => {
62
+ //resolveComponentName(child)
68
63
 
69
- controlId = controlProps.id ?? controlId
70
- controlDisabled = controlProps.disabled ?? false
71
- controlSuffix = control?.type?.config?.fieldSuffix ?? ""
72
- isInline = control?.type?.config?.isInline ?? false
64
+ if (child && typeof child === "object" && "type" in child) {
65
+ if (typeof child?.type === "function" && "slot" in child.type) {
66
+ const { slot } = child?.type as { slot: SlotConfig }
73
67
 
74
- slots.Control = controlProps.id
75
- ? control
76
- : React.cloneElement(control as React.ReactElement<HTMLInputElement>, { id: controlId })
77
- }
68
+ slots.Control = child
78
69
 
79
- if (React.isValidElement(slots.FieldLabel) && !(slots.FieldLabel.props as LabelProps).htmlFor) {
80
- slots.FieldLabel = React.cloneElement(slots.FieldLabel as React.ReactElement<LabelProps>, {
81
- htmlFor: controlId + controlSuffix,
70
+ if (slots.Control.props) {
71
+ controlProps.inline = slot.inline ?? false
72
+ controlProps.disabled = getSlotProp<boolean>(slots.Control, "disabled") ?? false
73
+ controlProps.id = getSlotProp<string>(slots.Control, "id") ?? controlProps.id
74
+ controlProps.suffix = slot.suffix ?? undefined
75
+ }
76
+
77
+ return false
78
+ }
79
+ }
80
+
81
+ return true
82
82
  })
83
83
  }
84
84
 
85
85
  const componentProps = {
86
86
  ...props,
87
- "aria-disabled": controlDisabled || undefined,
88
- className: clsx("coop-field", isInline && "coop-field-inline", className),
87
+ "aria-disabled": controlProps.disabled || undefined,
88
+ className: clsx("coop-field", controlProps.inline && "coop-field-inline", className),
89
89
  "data-boxed": boxed || undefined,
90
90
  "data-error": error || undefined,
91
91
  "data-hide-error": hideErrorBar || undefined,
92
92
  }
93
93
 
94
94
  return (
95
- <div {...componentProps} ref={ref}>
96
- {!isInline && hasMarkers && (
97
- <div className="coop-field-markers">
98
- {slots.FieldLabel}
99
- {slots.FieldHint}
100
- {slots.FieldError}
101
- </div>
102
- )}
103
- {slots.Control && (
104
- <div className="coop-field-control">
105
- {slots.Control}
106
- {isInline && hasMarkers && (
107
- <div className="coop-field-markers">
108
- {slots.FieldLabel}
109
- {slots.FieldHint}
110
- {slots.FieldError}
111
- </div>
112
- )}
113
- </div>
114
- )}
115
- {slots.Children}
116
- </div>
95
+ <FieldContext.Provider value={{ ...controlProps }}>
96
+ <div {...componentProps} ref={ref}>
97
+ {!controlProps?.inline && hasMarkers && (
98
+ <div className="coop-field-markers">
99
+ {slots.FieldLabel}
100
+ {slots.FieldHint}
101
+ {slots.FieldError}
102
+ </div>
103
+ )}
104
+ {slots.Control && (
105
+ <div className="coop-field-control">
106
+ {slots.Control}
107
+ {controlProps?.inline && hasMarkers && (
108
+ <div className="coop-field-markers">
109
+ {slots.FieldLabel}
110
+ {slots.FieldHint}
111
+ {slots.FieldError}
112
+ </div>
113
+ )}
114
+ </div>
115
+ )}
116
+ {slots.Children}
117
+ </div>
118
+ </FieldContext.Provider>
117
119
  )
118
120
  }
121
+
119
122
  const FieldLabel = (props: LabelProps) => <BaseLabel {...props} />
120
123
  const FieldHint = (props: HintProps) => <BaseHint {...props} />
121
124
  const FieldError = (props: ErrorProps) => <BaseError {...props} />
122
125
 
123
- FieldLabel.config = { name: "FieldLabel" }
124
- FieldHint.config = { name: "FieldHint" }
125
- FieldError.config = { name: "FieldError" }
126
+ Field.slot = { name: "Field" }
127
+ FieldLabel.slot = { name: "FieldLabel" }
128
+ FieldHint.slot = { name: "FieldHint" }
129
+ FieldError.slot = { name: "FieldError" }
126
130
 
127
131
  Field.Label = FieldLabel
128
132
  Field.Hint = FieldHint
129
133
  Field.Error = FieldError
130
134
 
131
135
  export default Field
136
+ export { Field, FieldError, FieldHint, FieldLabel }
@@ -1,6 +1,8 @@
1
1
  import clsx from "clsx"
2
2
  import { LabelHTMLAttributes, Ref } from "react"
3
3
 
4
+ import { useField } from "../Field/Field.context"
5
+
4
6
  export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
5
7
  /** **(Optional)** Main label for the form element. Accepts any valid JSX or string. */
6
8
  children?: string | React.ReactNode
@@ -13,8 +15,10 @@ export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
13
15
  }
14
16
 
15
17
  export const Label = ({ children, className, isVisible = true, ref, ...props }: LabelProps) => {
18
+ const field = useField()
16
19
  const componentProps = {
17
20
  className: clsx("coop-field-label", !isVisible && "sr-only", className),
21
+ htmlFor: props.htmlFor ?? (field?.id ? field.id + (field?.suffix ?? "") : undefined),
18
22
  ...props,
19
23
  }
20
24
  return (