@navikt/ds-react 5.8.0 → 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.
- package/_docs.json +1794 -1749
- package/cjs/date/context/useDateInputContext.js +1 -5
- package/cjs/date/datepicker/DatePicker.js +26 -25
- package/cjs/date/hooks/useDatepicker.js +9 -17
- package/cjs/date/hooks/useMonthPicker.js +9 -17
- package/cjs/date/hooks/useRangeDatepicker.js +9 -20
- package/cjs/date/monthpicker/MonthPicker.js +11 -6
- package/cjs/date/{DateInput.js → parts/DateInput.js} +14 -10
- package/cjs/date/parts/DateWrapper.js +55 -0
- package/cjs/date/utils/labels.js +77 -1
- package/cjs/form/combobox/Combobox.js +2 -2
- package/cjs/form/combobox/ComboboxProvider.js +1 -2
- package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
- package/cjs/form/combobox/FilteredOptions/filtered-options-util.js +24 -0
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +23 -106
- package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js +55 -0
- package/cjs/form/combobox/Input/Input.js +22 -13
- package/cjs/form/combobox/customOptionsContext.js +2 -3
- package/cjs/modal/Modal.js +4 -1
- package/cjs/popover/Popover.js +5 -7
- package/cjs/util/useMedia.js +30 -0
- package/esm/date/context/useDateInputContext.d.ts +6 -2
- package/esm/date/context/useDateInputContext.js +1 -5
- package/esm/date/context/useDateInputContext.js.map +1 -1
- package/esm/date/datepicker/DatePicker.d.ts +1 -1
- package/esm/date/datepicker/DatePicker.js +28 -27
- package/esm/date/datepicker/DatePicker.js.map +1 -1
- package/esm/date/datepicker/types.d.ts +0 -5
- package/esm/date/hooks/useDatepicker.d.ts +8 -5
- package/esm/date/hooks/useDatepicker.js +10 -18
- package/esm/date/hooks/useDatepicker.js.map +1 -1
- package/esm/date/hooks/useMonthPicker.d.ts +7 -4
- package/esm/date/hooks/useMonthPicker.js +10 -18
- package/esm/date/hooks/useMonthPicker.js.map +1 -1
- package/esm/date/hooks/useRangeDatepicker.d.ts +9 -3
- package/esm/date/hooks/useRangeDatepicker.js +10 -21
- package/esm/date/hooks/useRangeDatepicker.js.map +1 -1
- package/esm/date/index.d.ts +1 -1
- package/esm/date/index.js.map +1 -1
- package/esm/date/monthpicker/MonthPicker.d.ts +1 -1
- package/esm/date/monthpicker/MonthPicker.js +13 -8
- package/esm/date/monthpicker/MonthPicker.js.map +1 -1
- package/esm/date/monthpicker/types.d.ts +0 -5
- package/esm/date/{DateInput.d.ts → parts/DateInput.d.ts} +5 -1
- package/esm/date/{DateInput.js → parts/DateInput.js} +15 -11
- package/esm/date/parts/DateInput.js.map +1 -0
- package/esm/date/parts/DateWrapper.d.ts +15 -0
- package/esm/date/parts/DateWrapper.js +26 -0
- package/esm/date/parts/DateWrapper.js.map +1 -0
- package/esm/date/utils/labels.d.ts +2 -0
- package/esm/date/utils/labels.js +74 -0
- package/esm/date/utils/labels.js.map +1 -1
- package/esm/form/combobox/Combobox.js +2 -2
- package/esm/form/combobox/Combobox.js.map +1 -1
- package/esm/form/combobox/ComboboxProvider.js +1 -2
- package/esm/form/combobox/ComboboxProvider.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/filtered-options-util.d.ts +12 -0
- package/esm/form/combobox/FilteredOptions/filtered-options-util.js +23 -0
- package/esm/form/combobox/FilteredOptions/filtered-options-util.js.map +1 -0
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +10 -13
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +24 -107
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.d.ts +15 -0
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js +54 -0
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -0
- package/esm/form/combobox/Input/Input.js +22 -13
- package/esm/form/combobox/Input/Input.js.map +1 -1
- package/esm/form/combobox/customOptionsContext.d.ts +4 -1
- package/esm/form/combobox/customOptionsContext.js +2 -3
- package/esm/form/combobox/customOptionsContext.js.map +1 -1
- package/esm/modal/Modal.js +4 -1
- package/esm/modal/Modal.js.map +1 -1
- package/esm/popover/Popover.d.ts +0 -5
- package/esm/popover/Popover.js +5 -7
- package/esm/popover/Popover.js.map +1 -1
- package/esm/util/useMedia.d.ts +8 -0
- package/esm/util/useMedia.js +27 -0
- package/esm/util/useMedia.js.map +1 -0
- package/package.json +3 -3
- package/src/date/context/useDateInputContext.tsx +5 -5
- package/src/date/datepicker/DatePicker.tsx +58 -65
- package/src/date/datepicker/datepicker.stories.tsx +37 -46
- package/src/date/datepicker/types.ts +0 -5
- package/src/date/hooks/useDatepicker.tsx +20 -25
- package/src/date/hooks/useMonthPicker.tsx +18 -24
- package/src/date/hooks/useRangeDatepicker.tsx +27 -30
- package/src/date/index.ts +1 -1
- package/src/date/monthpicker/MonthPicker.tsx +39 -43
- package/src/date/monthpicker/types.ts +0 -5
- package/src/date/{DateInput.tsx → parts/DateInput.tsx} +23 -12
- package/src/date/parts/DateWrapper.tsx +80 -0
- package/src/date/utils/labels.ts +83 -0
- package/src/form/combobox/Combobox.tsx +2 -2
- package/src/form/combobox/ComboboxProvider.tsx +1 -2
- package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +28 -16
- package/src/form/combobox/FilteredOptions/filtered-options-util.ts +38 -0
- package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +70 -140
- package/src/form/combobox/FilteredOptions/useVirtualFocus.ts +87 -0
- package/src/form/combobox/Input/Input.tsx +22 -18
- package/src/form/combobox/customOptionsContext.tsx +10 -5
- package/src/guide-panel/guidepanel.stories.tsx +2 -2
- package/src/modal/Modal.tsx +4 -1
- package/src/popover/Popover.tsx +4 -12
- package/src/util/__tests__/useMedia.test.tsx +19 -0
- package/src/util/useMedia.ts +38 -0
- package/cjs/date/hooks/useEscape.js +0 -23
- package/cjs/date/hooks/useOutsideClickHandler.js +0 -26
- package/esm/date/DateInput.js.map +0 -1
- package/esm/date/hooks/useEscape.d.ts +0 -2
- package/esm/date/hooks/useEscape.js +0 -20
- package/esm/date/hooks/useEscape.js.map +0 -1
- package/esm/date/hooks/useOutsideClickHandler.d.ts +0 -1
- package/esm/date/hooks/useOutsideClickHandler.js +0 -23
- package/esm/date/hooks/useOutsideClickHandler.js.map +0 -1
- package/src/date/hooks/useEscape.tsx +0 -30
- package/src/date/hooks/useOutsideClickHandler.tsx +0 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navikt/ds-react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "Aksel react-components for NAV designsystem",
|
|
5
5
|
"author": "Aksel | NAV designsystem team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@floating-ui/react": "0.25.4",
|
|
41
|
-
"@navikt/aksel-icons": "^5.
|
|
42
|
-
"@navikt/ds-tokens": "^5.
|
|
41
|
+
"@navikt/aksel-icons": "^5.9.0",
|
|
42
|
+
"@navikt/ds-tokens": "^5.9.0",
|
|
43
43
|
"@radix-ui/react-tabs": "1.0.0",
|
|
44
44
|
"@radix-ui/react-toggle-group": "1.0.0",
|
|
45
45
|
"clsx": "^1.2.1",
|
|
@@ -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 {
|
|
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={
|
|
164
|
+
ref={mergedRef}
|
|
126
165
|
className={cl("navds-date__wrapper", wrapperClassName)}
|
|
127
166
|
>
|
|
128
167
|
{children}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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,
|
|
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
|
|
329
|
+
<DatePicker.Input
|
|
330
|
+
placeholder="10/10/2023"
|
|
331
|
+
size="medium"
|
|
332
|
+
{...inputProps}
|
|
333
|
+
label="Velg dato"
|
|
334
|
+
/>
|
|
342
335
|
</DatePicker>
|
|
343
|
-
<DatePicker {...
|
|
344
|
-
<DatePicker.Input
|
|
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" }}
|
|
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.
|
|
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
|
-
<
|
|
454
|
-
<
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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,
|
|
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
|
-
*
|
|
63
|
-
* @
|
|
60
|
+
* Will be removed in a future major-version
|
|
61
|
+
* @deprecated
|
|
64
62
|
*/
|
|
65
|
-
openOnFocus?:
|
|
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
|
-
> & {
|
|
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
|
-
|
|
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
|
-
|
|
329
|
+
setAnchorRef,
|
|
335
330
|
};
|
|
336
331
|
|
|
337
332
|
return { datepickerProps, inputProps, reset, selectedDay, setSelected };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { useCallback, useMemo,
|
|
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
|
-
*
|
|
49
|
-
* @
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
321
|
+
setAnchorRef,
|
|
328
322
|
};
|
|
329
323
|
|
|
330
324
|
return { monthpickerProps, inputProps, reset, selectedMonth, setSelected };
|