@homecode/ui 4.30.5 → 4.30.7

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.
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import cn from 'classnames';
3
3
  import '../AssistiveText/AssistiveText.styl.js';
4
- import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
4
+ import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
5
5
  import S from './Autocomplete.styl.js';
6
6
  import { Shimmer } from '../Shimmer/Shimmer.js';
7
7
  import debounce from '../../tools/debounce.js';
@@ -67,17 +67,25 @@ const SIZE_TO_ITEM_HEIGHT = {
67
67
  m: 40,
68
68
  l: 50,
69
69
  };
70
+ const getTotalCount = (total, newItemsCount = 0, offset = 0, pageSize = 20) => {
71
+ if (total !== undefined)
72
+ return total;
73
+ return offset + (newItemsCount === pageSize ? 1 : 0);
74
+ };
70
75
  function Autocomplete(props) {
71
- const { className, inputWrapperClassName, value, onChange, size = 'm', getOptions, onSelect, items, itemHeight = SIZE_TO_ITEM_HEIGHT[size], pageSize = 20, debounceDelay = 300, round = false, blur = false, inputProps = {}, popupProps = {}, menuProps = {}, } = props;
76
+ const { className, inputWrapperClassName, value, onChange, size = 'm', getOptions, onSelect, items, itemHeight = SIZE_TO_ITEM_HEIGHT[size], pageSize = 20, debounceDelay = 300, round = false, blur = false, selectable = false, inputProps = {}, popupProps = {}, menuProps = {}, scrollProps = {}, loadingPlaceholder, } = props;
72
77
  const isMounted = useIsMounted();
73
78
  const [filteredItems, setFilteredItems] = useState([]);
79
+ const [itemsWithoutFilter, setItemsWithoutFilter] = useState(() => items ?? []);
74
80
  const [currentFilter, setCurrentFilter] = useState('');
75
81
  const [currentOffset, setCurrentOffset] = useState(0);
76
82
  const [totalCount, setTotalCount] = useState(0);
83
+ const [scrollTop, setScrollTop] = useState(undefined);
77
84
  const [isLoading, setIsLoading] = useState(false);
78
85
  const [isLoadingMore, setIsLoadingMore] = useState(false);
79
86
  const [isOpen, setIsOpen] = useState(props.isOpen);
80
87
  const [isFocused, setIsFocused] = useState(isOpen);
88
+ const [selectedId, setSelectedId] = useState(null);
81
89
  const isFocusedRef = useRef(false);
82
90
  const searchValRef = useRef(value);
83
91
  const [searchValue, _setSearchValue] = useState(value);
@@ -88,8 +96,13 @@ function Autocomplete(props) {
88
96
  const currentRequest = useRef('');
89
97
  // @ts-ignore
90
98
  const inputRef = useRef(null);
91
- const displayItems = currentFilter ? filteredItems : items || [];
92
- const hasMore = currentFilter ? filteredItems.length < totalCount : false;
99
+ const displayItems = currentFilter
100
+ ? filteredItems
101
+ : itemsWithoutFilter.length
102
+ ? itemsWithoutFilter
103
+ : items ?? [];
104
+ const displayCount = displayItems.length;
105
+ const hasMore = totalCount > 0 && displayCount < totalCount;
93
106
  const classes = cn(S.root, className, popupProps.className);
94
107
  const handleFocus = (e) => {
95
108
  isFocusedRef.current = true;
@@ -108,30 +121,40 @@ function Autocomplete(props) {
108
121
  if (!val) {
109
122
  setCurrentFilter('');
110
123
  setFilteredItems([]);
124
+ setItemsWithoutFilter(items ?? []);
111
125
  setCurrentOffset(0);
112
126
  setTotalCount(0);
127
+ setScrollTop(0); // Reset scroll when filter is cleared
113
128
  }
114
129
  else {
115
130
  setCurrentFilter(val);
116
131
  setCurrentOffset(0);
132
+ setScrollTop(0); // Reset scroll when filter changes
117
133
  fetchOptions(val, 0);
118
134
  }
119
135
  return true;
120
136
  };
121
137
  const handleSelect = (option) => {
138
+ if (selectable) {
139
+ setSelectedId(option.id);
140
+ onSelect?.(option);
141
+ return;
142
+ }
122
143
  setSearchValue(option.label);
123
- setCurrentFilter('');
144
+ setCurrentFilter(option.label);
124
145
  setFilteredItems([]);
125
146
  setCurrentOffset(0);
126
147
  setTotalCount(0);
127
- onSelect(option);
148
+ setScrollTop(0);
149
+ fetchOptionsCore(option.label, 0);
150
+ onSelect?.(option);
128
151
  // set input caret to the end
129
152
  requestAnimationFrame(() => {
130
153
  const input = inputRef.current;
131
154
  if (!input)
132
155
  return;
133
156
  input.focus();
134
- input.setSelectionRange(value.length, value.length);
157
+ input.setSelectionRange(option.label.length, option.label.length);
135
158
  });
136
159
  };
137
160
  const { focusedIndex, setFocusedIndex } = useListKeyboardControl({
@@ -139,11 +162,7 @@ function Autocomplete(props) {
139
162
  itemsCount: displayItems.length,
140
163
  onSelect: index => handleSelect(displayItems[index]),
141
164
  });
142
- const fetchOptions = debounce(async (filter, offset) => {
143
- if (!filter) {
144
- setFilteredItems([]);
145
- return;
146
- }
165
+ const fetchOptionsCore = useCallback(async (filter, offset) => {
147
166
  const requestKey = `${filter}:${offset}`;
148
167
  currentRequest.current = requestKey;
149
168
  if (offset === 0) {
@@ -153,26 +172,51 @@ function Autocomplete(props) {
153
172
  setIsLoadingMore(true);
154
173
  }
155
174
  try {
156
- const newOptions = await getOptions(filter, offset);
175
+ const result = await getOptions(filter, offset);
176
+ const newOptions = result.items;
177
+ const total = result.total;
157
178
  if (!isMounted.current)
158
179
  return;
159
180
  if (currentRequest.current !== requestKey)
160
181
  return;
161
- if (offset === 0) {
162
- setFilteredItems(newOptions);
163
- setCurrentOffset(newOptions.length);
164
- setTotalCount(newOptions.length + (newOptions.length === pageSize ? 1 : 0));
182
+ const newTotal = getTotalCount(total, newOptions.length, offset + newOptions.length, pageSize);
183
+ if (filter) {
184
+ if (offset === 0) {
185
+ setFilteredItems(newOptions);
186
+ setScrollTop(0); // Reset scroll when new filter results load
187
+ }
188
+ else {
189
+ setFilteredItems(prev => [...prev, ...newOptions]);
190
+ }
191
+ setCurrentOffset(offset + newOptions.length);
192
+ setTotalCount(newTotal);
165
193
  }
166
194
  else {
167
- setFilteredItems(prev => [...prev, ...newOptions]);
168
- const newOffset = offset + newOptions.length;
169
- setCurrentOffset(newOffset);
170
- setTotalCount(newOffset + (newOptions.length === pageSize ? 1 : 0));
195
+ if (offset === 0) {
196
+ setItemsWithoutFilter(newOptions);
197
+ setScrollTop(0); // Reset scroll when loading initial items
198
+ }
199
+ else {
200
+ setItemsWithoutFilter(prev => [...prev, ...newOptions]);
201
+ }
202
+ setCurrentOffset(offset + newOptions.length);
203
+ setTotalCount(newTotal);
204
+ }
205
+ // Clear scrollTop after reset to allow normal scrolling
206
+ if (offset === 0) {
207
+ requestAnimationFrame(() => {
208
+ setScrollTop(undefined);
209
+ });
171
210
  }
172
211
  }
173
212
  catch (error) {
174
213
  if (offset === 0) {
175
- setFilteredItems([]);
214
+ if (filter) {
215
+ setFilteredItems([]);
216
+ }
217
+ else {
218
+ setItemsWithoutFilter(items ?? []);
219
+ }
176
220
  setCurrentOffset(0);
177
221
  setTotalCount(0);
178
222
  }
@@ -181,10 +225,21 @@ function Autocomplete(props) {
181
225
  setIsLoading(false);
182
226
  setIsLoadingMore(false);
183
227
  }
184
- }, debounceDelay);
228
+ }, [getOptions, isMounted, pageSize, items]);
229
+ const fetchOptions = useMemo(() => debounce(fetchOptionsCore, debounceDelay), [fetchOptionsCore, debounceDelay]);
185
230
  const handleScrollEnd = useCallback(() => {
186
- if (currentFilter && hasMore && !isLoading && !isLoadingMore) {
187
- fetchOptions(currentFilter, currentOffset);
231
+ if (!hasMore || isLoading || isLoadingMore)
232
+ return;
233
+ const filter = currentFilter;
234
+ const offset = currentOffset;
235
+ if (offset > 0) {
236
+ setIsLoadingMore(true);
237
+ requestAnimationFrame(() => {
238
+ fetchOptionsCore(filter, offset);
239
+ });
240
+ }
241
+ else {
242
+ fetchOptionsCore(filter, offset);
188
243
  }
189
244
  }, [
190
245
  currentFilter,
@@ -192,7 +247,7 @@ function Autocomplete(props) {
192
247
  isLoading,
193
248
  isLoadingMore,
194
249
  currentOffset,
195
- fetchOptions,
250
+ fetchOptionsCore,
196
251
  ]);
197
252
  useEffect(() => {
198
253
  if (typeof value !== 'string')
@@ -201,15 +256,36 @@ function Autocomplete(props) {
201
256
  if (!value) {
202
257
  setCurrentFilter('');
203
258
  setFilteredItems([]);
259
+ setItemsWithoutFilter(items ?? []);
204
260
  setCurrentOffset(0);
205
261
  setTotalCount(0);
262
+ setScrollTop(0); // Reset scroll when value is cleared
206
263
  }
207
264
  else if (isFocusedRef.current) {
208
265
  setCurrentFilter(value);
209
266
  setCurrentOffset(0);
267
+ setScrollTop(0); // Reset scroll when filter changes
210
268
  fetchOptions(value, 0);
211
269
  }
212
270
  }, [value]);
271
+ useEffect(() => {
272
+ if (!currentFilter && items?.length) {
273
+ setItemsWithoutFilter(items);
274
+ }
275
+ }, [currentFilter, items]);
276
+ useEffect(() => {
277
+ const open = isOpen ?? isFocused;
278
+ if (open && !currentFilter && items?.length && totalCount === 0) {
279
+ fetchOptionsCore('', 0);
280
+ }
281
+ }, [
282
+ isOpen,
283
+ isFocused,
284
+ currentFilter,
285
+ items?.length,
286
+ totalCount,
287
+ fetchOptionsCore,
288
+ ]);
213
289
  const renderItem = useCallback((itemProps) => {
214
290
  const option = displayItems[itemProps.key];
215
291
  if (!option)
@@ -220,35 +296,40 @@ function Autocomplete(props) {
220
296
  className: cn(S.option, itemProps.className),
221
297
  style: itemProps.style,
222
298
  focused: focusedIndex === itemProps.key,
299
+ isSelected: selectable && option.id === selectedId,
223
300
  onClick: () => handleSelect(option),
224
301
  onMouseEnter: () => setFocusedIndex(itemProps.key),
225
302
  };
226
303
  if (props.renderItem) {
227
304
  return props.renderItem(itemPropsForRender);
228
305
  }
229
- return (jsx(Menu.Item, { ...itemProps, focused: itemPropsForRender.focused, className: itemPropsForRender.className, onClick: itemPropsForRender.onClick, onMouseEnter: itemPropsForRender.onMouseEnter, style: itemPropsForRender.style, children: option.render ? option.render(option) : option.label }));
306
+ return (jsx(Menu.Item, { ...itemProps, focused: itemPropsForRender.focused, selected: itemPropsForRender.isSelected, className: itemPropsForRender.className, onClick: itemPropsForRender.onClick, onMouseEnter: itemPropsForRender.onMouseEnter, style: itemPropsForRender.style, children: option.render ? option.render(option) : option.label }));
230
307
  }, [
231
308
  displayItems,
232
309
  focusedIndex,
310
+ selectedId,
311
+ selectable,
233
312
  handleSelect,
234
313
  setFocusedIndex,
235
314
  props.renderItem,
236
315
  ]);
316
+ const LoadingPlaceholder = loadingPlaceholder ?? (jsxs("div", { className: S.loadingPlaceholder, children: [isLoadingMore && jsx(Shimmer, { size: size, round: round }), "Loading..."] }));
237
317
  const optionsList = useMemo(() => {
238
- if (!displayItems.length)
239
- return null;
240
- const computedTotalCount = currentFilter ? totalCount : displayItems.length;
241
- return (jsx(ListScroll, { className: cn(S.options, menuProps.className), scrollProps: {
318
+ if (!displayItems.length) {
319
+ return !selectable && isLoading ? LoadingPlaceholder : null;
320
+ }
321
+ const computedTotalCount = totalCount > 0 ? totalCount : displayItems.length;
322
+ return (jsx(ListScroll, { ...(selectable && { id: selectedId ?? 'none' }), className: cn(S.options, menuProps.className), scrollProps: {
242
323
  y: true,
243
- className: S.scroll,
244
- }, itemHeight: itemHeight, itemsCount: displayItems.length, totalCount: computedTotalCount, overlapCount: 10, pageSize: pageSize, onScrollEnd: handleScrollEnd, renderItem: renderItem, contentAfter: hasMore &&
245
- isLoadingMore && (jsx("div", { style: { padding: '8px 12px', textAlign: 'center' }, children: jsx(Shimmer, { size: size, round: round }) })) }));
324
+ ...scrollProps,
325
+ className: cn(S.scroll, scrollProps?.className),
326
+ }, itemHeight: itemHeight, itemsCount: displayItems.length, totalCount: computedTotalCount, overlapCount: 10, pageSize: pageSize, scrollTop: scrollTop, onScrollEnd: handleScrollEnd, renderItem: renderItem, contentAfter: hasMore && LoadingPlaceholder }));
246
327
  }, [
247
328
  displayItems,
248
329
  focusedIndex,
249
- currentFilter,
250
330
  totalCount,
251
331
  hasMore,
332
+ isLoading,
252
333
  isLoadingMore,
253
334
  itemHeight,
254
335
  pageSize,
@@ -257,10 +338,15 @@ function Autocomplete(props) {
257
338
  size,
258
339
  round,
259
340
  menuProps.className,
341
+ scrollProps,
342
+ scrollTop,
343
+ selectable,
344
+ selectedId,
345
+ LoadingPlaceholder,
260
346
  ]);
261
- return (jsx(Popup, { className: classes, isOpen: isOpen, focusControl: true, round: round, size: size, blur: blur, direction: "bottom", ...popupProps, trigger: jsxs("div", { className: inputWrapperClassName, children: [jsx(Input, { ref: inputRef,
262
- // @ts-ignore
263
- size: size, round: round, ...inputProps, value: searchValue, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, className: inputProps.className }), isLoading && (jsx(Shimmer, { className: S.shimmer, size: size, round: round }))] }), content: optionsList, contentProps: {
347
+ return (jsx(Popup, { className: classes, isOpen: isOpen, focusControl: true, round: round, size: size, blur: blur, direction: "bottom", ...popupProps, trigger: jsx(Input, { ref: inputRef,
348
+ // @ts-ignore
349
+ size: size, round: round, ...inputProps, value: searchValue, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, className: inputProps.className }), content: optionsList, contentProps: {
264
350
  ...popupProps?.contentProps,
265
351
  className: cn(S.popupContent, popupProps?.contentProps?.className),
266
352
  } }));
@@ -1,7 +1,7 @@
1
1
  import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
2
2
 
3
- var css_248z = ".Autocomplete_root__86RQs{position:relative}.Autocomplete_popupContent__Aet6P{margin-top:8px;width:100%}.Autocomplete_scroll__bFG6f{height:200px}.Autocomplete_options__NtttU{max-height:200px;overflow-y:auto}.Autocomplete_option__uBuih{cursor:pointer;padding:8px 12px;position:absolute}.Autocomplete_option__uBuih>span{align-items:center;display:flex}.Autocomplete_shimmer__s6rri{height:100%;left:0;position:absolute;top:0;width:100%}";
4
- var S = {"root":"Autocomplete_root__86RQs","popupContent":"Autocomplete_popupContent__Aet6P","scroll":"Autocomplete_scroll__bFG6f","options":"Autocomplete_options__NtttU","option":"Autocomplete_option__uBuih","shimmer":"Autocomplete_shimmer__s6rri"};
3
+ var css_248z = ".Autocomplete_root__86RQs{position:relative}.Autocomplete_popupContent__Aet6P{margin-top:8px;width:100%}.Autocomplete_scroll__bFG6f{height:200px}.Autocomplete_options__NtttU{max-height:200px;overflow-y:auto}.Autocomplete_option__uBuih{cursor:pointer;padding:8px 12px;position:absolute}.Autocomplete_option__uBuih>span{align-items:center;display:flex}.Autocomplete_loadingPlaceholder__Dn0dT{padding:8px 12px;text-align:center}.Autocomplete_shimmer__s6rri{height:100%;left:0;position:absolute;top:0;width:100%}";
4
+ var S = {"root":"Autocomplete_root__86RQs","popupContent":"Autocomplete_popupContent__Aet6P","scroll":"Autocomplete_scroll__bFG6f","options":"Autocomplete_options__NtttU","option":"Autocomplete_option__uBuih","loadingPlaceholder":"Autocomplete_loadingPlaceholder__Dn0dT","shimmer":"Autocomplete_shimmer__s6rri"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -1,4 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useCallback } from 'react';
2
3
  import cn from 'classnames';
3
4
  import { strToDate } from '../../tools/date.js';
4
5
  import { DateTime } from '../DateTime/DateTime.js';
@@ -8,13 +9,36 @@ import { Popup } from '../Popup/Popup.js';
8
9
  import S from './DatePickerInput.styl.js';
9
10
 
10
11
  function DatePickerInput(props) {
11
- const { value, variant = 'default', size = 'm', popupProps, buttonProps, displayFormat = 'MMM Do YYYY', } = props;
12
+ const { value, onChange, variant = 'default', size = 'm', popupProps, buttonProps, displayFormat = 'MMM Do YYYY', } = props;
12
13
  const isRange = Array.isArray(value);
13
- return (jsx(Popup, { size: size, focusControl: true, direction: "bottom-right", ...popupProps, trigger:
14
+ const isControlled = popupProps?.isOpen !== undefined;
15
+ const [isOpen, setIsOpen] = useState(false);
16
+ const handleChange = useCallback((newValue) => {
17
+ onChange(newValue);
18
+ if (!isRange) {
19
+ if (!isControlled) {
20
+ setIsOpen(false);
21
+ }
22
+ popupProps?.onClose?.();
23
+ }
24
+ }, [onChange, isRange, isControlled, popupProps]);
25
+ const handleClose = useCallback(() => {
26
+ if (!isControlled) {
27
+ setIsOpen(false);
28
+ }
29
+ popupProps?.onClose?.();
30
+ }, [popupProps, isControlled]);
31
+ const handleOpen = useCallback(() => {
32
+ if (!isControlled) {
33
+ setIsOpen(true);
34
+ }
35
+ popupProps?.onOpen?.();
36
+ }, [popupProps, isControlled]);
37
+ return (jsx(Popup, { size: size, focusControl: true, direction: "bottom-right", isOpen: isControlled ? popupProps.isOpen : isOpen, onOpen: isControlled ? popupProps.onOpen : handleOpen, onClose: isControlled ? popupProps.onClose : handleClose, ...popupProps, trigger:
14
38
  // @ts-ignore
15
39
  jsx(Button, { variant: variant, size: size, ...buttonProps, children: isRange ? (jsxs(Fragment, { children: [jsx(DateTime, { value: strToDate(value[0]), format: displayFormat }), ' - ', jsx(DateTime, { value: strToDate(value[1]), format: displayFormat })] })) : (jsx(DateTime, { value: strToDate(value), format: displayFormat })) }), contentProps: {
16
40
  className: cn(S.popupContent, props.doubleCalendar && S.doubleCalendar, S[`size-${size}`], popupProps?.contentProps?.className),
17
- }, content: jsx(DatePicker, { ...props, className: S.content, calendarProps: { className: S.calendar } }) }));
41
+ }, content: jsx(DatePicker, { ...props, onChange: handleChange, className: S.content, calendarProps: { className: S.calendar } }) }));
18
42
  }
19
43
 
20
44
  export { DatePickerInput };
@@ -2,6 +2,6 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import S from './Shimmer.styl.js';
3
3
  import cn from 'classnames';
4
4
 
5
- const Shimmer = ({ className, size = 'm', round = false, }) => (jsx("div", { className: cn(S.root, className, S[`size-${size}`], round && S.round), children: jsx("div", { className: S.inner }) }));
5
+ const Shimmer = ({ className, size = 'm', round = false, children, }) => (jsx("div", { className: cn(S.root, className, S[`size-${size}`], round && S.round), children: jsx("div", { className: S.inner, children: children }) }));
6
6
 
7
7
  export { Shimmer };
@@ -148,8 +148,9 @@ class Virtualized extends Component {
148
148
  const { itemsCount, totalCount, pageSize, onScrollEnd } = this.props;
149
149
  if (itemsCount === totalCount)
150
150
  return;
151
- if (itemsCount < this.lastScrollEndIndex)
152
- return;
151
+ if (itemsCount < this.lastScrollEndIndex) {
152
+ this.lastScrollEndIndex = 0; // Reset when list shrinks (e.g. filter cleared)
153
+ }
153
154
  this.lastScrollEndIndex = Math.min(itemsCount + pageSize, totalCount);
154
155
  onScrollEnd?.();
155
156
  };
@@ -2,6 +2,7 @@ import { FormControl, Size } from 'uilib/types';
2
2
  import { Props as InputProps } from 'uilib/components/Input/Input.types';
3
3
  import { Props as PopupProps } from 'uilib/components/Popup/Popup.types';
4
4
  import { MenuProps } from 'uilib/components/Menu/Menu.types';
5
+ import { ScrollProps } from 'uilib/components/Scroll/Scroll';
5
6
  export type Option = {
6
7
  id: string;
7
8
  label: string;
@@ -14,18 +15,24 @@ export type Props = FormControl<Value, HTMLInputElement> & {
14
15
  size?: Size;
15
16
  value: Value;
16
17
  isOpen?: boolean;
17
- getOptions: (filter: string, offset: number) => Promise<Option[]>;
18
- onSelect: (option: Option) => void;
18
+ getOptions: (filter: string, offset: number) => Promise<{
19
+ items: Option[];
20
+ total?: number;
21
+ }>;
22
+ onSelect?: (option: Option) => void;
19
23
  items?: Option[];
20
24
  itemHeight?: number;
21
25
  pageSize?: number;
22
26
  debounceDelay?: number;
23
27
  inputProps?: Partial<InputProps>;
24
28
  popupProps?: Partial<PopupProps>;
29
+ scrollProps?: Partial<ScrollProps>;
25
30
  menuProps?: Partial<MenuProps>;
26
31
  round?: boolean;
27
32
  blur?: boolean;
33
+ selectable?: boolean;
28
34
  renderItem?: (props: RenderItemProps) => React.ReactElement;
35
+ loadingPlaceholder?: React.ReactNode;
29
36
  };
30
37
  export type RenderItemProps = {
31
38
  option: Option;
@@ -33,6 +40,7 @@ export type RenderItemProps = {
33
40
  className?: string;
34
41
  style?: React.CSSProperties;
35
42
  focused: boolean;
43
+ isSelected: boolean;
36
44
  onClick: () => void;
37
45
  onMouseEnter: () => void;
38
46
  };
@@ -3,5 +3,6 @@ export type ShimmerProps = {
3
3
  className?: string;
4
4
  size?: Size;
5
5
  round?: boolean;
6
+ children?: React.ReactNode;
6
7
  };
7
- export declare const Shimmer: ({ className, size, round, }: ShimmerProps) => JSX.Element;
8
+ export declare const Shimmer: ({ className, size, round, children, }: ShimmerProps) => JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homecode/ui",
3
- "version": "4.30.5",
3
+ "version": "4.30.7",
4
4
  "description": "React UI components library",
5
5
  "scripts": {
6
6
  "tests": "jest",