@homecode/ui 4.18.70 → 4.19.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.
Files changed (27) hide show
  1. package/dist/esm/index.js +5 -0
  2. package/dist/esm/src/components/Autocomplete/Autocomplete.js +140 -0
  3. package/dist/esm/src/components/Autocomplete/Autocomplete.styl.js +7 -0
  4. package/dist/esm/src/components/Input/Input.js +5 -2
  5. package/dist/esm/src/components/InputFile/InputFile.js +3 -0
  6. package/dist/esm/src/components/Menu/Menu.js +23 -0
  7. package/dist/esm/src/components/Menu/Menu.styl.js +7 -0
  8. package/dist/esm/src/components/Popup/Popup.js +1 -1
  9. package/dist/esm/src/components/Shimmer/Shimmer.js +7 -0
  10. package/dist/esm/src/components/Shimmer/Shimmer.styl.js +7 -0
  11. package/dist/esm/src/hooks/useEvent.js +29 -0
  12. package/dist/esm/src/hooks/useIsMounted.js +11 -0
  13. package/dist/esm/src/hooks/useListKeyboardControl.js +50 -0
  14. package/dist/esm/types/src/components/Autocomplete/Autocomplete.d.ts +2 -0
  15. package/dist/esm/types/src/components/Autocomplete/Autocomplete.types.d.ts +19 -0
  16. package/dist/esm/types/src/components/Icon/Icon.d.ts +3 -0
  17. package/dist/esm/types/src/components/Input/Input.d.ts +1 -1
  18. package/dist/esm/types/src/components/Input/Input.types.d.ts +1 -1
  19. package/dist/esm/types/src/components/Menu/Menu.d.ts +6 -0
  20. package/dist/esm/types/src/components/Menu/Menu.types.d.ts +22 -0
  21. package/dist/esm/types/src/components/Shimmer/Shimmer.d.ts +7 -0
  22. package/dist/esm/types/src/components/index.d.ts +3 -0
  23. package/dist/esm/types/src/hooks/useEvent.d.ts +8 -0
  24. package/dist/esm/types/src/hooks/useIsMounted.d.ts +1 -0
  25. package/dist/esm/types/src/hooks/useListKeyboardControl.d.ts +10 -0
  26. package/dist/esm/types/src/types.d.ts +2 -2
  27. package/package.json +1 -1
package/dist/esm/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { AssistiveText } from './src/components/AssistiveText/AssistiveText.js';
2
+ export { Autocomplete } from './src/components/Autocomplete/Autocomplete.js';
2
3
  export { Button } from './src/components/Button/Button.js';
3
4
  export { ButtonGroup } from './src/components/ButtonGroup/ButtonGroup.js';
4
5
  export { Calendar } from './src/components/Calendar/Calendar.js';
@@ -18,6 +19,7 @@ export { InputFile } from './src/components/InputFile/InputFile.js';
18
19
  export { Label } from './src/components/Label/Label.js';
19
20
  export { Lazy } from './src/components/Lazy/Lazy.js';
20
21
  export { LightBox } from './src/components/LightBox/LightBox.js';
22
+ export { Menu } from './src/components/Menu/Menu.js';
21
23
  export { Notifications, NotificationsStore } from './src/components/Notifications/Notifications.js';
22
24
  export { Paranja } from './src/components/Paranja/Paranja.js';
23
25
  export { ANIMATION_DURATION, Popup } from './src/components/Popup/Popup.js';
@@ -27,6 +29,9 @@ export { Router, RouterContext, RouterStore } from './src/components/Router/Rout
27
29
  export { RequiredStar } from './src/components/RequiredStar/RequiredStar.js';
28
30
  export { Select, SelectHelpers } from './src/components/Select/Select.js';
29
31
  export { Scroll } from './src/components/Scroll/Scroll.js';
32
+ import 'react/jsx-runtime';
33
+ import 'classnames';
34
+ import './src/components/Shimmer/Shimmer.styl.js';
30
35
  export { Spinner } from './src/components/Spinner/Spinner.js';
31
36
  export { Table } from './src/components/Table/Table.js';
32
37
  export { Tabs } from './src/components/Tabs/Tabs.js';
@@ -0,0 +1,140 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import cn from 'classnames';
3
+ import '../AssistiveText/AssistiveText.styl.js';
4
+ import { useState, useRef, useEffect, useMemo } from 'react';
5
+ import debounce from '../../tools/debounce.js';
6
+ import { useIsMounted } from '../../hooks/useIsMounted.js';
7
+ import S from './Autocomplete.styl.js';
8
+ import Shimmer from '../Shimmer/Shimmer.js';
9
+ import { useListKeyboardControl } from '../../hooks/useListKeyboardControl.js';
10
+ import '../Spinner/Spinner.styl.js';
11
+ import '../Button/Button.styl.js';
12
+ import '../ButtonGroup/ButtonGroup.styl.js';
13
+ import '../Calendar/Calendar.styl.js';
14
+ import { Input } from '../Input/Input.js';
15
+ import '../../tools/dom.js';
16
+ import '../Icon/Icon.js';
17
+ import 'timen';
18
+ import '../Label/Label.styl.js';
19
+ import { Popup } from '../Popup/Popup.js';
20
+ import '../RequiredStar/RequiredStar.styl.js';
21
+ import '../Select/Select.styl.js';
22
+ import 'justorm/react';
23
+ import 'lodash.omit';
24
+ import 'compareq';
25
+ import 'lodash.pick';
26
+ import '../Scroll/Scroll.styl.js';
27
+ import 'nanoid';
28
+ import '../Checkbox/Checkbox.styl.js';
29
+ import '../Container/Container.styl.js';
30
+ import '../DatePicker/DatePicker.styl.js';
31
+ import 'moment';
32
+ import '../DatePickerInput/DatePickerInput.styl.js';
33
+ import '../../tools/queryParams.js';
34
+ import '../Draggable/Draggable.styl.js';
35
+ import '../Expand/Expand.styl.js';
36
+ import '../Form/Form.styl.js';
37
+ import '../Form/Validator.js';
38
+ import '../Form/SubmitButtons/SubmitButtons.styl.js';
39
+ import '../Gallery/Gallery.styl.js';
40
+ import '../Heading/Heading.js';
41
+ import '../InputFile/InputFile.styl.js';
42
+ import '../InputFile/Item/Item.styl.js';
43
+ import '../../services/i18n.js';
44
+ import '../Portal/Portal.js';
45
+ import '../Paranja/Paranja.styl.js';
46
+ import '../LightBox/LightBox.styl.js';
47
+ import { Menu } from '../Menu/Menu.js';
48
+ import '../Notifications/Notifications.js';
49
+ import '../PopupMenu/PopupMenu.styl.js';
50
+ import '../Router/Router.js';
51
+ import '../Table/Table.styl.js';
52
+ import '../Tabs/Tabs.styl.js';
53
+ import '../Text/Text.js';
54
+ import '../Virtualized/Virtualized.styl.js';
55
+ import '../Virtualized/List/List.styl.js';
56
+ import '../Virtualized/List/ListScroll.styl.js';
57
+
58
+ function Autocomplete(props) {
59
+ const { className, inputWrapperClassName, value, onChange, size = 'm', getOptions, onSelect, debounceDelay = 300, inputProps = {}, popupProps = {}, } = props;
60
+ const isMounted = useIsMounted();
61
+ const [searchValue, setSearchValue] = useState(value);
62
+ const [options, setOptions] = useState([]);
63
+ const [isLoading, setIsLoading] = useState(false);
64
+ const [isFocused, setIsFocused] = useState(false);
65
+ const currentRequest = useRef('');
66
+ const inputRef = useRef(null);
67
+ const isOpen = isFocused && options.length > 0;
68
+ const classes = cn(S.root, className);
69
+ const handleInputChange = (e, value) => {
70
+ const val = (value || e?.target.value) ?? '';
71
+ setOptions([]);
72
+ setSearchValue(val);
73
+ onChange(e, val);
74
+ fetchOptions(val);
75
+ return true;
76
+ };
77
+ const handleSelect = (value) => {
78
+ setSearchValue(value);
79
+ setOptions([]);
80
+ onSelect(value);
81
+ // set input caret to the end
82
+ requestAnimationFrame(() => {
83
+ const input = inputRef.current?.inputRef.current;
84
+ if (!input)
85
+ return;
86
+ input.focus();
87
+ input.setSelectionRange(value.length, value.length);
88
+ });
89
+ };
90
+ const { focusedIndex, setFocusedIndex } = useListKeyboardControl({
91
+ isActive: isOpen,
92
+ itemsCount: options.length,
93
+ onSelect: index => {
94
+ handleSelect(options[index].label);
95
+ },
96
+ });
97
+ const fetchOptions = debounce(async (inputValue) => {
98
+ if (!inputValue) {
99
+ setOptions([]);
100
+ return;
101
+ }
102
+ currentRequest.current = inputValue;
103
+ setIsLoading(true);
104
+ try {
105
+ const newOptions = await getOptions(inputValue);
106
+ if (!isMounted.current)
107
+ return;
108
+ if (currentRequest.current !== inputValue)
109
+ return;
110
+ setOptions(newOptions);
111
+ }
112
+ catch (error) {
113
+ setOptions([]);
114
+ }
115
+ finally {
116
+ setIsLoading(false);
117
+ }
118
+ }, debounceDelay);
119
+ useEffect(() => {
120
+ setSearchValue(value);
121
+ }, [value]);
122
+ const optionsList = useMemo(() => {
123
+ if (!options.length)
124
+ return null;
125
+ return (jsx(Menu, { className: S.options, size: size, children: options.map((option, index) => (jsx(Menu.Item, { focused: focusedIndex === index, className: S.option, onClick: () => handleSelect(option.label), onMouseEnter: () => setFocusedIndex(index), children: option.label }, option.id))) }));
126
+ }, [options, focusedIndex]);
127
+ return (jsx(Popup, { className: classes, isOpen: isOpen, focusControl: true, size: size, ...popupProps, trigger: jsxs("div", { className: inputWrapperClassName, children: [jsx(Input, { ref: inputRef,
128
+ // @ts-ignore
129
+ size: size, ...inputProps, value: searchValue, onChange: handleInputChange, className: inputProps.className, onFocus: e => {
130
+ setIsFocused(true);
131
+ inputProps.onFocus?.(e);
132
+ }, onBlur: e => {
133
+ setIsFocused(false);
134
+ inputProps.onBlur?.(e);
135
+ } }), isLoading && jsx(Shimmer, { className: S.shimmer, size: size })] }), content: optionsList, contentProps: {
136
+ className: S.popupContent,
137
+ } }));
138
+ }
139
+
140
+ export { Autocomplete };
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".Autocomplete_root__86RQs{position:relative}.Autocomplete_popupContent__Aet6P{margin-top:8px;width:100%}.Autocomplete_options__NtttU{max-height:200px;overflow-y:auto}.Autocomplete_option__uBuih{cursor:pointer;padding:8px 12px}.Autocomplete_shimmer__s6rri{height:100%;left:0;position:absolute;top:0;width:100%}";
4
+ var S = {"root":"Autocomplete_root__86RQs","popupContent":"Autocomplete_popupContent__Aet6P","options":"Autocomplete_options__NtttU","option":"Autocomplete_option__uBuih","shimmer":"Autocomplete_shimmer__s6rri"};
5
+ styleInject(css_248z);
6
+
7
+ export { S as default };
@@ -12,6 +12,9 @@ import { Scroll } from '../Scroll/Scroll.js';
12
12
  import { capitalize } from '../../tools/string.js';
13
13
  import { generateUID } from '../../tools/uid.js';
14
14
  import S from './Input.styl.js';
15
+ import debounce from '../../tools/debounce.js';
16
+ import '../Autocomplete/Autocomplete.styl.js';
17
+ import '../Shimmer/Shimmer.styl.js';
15
18
  import '../ButtonGroup/ButtonGroup.styl.js';
16
19
  import '../Calendar/Calendar.styl.js';
17
20
  import '../../tools/dom.js';
@@ -20,7 +23,6 @@ import '../Portal/Portal.js';
20
23
  import '../Paranja/Paranja.styl.js';
21
24
  import 'compareq';
22
25
  import 'lodash.pick';
23
- import debounce from '../../tools/debounce.js';
24
26
  import '../Popup/Popup.styl.js';
25
27
  import '../../tools/queryParams.js';
26
28
  import '../Select/Select.styl.js';
@@ -40,6 +42,7 @@ import '../Heading/Heading.js';
40
42
  import '../InputFile/InputFile.styl.js';
41
43
  import '../InputFile/Item/Item.styl.js';
42
44
  import '../LightBox/LightBox.styl.js';
45
+ import '../Menu/Menu.js';
43
46
  import '../Notifications/Notifications.js';
44
47
  import '../PopupMenu/PopupMenu.styl.js';
45
48
  import '../Router/Router.js';
@@ -196,7 +199,7 @@ class Input extends Component {
196
199
  };
197
200
  handleChange = (e) => {
198
201
  const value = this.getValue(e.target.value);
199
- this.onChange(value);
202
+ this.onChange(value, e);
200
203
  };
201
204
  onChange = (value, e) => {
202
205
  const { onChange, changeOnEnd, type } = this.props;
@@ -13,6 +13,8 @@ import { spliceWhere } from '../../tools/array.js';
13
13
  import S from './InputFile.styl.js';
14
14
  import Item from './Item/Item.js';
15
15
  import '../AssistiveText/AssistiveText.styl.js';
16
+ import '../Autocomplete/Autocomplete.styl.js';
17
+ import '../Shimmer/Shimmer.styl.js';
16
18
  import '../Spinner/Spinner.styl.js';
17
19
  import '../Button/Button.styl.js';
18
20
  import '../ButtonGroup/ButtonGroup.styl.js';
@@ -40,6 +42,7 @@ import '../Form/SubmitButtons/SubmitButtons.styl.js';
40
42
  import '../Gallery/Gallery.styl.js';
41
43
  import '../Heading/Heading.js';
42
44
  import '../LightBox/LightBox.styl.js';
45
+ import '../Menu/Menu.js';
43
46
  import '../Notifications/Notifications.js';
44
47
  import '../PopupMenu/PopupMenu.styl.js';
45
48
  import '../Router/Router.js';
@@ -0,0 +1,23 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { forwardRef } from 'react';
3
+ import cn from 'classnames';
4
+ import { Scroll } from '../Scroll/Scroll.js';
5
+ import S from './Menu.styl.js';
6
+
7
+ const MenuComponent = forwardRef(({ children, className, ...props }, ref) => {
8
+ return (jsx(Scroll, { y: true, ref: ref, className: cn(S.root, className), ...props, children: children }));
9
+ });
10
+ const MenuItem = forwardRef((props, ref) => {
11
+ const { children, className, selected, focused, disabled, level = 0, onClick, size = 'm', ...rest } = props;
12
+ const classes = cn(S.item, S[`size-${size}`], level > 0 && S[`level-${level}`], selected && S.selected, focused && S.focused, disabled && S.disabled, className);
13
+ return (jsx("div", { ref: ref, className: classes, onClick: disabled ? undefined : onClick, ...rest, children: jsx("span", { children: children }) }));
14
+ });
15
+ const MenuGroup = ({ children, className, label, ...props }) => {
16
+ return (jsxs(Fragment, { children: [jsx("div", { className: cn(S.group, className), ...props, children: label }), children] }));
17
+ };
18
+ const Menu = Object.assign(MenuComponent, {
19
+ Item: MenuItem,
20
+ Group: MenuGroup,
21
+ });
22
+
23
+ export { Menu };
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".Menu_root__xhtlo{max-height:200px;width:100%}.keyboard .Menu_root__xhtlo{pointer-events:none}.Menu_item__VtmwS{align-items:center;animation:Menu_fadeIn__XRZkT .3s ease-out;cursor:pointer;display:flex;overflow:hidden;padding-bottom:0!important;padding-top:0!important;position:relative;text-align:left;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap;width:calc(100% - 2px)}.Menu_item__VtmwS:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.Menu_item__VtmwS:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.Menu_item__VtmwS>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.Menu_item__VtmwS.Menu_size-s__DA0r3{font-size:16px;height:34px;padding:0 8px}.Menu_item__VtmwS.Menu_size-m__0EI47{font-size:20px;height:38px;padding:0 12px}.Menu_item__VtmwS.Menu_size-l__PXpIm{font-size:24px;height:42px;padding:0 14px}.Menu_item__VtmwS.Menu_size-xl__U1WW8{height:46px}.Menu_item__VtmwS.Menu_selected__V71xy{background-color:var(--active-color-alpha-500)}.Menu_item__VtmwS.Menu_disabled__5afRm{cursor:not-allowed;opacity:.4}.keyboard .Menu_item__VtmwS.Menu_focused__FLWqW,.pointer .Menu_item__VtmwS:hover{box-shadow:inset 100vw 0 0 0 var(--accent-color-alpha-200)}.Menu_group__6e-Ef{background-color:var(--decent-color);color:var(--accent-color);font-size:14px;font-weight:500;padding:8px 12px;pointer-events:none;position:sticky;top:0;z-index:1}.Menu_levelIndent__S6HXJ{--menu-indent-size:var(--indent-s)}.Menu_levelIndent__S6HXJ.Menu_level-1__kueO2{padding-left:calc(var(--menu-indent-size)*2)}.Menu_levelIndent__S6HXJ.Menu_level-2__JZGkJ{padding-left:calc(var(--menu-indent-size)*3)}.Menu_levelIndent__S6HXJ.Menu_level-3__LFd-F{padding-left:calc(var(--menu-indent-size)*4)}.Menu_levelIndent__S6HXJ.Menu_level-4__2DUMl{padding-left:calc(var(--menu-indent-size)*5)}.Menu_levelIndent__S6HXJ.Menu_level-5__xpgvQ{padding-left:calc(var(--menu-indent-size)*6)}@keyframes Menu_fadeIn__XRZkT{0%{opacity:0}10%{opacity:0}to{opacity:1}}";
4
+ var S = {"root":"Menu_root__xhtlo","item":"Menu_item__VtmwS","fadeIn":"Menu_fadeIn__XRZkT","size-s":"Menu_size-s__DA0r3","size-m":"Menu_size-m__0EI47","size-l":"Menu_size-l__PXpIm","size-xl":"Menu_size-xl__U1WW8","selected":"Menu_selected__V71xy","disabled":"Menu_disabled__5afRm","focused":"Menu_focused__FLWqW","group":"Menu_group__6e-Ef","levelIndent":"Menu_levelIndent__S6HXJ","level-1":"Menu_level-1__kueO2","level-2":"Menu_level-2__JZGkJ","level-3":"Menu_level-3__LFd-F","level-4":"Menu_level-4__2DUMl","level-5":"Menu_level-5__xpgvQ"};
5
+ styleInject(css_248z);
6
+
7
+ export { S as default };
@@ -348,7 +348,7 @@ class Popup extends Component {
348
348
  const { isOpen } = this.store;
349
349
  if (!trigger)
350
350
  return null;
351
- const disableTrigger = disabled || !content;
351
+ const disableTrigger = disabled || !trigger;
352
352
  const classesTrigger = cn(S.trigger, isOpen && S.isOpen, disableTrigger && S.disabled, triggerProps.className);
353
353
  if (!disableTrigger) {
354
354
  triggerProps.role = 'button';
@@ -0,0 +1,7 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import cn from 'classnames';
3
+ import S from './Shimmer.styl.js';
4
+
5
+ const Shimmer = ({ className, size = 'm' }) => (jsx("div", { className: cn(S.root, className, S[`size-${size}`]), children: jsx("div", { className: S.inner }) }));
6
+
7
+ export { Shimmer as default };
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".Shimmer_root__XaY5r{height:100%;left:0;overflow:hidden;pointer-events:none;position:absolute;top:0;width:100%}.Shimmer_inner__zssMV{animation:Shimmer_shimmer__hGfzF 1.5s linear infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.2) 50%,transparent);inset:0;position:absolute}.Shimmer_size-s__EYKhC{border-radius:4px}.Shimmer_size-m__AYziL{border-radius:6px}.Shimmer_size-l__GqE0a{border-radius:8px}@keyframes Shimmer_shimmer__hGfzF{0%{transform:translateX(-100%)}20%{transform:translateX(100%)}to{transform:translateX(100%)}}";
4
+ var S = {"root":"Shimmer_root__XaY5r","inner":"Shimmer_inner__zssMV","shimmer":"Shimmer_shimmer__hGfzF","size-s":"Shimmer_size-s__EYKhC","size-m":"Shimmer_size-m__AYziL","size-l":"Shimmer_size-l__GqE0a"};
5
+ styleInject(css_248z);
6
+
7
+ export { S as default };
@@ -0,0 +1,29 @@
1
+ import { useEffect } from 'react';
2
+
3
+ function useEvent({ elem, event, callback, isActive = true, }) {
4
+ useEffect(() => {
5
+ const events = Array.isArray(event) ? event : [event];
6
+ const elems = elem ? (Array.isArray(elem) ? elem : [elem]) : [document];
7
+ const getElem = (el) => el && ('current' in el ? el.current : el);
8
+ const each = cb => {
9
+ events.forEach(ev => {
10
+ elems.forEach(el => cb(getElem(el), ev));
11
+ });
12
+ };
13
+ const enable = () => {
14
+ each((el, ev) => el?.addEventListener(ev, callback));
15
+ };
16
+ const disable = () => {
17
+ each((el, ev) => el?.removeEventListener(ev, callback));
18
+ };
19
+ const hasRef = !elem || elems.some(getElem);
20
+ if (isActive && hasRef) {
21
+ enable();
22
+ }
23
+ return () => {
24
+ disable();
25
+ };
26
+ }, [isActive, elem, callback]);
27
+ }
28
+
29
+ export { useEvent as default };
@@ -0,0 +1,11 @@
1
+ import { useRef, useEffect } from 'react';
2
+
3
+ const useIsMounted = () => {
4
+ const isMounted = useRef(false);
5
+ useEffect(() => {
6
+ isMounted.current = true;
7
+ }, []);
8
+ return isMounted;
9
+ };
10
+
11
+ export { useIsMounted };
@@ -0,0 +1,50 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+ import useEvent from './useEvent.js';
3
+
4
+ const useListKeyboardControl = ({ isActive, itemsCount, onSelect, }) => {
5
+ const [focusedIndex, setFocusedIndex] = useState(-1);
6
+ const handleKeyDown = useCallback((e) => {
7
+ let newIndex = focusedIndex;
8
+ const set = (index) => {
9
+ e.preventDefault();
10
+ e.stopPropagation();
11
+ setFocusedIndex(index);
12
+ return;
13
+ };
14
+ if (e.key === 'ArrowDown') {
15
+ newIndex++;
16
+ if (newIndex >= itemsCount)
17
+ newIndex = 0;
18
+ set(newIndex);
19
+ return;
20
+ }
21
+ if (e.key === 'ArrowUp') {
22
+ newIndex--;
23
+ if (newIndex < 0)
24
+ newIndex = itemsCount - 1;
25
+ set(newIndex);
26
+ return;
27
+ }
28
+ if (e.key === 'Enter') {
29
+ onSelect(newIndex);
30
+ return;
31
+ }
32
+ }, [focusedIndex, itemsCount, onSelect]);
33
+ useEvent({
34
+ elem: document,
35
+ event: 'keydown',
36
+ callback: handleKeyDown,
37
+ isActive,
38
+ });
39
+ useEffect(() => {
40
+ if (itemsCount < focusedIndex) {
41
+ setFocusedIndex(itemsCount - 1);
42
+ }
43
+ }, [itemsCount]);
44
+ return {
45
+ focusedIndex,
46
+ setFocusedIndex,
47
+ };
48
+ };
49
+
50
+ export { useListKeyboardControl };
@@ -0,0 +1,2 @@
1
+ import * as T from './Autocomplete.types';
2
+ export declare function Autocomplete(props: T.Props): JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { FormControl, Size } from 'uilib/types';
2
+ import { Props as InputProps } from 'uilib/components/Input/Input.types';
3
+ import { Props as PopupProps } from 'uilib/components/Popup/Popup.types';
4
+ export type Option = {
5
+ id: string;
6
+ label: string;
7
+ };
8
+ export type Value = string;
9
+ export type Props = FormControl<Value, HTMLInputElement> & {
10
+ className?: string;
11
+ inputWrapperClassName?: string;
12
+ size?: Size;
13
+ value: Value;
14
+ getOptions: (value: Value) => Promise<Option[]>;
15
+ onSelect: (value: Value) => void;
16
+ debounceDelay?: number;
17
+ inputProps?: Partial<InputProps>;
18
+ popupProps?: Partial<PopupProps>;
19
+ };
@@ -11,6 +11,7 @@ export declare const icons: {
11
11
  chevronDown: () => Promise<any>;
12
12
  chevronRight: () => Promise<any>;
13
13
  chevronLeft: () => Promise<any>;
14
+ clearAll: () => Promise<any>;
14
15
  delete: () => Promise<any>;
15
16
  draft: () => Promise<any>;
16
17
  edit: () => Promise<any>;
@@ -23,6 +24,7 @@ export declare const icons: {
23
24
  fullscreen: () => Promise<any>;
24
25
  fullscreenExit: () => Promise<any>;
25
26
  function: () => Promise<any>;
27
+ flyover: () => Promise<any>;
26
28
  gear: () => Promise<any>;
27
29
  geolocation: () => Promise<any>;
28
30
  group: () => Promise<any>;
@@ -53,6 +55,7 @@ export declare const icons: {
53
55
  settings: () => Promise<any>;
54
56
  shoppingBag: () => Promise<any>;
55
57
  sparks: () => Promise<any>;
58
+ star: () => Promise<any>;
56
59
  syncArrows: () => Promise<any>;
57
60
  table: () => Promise<any>;
58
61
  telegram: () => Promise<any>;
@@ -30,7 +30,7 @@ export declare class Input extends Component<T.Props> {
30
30
  onClearPress: (e: any) => void;
31
31
  onDocKeyUp: (e: KeyboardEvent) => void;
32
32
  handleChange: (e: ChangeEvent<HTMLInputElement>) => void;
33
- onChange: (value: any, e?: any) => void;
33
+ onChange: (value: string, e?: ChangeEvent<HTMLInputElement>) => void;
34
34
  onNumberWheel: (delta: any) => void;
35
35
  onTextAreaInput: (e: any) => void;
36
36
  onLabelClipPathChange: (clipPath: string) => string;
@@ -3,7 +3,7 @@ import type { ComponentType, FormControl, Size, Variant } from '../../types';
3
3
  import type { Props as ScrollProps } from '../Scroll/Scroll.types';
4
4
  export type ControlProps = HTMLProps<HTMLInputElement>;
5
5
  export type Value = string | number;
6
- export type Props = Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> & Omit<ControlProps, 'ref'> & FormControl<Value> & {
6
+ export type Props = Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> & Omit<ControlProps, 'ref' | 'onChange'> & FormControl<Value, HTMLInputElement> & {
7
7
  name?: string;
8
8
  step?: number;
9
9
  size?: Size;
@@ -0,0 +1,6 @@
1
+ import { Scroll } from 'uilib/components/Scroll/Scroll';
2
+ import { MenuGroupProps, MenuItemProps, MenuProps } from './Menu.types';
3
+ export declare const Menu: import("react").ForwardRefExoticComponent<MenuProps & import("react").RefAttributes<Scroll>> & {
4
+ Item: import("react").ForwardRefExoticComponent<MenuItemProps & import("react").RefAttributes<HTMLDivElement>>;
5
+ Group: import("react").FC<MenuGroupProps>;
6
+ };
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from 'react';
2
+ import { Size } from 'uilib/types';
3
+ export interface MenuProps {
4
+ children: ReactNode;
5
+ className?: string;
6
+ size?: Size;
7
+ }
8
+ export interface MenuItemProps extends React.HTMLAttributes<HTMLDivElement> {
9
+ children: ReactNode;
10
+ className?: string;
11
+ selected?: boolean;
12
+ focused?: boolean;
13
+ disabled?: boolean;
14
+ level?: number;
15
+ size?: Size;
16
+ }
17
+ export interface MenuGroupProps {
18
+ children: ReactNode;
19
+ className?: string;
20
+ label: string;
21
+ size?: Size;
22
+ }
@@ -0,0 +1,7 @@
1
+ import { Size } from 'uilib/types';
2
+ type ShimmerProps = {
3
+ className?: string;
4
+ size?: Size;
5
+ };
6
+ declare const Shimmer: ({ className, size }: ShimmerProps) => JSX.Element;
7
+ export default Shimmer;
@@ -1,4 +1,5 @@
1
1
  export * from './AssistiveText/AssistiveText';
2
+ export * from './Autocomplete/Autocomplete';
2
3
  export * from './Button/Button';
3
4
  export * from './ButtonGroup/ButtonGroup';
4
5
  export * from './Calendar/Calendar';
@@ -18,6 +19,7 @@ export * from './InputFile/InputFile';
18
19
  export * from './Label/Label';
19
20
  export * from './Lazy/Lazy';
20
21
  export * from './LightBox/LightBox';
22
+ export * from './Menu/Menu';
21
23
  export * from './Notifications/Notifications';
22
24
  export * from './Paranja/Paranja';
23
25
  export * from './Popup/Popup';
@@ -27,6 +29,7 @@ export * from './Router/Router';
27
29
  export * from './RequiredStar/RequiredStar';
28
30
  export * from './Select/Select';
29
31
  export * from './Scroll/Scroll';
32
+ export * from './Shimmer/Shimmer';
30
33
  export * from './Spinner/Spinner';
31
34
  export * from './Table/Table';
32
35
  export * from './Tabs/Tabs';
@@ -0,0 +1,8 @@
1
+ import { RefObject } from 'react';
2
+ export type UseEventParams = {
3
+ elem?: Document | RefObject<HTMLElement> | RefObject<HTMLElement>[] | HTMLElement | HTMLElement[];
4
+ event: string | string[];
5
+ callback: (event: Event) => void;
6
+ isActive?: boolean;
7
+ };
8
+ export default function useEvent({ elem, event, callback, isActive, }: UseEventParams): void;
@@ -0,0 +1 @@
1
+ export declare const useIsMounted: () => import("react").MutableRefObject<boolean>;
@@ -0,0 +1,10 @@
1
+ type Props = {
2
+ isActive: boolean;
3
+ itemsCount: number;
4
+ onSelect?: (index: number) => void;
5
+ };
6
+ export declare const useListKeyboardControl: ({ isActive, itemsCount, onSelect, }: Props) => {
7
+ focusedIndex: number;
8
+ setFocusedIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
9
+ };
10
+ export {};
@@ -5,9 +5,9 @@ export type ComponentType = {
5
5
  className?: string;
6
6
  };
7
7
  export type FormFieldChangeHandler = (e: ChangeEvent | null, value: any) => void | boolean;
8
- export type FormControl<T> = {
8
+ export type FormControl<T, E = HTMLInputElement> = {
9
9
  value: T;
10
- onChange?: (e: ChangeEvent | null, value: T) => void | boolean;
10
+ onChange?: (e: ChangeEvent<E> | null, value: T) => void | boolean;
11
11
  required?: boolean;
12
12
  disabled?: boolean;
13
13
  error?: string | boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homecode/ui",
3
- "version": "4.18.70",
3
+ "version": "4.19.1",
4
4
  "description": "React UI components library",
5
5
  "scripts": {
6
6
  "test": "jest",