@seekho/ui 0.1.53 → 0.1.55

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/dist/index.d.mts CHANGED
@@ -57,10 +57,20 @@ interface AutoCompleteProps<T> {
57
57
  isOptionEqualToValue?: (option: T, value: T) => boolean;
58
58
  isLoading?: boolean;
59
59
  renderOption?: (props: RenderOptionProps, option: T) => React.ReactNode;
60
+ /**
61
+ * Override how `options` are narrowed down for the dropdown. Defaults to a
62
+ * case-insensitive match of the input against `getOptionLabel`.
63
+ * Pass `(options) => options` when `options` already come from a server-side
64
+ * search, so results that don't match the label (e.g. an id or phone lookup)
65
+ * aren't filtered out.
66
+ */
67
+ filterOptions?: (options: T[], state: {
68
+ inputValue: string;
69
+ }) => T[];
60
70
  onChange: (value: T | null) => void;
61
71
  onInputChange?: (value: string) => void;
62
72
  }
63
- declare function AutoComplete<T>({ label: _label, value, options, disabled, error, className, getOptionLabel, isOptionEqualToValue, isLoading, renderOption, onChange, onInputChange, }: AutoCompleteProps<T>): react_jsx_runtime.JSX.Element;
73
+ declare function AutoComplete<T>({ label: _label, value, options, disabled, error, className, getOptionLabel, isOptionEqualToValue, isLoading, renderOption, filterOptions, onChange, onInputChange, }: AutoCompleteProps<T>): react_jsx_runtime.JSX.Element;
64
74
 
65
75
  interface BreadcrumbProps {
66
76
  /** Current URL pathname — pass location.pathname (React Router) or router.pathname (Next.js) */
package/dist/index.d.ts CHANGED
@@ -57,10 +57,20 @@ interface AutoCompleteProps<T> {
57
57
  isOptionEqualToValue?: (option: T, value: T) => boolean;
58
58
  isLoading?: boolean;
59
59
  renderOption?: (props: RenderOptionProps, option: T) => React.ReactNode;
60
+ /**
61
+ * Override how `options` are narrowed down for the dropdown. Defaults to a
62
+ * case-insensitive match of the input against `getOptionLabel`.
63
+ * Pass `(options) => options` when `options` already come from a server-side
64
+ * search, so results that don't match the label (e.g. an id or phone lookup)
65
+ * aren't filtered out.
66
+ */
67
+ filterOptions?: (options: T[], state: {
68
+ inputValue: string;
69
+ }) => T[];
60
70
  onChange: (value: T | null) => void;
61
71
  onInputChange?: (value: string) => void;
62
72
  }
63
- declare function AutoComplete<T>({ label: _label, value, options, disabled, error, className, getOptionLabel, isOptionEqualToValue, isLoading, renderOption, onChange, onInputChange, }: AutoCompleteProps<T>): react_jsx_runtime.JSX.Element;
73
+ declare function AutoComplete<T>({ label: _label, value, options, disabled, error, className, getOptionLabel, isOptionEqualToValue, isLoading, renderOption, filterOptions, onChange, onInputChange, }: AutoCompleteProps<T>): react_jsx_runtime.JSX.Element;
64
74
 
65
75
  interface BreadcrumbProps {
66
76
  /** Current URL pathname — pass location.pathname (React Router) or router.pathname (Next.js) */
package/dist/index.js CHANGED
@@ -217,6 +217,12 @@ var Chip = ({
217
217
  }
218
218
  );
219
219
  };
220
+ var defaultFilterOptions = (options, {
221
+ inputValue,
222
+ getOptionLabel
223
+ }) => options.filter(
224
+ (option) => getOptionLabel(option).toLowerCase().includes(inputValue.toLowerCase())
225
+ );
220
226
  function AutoComplete({
221
227
  label: _label,
222
228
  value,
@@ -228,6 +234,7 @@ function AutoComplete({
228
234
  isOptionEqualToValue,
229
235
  isLoading = false,
230
236
  renderOption,
237
+ filterOptions,
231
238
  onChange,
232
239
  onInputChange
233
240
  }) {
@@ -241,18 +248,20 @@ function AutoComplete({
241
248
  );
242
249
  const [highlightedIndex, setHighlightedIndex] = React8.useState(-1);
243
250
  const [dropdownPos, setDropdownPos] = React8.useState(null);
251
+ const DROPDOWN_MAX_HEIGHT = 240;
244
252
  const handelUpdateDropdownPosition = () => {
245
253
  if (!containerRef.current) return;
246
254
  const rect = containerRef.current.getBoundingClientRect();
255
+ const spaceBelow = window.innerHeight - rect.bottom;
256
+ const openUpward = spaceBelow < DROPDOWN_MAX_HEIGHT + 8 && rect.top > spaceBelow;
247
257
  setDropdownPos({
248
- top: rect.bottom + 4,
258
+ top: openUpward ? void 0 : rect.bottom + 4,
259
+ bottom: openUpward ? window.innerHeight - rect.top + 4 : void 0,
249
260
  left: rect.left,
250
261
  width: rect.width
251
262
  });
252
263
  };
253
- const filteredOptions = options.filter(
254
- (option) => getOptionLabel(option).toLowerCase().includes(inputValue.toLowerCase())
255
- );
264
+ const filteredOptions = filterOptions ? filterOptions(options, { inputValue }) : defaultFilterOptions(options, { inputValue, getOptionLabel });
256
265
  const handleOpen = () => {
257
266
  const selectedIdx = filteredOptions.findIndex(
258
267
  (opt) => value ? isOptionEqualToValue ? isOptionEqualToValue(opt, value) : getOptionLabel(opt) === getOptionLabel(value) : false
@@ -467,6 +476,7 @@ function AutoComplete({
467
476
  style: {
468
477
  position: "fixed",
469
478
  top: dropdownPos.top,
479
+ bottom: dropdownPos.bottom,
470
480
  left: dropdownPos.left,
471
481
  width: dropdownPos.width
472
482
  },
package/dist/index.mjs CHANGED
@@ -210,6 +210,12 @@ var Chip = ({
210
210
  }
211
211
  );
212
212
  };
213
+ var defaultFilterOptions = (options, {
214
+ inputValue,
215
+ getOptionLabel
216
+ }) => options.filter(
217
+ (option) => getOptionLabel(option).toLowerCase().includes(inputValue.toLowerCase())
218
+ );
213
219
  function AutoComplete({
214
220
  label: _label,
215
221
  value,
@@ -221,6 +227,7 @@ function AutoComplete({
221
227
  isOptionEqualToValue,
222
228
  isLoading = false,
223
229
  renderOption,
230
+ filterOptions,
224
231
  onChange,
225
232
  onInputChange
226
233
  }) {
@@ -234,18 +241,20 @@ function AutoComplete({
234
241
  );
235
242
  const [highlightedIndex, setHighlightedIndex] = useState(-1);
236
243
  const [dropdownPos, setDropdownPos] = useState(null);
244
+ const DROPDOWN_MAX_HEIGHT = 240;
237
245
  const handelUpdateDropdownPosition = () => {
238
246
  if (!containerRef.current) return;
239
247
  const rect = containerRef.current.getBoundingClientRect();
248
+ const spaceBelow = window.innerHeight - rect.bottom;
249
+ const openUpward = spaceBelow < DROPDOWN_MAX_HEIGHT + 8 && rect.top > spaceBelow;
240
250
  setDropdownPos({
241
- top: rect.bottom + 4,
251
+ top: openUpward ? void 0 : rect.bottom + 4,
252
+ bottom: openUpward ? window.innerHeight - rect.top + 4 : void 0,
242
253
  left: rect.left,
243
254
  width: rect.width
244
255
  });
245
256
  };
246
- const filteredOptions = options.filter(
247
- (option) => getOptionLabel(option).toLowerCase().includes(inputValue.toLowerCase())
248
- );
257
+ const filteredOptions = filterOptions ? filterOptions(options, { inputValue }) : defaultFilterOptions(options, { inputValue, getOptionLabel });
249
258
  const handleOpen = () => {
250
259
  const selectedIdx = filteredOptions.findIndex(
251
260
  (opt) => value ? isOptionEqualToValue ? isOptionEqualToValue(opt, value) : getOptionLabel(opt) === getOptionLabel(value) : false
@@ -460,6 +469,7 @@ function AutoComplete({
460
469
  style: {
461
470
  position: "fixed",
462
471
  top: dropdownPos.top,
472
+ bottom: dropdownPos.bottom,
463
473
  left: dropdownPos.left,
464
474
  width: dropdownPos.width
465
475
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seekho/ui",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "description": "Seekho internal UI component library",
5
5
  "keywords": [
6
6
  "seekho",