@navikt/ds-react 4.6.1 → 4.7.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 +1711 -169
- package/cjs/chips/Chips.js +1 -2
- package/cjs/form/combobox/ClearButton.js +27 -0
- package/cjs/form/combobox/Combobox.js +78 -0
- package/cjs/form/combobox/ComboboxProvider.js +99 -0
- package/cjs/form/combobox/ComboboxWrapper.js +51 -0
- package/cjs/form/combobox/FilteredOptions/CheckIcon.js +11 -0
- package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +46 -0
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +208 -0
- package/cjs/form/combobox/Input/Input.js +143 -0
- package/cjs/form/combobox/Input/inputContext.js +86 -0
- package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +27 -0
- package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js +107 -0
- package/cjs/form/combobox/ToggleListButton.js +36 -0
- package/cjs/form/combobox/customOptionsContext.js +56 -0
- package/cjs/form/combobox/index.js +8 -0
- package/cjs/form/combobox/package.json +6 -0
- package/cjs/form/combobox/types.js +2 -0
- package/cjs/form/index.js +3 -1
- package/cjs/timeline/AxisLabels.js +12 -12
- package/cjs/timeline/Timeline.js +2 -2
- package/cjs/util/usePrevious.js +18 -0
- package/esm/chips/Chips.js +1 -2
- package/esm/chips/Chips.js.map +1 -1
- package/esm/date/datepicker/TableHead.d.ts +1 -0
- package/esm/form/Fieldset/useFieldset.d.ts +1 -1
- package/esm/form/checkbox/useCheckbox.d.ts +4 -4
- package/esm/form/combobox/ClearButton.d.ts +7 -0
- package/esm/form/combobox/ClearButton.js +21 -0
- package/esm/form/combobox/ClearButton.js.map +1 -0
- package/esm/form/combobox/Combobox.d.ts +4 -0
- package/esm/form/combobox/Combobox.js +50 -0
- package/esm/form/combobox/Combobox.js.map +1 -0
- package/esm/form/combobox/ComboboxProvider.d.ts +26 -0
- package/esm/form/combobox/ComboboxProvider.js +72 -0
- package/esm/form/combobox/ComboboxProvider.js.map +1 -0
- package/esm/form/combobox/ComboboxWrapper.d.ts +14 -0
- package/esm/form/combobox/ComboboxWrapper.js +24 -0
- package/esm/form/combobox/ComboboxWrapper.js.map +1 -0
- package/esm/form/combobox/FilteredOptions/CheckIcon.d.ts +3 -0
- package/esm/form/combobox/FilteredOptions/CheckIcon.js +7 -0
- package/esm/form/combobox/FilteredOptions/CheckIcon.js.map +1 -0
- package/esm/form/combobox/FilteredOptions/FilteredOptions.d.ts +3 -0
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js +42 -0
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -0
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +27 -0
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +178 -0
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -0
- package/esm/form/combobox/Input/Input.d.ts +10 -0
- package/esm/form/combobox/Input/Input.js +116 -0
- package/esm/form/combobox/Input/Input.js.map +1 -0
- package/esm/form/combobox/Input/inputContext.d.ts +19 -0
- package/esm/form/combobox/Input/inputContext.js +59 -0
- package/esm/form/combobox/Input/inputContext.js.map +1 -0
- package/esm/form/combobox/SelectedOptions/SelectedOptions.d.ts +8 -0
- package/esm/form/combobox/SelectedOptions/SelectedOptions.js +23 -0
- package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -0
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +17 -0
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js +77 -0
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -0
- package/esm/form/combobox/ToggleListButton.d.ts +6 -0
- package/esm/form/combobox/ToggleListButton.js +11 -0
- package/esm/form/combobox/ToggleListButton.js.map +1 -0
- package/esm/form/combobox/customOptionsContext.d.ts +11 -0
- package/esm/form/combobox/customOptionsContext.js +29 -0
- package/esm/form/combobox/customOptionsContext.js.map +1 -0
- package/esm/form/combobox/index.d.ts +2 -0
- package/esm/form/combobox/index.js +2 -0
- package/esm/form/combobox/index.js.map +1 -0
- package/esm/form/combobox/types.d.ts +119 -0
- package/esm/form/combobox/types.js +2 -0
- package/esm/form/combobox/types.js.map +1 -0
- package/esm/form/index.d.ts +1 -0
- package/esm/form/index.js +1 -0
- package/esm/form/index.js.map +1 -1
- package/esm/form/radio/useRadio.d.ts +4 -4
- package/esm/form/useFormField.d.ts +11 -10
- package/esm/form/useFormField.js.map +1 -1
- package/esm/timeline/AxisLabels.d.ts +7 -5
- package/esm/timeline/AxisLabels.js +12 -12
- package/esm/timeline/AxisLabels.js.map +1 -1
- package/esm/timeline/Timeline.d.ts +6 -0
- package/esm/timeline/Timeline.js +2 -2
- package/esm/timeline/Timeline.js.map +1 -1
- package/esm/timeline/utils/types.external.d.ts +5 -0
- package/esm/util/usePrevious.d.ts +2 -0
- package/esm/util/usePrevious.js +17 -0
- package/esm/util/usePrevious.js.map +1 -0
- package/package.json +2 -2
- package/src/chips/Chips.tsx +1 -1
- package/src/form/combobox/ClearButton.tsx +29 -0
- package/src/form/combobox/Combobox.tsx +136 -0
- package/src/form/combobox/ComboboxProvider.tsx +99 -0
- package/src/form/combobox/ComboboxWrapper.tsx +63 -0
- package/src/form/combobox/FilteredOptions/CheckIcon.tsx +23 -0
- package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +106 -0
- package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +266 -0
- package/src/form/combobox/Input/Input.tsx +170 -0
- package/src/form/combobox/Input/inputContext.tsx +127 -0
- package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +45 -0
- package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +147 -0
- package/src/form/combobox/ToggleListButton.tsx +37 -0
- package/src/form/combobox/combobox.stories.tsx +413 -0
- package/src/form/combobox/combobox.test.tsx +123 -0
- package/src/form/combobox/customOptionsContext.tsx +57 -0
- package/src/form/combobox/index.ts +2 -0
- package/src/form/combobox/types.ts +122 -0
- package/src/form/index.ts +1 -0
- package/src/form/useFormField.ts +19 -1
- package/src/timeline/AxisLabels.tsx +23 -13
- package/src/timeline/Timeline.tsx +18 -2
- package/src/timeline/utils/types.external.ts +6 -0
- package/src/util/usePrevious.ts +19 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { omit } from "../../..";
|
|
13
|
+
import React, { useCallback, forwardRef, } from "react";
|
|
14
|
+
import cl from "clsx";
|
|
15
|
+
import { useSelectedOptionsContext } from "../SelectedOptions/selectedOptionsContext";
|
|
16
|
+
import { useFilteredOptionsContext } from "../FilteredOptions/filteredOptionsContext";
|
|
17
|
+
import { useInputContext } from "./inputContext";
|
|
18
|
+
const Input = forwardRef((_a, ref) => {
|
|
19
|
+
var { inputClassName, error, errorId } = _a, rest = __rest(_a, ["inputClassName", "error", "errorId"]);
|
|
20
|
+
const { clearInput, inputProps, onChange, size, value } = useInputContext();
|
|
21
|
+
const { selectedOptions, removeSelectedOption, toggleOption } = useSelectedOptionsContext();
|
|
22
|
+
const { activeDecendantId, allowNewValues, currentOption, filteredOptions, toggleIsListOpen, isListOpen, filteredOptionsIndex, moveFocusUp, moveFocusDown, ariaDescribedBy, moveFocusToInput, moveFocusToEnd, shouldAutocomplete, } = useFilteredOptionsContext();
|
|
23
|
+
const onEnter = useCallback((event) => {
|
|
24
|
+
if (currentOption) {
|
|
25
|
+
event.preventDefault();
|
|
26
|
+
// Selecting a value from the dropdown / FilteredOptions
|
|
27
|
+
toggleOption(currentOption, event);
|
|
28
|
+
clearInput(event);
|
|
29
|
+
}
|
|
30
|
+
else if (shouldAutocomplete && selectedOptions.includes(value)) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
// Trying to set the same value that is already set, so just clearing the input
|
|
33
|
+
clearInput(event);
|
|
34
|
+
}
|
|
35
|
+
else if ((allowNewValues || shouldAutocomplete) && value !== "") {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
// Autocompleting or adding a new value
|
|
38
|
+
toggleOption(value, event);
|
|
39
|
+
clearInput(event);
|
|
40
|
+
}
|
|
41
|
+
}, [
|
|
42
|
+
allowNewValues,
|
|
43
|
+
clearInput,
|
|
44
|
+
currentOption,
|
|
45
|
+
selectedOptions,
|
|
46
|
+
shouldAutocomplete,
|
|
47
|
+
toggleOption,
|
|
48
|
+
value,
|
|
49
|
+
]);
|
|
50
|
+
const handleKeyUp = (e) => {
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
switch (e.key) {
|
|
53
|
+
case "Escape":
|
|
54
|
+
clearInput(e);
|
|
55
|
+
toggleIsListOpen(false);
|
|
56
|
+
break;
|
|
57
|
+
case "Enter":
|
|
58
|
+
case "Accept":
|
|
59
|
+
onEnter(e);
|
|
60
|
+
break;
|
|
61
|
+
case "Home":
|
|
62
|
+
moveFocusToInput();
|
|
63
|
+
break;
|
|
64
|
+
case "End":
|
|
65
|
+
moveFocusToEnd();
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const handleKeyDown = useCallback((e) => {
|
|
72
|
+
if (e.key === "Backspace") {
|
|
73
|
+
if (value === "") {
|
|
74
|
+
const lastSelectedOption = selectedOptions[selectedOptions.length - 1];
|
|
75
|
+
removeSelectedOption(lastSelectedOption);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (e.key === "ArrowDown") {
|
|
79
|
+
// Check that cursor position is at the end of the input field,
|
|
80
|
+
// so we don't interfere with text editing
|
|
81
|
+
if (e.target.selectionStart === (value === null || value === void 0 ? void 0 : value.length)) {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
moveFocusDown();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (e.key === "ArrowUp") {
|
|
87
|
+
// Check that the FilteredOptions list is open and has virtual focus.
|
|
88
|
+
// Otherwise ignore keystrokes, so it doesn't interfere with text editing
|
|
89
|
+
if (isListOpen && filteredOptionsIndex !== null) {
|
|
90
|
+
e.preventDefault();
|
|
91
|
+
moveFocusUp();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}, [
|
|
95
|
+
value,
|
|
96
|
+
selectedOptions,
|
|
97
|
+
removeSelectedOption,
|
|
98
|
+
moveFocusDown,
|
|
99
|
+
isListOpen,
|
|
100
|
+
filteredOptionsIndex,
|
|
101
|
+
moveFocusUp,
|
|
102
|
+
]);
|
|
103
|
+
const onChangeHandler = useCallback((event) => {
|
|
104
|
+
const newValue = event.target.value;
|
|
105
|
+
if (newValue && newValue !== "") {
|
|
106
|
+
toggleIsListOpen(true);
|
|
107
|
+
}
|
|
108
|
+
else if (filteredOptions.length === 0) {
|
|
109
|
+
toggleIsListOpen(false);
|
|
110
|
+
}
|
|
111
|
+
onChange(event);
|
|
112
|
+
}, [filteredOptions.length, onChange, toggleIsListOpen]);
|
|
113
|
+
return (React.createElement("input", Object.assign({}, rest, omit(inputProps, ["aria-invalid"]), { ref: ref, value: value, onChange: onChangeHandler, type: "text", role: "combobox", onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, "aria-controls": `${inputProps.id}-filtered-options`, "aria-expanded": !!isListOpen, autoComplete: "off", "aria-autocomplete": shouldAutocomplete ? "both" : "list", "aria-activedescendant": activeDecendantId, "aria-describedby": ariaDescribedBy, className: cl(inputClassName, "navds-combobox__input", "navds-body-short", `navds-body-${size}`) })));
|
|
114
|
+
});
|
|
115
|
+
export default Input;
|
|
116
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/form/combobox/Input/Input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React, { ChangeEventHandler } from "react";
|
|
2
|
+
import { FormFieldType } from "../../useFormField";
|
|
3
|
+
interface InputContextType extends FormFieldType {
|
|
4
|
+
clearInput: (event: React.PointerEvent | React.KeyboardEvent) => void;
|
|
5
|
+
focusInput: () => void;
|
|
6
|
+
inputRef: React.RefObject<HTMLInputElement>;
|
|
7
|
+
value: string;
|
|
8
|
+
setValue: (text: string) => void;
|
|
9
|
+
onChange: ChangeEventHandler<HTMLInputElement>;
|
|
10
|
+
searchTerm: string;
|
|
11
|
+
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
|
|
12
|
+
shouldAutocomplete?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const InputContextProvider: ({ children, value: props }: {
|
|
15
|
+
children: any;
|
|
16
|
+
value: any;
|
|
17
|
+
}) => React.JSX.Element;
|
|
18
|
+
export declare const useInputContext: () => InputContextType;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { createContext, useCallback, useContext, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
2
|
+
import { useFormField } from "../../useFormField";
|
|
3
|
+
const InputContext = createContext({});
|
|
4
|
+
export const InputContextProvider = ({ children, value: props }) => {
|
|
5
|
+
const { defaultValue = "", description, disabled, error, errorId, id: externalId, value: externalValue, onChange: externalOnChange, onClear, shouldAutocomplete, size, } = props;
|
|
6
|
+
const formFieldProps = useFormField({
|
|
7
|
+
description,
|
|
8
|
+
disabled,
|
|
9
|
+
error,
|
|
10
|
+
errorId,
|
|
11
|
+
id: externalId,
|
|
12
|
+
size,
|
|
13
|
+
}, "comboboxfield");
|
|
14
|
+
const inputRef = useRef(null);
|
|
15
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
16
|
+
const value = useMemo(() => String(externalValue !== null && externalValue !== void 0 ? externalValue : internalValue), [externalValue, internalValue]);
|
|
17
|
+
const [searchTerm, setSearchTerm] = useState(value);
|
|
18
|
+
const onChange = useCallback((event) => {
|
|
19
|
+
const value = event.currentTarget.value;
|
|
20
|
+
externalValue !== null && externalValue !== void 0 ? externalValue : setInternalValue(value);
|
|
21
|
+
externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange(event);
|
|
22
|
+
setSearchTerm(value);
|
|
23
|
+
}, [externalValue, externalOnChange]);
|
|
24
|
+
const setValue = useCallback((text) => {
|
|
25
|
+
setInternalValue(text);
|
|
26
|
+
}, [setInternalValue]);
|
|
27
|
+
const clearInput = useCallback((event) => {
|
|
28
|
+
onClear === null || onClear === void 0 ? void 0 : onClear(event);
|
|
29
|
+
setValue("");
|
|
30
|
+
setSearchTerm("");
|
|
31
|
+
}, [onClear, setSearchTerm, setValue]);
|
|
32
|
+
const focusInput = useCallback(() => {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
(_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
35
|
+
}, []);
|
|
36
|
+
useLayoutEffect(() => {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
if (shouldAutocomplete && inputRef && value !== searchTerm) {
|
|
39
|
+
(_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionRange) === null || _b === void 0 ? void 0 : _b.call(_a, searchTerm.length, value.length);
|
|
40
|
+
}
|
|
41
|
+
}, [value, searchTerm, shouldAutocomplete]);
|
|
42
|
+
return (React.createElement(InputContext.Provider, { value: Object.assign(Object.assign({}, formFieldProps), { clearInput,
|
|
43
|
+
focusInput,
|
|
44
|
+
inputRef,
|
|
45
|
+
value,
|
|
46
|
+
setValue,
|
|
47
|
+
onChange,
|
|
48
|
+
searchTerm,
|
|
49
|
+
setSearchTerm,
|
|
50
|
+
shouldAutocomplete }) }, children));
|
|
51
|
+
};
|
|
52
|
+
export const useInputContext = () => {
|
|
53
|
+
const context = useContext(InputContext);
|
|
54
|
+
if (!context) {
|
|
55
|
+
throw new Error("useInputContext must be used within an InputContextProvider");
|
|
56
|
+
}
|
|
57
|
+
return context;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=inputContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputContext.js","sourceRoot":"","sources":["../../../../src/form/combobox/Input/inputContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Chips } from "../../..";
|
|
3
|
+
import { useSelectedOptionsContext } from "./selectedOptionsContext";
|
|
4
|
+
const Option = ({ option }) => {
|
|
5
|
+
const { isMultiSelect, removeSelectedOption } = useSelectedOptionsContext();
|
|
6
|
+
const onClick = (e) => {
|
|
7
|
+
e.stopPropagation();
|
|
8
|
+
removeSelectedOption(option);
|
|
9
|
+
};
|
|
10
|
+
if (!isMultiSelect) {
|
|
11
|
+
return (React.createElement("div", { className: "navds-combobox__selected-options--no-bg" }, option));
|
|
12
|
+
}
|
|
13
|
+
return React.createElement(Chips.Removable, { onClick: onClick }, option);
|
|
14
|
+
};
|
|
15
|
+
const SelectedOptions = ({ selectedOptions = [], size, children, }) => {
|
|
16
|
+
return (React.createElement(Chips, { className: "navds-combobox__selected-options", size: size },
|
|
17
|
+
selectedOptions.length
|
|
18
|
+
? selectedOptions.map((option, i) => (React.createElement(Option, { key: option + i, option: option })))
|
|
19
|
+
: [],
|
|
20
|
+
children));
|
|
21
|
+
};
|
|
22
|
+
export default SelectedOptions;
|
|
23
|
+
//# sourceMappingURL=SelectedOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectedOptions.js","sourceRoot":"","sources":["../../../../src/form/combobox/SelectedOptions/SelectedOptions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAQrE,MAAM,MAAM,GAAG,CAAC,EAAE,MAAM,EAAsB,EAAE,EAAE;IAChD,MAAM,EAAE,aAAa,EAAE,oBAAoB,EAAE,GAAG,yBAAyB,EAAE,CAAC;IAE5E,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;QACpB,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,IAAI,CAAC,aAAa,EAAE;QAClB,OAAO,CACL,6BAAK,SAAS,EAAC,yCAAyC,IAAE,MAAM,CAAO,CACxE,CAAC;KACH;IAED,OAAO,oBAAC,KAAK,CAAC,SAAS,IAAC,OAAO,EAAE,OAAO,IAAG,MAAM,CAAmB,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,eAAe,GAAmC,CAAC,EACvD,eAAe,GAAG,EAAE,EACpB,IAAI,EACJ,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,oBAAC,KAAK,IAAC,SAAS,EAAC,kCAAkC,EAAC,IAAI,EAAE,IAAI;QAC3D,eAAe,CAAC,MAAM;YACrB,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CACjC,oBAAC,MAAM,IAAC,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAI,CAC5C,CAAC;YACJ,CAAC,CAAC,EAAE;QACL,QAAQ,CACH,CACT,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ComboboxProps } from "../types";
|
|
3
|
+
type SelectedOptionsContextType = {
|
|
4
|
+
addSelectedOption: (option: string) => void;
|
|
5
|
+
isMultiSelect?: boolean;
|
|
6
|
+
removeSelectedOption: (option: string) => void;
|
|
7
|
+
prevSelectedOptions?: string[];
|
|
8
|
+
selectedOptions: string[];
|
|
9
|
+
setSelectedOptions: (any: any) => void;
|
|
10
|
+
toggleOption: (option: string, event: React.KeyboardEvent | React.PointerEvent) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const SelectedOptionsProvider: ({ children, value, }: {
|
|
13
|
+
children: any;
|
|
14
|
+
value: Pick<ComboboxProps, "allowNewValues" | "isMultiSelect" | "options" | "selectedOptions" | "onToggleSelected">;
|
|
15
|
+
}) => React.JSX.Element;
|
|
16
|
+
export declare const useSelectedOptionsContext: () => SelectedOptionsContextType;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { createContext, useCallback, useContext, useMemo, useState, } from "react";
|
|
2
|
+
import usePrevious from "../../../util/usePrevious";
|
|
3
|
+
import { useInputContext } from "../Input/inputContext";
|
|
4
|
+
import { useCustomOptionsContext } from "../customOptionsContext";
|
|
5
|
+
const SelectedOptionsContext = createContext({});
|
|
6
|
+
export const SelectedOptionsProvider = ({ children, value, }) => {
|
|
7
|
+
const { clearInput, focusInput } = useInputContext();
|
|
8
|
+
const { customOptions, removeCustomOption, addCustomOption } = useCustomOptionsContext();
|
|
9
|
+
const { allowNewValues, isMultiSelect, selectedOptions: externalSelectedOptions, onToggleSelected, options, } = value;
|
|
10
|
+
const [internalSelectedOptions, setSelectedOptions] = useState([]);
|
|
11
|
+
const selectedOptions = useMemo(() => externalSelectedOptions !== null && externalSelectedOptions !== void 0 ? externalSelectedOptions : [...customOptions, ...internalSelectedOptions], [customOptions, externalSelectedOptions, internalSelectedOptions]);
|
|
12
|
+
const addSelectedOption = useCallback((option) => {
|
|
13
|
+
var _a;
|
|
14
|
+
if (!options
|
|
15
|
+
.map((opt) => opt.toLowerCase())
|
|
16
|
+
.includes((_a = option === null || option === void 0 ? void 0 : option.toLowerCase) === null || _a === void 0 ? void 0 : _a.call(option))) {
|
|
17
|
+
allowNewValues && addCustomOption(option);
|
|
18
|
+
}
|
|
19
|
+
else if (isMultiSelect) {
|
|
20
|
+
setSelectedOptions((prevSelectedOptions) => [
|
|
21
|
+
...prevSelectedOptions,
|
|
22
|
+
option,
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
setSelectedOptions([option]);
|
|
27
|
+
}
|
|
28
|
+
onToggleSelected === null || onToggleSelected === void 0 ? void 0 : onToggleSelected(option, true);
|
|
29
|
+
}, [addCustomOption, allowNewValues, isMultiSelect, onToggleSelected, options]);
|
|
30
|
+
const removeSelectedOption = useCallback((option) => {
|
|
31
|
+
if (customOptions.includes(option)) {
|
|
32
|
+
removeCustomOption(option);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
setSelectedOptions((prevSelectedOptions) => prevSelectedOptions.filter((selectedOption) => selectedOption !== option));
|
|
36
|
+
}
|
|
37
|
+
onToggleSelected === null || onToggleSelected === void 0 ? void 0 : onToggleSelected(option, false);
|
|
38
|
+
}, [customOptions, onToggleSelected, removeCustomOption]);
|
|
39
|
+
const toggleOption = useCallback((option, event) => {
|
|
40
|
+
if (selectedOptions.includes(option)) {
|
|
41
|
+
removeSelectedOption(option);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
addSelectedOption(option);
|
|
45
|
+
}
|
|
46
|
+
if (!isMultiSelect) {
|
|
47
|
+
clearInput(event);
|
|
48
|
+
}
|
|
49
|
+
focusInput();
|
|
50
|
+
}, [
|
|
51
|
+
addSelectedOption,
|
|
52
|
+
clearInput,
|
|
53
|
+
focusInput,
|
|
54
|
+
isMultiSelect,
|
|
55
|
+
removeSelectedOption,
|
|
56
|
+
selectedOptions,
|
|
57
|
+
]);
|
|
58
|
+
const prevSelectedOptions = usePrevious(selectedOptions);
|
|
59
|
+
const selectedOptionsState = {
|
|
60
|
+
addSelectedOption,
|
|
61
|
+
isMultiSelect,
|
|
62
|
+
removeSelectedOption,
|
|
63
|
+
prevSelectedOptions,
|
|
64
|
+
selectedOptions,
|
|
65
|
+
setSelectedOptions,
|
|
66
|
+
toggleOption,
|
|
67
|
+
};
|
|
68
|
+
return (React.createElement(SelectedOptionsContext.Provider, { value: selectedOptionsState }, children));
|
|
69
|
+
};
|
|
70
|
+
export const useSelectedOptionsContext = () => {
|
|
71
|
+
const context = useContext(SelectedOptionsContext);
|
|
72
|
+
if (!context) {
|
|
73
|
+
throw new Error("useSelectedOptionsContext must be used within a SelectedOptionsProvider");
|
|
74
|
+
}
|
|
75
|
+
return context;
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=selectedOptionsContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectedOptionsContext.js","sourceRoot":"","sources":["../../../../src/form/combobox/SelectedOptions/selectedOptionsContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface ToggleListButtonProps {
|
|
3
|
+
toggleListButtonLabel?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const ToggleListButton: React.ForwardRefExoticComponent<ToggleListButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
6
|
+
export default ToggleListButton;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { ChevronUpIcon, ChevronDownIcon } from "@navikt/aksel-icons";
|
|
3
|
+
import { useFilteredOptionsContext } from "./FilteredOptions/filteredOptionsContext";
|
|
4
|
+
export const ToggleListButton = forwardRef(({ toggleListButtonLabel }, ref) => {
|
|
5
|
+
const { isListOpen, toggleIsListOpen } = useFilteredOptionsContext();
|
|
6
|
+
return (React.createElement("button", { type: "button", onPointerUp: () => toggleIsListOpen(), onKeyDown: ({ key }) => key === "Enter" && toggleIsListOpen(), className: "navds-combobox__button-toggle-list", "aria-expanded": isListOpen, tabIndex: -1, ref: ref },
|
|
7
|
+
React.createElement("span", { className: "navds-sr-only" }, toggleListButtonLabel !== null && toggleListButtonLabel !== void 0 ? toggleListButtonLabel : "Alternativer"),
|
|
8
|
+
isListOpen ? (React.createElement(ChevronUpIcon, { "aria-hidden": true })) : (React.createElement(ChevronDownIcon, { "aria-hidden": true }))));
|
|
9
|
+
});
|
|
10
|
+
export default ToggleListButton;
|
|
11
|
+
//# sourceMappingURL=ToggleListButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToggleListButton.js","sourceRoot":"","sources":["../../../src/form/combobox/ToggleListButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AAMrF,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAGxC,CAAC,EAAE,qBAAqB,EAAE,EAAE,GAAG,EAAE,EAAE;IACnC,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,yBAAyB,EAAE,CAAC;IACrE,OAAO,CACL,gCACE,IAAI,EAAC,QAAQ,EACb,WAAW,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE,EACrC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO,IAAI,gBAAgB,EAAE,EAC7D,SAAS,EAAC,oCAAoC,mBAC/B,UAAU,EACzB,QAAQ,EAAE,CAAC,CAAC,EACZ,GAAG,EAAE,GAAG;QAER,8BAAM,SAAS,EAAC,eAAe,IAC5B,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,cAAc,CACnC;QACN,UAAU,CAAC,CAAC,CAAC,CACZ,oBAAC,aAAa,0BAAe,CAC9B,CAAC,CAAC,CAAC,CACF,oBAAC,eAAe,0BAAe,CAChC,CACM,CACV,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
type CustomOptionsContextType = {
|
|
3
|
+
customOptions: string[];
|
|
4
|
+
removeCustomOption: (option: string) => void;
|
|
5
|
+
addCustomOption: (option: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const CustomOptionsProvider: ({ children }: {
|
|
8
|
+
children: any;
|
|
9
|
+
}) => React.JSX.Element;
|
|
10
|
+
export declare const useCustomOptionsContext: () => CustomOptionsContextType;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useState, useCallback, createContext, useContext } from "react";
|
|
2
|
+
import { useInputContext } from "./Input/inputContext";
|
|
3
|
+
const CustomOptionsContext = createContext({});
|
|
4
|
+
export const CustomOptionsProvider = ({ children }) => {
|
|
5
|
+
const [customOptions, setCustomOptions] = useState([]);
|
|
6
|
+
const { focusInput } = useInputContext();
|
|
7
|
+
const removeCustomOption = useCallback((option) => {
|
|
8
|
+
setCustomOptions((prevCustomOptions) => prevCustomOptions.filter((o) => o !== option));
|
|
9
|
+
focusInput();
|
|
10
|
+
}, [focusInput, setCustomOptions]);
|
|
11
|
+
const addCustomOption = useCallback((option) => {
|
|
12
|
+
setCustomOptions((prevOptions) => [...prevOptions, option]);
|
|
13
|
+
focusInput();
|
|
14
|
+
}, [focusInput, setCustomOptions]);
|
|
15
|
+
const customOptionsState = {
|
|
16
|
+
customOptions,
|
|
17
|
+
removeCustomOption,
|
|
18
|
+
addCustomOption,
|
|
19
|
+
};
|
|
20
|
+
return (React.createElement(CustomOptionsContext.Provider, { value: customOptionsState }, children));
|
|
21
|
+
};
|
|
22
|
+
export const useCustomOptionsContext = () => {
|
|
23
|
+
const context = useContext(CustomOptionsContext);
|
|
24
|
+
if (!context) {
|
|
25
|
+
throw new Error("useCustomOptionsContext must be used within a CustomOptionsProvider");
|
|
26
|
+
}
|
|
27
|
+
return context;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=customOptionsContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customOptionsContext.js","sourceRoot":"","sources":["../../../src/form/combobox/customOptionsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQvD,MAAM,oBAAoB,GAAG,aAAa,CACxC,EAA8B,CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACpD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACjE,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,EAAE,CAAC;IAEzC,MAAM,kBAAkB,GAAG,WAAW,CACpC,CAAC,MAAM,EAAE,EAAE;QACT,gBAAgB,CAAC,CAAC,iBAAiB,EAAE,EAAE,CACrC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAC9C,CAAC;QACF,UAAU,EAAE,CAAC;IACf,CAAC,EACD,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAC/B,CAAC;IAEF,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,MAAM,EAAE,EAAE;QACT,gBAAgB,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAG,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,UAAU,EAAE,CAAC;IACf,CAAC,EACD,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAC/B,CAAC;IAEF,MAAM,kBAAkB,GAAG;QACzB,aAAa;QACb,kBAAkB;QAClB,eAAe;KAChB,CAAC;IAEF,OAAO,CACL,oBAAC,oBAAoB,CAAC,QAAQ,IAAC,KAAK,EAAE,kBAAkB,IACrD,QAAQ,CACqB,CACjC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,EAAE;IAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;KACH;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/form/combobox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React, { ChangeEvent, InputHTMLAttributes } from "react";
|
|
2
|
+
import { FormFieldProps } from "../useFormField";
|
|
3
|
+
export interface ComboboxProps extends FormFieldProps, Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange" | "value"> {
|
|
4
|
+
/**
|
|
5
|
+
* Combobox label
|
|
6
|
+
*/
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* List of options to use for autocompletion
|
|
10
|
+
*/
|
|
11
|
+
options: string[];
|
|
12
|
+
/**
|
|
13
|
+
* If enabled, adds an option to add the value of the input as an option whenever there are no options matching the value.
|
|
14
|
+
*/
|
|
15
|
+
allowNewValues?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* If "true" adds a button to clear the value in the input field
|
|
18
|
+
*/
|
|
19
|
+
clearButton?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Custom name for the clear button. Requires "clearButton" to be "true".
|
|
22
|
+
*
|
|
23
|
+
* @default "Tøm"
|
|
24
|
+
*/
|
|
25
|
+
clearButtonLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* A list of options to display in the dropdown list.
|
|
28
|
+
* If provided, this overrides the internal search logic in the component.
|
|
29
|
+
* Useful for e.g. searching on a server or when overriding the search algorithm to search for synonyms or similar.
|
|
30
|
+
*/
|
|
31
|
+
filteredOptions?: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Optionally hide the label visually.
|
|
34
|
+
* Not recommended, but can be considered for e.g. search fields in the top menu.
|
|
35
|
+
*/
|
|
36
|
+
hideLabel?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Custom class name for the input field.
|
|
39
|
+
*
|
|
40
|
+
* If used for styling, please consider using tokens instead.
|
|
41
|
+
*/
|
|
42
|
+
inputClassName?: string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Controlled open/closed state for the dropdown list
|
|
45
|
+
*/
|
|
46
|
+
isListOpen?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Set to "true" when doing an async search and waiting for new filteredOptions.
|
|
49
|
+
*
|
|
50
|
+
* Will show a spinner in the dropdown and announce to screen readers that it is loading.
|
|
51
|
+
*/
|
|
52
|
+
isLoading?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Set to "true" to allow multiple selections
|
|
55
|
+
*
|
|
56
|
+
* This will display selected values as a list of Chips in front of the input field, instead of a selection replacing the value of the input.
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
isMultiSelect?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Callback function triggered whenever the value of the input field is triggered.
|
|
62
|
+
*
|
|
63
|
+
* @param event
|
|
64
|
+
* @returns
|
|
65
|
+
*/
|
|
66
|
+
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Callback function triggered whenever the input field is cleared
|
|
69
|
+
*
|
|
70
|
+
* @param event
|
|
71
|
+
* @returns
|
|
72
|
+
*/
|
|
73
|
+
onClear?: (event: React.PointerEvent | React.KeyboardEvent) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Callback function triggered whenever an option is selected or de-selected
|
|
76
|
+
*
|
|
77
|
+
* @param option
|
|
78
|
+
* @param isSelected
|
|
79
|
+
* @returns
|
|
80
|
+
*/
|
|
81
|
+
onToggleSelected?: (option: string, isSelected: boolean) => void;
|
|
82
|
+
/**
|
|
83
|
+
* List of selected options.
|
|
84
|
+
*
|
|
85
|
+
* Use this prop when controlling the selected state outside for the component,
|
|
86
|
+
* e.g. for a filter, where options can be toggled elsewhere/programmatically.
|
|
87
|
+
*/
|
|
88
|
+
selectedOptions?: string[];
|
|
89
|
+
/**
|
|
90
|
+
* Set to "true" to enable inline autocomplete.
|
|
91
|
+
*
|
|
92
|
+
* @default false
|
|
93
|
+
*/
|
|
94
|
+
shouldAutocomplete?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* When set to "true" displays selected options as Chips before the input field
|
|
97
|
+
*
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
shouldShowSelectedOptions?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* When set to "true" displays the toggle button for opening/closing the dropdown list
|
|
103
|
+
*
|
|
104
|
+
* @default true
|
|
105
|
+
*/
|
|
106
|
+
toggleListButton?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Custom name for the toggle list-button. Requires "toggleListButton" to be "true".
|
|
109
|
+
*
|
|
110
|
+
* @default "Alternativer"
|
|
111
|
+
*/
|
|
112
|
+
toggleListButtonLabel?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Set this to override the value of the input field.
|
|
115
|
+
*
|
|
116
|
+
* This converts the input to a controlled input, so you have to use onChange to update the value.
|
|
117
|
+
*/
|
|
118
|
+
value?: string;
|
|
119
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/form/combobox/types.ts"],"names":[],"mappings":""}
|
package/esm/form/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { ErrorSummary, type ErrorSummaryProps } from "./error-summary";
|
|
|
4
4
|
export { Fieldset, FieldsetContext, type FieldsetProps } from "./Fieldset";
|
|
5
5
|
export { Radio, RadioGroup, type RadioGroupProps, type RadioProps, } from "./radio";
|
|
6
6
|
export { Search, type SearchClearEvent, type SearchProps } from "./search";
|
|
7
|
+
export { Combobox as UNSAFE_Combobox, type ComboboxProps } from "./combobox";
|
|
7
8
|
export { default as Select, type SelectProps } from "./Select";
|
|
8
9
|
export { default as Switch, type SwitchProps } from "./Switch";
|
|
9
10
|
export { Counter, default as Textarea, type TextareaProps } from "./Textarea";
|
package/esm/form/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { ErrorSummary } from "./error-summary";
|
|
|
4
4
|
export { Fieldset, FieldsetContext } from "./Fieldset";
|
|
5
5
|
export { Radio, RadioGroup, } from "./radio";
|
|
6
6
|
export { Search } from "./search";
|
|
7
|
+
export { Combobox as UNSAFE_Combobox } from "./combobox";
|
|
7
8
|
export { default as Select } from "./Select";
|
|
8
9
|
export { default as Switch } from "./Switch";
|
|
9
10
|
export { Counter, default as Textarea } from "./Textarea";
|
package/esm/form/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,aAAa,GAGd,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,OAAO,IAAI,iBAAiB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA0B,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AAC3E,OAAO,EACL,KAAK,EACL,UAAU,GAGX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAA2C,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,MAAM,EAAoB,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAoB,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAsB,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAuB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,aAAa,GAGd,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,OAAO,IAAI,iBAAiB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA0B,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAsB,MAAM,YAAY,CAAC;AAC3E,OAAO,EACL,KAAK,EACL,UAAU,GAGX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAA2C,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,QAAQ,IAAI,eAAe,EAAsB,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,MAAM,EAAoB,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAoB,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAsB,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAuB,MAAM,aAAa,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { RadioProps } from "./Radio";
|
|
|
3
3
|
* Handles props for Radios in context with Fieldset and RadioGroup
|
|
4
4
|
*/
|
|
5
5
|
export declare const useRadio: (props: RadioProps) => {
|
|
6
|
-
readOnly:
|
|
6
|
+
readOnly: boolean | undefined;
|
|
7
7
|
inputProps: {
|
|
8
8
|
name: string | undefined;
|
|
9
9
|
defaultChecked: boolean | undefined;
|
|
@@ -12,10 +12,10 @@ export declare const useRadio: (props: RadioProps) => {
|
|
|
12
12
|
onClick: (e: any) => void;
|
|
13
13
|
required: boolean | undefined;
|
|
14
14
|
type: string;
|
|
15
|
-
"aria-describedby": string | undefined;
|
|
16
|
-
disabled: boolean | undefined;
|
|
17
|
-
"aria-invalid"?: boolean | undefined;
|
|
18
15
|
id: string;
|
|
16
|
+
"aria-invalid"?: boolean | undefined;
|
|
17
|
+
"aria-describedby"?: string | undefined;
|
|
18
|
+
disabled?: boolean | undefined;
|
|
19
19
|
};
|
|
20
20
|
showErrorMsg: boolean;
|
|
21
21
|
hasError: boolean;
|