@astral/ui 4.36.0 → 4.37.0

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.
Files changed (110) hide show
  1. package/components/Autocomplete/Autocomplete.d.ts +1 -1
  2. package/components/Autocomplete/Autocomplete.js +53 -15
  3. package/components/Autocomplete/constants.d.ts +6 -0
  4. package/components/Autocomplete/constants.js +7 -0
  5. package/components/Autocomplete/styles.js +15 -1
  6. package/components/Autocomplete/useLogic/useLogic.d.ts +2 -1
  7. package/components/Autocomplete/useLogic/useLogic.js +11 -2
  8. package/components/TagsList/Tag/Tag.d.ts +1 -1
  9. package/components/TagsList/Tag/constants.d.ts +1 -0
  10. package/components/TagsList/Tag/constants.js +1 -0
  11. package/components/TagsList/Tag/index.d.ts +1 -0
  12. package/components/TagsList/Tag/index.js +1 -0
  13. package/components/TagsList/Tag/styles.js +2 -0
  14. package/components/TagsList/TagsList.js +6 -6
  15. package/components/TagsList/constants.d.ts +2 -0
  16. package/components/TagsList/constants.js +2 -0
  17. package/components/TagsList/styles.js +5 -1
  18. package/components/TagsList/types.d.ts +14 -5
  19. package/components/TagsList/useLogic/useLogic.d.ts +5 -5
  20. package/components/TagsList/useLogic/useLogic.js +70 -110
  21. package/components/TagsList/utils/calculateVisibleTagsCount/calculateVisibleTagsCount.d.ts +6 -0
  22. package/components/TagsList/utils/calculateVisibleTagsCount/calculateVisibleTagsCount.js +35 -0
  23. package/components/TagsList/utils/calculateVisibleTagsCount/index.d.ts +1 -0
  24. package/components/TagsList/utils/calculateVisibleTagsCount/index.js +1 -0
  25. package/components/TagsList/utils/getAvailableWidth/getAvailableWidth.d.ts +1 -0
  26. package/components/TagsList/utils/getAvailableWidth/getAvailableWidth.js +7 -0
  27. package/components/TagsList/utils/getAvailableWidth/index.d.ts +1 -0
  28. package/components/TagsList/utils/getAvailableWidth/index.js +1 -0
  29. package/components/TagsList/utils/getKey/getKey.d.ts +1 -1
  30. package/components/TagsList/utils/getKey/getKey.js +6 -3
  31. package/components/TagsList/utils/getTagWidth/getTagWidth.d.ts +2 -0
  32. package/components/TagsList/utils/getTagWidth/getTagWidth.js +21 -0
  33. package/components/TagsList/utils/getTagWidth/index.d.ts +1 -0
  34. package/components/TagsList/utils/getTagWidth/index.js +1 -0
  35. package/components/TagsList/utils/index.d.ts +3 -0
  36. package/components/TagsList/utils/index.js +3 -0
  37. package/components/TextField/TextField.js +6 -5
  38. package/components/TextField/constants.d.ts +1 -0
  39. package/components/TextField/constants.js +1 -0
  40. package/components/TextField/styles.js +4 -0
  41. package/components/TreeAsyncAutocomplete/OptionsModal/styles.js +1 -1
  42. package/components/TreeAutocomplete/OptionsModal/OptionsModal.js +1 -1
  43. package/components/TreeAutocomplete/OptionsModal/styles.d.ts +4 -0
  44. package/components/TreeAutocomplete/OptionsModal/styles.js +10 -3
  45. package/components/TreeAutocomplete/OptionsModal/useLogic/useLogic.d.ts +5 -3
  46. package/components/TreeAutocomplete/OptionsModal/useLogic/useLogic.js +2 -1
  47. package/components/TreeLikeAsyncAutocomplete/Input/Input.js +1 -1
  48. package/components/TreeLikeAsyncAutocomplete/OptionsModal/styles.js +1 -1
  49. package/components/TreeLikeAutocomplete/OptionsModal/OptionsModal.js +1 -1
  50. package/components/TreeLikeAutocomplete/OptionsModal/styles.d.ts +4 -0
  51. package/components/TreeLikeAutocomplete/OptionsModal/styles.js +10 -3
  52. package/components/TreeLikeAutocomplete/OptionsModal/useLogic/useLogic.d.ts +5 -3
  53. package/components/TreeLikeAutocomplete/OptionsModal/useLogic/useLogic.js +2 -1
  54. package/node/components/Autocomplete/Autocomplete.d.ts +1 -1
  55. package/node/components/Autocomplete/Autocomplete.js +51 -13
  56. package/node/components/Autocomplete/constants.d.ts +6 -0
  57. package/node/components/Autocomplete/constants.js +8 -1
  58. package/node/components/Autocomplete/styles.js +15 -1
  59. package/node/components/Autocomplete/useLogic/useLogic.d.ts +2 -1
  60. package/node/components/Autocomplete/useLogic/useLogic.js +10 -1
  61. package/node/components/TagsList/Tag/Tag.d.ts +1 -1
  62. package/node/components/TagsList/Tag/constants.d.ts +1 -0
  63. package/node/components/TagsList/Tag/constants.js +4 -0
  64. package/node/components/TagsList/Tag/index.d.ts +1 -0
  65. package/node/components/TagsList/Tag/index.js +1 -0
  66. package/node/components/TagsList/Tag/styles.js +2 -0
  67. package/node/components/TagsList/TagsList.js +6 -6
  68. package/node/components/TagsList/constants.d.ts +2 -0
  69. package/node/components/TagsList/constants.js +5 -0
  70. package/node/components/TagsList/styles.js +5 -1
  71. package/node/components/TagsList/types.d.ts +14 -5
  72. package/node/components/TagsList/useLogic/useLogic.d.ts +5 -5
  73. package/node/components/TagsList/useLogic/useLogic.js +70 -110
  74. package/node/components/TagsList/utils/calculateVisibleTagsCount/calculateVisibleTagsCount.d.ts +6 -0
  75. package/node/components/TagsList/utils/calculateVisibleTagsCount/calculateVisibleTagsCount.js +39 -0
  76. package/node/components/TagsList/utils/calculateVisibleTagsCount/index.d.ts +1 -0
  77. package/node/components/TagsList/utils/calculateVisibleTagsCount/index.js +5 -0
  78. package/node/components/TagsList/utils/getAvailableWidth/getAvailableWidth.d.ts +1 -0
  79. package/node/components/TagsList/utils/getAvailableWidth/getAvailableWidth.js +11 -0
  80. package/node/components/TagsList/utils/getAvailableWidth/index.d.ts +1 -0
  81. package/node/components/TagsList/utils/getAvailableWidth/index.js +5 -0
  82. package/node/components/TagsList/utils/getKey/getKey.d.ts +1 -1
  83. package/node/components/TagsList/utils/getKey/getKey.js +6 -3
  84. package/node/components/TagsList/utils/getTagWidth/getTagWidth.d.ts +2 -0
  85. package/node/components/TagsList/utils/getTagWidth/getTagWidth.js +25 -0
  86. package/node/components/TagsList/utils/getTagWidth/index.d.ts +1 -0
  87. package/node/components/TagsList/{public.js → utils/getTagWidth/index.js} +1 -2
  88. package/node/components/TagsList/utils/index.d.ts +3 -0
  89. package/node/components/TagsList/utils/index.js +7 -1
  90. package/node/components/TextField/TextField.js +6 -5
  91. package/node/components/TextField/constants.d.ts +1 -0
  92. package/node/components/TextField/constants.js +1 -0
  93. package/node/components/TextField/styles.js +4 -0
  94. package/node/components/TreeAsyncAutocomplete/OptionsModal/styles.js +1 -1
  95. package/node/components/TreeAutocomplete/OptionsModal/OptionsModal.js +1 -1
  96. package/node/components/TreeAutocomplete/OptionsModal/styles.d.ts +4 -0
  97. package/node/components/TreeAutocomplete/OptionsModal/styles.js +10 -3
  98. package/node/components/TreeAutocomplete/OptionsModal/useLogic/useLogic.d.ts +5 -3
  99. package/node/components/TreeAutocomplete/OptionsModal/useLogic/useLogic.js +2 -1
  100. package/node/components/TreeLikeAsyncAutocomplete/Input/Input.js +1 -1
  101. package/node/components/TreeLikeAsyncAutocomplete/OptionsModal/styles.js +1 -1
  102. package/node/components/TreeLikeAutocomplete/OptionsModal/OptionsModal.js +1 -1
  103. package/node/components/TreeLikeAutocomplete/OptionsModal/styles.d.ts +4 -0
  104. package/node/components/TreeLikeAutocomplete/OptionsModal/styles.js +10 -3
  105. package/node/components/TreeLikeAutocomplete/OptionsModal/useLogic/useLogic.d.ts +5 -3
  106. package/node/components/TreeLikeAutocomplete/OptionsModal/useLogic/useLogic.js +2 -1
  107. package/package.json +1 -1
  108. package/components/TagsList/public.d.ts +0 -2
  109. package/components/TagsList/public.js +0 -2
  110. package/node/components/TagsList/public.d.ts +0 -2
@@ -0,0 +1 @@
1
+ export declare const getAvailableWidth: (containerEl: HTMLElement, reservedWidth?: number) => number;
@@ -0,0 +1,7 @@
1
+ export const getAvailableWidth = (containerEl, reservedWidth = 0) => {
2
+ const containerWidth = containerEl.clientWidth;
3
+ const paddingLeft = parseFloat(getComputedStyle(containerEl).paddingLeft);
4
+ const paddingRight = parseFloat(getComputedStyle(containerEl).paddingRight);
5
+ const availableWidth = containerWidth - paddingLeft - paddingRight - reservedWidth;
6
+ return availableWidth;
7
+ };
@@ -0,0 +1 @@
1
+ export { getAvailableWidth } from './getAvailableWidth';
@@ -0,0 +1 @@
1
+ export { getAvailableWidth } from './getAvailableWidth';
@@ -1,2 +1,2 @@
1
1
  import type { TagValue } from '../../types';
2
- export declare const getKey: (option: TagValue, keyId: string) => string;
2
+ export declare const getKey: <TData extends TagValue>(option: TData, keyId: string | undefined, getOptionLabel: (tagOption: TData) => string | number) => string;
@@ -1,7 +1,10 @@
1
- export const getKey = (option, keyId) => {
1
+ export const getKey = (option, keyId, getOptionLabel) => {
2
2
  if (typeof option === 'string') {
3
3
  return option;
4
4
  }
5
- const key = option[keyId];
6
- return typeof key === 'number' ? key.toString() : key;
5
+ if (keyId) {
6
+ const key = option[keyId];
7
+ return typeof key === 'number' ? key.toString() : key;
8
+ }
9
+ return getOptionLabel(option).toString();
7
10
  };
@@ -0,0 +1,2 @@
1
+ import { type Theme } from '../../../theme/types';
2
+ export declare const getTagWidth: (label: string | number, theme: Theme, isCounter?: boolean) => number;
@@ -0,0 +1,21 @@
1
+ import { MAX_TAG_WIDTH } from '../../Tag';
2
+ export const getTagWidth = (label, theme, isCounter = false) => {
3
+ /** 16px иконка и 2px padding */
4
+ const DELETE_ICON_WIDTH = 18;
5
+ const el = document.createElement('div');
6
+ el.textContent = label.toString();
7
+ el.style.visibility = 'hidden';
8
+ el.style.position = 'absolute';
9
+ el.style.display = 'inline-flex';
10
+ el.style.whiteSpace = 'nowrap';
11
+ el.style.padding = theme.spacing(0, 2);
12
+ el.style.paddingLeft = theme.spacing(2);
13
+ el.style.paddingRight = isCounter ? theme.spacing(2) : theme.microSpacing(1);
14
+ el.style.boxSizing = 'border-box';
15
+ document.body.appendChild(el);
16
+ const width = isCounter
17
+ ? el.getBoundingClientRect().width
18
+ : el.getBoundingClientRect().width + DELETE_ICON_WIDTH;
19
+ document.body.removeChild(el);
20
+ return Math.ceil(Math.min(width, parseInt(MAX_TAG_WIDTH, 10)));
21
+ };
@@ -0,0 +1 @@
1
+ export * from './getTagWidth';
@@ -0,0 +1 @@
1
+ export * from './getTagWidth';
@@ -1,2 +1,5 @@
1
1
  export { getElementByText } from './getElementByText';
2
2
  export { getKey } from './getKey';
3
+ export { getTagWidth } from './getTagWidth';
4
+ export { getAvailableWidth } from './getAvailableWidth';
5
+ export { calculateVisibleTagsCount } from './calculateVisibleTagsCount';
@@ -1,2 +1,5 @@
1
1
  export { getElementByText } from './getElementByText';
2
2
  export { getKey } from './getKey';
3
+ export { getTagWidth } from './getTagWidth';
4
+ export { getAvailableWidth } from './getAvailableWidth';
5
+ export { calculateVisibleTagsCount } from './calculateVisibleTagsCount';
@@ -4,7 +4,7 @@ import { FormHelperTextContent } from '../FormHelperText';
4
4
  import { classNames } from '../utils/classNames';
5
5
  import { textFieldClassnames } from './constants';
6
6
  import { StyledTextField } from './styles';
7
- export const TextField = forwardRef(({ success, error, helperText: helperTextProp, fullWidth = false, startAdornment, endAdornment, inputProps, InputProps, maxLength, trimmed = true, onBlur, hideHelperText = false, className, ...props }, ref) => {
7
+ export const TextField = forwardRef(({ success, error, helperText: helperTextProp, fullWidth = false, startAdornment, endAdornment, inputProps, InputProps, maxLength, trimmed = true, onBlur, hideHelperText = false, className, disabled, ...props }, ref) => {
8
8
  const color = useMemo(() => {
9
9
  if (success) {
10
10
  return 'success';
@@ -37,9 +37,10 @@ export const TextField = forwardRef(({ success, error, helperText: helperTextPro
37
37
  }
38
38
  onBlur?.(event);
39
39
  };
40
- const classes = useMemo(() => {
41
- return classNames(className, hideHelperText ? textFieldClassnames.hideHelperText : '');
42
- }, [className, hideHelperText]);
40
+ const classnames = useMemo(() => classNames(className, {
41
+ [textFieldClassnames.hideHelperText]: hideHelperText,
42
+ [textFieldClassnames.disabled]: disabled,
43
+ }), [className, hideHelperText, disabled]);
43
44
  return (_jsx(StyledTextField, { ref: ref, variant: "outlined", fullWidth: fullWidth, error: error, color: color, helperText: helperText, InputProps: {
44
45
  startAdornment,
45
46
  endAdornment,
@@ -47,5 +48,5 @@ export const TextField = forwardRef(({ success, error, helperText: helperTextPro
47
48
  }, inputProps: {
48
49
  maxLength,
49
50
  ...inputProps,
50
- }, onBlur: handleBlur, className: classes, ...props }));
51
+ }, onBlur: handleBlur, className: classnames, disabled: disabled, ...props }));
51
52
  });
@@ -1,3 +1,4 @@
1
1
  export declare const textFieldClassnames: {
2
2
  hideHelperText: string;
3
+ disabled: string;
3
4
  };
@@ -1,4 +1,5 @@
1
1
  import { createUIKitClassname } from '../utils/createUIKitClassname';
2
2
  export const textFieldClassnames = {
3
3
  hideHelperText: createUIKitClassname('text-field__helper-text_hidden'),
4
+ disabled: createUIKitClassname('text-field_disabled'),
4
5
  };
@@ -14,4 +14,8 @@ export const StyledTextField = styled(TextField) `
14
14
  }
15
15
  }
16
16
  }
17
+
18
+ &.${textFieldClassnames.disabled} {
19
+ pointer-events: none;
20
+ }
17
21
  `;
@@ -13,7 +13,7 @@ export const StyledDialogContent = styled(DialogContent, {
13
13
  gap: ${({ theme }) => theme.spacing(4)};
14
14
 
15
15
  width: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
16
- height: ${({ $size }) => ($size === 'md' ? '500px' : `calc(${DIALOG_SIZES[$size].minWidth} - 50px)`)};
16
+ height: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
17
17
 
18
18
  ${({ theme }) => theme.breakpoints.down('sm')} {
19
19
  width: auto;
@@ -25,5 +25,5 @@ export const OptionsModal = (props) => {
25
25
  }
26
26
  return _jsx(TreeList, { ...treeProps, ...treeListProps });
27
27
  };
28
- return (_jsxs(Dialog, { ...externalDialogProps, disableRestoreFocus: true, open: isOpen, ...modalProps, children: [_jsxs(StyledDialogContent, { children: [_jsx(SearchField, { fullWidth: true, ...searchFieldProps }), _jsx(Paper, { variant: "outlined", children: _jsx(TreeListWrapper, { children: renderComponent() }) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "text", ...cancelButtonProps, children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { ...confirmButtonProps, children: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" })] })] }));
28
+ return (_jsxs(Dialog, { ...externalDialogProps, disableRestoreFocus: true, open: isOpen, ...modalProps, children: [_jsxs(StyledDialogContent, { "$size": modalProps.size, children: [_jsx(SearchField, { fullWidth: true, ...searchFieldProps }), _jsx(Paper, { variant: "outlined", children: _jsx(TreeListWrapper, { children: renderComponent() }) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "text", ...cancelButtonProps, children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { ...confirmButtonProps, children: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" })] })] }));
29
29
  };
@@ -1,8 +1,12 @@
1
1
  /// <reference types="react" />
2
+ type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
2
3
  export declare const StyledDialogContent: import("../../styled").StyledComponent<import("../../DialogContent").DialogContentProps & {
3
4
  theme?: import("@emotion/react").Theme | undefined;
5
+ } & {
6
+ $size: Size;
4
7
  }, {}, {}>;
5
8
  export declare const TreeListWrapper: import("../../styled").StyledComponent<{
6
9
  theme?: import("@emotion/react").Theme | undefined;
7
10
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
8
11
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
12
+ export {};
@@ -1,13 +1,20 @@
1
+ import { DIALOG_SIZES } from '../../Dialog';
1
2
  import { DialogContent } from '../../DialogContent';
2
3
  import { styled } from '../../styled';
3
- export const StyledDialogContent = styled(DialogContent) `
4
+ export const StyledDialogContent = styled(DialogContent, {
5
+ shouldForwardProp: (prop) => !['$size'].includes(prop),
6
+ }) `
4
7
  display: grid;
5
8
  grid-template-columns: 100%;
6
9
  grid-template-rows: max-content 1fr;
7
10
  gap: ${({ theme }) => theme.spacing(4)};
8
11
 
9
- width: 500px;
10
- height: 500px;
12
+ width: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
13
+ height: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
14
+
15
+ ${({ theme }) => theme.breakpoints.down('sm')} {
16
+ width: auto;
17
+ }
11
18
  `;
12
19
  export const TreeListWrapper = styled.div `
13
20
  overflow: auto;
@@ -1,15 +1,17 @@
1
1
  import { type ButtonProps } from '../../../Button';
2
- import { type DialogProps } from '../../../Dialog';
2
+ import { type DialogProps, type DialogSize } from '../../../Dialog';
3
3
  import { type SearchFieldProps } from '../../../SearchField';
4
4
  import { type TreeListProps } from '../../../Tree';
5
5
  import { type OptionsModalProps } from '../types';
6
6
  type UseLogicResult = {
7
7
  isNoResult: boolean;
8
8
  searchFieldProps: SearchFieldProps;
9
- modalProps: Partial<DialogProps>;
9
+ modalProps: Partial<DialogProps> & {
10
+ size: DialogSize;
11
+ };
10
12
  treeListProps: TreeListProps;
11
13
  cancelButtonProps: ButtonProps;
12
14
  confirmButtonProps: ButtonProps;
13
15
  };
14
- export declare const useLogic: ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, }: OptionsModalProps) => UseLogicResult;
16
+ export declare const useLogic: ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, size, }: OptionsModalProps) => UseLogicResult;
15
17
  export {};
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useMemo, useState, } from 'react';
2
2
  import { deepMap } from '../../../utils/array';
3
3
  import { findInTree } from './utils';
4
- export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, }) => {
4
+ export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, size = 'md', }) => {
5
5
  const [value, setValue] = useState(initialValue);
6
6
  const [searchValue, setSearchValue] = useState();
7
7
  useEffect(() => {
@@ -47,6 +47,7 @@ export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, opti
47
47
  isNoResult,
48
48
  modalProps: {
49
49
  onClose: handleClose,
50
+ size,
50
51
  },
51
52
  searchFieldProps: {
52
53
  value: searchValue,
@@ -9,7 +9,7 @@ import { IconWrapper, StyledTagsList, StyledTextField } from './styles';
9
9
  import { useLogic } from './useLogic';
10
10
  const ClearButton = ({ disabled, onClick }) => (_jsx(IconButton, { variant: "text", color: "grey", disabled: disabled, onClick: onClick, title: CLEAR_TEXT, "aria-label": CLEAR_TEXT, children: _jsx(CrossOutlineMd, {}) }));
11
11
  export const Input = forwardRef(({ disabled, onChange: propsOnChange, value, inputRef, hideHelperText = false, onClick, isLoading, ...restProps }, forwardedRef) => {
12
- const { isVisibleClearButton, onChange, isVisibleTagsList, textFieldProps, onClearAll, } = useLogic({
12
+ const { isVisibleClearButton, isVisibleTagsList, onChange, textFieldProps, onClearAll, } = useLogic({
13
13
  inputRef,
14
14
  value,
15
15
  onChange: propsOnChange,
@@ -13,7 +13,7 @@ export const StyledDialogContent = styled(DialogContent, {
13
13
  gap: ${({ theme }) => theme.spacing(4)};
14
14
 
15
15
  width: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
16
- height: ${({ $size }) => ($size === 'md' ? '500px' : `calc(${DIALOG_SIZES[$size].minWidth} - 50px)`)};
16
+ height: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
17
17
 
18
18
  ${({ theme }) => theme.breakpoints.down('sm')} {
19
19
  width: auto;
@@ -25,5 +25,5 @@ export const OptionsModal = (props) => {
25
25
  }
26
26
  return (_jsx(TreeLikeList, { isConfirmChildrenSelection: isConfirmChildrenSelection, ...treeProps, ...treeLikeListProps }));
27
27
  };
28
- return (_jsxs(Dialog, { ...externalDialogProps, disableRestoreFocus: true, open: isOpen, ...modalProps, children: [_jsxs(StyledDialogContent, { children: [_jsx(SearchField, { fullWidth: true, ...searchFieldProps }), _jsx(Paper, { variant: "outlined", children: _jsx(TreeListWrapper, { children: renderComponent() }) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "text", ...cancelButtonProps, children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { ...confirmButtonProps, children: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" })] })] }));
28
+ return (_jsxs(Dialog, { ...externalDialogProps, disableRestoreFocus: true, open: isOpen, ...modalProps, children: [_jsxs(StyledDialogContent, { "$size": modalProps.size, children: [_jsx(SearchField, { fullWidth: true, ...searchFieldProps }), _jsx(Paper, { variant: "outlined", children: _jsx(TreeListWrapper, { children: renderComponent() }) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "text", ...cancelButtonProps, children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { ...confirmButtonProps, children: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C" })] })] }));
29
29
  };
@@ -1,8 +1,12 @@
1
1
  /// <reference types="react" />
2
+ type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
2
3
  export declare const StyledDialogContent: import("../../styled").StyledComponent<import("../../DialogContent").DialogContentProps & {
3
4
  theme?: import("@emotion/react").Theme | undefined;
5
+ } & {
6
+ $size: Size;
4
7
  }, {}, {}>;
5
8
  export declare const TreeListWrapper: import("../../styled").StyledComponent<{
6
9
  theme?: import("@emotion/react").Theme | undefined;
7
10
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
8
11
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
12
+ export {};
@@ -1,13 +1,20 @@
1
+ import { DIALOG_SIZES } from '../../Dialog';
1
2
  import { DialogContent } from '../../DialogContent';
2
3
  import { styled } from '../../styled';
3
- export const StyledDialogContent = styled(DialogContent) `
4
+ export const StyledDialogContent = styled(DialogContent, {
5
+ shouldForwardProp: (prop) => !['$size'].includes(prop),
6
+ }) `
4
7
  display: grid;
5
8
  grid-template-columns: 100%;
6
9
  grid-template-rows: max-content 1fr;
7
10
  gap: ${({ theme }) => theme.spacing(4)};
8
11
 
9
- width: 100%;
10
- height: 500px;
12
+ width: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
13
+ height: ${({ $size }) => DIALOG_SIZES[$size].minWidth};
14
+
15
+ ${({ theme }) => theme.breakpoints.down('sm')} {
16
+ width: auto;
17
+ }
11
18
  `;
12
19
  export const TreeListWrapper = styled.div `
13
20
  overflow: auto;
@@ -1,5 +1,5 @@
1
1
  import { type ButtonProps } from '../../../Button';
2
- import { type DialogProps } from '../../../Dialog';
2
+ import { type DialogProps, type DialogSize } from '../../../Dialog';
3
3
  import { type SearchFieldProps } from '../../../SearchField';
4
4
  import { type TreeLikeListProps } from '../../../TreeLikeList';
5
5
  import { type OptionsModalProps } from '../types';
@@ -7,10 +7,12 @@ type UseLogicParams = OptionsModalProps;
7
7
  type UseLogicResult = {
8
8
  isNoResult: boolean;
9
9
  searchFieldProps: SearchFieldProps;
10
- modalProps: Partial<DialogProps>;
10
+ modalProps: Partial<DialogProps> & {
11
+ size: DialogSize;
12
+ };
11
13
  treeLikeListProps: TreeLikeListProps;
12
14
  cancelButtonProps: ButtonProps;
13
15
  confirmButtonProps: ButtonProps;
14
16
  };
15
- export declare const useLogic: ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, }: UseLogicParams) => UseLogicResult;
17
+ export declare const useLogic: ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, size, }: UseLogicParams) => UseLogicResult;
16
18
  export {};
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useMemo, useState, } from 'react';
2
2
  import { deepMap } from '../../../utils/array';
3
3
  import { findInTree } from './utils';
4
- export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, }) => {
4
+ export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, options, filterOptions, onChange, onClose, size = 'md', }) => {
5
5
  const [value, setValue] = useState(initialValue);
6
6
  const [searchValue, setSearchValue] = useState();
7
7
  useEffect(() => {
@@ -47,6 +47,7 @@ export const useLogic = ({ isOpen, isLoading, isLoadingError, initialValue, opti
47
47
  isNoResult,
48
48
  modalProps: {
49
49
  onClose: handleClose,
50
+ size,
50
51
  },
51
52
  searchFieldProps: {
52
53
  value: searchValue,
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { type AutocompleteRenderInputParams } from './types';
3
- export declare const Autocomplete: <TAutocompleteValueProps, TMultiple extends boolean, TDisableClearable extends boolean, TFreeSolo extends boolean>(props: Omit<import("..").WithoutEmotionSpecific<import("@mui/material/Autocomplete/Autocomplete").AutocompleteProps<TAutocompleteValueProps, TMultiple, TDisableClearable, TFreeSolo, "div">>, "size" | "clearText" | "closeText" | "noOptionsText" | "openText" | "renderInput"> & Pick<import("../TextField").TextFieldProps, "label" | "success" | "error" | "placeholder" | "required" | "inputRef" | "helperText" | "inputProps"> & {
3
+ export declare const Autocomplete: <TAutocompleteValueProps, TMultiple extends boolean, TDisableClearable extends boolean, TFreeSolo extends boolean>(props: Omit<import("..").WithoutEmotionSpecific<import("@mui/material").AutocompleteProps<TAutocompleteValueProps, TMultiple, TDisableClearable, TFreeSolo, "div">>, "size" | "clearText" | "closeText" | "noOptionsText" | "openText" | "renderInput"> & Pick<import("../TextField").TextFieldProps, "label" | "success" | "error" | "placeholder" | "required" | "inputRef" | "helperText" | "inputProps"> & {
4
4
  renderInput?: ((props: Omit<import("..").WithoutEmotionSpecific<import("@mui/material").TextFieldProps>, "color" | "select" | "margin" | "variant" | "multiline" | "SelectProps"> & {
5
5
  success?: boolean | undefined;
6
6
  startAdornment?: import("react").ReactNode;
@@ -14,7 +14,7 @@ const Checkbox_1 = require("../Checkbox");
14
14
  const forwardRefWithGeneric_1 = require("../forwardRefWithGeneric");
15
15
  const Loader_1 = require("../Loader");
16
16
  const OverflowTypography_1 = require("../OverflowTypography");
17
- const Tag_1 = require("../Tag");
17
+ const TagsList_1 = require("../TagsList");
18
18
  const TextField_1 = require("../TextField");
19
19
  const classNames_1 = require("../utils/classNames");
20
20
  const constants_1 = require("./constants");
@@ -22,14 +22,51 @@ const styles_1 = require("./styles");
22
22
  const useLogic_1 = require("./useLogic");
23
23
  const AutocompleteInner = (props, ref) => {
24
24
  const { isValueEmpty, isPopperVisible, autocompleteProps } = (0, useLogic_1.useLogic)(props);
25
- const { required, success, error, label, getOptionLabel, helperText, inputRef, multiple, size = 'medium', placeholder = constants_1.DEFAULT_PLACEHOLDER, overflowOption, closeText = 'Закрыть', openText = 'Открыть', clearText = 'Очистить', loadingText = (0, jsx_runtime_1.jsx)(Loader_1.Loader, {}), isLoadedDataError, loadedDataError, noOptionsText, autoHighlight, renderInput: externalRenderInput, renderTags: externalRenderTags, renderOption: externalRenderOption, inputProps, hideHelperText = false, loading, ...restProps } = props;
25
+ const inputBaseRef = (0, react_1.useRef)(null);
26
+ const { required, success, error, label, getOptionLabel, helperText, inputRef, multiple, size = 'medium', placeholder = constants_1.DEFAULT_PLACEHOLDER, overflowOption, closeText = 'Закрыть', openText = 'Открыть', clearText = 'Очистить', loadingText = (0, jsx_runtime_1.jsx)(Loader_1.Loader, {}), isLoadedDataError, loadedDataError, noOptionsText, autoHighlight, renderInput: externalRenderInput, renderTags: externalRenderTags, renderOption: externalRenderOption, inputProps, hideHelperText = false, loading, value, onChange, ...restProps } = props;
26
27
  const renderInput = (0, react_1.useCallback)((inputParams) => {
28
+ const createStartAdornment = () => {
29
+ if (!multiple || !Array.isArray(value)) {
30
+ return null;
31
+ }
32
+ const tagsListElement = ((0, jsx_runtime_1.jsx)(TagsList_1.TagsList, { data: value, getOptionLabel: (option) => getOptionLabel?.(option) ??
33
+ option.toString(), inputContainerRef: inputBaseRef, reservedWidth: constants_1.INPUT_MIN_WIDTH, onChange: (tagValues) => {
34
+ if (!onChange) {
35
+ return;
36
+ }
37
+ const syntheticEvent = {
38
+ type: 'change',
39
+ target: { value: tagValues },
40
+ currentTarget: { value: tagValues },
41
+ };
42
+ const reason = 'removeOption';
43
+ onChange(syntheticEvent, tagValues, reason);
44
+ } }));
45
+ return tagsListElement;
46
+ };
27
47
  const generalInputParams = {
28
48
  ...inputParams,
29
49
  inputProps: {
30
50
  ...inputParams.inputProps,
31
51
  className: (0, classNames_1.classNames)(inputParams?.inputProps?.className, inputProps?.className),
32
52
  },
53
+ InputProps: {
54
+ ...inputParams.InputProps,
55
+ ref: (element) => {
56
+ inputBaseRef.current = element;
57
+ const orig = inputParams.InputProps?.ref;
58
+ if (typeof orig === 'function') {
59
+ orig(element);
60
+ }
61
+ else if (orig) {
62
+ orig.current = element;
63
+ }
64
+ },
65
+ // Если есть externalRenderTags, используем renderTags(mui использует inputParams.InputProps?.startAdornment)
66
+ startAdornment: externalRenderTags
67
+ ? inputParams.InputProps?.startAdornment
68
+ : createStartAdornment(),
69
+ },
33
70
  inputRef,
34
71
  required,
35
72
  placeholder: isValueEmpty ? placeholder : '',
@@ -46,7 +83,9 @@ const AutocompleteInner = (props, ref) => {
46
83
  return (0, jsx_runtime_1.jsx)(TextField_1.TextField, { ...generalInputParams });
47
84
  }, [
48
85
  isValueEmpty,
86
+ value,
49
87
  externalRenderInput,
88
+ externalRenderTags,
50
89
  inputRef,
51
90
  required,
52
91
  placeholder,
@@ -56,6 +95,9 @@ const AutocompleteInner = (props, ref) => {
56
95
  helperText,
57
96
  size,
58
97
  hideHelperText,
98
+ multiple,
99
+ getOptionLabel,
100
+ onChange,
59
101
  ]);
60
102
  const renderOption = (0, react_1.useCallback)((optionProps, option, optionState, ownerState) => {
61
103
  if (externalRenderOption) {
@@ -65,26 +107,22 @@ const AutocompleteInner = (props, ref) => {
65
107
  const { key, ...restOptionProps } = optionProps;
66
108
  return ((0, jsx_runtime_1.jsxs)(styles_1.StyledMenuItem, { selected: isSelected, ...restOptionProps, children: [multiple && ((0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { role: "menuitemcheckbox", checked: isSelected }) })), (0, jsx_runtime_1.jsx)(OverflowTypography_1.OverflowTypography, { rowsCount: constants_1.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT, ...overflowOption, children: optionProps.key })] }, key));
67
109
  }, [multiple, overflowOption, externalRenderOption]);
68
- const renderTags = (0, react_1.useCallback)((tags, getTagProps, ownerSate) => {
69
- if (externalRenderTags) {
70
- return externalRenderTags(tags, getTagProps, ownerSate);
71
- }
72
- return tags.map((tag, index) => {
73
- const title = getOptionLabel?.(tag) || '';
74
- const { key, ...tagProps } = getTagProps({ index });
75
- return ((0, jsx_runtime_1.jsx)(Tag_1.Tag, { variant: "light", color: "grey", label: title, ...tagProps }, key));
76
- });
77
- }, [getOptionLabel, externalRenderTags]);
78
110
  const renderPopper = (0, react_1.useCallback)((popperProps) => {
79
111
  if (!isPopperVisible) {
80
112
  return null;
81
113
  }
82
114
  return (0, jsx_runtime_1.jsx)(Popper_1.default, { ...popperProps });
83
115
  }, [isPopperVisible]);
116
+ const renderTags = (0, react_1.useCallback)((tags, getTagProps, ownerState) => {
117
+ if (externalRenderTags) {
118
+ return externalRenderTags(tags, getTagProps, ownerState);
119
+ }
120
+ return null;
121
+ }, [externalRenderTags]);
84
122
  return ((0, jsx_runtime_1.jsx)(styles_1.StyledAutocomplete, { ...restProps, ref: ref, size: size, clearText: clearText, closeText: !loading ? closeText : '', openText: !loading ? openText : '', loadingText: loadingText, multiple: multiple, disableCloseOnSelect: multiple, clearIcon: (0, jsx_runtime_1.jsx)(CrossOutlineMd_1.CrossOutlineMd, {}), loading: loading, popupIcon: loading ? (0, jsx_runtime_1.jsx)(Loader_1.Loader, { color: "primary", size: "small" }) : (0, jsx_runtime_1.jsx)(DownOutlineMd_1.DownOutlineMd, {}), forcePopupIcon: true, slotProps: {
85
123
  popper: {
86
124
  component: renderPopper,
87
125
  },
88
- }, getOptionLabel: getOptionLabel, renderInput: renderInput, renderTags: renderTags, renderOption: renderOption, ...autocompleteProps }));
126
+ }, getOptionLabel: getOptionLabel, renderInput: renderInput, renderTags: renderTags, renderOption: renderOption, value: value, onChange: onChange, ...autocompleteProps }));
89
127
  };
90
128
  exports.Autocomplete = (0, forwardRefWithGeneric_1.forwardRefWithGeneric)(AutocompleteInner);
@@ -1,2 +1,8 @@
1
1
  export declare const DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = 2;
2
+ export declare const INPUT_MIN_WIDTH = 110;
2
3
  export declare const DEFAULT_PLACEHOLDER = "\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u0432\u0432\u043E\u0434\u0438\u0442\u044C \u0434\u043B\u044F \u043F\u043E\u0438\u0441\u043A\u0430";
4
+ export declare const autocompleteClassnames: {
5
+ root: string;
6
+ multiple: string;
7
+ emptyValue: string;
8
+ };
@@ -1,5 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_PLACEHOLDER = exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = void 0;
3
+ exports.autocompleteClassnames = exports.DEFAULT_PLACEHOLDER = exports.INPUT_MIN_WIDTH = exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = void 0;
4
+ const createUIKitClassname_1 = require("../utils/createUIKitClassname");
4
5
  exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = 2;
6
+ exports.INPUT_MIN_WIDTH = 110;
5
7
  exports.DEFAULT_PLACEHOLDER = 'Начните вводить для поиска';
8
+ exports.autocompleteClassnames = {
9
+ root: (0, createUIKitClassname_1.createUIKitClassname)('autocomplete'),
10
+ multiple: (0, createUIKitClassname_1.createUIKitClassname)('autocomplete_multiple'),
11
+ emptyValue: (0, createUIKitClassname_1.createUIKitClassname)('autocomplete_empty-value'),
12
+ };
@@ -31,6 +31,7 @@ const InputBase_1 = require("@mui/material/InputBase");
31
31
  const MenuItem_1 = require("../MenuItem");
32
32
  const SvgIcon_1 = require("../SvgIcon");
33
33
  const styled_1 = require("../styled");
34
+ const constants_1 = require("./constants");
34
35
  exports.StyledMenuItem = (0, styled_1.styled)(MenuItem_1.MenuItem) `
35
36
  max-height: ${({ theme }) => theme.spacing(13)};
36
37
 
@@ -49,5 +50,18 @@ exports.StyledAutocomplete = (0, styled_1.styled)(Autocomplete_1.default) `
49
50
 
50
51
  & .${Autocomplete_1.autocompleteClasses.endAdornment} .${IconButton_1.iconButtonClasses.root}:hover {
51
52
  background-color: ${({ loading, theme }) => (loading ? 'transparent' : theme.palette.grey[100])};
52
- }
53
+ }
54
+
55
+ &:not(.${constants_1.autocompleteClassnames.emptyValue}) .${InputBase_1.inputBaseClasses.root} {
56
+ gap: ${({ theme }) => theme.spacing(3)};
57
+ }
58
+
59
+ & .${Autocomplete_1.autocompleteClasses.inputRoot} .${InputBase_1.inputBaseClasses.input} {
60
+ min-width: ${constants_1.INPUT_MIN_WIDTH}px;
61
+ }
62
+
63
+ & .${Autocomplete_1.autocompleteClasses.inputRoot} {
64
+ flex-wrap: nowrap;
65
+ }
66
+
53
67
  `;
@@ -2,10 +2,11 @@ import { type AutocompleteInputChangeReason } from '@mui/material/Autocomplete';
2
2
  import { type SyntheticEvent } from 'react';
3
3
  import { type AutocompleteProps } from '../types';
4
4
  type UseLogicParams<TAutocompleteValueProps, TMultiple extends boolean, TDisableClearable extends boolean, TFreeSolo extends boolean> = AutocompleteProps<TAutocompleteValueProps, TMultiple, TDisableClearable, TFreeSolo>;
5
- export declare const useLogic: <TAutocompleteValueProps, TMultiple extends boolean, TDisableClearable extends boolean, TFreeSolo extends boolean>({ value, isOptionEqualToValue: externalOptionEqualToValue, autoHighlight, freeSolo, options, loading, isLoadedDataError, loadedDataError, noOptionsText, onInputChange, }: UseLogicParams<TAutocompleteValueProps, TMultiple, TDisableClearable, TFreeSolo>) => {
5
+ export declare const useLogic: <TAutocompleteValueProps, TMultiple extends boolean, TDisableClearable extends boolean, TFreeSolo extends boolean>({ value, isOptionEqualToValue: externalOptionEqualToValue, autoHighlight, freeSolo, options, multiple, className, loading, isLoadedDataError, loadedDataError, noOptionsText, onInputChange, }: UseLogicParams<TAutocompleteValueProps, TMultiple, TDisableClearable, TFreeSolo>) => {
6
6
  isValueEmpty: boolean;
7
7
  isPopperVisible: boolean | undefined;
8
8
  autocompleteProps: {
9
+ className: string;
9
10
  isOptionEqualToValue: (option: TAutocompleteValueProps, currentValue: TAutocompleteValueProps) => boolean;
10
11
  autoHighlight: boolean;
11
12
  noOptionsText: string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | null;
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useLogic = void 0;
4
4
  const react_1 = require("react");
5
+ const classNames_1 = require("../../utils/classNames");
6
+ const constants_1 = require("../constants");
5
7
  const utils_1 = require("./utils");
6
- const useLogic = ({ value, isOptionEqualToValue: externalOptionEqualToValue, autoHighlight = true, freeSolo, options, loading, isLoadedDataError, loadedDataError = 'Ошибка загрузки данных', noOptionsText = 'Нет данных', onInputChange, }) => {
8
+ const useLogic = ({ value, isOptionEqualToValue: externalOptionEqualToValue, autoHighlight = true, freeSolo, options, multiple, className, loading, isLoadedDataError, loadedDataError = 'Ошибка загрузки данных', noOptionsText = 'Нет данных', onInputChange, }) => {
7
9
  const [innerInputValue, setInnerInputValue] = (0, react_1.useState)('');
8
10
  const isValueEmpty = (0, utils_1.checkIsInputEmpty)(value);
9
11
  const isInnerInputValueNotEmpty = innerInputValue.length >= 1;
@@ -24,10 +26,17 @@ const useLogic = ({ value, isOptionEqualToValue: externalOptionEqualToValue, aut
24
26
  setInnerInputValue(currentValue);
25
27
  }
26
28
  };
29
+ const classnames = (0, react_1.useMemo)(() => {
30
+ return (0, classNames_1.classNames)(className, constants_1.autocompleteClassnames.root, {
31
+ [constants_1.autocompleteClassnames.multiple]: multiple,
32
+ [constants_1.autocompleteClassnames.emptyValue]: isValueEmpty,
33
+ });
34
+ }, [multiple, isValueEmpty]);
27
35
  return {
28
36
  isValueEmpty,
29
37
  isPopperVisible,
30
38
  autocompleteProps: {
39
+ className: classnames,
31
40
  isOptionEqualToValue,
32
41
  autoHighlight: freeSolo ? false : autoHighlight,
33
42
  noOptionsText: isLoadedDataError ? loadedDataError : noOptionsText,
@@ -20,7 +20,7 @@ export type TagProps = {
20
20
  /**
21
21
  * Хендлер клика по тегу
22
22
  */
23
- onClick: (value: MouseEvent<HTMLDivElement>) => void;
23
+ onClick?: (value: MouseEvent<HTMLDivElement>) => void;
24
24
  /**
25
25
  * Название класса, применяется к корневому компоненту
26
26
  */
@@ -0,0 +1 @@
1
+ export declare const MAX_TAG_WIDTH = "246px";
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_TAG_WIDTH = void 0;
4
+ exports.MAX_TAG_WIDTH = '246px';
@@ -1 +1,2 @@
1
1
  export * from './Tag';
2
+ export * from './constants';
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Tag"), exports);
18
+ __exportStar(require("./constants"), exports);
@@ -6,6 +6,8 @@ const Tag_1 = require("../../Tag");
6
6
  exports.StyledTag = (0, styled_1.styled)(Tag_1.Tag, {
7
7
  shouldForwardProp: (prop) => prop !== '$shrinks',
8
8
  }) `
9
+ overflow: hidden;
10
+
9
11
  /* 4em ширина необходима для отображения двух букв и избежания перекрытия кнопкой сброса всего текста тега */
10
12
  min-width: ${({ $shrinks }) => ($shrinks ? 'calc(2em + 20px)' : 'unset')};
11
13
  max-width: 246px;