@navikt/ds-react 7.0.1 → 7.1.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.
- package/cjs/collapsible/Collapsible.context.d.ts +1 -1
- package/cjs/form/combobox/Combobox.js +5 -2
- package/cjs/form/combobox/Combobox.js.map +1 -1
- package/cjs/form/combobox/ComboboxProvider.js +2 -1
- package/cjs/form/combobox/ComboboxProvider.js.map +1 -1
- package/cjs/form/combobox/ComboboxWrapper.d.ts +1 -0
- package/cjs/form/combobox/ComboboxWrapper.js +3 -1
- package/cjs/form/combobox/ComboboxWrapper.js.map +1 -1
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +6 -1
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/cjs/form/combobox/Input/Input.context.d.ts +1 -0
- package/cjs/form/combobox/Input/Input.context.js +2 -1
- package/cjs/form/combobox/Input/Input.context.js.map +1 -1
- package/cjs/form/combobox/Input/Input.js +6 -2
- package/cjs/form/combobox/Input/Input.js.map +1 -1
- package/cjs/form/combobox/Input/InputController.js +3 -3
- package/cjs/form/combobox/Input/InputController.js.map +1 -1
- package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +2 -2
- package/cjs/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
- package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +2 -2
- package/cjs/form/combobox/types.d.ts +10 -11
- package/cjs/form/error-summary/ErrorSummary.d.ts +3 -3
- package/cjs/form/error-summary/ErrorSummary.js +6 -7
- package/cjs/form/error-summary/ErrorSummary.js.map +1 -1
- package/cjs/form/file-upload/FileUpload.context.d.ts +1 -1
- package/cjs/form/form-summary/FormSummaryEditLink.js +2 -2
- package/cjs/form/form-summary/FormSummaryEditLink.js.map +1 -1
- package/cjs/layout/page/parts/PageBlock.js +1 -1
- package/cjs/layout/page/parts/PageBlock.js.map +1 -1
- package/cjs/layout/stack/HStack.js +14 -2
- package/cjs/layout/stack/HStack.js.map +1 -1
- package/cjs/layout/stack/VStack.js +14 -2
- package/cjs/layout/stack/VStack.js.map +1 -1
- package/cjs/list/List.d.ts +4 -1
- package/cjs/list/List.js +6 -12
- package/cjs/list/List.js.map +1 -1
- package/cjs/list/ListItem.d.ts +1 -1
- package/cjs/list/ListItem.js +3 -3
- package/cjs/list/ListItem.js.map +1 -1
- package/cjs/list/context.d.ts +2 -3
- package/cjs/list/context.js +0 -1
- package/cjs/list/context.js.map +1 -1
- package/cjs/list/types.d.ts +1 -1
- package/cjs/overlays/floating/Floating.utils.d.ts +1 -1
- package/cjs/pagination/Pagination.js +6 -7
- package/cjs/pagination/Pagination.js.map +1 -1
- package/cjs/pagination/PaginationItem.d.ts +3 -2
- package/cjs/pagination/PaginationItem.js +1 -1
- package/cjs/pagination/PaginationItem.js.map +1 -1
- package/cjs/stepper/context.d.ts +1 -1
- package/cjs/tabs/Tabs.context.d.ts +1 -1
- package/cjs/toggle-group/ToggleGroup.context.d.ts +1 -1
- package/cjs/util/create-context.js.map +1 -1
- package/cjs/util/virtualfocus/Context.d.ts +1 -1
- package/esm/collapsible/Collapsible.context.d.ts +1 -1
- package/esm/form/combobox/Combobox.js +5 -2
- package/esm/form/combobox/Combobox.js.map +1 -1
- package/esm/form/combobox/ComboboxProvider.js +2 -1
- package/esm/form/combobox/ComboboxProvider.js.map +1 -1
- package/esm/form/combobox/ComboboxWrapper.d.ts +1 -0
- package/esm/form/combobox/ComboboxWrapper.js +3 -1
- package/esm/form/combobox/ComboboxWrapper.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +6 -1
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/esm/form/combobox/Input/Input.context.d.ts +1 -0
- package/esm/form/combobox/Input/Input.context.js +2 -1
- package/esm/form/combobox/Input/Input.context.js.map +1 -1
- package/esm/form/combobox/Input/Input.js +6 -2
- package/esm/form/combobox/Input/Input.js.map +1 -1
- package/esm/form/combobox/Input/InputController.js +3 -3
- package/esm/form/combobox/Input/InputController.js.map +1 -1
- package/esm/form/combobox/SelectedOptions/SelectedOptions.js +2 -2
- package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +2 -2
- package/esm/form/combobox/types.d.ts +10 -11
- package/esm/form/error-summary/ErrorSummary.d.ts +3 -3
- package/esm/form/error-summary/ErrorSummary.js +7 -8
- package/esm/form/error-summary/ErrorSummary.js.map +1 -1
- package/esm/form/file-upload/FileUpload.context.d.ts +1 -1
- package/esm/form/form-summary/FormSummaryEditLink.js +2 -2
- package/esm/form/form-summary/FormSummaryEditLink.js.map +1 -1
- package/esm/layout/page/parts/PageBlock.js +1 -1
- package/esm/layout/page/parts/PageBlock.js.map +1 -1
- package/esm/layout/stack/HStack.js +14 -2
- package/esm/layout/stack/HStack.js.map +1 -1
- package/esm/layout/stack/VStack.js +14 -2
- package/esm/layout/stack/VStack.js.map +1 -1
- package/esm/list/List.d.ts +4 -1
- package/esm/list/List.js +7 -13
- package/esm/list/List.js.map +1 -1
- package/esm/list/ListItem.d.ts +1 -1
- package/esm/list/ListItem.js +3 -3
- package/esm/list/ListItem.js.map +1 -1
- package/esm/list/context.d.ts +2 -3
- package/esm/list/context.js +0 -1
- package/esm/list/context.js.map +1 -1
- package/esm/list/types.d.ts +1 -1
- package/esm/overlays/floating/Floating.utils.d.ts +1 -1
- package/esm/pagination/Pagination.js +6 -7
- package/esm/pagination/Pagination.js.map +1 -1
- package/esm/pagination/PaginationItem.d.ts +3 -2
- package/esm/pagination/PaginationItem.js +1 -1
- package/esm/pagination/PaginationItem.js.map +1 -1
- package/esm/stepper/context.d.ts +1 -1
- package/esm/tabs/Tabs.context.d.ts +1 -1
- package/esm/toggle-group/ToggleGroup.context.d.ts +1 -1
- package/esm/util/create-context.js.map +1 -1
- package/esm/util/virtualfocus/Context.d.ts +1 -1
- package/package.json +3 -3
- package/src/date/datepicker/datepicker.test.tsx +1 -1
- package/src/date/utils/__tests__/parse-dates.test.ts +12 -12
- package/src/form/combobox/Combobox.tsx +3 -0
- package/src/form/combobox/ComboboxProvider.tsx +2 -0
- package/src/form/combobox/ComboboxWrapper.tsx +4 -1
- package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +7 -1
- package/src/form/combobox/Input/Input.context.tsx +3 -0
- package/src/form/combobox/Input/Input.tsx +6 -0
- package/src/form/combobox/Input/InputController.tsx +3 -0
- package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +8 -2
- package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +2 -2
- package/src/form/combobox/types.ts +10 -12
- package/src/form/error-summary/ErrorSummary.tsx +9 -15
- package/src/form/form-summary/FormSummaryEditLink.tsx +12 -9
- package/src/layout/page/parts/PageBlock.tsx +1 -1
- package/src/layout/stack/HStack.tsx +2 -2
- package/src/layout/stack/VStack.tsx +4 -2
- package/src/list/List.tsx +15 -25
- package/src/list/ListItem.tsx +6 -6
- package/src/list/context.ts +2 -4
- package/src/list/types.ts +1 -1
- package/src/pagination/Pagination.tsx +7 -22
- package/src/pagination/PaginationItem.tsx +4 -3
- package/src/util/create-context.tsx +2 -2
|
@@ -4,29 +4,29 @@ import { describe, expect, test } from "vitest";
|
|
|
4
4
|
import { isValidDate, parseDate } from "..";
|
|
5
5
|
|
|
6
6
|
const check = (inp: string) =>
|
|
7
|
-
// eslint-disable-next-line vitest/valid-expect
|
|
7
|
+
// eslint-disable-next-line @vitest/valid-expect
|
|
8
8
|
expect(isValidDate(parseDate(inp, new Date(), nb, "date", false)));
|
|
9
9
|
|
|
10
10
|
const checkTwoDigit = (inp: string) =>
|
|
11
|
-
// eslint-disable-next-line vitest/valid-expect
|
|
11
|
+
// eslint-disable-next-line @vitest/valid-expect
|
|
12
12
|
expect(isValidDate(parseDate(inp, new Date(), nb, "date", true)));
|
|
13
13
|
|
|
14
14
|
const parse = (inp: string) => parseDate(inp, new Date(), nb, "date", false);
|
|
15
15
|
|
|
16
16
|
describe("Parse date-inputs with 4-digit years", () => {
|
|
17
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
17
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
18
18
|
test("No spaces", () => {
|
|
19
19
|
check("11052022").toBeTruthy();
|
|
20
20
|
check("15052022").toBeTruthy();
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
23
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
24
24
|
test(". divider", () => {
|
|
25
25
|
check("1.5.2022").toBeTruthy();
|
|
26
26
|
check("11.05.2022").toBeTruthy();
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
29
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
30
30
|
test("/ divider", () => {
|
|
31
31
|
check("1/5/2022").toBeTruthy();
|
|
32
32
|
check("10/5/2022").toBeTruthy();
|
|
@@ -34,7 +34,7 @@ describe("Parse date-inputs with 4-digit years", () => {
|
|
|
34
34
|
check("10/05/2022").toBeTruthy();
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
37
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
38
38
|
test("- divider", () => {
|
|
39
39
|
check("1-5-2022").toBeTruthy();
|
|
40
40
|
check("10-5-2022").toBeTruthy();
|
|
@@ -44,19 +44,19 @@ describe("Parse date-inputs with 4-digit years", () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
describe("Parse date-inputs with 2-digit years", () => {
|
|
47
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
47
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
48
48
|
test("No spaces", () => {
|
|
49
49
|
checkTwoDigit("110522").toBeTruthy();
|
|
50
50
|
checkTwoDigit("150522").toBeTruthy();
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
53
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
54
54
|
test(". divider", () => {
|
|
55
55
|
checkTwoDigit("1.5.22").toBeTruthy();
|
|
56
56
|
checkTwoDigit("11.05.22").toBeTruthy();
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
59
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
60
60
|
test("/ divider", () => {
|
|
61
61
|
checkTwoDigit("1/5/22").toBeTruthy();
|
|
62
62
|
checkTwoDigit("10/5/22").toBeTruthy();
|
|
@@ -64,7 +64,7 @@ describe("Parse date-inputs with 2-digit years", () => {
|
|
|
64
64
|
checkTwoDigit("10/05/22").toBeTruthy();
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
67
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
68
68
|
test("- divider", () => {
|
|
69
69
|
checkTwoDigit("1-5-22").toBeTruthy();
|
|
70
70
|
checkTwoDigit("10-5-22").toBeTruthy();
|
|
@@ -72,14 +72,14 @@ describe("Parse date-inputs with 2-digit years", () => {
|
|
|
72
72
|
checkTwoDigit("10-05-22").toBeTruthy();
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
75
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
76
76
|
test("Dissallow 1 and 3 digit years", () => {
|
|
77
77
|
checkTwoDigit("11052").toBeFalsy();
|
|
78
78
|
checkTwoDigit("1105222").toBeFalsy();
|
|
79
79
|
checkTwoDigit("1105999").toBeFalsy();
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
// eslint-disable-next-line vitest/expect-expect
|
|
82
|
+
// eslint-disable-next-line @vitest/expect-expect
|
|
83
83
|
test("Dissallow date before year 1000", () => {
|
|
84
84
|
checkTwoDigit("11050999").toBeFalsy();
|
|
85
85
|
checkTwoDigit("11050010").toBeFalsy();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import cl from "clsx";
|
|
2
2
|
import React, { forwardRef } from "react";
|
|
3
3
|
import { BodyShort, ErrorMessage, Label } from "../../typography";
|
|
4
|
+
import { ReadOnlyIcon } from "../ReadOnlyIcon";
|
|
4
5
|
import ComboboxWrapper from "./ComboboxWrapper";
|
|
5
6
|
import FilteredOptions from "./FilteredOptions/FilteredOptions";
|
|
6
7
|
import { useFilteredOptionsContext } from "./FilteredOptions/filteredOptionsContext";
|
|
@@ -27,6 +28,7 @@ export const Combobox = forwardRef<
|
|
|
27
28
|
inputProps,
|
|
28
29
|
showErrorMsg,
|
|
29
30
|
size = "medium",
|
|
31
|
+
readOnly,
|
|
30
32
|
} = useInputContext();
|
|
31
33
|
|
|
32
34
|
return (
|
|
@@ -44,6 +46,7 @@ export const Combobox = forwardRef<
|
|
|
44
46
|
"navds-sr-only": hideLabel,
|
|
45
47
|
})}
|
|
46
48
|
>
|
|
49
|
+
<ReadOnlyIcon nativeReadOnly={false} readOnly={readOnly} />
|
|
47
50
|
{label}
|
|
48
51
|
</Label>
|
|
49
52
|
{!!description && (
|
|
@@ -36,6 +36,7 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
|
|
|
36
36
|
children,
|
|
37
37
|
defaultValue,
|
|
38
38
|
disabled,
|
|
39
|
+
readOnly,
|
|
39
40
|
error,
|
|
40
41
|
errorId,
|
|
41
42
|
filteredOptions: externalFilteredOptions,
|
|
@@ -63,6 +64,7 @@ const ComboboxProvider = forwardRef<HTMLInputElement, ComboboxProps>(
|
|
|
63
64
|
defaultValue,
|
|
64
65
|
description: rest.description,
|
|
65
66
|
disabled,
|
|
67
|
+
readOnly,
|
|
66
68
|
error,
|
|
67
69
|
errorId,
|
|
68
70
|
id,
|
|
@@ -9,6 +9,7 @@ type ComboboxWrapperProps = {
|
|
|
9
9
|
inputProps: {
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
};
|
|
12
|
+
readOnly?: boolean;
|
|
12
13
|
inputSize: string;
|
|
13
14
|
toggleIsListOpen: (isListOpen: boolean) => void;
|
|
14
15
|
};
|
|
@@ -21,7 +22,7 @@ const ComboboxWrapper = ({
|
|
|
21
22
|
inputSize,
|
|
22
23
|
toggleIsListOpen,
|
|
23
24
|
}: ComboboxWrapperProps) => {
|
|
24
|
-
const { toggleOpenButtonRef, clearInput } = useInputContext();
|
|
25
|
+
const { toggleOpenButtonRef, clearInput, readOnly } = useInputContext();
|
|
25
26
|
|
|
26
27
|
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
27
28
|
const [hasFocusWithin, setHasFocusWithin] = useState(false);
|
|
@@ -55,6 +56,8 @@ const ComboboxWrapper = ({
|
|
|
55
56
|
"navds-combobox--error": hasError,
|
|
56
57
|
"navds-combobox--disabled": !!inputProps.disabled,
|
|
57
58
|
"navds-combobox--focused": hasFocusWithin,
|
|
59
|
+
"navds-combobox--readonly": readOnly,
|
|
60
|
+
"navds-form-field--readonly": readOnly,
|
|
58
61
|
},
|
|
59
62
|
)}
|
|
60
63
|
onFocus={onFocusInsideWrapper}
|
|
@@ -58,7 +58,8 @@ const FilteredOptionsProvider = ({
|
|
|
58
58
|
useState<HTMLUListElement | null>(null);
|
|
59
59
|
const virtualFocus = useVirtualFocus(filteredOptionsRef);
|
|
60
60
|
const {
|
|
61
|
-
inputProps: { "aria-describedby": partialAriaDescribedBy, id },
|
|
61
|
+
inputProps: { "aria-describedby": partialAriaDescribedBy, id, disabled },
|
|
62
|
+
readOnly,
|
|
62
63
|
value,
|
|
63
64
|
searchTerm,
|
|
64
65
|
setValue,
|
|
@@ -136,6 +137,9 @@ const FilteredOptionsProvider = ({
|
|
|
136
137
|
|
|
137
138
|
const toggleIsListOpen = useCallback(
|
|
138
139
|
(newState?: boolean) => {
|
|
140
|
+
if (disabled || readOnly) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
139
143
|
virtualFocus.moveFocusToTop();
|
|
140
144
|
if (newState ?? !isInternalListOpen) {
|
|
141
145
|
setHideCaret(!!maxSelected?.isLimitReached);
|
|
@@ -147,6 +151,8 @@ const FilteredOptionsProvider = ({
|
|
|
147
151
|
maxSelected?.isLimitReached,
|
|
148
152
|
isInternalListOpen,
|
|
149
153
|
setHideCaret,
|
|
154
|
+
disabled,
|
|
155
|
+
readOnly,
|
|
150
156
|
],
|
|
151
157
|
);
|
|
152
158
|
|
|
@@ -32,6 +32,7 @@ interface Props {
|
|
|
32
32
|
defaultValue: ComboboxProps["defaultValue"];
|
|
33
33
|
description: ComboboxProps["description"];
|
|
34
34
|
disabled: ComboboxProps["disabled"];
|
|
35
|
+
readOnly: ComboboxProps["readOnly"];
|
|
35
36
|
error: ComboboxProps["error"];
|
|
36
37
|
errorId: ComboboxProps["errorId"];
|
|
37
38
|
id: ComboboxProps["id"];
|
|
@@ -48,6 +49,7 @@ const InputProvider = ({ children, value: props }: Props) => {
|
|
|
48
49
|
defaultValue = "",
|
|
49
50
|
description,
|
|
50
51
|
disabled,
|
|
52
|
+
readOnly,
|
|
51
53
|
error,
|
|
52
54
|
errorId,
|
|
53
55
|
id: externalId,
|
|
@@ -61,6 +63,7 @@ const InputProvider = ({ children, value: props }: Props) => {
|
|
|
61
63
|
{
|
|
62
64
|
description,
|
|
63
65
|
disabled,
|
|
66
|
+
readOnly,
|
|
64
67
|
error,
|
|
65
68
|
errorId,
|
|
66
69
|
id: externalId,
|
|
@@ -49,6 +49,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
49
49
|
setValue,
|
|
50
50
|
hideCaret,
|
|
51
51
|
setHideCaret,
|
|
52
|
+
readOnly,
|
|
52
53
|
} = useInputContext();
|
|
53
54
|
const {
|
|
54
55
|
selectedOptions,
|
|
@@ -149,6 +150,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
149
150
|
const handleKeyDown = useCallback(
|
|
150
151
|
(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
151
152
|
setIsMouseLastUsedInputDevice(false);
|
|
153
|
+
if (readOnly) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
152
156
|
if (e.key === "Backspace") {
|
|
153
157
|
if (value === "" && shouldShowSelectedOptions) {
|
|
154
158
|
const lastSelectedOption =
|
|
@@ -214,6 +218,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
214
218
|
setValue,
|
|
215
219
|
searchTerm,
|
|
216
220
|
shouldShowSelectedOptions,
|
|
221
|
+
readOnly,
|
|
217
222
|
],
|
|
218
223
|
);
|
|
219
224
|
|
|
@@ -262,6 +267,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
262
267
|
aria-activedescendant={activeDecendantId}
|
|
263
268
|
aria-describedby={ariaDescribedBy}
|
|
264
269
|
aria-invalid={inputProps["aria-invalid"]}
|
|
270
|
+
readOnly={readOnly}
|
|
265
271
|
/>
|
|
266
272
|
);
|
|
267
273
|
},
|
|
@@ -45,6 +45,7 @@ export const InputController = forwardRef<
|
|
|
45
45
|
size = "medium",
|
|
46
46
|
inputRef,
|
|
47
47
|
toggleOpenButtonRef,
|
|
48
|
+
readOnly,
|
|
48
49
|
} = useInputContext();
|
|
49
50
|
|
|
50
51
|
const { activeDecendantId } = useFilteredOptionsContext();
|
|
@@ -65,6 +66,7 @@ export const InputController = forwardRef<
|
|
|
65
66
|
id={inputProps.id}
|
|
66
67
|
ref={mergedInputRef}
|
|
67
68
|
inputClassName={inputClassName}
|
|
69
|
+
readOnly={readOnly}
|
|
68
70
|
{...rest}
|
|
69
71
|
/>
|
|
70
72
|
) : (
|
|
@@ -74,6 +76,7 @@ export const InputController = forwardRef<
|
|
|
74
76
|
ref={mergedInputRef}
|
|
75
77
|
inputClassName={inputClassName}
|
|
76
78
|
shouldShowSelectedOptions={shouldShowSelectedOptions}
|
|
79
|
+
readOnly={readOnly}
|
|
77
80
|
{...rest}
|
|
78
81
|
/>
|
|
79
82
|
</SelectedOptions>
|
|
@@ -12,7 +12,7 @@ interface SelectedOptionsProps {
|
|
|
12
12
|
|
|
13
13
|
const Option = ({ option }: { option: ComboboxOption }) => {
|
|
14
14
|
const { isMultiSelect, removeSelectedOption } = useSelectedOptionsContext();
|
|
15
|
-
const { focusInput } = useInputContext();
|
|
15
|
+
const { focusInput, readOnly, inputProps } = useInputContext();
|
|
16
16
|
|
|
17
17
|
const onClick = (e) => {
|
|
18
18
|
e.stopPropagation();
|
|
@@ -28,7 +28,13 @@ const Option = ({ option }: { option: ComboboxOption }) => {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
return
|
|
31
|
+
return readOnly || inputProps.disabled ? (
|
|
32
|
+
<Chips.Toggle variant="neutral" checkmark={false} as="div">
|
|
33
|
+
{option.label}
|
|
34
|
+
</Chips.Toggle>
|
|
35
|
+
) : (
|
|
36
|
+
<Chips.Removable onClick={onClick}>{option.label}</Chips.Removable>
|
|
37
|
+
);
|
|
32
38
|
};
|
|
33
39
|
|
|
34
40
|
const SelectedOptions: React.FC<SelectedOptionsProps> = ({
|
|
@@ -4,7 +4,7 @@ import { usePrevious } from "../../../util/hooks";
|
|
|
4
4
|
import { useInputContext } from "../Input/Input.context";
|
|
5
5
|
import { isInList } from "../combobox-utils";
|
|
6
6
|
import { useComboboxCustomOptions } from "../customOptionsContext";
|
|
7
|
-
import { ComboboxOption, ComboboxProps
|
|
7
|
+
import { ComboboxOption, ComboboxProps } from "../types";
|
|
8
8
|
|
|
9
9
|
type SelectedOptionsContextValue = {
|
|
10
10
|
addSelectedOption: (option: ComboboxOption) => void;
|
|
@@ -12,7 +12,7 @@ type SelectedOptionsContextValue = {
|
|
|
12
12
|
removeSelectedOption: (option: ComboboxOption) => void;
|
|
13
13
|
prevSelectedOptions?: ComboboxOption[];
|
|
14
14
|
selectedOptions: ComboboxOption[];
|
|
15
|
-
maxSelected?:
|
|
15
|
+
maxSelected?: ComboboxProps["maxSelected"] & { isLimitReached: boolean };
|
|
16
16
|
setSelectedOptions: (any) => void;
|
|
17
17
|
toggleOption: (
|
|
18
18
|
option: ComboboxOption,
|
|
@@ -16,17 +16,6 @@ export type ComboboxOption = {
|
|
|
16
16
|
value: string;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export type MaxSelected = {
|
|
20
|
-
/**
|
|
21
|
-
* The limit for maximum selected options
|
|
22
|
-
*/
|
|
23
|
-
limit: number;
|
|
24
|
-
/**
|
|
25
|
-
* Override the message to display when the limit for maximum selected options has been reached
|
|
26
|
-
*/
|
|
27
|
-
message?: string;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
19
|
export interface ComboboxProps
|
|
31
20
|
extends FormFieldProps,
|
|
32
21
|
Omit<
|
|
@@ -135,7 +124,16 @@ export interface ComboboxProps
|
|
|
135
124
|
/**
|
|
136
125
|
* Options for the maximum number of selected options.
|
|
137
126
|
*/
|
|
138
|
-
maxSelected?:
|
|
127
|
+
maxSelected?: {
|
|
128
|
+
/**
|
|
129
|
+
* The limit for maximum selected options
|
|
130
|
+
*/
|
|
131
|
+
limit: number;
|
|
132
|
+
/**
|
|
133
|
+
* Override the message to display when the limit for maximum selected options has been reached
|
|
134
|
+
*/
|
|
135
|
+
message?: string;
|
|
136
|
+
};
|
|
139
137
|
/**
|
|
140
138
|
* Set to `true` to enable inline autocomplete.
|
|
141
139
|
*
|
|
@@ -2,7 +2,7 @@ import cl from "clsx";
|
|
|
2
2
|
import React, { HTMLAttributes, forwardRef, useRef } from "react";
|
|
3
3
|
import { BodyShort, Heading } from "../../typography";
|
|
4
4
|
import { composeEventHandlers } from "../../util/composeEventHandlers";
|
|
5
|
-
import {
|
|
5
|
+
import { useMergeRefs } from "../../util/hooks";
|
|
6
6
|
import ErrorSummaryItem from "./ErrorSummaryItem";
|
|
7
7
|
|
|
8
8
|
export interface ErrorSummaryProps
|
|
@@ -33,13 +33,13 @@ interface ErrorSummaryComponent
|
|
|
33
33
|
ErrorSummaryProps & React.RefAttributes<HTMLDivElement>
|
|
34
34
|
> {
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Error message with link to field.
|
|
37
37
|
*
|
|
38
38
|
* @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
|
|
39
39
|
*
|
|
40
40
|
* @example
|
|
41
41
|
* ```jsx
|
|
42
|
-
* <ErrorSummary.Item href="#
|
|
42
|
+
* <ErrorSummary.Item href="#id-til-alderfelt">
|
|
43
43
|
* Felt må fylles ut med alder
|
|
44
44
|
* </ErrorSummary.Item>
|
|
45
45
|
* ```
|
|
@@ -48,7 +48,7 @@ interface ErrorSummaryComponent
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* Summary of errors in a form.
|
|
52
52
|
*
|
|
53
53
|
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/errorsummary)
|
|
54
54
|
* @see 🏷️ {@link ErrorSummaryProps}
|
|
@@ -77,15 +77,13 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
|
|
|
77
77
|
},
|
|
78
78
|
ref,
|
|
79
79
|
) => {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
const sectionRef = useRef<HTMLDivElement>(null);
|
|
80
|
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
83
81
|
const headingRef = useRef<HTMLHeadingElement>(null);
|
|
84
82
|
|
|
85
|
-
const mergedRef = useMergeRefs(ref,
|
|
83
|
+
const mergedRef = useMergeRefs(ref, wrapperRef);
|
|
86
84
|
|
|
87
85
|
return (
|
|
88
|
-
<
|
|
86
|
+
<div
|
|
89
87
|
ref={mergedRef}
|
|
90
88
|
{...rest}
|
|
91
89
|
className={cl(
|
|
@@ -94,11 +92,8 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
|
|
|
94
92
|
`navds-error-summary--${size}`,
|
|
95
93
|
)}
|
|
96
94
|
tabIndex={-1}
|
|
97
|
-
aria-live="polite"
|
|
98
|
-
aria-relevant="all"
|
|
99
|
-
aria-labelledby={headingId}
|
|
100
95
|
onFocus={composeEventHandlers(rest.onFocus, (event) => {
|
|
101
|
-
if (event.target ===
|
|
96
|
+
if (event.target === wrapperRef.current) {
|
|
102
97
|
headingRef?.current?.focus();
|
|
103
98
|
}
|
|
104
99
|
})}
|
|
@@ -107,7 +102,6 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
|
|
|
107
102
|
className="navds-error-summary__heading"
|
|
108
103
|
as={headingTag}
|
|
109
104
|
size="small"
|
|
110
|
-
id={headingId}
|
|
111
105
|
ref={headingRef}
|
|
112
106
|
tabIndex={-1}
|
|
113
107
|
>
|
|
@@ -116,7 +110,7 @@ export const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
|
|
|
116
110
|
<BodyShort as="ul" size={size} className="navds-error-summary__list">
|
|
117
111
|
{children}
|
|
118
112
|
</BodyShort>
|
|
119
|
-
</
|
|
113
|
+
</div>
|
|
120
114
|
);
|
|
121
115
|
},
|
|
122
116
|
) as ErrorSummaryComponent;
|
|
@@ -22,14 +22,17 @@ export interface FormSummaryEditProps
|
|
|
22
22
|
export const FormSummaryEditLink: OverridableComponent<
|
|
23
23
|
FormSummaryEditProps,
|
|
24
24
|
HTMLAnchorElement
|
|
25
|
-
> = forwardRef(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
> = forwardRef(
|
|
26
|
+
({ children = "Endre svar", className, as = "a", ...rest }, ref) => (
|
|
27
|
+
<Link
|
|
28
|
+
ref={ref}
|
|
29
|
+
as={as}
|
|
30
|
+
{...rest}
|
|
31
|
+
className={cl("navds-form-summary__edit", className)}
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
</Link>
|
|
35
|
+
),
|
|
36
|
+
);
|
|
34
37
|
|
|
35
38
|
export default FormSummaryEditLink;
|
|
@@ -63,7 +63,7 @@ export const PageBlock: OverridableComponent<PageBlockProps, HTMLDivElement> =
|
|
|
63
63
|
{...rest}
|
|
64
64
|
className={cl(
|
|
65
65
|
"navds-pageblock",
|
|
66
|
-
`navds-pageblock--${width}`,
|
|
66
|
+
width && `navds-pageblock--${width}`,
|
|
67
67
|
className,
|
|
68
68
|
{ "navds-pageblock--gutters": gutters },
|
|
69
69
|
)}
|
|
@@ -26,8 +26,8 @@ export type HStackProps = PrimitiveAsChildProps & Omit<StackProps, "direction">;
|
|
|
26
26
|
* </HStack>
|
|
27
27
|
*/
|
|
28
28
|
export const HStack: OverridableComponent<HStackProps, HTMLDivElement> =
|
|
29
|
-
forwardRef((
|
|
30
|
-
return <Stack {...
|
|
29
|
+
forwardRef(({ as = "div", ...rest }, ref) => {
|
|
30
|
+
return <Stack as={as} {...rest} ref={ref} direction="row" />;
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
export default HStack;
|
|
@@ -27,8 +27,10 @@ export type VStackProps = PrimitiveAsChildProps &
|
|
|
27
27
|
* </VStack>
|
|
28
28
|
*/
|
|
29
29
|
export const VStack: OverridableComponent<VStackProps, HTMLDivElement> =
|
|
30
|
-
forwardRef((
|
|
31
|
-
return
|
|
30
|
+
forwardRef(({ as = "div", ...rest }, ref) => {
|
|
31
|
+
return (
|
|
32
|
+
<Stack as={as} {...rest} ref={ref} direction="column" wrap={false} />
|
|
33
|
+
);
|
|
32
34
|
});
|
|
33
35
|
|
|
34
36
|
export default VStack;
|
package/src/list/List.tsx
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import cl from "clsx";
|
|
2
2
|
import React, { forwardRef, useContext } from "react";
|
|
3
|
-
import { BodyShort, Heading } from "../typography";
|
|
4
|
-
import { useId } from "../util/hooks";
|
|
3
|
+
import { BodyLong, BodyShort, Heading } from "../typography";
|
|
5
4
|
import { ListItem } from "./ListItem";
|
|
6
5
|
import { ListContext } from "./context";
|
|
7
|
-
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
7
|
+
import type { ListItemProps, ListProps } from "./types";
|
|
8
8
|
|
|
9
9
|
export interface ListComponent
|
|
10
10
|
extends React.ForwardRefExoticComponent<
|
|
11
11
|
ListProps & React.RefAttributes<HTMLDivElement>
|
|
12
12
|
> {
|
|
13
|
+
/**
|
|
14
|
+
* @see 🏷️ {@link ListItemProps}
|
|
15
|
+
*/
|
|
13
16
|
Item: typeof ListItem;
|
|
14
17
|
}
|
|
15
18
|
|
|
@@ -42,47 +45,34 @@ export const List = forwardRef<HTMLDivElement, ListProps>(
|
|
|
42
45
|
},
|
|
43
46
|
ref,
|
|
44
47
|
) => {
|
|
45
|
-
const
|
|
48
|
+
const { size: contextSize } = useContext(ListContext);
|
|
46
49
|
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
const listSize = size ?? _size ?? "medium";
|
|
50
|
+
const listSize = size ?? contextSize;
|
|
50
51
|
return (
|
|
51
52
|
<ListContext.Provider
|
|
52
53
|
value={{
|
|
53
54
|
listType: ListTag,
|
|
54
|
-
isNested: isNested === null ? false : true,
|
|
55
55
|
size: listSize,
|
|
56
56
|
}}
|
|
57
57
|
>
|
|
58
|
-
<
|
|
58
|
+
<BodyLong
|
|
59
|
+
as="div"
|
|
59
60
|
{...rest}
|
|
61
|
+
size={size}
|
|
60
62
|
ref={ref}
|
|
61
|
-
className={cl("navds-list", `navds-list--${listSize}`, className
|
|
62
|
-
"navds-list--nested": isNested === null ? false : true,
|
|
63
|
-
})}
|
|
63
|
+
className={cl("navds-list", `navds-list--${listSize}`, className)}
|
|
64
64
|
>
|
|
65
65
|
{title && (
|
|
66
66
|
<Heading
|
|
67
|
-
id={`tittel-${ariaId}`}
|
|
68
67
|
size={listSize === "medium" ? "small" : "xsmall"}
|
|
69
68
|
as={headingTag}
|
|
70
69
|
>
|
|
71
70
|
{title}
|
|
72
71
|
</Heading>
|
|
73
72
|
)}
|
|
74
|
-
{description &&
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
</BodyShort>
|
|
78
|
-
)}
|
|
79
|
-
<ListTag
|
|
80
|
-
aria-labelledby={title && `tittel-${ariaId}`}
|
|
81
|
-
aria-describedby={description && `description-${ariaId}`}
|
|
82
|
-
>
|
|
83
|
-
{children}
|
|
84
|
-
</ListTag>
|
|
85
|
-
</div>
|
|
73
|
+
{description && <BodyShort size={listSize}>{description}</BodyShort>}
|
|
74
|
+
<ListTag role="list">{children}</ListTag>
|
|
75
|
+
</BodyLong>
|
|
86
76
|
</ListContext.Provider>
|
|
87
77
|
);
|
|
88
78
|
},
|
package/src/list/ListItem.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import cl from "clsx";
|
|
|
2
2
|
import React, { forwardRef, useContext } from "react";
|
|
3
3
|
import { BodyLong } from "../typography";
|
|
4
4
|
import { ListContext } from "./context";
|
|
5
|
-
import { ListItemProps } from "./types";
|
|
5
|
+
import type { ListItemProps } from "./types";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @see 🏷️ {@link ListItemProps}
|
|
@@ -21,7 +21,7 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
|
|
|
21
21
|
<li {...rest} ref={ref} className={cl("navds-list__item", className)}>
|
|
22
22
|
{listType === "ul" && (
|
|
23
23
|
<div
|
|
24
|
-
className={cl({
|
|
24
|
+
className={cl("navds-list__item-marker", {
|
|
25
25
|
"navds-list__item-marker--icon": icon,
|
|
26
26
|
"navds-list__item-marker--bullet": !icon,
|
|
27
27
|
})}
|
|
@@ -30,8 +30,8 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
|
|
|
30
30
|
icon
|
|
31
31
|
) : (
|
|
32
32
|
<svg
|
|
33
|
-
width="
|
|
34
|
-
height="
|
|
33
|
+
width="0.375rem"
|
|
34
|
+
height="0.375rem"
|
|
35
35
|
viewBox="0 0 6 6"
|
|
36
36
|
fill="none"
|
|
37
37
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -45,14 +45,14 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
|
|
|
45
45
|
</div>
|
|
46
46
|
)}
|
|
47
47
|
|
|
48
|
-
<
|
|
48
|
+
<div>
|
|
49
49
|
{title && (
|
|
50
50
|
<BodyLong as="p" size={size} weight="semibold">
|
|
51
51
|
{title}
|
|
52
52
|
</BodyLong>
|
|
53
53
|
)}
|
|
54
54
|
{children}
|
|
55
|
-
</
|
|
55
|
+
</div>
|
|
56
56
|
</li>
|
|
57
57
|
);
|
|
58
58
|
},
|
package/src/list/context.ts
CHANGED
|
@@ -2,13 +2,11 @@ import { createContext } from "react";
|
|
|
2
2
|
import { ListProps } from "./types";
|
|
3
3
|
|
|
4
4
|
interface ListContextProps {
|
|
5
|
-
listType: ListProps["as"]
|
|
6
|
-
|
|
7
|
-
size: ListProps["size"];
|
|
5
|
+
listType: Exclude<ListProps["as"], undefined>;
|
|
6
|
+
size: Exclude<ListProps["size"], undefined>;
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
export const ListContext = createContext<ListContextProps>({
|
|
11
10
|
listType: "ul",
|
|
12
|
-
isNested: null,
|
|
13
11
|
size: "medium",
|
|
14
12
|
});
|
package/src/list/types.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface ListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
*/
|
|
20
20
|
headingTag?: React.ElementType<any>;
|
|
21
21
|
/**
|
|
22
|
-
* Changes
|
|
22
|
+
* Changes margin-block on list and font size on items.
|
|
23
23
|
* @default "medium"
|
|
24
24
|
*/
|
|
25
25
|
size?: "medium" | "small";
|