@navikt/ds-react 3.4.2 → 4.0.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 (234) hide show
  1. package/_docs.json +5615 -3780
  2. package/cjs/date/hooks/index.js +4 -4
  3. package/cjs/date/index.js +6 -6
  4. package/cjs/dropdown/Dropdown.js +57 -0
  5. package/cjs/dropdown/Menu/Divider.js +47 -0
  6. package/cjs/dropdown/Menu/GroupedList/Heading.js +47 -0
  7. package/cjs/dropdown/Menu/GroupedList/Item.js +54 -0
  8. package/cjs/dropdown/Menu/GroupedList/index.js +51 -0
  9. package/cjs/dropdown/Menu/GroupedList/package.json +6 -0
  10. package/cjs/dropdown/Menu/List/Item.js +54 -0
  11. package/cjs/dropdown/Menu/List/index.js +49 -0
  12. package/cjs/dropdown/Menu/List/package.json +6 -0
  13. package/cjs/dropdown/Menu/index.js +64 -0
  14. package/cjs/dropdown/Menu/package.json +6 -0
  15. package/cjs/dropdown/Toggle.js +66 -0
  16. package/cjs/dropdown/index.js +23 -0
  17. package/cjs/dropdown/package.json +6 -0
  18. package/cjs/form/radio/RadioGroup.js +10 -0
  19. package/cjs/index.js +3 -0
  20. package/cjs/internal-header/InternalHeader.js +55 -0
  21. package/cjs/internal-header/InternalHeaderButton.js +47 -0
  22. package/cjs/internal-header/InternalHeaderTitle.js +48 -0
  23. package/cjs/internal-header/InternalHeaderUser.js +51 -0
  24. package/cjs/internal-header/InternalHeaderUserButton.js +54 -0
  25. package/cjs/internal-header/index.js +8 -0
  26. package/cjs/internal-header/package.json +6 -0
  27. package/cjs/read-more/ReadMore.js +17 -0
  28. package/cjs/timeline/AxisLabels.js +90 -0
  29. package/cjs/timeline/Pin.js +106 -0
  30. package/cjs/timeline/Timeline.js +162 -0
  31. package/cjs/timeline/TimelineRow.js +86 -0
  32. package/cjs/timeline/hooks/usePeriodContext.js +16 -0
  33. package/cjs/timeline/hooks/useRowContext.js +18 -0
  34. package/cjs/timeline/hooks/useTimelineContext.js +23 -0
  35. package/cjs/timeline/hooks/useTimelineRows.js +79 -0
  36. package/cjs/timeline/index.js +8 -0
  37. package/cjs/timeline/package.json +6 -0
  38. package/cjs/timeline/period/ClickablePeriod.js +120 -0
  39. package/cjs/timeline/period/NonClickablePeriod.js +18 -0
  40. package/cjs/timeline/period/index.js +46 -0
  41. package/cjs/timeline/period/package.json +6 -0
  42. package/cjs/timeline/utils/calc.js +19 -0
  43. package/cjs/timeline/utils/filter.js +18 -0
  44. package/cjs/timeline/utils/index.js +7 -0
  45. package/cjs/timeline/utils/package.json +6 -0
  46. package/cjs/timeline/utils/period.js +40 -0
  47. package/cjs/timeline/utils/sort.js +10 -0
  48. package/cjs/timeline/utils/timeline.js +79 -0
  49. package/cjs/timeline/utils/types.external.js +2 -0
  50. package/cjs/timeline/utils/types.internal.js +2 -0
  51. package/cjs/timeline/zoom/ZoomButton.js +68 -0
  52. package/cjs/timeline/zoom/index.js +50 -0
  53. package/cjs/timeline/zoom/package.json +6 -0
  54. package/esm/date/hooks/index.d.ts +3 -3
  55. package/esm/date/hooks/index.js +3 -3
  56. package/esm/date/hooks/index.js.map +1 -1
  57. package/esm/date/index.d.ts +3 -3
  58. package/esm/date/index.js +3 -3
  59. package/esm/date/index.js.map +1 -1
  60. package/esm/dropdown/Dropdown.d.ts +37 -0
  61. package/esm/dropdown/Dropdown.js +29 -0
  62. package/esm/dropdown/Dropdown.js.map +1 -0
  63. package/esm/dropdown/Menu/Divider.d.ts +4 -0
  64. package/esm/dropdown/Menu/Divider.js +19 -0
  65. package/esm/dropdown/Menu/Divider.js.map +1 -0
  66. package/esm/dropdown/Menu/GroupedList/Heading.d.ts +10 -0
  67. package/esm/dropdown/Menu/GroupedList/Heading.js +19 -0
  68. package/esm/dropdown/Menu/GroupedList/Heading.js.map +1 -0
  69. package/esm/dropdown/Menu/GroupedList/Item.d.ts +11 -0
  70. package/esm/dropdown/Menu/GroupedList/Item.js +26 -0
  71. package/esm/dropdown/Menu/GroupedList/Item.js.map +1 -0
  72. package/esm/dropdown/Menu/GroupedList/index.d.ts +15 -0
  73. package/esm/dropdown/Menu/GroupedList/index.js +23 -0
  74. package/esm/dropdown/Menu/GroupedList/index.js.map +1 -0
  75. package/esm/dropdown/Menu/List/Item.d.ts +11 -0
  76. package/esm/dropdown/Menu/List/Item.js +26 -0
  77. package/esm/dropdown/Menu/List/Item.js.map +1 -0
  78. package/esm/dropdown/Menu/List/index.d.ts +13 -0
  79. package/esm/dropdown/Menu/List/index.js +21 -0
  80. package/esm/dropdown/Menu/List/index.js.map +1 -0
  81. package/esm/dropdown/Menu/index.d.ts +27 -0
  82. package/esm/dropdown/Menu/index.js +36 -0
  83. package/esm/dropdown/Menu/index.js.map +1 -0
  84. package/esm/dropdown/Toggle.d.ts +10 -0
  85. package/esm/dropdown/Toggle.js +38 -0
  86. package/esm/dropdown/Toggle.js.map +1 -0
  87. package/esm/dropdown/index.d.ts +2 -0
  88. package/esm/dropdown/index.js +3 -0
  89. package/esm/dropdown/index.js.map +1 -0
  90. package/esm/form/radio/RadioGroup.d.ts +10 -0
  91. package/esm/form/radio/RadioGroup.js +10 -0
  92. package/esm/form/radio/RadioGroup.js.map +1 -1
  93. package/esm/index.d.ts +3 -0
  94. package/esm/index.js +3 -0
  95. package/esm/index.js.map +1 -1
  96. package/esm/internal-header/InternalHeader.d.ts +16 -0
  97. package/esm/internal-header/InternalHeader.js +27 -0
  98. package/esm/internal-header/InternalHeader.js.map +1 -0
  99. package/esm/internal-header/InternalHeaderButton.d.ts +11 -0
  100. package/esm/internal-header/InternalHeaderButton.js +19 -0
  101. package/esm/internal-header/InternalHeaderButton.js.map +1 -0
  102. package/esm/internal-header/InternalHeaderTitle.d.ts +11 -0
  103. package/esm/internal-header/InternalHeaderTitle.js +20 -0
  104. package/esm/internal-header/InternalHeaderTitle.js.map +1 -0
  105. package/esm/internal-header/InternalHeaderUser.d.ts +14 -0
  106. package/esm/internal-header/InternalHeaderUser.js +23 -0
  107. package/esm/internal-header/InternalHeaderUser.js.map +1 -0
  108. package/esm/internal-header/InternalHeaderUserButton.d.ts +15 -0
  109. package/esm/internal-header/InternalHeaderUserButton.js +26 -0
  110. package/esm/internal-header/InternalHeaderUserButton.js.map +1 -0
  111. package/esm/internal-header/index.d.ts +5 -0
  112. package/esm/internal-header/index.js +2 -0
  113. package/esm/internal-header/index.js.map +1 -0
  114. package/esm/read-more/ReadMore.d.ts +17 -0
  115. package/esm/read-more/ReadMore.js +17 -0
  116. package/esm/read-more/ReadMore.js.map +1 -1
  117. package/esm/timeline/AxisLabels.d.ts +6 -0
  118. package/esm/timeline/AxisLabels.js +81 -0
  119. package/esm/timeline/AxisLabels.js.map +1 -0
  120. package/esm/timeline/Pin.d.ts +17 -0
  121. package/esm/timeline/Pin.js +81 -0
  122. package/esm/timeline/Pin.js.map +1 -0
  123. package/esm/timeline/Timeline.d.ts +45 -0
  124. package/esm/timeline/Timeline.js +134 -0
  125. package/esm/timeline/Timeline.js.map +1 -0
  126. package/esm/timeline/TimelineRow.d.ts +22 -0
  127. package/esm/timeline/TimelineRow.js +58 -0
  128. package/esm/timeline/TimelineRow.js.map +1 -0
  129. package/esm/timeline/hooks/usePeriodContext.d.ts +9 -0
  130. package/esm/timeline/hooks/usePeriodContext.js +13 -0
  131. package/esm/timeline/hooks/usePeriodContext.js.map +1 -0
  132. package/esm/timeline/hooks/useRowContext.d.ts +11 -0
  133. package/esm/timeline/hooks/useRowContext.js +15 -0
  134. package/esm/timeline/hooks/useRowContext.js.map +1 -0
  135. package/esm/timeline/hooks/useTimelineContext.d.ts +15 -0
  136. package/esm/timeline/hooks/useTimelineContext.js +20 -0
  137. package/esm/timeline/hooks/useTimelineContext.js.map +1 -0
  138. package/esm/timeline/hooks/useTimelineRows.d.ts +4 -0
  139. package/esm/timeline/hooks/useTimelineRows.js +74 -0
  140. package/esm/timeline/hooks/useTimelineRows.js.map +1 -0
  141. package/esm/timeline/index.d.ts +6 -0
  142. package/esm/timeline/index.js +2 -0
  143. package/esm/timeline/index.js.map +1 -0
  144. package/esm/timeline/period/ClickablePeriod.d.ts +9 -0
  145. package/esm/timeline/period/ClickablePeriod.js +93 -0
  146. package/esm/timeline/period/ClickablePeriod.js.map +1 -0
  147. package/esm/timeline/period/NonClickablePeriod.d.ts +7 -0
  148. package/esm/timeline/period/NonClickablePeriod.js +14 -0
  149. package/esm/timeline/period/NonClickablePeriod.js.map +1 -0
  150. package/esm/timeline/period/index.d.ts +57 -0
  151. package/esm/timeline/period/index.js +18 -0
  152. package/esm/timeline/period/index.js.map +1 -0
  153. package/esm/timeline/utils/calc.d.ts +5 -0
  154. package/esm/timeline/utils/calc.js +15 -0
  155. package/esm/timeline/utils/calc.js.map +1 -0
  156. package/esm/timeline/utils/filter.d.ts +10 -0
  157. package/esm/timeline/utils/filter.js +11 -0
  158. package/esm/timeline/utils/filter.js.map +1 -0
  159. package/esm/timeline/utils/index.d.ts +1 -0
  160. package/esm/timeline/utils/index.js +2 -0
  161. package/esm/timeline/utils/index.js.map +1 -0
  162. package/esm/timeline/utils/period.d.ts +2 -0
  163. package/esm/timeline/utils/period.js +33 -0
  164. package/esm/timeline/utils/period.js.map +1 -0
  165. package/esm/timeline/utils/sort.d.ts +4 -0
  166. package/esm/timeline/utils/sort.js +5 -0
  167. package/esm/timeline/utils/sort.js.map +1 -0
  168. package/esm/timeline/utils/timeline.d.ts +12 -0
  169. package/esm/timeline/utils/timeline.js +73 -0
  170. package/esm/timeline/utils/timeline.js.map +1 -0
  171. package/esm/timeline/utils/types.external.d.ts +53 -0
  172. package/esm/timeline/utils/types.external.js +2 -0
  173. package/esm/timeline/utils/types.external.js.map +1 -0
  174. package/esm/timeline/utils/types.internal.d.ts +61 -0
  175. package/esm/timeline/utils/types.internal.js +2 -0
  176. package/esm/timeline/utils/types.internal.js.map +1 -0
  177. package/esm/timeline/zoom/ZoomButton.d.ts +19 -0
  178. package/esm/timeline/zoom/ZoomButton.js +43 -0
  179. package/esm/timeline/zoom/ZoomButton.js.map +1 -0
  180. package/esm/timeline/zoom/index.d.ts +11 -0
  181. package/esm/timeline/zoom/index.js +22 -0
  182. package/esm/timeline/zoom/index.js.map +1 -0
  183. package/package.json +2 -2
  184. package/src/date/datepicker/datepicker.stories.tsx +19 -21
  185. package/src/date/datepicker/datepicker.test.tsx +5 -5
  186. package/src/date/hooks/index.ts +3 -3
  187. package/src/date/hooks/useRangeDatepicker.test.tsx +6 -6
  188. package/src/date/index.ts +5 -5
  189. package/src/date/monthpicker/monthpicker.stories.tsx +5 -5
  190. package/src/date/utils/__tests__/get-dates.test.ts +0 -1
  191. package/src/dropdown/Dropdown.tsx +80 -0
  192. package/src/dropdown/Menu/Divider.tsx +18 -0
  193. package/src/dropdown/Menu/GroupedList/Heading.tsx +31 -0
  194. package/src/dropdown/Menu/GroupedList/Item.tsx +45 -0
  195. package/src/dropdown/Menu/GroupedList/index.tsx +33 -0
  196. package/src/dropdown/Menu/List/Item.tsx +44 -0
  197. package/src/dropdown/Menu/List/index.tsx +27 -0
  198. package/src/dropdown/Menu/index.tsx +85 -0
  199. package/src/dropdown/Toggle.tsx +52 -0
  200. package/src/dropdown/dropdown.stories.tsx +91 -0
  201. package/src/dropdown/index.ts +2 -0
  202. package/src/form/radio/RadioGroup.tsx +10 -0
  203. package/src/index.ts +3 -0
  204. package/src/internal-header/InternalHeader.tsx +44 -0
  205. package/src/internal-header/InternalHeaderButton.tsx +28 -0
  206. package/src/internal-header/InternalHeaderTitle.tsx +35 -0
  207. package/src/internal-header/InternalHeaderUser.tsx +39 -0
  208. package/src/internal-header/InternalHeaderUserButton.tsx +43 -0
  209. package/src/internal-header/header.stories.tsx +225 -0
  210. package/src/internal-header/index.ts +8 -0
  211. package/src/read-more/ReadMore.tsx +17 -0
  212. package/src/timeline/AxisLabels.tsx +143 -0
  213. package/src/timeline/Pin.tsx +169 -0
  214. package/src/timeline/Timeline.tsx +219 -0
  215. package/src/timeline/TimelineRow.tsx +122 -0
  216. package/src/timeline/hooks/usePeriodContext.tsx +22 -0
  217. package/src/timeline/hooks/useRowContext.tsx +26 -0
  218. package/src/timeline/hooks/useTimelineContext.tsx +37 -0
  219. package/src/timeline/hooks/useTimelineRows.ts +161 -0
  220. package/src/timeline/index.ts +6 -0
  221. package/src/timeline/period/ClickablePeriod.tsx +193 -0
  222. package/src/timeline/period/NonClickablePeriod.tsx +46 -0
  223. package/src/timeline/period/index.tsx +130 -0
  224. package/src/timeline/timeline.stories.tsx +444 -0
  225. package/src/timeline/utils/calc.ts +26 -0
  226. package/src/timeline/utils/filter.ts +32 -0
  227. package/src/timeline/utils/index.ts +6 -0
  228. package/src/timeline/utils/period.ts +48 -0
  229. package/src/timeline/utils/sort.ts +11 -0
  230. package/src/timeline/utils/timeline.ts +83 -0
  231. package/src/timeline/utils/types.external.ts +67 -0
  232. package/src/timeline/utils/types.internal.ts +76 -0
  233. package/src/timeline/zoom/ZoomButton.tsx +83 -0
  234. package/src/timeline/zoom/index.tsx +30 -0
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
2
  import React, { useId, useState } from "react";
3
- import { UNSAFE_useDatepicker, UNSAFE_useRangeDatepicker } from "..";
3
+ import { useDatepicker, useRangeDatepicker } from "..";
4
4
  import { Button } from "../..";
5
5
  import DatePicker from "./DatePicker";
6
6
 
@@ -18,12 +18,12 @@ export const Default = {
18
18
  render: (props) => {
19
19
  const [open, setOpen] = useState(false);
20
20
 
21
- const rangeCtx = UNSAFE_useRangeDatepicker({
21
+ const rangeCtx = useRangeDatepicker({
22
22
  fromDate: new Date("Aug 23 2020"),
23
23
  toDate: new Date("Aug 23 2023"),
24
24
  });
25
25
 
26
- const singleCtx = UNSAFE_useDatepicker({
26
+ const singleCtx = useDatepicker({
27
27
  fromDate: new Date("Aug 23 2020"),
28
28
  toDate: new Date("Aug 23 2023"),
29
29
  });
@@ -147,7 +147,7 @@ export const ShowWeekNumber = () => (
147
147
  );
148
148
 
149
149
  export const UseDatepicker = () => {
150
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
150
+ const { datepickerProps, inputProps } = useDatepicker({
151
151
  fromDate: new Date("Aug 23 2019"),
152
152
  toDate: new Date("Feb 23 2024"),
153
153
  onDateChange: console.log,
@@ -163,12 +163,11 @@ export const UseDatepicker = () => {
163
163
  };
164
164
 
165
165
  export const UseRangedDatepicker = () => {
166
- const { datepickerProps, fromInputProps, toInputProps } =
167
- UNSAFE_useRangeDatepicker({
168
- fromDate: new Date("Aug 23 2019"),
169
- onRangeChange: console.log,
170
- onValidate: console.log,
171
- });
166
+ const { datepickerProps, fromInputProps, toInputProps } = useRangeDatepicker({
167
+ fromDate: new Date("Aug 23 2019"),
168
+ onRangeChange: console.log,
169
+ onValidate: console.log,
170
+ });
172
171
 
173
172
  return (
174
173
  <div style={{ display: "flex", gap: "1rem" }}>
@@ -183,7 +182,7 @@ export const UseRangedDatepicker = () => {
183
182
  };
184
183
 
185
184
  export const OpenOnFocus = () => {
186
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
185
+ const { datepickerProps, inputProps } = useDatepicker({
187
186
  onDateChange: console.log,
188
187
  openOnFocus: false,
189
188
  });
@@ -243,7 +242,7 @@ export const UserControlled = () => {
243
242
 
244
243
  export const Validering = () => {
245
244
  const [error, setError] = useState(false);
246
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
245
+ const { datepickerProps, inputProps } = useDatepicker({
247
246
  fromDate: new Date("Aug 2 2019"),
248
247
  onValidate: (val) => setError(val.isWeekend),
249
248
  defaultSelected: new Date("Nov 26 2022"),
@@ -289,13 +288,12 @@ export const ErrorInput = () => {
289
288
  };
290
289
 
291
290
  export const UseRangedDatepickerValidation = () => {
292
- const { datepickerProps, fromInputProps, toInputProps } =
293
- UNSAFE_useRangeDatepicker({
294
- fromDate: new Date("Aug 23 2019"),
295
- disableWeekends: true,
296
- disabled: [new Date("Oct 10 2022")],
297
- onValidate: console.table,
298
- });
291
+ const { datepickerProps, fromInputProps, toInputProps } = useRangeDatepicker({
292
+ fromDate: new Date("Aug 23 2019"),
293
+ disableWeekends: true,
294
+ disabled: [new Date("Oct 10 2022")],
295
+ onValidate: console.table,
296
+ });
299
297
 
300
298
  return (
301
299
  <div style={{ display: "flex", gap: "1rem" }}>
@@ -310,7 +308,7 @@ export const UseRangedDatepickerValidation = () => {
310
308
  };
311
309
 
312
310
  export const defaultShownMonth = () => {
313
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
311
+ const { datepickerProps, inputProps } = useDatepicker({
314
312
  fromDate: new Date("Aug 23 2019"),
315
313
  onDateChange: console.log,
316
314
  defaultMonth: new Date("Oct 23 2022"),
@@ -326,7 +324,7 @@ export const defaultShownMonth = () => {
326
324
  };
327
325
 
328
326
  export const Size = () => {
329
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
327
+ const { datepickerProps, inputProps } = useDatepicker({
330
328
  fromDate: new Date("Aug 23 2019"),
331
329
  toDate: new Date("Feb 23 2024"),
332
330
  onDateChange: console.log,
@@ -2,18 +2,18 @@
2
2
  import { act, render } from "@testing-library/react";
3
3
  import userEvent from "@testing-library/user-event";
4
4
  import React from "react";
5
- import { UNSAFE_DatePicker, UNSAFE_useDatepicker } from "..";
5
+ import { DatePicker, useDatepicker } from "..";
6
6
 
7
7
  const App = () => {
8
- const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
8
+ const { datepickerProps, inputProps } = useDatepicker({
9
9
  fromDate: new Date("Aug 23 2019"),
10
10
  onDateChange: console.log,
11
11
  });
12
12
 
13
13
  return (
14
- <UNSAFE_DatePicker {...datepickerProps}>
15
- <UNSAFE_DatePicker.Input {...inputProps} label="Velg dato" />
16
- </UNSAFE_DatePicker>
14
+ <DatePicker {...datepickerProps}>
15
+ <DatePicker.Input {...inputProps} label="Velg dato" />
16
+ </DatePicker>
17
17
  );
18
18
  };
19
19
 
@@ -1,6 +1,6 @@
1
- export { useDatepicker as UNSAFE_useDatepicker } from "./useDatepicker";
1
+ export { useDatepicker } from "./useDatepicker";
2
2
  export type { DateValidationT } from "./useDatepicker";
3
- export { useRangeDatepicker as UNSAFE_useRangeDatepicker } from "./useRangeDatepicker";
3
+ export { useRangeDatepicker } from "./useRangeDatepicker";
4
4
  export type { RangeValidationT } from "./useRangeDatepicker";
5
- export { useMonthpicker as UNSAFE_useMonthpicker } from "./useMonthPicker";
5
+ export { useMonthpicker } from "./useMonthPicker";
6
6
  export type { MonthValidationT } from "./useMonthPicker";
@@ -2,20 +2,20 @@
2
2
  import { act, render } from "@testing-library/react";
3
3
  import userEvent from "@testing-library/user-event";
4
4
  import React from "react";
5
- import { UNSAFE_DatePicker, UNSAFE_useRangeDatepicker } from "..";
5
+ import { DatePicker, useRangeDatepicker } from "..";
6
6
 
7
7
  const RangeDemo = () => {
8
8
  const { datepickerProps, fromInputProps, selectedRange, toInputProps } =
9
- UNSAFE_useRangeDatepicker({
9
+ useRangeDatepicker({
10
10
  fromDate: new Date("Aug 23 2019"),
11
11
  });
12
12
 
13
13
  return (
14
14
  <div style={{ display: "flex", gap: "1rem" }}>
15
- <UNSAFE_DatePicker {...datepickerProps}>
16
- <UNSAFE_DatePicker.Input {...fromInputProps} label="Fra" />
17
- <UNSAFE_DatePicker.Input {...toInputProps} label="Til" />
18
- </UNSAFE_DatePicker>
15
+ <DatePicker {...datepickerProps}>
16
+ <DatePicker.Input {...fromInputProps} label="Fra" />
17
+ <DatePicker.Input {...toInputProps} label="Til" />
18
+ </DatePicker>
19
19
  <div title="res">{JSON.stringify(selectedRange)}</div>
20
20
  </div>
21
21
  );
package/src/date/index.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  export { type DateInputProps } from "./DateInput";
2
2
  export {
3
3
  type DatePickerProps,
4
- default as UNSAFE_DatePicker,
4
+ default as DatePicker,
5
5
  } from "./datepicker/DatePicker";
6
6
  export { type DatePickerStandaloneProps } from "./datepicker/DatePickerStandalone";
7
7
  export { type MonthPickerStandaloneProps } from "./monthpicker/MonthPickerStandalone";
8
8
  export {
9
- UNSAFE_useDatepicker,
10
- UNSAFE_useMonthpicker,
11
- UNSAFE_useRangeDatepicker,
9
+ useDatepicker,
10
+ useMonthpicker,
11
+ useRangeDatepicker,
12
12
  type RangeValidationT,
13
13
  type DateValidationT,
14
14
  type MonthValidationT,
15
15
  } from "./hooks";
16
16
  export {
17
- default as UNSAFE_MonthPicker,
17
+ default as MonthPicker,
18
18
  type MonthPickerProps,
19
19
  } from "./monthpicker/MonthPicker";
@@ -1,6 +1,6 @@
1
1
  import React, { useId, useState } from "react";
2
2
  import { Button } from "../..";
3
- import { UNSAFE_useMonthpicker } from "../hooks";
3
+ import { useMonthpicker } from "../hooks";
4
4
  import MonthPicker from "./MonthPicker";
5
5
 
6
6
  export default {
@@ -23,7 +23,7 @@ export default {
23
23
  };
24
24
 
25
25
  export const Default = () => {
26
- const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
26
+ const { inputProps, monthpickerProps } = useMonthpicker({
27
27
  disabled: [new Date("Apr 1 2022")],
28
28
  });
29
29
 
@@ -74,7 +74,7 @@ export const Standalone = () => {
74
74
  };
75
75
 
76
76
  export const UseMonthpicker = () => {
77
- const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
77
+ const { inputProps, monthpickerProps } = useMonthpicker({
78
78
  disabled: [new Date("Apr 1 2022")],
79
79
  onMonthChange: console.log,
80
80
  fromDate: new Date("Jan 1 2022"),
@@ -95,7 +95,7 @@ export const UseMonthpicker = () => {
95
95
  };
96
96
 
97
97
  export const UseMonthpickerFormat = () => {
98
- const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
98
+ const { inputProps, monthpickerProps } = useMonthpicker({
99
99
  disabled: [new Date("Apr 1 2022")],
100
100
  onMonthChange: console.log,
101
101
  inputFormat: "MM.yyyy",
@@ -115,7 +115,7 @@ export const UseMonthpickerFormat = () => {
115
115
  };
116
116
 
117
117
  export const Required = () => {
118
- const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
118
+ const { inputProps, monthpickerProps } = useMonthpicker({
119
119
  locale: "nb",
120
120
  defaultSelected: new Date(),
121
121
  disabled: [new Date("Apr 1 2022")],
@@ -73,7 +73,6 @@ describe("Extracts correct months", () => {
73
73
  current: new Date(2022, 9, 22),
74
74
  res: 9,
75
75
  };
76
- console.log(getMonths(t.start, t.end, t.current));
77
76
  expect(getMonths(t.start, t.end, t.current).length).toEqual(t.res);
78
77
  });
79
78
  });
@@ -0,0 +1,80 @@
1
+ import React, { createContext, useState } from "react";
2
+ import Toggle, { ToggleType } from "./Toggle";
3
+ import Menu, { MenuType } from "./Menu";
4
+
5
+ export interface DropdownProps {
6
+ children: React.ReactNode;
7
+ /**
8
+ * Handler called when an item is selected.
9
+ */
10
+ onSelect?: (element: React.MouseEvent) => void;
11
+ /**
12
+ * Whether the Menu closes when a selection is made.
13
+ * @default true
14
+ */
15
+ closeOnSelect?: boolean;
16
+ /**
17
+ * @default false
18
+ */
19
+ defaultOpen?: boolean;
20
+ /**
21
+ * Controlled state of the dropdown. When set, you will need to handle onClose and onSelect manually.
22
+ */
23
+ open?: boolean;
24
+ }
25
+
26
+ export interface DropdownType extends React.FC<DropdownProps> {
27
+ Toggle: ToggleType;
28
+ Menu: MenuType;
29
+ }
30
+
31
+ export interface DropdownContextType {
32
+ readonly isOpen: boolean;
33
+ handleToggle: (v: boolean) => void;
34
+ readonly anchorEl: Element | null;
35
+ setAnchorEl: React.Dispatch<React.SetStateAction<Element | null>>;
36
+ onSelect: (element: React.MouseEvent) => void;
37
+ }
38
+
39
+ export const DropdownContext = createContext<DropdownContextType | null>(null);
40
+
41
+ export const Dropdown = (({
42
+ children,
43
+ onSelect,
44
+ closeOnSelect = true,
45
+ defaultOpen = false,
46
+ open,
47
+ }) => {
48
+ const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
49
+ const [anchorEl, setAnchorEl] = useState<Element | null>(null);
50
+
51
+ const handleToggle = (v: boolean) => {
52
+ if (open === undefined) {
53
+ setIsOpen(v);
54
+ }
55
+ };
56
+
57
+ return (
58
+ <DropdownContext.Provider
59
+ value={{
60
+ isOpen: open ?? isOpen,
61
+ handleToggle,
62
+ anchorEl,
63
+ setAnchorEl,
64
+ onSelect: (event) => {
65
+ onSelect?.(event);
66
+ if (closeOnSelect) {
67
+ open === undefined && setIsOpen(false);
68
+ }
69
+ },
70
+ }}
71
+ >
72
+ {children}
73
+ </DropdownContext.Provider>
74
+ );
75
+ }) as DropdownType;
76
+
77
+ Dropdown.Toggle = Toggle;
78
+ Dropdown.Menu = Menu;
79
+
80
+ export default Dropdown;
@@ -0,0 +1,18 @@
1
+ import React, { forwardRef } from "react";
2
+ import cl from "clsx";
3
+
4
+ export type DividerType = React.ForwardRefExoticComponent<
5
+ React.HTMLAttributes<HTMLHRElement> & React.RefAttributes<HTMLHRElement>
6
+ >;
7
+
8
+ export const Divider: DividerType = forwardRef(
9
+ ({ className, ...rest }, ref) => (
10
+ <hr
11
+ {...rest}
12
+ ref={ref}
13
+ className={cl("navds-dropdown__divider", className)}
14
+ />
15
+ )
16
+ );
17
+
18
+ export default Divider;
@@ -0,0 +1,31 @@
1
+ import React, { forwardRef } from "react";
2
+ import cl from "clsx";
3
+
4
+ export interface GroupedHeadingProps
5
+ extends React.HTMLAttributes<HTMLDetailsElement> {
6
+ /**
7
+ * Heading
8
+ */
9
+ children: React.ReactNode;
10
+ }
11
+
12
+ export type GroupedHeadingType = React.ForwardRefExoticComponent<
13
+ GroupedHeadingProps & React.RefAttributes<HTMLElement>
14
+ >;
15
+
16
+ export const GroupedHeading: GroupedHeadingType = forwardRef(
17
+ ({ className, ...rest }, ref) => (
18
+ <dt
19
+ {...rest}
20
+ ref={ref}
21
+ className={cl(
22
+ "navds-dropdown__list-heading",
23
+ "navds-heading",
24
+ "navds-heading--xsmall",
25
+ className
26
+ )}
27
+ />
28
+ )
29
+ );
30
+
31
+ export default GroupedHeading;
@@ -0,0 +1,45 @@
1
+ import { OverridableComponent } from "../../../util/OverridableComponent";
2
+ import cl from "clsx";
3
+ import React, { forwardRef, useContext } from "react";
4
+ import { DropdownContext } from "../../Dropdown";
5
+
6
+ export interface GroupedItemProps
7
+ extends React.ButtonHTMLAttributes<HTMLElement> {
8
+ /**
9
+ * Menu item content
10
+ */
11
+ children: React.ReactNode;
12
+ }
13
+
14
+ export type GroupedItemType = OverridableComponent<
15
+ GroupedItemProps,
16
+ HTMLButtonElement
17
+ >;
18
+
19
+ export const GroupedItem: GroupedItemType = forwardRef(
20
+ ({ as: Component = "button", className, ...rest }, ref) => {
21
+ const context = useContext(DropdownContext);
22
+
23
+ return (
24
+ <dd className="navds-dropdown__list-item">
25
+ <Component
26
+ {...rest}
27
+ value={rest.children}
28
+ onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
29
+ context?.onSelect?.(event);
30
+ rest?.onClick?.(event);
31
+ }}
32
+ ref={ref}
33
+ className={cl(
34
+ "navds-dropdown__item",
35
+ "navds-body-short",
36
+ "navds-body-short--small",
37
+ className
38
+ )}
39
+ />
40
+ </dd>
41
+ );
42
+ }
43
+ );
44
+
45
+ export default GroupedItem;
@@ -0,0 +1,33 @@
1
+ import React, { forwardRef } from "react";
2
+ import cl from "clsx";
3
+ import GroupedHeading, { GroupedHeadingType } from "./Heading";
4
+ import GroupedItem, { GroupedItemType } from "./Item";
5
+
6
+ export interface GroupedListProps
7
+ extends React.HTMLAttributes<HTMLDListElement> {
8
+ /**
9
+ * Menu list content
10
+ */
11
+ children: React.ReactNode;
12
+ }
13
+
14
+ export interface GroupedListType
15
+ extends React.ForwardRefExoticComponent<
16
+ GroupedListProps & React.RefAttributes<HTMLDListElement>
17
+ > {
18
+ Heading: GroupedHeadingType;
19
+ Item: GroupedItemType;
20
+ }
21
+
22
+ export const DescriptionList = forwardRef(
23
+ ({ className, children, ...rest }, ref) => (
24
+ <dl {...rest} ref={ref} className={cl("navds-dropdown__list", className)}>
25
+ {children}
26
+ </dl>
27
+ )
28
+ ) as GroupedListType;
29
+
30
+ DescriptionList.Heading = GroupedHeading;
31
+ DescriptionList.Item = GroupedItem;
32
+
33
+ export default DescriptionList;
@@ -0,0 +1,44 @@
1
+ import React, { forwardRef, useContext } from "react";
2
+ import cl from "clsx";
3
+ import { OverridableComponent } from "../../../util/OverridableComponent";
4
+ import { DropdownContext } from "../../Dropdown";
5
+
6
+ export interface ListItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
7
+ /**
8
+ * Menu item content
9
+ */
10
+ children: React.ReactNode;
11
+ }
12
+
13
+ export type ListItemType = OverridableComponent<
14
+ ListItemProps,
15
+ HTMLButtonElement
16
+ >;
17
+
18
+ export const ListItem: ListItemType = forwardRef(
19
+ ({ as: Component = "button", className, ...rest }, ref) => {
20
+ const context = useContext(DropdownContext);
21
+
22
+ return (
23
+ <li className="navds-dropdown__list-item">
24
+ <Component
25
+ {...rest}
26
+ value={rest.children}
27
+ onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
28
+ context?.onSelect?.(event);
29
+ rest?.onClick?.(event);
30
+ }}
31
+ ref={ref}
32
+ className={cl(
33
+ "navds-dropdown__item",
34
+ "navds-body-short",
35
+ "navds-body-short--small",
36
+ className
37
+ )}
38
+ />
39
+ </li>
40
+ );
41
+ }
42
+ );
43
+
44
+ export default ListItem;
@@ -0,0 +1,27 @@
1
+ import React, { forwardRef } from "react";
2
+ import cl from "clsx";
3
+ import ListItem, { ListItemType } from "./Item";
4
+
5
+ export interface ListProps extends React.HTMLAttributes<HTMLUListElement> {
6
+ /**
7
+ * Menu list content
8
+ */
9
+ children: React.ReactNode;
10
+ }
11
+
12
+ export interface ListType
13
+ extends React.ForwardRefExoticComponent<
14
+ ListProps & React.RefAttributes<HTMLUListElement>
15
+ > {
16
+ Item: ListItemType;
17
+ }
18
+
19
+ export const List = forwardRef(({ className, children, ...rest }, ref) => (
20
+ <ul {...rest} ref={ref} className={cl("navds-dropdown__list", className)}>
21
+ {children}
22
+ </ul>
23
+ )) as ListType;
24
+
25
+ List.Item = ListItem;
26
+
27
+ export default List;
@@ -0,0 +1,85 @@
1
+ import { Popover } from "../../popover";
2
+ import cl from "clsx";
3
+ import React, { forwardRef, useContext } from "react";
4
+ import { DropdownContext } from "../Dropdown";
5
+ import Divider, { DividerType } from "./Divider";
6
+ import GroupedList, { GroupedListType } from "./GroupedList";
7
+ import List, { ListType } from "./List";
8
+
9
+ interface MenuProps extends React.HTMLAttributes<HTMLDivElement> {
10
+ /**
11
+ * Dropdown content
12
+ */
13
+ children: React.ReactNode;
14
+ /**
15
+ * onClose callback
16
+ */
17
+ onClose?: () => void;
18
+ /**
19
+ * Popover positionion strategy
20
+ * @default "absolute"
21
+ */
22
+ strategy?: "fixed" | "absolute";
23
+ /*
24
+ * Default dialog-placement on open
25
+ * @default "bottom-end"
26
+ */
27
+ placement?:
28
+ | "top"
29
+ | "bottom"
30
+ | "right"
31
+ | "left"
32
+ | "top-start"
33
+ | "top-end"
34
+ | "bottom-start"
35
+ | "bottom-end"
36
+ | "right-start"
37
+ | "right-end"
38
+ | "left-start"
39
+ | "left-end";
40
+ }
41
+
42
+ export interface MenuType<Props = MenuProps>
43
+ extends React.ForwardRefExoticComponent<
44
+ Props & React.RefAttributes<HTMLDivElement>
45
+ > {
46
+ List: ListType;
47
+ GroupedList: GroupedListType;
48
+ Divider: DividerType;
49
+ }
50
+
51
+ export const Menu = forwardRef<HTMLDivElement, MenuProps>(
52
+ ({ className, onClose, placement = "bottom-end", ...rest }, ref) => {
53
+ const context = useContext(DropdownContext);
54
+
55
+ if (!context) {
56
+ console.warn("Dropdown.Menu has to be wrapped in <Dropdown />");
57
+ return null;
58
+ }
59
+
60
+ const { isOpen, anchorEl, handleToggle } = context;
61
+
62
+ return (
63
+ <Popover
64
+ {...rest}
65
+ placement={placement}
66
+ ref={ref}
67
+ arrow={false}
68
+ className={cl("navds-dropdown__menu", className)}
69
+ offset={-4}
70
+ anchorEl={anchorEl}
71
+ open={isOpen}
72
+ onClose={() => {
73
+ handleToggle(false);
74
+ onClose && onClose();
75
+ }}
76
+ />
77
+ );
78
+ }
79
+ ) as MenuType;
80
+
81
+ Menu.List = List;
82
+ Menu.GroupedList = GroupedList;
83
+ Menu.Divider = Divider;
84
+
85
+ export default Menu;
@@ -0,0 +1,52 @@
1
+ import React, { forwardRef, useContext } from "react";
2
+ import cl from "clsx";
3
+ import { DropdownContext } from ".";
4
+
5
+ export interface ToggleProps
6
+ extends React.ButtonHTMLAttributes<HTMLButtonElement> {
7
+ /**
8
+ * Button content
9
+ */
10
+ children: React.ReactNode;
11
+ }
12
+
13
+ export type ToggleType = React.ForwardRefExoticComponent<
14
+ ToggleProps & React.RefAttributes<HTMLButtonElement>
15
+ >;
16
+
17
+ export const Toggle: ToggleType = forwardRef(
18
+ ({ className, onClick, ...rest }, ref) => {
19
+ const context = useContext(DropdownContext);
20
+
21
+ if (!context) {
22
+ console.warn("Dropdown.Toggle has to be wrapped in <Dropdown />");
23
+ return null;
24
+ }
25
+
26
+ const { setAnchorEl, handleToggle, isOpen } = context;
27
+
28
+ return (
29
+ <button
30
+ {...rest}
31
+ ref={(el) => {
32
+ setAnchorEl(el);
33
+
34
+ if (typeof ref === "function") {
35
+ ref(el);
36
+ } else if (ref != null) {
37
+ ref.current = el;
38
+ }
39
+ }}
40
+ onClick={(e) => {
41
+ setAnchorEl(e.currentTarget);
42
+ handleToggle(!isOpen);
43
+ onClick && onClick(e);
44
+ }}
45
+ aria-expanded={isOpen}
46
+ className={cl("navds-dropdown__toggle", className)}
47
+ />
48
+ );
49
+ }
50
+ );
51
+
52
+ export default Toggle;