@astral/ui 4.73.0 → 4.74.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.
@@ -70,7 +70,9 @@ export const HeaderSection = styled.div `
70
70
  align-items: center;
71
71
 
72
72
  ${({ theme }) => theme.breakpoints.down('sm')} {
73
- flex-grow: 1;
73
+ flex-shrink: 0;
74
+
75
+ min-width: 0;
74
76
  }
75
77
  `;
76
78
  export const HeaderContentSection = styled(HeaderSection) `
@@ -78,6 +80,8 @@ export const HeaderContentSection = styled(HeaderSection) `
78
80
  justify-content: flex-end;
79
81
 
80
82
  ${({ theme }) => theme.breakpoints.down('sm')} {
83
+ flex-grow: 1;
84
+ flex-shrink: unset;
81
85
  gap: ${({ theme }) => theme.spacing(2)};
82
86
 
83
87
  &.${dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
@@ -119,6 +123,7 @@ export const HeaderContent = styled.div `
119
123
  justify-content: space-between;
120
124
 
121
125
  ${({ theme }) => theme.breakpoints.down('sm')} {
126
+ width: 100%;
122
127
  padding: 0;
123
128
  }
124
129
  `;
@@ -127,6 +132,17 @@ export const HeaderContent = styled.div `
127
132
  */
128
133
  export const PriorityFeatureWrapper = styled.div `
129
134
  ${({ theme }) => theme.breakpoints.down('sm')} {
135
+ display: flex;
136
+ justify-content: flex-end;
137
+
138
+ min-width: 0;
139
+
140
+ &.${dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
141
+ & .${menuOrganizationClassnames.button} {
142
+ padding: ${({ theme }) => theme.spacing(2, 0)};
143
+ }
144
+ }
145
+
130
146
  &.${dashboardLayoutHeaderClassnames.featureInSidebar} {
131
147
  position: absolute;
132
148
  z-index: ${({ theme }) => theme.zIndex.appBar - 1};
@@ -188,6 +204,10 @@ export const PriorityFeatureWrapper = styled.div `
188
204
  }
189
205
 
190
206
  &.${dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
207
+ & .${menuOrganizationClassnames.button} {
208
+ padding: ${({ theme }) => theme.spacing(2, 0)};
209
+ }
210
+
191
211
  & .${dashboardLayoutHeaderClassnames.profile} {
192
212
  display: block;
193
213
  flex-grow: 1;
@@ -27,6 +27,7 @@ export const StyledButton = styled(Button) `
27
27
  justify-content: space-between;
28
28
 
29
29
  width: 100%;
30
+ min-width: unset;
30
31
  max-width: unset;
31
32
 
32
33
  border-radius: 0;
@@ -48,6 +49,8 @@ export const Container = styled.div `
48
49
  display: flex;
49
50
  flex-direction: column;
50
51
 
52
+ /* Позволяет элементу сжиматься до ширины контейнера */
53
+ min-width: 0;
51
54
  max-width: 260px;
52
55
  `;
53
56
  export const StyledTypography = styled(Typography, {
@@ -12,4 +12,13 @@ export type SearchFieldProps = Omit<TextFieldProps, 'startAdornment' | 'endAdorn
12
12
  * Если true, будет отображаться лоадер в конце инпута
13
13
  */
14
14
  isLoading?: boolean;
15
+ /**
16
+ * Если true, вводимое пользователем значение будет применяться с debounce задержкой
17
+ */
18
+ isDebounced?: boolean;
19
+ /**
20
+ * Время, на которое будет откладываться вызов onChange при вводе символов в инпут
21
+ * @default 250
22
+ */
23
+ debounceDelay?: number;
15
24
  };
@@ -15,5 +15,5 @@ type UseLogicResult = {
15
15
  onBlur: (event: FocusEvent<HTMLInputElement>) => void;
16
16
  hideHelperText?: boolean;
17
17
  };
18
- export declare const useLogic: ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder, inputComponent, hideHelperText, ...restProps }: SearchFieldProps) => UseLogicResult;
18
+ export declare const useLogic: ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder, inputComponent, hideHelperText, isDebounced, debounceDelay, ...restProps }: SearchFieldProps) => UseLogicResult;
19
19
  export {};
@@ -1,7 +1,9 @@
1
- import { useEffect, useState, } from 'react';
1
+ import { useCallback, useEffect, useMemo, useState, } from 'react';
2
2
  import { useFirstMountState } from '../../useFirstMountState';
3
3
  import { useForwardedRef } from '../../useForwardedRef';
4
- export const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder = 'Поиск', inputComponent, hideHelperText = true, ...restProps }) => {
4
+ import { debounce } from '../../utils/debounce';
5
+ const DEFAULT_DEBOUNCE_TIME = 250;
6
+ export const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder = 'Поиск', inputComponent, hideHelperText = true, isDebounced, debounceDelay = DEFAULT_DEBOUNCE_TIME, ...restProps }) => {
5
7
  const inputRef = useForwardedRef(externalInputRef);
6
8
  const [internalValue, setInternalValue] = useState(defaultValue || value || '');
7
9
  const isFirstRender = useFirstMountState();
@@ -13,13 +15,29 @@ export const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRe
13
15
  setInternalValue('');
14
16
  }
15
17
  }, [value]);
18
+ const createChangeEvent = useCallback((eventValue) => ({
19
+ target: {
20
+ value: eventValue,
21
+ },
22
+ }), []);
23
+ const debouncedOnChange = useMemo(() => isDebounced
24
+ ? debounce((targetValue) => propsOnChange?.(createChangeEvent(targetValue)), {
25
+ waitMs: debounceDelay,
26
+ }).call
27
+ : () => undefined, [createChangeEvent, propsOnChange, isDebounced]);
16
28
  const onChange = (event) => {
17
- const trimmedEvent = {
18
- ...event,
19
- target: { ...event.target, value: event.target.value.trim() },
20
- };
21
- propsOnChange?.(trimmedEvent);
22
- setInternalValue(event.target.value);
29
+ const originalValue = event.target.value;
30
+ setInternalValue(originalValue);
31
+ if (!propsOnChange) {
32
+ return;
33
+ }
34
+ const trimmedValue = originalValue.trim();
35
+ return isDebounced
36
+ ? debouncedOnChange(trimmedValue)
37
+ : propsOnChange({
38
+ ...event,
39
+ target: { ...event.target, value: trimmedValue },
40
+ });
23
41
  };
24
42
  const onBlur = (event) => {
25
43
  propsOnBlur?.(event);
@@ -27,15 +45,9 @@ export const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRe
27
45
  setInternalValue(value);
28
46
  }
29
47
  };
30
- const createChangeEvent = (eventValue) => {
31
- return {
32
- target: {
33
- value: eventValue,
34
- },
35
- };
36
- };
37
48
  const onClearValue = () => {
38
- onChange?.(createChangeEvent(''));
49
+ setInternalValue('');
50
+ propsOnChange?.(createChangeEvent(''));
39
51
  inputRef.current.value = '';
40
52
  inputRef.current?.focus();
41
53
  };
@@ -73,7 +73,9 @@ exports.HeaderSection = styled_1.styled.div `
73
73
  align-items: center;
74
74
 
75
75
  ${({ theme }) => theme.breakpoints.down('sm')} {
76
- flex-grow: 1;
76
+ flex-shrink: 0;
77
+
78
+ min-width: 0;
77
79
  }
78
80
  `;
79
81
  exports.HeaderContentSection = (0, styled_1.styled)(exports.HeaderSection) `
@@ -81,6 +83,8 @@ exports.HeaderContentSection = (0, styled_1.styled)(exports.HeaderSection) `
81
83
  justify-content: flex-end;
82
84
 
83
85
  ${({ theme }) => theme.breakpoints.down('sm')} {
86
+ flex-grow: 1;
87
+ flex-shrink: unset;
84
88
  gap: ${({ theme }) => theme.spacing(2)};
85
89
 
86
90
  &.${constants_6.dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
@@ -122,6 +126,7 @@ exports.HeaderContent = styled_1.styled.div `
122
126
  justify-content: space-between;
123
127
 
124
128
  ${({ theme }) => theme.breakpoints.down('sm')} {
129
+ width: 100%;
125
130
  padding: 0;
126
131
  }
127
132
  `;
@@ -130,6 +135,17 @@ exports.HeaderContent = styled_1.styled.div `
130
135
  */
131
136
  exports.PriorityFeatureWrapper = styled_1.styled.div `
132
137
  ${({ theme }) => theme.breakpoints.down('sm')} {
138
+ display: flex;
139
+ justify-content: flex-end;
140
+
141
+ min-width: 0;
142
+
143
+ &.${constants_6.dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
144
+ & .${constants_1.menuOrganizationClassnames.button} {
145
+ padding: ${({ theme }) => theme.spacing(2, 0)};
146
+ }
147
+ }
148
+
133
149
  &.${constants_6.dashboardLayoutHeaderClassnames.featureInSidebar} {
134
150
  position: absolute;
135
151
  z-index: ${({ theme }) => theme.zIndex.appBar - 1};
@@ -191,6 +207,10 @@ exports.PriorityFeatureWrapper = styled_1.styled.div `
191
207
  }
192
208
 
193
209
  &.${constants_6.dashboardLayoutHeaderClassnames.priorityFeatureMenuOrg} {
210
+ & .${constants_1.menuOrganizationClassnames.button} {
211
+ padding: ${({ theme }) => theme.spacing(2, 0)};
212
+ }
213
+
194
214
  & .${constants_6.dashboardLayoutHeaderClassnames.profile} {
195
215
  display: block;
196
216
  flex-grow: 1;
@@ -30,6 +30,7 @@ exports.StyledButton = (0, styled_1.styled)(Button_1.Button) `
30
30
  justify-content: space-between;
31
31
 
32
32
  width: 100%;
33
+ min-width: unset;
33
34
  max-width: unset;
34
35
 
35
36
  border-radius: 0;
@@ -51,6 +52,8 @@ exports.Container = styled_1.styled.div `
51
52
  display: flex;
52
53
  flex-direction: column;
53
54
 
55
+ /* Позволяет элементу сжиматься до ширины контейнера */
56
+ min-width: 0;
54
57
  max-width: 260px;
55
58
  `;
56
59
  exports.StyledTypography = (0, styled_1.styled)(Typography_1.Typography, {
@@ -12,4 +12,13 @@ export type SearchFieldProps = Omit<TextFieldProps, 'startAdornment' | 'endAdorn
12
12
  * Если true, будет отображаться лоадер в конце инпута
13
13
  */
14
14
  isLoading?: boolean;
15
+ /**
16
+ * Если true, вводимое пользователем значение будет применяться с debounce задержкой
17
+ */
18
+ isDebounced?: boolean;
19
+ /**
20
+ * Время, на которое будет откладываться вызов onChange при вводе символов в инпут
21
+ * @default 250
22
+ */
23
+ debounceDelay?: number;
15
24
  };
@@ -15,5 +15,5 @@ type UseLogicResult = {
15
15
  onBlur: (event: FocusEvent<HTMLInputElement>) => void;
16
16
  hideHelperText?: boolean;
17
17
  };
18
- export declare const useLogic: ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder, inputComponent, hideHelperText, ...restProps }: SearchFieldProps) => UseLogicResult;
18
+ export declare const useLogic: ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder, inputComponent, hideHelperText, isDebounced, debounceDelay, ...restProps }: SearchFieldProps) => UseLogicResult;
19
19
  export {};
@@ -4,7 +4,9 @@ exports.useLogic = void 0;
4
4
  const react_1 = require("react");
5
5
  const useFirstMountState_1 = require("../../useFirstMountState");
6
6
  const useForwardedRef_1 = require("../../useForwardedRef");
7
- const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder = 'Поиск', inputComponent, hideHelperText = true, ...restProps }) => {
7
+ const debounce_1 = require("../../utils/debounce");
8
+ const DEFAULT_DEBOUNCE_TIME = 250;
9
+ const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: externalInputRef, disabled, onBlur: propsOnBlur, fullWidth, isLoading, placeholder = 'Поиск', inputComponent, hideHelperText = true, isDebounced, debounceDelay = DEFAULT_DEBOUNCE_TIME, ...restProps }) => {
8
10
  const inputRef = (0, useForwardedRef_1.useForwardedRef)(externalInputRef);
9
11
  const [internalValue, setInternalValue] = (0, react_1.useState)(defaultValue || value || '');
10
12
  const isFirstRender = (0, useFirstMountState_1.useFirstMountState)();
@@ -16,13 +18,29 @@ const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: exte
16
18
  setInternalValue('');
17
19
  }
18
20
  }, [value]);
21
+ const createChangeEvent = (0, react_1.useCallback)((eventValue) => ({
22
+ target: {
23
+ value: eventValue,
24
+ },
25
+ }), []);
26
+ const debouncedOnChange = (0, react_1.useMemo)(() => isDebounced
27
+ ? (0, debounce_1.debounce)((targetValue) => propsOnChange?.(createChangeEvent(targetValue)), {
28
+ waitMs: debounceDelay,
29
+ }).call
30
+ : () => undefined, [createChangeEvent, propsOnChange, isDebounced]);
19
31
  const onChange = (event) => {
20
- const trimmedEvent = {
21
- ...event,
22
- target: { ...event.target, value: event.target.value.trim() },
23
- };
24
- propsOnChange?.(trimmedEvent);
25
- setInternalValue(event.target.value);
32
+ const originalValue = event.target.value;
33
+ setInternalValue(originalValue);
34
+ if (!propsOnChange) {
35
+ return;
36
+ }
37
+ const trimmedValue = originalValue.trim();
38
+ return isDebounced
39
+ ? debouncedOnChange(trimmedValue)
40
+ : propsOnChange({
41
+ ...event,
42
+ target: { ...event.target, value: trimmedValue },
43
+ });
26
44
  };
27
45
  const onBlur = (event) => {
28
46
  propsOnBlur?.(event);
@@ -30,15 +48,9 @@ const useLogic = ({ onChange: propsOnChange, defaultValue, value, inputRef: exte
30
48
  setInternalValue(value);
31
49
  }
32
50
  };
33
- const createChangeEvent = (eventValue) => {
34
- return {
35
- target: {
36
- value: eventValue,
37
- },
38
- };
39
- };
40
51
  const onClearValue = () => {
41
- onChange?.(createChangeEvent(''));
52
+ setInternalValue('');
53
+ propsOnChange?.(createChangeEvent(''));
42
54
  inputRef.current.value = '';
43
55
  inputRef.current?.focus();
44
56
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astral/ui",
3
- "version": "4.73.0",
3
+ "version": "4.74.0",
4
4
  "browser": "./index.js",
5
5
  "main": "./node/index.js",
6
6
  "dependencies": {