@navikt/ds-react 7.29.1 → 7.30.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 (241) hide show
  1. package/cjs/accordion/AccordionContent.js +1 -1
  2. package/cjs/accordion/AccordionContent.js.map +1 -1
  3. package/cjs/accordion/AccordionHeader.js +1 -1
  4. package/cjs/accordion/AccordionHeader.js.map +1 -1
  5. package/cjs/chips/Removable.js +1 -1
  6. package/cjs/chips/Removable.js.map +1 -1
  7. package/cjs/chips/Toggle.js +1 -1
  8. package/cjs/chips/Toggle.js.map +1 -1
  9. package/cjs/copybutton/CopyButton.js +8 -4
  10. package/cjs/copybutton/CopyButton.js.map +1 -1
  11. package/cjs/date/datepicker/parts/DatePicker.WeekNumber.js +1 -1
  12. package/cjs/date/datepicker/parts/DatePicker.WeekNumber.js.map +1 -1
  13. package/cjs/expansion-card/ExpansionCardContent.js +2 -1
  14. package/cjs/expansion-card/ExpansionCardContent.js.map +1 -1
  15. package/cjs/form/checkbox/Checkbox.js +42 -0
  16. package/cjs/form/checkbox/Checkbox.js.map +1 -1
  17. package/cjs/form/checkbox/useCheckbox.d.ts +2 -2
  18. package/cjs/form/checkbox/useCheckbox.js +5 -5
  19. package/cjs/form/checkbox/useCheckbox.js.map +1 -1
  20. package/cjs/form/form-summary/FormSummary.d.ts +11 -17
  21. package/cjs/form/form-summary/FormSummary.js +5 -1
  22. package/cjs/form/form-summary/FormSummary.js.map +1 -1
  23. package/cjs/form/form-summary/FormSummaryEditLink.js +6 -1
  24. package/cjs/form/form-summary/FormSummaryEditLink.js.map +1 -1
  25. package/cjs/form/form-summary/FormSummaryFooter.d.ts +12 -0
  26. package/cjs/form/form-summary/FormSummaryFooter.js +56 -0
  27. package/cjs/form/form-summary/FormSummaryFooter.js.map +1 -0
  28. package/cjs/form/form-summary/FormSummaryHeader.d.ts +1 -1
  29. package/cjs/form/form-summary/FormSummaryHeader.js +3 -1
  30. package/cjs/form/form-summary/FormSummaryHeader.js.map +1 -1
  31. package/cjs/form/form-summary/index.d.ts +1 -0
  32. package/cjs/form/form-summary/index.js +3 -1
  33. package/cjs/form/form-summary/index.js.map +1 -1
  34. package/cjs/form/radio/Radio.js +18 -0
  35. package/cjs/form/radio/Radio.js.map +1 -1
  36. package/cjs/form/radio/useRadio.d.ts +2 -2
  37. package/cjs/form/radio/useRadio.js +5 -5
  38. package/cjs/form/radio/useRadio.js.map +1 -1
  39. package/cjs/form/search/Search.js +1 -1
  40. package/cjs/form/search/Search.js.map +1 -1
  41. package/cjs/guide-panel/GuidePanel.js +3 -3
  42. package/cjs/guide-panel/GuidePanel.js.map +1 -1
  43. package/cjs/help-text/HelpText.js +1 -1
  44. package/cjs/help-text/HelpText.js.map +1 -1
  45. package/cjs/internal-header/InternalHeader.js +1 -1
  46. package/cjs/internal-header/InternalHeader.js.map +1 -1
  47. package/cjs/layout/base/BasePrimitive.js +1 -1
  48. package/cjs/layout/base/BasePrimitive.js.map +1 -1
  49. package/cjs/layout/bleed/Bleed.js +1 -1
  50. package/cjs/layout/bleed/Bleed.js.map +1 -1
  51. package/cjs/layout/box/Box.js +4 -4
  52. package/cjs/layout/box/Box.js.map +1 -1
  53. package/cjs/layout/grid/HGrid.js +1 -1
  54. package/cjs/layout/grid/HGrid.js.map +1 -1
  55. package/cjs/layout/page/Page.js +3 -1
  56. package/cjs/layout/page/Page.js.map +1 -1
  57. package/cjs/layout/stack/Stack.js +1 -1
  58. package/cjs/layout/stack/Stack.js.map +1 -1
  59. package/cjs/link/Link.js +1 -1
  60. package/cjs/link/Link.js.map +1 -1
  61. package/cjs/list/List.js +1 -1
  62. package/cjs/list/List.js.map +1 -1
  63. package/cjs/overlays/action-menu/ActionMenu.js +1 -1
  64. package/cjs/overlays/action-menu/ActionMenu.js.map +1 -1
  65. package/cjs/pagination/PaginationItem.js +1 -1
  66. package/cjs/pagination/PaginationItem.js.map +1 -1
  67. package/cjs/popover/Popover.js +2 -2
  68. package/cjs/popover/Popover.js.map +1 -1
  69. package/cjs/portal/Portal.js +1 -1
  70. package/cjs/portal/Portal.js.map +1 -1
  71. package/cjs/theme/Theme.d.ts +6 -1
  72. package/cjs/theme/Theme.js +10 -2
  73. package/cjs/theme/Theme.js.map +1 -1
  74. package/cjs/timeline/Pin.js +1 -1
  75. package/cjs/timeline/Pin.js.map +1 -1
  76. package/cjs/timeline/period/ClickablePeriod.js +1 -1
  77. package/cjs/timeline/period/ClickablePeriod.js.map +1 -1
  78. package/cjs/timeline/period/index.d.ts +1 -1
  79. package/cjs/timeline/period/index.js.map +1 -1
  80. package/cjs/timeline/utils/timeline.d.ts +7 -6
  81. package/cjs/timeline/utils/timeline.js +39 -62
  82. package/cjs/timeline/utils/timeline.js.map +1 -1
  83. package/cjs/timeline/utils/types.external.d.ts +2 -3
  84. package/cjs/timeline/utils/types.internal.d.ts +1 -1
  85. package/cjs/toggle-group/ToggleGroup.js +1 -1
  86. package/cjs/toggle-group/ToggleGroup.js.map +1 -1
  87. package/cjs/util/composition-warning/CompositionWarning.d.ts +37 -0
  88. package/cjs/util/composition-warning/CompositionWarning.js +71 -0
  89. package/cjs/util/composition-warning/CompositionWarning.js.map +1 -0
  90. package/cjs/util/composition-warning/index.d.ts +1 -0
  91. package/cjs/util/composition-warning/index.js +38 -0
  92. package/cjs/util/composition-warning/index.js.map +1 -0
  93. package/cjs/util/getChildRef.d.ts +1 -0
  94. package/cjs/util/getChildRef.js +8 -0
  95. package/cjs/util/getChildRef.js.map +1 -0
  96. package/cjs/util/renderStoriesForChromatic.d.ts +2 -10
  97. package/cjs/util/renderStoriesForChromatic.js +2 -2
  98. package/cjs/util/renderStoriesForChromatic.js.map +1 -1
  99. package/esm/accordion/AccordionContent.js +1 -1
  100. package/esm/accordion/AccordionContent.js.map +1 -1
  101. package/esm/accordion/AccordionHeader.js +1 -1
  102. package/esm/accordion/AccordionHeader.js.map +1 -1
  103. package/esm/chips/Removable.js +1 -1
  104. package/esm/chips/Removable.js.map +1 -1
  105. package/esm/chips/Toggle.js +1 -1
  106. package/esm/chips/Toggle.js.map +1 -1
  107. package/esm/copybutton/CopyButton.js +8 -4
  108. package/esm/copybutton/CopyButton.js.map +1 -1
  109. package/esm/date/datepicker/parts/DatePicker.WeekNumber.js +1 -1
  110. package/esm/date/datepicker/parts/DatePicker.WeekNumber.js.map +1 -1
  111. package/esm/expansion-card/ExpansionCardContent.js +3 -2
  112. package/esm/expansion-card/ExpansionCardContent.js.map +1 -1
  113. package/esm/form/checkbox/Checkbox.js +44 -2
  114. package/esm/form/checkbox/Checkbox.js.map +1 -1
  115. package/esm/form/checkbox/useCheckbox.d.ts +2 -2
  116. package/esm/form/checkbox/useCheckbox.js +5 -5
  117. package/esm/form/checkbox/useCheckbox.js.map +1 -1
  118. package/esm/form/form-summary/FormSummary.d.ts +11 -17
  119. package/esm/form/form-summary/FormSummary.js +5 -1
  120. package/esm/form/form-summary/FormSummary.js.map +1 -1
  121. package/esm/form/form-summary/FormSummaryEditLink.js +6 -1
  122. package/esm/form/form-summary/FormSummaryEditLink.js.map +1 -1
  123. package/esm/form/form-summary/FormSummaryFooter.d.ts +12 -0
  124. package/esm/form/form-summary/FormSummaryFooter.js +20 -0
  125. package/esm/form/form-summary/FormSummaryFooter.js.map +1 -0
  126. package/esm/form/form-summary/FormSummaryHeader.d.ts +1 -1
  127. package/esm/form/form-summary/FormSummaryHeader.js +3 -1
  128. package/esm/form/form-summary/FormSummaryHeader.js.map +1 -1
  129. package/esm/form/form-summary/index.d.ts +1 -0
  130. package/esm/form/form-summary/index.js +1 -0
  131. package/esm/form/form-summary/index.js.map +1 -1
  132. package/esm/form/radio/Radio.js +17 -2
  133. package/esm/form/radio/Radio.js.map +1 -1
  134. package/esm/form/radio/useRadio.d.ts +2 -2
  135. package/esm/form/radio/useRadio.js +5 -5
  136. package/esm/form/radio/useRadio.js.map +1 -1
  137. package/esm/form/search/Search.js +1 -1
  138. package/esm/form/search/Search.js.map +1 -1
  139. package/esm/guide-panel/GuidePanel.js +3 -3
  140. package/esm/guide-panel/GuidePanel.js.map +1 -1
  141. package/esm/help-text/HelpText.js +1 -1
  142. package/esm/help-text/HelpText.js.map +1 -1
  143. package/esm/internal-header/InternalHeader.js +1 -1
  144. package/esm/internal-header/InternalHeader.js.map +1 -1
  145. package/esm/layout/base/BasePrimitive.js +1 -1
  146. package/esm/layout/base/BasePrimitive.js.map +1 -1
  147. package/esm/layout/bleed/Bleed.js +1 -1
  148. package/esm/layout/bleed/Bleed.js.map +1 -1
  149. package/esm/layout/box/Box.js +4 -4
  150. package/esm/layout/box/Box.js.map +1 -1
  151. package/esm/layout/grid/HGrid.js +1 -1
  152. package/esm/layout/grid/HGrid.js.map +1 -1
  153. package/esm/layout/page/Page.js +3 -1
  154. package/esm/layout/page/Page.js.map +1 -1
  155. package/esm/layout/stack/Stack.js +1 -1
  156. package/esm/layout/stack/Stack.js.map +1 -1
  157. package/esm/link/Link.js +1 -1
  158. package/esm/link/Link.js.map +1 -1
  159. package/esm/list/List.js +1 -1
  160. package/esm/list/List.js.map +1 -1
  161. package/esm/overlays/action-menu/ActionMenu.js +1 -1
  162. package/esm/overlays/action-menu/ActionMenu.js.map +1 -1
  163. package/esm/pagination/PaginationItem.js +1 -1
  164. package/esm/pagination/PaginationItem.js.map +1 -1
  165. package/esm/popover/Popover.js +2 -2
  166. package/esm/popover/Popover.js.map +1 -1
  167. package/esm/portal/Portal.js +1 -1
  168. package/esm/portal/Portal.js.map +1 -1
  169. package/esm/theme/Theme.d.ts +6 -1
  170. package/esm/theme/Theme.js +10 -2
  171. package/esm/theme/Theme.js.map +1 -1
  172. package/esm/timeline/Pin.js +1 -1
  173. package/esm/timeline/Pin.js.map +1 -1
  174. package/esm/timeline/period/ClickablePeriod.js +1 -1
  175. package/esm/timeline/period/ClickablePeriod.js.map +1 -1
  176. package/esm/timeline/period/index.d.ts +1 -1
  177. package/esm/timeline/period/index.js.map +1 -1
  178. package/esm/timeline/utils/timeline.d.ts +7 -6
  179. package/esm/timeline/utils/timeline.js +39 -62
  180. package/esm/timeline/utils/timeline.js.map +1 -1
  181. package/esm/timeline/utils/types.external.d.ts +2 -3
  182. package/esm/timeline/utils/types.internal.d.ts +1 -1
  183. package/esm/toggle-group/ToggleGroup.js +1 -1
  184. package/esm/toggle-group/ToggleGroup.js.map +1 -1
  185. package/esm/util/composition-warning/CompositionWarning.d.ts +37 -0
  186. package/esm/util/composition-warning/CompositionWarning.js +34 -0
  187. package/esm/util/composition-warning/CompositionWarning.js.map +1 -0
  188. package/esm/util/composition-warning/index.d.ts +1 -0
  189. package/esm/util/composition-warning/index.js +2 -0
  190. package/esm/util/composition-warning/index.js.map +1 -0
  191. package/esm/util/getChildRef.d.ts +1 -0
  192. package/esm/util/getChildRef.js +4 -0
  193. package/esm/util/getChildRef.js.map +1 -0
  194. package/esm/util/renderStoriesForChromatic.d.ts +2 -10
  195. package/esm/util/renderStoriesForChromatic.js +2 -2
  196. package/esm/util/renderStoriesForChromatic.js.map +1 -1
  197. package/package.json +3 -3
  198. package/src/accordion/AccordionContent.tsx +1 -1
  199. package/src/accordion/AccordionHeader.tsx +1 -1
  200. package/src/chips/Removable.tsx +1 -1
  201. package/src/chips/Toggle.tsx +1 -1
  202. package/src/copybutton/CopyButton.tsx +8 -4
  203. package/src/date/datepicker/parts/DatePicker.WeekNumber.tsx +3 -1
  204. package/src/expansion-card/ExpansionCardContent.tsx +3 -1
  205. package/src/form/checkbox/Checkbox.tsx +91 -2
  206. package/src/form/checkbox/useCheckbox.ts +5 -5
  207. package/src/form/form-summary/FormSummary.tsx +12 -17
  208. package/src/form/form-summary/FormSummaryEditLink.tsx +16 -7
  209. package/src/form/form-summary/FormSummaryFooter.tsx +33 -0
  210. package/src/form/form-summary/FormSummaryHeader.tsx +12 -9
  211. package/src/form/form-summary/index.ts +4 -0
  212. package/src/form/radio/Radio.tsx +47 -2
  213. package/src/form/radio/useRadio.ts +5 -5
  214. package/src/form/search/Search.tsx +1 -1
  215. package/src/guide-panel/GuidePanel.tsx +3 -3
  216. package/src/help-text/HelpText.tsx +2 -2
  217. package/src/internal-header/InternalHeader.tsx +1 -1
  218. package/src/layout/base/BasePrimitive.tsx +1 -1
  219. package/src/layout/bleed/Bleed.tsx +1 -1
  220. package/src/layout/box/Box.tsx +5 -4
  221. package/src/layout/grid/HGrid.tsx +1 -1
  222. package/src/layout/page/Page.tsx +5 -1
  223. package/src/layout/stack/Stack.tsx +1 -1
  224. package/src/link/Link.tsx +1 -1
  225. package/src/list/List.tsx +1 -1
  226. package/src/overlays/action-menu/ActionMenu.tsx +1 -1
  227. package/src/pagination/PaginationItem.tsx +1 -1
  228. package/src/popover/Popover.tsx +2 -2
  229. package/src/portal/Portal.tsx +1 -1
  230. package/src/theme/Theme.tsx +14 -3
  231. package/src/timeline/Pin.tsx +1 -1
  232. package/src/timeline/period/ClickablePeriod.tsx +1 -1
  233. package/src/timeline/period/index.tsx +3 -1
  234. package/src/timeline/utils/timeline.ts +56 -67
  235. package/src/timeline/utils/types.external.ts +4 -3
  236. package/src/timeline/utils/types.internal.ts +3 -1
  237. package/src/toggle-group/ToggleGroup.tsx +1 -1
  238. package/src/util/composition-warning/CompositionWarning.tsx +67 -0
  239. package/src/util/composition-warning/index.ts +1 -0
  240. package/src/util/getChildRef.ts +6 -0
  241. package/src/util/renderStoriesForChromatic.tsx +12 -9
@@ -45,6 +45,8 @@ const RenameCSS = ({ children }: { children: React.ReactNode }) => {
45
45
  /* -------------------------------------------------------------------------- */
46
46
  /* Theme provider */
47
47
  /* -------------------------------------------------------------------------- */
48
+ const DEFAULT_COLOR: AkselColor = "accent";
49
+
48
50
  type ThemeContext = {
49
51
  /**
50
52
  * Color theme
@@ -52,12 +54,21 @@ type ThemeContext = {
52
54
  */
53
55
  theme?: "light" | "dark";
54
56
  color?: AkselColor;
57
+ /**
58
+ * Indicates if Theme-component is used or not.
59
+ * @default false
60
+ */
61
+ isDarkside: boolean;
55
62
  };
56
63
 
57
64
  const [ThemeProvider, useThemeInternal] = createContext<ThemeContext>({
58
65
  hookName: "useTheme",
59
66
  name: "ThemeProvider",
60
67
  providerName: "ThemeProvider",
68
+ defaultValue: {
69
+ color: DEFAULT_COLOR,
70
+ isDarkside: false,
71
+ },
61
72
  });
62
73
 
63
74
  export type ThemeProps = {
@@ -70,7 +81,7 @@ export type ThemeProps = {
70
81
  * Sets default 'base'-color for application
71
82
  */
72
83
  "data-color"?: AkselColor;
73
- } & Omit<ThemeContext, "color"> &
84
+ } & Omit<ThemeContext, "color" | "isDarkside"> &
74
85
  AsChildProps;
75
86
 
76
87
  const Theme = forwardRef<HTMLDivElement, ThemeProps>(
@@ -86,7 +97,7 @@ const Theme = forwardRef<HTMLDivElement, ThemeProps>(
86
97
  "data-color": color = context?.color,
87
98
  } = props;
88
99
 
89
- const isRoot = context === undefined;
100
+ const isRoot = !context?.isDarkside;
90
101
 
91
102
  const hasBackground =
92
103
  hasBackgroundProp ?? (isRoot && props.theme !== undefined);
@@ -94,7 +105,7 @@ const Theme = forwardRef<HTMLDivElement, ThemeProps>(
94
105
  const SlotElement = asChild ? Slot : "div";
95
106
 
96
107
  return (
97
- <ThemeProvider theme={theme} color={color}>
108
+ <ThemeProvider theme={theme} color={color} isDarkside={true}>
98
109
  <RenameCSS>
99
110
  <SlotElement
100
111
  ref={ref}
@@ -49,7 +49,7 @@ export const Pin = forwardRef<HTMLButtonElement, TimelinePinProps>(
49
49
  const translate = useI18n("Timeline");
50
50
 
51
51
  const themeContext = useThemeInternal(false);
52
- const showArrow = !themeContext;
52
+ const showArrow = !themeContext?.isDarkside;
53
53
 
54
54
  const {
55
55
  context,
@@ -61,7 +61,7 @@ const ClickablePeriod = React.memo(
61
61
  const translate = useI18n("Timeline");
62
62
 
63
63
  const themeContext = useThemeInternal(false);
64
- const showArrow = !themeContext;
64
+ const showArrow = !themeContext?.isDarkside;
65
65
 
66
66
  const {
67
67
  context,
@@ -32,7 +32,9 @@ export interface TimelinePeriodProps
32
32
  /**
33
33
  * Callback when selecting a period.
34
34
  */
35
- onSelectPeriod?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
35
+ onSelectPeriod?: (
36
+ event: React.MouseEvent<Element> | React.KeyboardEvent<Element>,
37
+ ) => void;
36
38
  /**
37
39
  * Content displayed in Popover on click.
38
40
  */
@@ -1,82 +1,71 @@
1
1
  import React, { ReactNode } from "react";
2
+ import type { TimelinePeriod, TimelineRow, TimelineRowProps } from "..";
2
3
  import { omit } from "../../util";
4
+ import { getChildRef } from "../../util/getChildRef";
3
5
  import { Period } from "./types.external";
4
6
 
5
- type ParsedChild = {
6
- label?: string;
7
+ type TimelineRowPropsWithRef = React.ComponentProps<typeof TimelineRow>;
8
+ type TimelinePeriodPropsWithRef = React.ComponentProps<typeof TimelinePeriod>;
9
+
10
+ type ParsedRow = {
11
+ label: string;
7
12
  icon?: React.ReactNode;
8
- headingTag: string;
13
+ headingTag?: string;
9
14
  periods: Omit<Period, "id" | "endInclusive">[];
10
- restProps: any;
11
- ref: any;
15
+ restProps: Omit<TimelineRowProps, "label" | "icon" | "headingTag">;
16
+ ref?: React.Ref<HTMLOListElement>;
12
17
  };
13
18
 
14
19
  export const parseRows = (rowChildren: ReactNode[]) => {
15
- const parsedChildren: ParsedChild[] = [];
16
- rowChildren?.forEach((r: React.ReactNode) => {
17
- const periods: ParsedChild["periods"] = [];
18
- if (React.isValidElement(r) && r?.props?.children) {
19
- if (Array.isArray(r.props.children)) {
20
- for (let i = 0; i < r.props.children.length; i++) {
21
- const p = r.props.children[i];
20
+ const parsedChildren: ParsedRow[] = [];
21
+
22
+ rowChildren?.forEach((row: React.ReactNode) => {
23
+ const periods: ParsedRow["periods"] = [];
24
+
25
+ if (
26
+ !React.isValidElement<TimelineRowPropsWithRef>(row) ||
27
+ !row.props.children
28
+ ) {
29
+ return;
30
+ }
22
31
 
23
- periods.push({
24
- start: p?.props?.start,
25
- end: p?.props?.end,
26
- status: p?.props?.status || "neutral",
27
- onSelectPeriod: p.props?.onSelectPeriod,
28
- label: r.props.label,
29
- icon: p.props.icon,
30
- children: p.props.children,
31
- isActive: p.props.isActive,
32
- statusLabel: p.props.statusLabel,
33
- restProps: omit(p.props, [
34
- "start",
35
- "end",
36
- "status",
37
- "onSelectPeriod",
38
- "label",
39
- "icon",
40
- "children",
41
- "isActive",
42
- "statusLabel",
43
- ]),
44
- ref: p?.ref,
45
- });
46
- }
47
- } else {
48
- periods.push({
49
- start: r.props.children.props.start,
50
- end: r.props.children.props.end,
51
- status: r.props.children.props?.status || "neutral",
52
- onSelectPeriod: r.props.children.props?.onSelectPeriod,
53
- label: r.props.label,
54
- icon: r.props.children.props?.icon,
55
- children: r.props.children.props?.children,
56
- statusLabel: r.props.children.props?.statusLabel,
57
- restProps: omit(r.props.children.props, [
58
- "start",
59
- "end",
60
- "status",
61
- "onSelectPeriod",
62
- "label",
63
- "icon",
64
- "children",
65
- "isActive",
66
- "statusLabel",
67
- ]),
68
- ref: r.props?.children?.ref,
69
- });
32
+ React.Children.toArray(row.props.children).forEach((period) => {
33
+ if (!React.isValidElement<TimelinePeriodPropsWithRef>(period)) {
34
+ return;
70
35
  }
71
- parsedChildren.push({
72
- label: r.props.label,
73
- icon: r.props.icon,
74
- headingTag: r.props.headingTag,
75
- periods,
76
- restProps: omit(r.props, ["label", "icon", "headingTag"]),
77
- ref: (r as any)?.ref,
36
+
37
+ periods.push({
38
+ start: period.props.start,
39
+ end: period.props.end,
40
+ status: period.props.status || "neutral",
41
+ onSelectPeriod: period.props.onSelectPeriod,
42
+ icon: period.props.icon,
43
+ children: period.props.children,
44
+ isActive: period.props.isActive,
45
+ statusLabel: period.props.statusLabel,
46
+ restProps: omit(period.props, [
47
+ "start",
48
+ "end",
49
+ "status",
50
+ "onSelectPeriod",
51
+ "icon",
52
+ "children",
53
+ "isActive",
54
+ "statusLabel",
55
+ "placement",
56
+ ]),
57
+ ref: getChildRef(period),
78
58
  });
79
- }
59
+ });
60
+
61
+ parsedChildren.push({
62
+ label: row.props.label,
63
+ icon: row.props.icon,
64
+ headingTag: row.props.headingTag,
65
+ periods,
66
+ restProps: omit(row.props, ["label", "icon", "headingTag"]),
67
+ ref: getChildRef(row),
68
+ });
80
69
  });
81
70
 
82
71
  return parsedChildren;
@@ -16,18 +16,19 @@ export interface Positioned {
16
16
 
17
17
  export interface Period {
18
18
  id: string;
19
- label?: string;
20
19
  start: Date;
21
20
  endInclusive: Date;
22
21
  status?: PeriodStatus;
23
- onSelectPeriod?: () => void;
22
+ onSelectPeriod?: (
23
+ e: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>,
24
+ ) => void;
24
25
  icon?: React.ReactNode;
25
26
  children?: React.ReactNode;
26
27
  end: Date;
27
28
  isActive?: boolean;
28
29
  statusLabel?: string;
29
30
  restProps?: any;
30
- ref?: Element;
31
+ ref?: React.Ref<HTMLDivElement | HTMLButtonElement>;
31
32
  }
32
33
 
33
34
  export interface PositionedPeriod extends Period, Positioned {
@@ -21,7 +21,9 @@ export interface Period {
21
21
  start: Date;
22
22
  endInclusive: Date;
23
23
  status?: PeriodStatus;
24
- onSelectPeriod?: () => void;
24
+ onSelectPeriod?: (
25
+ e: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element>,
26
+ ) => void;
25
27
  icon?: React.ReactNode;
26
28
  children?: React.ReactNode;
27
29
  isActive?: boolean;
@@ -84,7 +84,7 @@ export const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(
84
84
 
85
85
  let localVariant: ToggleGroupProps["variant"] | undefined;
86
86
 
87
- if (themeContext) {
87
+ if (themeContext?.isDarkside) {
88
88
  localVariant = variant;
89
89
  } else {
90
90
  localVariant = variant ?? "action";
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Give warnings based on component composition (which slot/parent a child is rendered in).
3
+ *
4
+ * Used when child components need to know which slot/parent they are rendered in
5
+ * (e.g. `FormSummary.Header` vs `FormSummary.Footer`) and should warn or error in development
6
+ * if placed in a discouraged or forbidden slot.
7
+ *
8
+ * Usage:
9
+ * - Wrap slot components with <CompositionWarning.Root name="FormSummary.Header">...</CompositionWarning.Root>
10
+ * - In child: `<CompositionWarning.Forbidden name="FormSummary.Header" />` to forbid slot.
11
+ *
12
+ * This is guidance only: warnings are logged to the console in development, never enforced at runtime.
13
+ */
14
+ import React, { useEffect, useRef } from "react";
15
+ import { Slot } from "../../slot/Slot";
16
+ import { createContext } from "../create-context";
17
+
18
+ type CompositionName = string;
19
+
20
+ const isDev = process.env.NODE_ENV !== "production";
21
+
22
+ type CompositionWarningContextType = {
23
+ /**
24
+ * Name of the slot component we want to check.
25
+ */
26
+ name: CompositionName;
27
+ };
28
+
29
+ const [CompositionWarning, useCompositionWarning] =
30
+ createContext<CompositionWarningContextType>({
31
+ errorMessage:
32
+ "useCompositionWarning() must be used within <CompositionWarning />",
33
+ });
34
+
35
+ type CompositionWarningForbiddenProps = {
36
+ children?: React.ReactElement;
37
+ /**
38
+ * Name of the parent slot component where the child is not allowed.
39
+ */
40
+ name: CompositionName;
41
+ /**
42
+ * Warning message to display if the child is found.
43
+ */
44
+ message: string;
45
+ };
46
+
47
+ function CompositionWarningForbidden({
48
+ children,
49
+ name,
50
+ message,
51
+ }: CompositionWarningForbiddenProps) {
52
+ const compositionName = useCompositionWarning(false)?.name;
53
+
54
+ const elementRef = useRef<HTMLElement>(null);
55
+
56
+ useEffect(() => {
57
+ if (!isDev || !compositionName || name !== compositionName) {
58
+ return;
59
+ }
60
+
61
+ console.warn(`[Aksel] ${message}\nElement: `, elementRef.current);
62
+ }, [compositionName, name, message]);
63
+
64
+ return <Slot ref={elementRef}>{children}</Slot>;
65
+ }
66
+
67
+ export { CompositionWarningForbidden as Forbidden, CompositionWarning as Root };
@@ -0,0 +1 @@
1
+ export * as CompositionWarning from "./CompositionWarning";
@@ -0,0 +1,6 @@
1
+ export const getChildRef = <T>(
2
+ children: React.ReactElement<React.RefAttributes<T>>,
3
+ ): React.Ref<T> | undefined =>
4
+ Object.prototype.propertyIsEnumerable.call(children.props, "ref")
5
+ ? (children.props as any).ref // React 19 (children.ref still works, but gives a warning)
6
+ : (children as any).ref; // React <19
@@ -1,4 +1,4 @@
1
- import { Args } from "@storybook/react";
1
+ import { Args, StoryObj } from "@storybook/react";
2
2
  import React from "react";
3
3
  import { Renderer, StoryContext } from "storybook/internal/types";
4
4
 
@@ -8,15 +8,18 @@ export function renderStoriesForChromatic(
8
8
  | { render?: (...args: any[]) => React.ReactNode }
9
9
  | React.FunctionComponent<void>
10
10
  >,
11
- ) {
11
+ ): StoryObj {
12
12
  return {
13
- render: (...args: [Args, StoryContext<Renderer, Args>]) =>
14
- Object.entries(stories).map(([storyName, story]) => (
15
- <div key={storyName}>
16
- <h2 className="storyheading">{storyName}</h2>
17
- {typeof story === "function" ? story() : story.render?.(...args)}
18
- </div>
19
- )),
13
+ render: (...args: [Args, StoryContext<Renderer, Args>]) => (
14
+ <>
15
+ {Object.entries(stories).map(([storyName, story]) => (
16
+ <div key={storyName}>
17
+ <h2 className="storyheading">{storyName}</h2>
18
+ {typeof story === "function" ? story() : story.render?.(...args)}
19
+ </div>
20
+ ))}
21
+ </>
22
+ ),
20
23
  parameters: {
21
24
  chromatic: { disable: false },
22
25
  },