@reykjavik/hanna-react 0.10.171 → 0.10.173
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/AutosuggestSearch.js +1 -1
- package/CHANGELOG.md +15 -0
- package/Datepicker.js +18 -5
- package/Multiselect.js +1 -1
- package/_abstract/_TogglerGroup.js +2 -2
- package/_abstract/_TogglerInput.js +2 -2
- package/esm/AutosuggestSearch.js +1 -1
- package/esm/Datepicker.js +19 -6
- package/esm/Multiselect.js +1 -1
- package/esm/_abstract/_TogglerGroup.js +2 -2
- package/esm/_abstract/_TogglerInput.js +2 -2
- package/package.json +1 -1
package/AutosuggestSearch.js
CHANGED
|
@@ -94,7 +94,7 @@ const AutosuggestSearch = (props) => {
|
|
|
94
94
|
: emptyMessage;
|
|
95
95
|
contents = (react_1.default.createElement("div", { className: (0, hanna_utils_1.modifiedClass)('AutosuggestSearch__emptyMessage', type !== 'empty' && type) }, message));
|
|
96
96
|
}
|
|
97
|
-
return (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
|
|
97
|
+
return (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }, (!options.length && { role: undefined })), contents));
|
|
98
98
|
}, inputProps: Object.assign({ ref: inputRef, value: inputValue, onChange: (_, { newValue, method }) => {
|
|
99
99
|
if (!inputChangeMethods.has(method)) {
|
|
100
100
|
return;
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
- ... <!-- Add new lines here. -->
|
|
6
6
|
|
|
7
|
+
## 0.10.173
|
|
8
|
+
|
|
9
|
+
_2026-05-19_
|
|
10
|
+
|
|
11
|
+
- fix: Add `role="generic"` to checkbox- and radio-group `<li/>` elments
|
|
12
|
+
- `AutosuggestSearch`:
|
|
13
|
+
- fix: Suppress `role="listbox"` when there are no suggestions
|
|
14
|
+
|
|
15
|
+
## 0.10.172
|
|
16
|
+
|
|
17
|
+
_2026-04-30_
|
|
18
|
+
|
|
19
|
+
- `Datepicker`:
|
|
20
|
+
- feat: Scroll calendar into view when opened, and back to input when closed
|
|
21
|
+
|
|
7
22
|
## 0.10.171
|
|
8
23
|
|
|
9
24
|
_2026-04-02_
|
package/Datepicker.js
CHANGED
|
@@ -154,13 +154,16 @@ const Datepicker = (props) => {
|
|
|
154
154
|
.concat(txts.dateFormats)
|
|
155
155
|
.concat(['P', 'PP', 'PPP']);
|
|
156
156
|
}, [dateFormat, txts]);
|
|
157
|
+
const wrapperRef = (0, react_1.useRef)();
|
|
157
158
|
return (react_1.default.createElement(FormField_js_1.FormField, Object.assign({ extraClassName: "Datepicker", filled: filled, empty: empty }, fieldWrapperProps, { renderInput: (className, inputProps, addFocusProps) => {
|
|
158
|
-
return (react_1.default.createElement("div", Object.assign({ className: className.input, onClick: ({ target, currentTarget }) => { var _a; return target === currentTarget && ((_a = currentTarget.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus()); }, ref:
|
|
159
|
-
|
|
159
|
+
return (react_1.default.createElement("div", Object.assign({ className: className.input, onClick: ({ target, currentTarget }) => { var _a; return target === currentTarget && ((_a = currentTarget.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus()); }, ref: (elm) => {
|
|
160
|
+
wrapperRef.current = elm;
|
|
161
|
+
if (inputRef) {
|
|
160
162
|
inputRef.current =
|
|
161
163
|
(elm === null || elm === void 0 ? void 0 : elm.querySelector('input')) || undefined;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
}
|
|
165
|
+
return elm;
|
|
166
|
+
} }, addFocusProps()),
|
|
164
167
|
isoMode && react_1.default.createElement("input", { type: "hidden", name: name, value: toLocalIsoDate(value) }),
|
|
165
168
|
react_1.default.createElement(ReactDatepicker_js_1.ReactDatePicker, Object.assign({ required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang || i18n_1.DEFAULT_LANG, dateFormat: normalizedDateFormats, onChange: (date) => {
|
|
166
169
|
date = date || undefined;
|
|
@@ -173,7 +176,17 @@ const Datepicker = (props) => {
|
|
|
173
176
|
}, placeholderText: placeholder,
|
|
174
177
|
// TODO: Implement this
|
|
175
178
|
// selectsRange
|
|
176
|
-
minDate: minDateNormalized, maxDate: maxDate, startDate: startDate, endDate: endDate, selectsStart: isStartDate, selectsEnd: isEndDate, formatWeekDay: (weekday) => weekday.charAt(0).toUpperCase(), showYearDropdown: true, scrollableYearDropdown: true, yearDropdownItemNumber: 15,
|
|
179
|
+
minDate: minDateNormalized, maxDate: maxDate, startDate: startDate, endDate: endDate, selectsStart: isStartDate, selectsEnd: isEndDate, formatWeekDay: (weekday) => weekday.charAt(0).toUpperCase(), showYearDropdown: true, scrollableYearDropdown: true, yearDropdownItemNumber: 15, onCalendarOpen: () => {
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
var _a;
|
|
182
|
+
const calElm = (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.react-datepicker');
|
|
183
|
+
calElm === null || calElm === void 0 ? void 0 : calElm.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
184
|
+
}, 100);
|
|
185
|
+
}, onCalendarClose: () => {
|
|
186
|
+
var _a;
|
|
187
|
+
const inputElm = (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) || ((_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('input'));
|
|
188
|
+
inputElm === null || inputElm === void 0 ? void 0 : inputElm.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
189
|
+
}, showMonthDropdown: true }, inputProps, txts, datepickerExtraProps, { autoComplete: "off" }))));
|
|
177
190
|
} })));
|
|
178
191
|
};
|
|
179
192
|
exports.Datepicker = Datepicker;
|
package/Multiselect.js
CHANGED
|
@@ -246,7 +246,7 @@ const Multiselect = (props) => {
|
|
|
246
246
|
const insertGroupSeparator = !isFiltered &&
|
|
247
247
|
item.group !== (filteredOptions[idx - 1] || {}).group &&
|
|
248
248
|
(idx > 0 || !!item.group);
|
|
249
|
-
const checkbox = (react_1.default.createElement(Checkbox_js_1.default, Object.assign({ key: idx, className: (0, hanna_utils_1.modifiedClass)('Multiselect__option', activeItemIndex === idx && 'focused'), reqText: false, disabled: isDisabled, readOnly: readOnly, required: props.required, Wrapper: "li", name: name }, item, { checked: isChecked, "aria-invalid": props.invalid, label: item.label || item.value, onChange: () => handleCheckboxSelection(item), onFocus: () => setActiveItemIndex(idx), wrapperProps: {
|
|
249
|
+
const checkbox = (react_1.default.createElement(Checkbox_js_1.default, Object.assign({ key: idx, className: (0, hanna_utils_1.modifiedClass)('Multiselect__option', activeItemIndex === idx && 'focused'), reqText: false, disabled: isDisabled, readOnly: readOnly, required: props.required, Wrapper: "li", role: "generic", name: name }, item, { checked: isChecked, "aria-invalid": props.invalid, label: item.label || item.value, onChange: () => handleCheckboxSelection(item), onFocus: () => setActiveItemIndex(idx), wrapperProps: {
|
|
250
250
|
onMouseEnter: () => setActiveItemIndex(idx),
|
|
251
251
|
} })));
|
|
252
252
|
return insertGroupSeparator ? (react_1.default.createElement(react_1.Fragment, { key: idx },
|
|
@@ -37,11 +37,11 @@ const TogglerGroup = (props) => {
|
|
|
37
37
|
onSelected && onSelected({ value, checked, option, selectedValues });
|
|
38
38
|
}, disabled: isDisabled, readOnly: readOnly, 'aria-invalid': props['aria-invalid'], checked: isChecked });
|
|
39
39
|
if (renderItemSubContent) {
|
|
40
|
-
return (react_1.default.createElement("li", { key: i, className: `${bem}__item
|
|
40
|
+
return (react_1.default.createElement("li", { key: i, className: `${bem}__item`, role: "generic" },
|
|
41
41
|
react_1.default.createElement(Toggler, Object.assign({}, togglerProps)),
|
|
42
42
|
renderItemSubContent(option, isChecked)));
|
|
43
43
|
}
|
|
44
|
-
return (react_1.default.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li" }, togglerProps)));
|
|
44
|
+
return (react_1.default.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li", role: "generic" }, togglerProps)));
|
|
45
45
|
})));
|
|
46
46
|
};
|
|
47
47
|
exports.TogglerGroup = TogglerGroup;
|
|
@@ -13,7 +13,7 @@ const defaultReqText = {
|
|
|
13
13
|
};
|
|
14
14
|
// eslint-disable-next-line complexity
|
|
15
15
|
const TogglerInput = (props) => {
|
|
16
|
-
const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps } = props, restInputProps = tslib_1.__rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps"]);
|
|
16
|
+
const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps, role } = props, restInputProps = tslib_1.__rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps", "role"]);
|
|
17
17
|
const domid = (0, useDomid_js_1.useDomid)(id);
|
|
18
18
|
const errorId = errorMessage && `error${domid}`;
|
|
19
19
|
const reqStar = required && reqText !== false && (react_1.default.createElement("abbr", { className: `${bem}__label__reqstar`,
|
|
@@ -28,7 +28,7 @@ const TogglerInput = (props) => {
|
|
|
28
28
|
' '));
|
|
29
29
|
return (react_1.default.createElement(Wrapper, Object.assign({}, wrapperProps, { className: (0, hanna_utils_1.modifiedClass)(bem, [modifier, hideLabel && 'nolabel'],
|
|
30
30
|
// Prefer `className` over `wrapperProps.className`
|
|
31
|
-
className || (wrapperProps || {}).className) }),
|
|
31
|
+
className || (wrapperProps || {}).className), role: role }),
|
|
32
32
|
react_1.default.createElement("input", Object.assign({ className: `${bem}__input`, type: type, id: domid, "aria-invalid": invalid || !!errorMessage || undefined, "aria-describedby": errorId }, restInputProps, inputProps, (readOnly && { disabled: true }))),
|
|
33
33
|
' ',
|
|
34
34
|
react_1.default.createElement("label", { className: `${bem}__label`, htmlFor: domid },
|
package/esm/AutosuggestSearch.js
CHANGED
|
@@ -91,7 +91,7 @@ export const AutosuggestSearch = (props) => {
|
|
|
91
91
|
: emptyMessage;
|
|
92
92
|
contents = (React.createElement("div", { className: modifiedClass('AutosuggestSearch__emptyMessage', type !== 'empty' && type) }, message));
|
|
93
93
|
}
|
|
94
|
-
return (React.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
|
|
94
|
+
return (React.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }, (!options.length && { role: undefined })), contents));
|
|
95
95
|
}, inputProps: Object.assign({ ref: inputRef, value: inputValue, onChange: (_, { newValue, method }) => {
|
|
96
96
|
if (!inputChangeMethods.has(method)) {
|
|
97
97
|
return;
|
package/esm/Datepicker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo, useRef } from 'react';
|
|
2
2
|
import { DEFAULT_LANG, getTexts, } from '@reykjavik/hanna-utils/i18n';
|
|
3
3
|
// For more info on localization see: https://stackoverflow.com/questions/54399084/change-locale-in-react-datepicker/58306958#58306958
|
|
4
4
|
import is from 'date-fns/locale/is/index.js';
|
|
@@ -149,13 +149,16 @@ export const Datepicker = (props) => {
|
|
|
149
149
|
.concat(txts.dateFormats)
|
|
150
150
|
.concat(['P', 'PP', 'PPP']);
|
|
151
151
|
}, [dateFormat, txts]);
|
|
152
|
+
const wrapperRef = useRef();
|
|
152
153
|
return (React.createElement(FormField, Object.assign({ extraClassName: "Datepicker", filled: filled, empty: empty }, fieldWrapperProps, { renderInput: (className, inputProps, addFocusProps) => {
|
|
153
|
-
return (React.createElement("div", Object.assign({ className: className.input, onClick: ({ target, currentTarget }) => { var _a; return target === currentTarget && ((_a = currentTarget.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus()); }, ref:
|
|
154
|
-
|
|
154
|
+
return (React.createElement("div", Object.assign({ className: className.input, onClick: ({ target, currentTarget }) => { var _a; return target === currentTarget && ((_a = currentTarget.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus()); }, ref: (elm) => {
|
|
155
|
+
wrapperRef.current = elm;
|
|
156
|
+
if (inputRef) {
|
|
155
157
|
inputRef.current =
|
|
156
158
|
(elm === null || elm === void 0 ? void 0 : elm.querySelector('input')) || undefined;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
}
|
|
160
|
+
return elm;
|
|
161
|
+
} }, addFocusProps()),
|
|
159
162
|
isoMode && React.createElement("input", { type: "hidden", name: name, value: toLocalIsoDate(value) }),
|
|
160
163
|
React.createElement(ReactDatePicker, Object.assign({ required: inputProps.required, disabled: inputProps.disabled, readOnly: inputProps.readOnly, selected: value, name: isoMode ? undefined : name, locale: lang || DEFAULT_LANG, dateFormat: normalizedDateFormats, onChange: (date) => {
|
|
161
164
|
date = date || undefined;
|
|
@@ -168,7 +171,17 @@ export const Datepicker = (props) => {
|
|
|
168
171
|
}, placeholderText: placeholder,
|
|
169
172
|
// TODO: Implement this
|
|
170
173
|
// selectsRange
|
|
171
|
-
minDate: minDateNormalized, maxDate: maxDate, startDate: startDate, endDate: endDate, selectsStart: isStartDate, selectsEnd: isEndDate, formatWeekDay: (weekday) => weekday.charAt(0).toUpperCase(), showYearDropdown: true, scrollableYearDropdown: true, yearDropdownItemNumber: 15,
|
|
174
|
+
minDate: minDateNormalized, maxDate: maxDate, startDate: startDate, endDate: endDate, selectsStart: isStartDate, selectsEnd: isEndDate, formatWeekDay: (weekday) => weekday.charAt(0).toUpperCase(), showYearDropdown: true, scrollableYearDropdown: true, yearDropdownItemNumber: 15, onCalendarOpen: () => {
|
|
175
|
+
setTimeout(() => {
|
|
176
|
+
var _a;
|
|
177
|
+
const calElm = (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.react-datepicker');
|
|
178
|
+
calElm === null || calElm === void 0 ? void 0 : calElm.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
179
|
+
}, 100);
|
|
180
|
+
}, onCalendarClose: () => {
|
|
181
|
+
var _a;
|
|
182
|
+
const inputElm = (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) || ((_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('input'));
|
|
183
|
+
inputElm === null || inputElm === void 0 ? void 0 : inputElm.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
184
|
+
}, showMonthDropdown: true }, inputProps, txts, datepickerExtraProps, { autoComplete: "off" }))));
|
|
172
185
|
} })));
|
|
173
186
|
};
|
|
174
187
|
export default Datepicker;
|
package/esm/Multiselect.js
CHANGED
|
@@ -242,7 +242,7 @@ export const Multiselect = (props) => {
|
|
|
242
242
|
const insertGroupSeparator = !isFiltered &&
|
|
243
243
|
item.group !== (filteredOptions[idx - 1] || {}).group &&
|
|
244
244
|
(idx > 0 || !!item.group);
|
|
245
|
-
const checkbox = (React.createElement(Checkbox, Object.assign({ key: idx, className: modifiedClass('Multiselect__option', activeItemIndex === idx && 'focused'), reqText: false, disabled: isDisabled, readOnly: readOnly, required: props.required, Wrapper: "li", name: name }, item, { checked: isChecked, "aria-invalid": props.invalid, label: item.label || item.value, onChange: () => handleCheckboxSelection(item), onFocus: () => setActiveItemIndex(idx), wrapperProps: {
|
|
245
|
+
const checkbox = (React.createElement(Checkbox, Object.assign({ key: idx, className: modifiedClass('Multiselect__option', activeItemIndex === idx && 'focused'), reqText: false, disabled: isDisabled, readOnly: readOnly, required: props.required, Wrapper: "li", role: "generic", name: name }, item, { checked: isChecked, "aria-invalid": props.invalid, label: item.label || item.value, onChange: () => handleCheckboxSelection(item), onFocus: () => setActiveItemIndex(idx), wrapperProps: {
|
|
246
246
|
onMouseEnter: () => setActiveItemIndex(idx),
|
|
247
247
|
} })));
|
|
248
248
|
return insertGroupSeparator ? (React.createElement(Fragment, { key: idx },
|
|
@@ -33,10 +33,10 @@ export const TogglerGroup = (props) => {
|
|
|
33
33
|
onSelected && onSelected({ value, checked, option, selectedValues });
|
|
34
34
|
}, disabled: isDisabled, readOnly: readOnly, 'aria-invalid': props['aria-invalid'], checked: isChecked });
|
|
35
35
|
if (renderItemSubContent) {
|
|
36
|
-
return (React.createElement("li", { key: i, className: `${bem}__item
|
|
36
|
+
return (React.createElement("li", { key: i, className: `${bem}__item`, role: "generic" },
|
|
37
37
|
React.createElement(Toggler, Object.assign({}, togglerProps)),
|
|
38
38
|
renderItemSubContent(option, isChecked)));
|
|
39
39
|
}
|
|
40
|
-
return (React.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li" }, togglerProps)));
|
|
40
|
+
return (React.createElement(Toggler, Object.assign({ key: i, className: `${bem}__item`, Wrapper: "li", role: "generic" }, togglerProps)));
|
|
41
41
|
})));
|
|
42
42
|
};
|
|
@@ -10,7 +10,7 @@ const defaultReqText = {
|
|
|
10
10
|
};
|
|
11
11
|
// eslint-disable-next-line complexity
|
|
12
12
|
export const TogglerInput = (props) => {
|
|
13
|
-
const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps } = props, restInputProps = __rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps"]);
|
|
13
|
+
const { bem, modifier, className, label, hideLabel, invalid, errorMessage, Wrapper = 'div', required, reqText, type, id, innerWrap, wrapperProps, inputProps, role } = props, restInputProps = __rest(props, ["bem", "modifier", "className", "label", "hideLabel", "invalid", "errorMessage", "Wrapper", "required", "reqText", "type", "id", "innerWrap", "wrapperProps", "inputProps", "role"]);
|
|
14
14
|
const domid = useDomid(id);
|
|
15
15
|
const errorId = errorMessage && `error${domid}`;
|
|
16
16
|
const reqStar = required && reqText !== false && (React.createElement("abbr", { className: `${bem}__label__reqstar`,
|
|
@@ -25,7 +25,7 @@ export const TogglerInput = (props) => {
|
|
|
25
25
|
' '));
|
|
26
26
|
return (React.createElement(Wrapper, Object.assign({}, wrapperProps, { className: modifiedClass(bem, [modifier, hideLabel && 'nolabel'],
|
|
27
27
|
// Prefer `className` over `wrapperProps.className`
|
|
28
|
-
className || (wrapperProps || {}).className) }),
|
|
28
|
+
className || (wrapperProps || {}).className), role: role }),
|
|
29
29
|
React.createElement("input", Object.assign({ className: `${bem}__input`, type: type, id: domid, "aria-invalid": invalid || !!errorMessage || undefined, "aria-describedby": errorId }, restInputProps, inputProps, (readOnly && { disabled: true }))),
|
|
30
30
|
' ',
|
|
31
31
|
React.createElement("label", { className: `${bem}__label`, htmlFor: domid },
|