@navikt/ds-react 5.7.6 → 5.9.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 (164) hide show
  1. package/_docs.json +1824 -1758
  2. package/cjs/accordion/AccordionHeader.js +2 -2
  3. package/cjs/date/context/useDateInputContext.js +1 -5
  4. package/cjs/date/datepicker/DatePicker.js +26 -25
  5. package/cjs/date/hooks/useDatepicker.js +9 -17
  6. package/cjs/date/hooks/useMonthPicker.js +9 -17
  7. package/cjs/date/hooks/useRangeDatepicker.js +9 -20
  8. package/cjs/date/monthpicker/MonthPicker.js +11 -6
  9. package/cjs/date/{DateInput.js → parts/DateInput.js} +14 -10
  10. package/cjs/date/parts/DateWrapper.js +55 -0
  11. package/cjs/date/utils/labels.js +77 -1
  12. package/cjs/form/combobox/Combobox.js +2 -2
  13. package/cjs/form/combobox/ComboboxProvider.js +1 -2
  14. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
  15. package/cjs/form/combobox/FilteredOptions/filtered-options-util.js +24 -0
  16. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +24 -108
  17. package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js +55 -0
  18. package/cjs/form/combobox/Input/Input.js +33 -16
  19. package/cjs/form/combobox/customOptionsContext.js +2 -3
  20. package/cjs/layout/sidemal-test/Sidebar.js +1 -1
  21. package/cjs/loader/Loader.js +1 -1
  22. package/cjs/modal/Modal.js +39 -15
  23. package/cjs/popover/Popover.js +5 -7
  24. package/cjs/tooltip/Tooltip.js +14 -3
  25. package/cjs/util/useMedia.js +30 -0
  26. package/esm/accordion/AccordionHeader.js +2 -2
  27. package/esm/accordion/AccordionHeader.js.map +1 -1
  28. package/esm/date/context/useDateInputContext.d.ts +6 -2
  29. package/esm/date/context/useDateInputContext.js +1 -5
  30. package/esm/date/context/useDateInputContext.js.map +1 -1
  31. package/esm/date/datepicker/DatePicker.d.ts +1 -1
  32. package/esm/date/datepicker/DatePicker.js +28 -27
  33. package/esm/date/datepicker/DatePicker.js.map +1 -1
  34. package/esm/date/datepicker/types.d.ts +0 -5
  35. package/esm/date/hooks/useDatepicker.d.ts +8 -5
  36. package/esm/date/hooks/useDatepicker.js +10 -18
  37. package/esm/date/hooks/useDatepicker.js.map +1 -1
  38. package/esm/date/hooks/useMonthPicker.d.ts +7 -4
  39. package/esm/date/hooks/useMonthPicker.js +10 -18
  40. package/esm/date/hooks/useMonthPicker.js.map +1 -1
  41. package/esm/date/hooks/useRangeDatepicker.d.ts +9 -3
  42. package/esm/date/hooks/useRangeDatepicker.js +10 -21
  43. package/esm/date/hooks/useRangeDatepicker.js.map +1 -1
  44. package/esm/date/index.d.ts +1 -1
  45. package/esm/date/index.js.map +1 -1
  46. package/esm/date/monthpicker/MonthPicker.d.ts +1 -1
  47. package/esm/date/monthpicker/MonthPicker.js +13 -8
  48. package/esm/date/monthpicker/MonthPicker.js.map +1 -1
  49. package/esm/date/monthpicker/types.d.ts +0 -5
  50. package/esm/date/{DateInput.d.ts → parts/DateInput.d.ts} +5 -1
  51. package/esm/date/{DateInput.js → parts/DateInput.js} +15 -11
  52. package/esm/date/parts/DateInput.js.map +1 -0
  53. package/esm/date/parts/DateWrapper.d.ts +15 -0
  54. package/esm/date/parts/DateWrapper.js +26 -0
  55. package/esm/date/parts/DateWrapper.js.map +1 -0
  56. package/esm/date/utils/labels.d.ts +2 -0
  57. package/esm/date/utils/labels.js +74 -0
  58. package/esm/date/utils/labels.js.map +1 -1
  59. package/esm/form/combobox/Combobox.js +2 -2
  60. package/esm/form/combobox/Combobox.js.map +1 -1
  61. package/esm/form/combobox/ComboboxProvider.js +1 -2
  62. package/esm/form/combobox/ComboboxProvider.js.map +1 -1
  63. package/esm/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
  64. package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  65. package/esm/form/combobox/FilteredOptions/filtered-options-util.d.ts +12 -0
  66. package/esm/form/combobox/FilteredOptions/filtered-options-util.js +23 -0
  67. package/esm/form/combobox/FilteredOptions/filtered-options-util.js.map +1 -0
  68. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +10 -13
  69. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +25 -109
  70. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  71. package/esm/form/combobox/FilteredOptions/useVirtualFocus.d.ts +15 -0
  72. package/esm/form/combobox/FilteredOptions/useVirtualFocus.js +54 -0
  73. package/esm/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -0
  74. package/esm/form/combobox/Input/Input.js +33 -16
  75. package/esm/form/combobox/Input/Input.js.map +1 -1
  76. package/esm/form/combobox/customOptionsContext.d.ts +4 -1
  77. package/esm/form/combobox/customOptionsContext.js +2 -3
  78. package/esm/form/combobox/customOptionsContext.js.map +1 -1
  79. package/esm/layout/bleed/Bleed.d.ts +1 -1
  80. package/esm/layout/bleed/Bleed.js +1 -1
  81. package/esm/layout/bleed/Bleed.js.map +1 -1
  82. package/esm/layout/box/Box.d.ts +1 -2
  83. package/esm/layout/box/Box.js +1 -1
  84. package/esm/layout/box/Box.js.map +1 -1
  85. package/esm/layout/grid/HGrid.d.ts +1 -1
  86. package/esm/layout/grid/HGrid.js +1 -1
  87. package/esm/layout/grid/HGrid.js.map +1 -1
  88. package/esm/layout/responsive/Responsive.d.ts +1 -1
  89. package/esm/layout/sidemal-test/Sidebar.js +1 -1
  90. package/esm/layout/sidemal-test/Sidebar.js.map +1 -1
  91. package/esm/layout/stack/Stack.d.ts +1 -1
  92. package/esm/layout/stack/Stack.js +1 -1
  93. package/esm/layout/stack/Stack.js.map +1 -1
  94. package/esm/layout/utilities/css.d.ts +1 -8
  95. package/esm/layout/utilities/css.js.map +1 -1
  96. package/esm/layout/utilities/types.d.ts +9 -0
  97. package/esm/loader/Loader.d.ts +1 -1
  98. package/esm/loader/Loader.js +1 -1
  99. package/esm/modal/Modal.js +39 -15
  100. package/esm/modal/Modal.js.map +1 -1
  101. package/esm/modal/ModalContext.d.ts +1 -0
  102. package/esm/modal/ModalContext.js.map +1 -1
  103. package/esm/modal/types.d.ts +7 -0
  104. package/esm/popover/Popover.d.ts +0 -5
  105. package/esm/popover/Popover.js +5 -7
  106. package/esm/popover/Popover.js.map +1 -1
  107. package/esm/tooltip/Tooltip.js +16 -5
  108. package/esm/tooltip/Tooltip.js.map +1 -1
  109. package/esm/util/useMedia.d.ts +8 -0
  110. package/esm/util/useMedia.js +27 -0
  111. package/esm/util/useMedia.js.map +1 -0
  112. package/package.json +3 -3
  113. package/src/accordion/AccordionHeader.tsx +3 -3
  114. package/src/date/context/useDateInputContext.tsx +5 -5
  115. package/src/date/datepicker/DatePicker.tsx +58 -65
  116. package/src/date/datepicker/datepicker.stories.tsx +37 -46
  117. package/src/date/datepicker/types.ts +0 -5
  118. package/src/date/hooks/useDatepicker.tsx +20 -25
  119. package/src/date/hooks/useMonthPicker.tsx +18 -24
  120. package/src/date/hooks/useRangeDatepicker.tsx +27 -30
  121. package/src/date/index.ts +1 -1
  122. package/src/date/monthpicker/MonthPicker.tsx +39 -43
  123. package/src/date/monthpicker/types.ts +0 -5
  124. package/src/date/{DateInput.tsx → parts/DateInput.tsx} +23 -12
  125. package/src/date/parts/DateWrapper.tsx +80 -0
  126. package/src/date/utils/labels.ts +83 -0
  127. package/src/form/combobox/Combobox.tsx +2 -2
  128. package/src/form/combobox/ComboboxProvider.tsx +1 -2
  129. package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +28 -16
  130. package/src/form/combobox/FilteredOptions/filtered-options-util.ts +38 -0
  131. package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +71 -142
  132. package/src/form/combobox/FilteredOptions/useVirtualFocus.ts +87 -0
  133. package/src/form/combobox/Input/Input.tsx +40 -21
  134. package/src/form/combobox/combobox.stories.tsx +44 -0
  135. package/src/form/combobox/customOptionsContext.tsx +10 -5
  136. package/src/guide-panel/guidepanel.stories.tsx +2 -2
  137. package/src/layout/bleed/Bleed.tsx +2 -5
  138. package/src/layout/box/Box.tsx +1 -3
  139. package/src/layout/grid/HGrid.tsx +2 -6
  140. package/src/layout/responsive/Responsive.tsx +1 -1
  141. package/src/layout/sidemal-test/Sidebar.tsx +1 -1
  142. package/src/layout/stack/Stack.tsx +2 -6
  143. package/src/layout/utilities/css.ts +1 -36
  144. package/src/layout/utilities/types.ts +16 -0
  145. package/src/loader/Loader.tsx +1 -1
  146. package/src/modal/Modal.tsx +54 -21
  147. package/src/modal/ModalContext.ts +1 -0
  148. package/src/modal/modal.stories.tsx +30 -2
  149. package/src/modal/types.ts +7 -0
  150. package/src/popover/Popover.tsx +4 -12
  151. package/src/tooltip/Tooltip.tsx +18 -6
  152. package/src/util/__tests__/useMedia.test.tsx +19 -0
  153. package/src/util/useMedia.ts +38 -0
  154. package/cjs/date/hooks/useEscape.js +0 -23
  155. package/cjs/date/hooks/useOutsideClickHandler.js +0 -26
  156. package/esm/date/DateInput.js.map +0 -1
  157. package/esm/date/hooks/useEscape.d.ts +0 -2
  158. package/esm/date/hooks/useEscape.js +0 -20
  159. package/esm/date/hooks/useEscape.js.map +0 -1
  160. package/esm/date/hooks/useOutsideClickHandler.d.ts +0 -1
  161. package/esm/date/hooks/useOutsideClickHandler.js +0 -23
  162. package/esm/date/hooks/useOutsideClickHandler.js.map +0 -1
  163. package/src/date/hooks/useEscape.tsx +0 -30
  164. package/src/date/hooks/useOutsideClickHandler.tsx +0 -34
@@ -1,9 +1,9 @@
1
+ import { ChevronDownIcon } from "@navikt/aksel-icons";
1
2
  import cl from "clsx";
2
3
  import React, { forwardRef, useContext } from "react";
3
4
  import { Heading } from "../typography";
4
5
  import { AccordionContext } from "./AccordionContext";
5
6
  import { AccordionItemContext } from "./AccordionItem";
6
- import { ChevronDownIcon } from "@navikt/aksel-icons";
7
7
 
8
8
  export interface AccordionHeaderProps
9
9
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
@@ -37,13 +37,13 @@ const AccordionHeader = forwardRef<HTMLButtonElement, AccordionHeaderProps>(
37
37
  aria-expanded={itemContext.open}
38
38
  type="button"
39
39
  >
40
- <div className="navds-accordion__icon-wrapper">
40
+ <span className="navds-accordion__icon-wrapper">
41
41
  <ChevronDownIcon
42
42
  className="navds-accordion__header-chevron"
43
43
  title="Vis mer"
44
44
  aria-hidden
45
45
  />
46
- </div>
46
+ </span>
47
47
  <Heading
48
48
  size={accordionContext?.headingSize ?? "small"}
49
49
  as="span"
@@ -13,13 +13,13 @@ interface DateContextContextProps {
13
13
  * Aria-connected ID
14
14
  */
15
15
  ariaId?: string;
16
+ /**
17
+ * Flag for enabled-check
18
+ */
19
+ defined: boolean;
16
20
  }
17
21
 
18
- export const DateContext = createContext<DateContextContextProps>({
19
- open: false,
20
- onOpen: () => null,
21
- ariaId: undefined,
22
- });
22
+ export const DateContext = createContext<DateContextContextProps | null>(null);
23
23
 
24
24
  export const useDateInputContext = () => {
25
25
  const context = useContext(DateContext);
@@ -1,11 +1,11 @@
1
1
  import cl from "clsx";
2
2
  import isWeekend from "date-fns/isWeekend";
3
- import React, { forwardRef, useRef, useState } from "react";
3
+ import React, { forwardRef, useMemo, useRef, useState } from "react";
4
4
  import { DateRange, DayPicker, isMatch } from "react-day-picker";
5
- import { Popover } from "../../popover";
6
- import { omit, useId } from "../../util";
7
- import { DatePickerInput } from "../DateInput";
5
+ import { mergeRefs, omit, useId } from "../../util";
8
6
  import { DateContext } from "../context";
7
+ import { DatePickerInput } from "../parts/DateInput";
8
+ import { DateWrapper } from "../parts/DateWrapper";
9
9
  import { getLocaleFromString, labels } from "../utils";
10
10
  import DatePickerStandalone from "./DatePickerStandalone";
11
11
  import Caption from "./parts/Caption";
@@ -79,7 +79,6 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
79
79
  onClose,
80
80
  onOpenToggle,
81
81
  strategy,
82
- bubbleEscape = false,
83
82
  onWeekNumberClick,
84
83
  ...rest
85
84
  },
@@ -89,6 +88,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
89
88
  const [open, setOpen] = useState(_open ?? false);
90
89
 
91
90
  const wrapperRef = useRef<HTMLDivElement | null>(null);
91
+ const mergedRef = useMemo(() => mergeRefs([wrapperRef, ref]), [ref]);
92
92
 
93
93
  const [selectedDates, setSelectedDates] = React.useState<
94
94
  Date | Date[] | DateRange | undefined
@@ -110,6 +110,44 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
110
110
  rest?.onSelect?.(newSelected);
111
111
  };
112
112
 
113
+ const DatePickerComponent = (
114
+ <DayPicker
115
+ locale={getLocaleFromString(locale)}
116
+ mode={mode}
117
+ onSelect={handleSelect}
118
+ selected={selected ?? selectedDates}
119
+ components={{
120
+ Caption: dropdownCaption ? DropdownCaption : Caption,
121
+ Head: TableHead,
122
+ HeadRow,
123
+ WeekNumber,
124
+ Row,
125
+ Day: DayButton,
126
+ }}
127
+ className={cl("navds-date", className)}
128
+ classNames={{
129
+ vhidden: "navds-sr-only",
130
+ }}
131
+ disabled={(day) => {
132
+ return (disableWeekends && isWeekend(day)) || isMatch(day, disabled);
133
+ }}
134
+ weekStartsOn={1}
135
+ initialFocus={false}
136
+ labels={labels as any}
137
+ modifiers={{
138
+ weekend: (day) => disableWeekends && isWeekend(day),
139
+ }}
140
+ modifiersClassNames={{
141
+ weekend: "rdp-day__weekend",
142
+ }}
143
+ showWeekNumber={showWeekNumber}
144
+ onWeekNumberClick={mode === "multiple" ? onWeekNumberClick : undefined}
145
+ fixedWeeks
146
+ showOutsideDays
147
+ {...omit(rest, ["onSelect"])}
148
+ />
149
+ );
150
+
113
151
  return (
114
152
  <DateContext.Provider
115
153
  value={{
@@ -119,72 +157,27 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
119
157
  onOpenToggle?.();
120
158
  },
121
159
  ariaId,
160
+ defined: true,
122
161
  }}
123
162
  >
124
163
  <div
125
- ref={wrapperRef}
164
+ ref={mergedRef}
126
165
  className={cl("navds-date__wrapper", wrapperClassName)}
127
166
  >
128
167
  {children}
129
- {(_open ?? open) && (
130
- <Popover
131
- arrow={false}
132
- anchorEl={wrapperRef.current}
133
- open={_open ?? open}
134
- onClose={() => {
135
- onClose?.() ?? setOpen(false);
136
- }}
137
- placement="bottom-start"
138
- id={ariaId}
139
- role="dialog"
140
- ref={ref}
141
- strategy={strategy}
142
- className="navds-date__popover"
143
- bubbleEscape={bubbleEscape}
144
- flip={false}
145
- >
146
- <DayPicker
147
- locale={getLocaleFromString(locale)}
148
- mode={mode}
149
- onSelect={handleSelect}
150
- selected={selected ?? selectedDates}
151
- components={{
152
- Caption: dropdownCaption ? DropdownCaption : Caption,
153
- Head: TableHead,
154
- HeadRow,
155
- WeekNumber,
156
- Row,
157
- Day: DayButton,
158
- }}
159
- className={cl("navds-date", className)}
160
- classNames={{
161
- vhidden: "navds-sr-only",
162
- }}
163
- disabled={(day) => {
164
- return (
165
- (disableWeekends && isWeekend(day)) ||
166
- isMatch(day, disabled)
167
- );
168
- }}
169
- weekStartsOn={1}
170
- initialFocus={false}
171
- labels={labels as any}
172
- modifiers={{
173
- weekend: (day) => disableWeekends && isWeekend(day),
174
- }}
175
- modifiersClassNames={{
176
- weekend: "rdp-day__weekend",
177
- }}
178
- showWeekNumber={showWeekNumber}
179
- onWeekNumberClick={
180
- mode === "multiple" ? onWeekNumberClick : undefined
181
- }
182
- fixedWeeks
183
- showOutsideDays
184
- {...omit(rest, ["onSelect"])}
185
- />
186
- </Popover>
187
- )}
168
+ <DateWrapper
169
+ open={_open ?? open}
170
+ anchor={wrapperRef.current}
171
+ onClose={() => onClose?.() ?? setOpen(false)}
172
+ locale={locale}
173
+ variant={mode}
174
+ popoverProps={{
175
+ id: ariaId,
176
+ strategy,
177
+ }}
178
+ >
179
+ {DatePickerComponent}
180
+ </DateWrapper>
188
181
  </div>
189
182
  </DateContext.Provider>
190
183
  );
@@ -3,7 +3,7 @@ import { Meta, StoryObj } from "@storybook/react";
3
3
  import isSameDay from "date-fns/isSameDay";
4
4
  import React, { useId, useState } from "react";
5
5
  import { useDatepicker, useRangeDatepicker } from "..";
6
- import { BodyLong, Button, HGrid, HStack, Modal, VStack } from "../..";
6
+ import { BodyLong, Button, HGrid, Modal, VStack } from "../..";
7
7
  import DatePicker, { DatePickerProps } from "./DatePicker";
8
8
 
9
9
  const disabledDays = [
@@ -18,7 +18,6 @@ export default {
18
18
 
19
19
  type DefaultStoryProps = DatePickerProps & {
20
20
  size: "medium" | "small";
21
- openOnFocus: boolean;
22
21
  inputfield: boolean;
23
22
  standalone: boolean;
24
23
  };
@@ -30,13 +29,11 @@ export const Default: StoryObj<DefaultStoryProps> = {
30
29
  const rangeCtx = useRangeDatepicker({
31
30
  fromDate: new Date("Aug 23 2020"),
32
31
  toDate: new Date("Aug 23 2023"),
33
- openOnFocus: props.openOnFocus,
34
32
  });
35
33
 
36
34
  const singleCtx = useDatepicker({
37
35
  fromDate: new Date("Aug 23 2020"),
38
36
  toDate: new Date("Aug 23 2023"),
39
- openOnFocus: props.openOnFocus,
40
37
  });
41
38
 
42
39
  const newProps = {
@@ -111,7 +108,6 @@ export const Default: StoryObj<DefaultStoryProps> = {
111
108
  disableWeekends: false,
112
109
  showWeekNumber: false,
113
110
  mode: "single",
114
- openOnFocus: true,
115
111
  inputfield: true,
116
112
  standalone: false,
117
113
  },
@@ -186,21 +182,6 @@ export const UseRangedDatepicker = () => {
186
182
  );
187
183
  };
188
184
 
189
- export const OpenOnFocus = () => {
190
- const { datepickerProps, inputProps } = useDatepicker({
191
- onDateChange: console.log,
192
- openOnFocus: false,
193
- });
194
-
195
- return (
196
- <div style={{ display: "flex", gap: "1rem" }}>
197
- <DatePicker {...datepickerProps}>
198
- <DatePicker.Input {...inputProps} label="Velg dato" />
199
- </DatePicker>
200
- </div>
201
- );
202
- };
203
-
204
185
  export const NB = () => (
205
186
  <DatePicker.Standalone locale="nb" today={new Date("2006-07-01")} />
206
187
  );
@@ -333,15 +314,32 @@ export const Size = () => {
333
314
  fromDate: new Date("Aug 23 2019"),
334
315
  toDate: new Date("Feb 23 2024"),
335
316
  onDateChange: console.log,
317
+ defaultSelected: new Date("Feb 23 2023"),
318
+ });
319
+ const { datepickerProps: d2, inputProps: i2 } = useDatepicker({
320
+ fromDate: new Date("Aug 23 2019"),
321
+ toDate: new Date("Feb 23 2024"),
322
+ onDateChange: console.log,
323
+ defaultSelected: new Date("Feb 23 2023"),
336
324
  });
337
325
 
338
326
  return (
339
327
  <div style={{ display: "flex", gap: "1rem" }}>
340
328
  <DatePicker {...datepickerProps} dropdownCaption>
341
- <DatePicker.Input size="medium" {...inputProps} label="Velg dato" />
329
+ <DatePicker.Input
330
+ placeholder="10/10/2023"
331
+ size="medium"
332
+ {...inputProps}
333
+ label="Velg dato"
334
+ />
342
335
  </DatePicker>
343
- <DatePicker {...datepickerProps} dropdownCaption>
344
- <DatePicker.Input size="small" {...inputProps} label="Velg dato" />
336
+ <DatePicker {...d2} dropdownCaption>
337
+ <DatePicker.Input
338
+ placeholder="10/10/2023"
339
+ size="small"
340
+ {...i2}
341
+ label="Velg dato"
342
+ />
345
343
  </DatePicker>
346
344
  </div>
347
345
  );
@@ -441,33 +439,26 @@ export const ModalDemo = () => {
441
439
  });
442
440
 
443
441
  return (
444
- <Modal open header={{ heading: "Modal-demo" }} width="1024px">
442
+ <Modal open header={{ heading: "Modal-demo" }}>
445
443
  <Modal.Body style={{ position: "relative" }}>
446
- <BodyLong>
447
- Lorem ipsum dolor sit, amet consectetur adipisicing elit. Maiores nisi
448
- incidunt ipsum cupiditate nostrum nesciunt, corrupti nihil at atque
449
- animi ab aut. Quam iusto harum eligendi magnam nulla repudiandae
450
- molestias.
444
+ <BodyLong spacing>
445
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit.
451
446
  </BodyLong>
452
447
 
453
- <HGrid gap="6" columns={{ xs: 1, lg: 2 }}>
454
- <HStack justify="center" align="start">
455
- <DatePicker.Standalone
456
- fromDate={new Date("Aug 23 2019")}
457
- toDate={new Date("Feb 23 2024")}
458
- />
459
- </HStack>
460
- <DatePicker {...datepickerProps} dropdownCaption>
461
- <DatePicker.Input {...inputProps} label="Velg dato" />
462
- </DatePicker>
463
- <HStack justify="center">
464
- <DatePicker.Standalone
465
- fromDate={new Date("Aug 23 2019")}
466
- toDate={new Date("Feb 23 2024")}
467
- />
468
- </HStack>
469
- </HGrid>
448
+ <DatePicker {...datepickerProps} dropdownCaption>
449
+ <DatePicker.Input
450
+ {...inputProps}
451
+ label="Velg dato"
452
+ description="Format: dd.mm.yyyy"
453
+ />
454
+ </DatePicker>
470
455
  </Modal.Body>
456
+ <Modal.Footer>
457
+ <Button>Neste</Button>
458
+ <Button variant="secondary">Tilbake</Button>
459
+ <Button variant="tertiary">Avbryt</Button>
460
+ </Modal.Footer>
471
461
  </Modal>
472
462
  );
473
463
  };
464
+ ModalDemo.parameters = { chromatic: { pauseAnimationAtEnd: true } };
@@ -101,9 +101,4 @@ export interface DatePickerDefaultProps
101
101
  * @default See Popover
102
102
  */
103
103
  strategy?: "absolute" | "fixed";
104
- /**
105
- * Bubbles Escape keydown-event up trough DOM-tree. This is set to false by default to prevent closing components like Modal on Escape
106
- * @default false
107
- */
108
- bubbleEscape?: boolean;
109
104
  }
@@ -1,17 +1,15 @@
1
1
  import differenceInCalendarDays from "date-fns/differenceInCalendarDays";
2
2
  import isWeekend from "date-fns/isWeekend";
3
- import React, { useCallback, useRef, useState } from "react";
3
+ import React, { useCallback, useState } from "react";
4
4
  import { DayClickEventHandler, isMatch } from "react-day-picker";
5
- import { DateInputProps } from "../DateInput";
6
5
  import { DatePickerProps } from "../datepicker/DatePicker";
6
+ import { DateInputProps } from "../parts/DateInput";
7
7
  import {
8
8
  formatDateForInput,
9
9
  getLocaleFromString,
10
10
  isValidDate,
11
11
  parseDate,
12
12
  } from "../utils";
13
- import { useEscape } from "./useEscape";
14
- import { useOutsideClickHandler } from "./useOutsideClickHandler";
15
13
 
16
14
  export interface UseDatepickerOptions
17
15
  extends Pick<
@@ -59,10 +57,10 @@ export interface UseDatepickerOptions
59
57
  */
60
58
  allowTwoDigitYear?: boolean;
61
59
  /**
62
- * Opens datepicker on input-focus
63
- * @default true
60
+ * Will be removed in a future major-version
61
+ * @deprecated
64
62
  */
65
- openOnFocus?: boolean;
63
+ openOnFocus?: false;
66
64
  }
67
65
 
68
66
  interface UseDatepickerValue {
@@ -76,7 +74,14 @@ interface UseDatepickerValue {
76
74
  inputProps: Pick<
77
75
  DateInputProps,
78
76
  "onChange" | "onFocus" | "onBlur" | "value"
79
- > & { ref: React.RefObject<HTMLInputElement> };
77
+ > & {
78
+ /**
79
+ * @private
80
+ */
81
+ setAnchorRef: React.Dispatch<
82
+ React.SetStateAction<HTMLButtonElement | null>
83
+ >;
84
+ };
80
85
  /**
81
86
  * Resets all states (callback)
82
87
  */
@@ -143,14 +148,11 @@ export const useDatepicker = (
143
148
  onValidate,
144
149
  defaultMonth,
145
150
  allowTwoDigitYear = true,
146
- openOnFocus = true,
147
151
  } = opt;
148
152
 
153
+ const [anchorRef, setAnchorRef] = useState<HTMLButtonElement | null>(null);
149
154
  const locale = getLocaleFromString(_locale);
150
155
 
151
- const inputRef = useRef<HTMLInputElement>(null);
152
- const [daypickerRef, setDaypickerRef] = useState<HTMLDivElement>();
153
-
154
156
  const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
155
157
 
156
158
  // Initialize states
@@ -172,14 +174,6 @@ export const useDatepicker = (
172
174
  [defaultMonth, defaultSelected, selectedDay, today]
173
175
  );
174
176
 
175
- useOutsideClickHandler(open, handleOpen, [
176
- daypickerRef,
177
- inputRef.current,
178
- inputRef.current?.nextSibling,
179
- ]);
180
-
181
- useEscape(open, handleOpen, inputRef);
182
-
183
177
  const updateDate = (date?: Date) => {
184
178
  onDateChange?.(date);
185
179
  setSelectedDay(date);
@@ -207,7 +201,6 @@ export const useDatepicker = (
207
201
  if (e.target.readOnly) {
208
202
  return;
209
203
  }
210
- !open && openOnFocus && handleOpen(true);
211
204
  const day = parseDate(
212
205
  e.target.value,
213
206
  today,
@@ -243,7 +236,7 @@ export const useDatepicker = (
243
236
  const handleDayClick: DayClickEventHandler = (day, { selected }) => {
244
237
  if (day && !selected) {
245
238
  handleOpen(false);
246
- inputRef.current && inputRef.current.focus();
239
+ anchorRef?.focus();
247
240
  }
248
241
 
249
242
  if (!required && selected) {
@@ -319,11 +312,13 @@ export const useDatepicker = (
319
312
  toDate,
320
313
  today,
321
314
  open,
315
+ onClose: () => {
316
+ handleOpen(false);
317
+ anchorRef?.focus();
318
+ },
322
319
  onOpenToggle: () => handleOpen(!open),
323
320
  disabled,
324
321
  disableWeekends,
325
- bubbleEscape: true,
326
- ref: setDaypickerRef,
327
322
  };
328
323
 
329
324
  const inputProps = {
@@ -331,7 +326,7 @@ export const useDatepicker = (
331
326
  onFocus: handleFocus,
332
327
  onBlur: handleBlur,
333
328
  value: inputValue,
334
- ref: inputRef,
329
+ setAnchorRef,
335
330
  };
336
331
 
337
332
  return { datepickerProps, inputProps, reset, selectedDay, setSelected };
@@ -1,6 +1,6 @@
1
- import React, { useCallback, useMemo, useRef, useState } from "react";
2
- import { DateInputProps } from "../DateInput";
1
+ import React, { useCallback, useMemo, useState } from "react";
3
2
  import { MonthPickerProps } from "../monthpicker/types";
3
+ import { DateInputProps } from "../parts/DateInput";
4
4
  import {
5
5
  formatDateForInput,
6
6
  getLocaleFromString,
@@ -8,8 +8,6 @@ import {
8
8
  isValidDate,
9
9
  parseDate,
10
10
  } from "../utils";
11
- import { useEscape } from "./useEscape";
12
- import { useOutsideClickHandler } from "./useOutsideClickHandler";
13
11
 
14
12
  export interface UseMonthPickerOptions
15
13
  extends Pick<
@@ -45,8 +43,8 @@ export interface UseMonthPickerOptions
45
43
  */
46
44
  allowTwoDigitYear?: boolean;
47
45
  /**
48
- * Opens datepicker on input-focus
49
- * @default true
46
+ * Will be removed in a future major-version
47
+ * @deprecated
50
48
  */
51
49
  openOnFocus?: boolean;
52
50
  }
@@ -60,7 +58,12 @@ interface UseMonthPickerValue {
60
58
  * Use: <MonthPicker.Input {...inputProps} />
61
59
  */
62
60
  inputProps: Pick<DateInputProps, "onChange" | "onFocus" | "value"> & {
63
- ref: React.RefObject<HTMLInputElement>;
61
+ /**
62
+ * @private
63
+ */
64
+ setAnchorRef: React.Dispatch<
65
+ React.SetStateAction<HTMLButtonElement | null>
66
+ >;
64
67
  };
65
68
  /**
66
69
  * Currently selected Date
@@ -138,17 +141,14 @@ export const useMonthpicker = (
138
141
  onValidate,
139
142
  defaultYear,
140
143
  allowTwoDigitYear = true,
141
- openOnFocus = true,
142
144
  } = opt;
143
145
 
146
+ const [anchorRef, setAnchorRef] = useState<HTMLButtonElement | null>(null);
144
147
  const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
145
148
 
146
149
  const today = useMemo(() => new Date(), []);
147
150
  const locale = getLocaleFromString(_locale);
148
151
 
149
- const inputRef = useRef<HTMLInputElement>(null);
150
- const [monthpickerRef, setMonthpickerRef] = useState<HTMLDivElement>();
151
-
152
152
  // Initialize states
153
153
  const [year, setYear] = useState(defaultSelected ?? defaultYear ?? today);
154
154
  const [selectedMonth, setSelectedMonth] = useState(defaultSelected);
@@ -169,14 +169,6 @@ export const useMonthpicker = (
169
169
  [defaultSelected, defaultYear, selectedMonth, today]
170
170
  );
171
171
 
172
- useOutsideClickHandler(open, handleOpen, [
173
- monthpickerRef,
174
- inputRef.current,
175
- inputRef.current?.nextSibling,
176
- ]);
177
-
178
- useEscape(open, handleOpen, inputRef);
179
-
180
172
  const updateMonth = (date?: Date) => {
181
173
  onMonthChange?.(date);
182
174
  setSelectedMonth(date);
@@ -204,7 +196,7 @@ export const useMonthpicker = (
204
196
  if (e.target.readOnly) {
205
197
  return;
206
198
  }
207
- !open && openOnFocus && handleOpen(true);
199
+
208
200
  const day = parseDate(
209
201
  e.target.value,
210
202
  today,
@@ -239,8 +231,8 @@ export const useMonthpicker = (
239
231
  const handleMonthClick = (month?: Date) => {
240
232
  if (month) {
241
233
  handleOpen(false);
242
- inputRef.current && inputRef.current.focus();
243
234
  setYear(month);
235
+ anchorRef?.focus();
244
236
  }
245
237
 
246
238
  if (!required && !month) {
@@ -314,9 +306,11 @@ export const useMonthpicker = (
314
306
  toDate,
315
307
  open,
316
308
  onOpenToggle: () => handleOpen(!open),
309
+ onClose: () => {
310
+ handleOpen(false);
311
+ anchorRef?.focus();
312
+ },
317
313
  disabled,
318
- bubbleEscape: true,
319
- ref: setMonthpickerRef,
320
314
  };
321
315
 
322
316
  const inputProps = {
@@ -324,7 +318,7 @@ export const useMonthpicker = (
324
318
  onFocus: handleFocus,
325
319
  onBlur: handleBlur,
326
320
  value: inputValue,
327
- ref: inputRef,
321
+ setAnchorRef,
328
322
  };
329
323
 
330
324
  return { monthpickerProps, inputProps, reset, selectedMonth, setSelected };