@reykjavik/hanna-react 0.10.145 → 0.10.147
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.d.ts +18 -2
- package/AutosuggestSearch.js +26 -10
- package/CHANGELOG.md +16 -0
- package/Datepicker.js +1 -1
- package/esm/AutosuggestSearch.d.ts +18 -2
- package/esm/AutosuggestSearch.js +26 -10
- package/esm/Datepicker.js +1 -1
- package/package.json +1 -1
package/AutosuggestSearch.d.ts
CHANGED
|
@@ -30,7 +30,23 @@ export type AutosuggestSearchProps<T extends string | object> = {
|
|
|
30
30
|
value: string;
|
|
31
31
|
option: T;
|
|
32
32
|
}) => void;
|
|
33
|
-
onClearOptions
|
|
33
|
+
onClearOptions?: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Called when the sarch input receives focus, except when the user clicks
|
|
36
|
+
* a suggestion.
|
|
37
|
+
*
|
|
38
|
+
* Clicking a suggestion briefly blurs the input, and then when the
|
|
39
|
+
* input is immediately re-focused, this event is not triggered.
|
|
40
|
+
*/
|
|
41
|
+
onInputFocus?: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Called when the search input loses focus, except when the user clicks
|
|
44
|
+
* a suggestion and the input is immediately re-focused.
|
|
45
|
+
*
|
|
46
|
+
* Thus the triggering of this callback is thus always delayed by about 100ms
|
|
47
|
+
* and may occur after other elements have received focused.
|
|
48
|
+
*/
|
|
49
|
+
onInputBlurred?: () => void;
|
|
34
50
|
getOptionValue?: (option: T) => string;
|
|
35
51
|
renderSuggestion?: (option: T, context: {
|
|
36
52
|
query: string;
|
|
@@ -43,6 +59,6 @@ export type AutosuggestSearchProps<T extends string | object> = {
|
|
|
43
59
|
renderInputField?: (inputProps: RenderInputComponentProps, texts: AutosuggestSearchI18n) => JSX.Element;
|
|
44
60
|
texts?: AutosuggestSearchI18n;
|
|
45
61
|
lang?: HannaLang;
|
|
46
|
-
} & Pick<SearchInputProps, 'onSubmit' | 'onButtonClick' | 'button'> & WrapperElmProps
|
|
62
|
+
} & Pick<SearchInputProps, 'onSubmit' | 'onButtonClick' | 'button' | 'invalid' | 'errorMessage' | 'assistText'> & WrapperElmProps<'div', 'aria-label'>;
|
|
47
63
|
export declare const AutosuggestSearch: <T extends string | object>(props: AutosuggestSearchProps<T>) => JSX.Element;
|
|
48
64
|
export {};
|
package/AutosuggestSearch.js
CHANGED
|
@@ -40,20 +40,40 @@ const AutosuggestSearch = (props) => {
|
|
|
40
40
|
? opt.value.toString()
|
|
41
41
|
: '', renderSuggestion = (opt) => typeof opt === 'object' && 'label' in opt && opt.label != null
|
|
42
42
|
? opt.label.toString()
|
|
43
|
-
: getOptionValue(opt), InputComponent = SearchInput_js_1.default, renderInputField,
|
|
43
|
+
: getOptionValue(opt), InputComponent = SearchInput_js_1.default, renderInputField, invalid, errorMessage, assistText, onInputFocus, onInputBlurred, } = props;
|
|
44
44
|
const [inputValue, setInputValue] = (0, utils_js_1.useMixedControlState)(props, 'inputValue', '');
|
|
45
45
|
const inputRef = (0, react_1.useRef)(null);
|
|
46
46
|
const txt = (0, i18n_1.getTexts)(props, exports.defaultAutosuggestSearchTexts);
|
|
47
47
|
const showEmptyMessage = !options.length && emptyMessage;
|
|
48
|
+
const _a = props.wrapperProps || {}, { className } = _a, wrapperProps = tslib_1.__rest(_a, ["className"]);
|
|
49
|
+
const blurTimeout = (0, react_1.useRef)();
|
|
50
|
+
const inputFocusProps = onInputFocus || onInputBlurred
|
|
51
|
+
? {
|
|
52
|
+
onFocus: () => {
|
|
53
|
+
if (!blurTimeout.current) {
|
|
54
|
+
onInputFocus === null || onInputFocus === void 0 ? void 0 : onInputFocus();
|
|
55
|
+
}
|
|
56
|
+
clearTimeout(blurTimeout.current);
|
|
57
|
+
blurTimeout.current = undefined;
|
|
58
|
+
},
|
|
59
|
+
onBlur: () => {
|
|
60
|
+
clearTimeout(blurTimeout.current);
|
|
61
|
+
blurTimeout.current = setTimeout(() => {
|
|
62
|
+
blurTimeout.current = undefined;
|
|
63
|
+
onInputBlurred === null || onInputBlurred === void 0 ? void 0 : onInputBlurred();
|
|
64
|
+
}, 100);
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
: undefined;
|
|
48
68
|
return (react_1.default.createElement(react_autosuggest_1.default, { theme: {
|
|
49
|
-
container:
|
|
69
|
+
container: `AutosuggestSearch ${className || ''}`,
|
|
50
70
|
containerOpen: 'AutosuggestSearch--open',
|
|
51
71
|
suggestionsContainer: 'AutosuggestSearch__container',
|
|
52
72
|
suggestionsContainerOpen: 'AutosuggestSearch__container--open',
|
|
53
73
|
suggestionsList: (0, hanna_utils_1.modifiedClass)('AutosuggestSearch__list', itemActionIcon && `action--${itemActionIcon}`),
|
|
54
74
|
suggestion: 'AutosuggestSearch__item',
|
|
55
75
|
suggestionHighlighted: 'AutosuggestSearch__item--highlighted',
|
|
56
|
-
}, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ( /* { value } */) => {
|
|
76
|
+
}, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions || (() => undefined), onSuggestionsFetchRequested: ( /* { value } */) => {
|
|
57
77
|
// weirdly required prop, but we don't need to do anything here
|
|
58
78
|
// as we run onInput on input change below.
|
|
59
79
|
}, getSuggestionValue: showEmptyMessage
|
|
@@ -75,22 +95,18 @@ const AutosuggestSearch = (props) => {
|
|
|
75
95
|
contents = (react_1.default.createElement("div", { className: (0, hanna_utils_1.modifiedClass)('AutosuggestSearch__emptyMessage', type !== 'empty' && type) }, message));
|
|
76
96
|
}
|
|
77
97
|
return (react_1.default.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
|
|
78
|
-
}, inputProps: {
|
|
79
|
-
ref: inputRef,
|
|
80
|
-
value: inputValue,
|
|
81
|
-
onChange: (_, { newValue, method }) => {
|
|
98
|
+
}, inputProps: Object.assign({ ref: inputRef, value: inputValue, onChange: (_, { newValue, method }) => {
|
|
82
99
|
if (!inputChangeMethods.has(method)) {
|
|
83
100
|
return;
|
|
84
101
|
}
|
|
85
102
|
onInput(newValue);
|
|
86
103
|
setInputValue(newValue);
|
|
87
|
-
},
|
|
88
|
-
}, renderInputComponent: renderInputField
|
|
104
|
+
} }, inputFocusProps), renderInputComponent: renderInputField
|
|
89
105
|
? (inputProps) => renderInputField(inputProps, txt)
|
|
90
106
|
: (inputProps) => {
|
|
91
107
|
/* prettier-ignore */
|
|
92
108
|
const { className, type, disabled, readOnly, required, children, ref, defaultValue } = inputProps, siteSearchProps = tslib_1.__rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref", "defaultValue"]);
|
|
93
|
-
return (react_1.default.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
|
|
109
|
+
return (react_1.default.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, invalid: invalid, errorMessage: errorMessage, assistText: assistText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
|
|
94
110
|
} }));
|
|
95
111
|
};
|
|
96
112
|
exports.AutosuggestSearch = AutosuggestSearch;
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
- ... <!-- Add new lines here. -->
|
|
6
6
|
|
|
7
|
+
## 0.10.147
|
|
8
|
+
|
|
9
|
+
_2025-02-25_
|
|
10
|
+
|
|
11
|
+
- `AutosuggestSearch`:
|
|
12
|
+
- feat: Add props `errorMessage`, `invalid`, `assistText`
|
|
13
|
+
- feat: Add props `onInputFocus` and `onInputBlur`
|
|
14
|
+
- fix: `wrapperProps.className` overrides wrapper's default class
|
|
15
|
+
- fix: Make `onClearOptions` prop optional
|
|
16
|
+
|
|
17
|
+
## 0.10.146
|
|
18
|
+
|
|
19
|
+
_2025-02-10_
|
|
20
|
+
|
|
21
|
+
- fix: Avoid conrolled–uncontrolled warning for `Datepicker` in `isoMode`
|
|
22
|
+
|
|
7
23
|
## 0.10.145
|
|
8
24
|
|
|
9
25
|
_2025-01-14_
|
package/Datepicker.js
CHANGED
|
@@ -110,7 +110,7 @@ const defaultDatepickerTexts = {
|
|
|
110
110
|
};
|
|
111
111
|
const toLocalIsoDate = (date) => {
|
|
112
112
|
if (!date) {
|
|
113
|
-
return
|
|
113
|
+
return '';
|
|
114
114
|
}
|
|
115
115
|
const localDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
|
|
116
116
|
return localDate.toISOString().split('T')[0];
|
|
@@ -30,7 +30,23 @@ export type AutosuggestSearchProps<T extends string | object> = {
|
|
|
30
30
|
value: string;
|
|
31
31
|
option: T;
|
|
32
32
|
}) => void;
|
|
33
|
-
onClearOptions
|
|
33
|
+
onClearOptions?: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Called when the sarch input receives focus, except when the user clicks
|
|
36
|
+
* a suggestion.
|
|
37
|
+
*
|
|
38
|
+
* Clicking a suggestion briefly blurs the input, and then when the
|
|
39
|
+
* input is immediately re-focused, this event is not triggered.
|
|
40
|
+
*/
|
|
41
|
+
onInputFocus?: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Called when the search input loses focus, except when the user clicks
|
|
44
|
+
* a suggestion and the input is immediately re-focused.
|
|
45
|
+
*
|
|
46
|
+
* Thus the triggering of this callback is thus always delayed by about 100ms
|
|
47
|
+
* and may occur after other elements have received focused.
|
|
48
|
+
*/
|
|
49
|
+
onInputBlurred?: () => void;
|
|
34
50
|
getOptionValue?: (option: T) => string;
|
|
35
51
|
renderSuggestion?: (option: T, context: {
|
|
36
52
|
query: string;
|
|
@@ -43,6 +59,6 @@ export type AutosuggestSearchProps<T extends string | object> = {
|
|
|
43
59
|
renderInputField?: (inputProps: RenderInputComponentProps, texts: AutosuggestSearchI18n) => JSX.Element;
|
|
44
60
|
texts?: AutosuggestSearchI18n;
|
|
45
61
|
lang?: HannaLang;
|
|
46
|
-
} & Pick<SearchInputProps, 'onSubmit' | 'onButtonClick' | 'button'> & WrapperElmProps
|
|
62
|
+
} & Pick<SearchInputProps, 'onSubmit' | 'onButtonClick' | 'button' | 'invalid' | 'errorMessage' | 'assistText'> & WrapperElmProps<'div', 'aria-label'>;
|
|
47
63
|
export declare const AutosuggestSearch: <T extends string | object>(props: AutosuggestSearchProps<T>) => JSX.Element;
|
|
48
64
|
export {};
|
package/esm/AutosuggestSearch.js
CHANGED
|
@@ -37,20 +37,40 @@ export const AutosuggestSearch = (props) => {
|
|
|
37
37
|
? opt.value.toString()
|
|
38
38
|
: '', renderSuggestion = (opt) => typeof opt === 'object' && 'label' in opt && opt.label != null
|
|
39
39
|
? opt.label.toString()
|
|
40
|
-
: getOptionValue(opt), InputComponent = SearchInput, renderInputField,
|
|
40
|
+
: getOptionValue(opt), InputComponent = SearchInput, renderInputField, invalid, errorMessage, assistText, onInputFocus, onInputBlurred, } = props;
|
|
41
41
|
const [inputValue, setInputValue] = useMixedControlState(props, 'inputValue', '');
|
|
42
42
|
const inputRef = useRef(null);
|
|
43
43
|
const txt = getTexts(props, defaultAutosuggestSearchTexts);
|
|
44
44
|
const showEmptyMessage = !options.length && emptyMessage;
|
|
45
|
+
const _a = props.wrapperProps || {}, { className } = _a, wrapperProps = __rest(_a, ["className"]);
|
|
46
|
+
const blurTimeout = useRef();
|
|
47
|
+
const inputFocusProps = onInputFocus || onInputBlurred
|
|
48
|
+
? {
|
|
49
|
+
onFocus: () => {
|
|
50
|
+
if (!blurTimeout.current) {
|
|
51
|
+
onInputFocus === null || onInputFocus === void 0 ? void 0 : onInputFocus();
|
|
52
|
+
}
|
|
53
|
+
clearTimeout(blurTimeout.current);
|
|
54
|
+
blurTimeout.current = undefined;
|
|
55
|
+
},
|
|
56
|
+
onBlur: () => {
|
|
57
|
+
clearTimeout(blurTimeout.current);
|
|
58
|
+
blurTimeout.current = setTimeout(() => {
|
|
59
|
+
blurTimeout.current = undefined;
|
|
60
|
+
onInputBlurred === null || onInputBlurred === void 0 ? void 0 : onInputBlurred();
|
|
61
|
+
}, 100);
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
: undefined;
|
|
45
65
|
return (React.createElement(Autosuggest, { theme: {
|
|
46
|
-
container:
|
|
66
|
+
container: `AutosuggestSearch ${className || ''}`,
|
|
47
67
|
containerOpen: 'AutosuggestSearch--open',
|
|
48
68
|
suggestionsContainer: 'AutosuggestSearch__container',
|
|
49
69
|
suggestionsContainerOpen: 'AutosuggestSearch__container--open',
|
|
50
70
|
suggestionsList: modifiedClass('AutosuggestSearch__list', itemActionIcon && `action--${itemActionIcon}`),
|
|
51
71
|
suggestion: 'AutosuggestSearch__item',
|
|
52
72
|
suggestionHighlighted: 'AutosuggestSearch__item--highlighted',
|
|
53
|
-
}, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions, onSuggestionsFetchRequested: ( /* { value } */) => {
|
|
73
|
+
}, focusInputOnSuggestionClick: true, suggestions: showEmptyMessage ? [true] : options, onSuggestionsClearRequested: onClearOptions || (() => undefined), onSuggestionsFetchRequested: ( /* { value } */) => {
|
|
54
74
|
// weirdly required prop, but we don't need to do anything here
|
|
55
75
|
// as we run onInput on input change below.
|
|
56
76
|
}, getSuggestionValue: showEmptyMessage
|
|
@@ -72,21 +92,17 @@ export const AutosuggestSearch = (props) => {
|
|
|
72
92
|
contents = (React.createElement("div", { className: modifiedClass('AutosuggestSearch__emptyMessage', type !== 'empty' && type) }, message));
|
|
73
93
|
}
|
|
74
94
|
return (React.createElement("div", Object.assign({}, containerProps, { "aria-label": options.length ? txt.suggestionsLabel : undefined }), contents));
|
|
75
|
-
}, inputProps: {
|
|
76
|
-
ref: inputRef,
|
|
77
|
-
value: inputValue,
|
|
78
|
-
onChange: (_, { newValue, method }) => {
|
|
95
|
+
}, inputProps: Object.assign({ ref: inputRef, value: inputValue, onChange: (_, { newValue, method }) => {
|
|
79
96
|
if (!inputChangeMethods.has(method)) {
|
|
80
97
|
return;
|
|
81
98
|
}
|
|
82
99
|
onInput(newValue);
|
|
83
100
|
setInputValue(newValue);
|
|
84
|
-
},
|
|
85
|
-
}, renderInputComponent: renderInputField
|
|
101
|
+
} }, inputFocusProps), renderInputComponent: renderInputField
|
|
86
102
|
? (inputProps) => renderInputField(inputProps, txt)
|
|
87
103
|
: (inputProps) => {
|
|
88
104
|
/* prettier-ignore */
|
|
89
105
|
const { className, type, disabled, readOnly, required, children, ref, defaultValue } = inputProps, siteSearchProps = __rest(inputProps, ["className", "type", "disabled", "readOnly", "required", "children", "ref", "defaultValue"]);
|
|
90
|
-
return (React.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
|
|
106
|
+
return (React.createElement(InputComponent, Object.assign({ lang: props.lang, defaultValue: defaultValue }, siteSearchProps, { inputRef: ref, button: button, label: txt.inputLabel, placeholder: txt.placeholder, buttonText: txt.buttonText, invalid: invalid, errorMessage: errorMessage, assistText: assistText, onSubmit: onSubmit && (() => onSubmit(inputValue)), onButtonClick: onButtonClick && (() => onButtonClick(inputValue)) })));
|
|
91
107
|
} }));
|
|
92
108
|
};
|
package/esm/Datepicker.js
CHANGED
|
@@ -105,7 +105,7 @@ const defaultDatepickerTexts = {
|
|
|
105
105
|
};
|
|
106
106
|
const toLocalIsoDate = (date) => {
|
|
107
107
|
if (!date) {
|
|
108
|
-
return
|
|
108
|
+
return '';
|
|
109
109
|
}
|
|
110
110
|
const localDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
|
|
111
111
|
return localDate.toISOString().split('T')[0];
|