@astral/ui 4.29.0 → 4.31.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 (73) hide show
  1. package/components/Filename/Filename.js +2 -2
  2. package/components/Filename/styles.d.ts +4 -0
  3. package/components/Filename/styles.js +4 -1
  4. package/components/Stepper/StepButton/StepButton.d.ts +7 -1
  5. package/components/Stepper/StepButton/StepButton.js +4 -2
  6. package/components/Stepper/StepButton/styles.d.ts +2 -1
  7. package/components/Stepper/StepIcon/StepIcon.d.ts +6 -2
  8. package/components/Stepper/StepIcon/StepIcon.js +11 -7
  9. package/components/Stepper/StepIcon/styles.js +1 -0
  10. package/components/Stepper/StepLabel/StepLabel.d.ts +7 -1
  11. package/components/Stepper/StepLabel/StepLabel.js +2 -2
  12. package/components/Stepper/constants.d.ts +1 -0
  13. package/components/Stepper/constants.js +1 -0
  14. package/hook-form/FormFilters/AllFiltersButton/AllFiltersButton.d.ts +2 -0
  15. package/hook-form/FormFilters/AllFiltersButton/AllFiltersButton.js +10 -0
  16. package/hook-form/FormFilters/AllFiltersButton/index.d.ts +1 -0
  17. package/hook-form/FormFilters/AllFiltersButton/index.js +1 -0
  18. package/hook-form/FormFilters/AllFiltersButton/styles.d.ts +19 -0
  19. package/hook-form/FormFilters/AllFiltersButton/styles.js +53 -0
  20. package/hook-form/FormFilters/AllFiltersButton/types.d.ts +8 -0
  21. package/hook-form/FormFilters/AllFiltersButton/types.js +1 -0
  22. package/hook-form/FormFilters/AllFiltersButton/useLogic/index.d.ts +1 -0
  23. package/hook-form/FormFilters/AllFiltersButton/useLogic/index.js +1 -0
  24. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +6 -0
  25. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +33 -0
  26. package/hook-form/FormFilters/FormFilters.js +5 -6
  27. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +1 -1
  28. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -7
  29. package/hook-form/FormFilters/constants.d.ts +0 -1
  30. package/hook-form/FormFilters/constants.js +0 -1
  31. package/hook-form/FormFilters/styles.d.ts +0 -18
  32. package/hook-form/FormFilters/styles.js +0 -51
  33. package/hook-form/FormFilters/types.d.ts +7 -16
  34. package/hook-form/FormFilters/useLogic/useLogic.d.ts +5 -6
  35. package/hook-form/FormFilters/useLogic/useLogic.js +7 -95
  36. package/hook-form/FormFiltersSearchField/FormFiltersSearchField.js +1 -1
  37. package/node/components/Filename/Filename.js +1 -1
  38. package/node/components/Filename/styles.d.ts +4 -0
  39. package/node/components/Filename/styles.js +5 -2
  40. package/node/components/Stepper/StepButton/StepButton.d.ts +7 -1
  41. package/node/components/Stepper/StepButton/StepButton.js +4 -2
  42. package/node/components/Stepper/StepButton/styles.d.ts +2 -1
  43. package/node/components/Stepper/StepIcon/StepIcon.d.ts +6 -2
  44. package/node/components/Stepper/StepIcon/StepIcon.js +11 -7
  45. package/node/components/Stepper/StepIcon/styles.js +1 -0
  46. package/node/components/Stepper/StepLabel/StepLabel.d.ts +7 -1
  47. package/node/components/Stepper/StepLabel/StepLabel.js +2 -2
  48. package/node/components/Stepper/constants.d.ts +1 -0
  49. package/node/components/Stepper/constants.js +1 -0
  50. package/node/hook-form/FormFilters/AllFiltersButton/AllFiltersButton.d.ts +2 -0
  51. package/node/hook-form/FormFilters/AllFiltersButton/AllFiltersButton.js +14 -0
  52. package/node/hook-form/FormFilters/AllFiltersButton/index.d.ts +1 -0
  53. package/node/hook-form/FormFilters/AllFiltersButton/index.js +5 -0
  54. package/node/hook-form/FormFilters/AllFiltersButton/styles.d.ts +19 -0
  55. package/node/hook-form/FormFilters/AllFiltersButton/styles.js +56 -0
  56. package/node/hook-form/FormFilters/AllFiltersButton/types.d.ts +8 -0
  57. package/node/hook-form/FormFilters/AllFiltersButton/types.js +2 -0
  58. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/index.d.ts +1 -0
  59. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/index.js +17 -0
  60. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +6 -0
  61. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +37 -0
  62. package/node/hook-form/FormFilters/FormFilters.js +3 -4
  63. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +1 -1
  64. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -7
  65. package/node/hook-form/FormFilters/constants.d.ts +0 -1
  66. package/node/hook-form/FormFilters/constants.js +0 -1
  67. package/node/hook-form/FormFilters/styles.d.ts +0 -18
  68. package/node/hook-form/FormFilters/styles.js +1 -52
  69. package/node/hook-form/FormFilters/types.d.ts +7 -16
  70. package/node/hook-form/FormFilters/useLogic/useLogic.d.ts +5 -6
  71. package/node/hook-form/FormFilters/useLogic/useLogic.js +6 -94
  72. package/node/hook-form/FormFiltersSearchField/FormFiltersSearchField.js +1 -1
  73. package/package.json +1 -1
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { useHidePersonalData } from '../personalDataSecurity';
4
4
  import { Tooltip } from '../Tooltip';
5
5
  import { classNames } from '../utils/classNames';
6
- import { FileBaseName, StyledTypography } from './styles';
6
+ import { FileBaseName, FileSuffix, StyledTypography } from './styles';
7
7
  import { useLogic } from './useLogic';
8
8
  export const Filename = forwardRef((props, forwardedRef) => {
9
9
  const { isOverflowed, suffixWithExtension, baseNameProps } = useLogic({
@@ -14,5 +14,5 @@ export const Filename = forwardRef((props, forwardedRef) => {
14
14
  const hidePersonalDataClassname = useHidePersonalData({
15
15
  isEnabled: isHidePersonalData,
16
16
  });
17
- return (_jsx(Tooltip, { title: isOverflowed && children, disableInteractive: true, ...tooltipProps, className: classNames(tooltipProps?.className, hidePersonalDataClassname), children: _jsxs(StyledTypography, { "$align": align, variant: variant, className: classNames(className, hidePersonalDataClassname), ...restProps, children: [_jsx(FileBaseName, { ...baseNameProps }), _jsx("span", { children: suffixWithExtension })] }) }));
17
+ return (_jsx(Tooltip, { title: isOverflowed && children, disableInteractive: true, ...tooltipProps, className: classNames(tooltipProps?.className, hidePersonalDataClassname), children: _jsxs(StyledTypography, { "$align": align, variant: variant, className: classNames(className, hidePersonalDataClassname), ...restProps, children: [_jsx(FileBaseName, { ...baseNameProps }), _jsx(FileSuffix, { children: suffixWithExtension })] }) }));
18
18
  });
@@ -3,6 +3,10 @@ export declare const FileBaseName: import("../styled").StyledComponent<{
3
3
  theme?: import("@emotion/react").Theme | undefined;
4
4
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
5
5
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
6
+ export declare const FileSuffix: import("../styled").StyledComponent<{
7
+ theme?: import("@emotion/react").Theme | undefined;
8
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
6
10
  export declare const StyledTypography: import("../styled").StyledComponent<import("../Typography/types").TypographyPropsBase & {
7
11
  color?: import("../Typography").TypographyColor | undefined;
8
12
  variant?: import("../Typography").TypographyVariant | undefined;
@@ -6,7 +6,10 @@ export const FileBaseName = styled.span `
6
6
  max-width: 100%;
7
7
 
8
8
  text-overflow: ellipsis;
9
- white-space: nowrap;
9
+ white-space: preserve nowrap;
10
+ `;
11
+ export const FileSuffix = styled.span `
12
+ white-space: pre;
10
13
  `;
11
14
  export const StyledTypography = styled(Typography, {
12
15
  shouldForwardProp: (prop) => !['$align'].includes(prop),
@@ -1,5 +1,7 @@
1
1
  import type { StepLabelProps as MuiStepLabelProps } from '@mui/material/StepLabel';
2
+ import { type ReactNode } from 'react';
2
3
  import type { WithoutEmotionSpecific } from '../../types/WithoutEmotionSpecific';
4
+ import { type StepIconProps } from '../StepIcon';
3
5
  export type StepButtonProps = {
4
6
  /**
5
7
  * Если true, текущий шаг будет отображен как активный
@@ -9,5 +11,9 @@ export type StepButtonProps = {
9
11
  * Функция, вызываемая при клике на элемент
10
12
  */
11
13
  onClick: () => void;
12
- } & WithoutEmotionSpecific<MuiStepLabelProps>;
14
+ /**
15
+ * Кастомный компонент иконки
16
+ */
17
+ icon?: (props: Omit<StepIconProps, 'icon'>) => ReactNode;
18
+ } & Omit<WithoutEmotionSpecific<MuiStepLabelProps>, 'icon'>;
13
19
  export declare const StepButton: (props: StepButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,9 @@ import { stepperClassnames } from '../constants';
4
4
  import { StepIcon } from '../StepIcon';
5
5
  import { Button, StyledStepLabel } from './styles';
6
6
  export const StepButton = (props) => {
7
- const { isSelected, onClick, ...restProps } = props;
8
- const stepIconRender = useCallback(({ active, completed, error, icon }) => (_jsx(StepIcon, { icon: icon, isSelected: isSelected, active: active, completed: completed, error: error })), [isSelected]);
7
+ const { isSelected, onClick, icon: Icon, ...restProps } = props;
8
+ const stepIconRender = useCallback(({ active, completed, error }) => {
9
+ return (_jsx(StepIcon, { icon: Icon, isSelected: isSelected, active: active, completed: completed, error: error }));
10
+ }, [isSelected, Icon]);
9
11
  return (_jsx(Button, { onClick: onClick, tabIndex: 1, className: stepperClassnames.stepButton, children: _jsx(StyledStepLabel, { StepIconComponent: stepIconRender, ...restProps }) }));
10
12
  };
@@ -5,6 +5,7 @@ export declare const Button: import("../../styled").StyledComponent<{
5
5
  }, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
6
6
  export declare const StyledStepLabel: import("../../styled").StyledComponent<{
7
7
  isSelected?: boolean | undefined;
8
- } & import("../..").WithoutEmotionSpecific<import("@mui/material/StepLabel").StepLabelProps> & {
8
+ icon?: ((props: Omit<import("../StepIcon").StepIconProps, "icon">) => import("react").ReactNode) | undefined;
9
+ } & Omit<import("../..").WithoutEmotionSpecific<import("@mui/material/StepLabel").StepLabelProps>, "icon"> & {
9
10
  theme?: import("@emotion/react").Theme | undefined;
10
11
  }, {}, {}>;
@@ -1,10 +1,14 @@
1
- /// <reference types="react" />
2
1
  import type { StepIconProps as MuiStepIconProps } from '@mui/material/StepIcon';
2
+ import { type ReactNode } from 'react';
3
3
  import { type WithoutEmotionSpecific } from '../../types/WithoutEmotionSpecific';
4
4
  export type StepIconProps = {
5
5
  /**
6
6
  * Является ли шаг в состоянии select
7
7
  */
8
8
  isSelected?: boolean;
9
- } & WithoutEmotionSpecific<MuiStepIconProps>;
9
+ /**
10
+ * Кастомный компонент иконки
11
+ */
12
+ icon?: (props: Omit<StepIconProps, 'icon'>) => ReactNode;
13
+ } & Omit<WithoutEmotionSpecific<MuiStepIconProps>, 'icon'>;
10
14
  export declare const StepIcon: import("react").MemoExoticComponent<(props: StepIconProps) => import("react/jsx-runtime").JSX.Element>;
@@ -1,22 +1,26 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo } from 'react';
3
+ import { stepperClassnames } from '../constants';
3
4
  import { ActiveIcon, DefaultIcon, ErrorIcon, SelectIcon, SuccessIcon, } from './styles';
4
5
  export const StepIcon = memo((props) => {
5
- const { active, completed, error, isSelected } = props;
6
+ const { active, completed, error, isSelected, icon: Icon } = props;
7
+ if (Icon) {
8
+ return (_jsx(Icon, { active: active, completed: completed, error: error, isSelected: isSelected, className: stepperClassnames.stepIcon }));
9
+ }
6
10
  if (completed && error && isSelected) {
7
- return _jsx(SelectIcon, { "$isError": true });
11
+ return _jsx(SelectIcon, { "$isError": true, className: stepperClassnames.stepIcon });
8
12
  }
9
13
  if (completed && isSelected) {
10
- return _jsx(SelectIcon, {});
14
+ return _jsx(SelectIcon, { className: stepperClassnames.stepIcon });
11
15
  }
12
16
  if (error) {
13
- return _jsx(ErrorIcon, {});
17
+ return _jsx(ErrorIcon, { className: stepperClassnames.stepIcon });
14
18
  }
15
19
  if (completed) {
16
- return _jsx(SuccessIcon, {});
20
+ return _jsx(SuccessIcon, { className: stepperClassnames.stepIcon });
17
21
  }
18
22
  if (active) {
19
- return _jsx(ActiveIcon, { color: "primary" });
23
+ return _jsx(ActiveIcon, { className: stepperClassnames.stepIcon });
20
24
  }
21
- return _jsx(DefaultIcon, {});
25
+ return _jsx(DefaultIcon, { className: stepperClassnames.stepIcon });
22
26
  });
@@ -29,4 +29,5 @@ export const DefaultIcon = styled(StepDefaultFillMd) `
29
29
  `;
30
30
  export const ActiveIcon = styled(StepDefaultFillMd) `
31
31
  ${({ theme }) => iconsSize(theme)};
32
+ color: ${({ theme }) => theme.palette.primary[800]};
32
33
  `;
@@ -1,9 +1,15 @@
1
1
  import type { StepLabelProps as MuiStepLabelProps } from '@mui/material/StepLabel';
2
+ import { type ReactNode } from 'react';
2
3
  import { type WithoutEmotionSpecific } from '../../types/WithoutEmotionSpecific';
4
+ import { type StepIconProps } from '../StepIcon';
3
5
  export type StepProps = {
4
6
  /**
5
7
  * Является ли шаг в состоянии select
6
8
  */
7
9
  isSelected?: boolean;
8
- } & WithoutEmotionSpecific<MuiStepLabelProps>;
10
+ /**
11
+ * Кастомный компонент иконки
12
+ */
13
+ icon?: (props: Omit<StepIconProps, 'icon'>) => ReactNode;
14
+ } & Omit<WithoutEmotionSpecific<MuiStepLabelProps>, 'icon'>;
9
15
  export declare const StepLabel: (props: StepProps) => import("react/jsx-runtime").JSX.Element;
@@ -3,7 +3,7 @@ import MuiStepLabel from '@mui/material/StepLabel';
3
3
  import { useCallback } from 'react';
4
4
  import { StepIcon } from '../StepIcon';
5
5
  export const StepLabel = (props) => {
6
- const { isSelected, ...restProps } = props;
7
- const stepIconRender = useCallback(({ active, completed, error, icon }) => (_jsx(StepIcon, { icon: icon, isSelected: isSelected, active: active, completed: completed, error: error })), [isSelected]);
6
+ const { isSelected, icon: Icon, ...restProps } = props;
7
+ const stepIconRender = useCallback(({ active, completed, error }) => (_jsx(StepIcon, { icon: Icon, isSelected: isSelected, active: active, completed: completed, error: error })), [isSelected]);
8
8
  return _jsx(MuiStepLabel, { StepIconComponent: stepIconRender, ...restProps });
9
9
  };
@@ -1,3 +1,4 @@
1
1
  export declare const stepperClassnames: {
2
2
  stepButton: string;
3
+ stepIcon: string;
3
4
  };
@@ -1,4 +1,5 @@
1
1
  import { createUIKitClassname } from '../utils/createUIKitClassname';
2
2
  export const stepperClassnames = {
3
3
  stepButton: createUIKitClassname('stepper_stepButton'),
4
+ stepIcon: createUIKitClassname('stepper_stepIcon'),
4
5
  };
@@ -0,0 +1,2 @@
1
+ import { type AllFiltersButtonProps } from './types';
2
+ export declare const AllFiltersButton: <TFieldValues extends Record<string, unknown>>(props: AllFiltersButtonProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button } from '../../../components/Button';
3
+ import { Filter2OutlineMd } from '../../../icons/Filter2OutlineMd';
4
+ import { formFiltersClassnames } from '../constants';
5
+ import { AllFiltersButtonWrapper, StyledBadge, StyledCounter } from './styles';
6
+ import { useLogic } from './useLogic';
7
+ export const AllFiltersButton = (props) => {
8
+ const { allFiltersButtonClassName, counter, onOpenModal } = useLogic(props);
9
+ return (_jsx(AllFiltersButtonWrapper, { className: allFiltersButtonClassName, children: _jsx(StyledBadge, { color: "error", badgeContent: counter, variant: "dot", children: _jsx(Button, { onClick: onOpenModal, variant: "outlined", color: "grey", startIcon: _jsx(Filter2OutlineMd, {}), endIcon: counter ? _jsx(StyledCounter, { color: "error", content: counter }) : null, className: formFiltersClassnames.allFiltersButton, children: "\u0412\u0441\u0435 \u0444\u0438\u043B\u044C\u0442\u0440\u044B" }) }) }));
10
+ };
@@ -0,0 +1 @@
1
+ export { AllFiltersButton } from './AllFiltersButton';
@@ -0,0 +1 @@
1
+ export { AllFiltersButton } from './AllFiltersButton';
@@ -0,0 +1,19 @@
1
+ /// <reference types="react" />
2
+ export declare const AllFiltersButtonWrapper: import("../../../components/styled").StyledComponent<{
3
+ theme?: import("@emotion/react").Theme | undefined;
4
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
5
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
6
+ export declare const StyledBadge: import("../../../components/styled").StyledComponent<Omit<import("../../..").WithoutEmotionSpecific<import("@mui/material/Badge").BadgeProps>, "color"> & {
7
+ color: import("../../../components/Badge").BadgeColor;
8
+ withBorder?: boolean | undefined;
9
+ variantColor?: import("../../../components/Badge").BadgeVariantsColor | undefined;
10
+ } & {
11
+ theme?: import("@emotion/react").Theme | undefined;
12
+ }, {}, {}>;
13
+ export declare const StyledCounter: import("../../../components/styled").StyledComponent<Omit<import("../../..").WithoutEmotionSpecific<import("@mui/material/Badge").BadgeProps>, "content" | "color" | "children" | "variant" | "invisible" | "anchorOrigin" | "badgeContent" | "overlap" | "withBorder"> & {
14
+ color: import("../../../components/Counter/types").CounterColor;
15
+ variant?: import("../../../components/Counter/types").CounterVariants | undefined;
16
+ content?: number | undefined;
17
+ } & {
18
+ theme?: import("@emotion/react").Theme | undefined;
19
+ }, {}, {}>;
@@ -0,0 +1,53 @@
1
+ import { badgeClasses } from '@mui/material/Badge';
2
+ import { Badge } from '../../../components/Badge';
3
+ import { Counter } from '../../../components/Counter';
4
+ import { styled } from '../../../components/styled';
5
+ import { formFiltersClassnames } from '../constants';
6
+ export const AllFiltersButtonWrapper = styled.div `
7
+ display: none;
8
+
9
+ white-space: nowrap;
10
+
11
+ &.${formFiltersClassnames.showAllFiltersButtonOnDesktop} {
12
+ display: flex;
13
+ }
14
+
15
+ ${({ theme }) => theme.breakpoints.down('sm')} {
16
+ margin-right: 0;
17
+ &.${formFiltersClassnames.showAllFiltersButtonOnMobile} {
18
+ display: flex;
19
+ }
20
+
21
+ &.${formFiltersClassnames.withoutSearch} {
22
+ width: 100%;
23
+
24
+ .${formFiltersClassnames.allFiltersButton} {
25
+ width: 100%;
26
+ }
27
+ }
28
+
29
+ &.${formFiltersClassnames.withSearch} {
30
+ .${formFiltersClassnames.allFiltersButton} {
31
+ display: unset;
32
+ gap: 0;
33
+
34
+ padding: 8px;
35
+
36
+ font-size: 0;
37
+ }
38
+ }
39
+ }
40
+ `;
41
+ export const StyledBadge = styled(Badge) `
42
+ width: 100%;
43
+ .${badgeClasses.dot} {
44
+ ${({ theme }) => theme.breakpoints.up('sm')} {
45
+ display: none;
46
+ }
47
+ }
48
+ `;
49
+ export const StyledCounter = styled(Counter) `
50
+ ${({ theme }) => theme.breakpoints.down('sm')} {
51
+ display: none;
52
+ }
53
+ `;
@@ -0,0 +1,8 @@
1
+ import { type UseFormReturn } from 'react-hook-form';
2
+ export type AllFiltersButtonProps<TFieldValues extends Record<string, unknown>> = {
3
+ form: UseFormReturn<TFieldValues>;
4
+ onOpenModal: () => void;
5
+ hasMainFilters: boolean;
6
+ hasSecondaryFilters: boolean;
7
+ hasSearch: boolean;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './useLogic';
@@ -0,0 +1 @@
1
+ export * from './useLogic';
@@ -0,0 +1,6 @@
1
+ import { type AllFiltersButtonProps } from '../types';
2
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, }: AllFiltersButtonProps<TFieldValues>) => {
3
+ allFiltersButtonClassName: string;
4
+ counter: number;
5
+ onOpenModal: () => void;
6
+ };
@@ -0,0 +1,33 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import { useWatch } from 'react-hook-form';
3
+ import { classNames } from '../../../../components/utils/classNames';
4
+ import { FORM_FILTERS_SEARCH_FIELD_ID } from '../../../FormFiltersSearchField/constants';
5
+ import { formFiltersClassnames } from '../../constants';
6
+ export const useLogic = ({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, }) => {
7
+ const formValues = useWatch({
8
+ control: form.control,
9
+ });
10
+ const [searchName, setSearchName] = useState('');
11
+ useEffect(() => {
12
+ const searchFieldName = document
13
+ .getElementById(FORM_FILTERS_SEARCH_FIELD_ID)
14
+ ?.getAttribute('name') || '';
15
+ setSearchName(searchFieldName);
16
+ }, [hasSearch]);
17
+ // Исключаем поиск из счетчика фильтров
18
+ const counter = Object.values(formValues || {}).filter(Boolean).length -
19
+ (formValues?.[searchName] ? 1 : 0);
20
+ const allFiltersButtonClassName = useMemo(() => {
21
+ return classNames({
22
+ [formFiltersClassnames.showAllFiltersButtonOnDesktop]: hasSecondaryFilters,
23
+ [formFiltersClassnames.showAllFiltersButtonOnMobile]: hasMainFilters || hasSecondaryFilters,
24
+ [formFiltersClassnames.withSearch]: hasSearch,
25
+ [formFiltersClassnames.withoutSearch]: !hasSearch,
26
+ });
27
+ }, [hasMainFilters, hasSecondaryFilters, hasSearch]);
28
+ return {
29
+ allFiltersButtonClassName,
30
+ counter,
31
+ onOpenModal,
32
+ };
33
+ };
@@ -1,20 +1,19 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Button } from '../../components/Button';
3
- import { Filter2OutlineMd } from '../../icons/Filter2OutlineMd';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
2
  import { Form } from '../Form';
5
3
  import { FormControlProvider } from '../FormControlProvider';
4
+ import { AllFiltersButton } from './AllFiltersButton';
6
5
  import { formFiltersClassnames } from './constants';
7
6
  import { FormFiltersDialog } from './FormFiltersDialog';
8
7
  import { FormFiltersSkeleton } from './FormFiltersSkeleton';
9
- import { AllFiltersButtonWrapper, MainFiltersWrapper, StyledBadge, StyledCounter, SubmitButtonWrapper, Wrapper, } from './styles';
8
+ import { MainFiltersWrapper, SubmitButtonWrapper, Wrapper } from './styles';
10
9
  import { useLogic } from './useLogic';
11
10
  /**
12
11
  * Компонент для отображения фильтров формы
13
12
  */
14
13
  export const FormFilters = (props) => {
15
- const { headerForm, searchField: SearchField, mainFilters: MainFilters, submitButton: SubmitButton, counter, onSubmit, onOpenModal, dialogProps, mainFiltersColumns, isLoading, allFiltersButtonClassName, } = useLogic(props);
14
+ const { form, onSubmit, searchField: SearchField, mainFilters: MainFilters, submitButton: SubmitButton, secondaryFilters: SecondaryFilters, onOpenModal, dialogProps, mainFiltersColumns, isLoading, } = useLogic(props);
16
15
  if (isLoading) {
17
16
  return _jsx(FormFiltersSkeleton, {});
18
17
  }
19
- return (_jsxs(_Fragment, { children: [_jsx(FormControlProvider, { size: "small", hideHelperText: true, children: _jsx(Form, { form: headerForm, onSubmit: headerForm.handleSubmit(onSubmit), children: _jsxs(Wrapper, { children: [SearchField && (_jsx(SearchField, { control: headerForm.control, fullWidth: true })), _jsx(AllFiltersButtonWrapper, { className: allFiltersButtonClassName, children: _jsx(StyledBadge, { color: "error", badgeContent: counter, variant: "dot", children: _jsx(Button, { onClick: onOpenModal, variant: "outlined", color: "grey", startIcon: _jsx(Filter2OutlineMd, {}), endIcon: counter ? (_jsx(StyledCounter, { color: "error", content: counter })) : null, className: formFiltersClassnames.allFiltersButton, children: "\u0412\u0441\u0435 \u0444\u0438\u043B\u044C\u0442\u0440\u044B" }) }) }), _jsx(MainFiltersWrapper, { className: formFiltersClassnames.pageHeaderFilters, columns: mainFiltersColumns, children: MainFilters && (_jsx(MainFilters, { control: headerForm.control, isModal: false })) }), SubmitButton && (_jsx(SubmitButtonWrapper, { children: _jsx(SubmitButton, { size: "medium", className: formFiltersClassnames.submitButton }) }))] }) }) }), _jsx(FormFiltersDialog, { ...dialogProps })] }));
18
+ return (_jsxs(Form, { name: "form", form: form, onSubmit: form.handleSubmit(onSubmit || (() => undefined)), children: [_jsx(FormControlProvider, { size: "small", hideHelperText: true, children: _jsxs(Wrapper, { children: [SearchField && _jsx(SearchField, { control: form.control }), _jsx(AllFiltersButton, { form: form, onOpenModal: onOpenModal, hasMainFilters: Boolean(MainFilters), hasSecondaryFilters: Boolean(SecondaryFilters), hasSearch: Boolean(SearchField) }), _jsx(MainFiltersWrapper, { columns: mainFiltersColumns, children: MainFilters && (_jsx(MainFilters, { control: form.control, isModal: false })) }), SubmitButton && (_jsx(SubmitButtonWrapper, { children: _jsx(SubmitButton, { size: "medium", className: formFiltersClassnames.submitButton }) }))] }) }), _jsx(FormFiltersDialog, { ...dialogProps })] }));
20
19
  };
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { type FormFiltersDialogProps } from '../types';
3
- export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ validationSchema, values, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, defaultValues, onSubmit, }: FormFiltersDialogProps<TFieldValues>) => {
3
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ validationSchema, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, onSubmit, form, }: FormFiltersDialogProps<TFieldValues>) => {
4
4
  modalForm: import("react-hook-form").UseFormReturn<TFieldValues, any>;
5
5
  onCloseModal: () => void;
6
6
  onResetModal: () => void;
@@ -1,16 +1,16 @@
1
1
  import { useEffect } from 'react';
2
2
  import { useForm } from '../../../useForm';
3
- export const useLogic = ({ validationSchema, values, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, defaultValues, onSubmit, }) => {
3
+ export const useLogic = ({ validationSchema, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, onSubmit, form, }) => {
4
4
  const modalForm = useForm({
5
5
  validationSchema,
6
- defaultValues: values,
6
+ defaultValues: form.getValues(),
7
7
  });
8
8
  const onCloseModal = () => {
9
9
  setIsModalOpen(false);
10
10
  modalForm.reset();
11
11
  };
12
12
  const onResetModal = () => {
13
- modalForm.reset(defaultValues);
13
+ modalForm.reset(form.getValues());
14
14
  };
15
15
  const onSubmitModal = (submittedValues) => {
16
16
  onSubmit(submittedValues);
@@ -18,13 +18,10 @@ export const useLogic = ({ validationSchema, values, mainFilters, secondaryFilte
18
18
  };
19
19
  const isResetButtonDisabled = !modalForm.formState.isDirty;
20
20
  useEffect(() => {
21
- if (isModalOpen && defaultValues) {
21
+ if (isModalOpen) {
22
22
  onResetModal();
23
23
  }
24
24
  }, [isModalOpen]);
25
- useEffect(() => {
26
- modalForm.reset(values);
27
- }, [values]);
28
25
  return {
29
26
  modalForm,
30
27
  onCloseModal,
@@ -1,6 +1,5 @@
1
1
  export declare const formFiltersClassnames: {
2
2
  modalFilters: string;
3
- pageHeaderFilters: string;
4
3
  submitButton: string;
5
4
  allFiltersButton: string;
6
5
  showAllFiltersButtonOnDesktop: string;
@@ -1,7 +1,6 @@
1
1
  import { createUIKitClassname } from '../../components/utils/createUIKitClassname';
2
2
  export const formFiltersClassnames = {
3
3
  modalFilters: createUIKitClassname('form-filters__modal-filters'),
4
- pageHeaderFilters: createUIKitClassname('form-filters__page-header-filters'),
5
4
  submitButton: createUIKitClassname('form-filters__submit-button'),
6
5
  allFiltersButton: createUIKitClassname('form-filters__all-filters-button'),
7
6
  showAllFiltersButtonOnDesktop: createUIKitClassname('form-filters_show-all-filters-button_desktop'),
@@ -3,30 +3,12 @@ export declare const Wrapper: import("../../components/styled").StyledComponent<
3
3
  theme?: import("@emotion/react").Theme | undefined;
4
4
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
5
5
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
6
- export declare const AllFiltersButtonWrapper: import("../../components/styled").StyledComponent<{
7
- theme?: import("@emotion/react").Theme | undefined;
8
- as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
10
6
  export declare const MainFiltersWrapper: import("../../components/styled").StyledComponent<{
11
7
  theme?: import("@emotion/react").Theme | undefined;
12
8
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
13
9
  } & {
14
10
  columns?: string | undefined;
15
11
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
16
- export declare const StyledBadge: import("../../components/styled").StyledComponent<Omit<import("../..").WithoutEmotionSpecific<import("@mui/material/Badge").BadgeProps>, "color"> & {
17
- color: import("../../components/Badge").BadgeColor;
18
- withBorder?: boolean | undefined;
19
- variantColor?: import("../../components/Badge").BadgeVariantsColor | undefined;
20
- } & {
21
- theme?: import("@emotion/react").Theme | undefined;
22
- }, {}, {}>;
23
- export declare const StyledCounter: import("../../components/styled").StyledComponent<Omit<import("../..").WithoutEmotionSpecific<import("@mui/material/Badge").BadgeProps>, "content" | "color" | "children" | "variant" | "invisible" | "anchorOrigin" | "badgeContent" | "overlap" | "withBorder"> & {
24
- color: import("../../components/Counter/types").CounterColor;
25
- variant?: import("../../components/Counter/types").CounterVariants | undefined;
26
- content?: number | undefined;
27
- } & {
28
- theme?: import("@emotion/react").Theme | undefined;
29
- }, {}, {}>;
30
12
  export declare const SubmitButtonWrapper: import("../../components/styled").StyledComponent<{
31
13
  theme?: import("@emotion/react").Theme | undefined;
32
14
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
@@ -1,8 +1,5 @@
1
- import { badgeClasses } from '@mui/material/Badge';
2
1
  import { formLabelClasses } from '@mui/material/FormLabel';
3
2
  import { inputBaseClasses } from '@mui/material/InputBase';
4
- import { Badge } from '../../components/Badge';
5
- import { Counter } from '../../components/Counter';
6
3
  import { styled } from '../../components/styled';
7
4
  import { formFiltersClassnames } from './constants';
8
5
  export const Wrapper = styled.div `
@@ -32,41 +29,6 @@ export const Wrapper = styled.div `
32
29
  }
33
30
  }
34
31
  `;
35
- export const AllFiltersButtonWrapper = styled.div `
36
- display: none;
37
-
38
- white-space: nowrap;
39
-
40
- &.${formFiltersClassnames.showAllFiltersButtonOnDesktop} {
41
- display: flex;
42
- }
43
-
44
- ${({ theme }) => theme.breakpoints.down('sm')} {
45
- margin-right: 0;
46
- &.${formFiltersClassnames.showAllFiltersButtonOnMobile} {
47
- display: flex;
48
- }
49
-
50
- &.${formFiltersClassnames.withoutSearch} {
51
- width: 100%;
52
-
53
- .${formFiltersClassnames.allFiltersButton} {
54
- width: 100%;
55
- }
56
- }
57
-
58
- &.${formFiltersClassnames.withSearch} {
59
- .${formFiltersClassnames.allFiltersButton} {
60
- display: unset;
61
- gap: 0;
62
-
63
- padding: 8px;
64
-
65
- font-size: 0;
66
- }
67
- }
68
- }
69
- `;
70
32
  export const MainFiltersWrapper = styled.div `
71
33
  display: grid;
72
34
  grid-auto-flow: column;
@@ -79,19 +41,6 @@ export const MainFiltersWrapper = styled.div `
79
41
  display: none;
80
42
  }
81
43
  `;
82
- export const StyledBadge = styled(Badge) `
83
- width: 100%;
84
- .${badgeClasses.dot} {
85
- ${({ theme }) => theme.breakpoints.up('sm')} {
86
- display: none;
87
- }
88
- }
89
- `;
90
- export const StyledCounter = styled(Counter) `
91
- ${({ theme }) => theme.breakpoints.down('sm')} {
92
- display: none;
93
- }
94
- `;
95
44
  export const SubmitButtonWrapper = styled.div `
96
45
  white-space: nowrap;
97
46
 
@@ -1,45 +1,36 @@
1
1
  import { type ObjectAsyncGuard, type ObjectGuard } from '@astral/validations';
2
2
  import { type ReactNode } from 'react';
3
- import { type Control } from 'react-hook-form';
3
+ import { type Control, type UseFormReturn } from 'react-hook-form';
4
4
  import type { ButtonProps } from '../../components/Button';
5
5
  type InputsProps<TFieldValues extends Record<string, unknown>> = {
6
6
  control: Control<TFieldValues>;
7
7
  };
8
8
  export type FormFiltersProps<TFieldValues extends Record<string, unknown>> = {
9
+ form: UseFormReturn<TFieldValues>;
10
+ onSubmit?: (values: TFieldValues) => void;
9
11
  /**
10
12
  * Схема валидации из @astral/validations
11
13
  */
12
14
  validationSchema?: ObjectGuard<TFieldValues> | ObjectAsyncGuard<TFieldValues>;
13
- /**
14
- * Значения фильтров
15
- */
16
- values?: TFieldValues;
17
- /**
18
- * Callback вызываемый при изменении значений фильтров. Вызывается с debounce (300ms)
19
- */
20
- onChange: (values: TFieldValues) => void;
21
15
  /**
22
16
  * Поле поиска
23
17
  *
24
18
  * @example
25
19
  * ```ts
26
20
  * <FormFilters
27
- * SearchField={(props) => <FormFiltersSearchField {...props} placeholder="Поиск..." />}
21
+ * SearchField={({control}) => <FormFiltersSearchField control={control} placeholder="Поиск..." />}
28
22
  * />
29
23
  * ```
30
24
  */
31
- searchField?: (props: InputsProps<TFieldValues> & {
32
- fullWidth?: boolean;
33
- }) => ReactNode;
25
+ searchField?: (props: InputsProps<TFieldValues>) => ReactNode;
34
26
  /**
35
27
  * Основные фильтры
36
28
  *
37
29
  * @example
38
30
  * ```ts
39
31
  * <FormFilters
40
- * MainFilters={({ control, isModal, ...props }) =>
32
+ * MainFilters={({ control, isModal }) =>
41
33
  * <FormTextField
42
- * {...props}
43
34
  * control={control}
44
35
  * name="name"
45
36
  * label="Название"
@@ -57,7 +48,7 @@ export type FormFiltersProps<TFieldValues extends Record<string, unknown>> = {
57
48
  * @example
58
49
  * ```ts
59
50
  * <FormFilters
60
- * SecondaryFilters={({ control, ...props }) => <FormTextField {...props} control={control} placeholder="Введите название" />}
51
+ * SecondaryFilters={({ control }) => <FormTextField control={control} name="name" label="Название" placeholder="Введите название" />}
61
52
  * />
62
53
  * ```
63
54
  */
@@ -1,18 +1,17 @@
1
- import { type UseFormReturn } from '../../useForm';
1
+ import { type UseFormReturn } from 'react-hook-form';
2
2
  import { type FormFiltersDialogProps } from '../FormFiltersDialog/types';
3
3
  import { type FormFiltersProps } from '../types';
4
4
  type UseLogicReturn<TFieldValues extends Record<string, unknown>> = {
5
- headerForm: UseFormReturn<TFieldValues>;
5
+ form: UseFormReturn<TFieldValues>;
6
+ onSubmit?: (values: TFieldValues) => void;
6
7
  searchField: FormFiltersProps<TFieldValues>['searchField'];
7
8
  mainFilters: FormFiltersProps<TFieldValues>['mainFilters'];
8
9
  submitButton: FormFiltersProps<TFieldValues>['submitButton'];
9
- counter: number;
10
- onSubmit: (submittedValues: TFieldValues) => void;
10
+ secondaryFilters: FormFiltersProps<TFieldValues>['secondaryFilters'];
11
11
  onOpenModal: () => void;
12
12
  dialogProps: FormFiltersDialogProps<TFieldValues>;
13
13
  mainFiltersColumns?: string;
14
14
  isLoading?: boolean;
15
- allFiltersButtonClassName: string;
16
15
  };
17
- export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ validationSchema, values, onChange, searchField, mainFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }: FormFiltersProps<TFieldValues>) => UseLogicReturn<TFieldValues>;
16
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onSubmit, validationSchema, searchField, mainFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }: FormFiltersProps<TFieldValues>) => UseLogicReturn<TFieldValues>;
18
17
  export {};