mautourco-components 0.2.103 → 0.2.104
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.
|
@@ -29,6 +29,7 @@ var LocationDropdown = function (_a) {
|
|
|
29
29
|
var _q = useState(false), isOpen = _q[0], setIsOpen = _q[1];
|
|
30
30
|
var _r = useState(''), searchQuery = _r[0], setSearchQuery = _r[1];
|
|
31
31
|
var dropdownRef = useRef(null);
|
|
32
|
+
var dropdownPanelRef = useRef(null);
|
|
32
33
|
var inputRef = useRef(null);
|
|
33
34
|
var searchInputRef = useRef(null);
|
|
34
35
|
// Close dropdown when clicking outside
|
|
@@ -45,7 +46,11 @@ var LocationDropdown = function (_a) {
|
|
|
45
46
|
}, []);
|
|
46
47
|
// Scroll to input when dropdown opens (if scrollOnOpen is true)
|
|
47
48
|
useEffect(function () {
|
|
48
|
-
|
|
49
|
+
setTimeout(function () {
|
|
50
|
+
if (dropdownPanelRef.current) {
|
|
51
|
+
scrollIntoViewOnOpen(dropdownPanelRef, isOpen, scrollOnOpen);
|
|
52
|
+
}
|
|
53
|
+
}, 10);
|
|
49
54
|
}, [isOpen, scrollOnOpen]);
|
|
50
55
|
// Reset search when dropdown closes
|
|
51
56
|
useEffect(function () {
|
|
@@ -88,9 +93,7 @@ var LocationDropdown = function (_a) {
|
|
|
88
93
|
if (!searchQuery.trim())
|
|
89
94
|
return opts;
|
|
90
95
|
var query = searchQuery.toLowerCase();
|
|
91
|
-
return opts.filter(function (option) {
|
|
92
|
-
return option.label.toLowerCase().includes(query);
|
|
93
|
-
});
|
|
96
|
+
return opts.filter(function (option) { return option.label.toLowerCase().includes(query); });
|
|
94
97
|
};
|
|
95
98
|
var getSelectedOption = function () {
|
|
96
99
|
if (selectedValue) {
|
|
@@ -156,13 +159,15 @@ var LocationDropdown = function (_a) {
|
|
|
156
159
|
var displayText = selectedOption ? selectedOption.label : placeholder;
|
|
157
160
|
// Prepare all options (flat or grouped) and filter them
|
|
158
161
|
var allOptionsRaw = groups.length > 0 ? groups : [{ id: 'default', label: '', options: options }];
|
|
159
|
-
var allOptions = allOptionsRaw
|
|
162
|
+
var allOptions = allOptionsRaw
|
|
163
|
+
.map(function (group) { return (__assign(__assign({}, group), { options: filterOptions(group.options) })); })
|
|
164
|
+
.filter(function (group) { return group.options.length > 0; });
|
|
160
165
|
// Skeleton loader component
|
|
161
166
|
var SkeletonOption = function () { return (_jsxs("div", { className: "location-dropdown__option location-dropdown__option--skeleton", children: [_jsx("div", { className: "location-dropdown__skeleton-icon" }), _jsx("div", { className: "location-dropdown__skeleton-text" })] })); };
|
|
162
167
|
// Render skeleton loading state
|
|
163
168
|
var renderSkeletonLoading = function () { return (_jsx("div", { className: "location-dropdown__panel", children: _jsx("div", { className: "location-dropdown__content", style: { maxHeight: "".concat(maxHeight, "px") }, children: _jsx("div", { className: "location-dropdown__options-wrapper", children: _jsx("div", { className: "location-dropdown__group", children: _jsx("div", { className: "location-dropdown__group-options", children: __spreadArray([], Array(5), true).map(function (_, index) { return (_jsx(SkeletonOption, {}, "skeleton-".concat(index))); }) }) }) }) }) })); };
|
|
164
169
|
return (_jsxs("div", { ref: dropdownRef, className: "location-dropdown location-dropdown--".concat(type, " ").concat(disabled ? 'location-dropdown--disabled' : '', " ").concat(className), children: [label && (_jsx("div", { className: "location-dropdown__label", children: _jsx(Text, { size: "sm", variant: "medium", children: label }) })), _jsxs("div", { ref: inputRef, className: "location-dropdown__input location-dropdown__input--".concat(getDropdownState()), onClick: handleToggleDropdown, children: [_jsxs("div", { className: "location-dropdown__input-content", children: [_jsx(Icon, { name: getInputIcon(), size: "sm", className: "location-dropdown__input-icon ".concat(!selectedOption ? 'location-dropdown__input-icon--placeholder' : '') }), isOpen ? (_jsx("input", { ref: searchInputRef, type: "text", className: "location-dropdown__input-text ".concat(!selectedOption && !searchQuery ? 'location-dropdown__input-text--placeholder' : ''), placeholder: displayText, value: searchQuery, onChange: handleSearchChange, onClick: function (e) { return e.stopPropagation(); }, disabled: disabled, autoFocus: true })) : (_jsx("span", { className: "location-dropdown__input-text ".concat(!selectedOption ? 'location-dropdown__input-text--placeholder' : ''), children: displayText }))] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "location-dropdown__input-chevron" })] }), isOpen &&
|
|
165
|
-
(loading ? (renderSkeletonLoading()) : (_jsx("div", { className: "location-dropdown__panel", children: _jsx("div", { className: "location-dropdown__content", style: { maxHeight: "".concat(maxHeight, "px") }, children: _jsx("div", { className: "location-dropdown__options-wrapper", children: allOptions.length === 0 ? (_jsx("div", { className: "location-dropdown__no-results", children: _jsx(Text, { size: "sm", variant: "medium", children: "No locations found" }) })) : (allOptions.map(function (group, groupIndex) { return (_jsxs("div", { className: "location-dropdown__group", children: [showGroupTitles && group.label && groups.length > 0 && (_jsxs(_Fragment, { children: [groupIndex > 0 && _jsx("div", { className: "location-dropdown__divider" }), _jsx("div", { className: "location-dropdown__group-header", children: _jsx(Text, { size: "xs", variant: "bold", children: group.label }) })] })), _jsx("div", { className: "location-dropdown__group-options", children: group.options.map(function (option) {
|
|
170
|
+
(loading ? (renderSkeletonLoading()) : (_jsx("div", { className: "location-dropdown__panel", ref: dropdownPanelRef, children: _jsx("div", { className: "location-dropdown__content", style: { maxHeight: "".concat(maxHeight, "px") }, children: _jsx("div", { className: "location-dropdown__options-wrapper", children: allOptions.length === 0 ? (_jsx("div", { className: "location-dropdown__no-results", children: _jsx(Text, { size: "sm", variant: "medium", children: "No locations found" }) })) : (allOptions.map(function (group, groupIndex) { return (_jsxs("div", { className: "location-dropdown__group", children: [showGroupTitles && group.label && groups.length > 0 && (_jsxs(_Fragment, { children: [groupIndex > 0 && (_jsx("div", { className: "location-dropdown__divider" })), _jsx("div", { className: "location-dropdown__group-header", children: _jsx(Text, { size: "xs", variant: "bold", children: group.label }) })] })), _jsx("div", { className: "location-dropdown__group-options", children: group.options.map(function (option) {
|
|
166
171
|
var isSelected = effectiveSelectedValue === option.id;
|
|
167
172
|
var isDisabled = option.disabled || disabled;
|
|
168
173
|
return (_jsxs("div", { className: "location-dropdown__option ".concat(isSelected ? 'location-dropdown__option--selected' : '', " ").concat(isDisabled ? 'location-dropdown__option--disabled' : ''), onClick: function () { return !isDisabled && handleOptionSelect(option); }, children: [_jsx(Icon, { name: getOptionIcon(option, isSelected), size: "sm", className: "location-dropdown__option-icon" }), _jsx("span", { className: "location-dropdown__option-text", children: option.label })] }, option.id));
|
package/dist/lib/utils.js
CHANGED
|
@@ -21,17 +21,22 @@ export function cn() {
|
|
|
21
21
|
export function scrollIntoViewOnOpen(elementRef, isOpen, scrollOnOpen, offset) {
|
|
22
22
|
if (offset === void 0) { offset = 20; }
|
|
23
23
|
if (isOpen && scrollOnOpen && elementRef.current) {
|
|
24
|
+
var bodyBottom_1 = document.body.clientHeight;
|
|
24
25
|
// Use setTimeout to ensure the dropdown is rendered before scrolling
|
|
25
26
|
setTimeout(function () {
|
|
26
27
|
if (elementRef.current) {
|
|
27
28
|
var elementTop = elementRef.current.getBoundingClientRect().top + window.pageYOffset;
|
|
29
|
+
var elementBottom = elementRef.current.getBoundingClientRect().bottom;
|
|
30
|
+
var realBottom = elementBottom + window.scrollY;
|
|
28
31
|
// Scroll to show the element with some padding from the top
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
if (realBottom > bodyBottom_1) {
|
|
33
|
+
window.scrollTo({
|
|
34
|
+
top: elementTop - offset,
|
|
35
|
+
behavior: 'smooth',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
|
-
},
|
|
39
|
+
}, 350);
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
/**
|
package/package.json
CHANGED
|
@@ -64,6 +64,7 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
64
64
|
const [isOpen, setIsOpen] = useState(false);
|
|
65
65
|
const [searchQuery, setSearchQuery] = useState('');
|
|
66
66
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
67
|
+
const dropdownPanelRef = useRef<HTMLDivElement>(null);
|
|
67
68
|
const inputRef = useRef<HTMLDivElement>(null);
|
|
68
69
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
69
70
|
|
|
@@ -83,7 +84,11 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
83
84
|
|
|
84
85
|
// Scroll to input when dropdown opens (if scrollOnOpen is true)
|
|
85
86
|
useEffect(() => {
|
|
86
|
-
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
if (dropdownPanelRef.current) {
|
|
89
|
+
scrollIntoViewOnOpen(dropdownPanelRef, isOpen, scrollOnOpen);
|
|
90
|
+
}
|
|
91
|
+
}, 10);
|
|
87
92
|
}, [isOpen, scrollOnOpen]);
|
|
88
93
|
|
|
89
94
|
// Reset search when dropdown closes
|
|
@@ -129,11 +134,9 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
129
134
|
// Filter locations based on search query
|
|
130
135
|
const filterOptions = (opts: LocationOption[]): LocationOption[] => {
|
|
131
136
|
if (!searchQuery.trim()) return opts;
|
|
132
|
-
|
|
137
|
+
|
|
133
138
|
const query = searchQuery.toLowerCase();
|
|
134
|
-
return opts.filter((option) =>
|
|
135
|
-
option.label.toLowerCase().includes(query)
|
|
136
|
-
);
|
|
139
|
+
return opts.filter((option) => option.label.toLowerCase().includes(query));
|
|
137
140
|
};
|
|
138
141
|
|
|
139
142
|
const getSelectedOption = (): LocationOption | null => {
|
|
@@ -201,11 +204,14 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
201
204
|
const displayText = selectedOption ? selectedOption.label : placeholder;
|
|
202
205
|
|
|
203
206
|
// Prepare all options (flat or grouped) and filter them
|
|
204
|
-
const allOptionsRaw =
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
const allOptionsRaw =
|
|
208
|
+
groups.length > 0 ? groups : [{ id: 'default', label: '', options }];
|
|
209
|
+
const allOptions = allOptionsRaw
|
|
210
|
+
.map((group) => ({
|
|
211
|
+
...group,
|
|
212
|
+
options: filterOptions(group.options),
|
|
213
|
+
}))
|
|
214
|
+
.filter((group) => group.options.length > 0);
|
|
209
215
|
|
|
210
216
|
// Skeleton loader component
|
|
211
217
|
const SkeletonOption = () => (
|
|
@@ -284,7 +290,7 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
284
290
|
(loading ? (
|
|
285
291
|
renderSkeletonLoading()
|
|
286
292
|
) : (
|
|
287
|
-
<div className="location-dropdown__panel">
|
|
293
|
+
<div className="location-dropdown__panel" ref={dropdownPanelRef}>
|
|
288
294
|
<div
|
|
289
295
|
className="location-dropdown__content"
|
|
290
296
|
style={{ maxHeight: `${maxHeight}px` }}>
|
|
@@ -297,41 +303,43 @@ const LocationDropdown: React.FC<LocationDropdownProps> = ({
|
|
|
297
303
|
</div>
|
|
298
304
|
) : (
|
|
299
305
|
allOptions.map((group, groupIndex) => (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
)}
|
|
311
|
-
|
|
312
|
-
<div className="location-dropdown__group-options">
|
|
313
|
-
{group.options.map((option) => {
|
|
314
|
-
const isSelected = effectiveSelectedValue === option.id;
|
|
315
|
-
const isDisabled = option.disabled || disabled;
|
|
316
|
-
|
|
317
|
-
return (
|
|
318
|
-
<div
|
|
319
|
-
key={option.id}
|
|
320
|
-
className={`location-dropdown__option ${isSelected ? 'location-dropdown__option--selected' : ''} ${isDisabled ? 'location-dropdown__option--disabled' : ''}`}
|
|
321
|
-
onClick={() => !isDisabled && handleOptionSelect(option)}>
|
|
322
|
-
<Icon
|
|
323
|
-
name={getOptionIcon(option, isSelected)}
|
|
324
|
-
size="sm"
|
|
325
|
-
className="location-dropdown__option-icon"
|
|
326
|
-
/>
|
|
327
|
-
<span className="location-dropdown__option-text">
|
|
328
|
-
{option.label}
|
|
329
|
-
</span>
|
|
306
|
+
<div key={group.id} className="location-dropdown__group">
|
|
307
|
+
{showGroupTitles && group.label && groups.length > 0 && (
|
|
308
|
+
<>
|
|
309
|
+
{groupIndex > 0 && (
|
|
310
|
+
<div className="location-dropdown__divider" />
|
|
311
|
+
)}
|
|
312
|
+
<div className="location-dropdown__group-header">
|
|
313
|
+
<Text size="xs" variant="bold">
|
|
314
|
+
{group.label}
|
|
315
|
+
</Text>
|
|
330
316
|
</div>
|
|
331
|
-
|
|
332
|
-
|
|
317
|
+
</>
|
|
318
|
+
)}
|
|
319
|
+
|
|
320
|
+
<div className="location-dropdown__group-options">
|
|
321
|
+
{group.options.map((option) => {
|
|
322
|
+
const isSelected = effectiveSelectedValue === option.id;
|
|
323
|
+
const isDisabled = option.disabled || disabled;
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div
|
|
327
|
+
key={option.id}
|
|
328
|
+
className={`location-dropdown__option ${isSelected ? 'location-dropdown__option--selected' : ''} ${isDisabled ? 'location-dropdown__option--disabled' : ''}`}
|
|
329
|
+
onClick={() => !isDisabled && handleOptionSelect(option)}>
|
|
330
|
+
<Icon
|
|
331
|
+
name={getOptionIcon(option, isSelected)}
|
|
332
|
+
size="sm"
|
|
333
|
+
className="location-dropdown__option-icon"
|
|
334
|
+
/>
|
|
335
|
+
<span className="location-dropdown__option-text">
|
|
336
|
+
{option.label}
|
|
337
|
+
</span>
|
|
338
|
+
</div>
|
|
339
|
+
);
|
|
340
|
+
})}
|
|
341
|
+
</div>
|
|
333
342
|
</div>
|
|
334
|
-
</div>
|
|
335
343
|
))
|
|
336
344
|
)}
|
|
337
345
|
</div>
|