@homecode/ui 4.30.6 → 4.30.8
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/.cursor/debug-a8590a.log +26 -0
- package/.cursor/debug-cdef6d.log +694 -0
- package/.cursor/debug.log +207 -217
- package/dist/esm/src/components/Autocomplete/Autocomplete.js +133 -37
- package/dist/esm/src/components/Autocomplete/Autocomplete.styl.js +2 -2
- package/dist/esm/src/components/DatePickerInput/DatePickerInput.js +27 -3
- package/dist/esm/src/components/Shimmer/Shimmer.js +1 -1
- package/dist/esm/src/components/Virtualized/Virtualized.js +3 -2
- package/dist/esm/types/src/components/Autocomplete/Autocomplete.types.d.ts +8 -2
- package/dist/esm/types/src/components/Shimmer/Shimmer.d.ts +2 -1
- package/package.json +1 -1
|
@@ -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,
|
|
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,26 @@ 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 = {}, scrollProps = {}, } = 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);
|
|
89
|
+
const [selectedLabel, setSelectedLabel] = useState(null);
|
|
81
90
|
const isFocusedRef = useRef(false);
|
|
82
91
|
const searchValRef = useRef(value);
|
|
83
92
|
const [searchValue, _setSearchValue] = useState(value);
|
|
@@ -88,8 +97,16 @@ function Autocomplete(props) {
|
|
|
88
97
|
const currentRequest = useRef('');
|
|
89
98
|
// @ts-ignore
|
|
90
99
|
const inputRef = useRef(null);
|
|
91
|
-
const
|
|
92
|
-
|
|
100
|
+
const inputDisplayValue = selectable && !isFocused && selectedLabel != null
|
|
101
|
+
? selectedLabel
|
|
102
|
+
: searchValue;
|
|
103
|
+
const displayItems = currentFilter
|
|
104
|
+
? filteredItems
|
|
105
|
+
: itemsWithoutFilter.length
|
|
106
|
+
? itemsWithoutFilter
|
|
107
|
+
: (items ?? []);
|
|
108
|
+
const displayCount = displayItems.length;
|
|
109
|
+
const hasMore = totalCount > 0 && displayCount < totalCount;
|
|
93
110
|
const classes = cn(S.root, className, popupProps.className);
|
|
94
111
|
const handleFocus = (e) => {
|
|
95
112
|
isFocusedRef.current = true;
|
|
@@ -108,30 +125,41 @@ function Autocomplete(props) {
|
|
|
108
125
|
if (!val) {
|
|
109
126
|
setCurrentFilter('');
|
|
110
127
|
setFilteredItems([]);
|
|
128
|
+
setItemsWithoutFilter(items ?? []);
|
|
111
129
|
setCurrentOffset(0);
|
|
112
130
|
setTotalCount(0);
|
|
131
|
+
setScrollTop(0); // Reset scroll when filter is cleared
|
|
113
132
|
}
|
|
114
133
|
else {
|
|
115
134
|
setCurrentFilter(val);
|
|
116
135
|
setCurrentOffset(0);
|
|
136
|
+
setScrollTop(0); // Reset scroll when filter changes
|
|
117
137
|
fetchOptions(val, 0);
|
|
118
138
|
}
|
|
119
139
|
return true;
|
|
120
140
|
};
|
|
121
141
|
const handleSelect = (option) => {
|
|
142
|
+
if (selectable) {
|
|
143
|
+
setSelectedId(option.id);
|
|
144
|
+
setSelectedLabel(option.label);
|
|
145
|
+
onSelect?.(option);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
122
148
|
setSearchValue(option.label);
|
|
123
|
-
setCurrentFilter(
|
|
149
|
+
setCurrentFilter(option.label);
|
|
124
150
|
setFilteredItems([]);
|
|
125
151
|
setCurrentOffset(0);
|
|
126
152
|
setTotalCount(0);
|
|
127
|
-
|
|
153
|
+
setScrollTop(0);
|
|
154
|
+
fetchOptionsCore(option.label, 0);
|
|
155
|
+
onSelect?.(option);
|
|
128
156
|
// set input caret to the end
|
|
129
157
|
requestAnimationFrame(() => {
|
|
130
158
|
const input = inputRef.current;
|
|
131
159
|
if (!input)
|
|
132
160
|
return;
|
|
133
161
|
input.focus();
|
|
134
|
-
input.setSelectionRange(
|
|
162
|
+
input.setSelectionRange(option.label.length, option.label.length);
|
|
135
163
|
});
|
|
136
164
|
};
|
|
137
165
|
const { focusedIndex, setFocusedIndex } = useListKeyboardControl({
|
|
@@ -139,11 +167,7 @@ function Autocomplete(props) {
|
|
|
139
167
|
itemsCount: displayItems.length,
|
|
140
168
|
onSelect: index => handleSelect(displayItems[index]),
|
|
141
169
|
});
|
|
142
|
-
const
|
|
143
|
-
if (!filter) {
|
|
144
|
-
setFilteredItems([]);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
170
|
+
const fetchOptionsCore = useCallback(async (filter, offset) => {
|
|
147
171
|
const requestKey = `${filter}:${offset}`;
|
|
148
172
|
currentRequest.current = requestKey;
|
|
149
173
|
if (offset === 0) {
|
|
@@ -153,26 +177,51 @@ function Autocomplete(props) {
|
|
|
153
177
|
setIsLoadingMore(true);
|
|
154
178
|
}
|
|
155
179
|
try {
|
|
156
|
-
const
|
|
180
|
+
const result = await getOptions(filter, offset);
|
|
181
|
+
const newOptions = result.items;
|
|
182
|
+
const total = result.total;
|
|
157
183
|
if (!isMounted.current)
|
|
158
184
|
return;
|
|
159
185
|
if (currentRequest.current !== requestKey)
|
|
160
186
|
return;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
187
|
+
const newTotal = getTotalCount(total, newOptions.length, offset + newOptions.length, pageSize);
|
|
188
|
+
if (filter) {
|
|
189
|
+
if (offset === 0) {
|
|
190
|
+
setFilteredItems(newOptions);
|
|
191
|
+
setScrollTop(0); // Reset scroll when new filter results load
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
setFilteredItems(prev => [...prev, ...newOptions]);
|
|
195
|
+
}
|
|
196
|
+
setCurrentOffset(offset + newOptions.length);
|
|
197
|
+
setTotalCount(newTotal);
|
|
165
198
|
}
|
|
166
199
|
else {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
200
|
+
if (offset === 0) {
|
|
201
|
+
setItemsWithoutFilter(newOptions);
|
|
202
|
+
setScrollTop(0); // Reset scroll when loading initial items
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
setItemsWithoutFilter(prev => [...prev, ...newOptions]);
|
|
206
|
+
}
|
|
207
|
+
setCurrentOffset(offset + newOptions.length);
|
|
208
|
+
setTotalCount(newTotal);
|
|
209
|
+
}
|
|
210
|
+
// Clear scrollTop after reset to allow normal scrolling
|
|
211
|
+
if (offset === 0) {
|
|
212
|
+
requestAnimationFrame(() => {
|
|
213
|
+
setScrollTop(undefined);
|
|
214
|
+
});
|
|
171
215
|
}
|
|
172
216
|
}
|
|
173
217
|
catch (error) {
|
|
174
218
|
if (offset === 0) {
|
|
175
|
-
|
|
219
|
+
if (filter) {
|
|
220
|
+
setFilteredItems([]);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
setItemsWithoutFilter(items ?? []);
|
|
224
|
+
}
|
|
176
225
|
setCurrentOffset(0);
|
|
177
226
|
setTotalCount(0);
|
|
178
227
|
}
|
|
@@ -181,10 +230,21 @@ function Autocomplete(props) {
|
|
|
181
230
|
setIsLoading(false);
|
|
182
231
|
setIsLoadingMore(false);
|
|
183
232
|
}
|
|
184
|
-
},
|
|
233
|
+
}, [getOptions, isMounted, pageSize, items]);
|
|
234
|
+
const fetchOptions = useMemo(() => debounce(fetchOptionsCore, debounceDelay), [fetchOptionsCore, debounceDelay]);
|
|
185
235
|
const handleScrollEnd = useCallback(() => {
|
|
186
|
-
if (
|
|
187
|
-
|
|
236
|
+
if (!hasMore || isLoading || isLoadingMore)
|
|
237
|
+
return;
|
|
238
|
+
const filter = currentFilter;
|
|
239
|
+
const offset = currentOffset;
|
|
240
|
+
if (offset > 0) {
|
|
241
|
+
setIsLoadingMore(true);
|
|
242
|
+
requestAnimationFrame(() => {
|
|
243
|
+
fetchOptionsCore(filter, offset);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
fetchOptionsCore(filter, offset);
|
|
188
248
|
}
|
|
189
249
|
}, [
|
|
190
250
|
currentFilter,
|
|
@@ -192,7 +252,7 @@ function Autocomplete(props) {
|
|
|
192
252
|
isLoading,
|
|
193
253
|
isLoadingMore,
|
|
194
254
|
currentOffset,
|
|
195
|
-
|
|
255
|
+
fetchOptionsCore,
|
|
196
256
|
]);
|
|
197
257
|
useEffect(() => {
|
|
198
258
|
if (typeof value !== 'string')
|
|
@@ -201,15 +261,42 @@ function Autocomplete(props) {
|
|
|
201
261
|
if (!value) {
|
|
202
262
|
setCurrentFilter('');
|
|
203
263
|
setFilteredItems([]);
|
|
264
|
+
setItemsWithoutFilter(items ?? []);
|
|
204
265
|
setCurrentOffset(0);
|
|
205
266
|
setTotalCount(0);
|
|
267
|
+
setScrollTop(0); // Reset scroll when value is cleared
|
|
206
268
|
}
|
|
207
269
|
else if (isFocusedRef.current) {
|
|
208
270
|
setCurrentFilter(value);
|
|
209
271
|
setCurrentOffset(0);
|
|
272
|
+
setScrollTop(0); // Reset scroll when filter changes
|
|
210
273
|
fetchOptions(value, 0);
|
|
211
274
|
}
|
|
212
275
|
}, [value]);
|
|
276
|
+
useEffect(() => {
|
|
277
|
+
if (selectable && !value) {
|
|
278
|
+
setSelectedId(null);
|
|
279
|
+
setSelectedLabel(null);
|
|
280
|
+
}
|
|
281
|
+
}, [selectable, value]);
|
|
282
|
+
useEffect(() => {
|
|
283
|
+
if (!currentFilter && items?.length) {
|
|
284
|
+
setItemsWithoutFilter(items);
|
|
285
|
+
}
|
|
286
|
+
}, [currentFilter, items]);
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
const open = isOpen ?? isFocused;
|
|
289
|
+
if (open && !currentFilter && items?.length && totalCount === 0) {
|
|
290
|
+
fetchOptionsCore('', 0);
|
|
291
|
+
}
|
|
292
|
+
}, [
|
|
293
|
+
isOpen,
|
|
294
|
+
isFocused,
|
|
295
|
+
currentFilter,
|
|
296
|
+
items?.length,
|
|
297
|
+
totalCount,
|
|
298
|
+
fetchOptionsCore,
|
|
299
|
+
]);
|
|
213
300
|
const renderItem = useCallback((itemProps) => {
|
|
214
301
|
const option = displayItems[itemProps.key];
|
|
215
302
|
if (!option)
|
|
@@ -220,36 +307,40 @@ function Autocomplete(props) {
|
|
|
220
307
|
className: cn(S.option, itemProps.className),
|
|
221
308
|
style: itemProps.style,
|
|
222
309
|
focused: focusedIndex === itemProps.key,
|
|
310
|
+
isSelected: selectable && option.id === selectedId,
|
|
223
311
|
onClick: () => handleSelect(option),
|
|
224
312
|
onMouseEnter: () => setFocusedIndex(itemProps.key),
|
|
225
313
|
};
|
|
226
314
|
if (props.renderItem) {
|
|
227
315
|
return props.renderItem(itemPropsForRender);
|
|
228
316
|
}
|
|
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 }));
|
|
317
|
+
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
318
|
}, [
|
|
231
319
|
displayItems,
|
|
232
320
|
focusedIndex,
|
|
321
|
+
selectedId,
|
|
322
|
+
selectable,
|
|
233
323
|
handleSelect,
|
|
234
324
|
setFocusedIndex,
|
|
235
325
|
props.renderItem,
|
|
236
326
|
]);
|
|
327
|
+
const LoadingPlaceholder = loadingPlaceholder ?? (jsxs("div", { className: S.loadingPlaceholder, children: [isLoadingMore && jsx(Shimmer, { size: size, round: round }), "Loading..."] }));
|
|
237
328
|
const optionsList = useMemo(() => {
|
|
238
|
-
if (!displayItems.length)
|
|
239
|
-
return null;
|
|
240
|
-
|
|
241
|
-
|
|
329
|
+
if (!displayItems.length) {
|
|
330
|
+
return !selectable && isLoading ? LoadingPlaceholder : null;
|
|
331
|
+
}
|
|
332
|
+
const computedTotalCount = totalCount > 0 ? totalCount : displayItems.length;
|
|
333
|
+
return (jsx(ListScroll, { ...(selectable && { id: selectedId ?? 'none' }), className: cn(S.options, menuProps.className), scrollProps: {
|
|
242
334
|
y: true,
|
|
243
335
|
...scrollProps,
|
|
244
336
|
className: cn(S.scroll, scrollProps?.className),
|
|
245
|
-
}, itemHeight: itemHeight, itemsCount: displayItems.length, totalCount: computedTotalCount, overlapCount: 10, pageSize: pageSize, onScrollEnd: handleScrollEnd, renderItem: renderItem, contentAfter: hasMore &&
|
|
246
|
-
isLoadingMore && (jsx("div", { style: { padding: '8px 12px', textAlign: 'center' }, children: jsx(Shimmer, { size: size, round: round }) })) }));
|
|
337
|
+
}, itemHeight: itemHeight, itemsCount: displayItems.length, totalCount: computedTotalCount, overlapCount: 10, pageSize: pageSize, scrollTop: scrollTop, onScrollEnd: handleScrollEnd, renderItem: renderItem, contentAfter: hasMore && LoadingPlaceholder }));
|
|
247
338
|
}, [
|
|
248
339
|
displayItems,
|
|
249
340
|
focusedIndex,
|
|
250
|
-
currentFilter,
|
|
251
341
|
totalCount,
|
|
252
342
|
hasMore,
|
|
343
|
+
isLoading,
|
|
253
344
|
isLoadingMore,
|
|
254
345
|
itemHeight,
|
|
255
346
|
pageSize,
|
|
@@ -258,10 +349,15 @@ function Autocomplete(props) {
|
|
|
258
349
|
size,
|
|
259
350
|
round,
|
|
260
351
|
menuProps.className,
|
|
352
|
+
scrollProps,
|
|
353
|
+
scrollTop,
|
|
354
|
+
selectable,
|
|
355
|
+
selectedId,
|
|
356
|
+
LoadingPlaceholder,
|
|
261
357
|
]);
|
|
262
|
-
return (jsx(Popup, { className: classes, isOpen: isOpen, focusControl: true, round: round, size: size, blur: blur, direction: "bottom", ...popupProps, trigger:
|
|
263
|
-
|
|
264
|
-
|
|
358
|
+
return (jsx(Popup, { className: classes, isOpen: isOpen, focusControl: true, round: round, size: size, blur: blur, direction: "bottom", ...popupProps, trigger: jsx(Input, { ref: inputRef,
|
|
359
|
+
// @ts-ignore
|
|
360
|
+
size: size, round: round, ...inputProps, value: inputDisplayValue, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, className: cn(inputProps.className, selectable && !isFocused && S.inputSelectableDisplay) }), content: optionsList, contentProps: {
|
|
265
361
|
...popupProps?.contentProps,
|
|
266
362
|
className: cn(S.popupContent, popupProps?.contentProps?.className),
|
|
267
363
|
} }));
|
|
@@ -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_inputSelectableDisplay__rgFwu{overflow:hidden;text-overflow:ellipsis}.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","inputSelectableDisplay":"Autocomplete_inputSelectableDisplay__rgFwu","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
|
-
|
|
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
|
-
|
|
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
|
};
|
|
@@ -15,8 +15,11 @@ export type Props = FormControl<Value, HTMLInputElement> & {
|
|
|
15
15
|
size?: Size;
|
|
16
16
|
value: Value;
|
|
17
17
|
isOpen?: boolean;
|
|
18
|
-
getOptions: (filter: string, offset: number) => Promise<
|
|
19
|
-
|
|
18
|
+
getOptions: (filter: string, offset: number) => Promise<{
|
|
19
|
+
items: Option[];
|
|
20
|
+
total?: number;
|
|
21
|
+
}>;
|
|
22
|
+
onSelect?: (option: Option) => void;
|
|
20
23
|
items?: Option[];
|
|
21
24
|
itemHeight?: number;
|
|
22
25
|
pageSize?: number;
|
|
@@ -27,7 +30,9 @@ export type Props = FormControl<Value, HTMLInputElement> & {
|
|
|
27
30
|
menuProps?: Partial<MenuProps>;
|
|
28
31
|
round?: boolean;
|
|
29
32
|
blur?: boolean;
|
|
33
|
+
selectable?: boolean;
|
|
30
34
|
renderItem?: (props: RenderItemProps) => React.ReactElement;
|
|
35
|
+
loadingPlaceholder?: React.ReactNode;
|
|
31
36
|
};
|
|
32
37
|
export type RenderItemProps = {
|
|
33
38
|
option: Option;
|
|
@@ -35,6 +40,7 @@ export type RenderItemProps = {
|
|
|
35
40
|
className?: string;
|
|
36
41
|
style?: React.CSSProperties;
|
|
37
42
|
focused: boolean;
|
|
43
|
+
isSelected: boolean;
|
|
38
44
|
onClick: () => void;
|
|
39
45
|
onMouseEnter: () => void;
|
|
40
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;
|