@via-profit/ui-kit 0.2.2 → 0.2.4

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,8 +1,8 @@
1
1
  import React from 'react';
2
- import { AutocompleteTextFieldProps } from './AutocompleteTextField';
2
+ import { TextFieldProps } from '../TextField';
3
3
  import { PositionStrategy } from '../Popper';
4
4
  import { AnchorPos, GetOptionSelected, MenuItemProps, OnRequestClose, Value } from '../Menu';
5
- export interface AutocompleteProps<T, Multiple extends boolean | undefined = undefined> extends Omit<AutocompleteTextFieldProps, 'value' | 'onChange' | 'children' | 'overrides'> {
5
+ export interface AutocompleteProps<T, Multiple extends boolean | undefined = undefined> extends Omit<TextFieldProps, 'value' | 'onChange' | 'children' | 'overrides'> {
6
6
  readonly items: readonly T[];
7
7
  readonly value: Value<T, Multiple>;
8
8
  /**
@@ -21,7 +21,7 @@ export interface AutocompleteProps<T, Multiple extends boolean | undefined = und
21
21
  /**
22
22
  * Anchor position\
23
23
  * \
24
- * Default: `bottom-fill`
24
+ * Default: `bottom`
25
25
  */
26
26
  readonly anchorPos?: AnchorPos;
27
27
  /**
@@ -43,6 +43,7 @@ export interface AutocompleteProps<T, Multiple extends boolean | undefined = und
43
43
  * ```
44
44
  */
45
45
  readonly positionStrategy?: PositionStrategy;
46
+ readonly alternativePlacements?: readonly AnchorPos[];
46
47
  /**
47
48
  * Minimum distance (in pixels) that the popper must maintain from the viewport edges.
48
49
  * Used to prevent the popper from being positioned too close to the screen boundaries.
@@ -137,7 +138,7 @@ export interface AutocompleteOverrides {
137
138
  /**
138
139
  * Element wrapper
139
140
  */
140
- readonly TextField?: React.ComponentType<AutocompleteTextFieldProps & React.RefAttributes<HTMLDivElement>>;
141
+ readonly TextField?: React.ComponentType<TextFieldProps & React.RefAttributes<HTMLDivElement>>;
141
142
  }
142
143
  export type Children<T> = (data: {
143
144
  item: T;
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __rest = (this && this.__rest) || function (s, e) {
26
3
  var t = {};
27
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -38,26 +15,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
15
  };
39
16
  Object.defineProperty(exports, "__esModule", { value: true });
40
17
  const react_1 = __importDefault(require("react"));
41
- const AutocompleteTextField_1 = __importDefault(require("./AutocompleteTextField"));
18
+ const TextField_1 = __importDefault(require("../TextField"));
42
19
  const Button_1 = __importDefault(require("../Button"));
43
- const Spinner_1 = __importDefault(require("../LoadingIndicator/Spinner"));
44
- const context_1 = __importStar(require("./context"));
20
+ const LoadingIndicator_1 = require("../LoadingIndicator");
21
+ const context_1 = require("./context");
45
22
  const IconClear_1 = __importDefault(require("./IconClear"));
46
23
  const ClickOutside_1 = require("../ClickOutside");
47
- const OverrideMenuList_1 = __importDefault(require("./OverrideMenuList"));
48
24
  const Menu_1 = __importDefault(require("../Menu"));
49
- //
50
25
  const Autocomplete = react_1.default.forwardRef((props, ref) => {
51
- const { items, value, multiple, isOpen = false, isLoading = false, clearOnBlur = true, anchorPos = 'bottom-fill', openOnFocus = true, autoFlip, viewportMargin, positionStrategy, requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, clearable = true, onInputChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearOnBlur", "anchorPos", "openOnFocus", "autoFlip", "viewportMargin", "positionStrategy", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "clearable", "onInputChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
52
- const [actualPlacement, setActualPlacement] = react_1.default.useState(anchorPos);
26
+ const { items, value, multiple, isOpen = false, isLoading = false, clearOnBlur = true, anchorPos = 'bottom-fill', alternativePlacements = ['bottom-fill', 'top-fill'], openOnFocus = true, autoFlip = true, viewportMargin, positionStrategy, requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, clearable = true, onInputChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearOnBlur", "anchorPos", "alternativePlacements", "openOnFocus", "autoFlip", "viewportMargin", "positionStrategy", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "clearable", "onInputChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
53
27
  const menuRef = react_1.default.useRef(null);
54
28
  const fieldInputRef = react_1.default.useRef(null);
55
29
  const isFocusedRef = react_1.default.useRef(false);
56
30
  const itemsRef = react_1.default.useRef(items);
57
- const { state, dispatch } = (0, context_1.default)();
58
- const { currentOpen, filteredItems, inputValue, currentValue, anchorElement, currentLoading } = state;
31
+ const { currentOpen, filteredItems, inputValue, currentValue, anchorElement, currentLoading } = (0, context_1.useContextState)();
32
+ const dispatch = (0, context_1.useContextDispatch)();
59
33
  const overridesMap = react_1.default.useMemo(() => ({
60
- TextField: (overrides === null || overrides === void 0 ? void 0 : overrides.TextField) || AutocompleteTextField_1.default,
34
+ TextField: (overrides === null || overrides === void 0 ? void 0 : overrides.TextField) || TextField_1.default,
61
35
  }), [overrides]);
62
36
  const clear = react_1.default.useCallback(() => {
63
37
  if (onChange) {
@@ -179,7 +153,6 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
179
153
  }
180
154
  }, [isLoading, currentLoading, dispatch]);
181
155
  react_1.default.useEffect(() => {
182
- // Сравниваем items более эффективно
183
156
  if (itemsRef.current === items) {
184
157
  return;
185
158
  }
@@ -241,119 +214,137 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
241
214
  inputValue,
242
215
  multiple,
243
216
  ]);
217
+ const onSelectMenuItem = react_1.default.useCallback(item => {
218
+ if (!multiple) {
219
+ dispatch({
220
+ type: 'setPartial',
221
+ payload: {
222
+ filteredItems: applyFilterForItems(selectedItemToString(item), items),
223
+ },
224
+ });
225
+ }
226
+ if (typeof onChange === 'function') {
227
+ onChange(item);
228
+ }
229
+ }, [applyFilterForItems, dispatch, items, multiple, onChange, selectedItemToString]);
230
+ const endIconMemo = react_1.default.useMemo(() => {
231
+ if (currentLoading) {
232
+ return (react_1.default.createElement(Button_1.default, { iconOnly: true, type: "button", variant: "plain", disabled: true },
233
+ react_1.default.createElement(LoadingIndicator_1.StaticLoadingIndicator, null)));
234
+ }
235
+ if (!clearable) {
236
+ return undefined;
237
+ }
238
+ return (react_1.default.createElement(Button_1.default, { iconOnly: true, type: "button", variant: "plain", onClick: clear, "aria-label": "Clear" },
239
+ react_1.default.createElement(IconClear_1.default, null)));
240
+ }, [clear, clearable, currentLoading]);
241
+ const textFieldOnKeyDown = react_1.default.useCallback(event => {
242
+ inputKeydownEvent(event);
243
+ if (typeof nativeInputProps.onKeyDown === 'function') {
244
+ nativeInputProps.onKeyDown(event);
245
+ }
246
+ }, [inputKeydownEvent, nativeInputProps]);
247
+ const textFieldOnChange = react_1.default.useCallback(event => {
248
+ if (typeof onInputChange === 'function') {
249
+ onInputChange(event);
250
+ }
251
+ // If openOnFocus is false, but value is not empty
252
+ // we should open menu list if is not opened
253
+ if (!openOnFocus && isFocusedRef.current && !currentOpen && filteredItems.length > 0) {
254
+ onRequestOpen(event);
255
+ }
256
+ const newFilteredItems = applyFilterForItems(event.currentTarget.value, items);
257
+ if (newFilteredItems.length === 0 && currentOpen) {
258
+ onRequestClose();
259
+ }
260
+ if (newFilteredItems.length > 0 && !currentOpen) {
261
+ onRequestOpen(event);
262
+ }
263
+ dispatch((0, context_1.actionSetPartial)({
264
+ filteredItems: newFilteredItems,
265
+ inputValue: event.currentTarget.value,
266
+ }));
267
+ }, [
268
+ applyFilterForItems,
269
+ currentOpen,
270
+ dispatch,
271
+ filteredItems.length,
272
+ items,
273
+ onInputChange,
274
+ onRequestClose,
275
+ onRequestOpen,
276
+ openOnFocus,
277
+ ]);
278
+ const textFieldClick = react_1.default.useCallback(event => {
279
+ if (typeof nativeInputProps.onClick === 'function') {
280
+ nativeInputProps.onClick(event);
281
+ }
282
+ if (isFocusedRef.current &&
283
+ !currentOpen &&
284
+ filteredItems.length > 0
285
+ // && inputValue.trim() !== ''
286
+ ) {
287
+ onRequestOpen(event);
288
+ }
289
+ }, [currentOpen, filteredItems.length, nativeInputProps, onRequestOpen]);
290
+ const textFieldFocus = react_1.default.useCallback(event => {
291
+ isFocusedRef.current = true;
292
+ if (openOnFocus && !currentOpen && filteredItems.length > 0) {
293
+ onRequestOpen(event);
294
+ }
295
+ if (typeof nativeInputProps.onFocus === 'function') {
296
+ nativeInputProps.onFocus(event);
297
+ }
298
+ }, [currentOpen, filteredItems.length, nativeInputProps, onRequestOpen, openOnFocus]);
299
+ const textFieldBlur = react_1.default.useCallback(event => {
300
+ isFocusedRef.current = false;
301
+ if (typeof nativeInputProps.onBlur === 'function') {
302
+ nativeInputProps.onBlur(event);
303
+ }
304
+ }, [nativeInputProps]);
305
+ const setAnchorElementRef = react_1.default.useCallback((el) => {
306
+ if (anchorElement !== el) {
307
+ dispatch((0, context_1.actionSetPartial)({ anchorElement: el }));
308
+ }
309
+ }, [anchorElement, dispatch]);
310
+ const inputRefRef = react_1.default.useRef(inputRef);
311
+ react_1.default.useEffect(() => {
312
+ inputRefRef.current = inputRef;
313
+ }, [inputRef]);
314
+ const setInputElementRef = react_1.default.useCallback((el) => {
315
+ fieldInputRef.current = el;
316
+ const currentInputRef = inputRefRef.current;
317
+ if (typeof currentInputRef === 'function') {
318
+ currentInputRef(el);
319
+ }
320
+ else if (currentInputRef && typeof currentInputRef === 'object') {
321
+ currentInputRef.current = el;
322
+ }
323
+ }, []);
244
324
  return (react_1.default.createElement(react_1.default.Fragment, null,
245
- react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.TextField, Object.assign({ placeholder: placeholder, anchorPos: actualPlacement, isOpen: currentOpen, label: label, error: error, requiredAsterisk: requiredAsterisk, errorText: errorText, fullWidth: fullWidth, startIcon: startIcon, isLoading: currentLoading, endIcon: clearable ? (react_1.default.createElement(Button_1.default, { iconOnly: true, type: "button", variant: "plain", onClick: () => (currentLoading ? 'undefined' : clear()) }, currentLoading ? react_1.default.createElement(Spinner_1.default, null) : react_1.default.createElement(IconClear_1.default, null))) : undefined }, nativeInputProps, { onKeyDown: event => {
246
- inputKeydownEvent(event);
247
- if (typeof nativeInputProps.onKeyDown === 'function') {
248
- nativeInputProps.onKeyDown(event);
249
- }
250
- }, ref: el => {
251
- if (anchorElement !== el) {
252
- dispatch((0, context_1.actionSetPartial)({ anchorElement: el }));
253
- }
254
- }, inputRef: el => {
255
- fieldInputRef.current = el;
256
- if (typeof inputRef === 'function') {
257
- inputRef(el);
258
- }
259
- if (inputRef && typeof inputRef === 'object') {
260
- inputRef.current = el;
261
- }
262
- }, value: inputValue, onBlur: event => {
263
- isFocusedRef.current = false;
264
- if (typeof nativeInputProps.onBlur === 'function') {
265
- nativeInputProps.onBlur(event);
266
- }
267
- }, onFocus: event => {
268
- isFocusedRef.current = true;
269
- if (openOnFocus && !currentOpen && filteredItems.length > 0) {
270
- onRequestOpen(event);
271
- }
272
- // if (!openOnFocus && !currentOpen && inputValue !== '' && filteredItems.length > 0) {
273
- // onRequestOpen(event);
274
- // }
275
- if (typeof nativeInputProps.onFocus === 'function') {
276
- nativeInputProps.onFocus(event);
277
- }
278
- }, onClick: event => {
279
- if (typeof nativeInputProps.onClick === 'function') {
280
- nativeInputProps.onClick(event);
281
- }
282
- if (isFocusedRef.current &&
283
- !currentOpen &&
284
- filteredItems.length > 0
285
- // && inputValue.trim() !== ''
286
- ) {
287
- onRequestOpen(event);
288
- }
289
- }, onChange: event => {
290
- if (typeof onInputChange === 'function') {
291
- onInputChange(event);
292
- }
293
- // If openOnFocus is false, but value is not empty
294
- // we should open menu list if is not opened
295
- if (!openOnFocus &&
296
- isFocusedRef.current &&
297
- !currentOpen &&
298
- filteredItems.length > 0) {
299
- onRequestOpen(event);
300
- }
301
- // console.debug('set filteredItems');
302
- const newFilteredItems = applyFilterForItems(event.currentTarget.value, items);
303
- if (newFilteredItems.length === 0 && currentOpen) {
304
- onRequestClose();
305
- }
306
- if (newFilteredItems.length > 0 && !currentOpen) {
307
- onRequestOpen(event);
308
- }
309
- dispatch((0, context_1.actionSetPartial)({
310
- filteredItems: newFilteredItems,
311
- inputValue: event.currentTarget.value,
312
- }));
313
- } }))), [
325
+ react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.TextField, Object.assign({ placeholder: placeholder, label: label, error: error, requiredAsterisk: requiredAsterisk, errorText: errorText, fullWidth: fullWidth, startIcon: startIcon, endIcon: endIconMemo }, nativeInputProps, { onKeyDown: textFieldOnKeyDown, ref: setAnchorElementRef, inputRef: setInputElementRef, value: inputValue, onBlur: textFieldBlur, onFocus: textFieldFocus, onClick: textFieldClick, onChange: textFieldOnChange }))), [
326
+ setAnchorElementRef,
327
+ setInputElementRef,
314
328
  overridesMap,
315
329
  placeholder,
316
- actualPlacement,
317
- currentOpen,
318
330
  label,
319
331
  error,
320
332
  requiredAsterisk,
321
333
  errorText,
322
334
  fullWidth,
323
335
  startIcon,
324
- currentLoading,
325
- clearable,
336
+ endIconMemo,
326
337
  nativeInputProps,
338
+ textFieldOnKeyDown,
327
339
  inputValue,
328
- clear,
329
- inputKeydownEvent,
330
- anchorElement,
331
- dispatch,
332
- inputRef,
333
- openOnFocus,
334
- filteredItems.length,
335
- onRequestOpen,
336
- onInputChange,
337
- applyFilterForItems,
338
- items,
339
- onRequestClose,
340
+ textFieldBlur,
341
+ textFieldFocus,
342
+ textFieldClick,
343
+ textFieldOnChange,
340
344
  ]),
341
- react_1.default.useMemo(() => (react_1.default.createElement(Menu_1.default, { ref: menuRef, onAnchorPosChanged: setActualPlacement, anchorPos: actualPlacement, multiple: multiple, items: filteredItems, value: currentValue, isOpen: currentOpen, autofocus: false, autoFlip: autoFlip, viewportMargin: viewportMargin, offset: 0, overrides: {
342
- List: OverrideMenuList_1.default,
343
- }, positionStrategy: positionStrategy, anchorElement: anchorElement, closeOutsideClick: false, getOptionSelected: getOptionSelected, onRequestClose: onRequestClose, closeOnSelect: !multiple, onSelectItem: item => {
344
- if (!multiple) {
345
- dispatch({
346
- type: 'setPartial',
347
- payload: {
348
- filteredItems: applyFilterForItems(selectedItemToString(item), items),
349
- },
350
- });
351
- }
352
- if (typeof onChange === 'function') {
353
- onChange(item);
354
- }
355
- } }, renderChildren)), [
356
- actualPlacement,
345
+ react_1.default.useMemo(() => (react_1.default.createElement(Menu_1.default, { ref: menuRef, anchorPos: anchorPos, alternativePlacements: alternativePlacements, multiple: multiple, items: filteredItems, value: currentValue, isOpen: currentOpen, autofocus: false, autoFlip: autoFlip, viewportMargin: viewportMargin, offset: 0, positionStrategy: positionStrategy, anchorElement: anchorElement, closeOutsideClick: false, getOptionSelected: getOptionSelected, onRequestClose: onRequestClose, closeOnSelect: !multiple, onSelectItem: onSelectMenuItem }, renderChildren)), [
346
+ anchorPos,
347
+ alternativePlacements,
357
348
  multiple,
358
349
  filteredItems,
359
350
  currentValue,
@@ -364,13 +355,8 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
364
355
  anchorElement,
365
356
  getOptionSelected,
366
357
  onRequestClose,
367
- onChange,
368
- dispatch,
369
- applyFilterForItems,
370
- selectedItemToString,
371
- items,
372
- children,
373
- inputValue,
358
+ onSelectMenuItem,
359
+ renderChildren,
374
360
  ])));
375
361
  });
376
362
  Autocomplete.displayName = 'Autocomplete';
@@ -20,7 +20,7 @@ const styled_1 = __importDefault(require("@emotion/styled"));
20
20
  const react_2 = require("@emotion/react");
21
21
  const MenuItem_1 = __importDefault(require("../Menu/MenuItem"));
22
22
  const StyeldMenuItem = (0, styled_1.default)(MenuItem_1.default, {
23
- shouldForwardProp: p => !['$vatiant'].includes(p),
23
+ shouldForwardProp: p => !['variant'].includes(p),
24
24
  }) `
25
25
  ${({ $variant, theme }) => $variant === 'virtual' &&
26
26
  (0, react_2.css) `
@@ -29,8 +29,6 @@ interface ContextProviderProps {
29
29
  readonly initialState?: Partial<State>;
30
30
  }
31
31
  export declare const ContextProvider: React.FC<ContextProviderProps>;
32
- export declare const useContext: () => {
33
- state: State;
34
- dispatch: React.Dispatch<ActionSetPartial>;
35
- };
36
- export default useContext;
32
+ export declare const useContextState: () => State;
33
+ export declare const useContextDispatch: () => React.Dispatch<Action>;
34
+ export {};
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.useContext = exports.ContextProvider = exports.createInitialState = exports.reducer = exports.defaultState = exports.actionSetPartial = void 0;
6
+ exports.useContextDispatch = exports.useContextState = exports.ContextProvider = exports.createInitialState = exports.reducer = exports.defaultState = exports.actionSetPartial = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const actionSetPartial = (payload) => ({
9
9
  type: 'setPartial',
@@ -41,22 +41,30 @@ const createInitialState = (params) => {
41
41
  inputValue, currentValue: value, currentOpen: Boolean(isOpen) });
42
42
  };
43
43
  exports.createInitialState = createInitialState;
44
- const context = react_1.default.createContext({
45
- state: exports.defaultState,
46
- dispatch: () => undefined,
47
- });
44
+ const StateContext = react_1.default.createContext(exports.defaultState);
45
+ const DispatchContext = react_1.default.createContext(() => undefined);
48
46
  const ContextProvider = props => {
49
47
  const { children, initialState } = props;
50
48
  const [state, dispatch] = react_1.default.useReducer(exports.reducer, Object.assign(Object.assign({}, exports.defaultState), initialState));
51
- return react_1.default.createElement(context.Provider, { value: { state, dispatch } }, children);
49
+ const stateValue = react_1.default.useMemo(() => state, [state]);
50
+ const dispatchValue = react_1.default.useMemo(() => dispatch, []);
51
+ return (react_1.default.createElement(DispatchContext.Provider, { value: dispatchValue },
52
+ react_1.default.createElement(StateContext.Provider, { value: stateValue }, children)));
52
53
  };
53
54
  exports.ContextProvider = ContextProvider;
54
- const useContext = () => {
55
- const { state, dispatch } = react_1.default.useContext(context);
56
- return {
57
- state,
58
- dispatch,
59
- };
55
+ const useContextState = () => {
56
+ const context = react_1.default.useContext(StateContext);
57
+ if (context === undefined) {
58
+ throw new Error('useContextState must be used within a ContextProvider');
59
+ }
60
+ return context;
61
+ };
62
+ exports.useContextState = useContextState;
63
+ const useContextDispatch = () => {
64
+ const context = react_1.default.useContext(DispatchContext);
65
+ if (context === undefined) {
66
+ throw new Error('useContextDispatch must be used within a ContextProvider');
67
+ }
68
+ return context;
60
69
  };
61
- exports.useContext = useContext;
62
- exports.default = exports.useContext;
70
+ exports.useContextDispatch = useContextDispatch;
@@ -36,13 +36,18 @@ const Highlighted = (props, ref) => {
36
36
  Mark: (overrides === null || overrides === void 0 ? void 0 : overrides.Mark) || HighlightedMark_1.default,
37
37
  Text: (overrides === null || overrides === void 0 ? void 0 : overrides.Text) || HighlightedText_1.default,
38
38
  }), [overrides]);
39
+ const renderParts = react_1.default.useCallback(() => {
40
+ if (disabledHighlighting || patterns.length === 0) {
41
+ return null;
42
+ }
43
+ return text.split(regex).map((part, i) => {
44
+ const isMatch = part.match(regex) !== null;
45
+ return isMatch ? (react_1.default.createElement(overridesMap.Mark, { key: i }, part)) : (react_1.default.createElement(overridesMap.Text, { key: i }, part));
46
+ });
47
+ }, [disabledHighlighting, patterns.length, regex, text, overridesMap]);
39
48
  return (react_1.default.createElement(overridesMap.Container, Object.assign({}, nativeProps, { ref: ref }),
40
49
  disabledHighlighting && react_1.default.createElement(overridesMap.Text, null, text),
41
50
  !disabledHighlighting && patterns.length === 0 && (react_1.default.createElement(overridesMap.Text, null, text)),
42
- !disabledHighlighting &&
43
- patterns.length > 0 &&
44
- text
45
- .split(regex)
46
- .map((part, i) => regex.test(part) ? (react_1.default.createElement(overridesMap.Mark, { key: i }, part)) : (react_1.default.createElement(overridesMap.Text, { key: i }, part)))));
51
+ renderParts()));
47
52
  };
48
53
  exports.default = react_1.default.forwardRef(Highlighted);
@@ -0,0 +1,5 @@
1
+ export declare const splitTextIntoParts: (text: string, regex: RegExp, patterns: string[]) => {
2
+ text: string;
3
+ highlighted: boolean;
4
+ }[];
5
+ export default splitTextIntoParts;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitTextIntoParts = void 0;
4
+ const MAX_MATCHES = 1000;
5
+ const splitTextIntoParts = (text, regex, patterns) => {
6
+ if (patterns.length === 0) {
7
+ return [{ text, highlighted: false }];
8
+ }
9
+ const parts = [];
10
+ let lastIndex = 0;
11
+ let match;
12
+ let matchCount = 0;
13
+ const cleanRegex = new RegExp(regex.source, regex.flags);
14
+ while ((match = cleanRegex.exec(text)) !== null) {
15
+ matchCount++;
16
+ if (matchCount > MAX_MATCHES) {
17
+ console.warn(`splitTextIntoParts: Too many matches (${matchCount}), stopping at ${MAX_MATCHES} matches`);
18
+ break;
19
+ }
20
+ const matchStart = match.index;
21
+ const matchEnd = matchStart + match[0].length;
22
+ if (matchStart > lastIndex) {
23
+ parts.push({
24
+ text: text.substring(lastIndex, matchStart),
25
+ highlighted: false,
26
+ });
27
+ }
28
+ parts.push({
29
+ text: match[0],
30
+ highlighted: true,
31
+ });
32
+ lastIndex = matchEnd;
33
+ if (match[0].length === 0) {
34
+ break;
35
+ }
36
+ }
37
+ if (lastIndex < text.length) {
38
+ parts.push({
39
+ text: text.substring(lastIndex),
40
+ highlighted: false,
41
+ });
42
+ }
43
+ return parts;
44
+ };
45
+ exports.splitTextIntoParts = splitTextIntoParts;
46
+ exports.default = exports.splitTextIntoParts;
@@ -90,6 +90,7 @@ export interface MenuProps<T, Multiple extends boolean | undefined = undefined>
90
90
  * Default: `bottom`
91
91
  */
92
92
  readonly anchorPos?: AnchorPos;
93
+ readonly alternativePlacements?: readonly AnchorPos[];
93
94
  readonly onAnchorPosChanged?: (anchorPos: AnchorPos) => void;
94
95
  /**
95
96
  * When enabled, the popper will automatically try to find the best placement
@@ -164,6 +165,28 @@ export interface MenuProps<T, Multiple extends boolean | undefined = undefined>
164
165
  * The function that will be called at the moment when you want to close the menu
165
166
  */
166
167
  readonly onRequestClose?: OnRequestClose;
168
+ /**
169
+ * List menu maximum width (px, em, etc.)\
170
+ * Using pixels:
171
+ * ```tsx
172
+ * <Menu
173
+ * maxWidth={250}
174
+ * >
175
+ * ```
176
+ * Using em:
177
+ * ```tsx
178
+ * <Menu
179
+ * maxWidth="16em"
180
+ * >
181
+ * ```
182
+ * Using pixels:
183
+ * ```tsx
184
+ * <Menu
185
+ * maxWidth="16px"
186
+ * >
187
+ * ```
188
+ */
189
+ readonly maxWidth?: number | string;
167
190
  }
168
191
  export interface MenuOverrides {
169
192
  /**
@@ -220,9 +243,8 @@ export type MenuRef = {
220
243
  * Returns the list HTML container
221
244
  */
222
245
  getListElement: () => HTMLDivElement | null;
223
- setActualPlacement: (placement: AnchorPos) => void;
224
246
  };
225
- export type Value<T, Multiple> = Multiple extends undefined | undefined ? T | null : readonly T[];
247
+ export type Value<T, Multiple> = Multiple extends undefined ? T | null : readonly T[];
226
248
  export type GetOptionSelected<T> = (payload: {
227
249
  readonly item: T;
228
250
  readonly value: T;