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
- scrollIntoViewOnOpen(inputRef, isOpen, scrollOnOpen);
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.map(function (group) { return (__assign(__assign({}, group), { options: filterOptions(group.options) })); }).filter(function (group) { return group.options.length > 0; });
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
- window.scrollTo({
30
- top: elementTop - offset,
31
- behavior: 'smooth',
32
- });
32
+ if (realBottom > bodyBottom_1) {
33
+ window.scrollTo({
34
+ top: elementTop - offset,
35
+ behavior: 'smooth',
36
+ });
37
+ }
33
38
  }
34
- }, 0);
39
+ }, 350);
35
40
  }
36
41
  }
37
42
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mautourco-components",
3
- "version": "0.2.103",
3
+ "version": "0.2.104",
4
4
  "private": false,
5
5
  "description": "Bibliothèque de composants Mautourco pour le redesign",
6
6
  "main": "dist/index.js",
@@ -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
- scrollIntoViewOnOpen(inputRef, isOpen, scrollOnOpen);
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 = groups.length > 0 ? groups : [{ id: 'default', label: '', options }];
205
- const allOptions = allOptionsRaw.map((group) => ({
206
- ...group,
207
- options: filterOptions(group.options),
208
- })).filter((group) => group.options.length > 0);
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
- <div key={group.id} className="location-dropdown__group">
301
- {showGroupTitles && group.label && groups.length > 0 && (
302
- <>
303
- {groupIndex > 0 && <div className="location-dropdown__divider" />}
304
- <div className="location-dropdown__group-header">
305
- <Text size="xs" variant="bold">
306
- {group.label}
307
- </Text>
308
- </div>
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>