@astral/ui 4.34.0 → 4.34.2

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 (183) hide show
  1. package/components/Badge/styles.js +5 -0
  2. package/components/Badge/types.d.ts +1 -1
  3. package/components/Chip/Chip.js +3 -3
  4. package/components/Chip/ChipProvider/ChipProvider.d.ts +26 -0
  5. package/components/Chip/ChipProvider/ChipProvider.js +13 -0
  6. package/components/Chip/ChipProvider/index.d.ts +1 -0
  7. package/components/Chip/ChipProvider/index.js +1 -0
  8. package/components/Chip/index.d.ts +2 -1
  9. package/components/Chip/index.js +1 -0
  10. package/components/Chip/public.d.ts +2 -1
  11. package/components/Chip/public.js +1 -0
  12. package/components/Chip/styles.d.ts +7 -3
  13. package/components/Chip/styles.js +26 -2
  14. package/components/Chip/types.d.ts +21 -1
  15. package/components/Chip/useLogic/useLogic.d.ts +5 -4
  16. package/components/Chip/useLogic/useLogic.js +11 -3
  17. package/components/Counter/Counter.d.ts +5 -1
  18. package/components/Counter/Counter.js +1 -1
  19. package/components/Counter/types.d.ts +1 -1
  20. package/components/DashboardSidebarCounter/styles.d.ts +1 -0
  21. package/components/DataGridPaginationContainer/styles.js +1 -1
  22. package/components/MenuOrganization/faker.js +112 -18
  23. package/components/PageContent/styles.js +1 -0
  24. package/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.d.ts +15 -0
  25. package/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.js +8 -0
  26. package/components/PageHeader/HeaderContent/FormFiltersProvider/index.d.ts +1 -0
  27. package/components/PageHeader/HeaderContent/FormFiltersProvider/index.js +1 -0
  28. package/components/PageHeader/HeaderContent/HeaderContent.js +3 -2
  29. package/components/PageHeader/HeaderContent/index.d.ts +1 -0
  30. package/components/PageHeader/HeaderContent/index.js +1 -0
  31. package/components/PageHeader/HeaderContent/styles.d.ts +0 -4
  32. package/components/PageHeader/HeaderContent/styles.js +1 -10
  33. package/components/PageHeader/PageActions/PageActions.js +1 -1
  34. package/components/PageHeader/constants.d.ts +2 -0
  35. package/components/PageHeader/constants.js +2 -0
  36. package/components/PageHeader/index.d.ts +1 -0
  37. package/components/PageHeader/index.js +1 -0
  38. package/components/PageHeader/styles.js +21 -0
  39. package/components/PageLayoutContainer/styles.js +6 -0
  40. package/components/TagBadge/styles.js +2 -1
  41. package/hook-form/FormFilters/AllFiltersButton/styles.d.ts +1 -0
  42. package/hook-form/FormFilters/AllFiltersButton/types.d.ts +1 -0
  43. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +1 -1
  44. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +21 -5
  45. package/hook-form/FormFilters/FormFilters.js +7 -4
  46. package/hook-form/FormFilters/FormFiltersDialog/FormFiltersDialog.js +4 -4
  47. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.d.ts +6 -0
  48. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.js +11 -0
  49. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.d.ts +1 -0
  50. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.js +1 -0
  51. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.d.ts +14 -0
  52. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.js +14 -0
  53. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.d.ts +1 -0
  54. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.js +1 -0
  55. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.d.ts +6 -0
  56. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.js +11 -0
  57. package/hook-form/FormFilters/FormFiltersDialog/styles.d.ts +1 -10
  58. package/hook-form/FormFilters/FormFiltersDialog/styles.js +1 -9
  59. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +4 -2
  60. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -5
  61. package/hook-form/FormFilters/FormFiltersSkeleton/FormFiltersSkeleton.js +4 -1
  62. package/hook-form/FormFilters/styles.d.ts +4 -0
  63. package/hook-form/FormFilters/styles.js +11 -2
  64. package/hook-form/FormFilters/types.d.ts +24 -4
  65. package/hook-form/FormFilters/useLogic/useLogic.d.ts +2 -1
  66. package/hook-form/FormFilters/useLogic/useLogic.js +13 -2
  67. package/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.d.ts +1 -0
  68. package/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.js +18 -0
  69. package/hook-form/FormFilters/utils/checkIsFilledValue/index.d.ts +1 -0
  70. package/hook-form/FormFilters/utils/checkIsFilledValue/index.js +1 -0
  71. package/hook-form/FormFilters/utils/getFilledCount/getFilledCount.d.ts +1 -0
  72. package/hook-form/FormFilters/utils/getFilledCount/getFilledCount.js +4 -0
  73. package/hook-form/FormFilters/utils/getFilledCount/index.d.ts +1 -0
  74. package/hook-form/FormFilters/utils/getFilledCount/index.js +1 -0
  75. package/hook-form/FormFilters/utils/index.d.ts +2 -0
  76. package/hook-form/FormFilters/utils/index.js +2 -0
  77. package/hook-form/FormQuickFilters/FormQuickFilters.d.ts +26 -0
  78. package/hook-form/FormQuickFilters/FormQuickFilters.js +46 -0
  79. package/hook-form/FormQuickFilters/constants.d.ts +6 -0
  80. package/hook-form/FormQuickFilters/constants.js +6 -0
  81. package/hook-form/FormQuickFilters/index.d.ts +2 -0
  82. package/hook-form/FormQuickFilters/index.js +1 -0
  83. package/hook-form/FormQuickFilters/public.d.ts +2 -0
  84. package/hook-form/FormQuickFilters/public.js +1 -0
  85. package/hook-form/FormQuickFilters/styles.d.ts +9 -0
  86. package/hook-form/FormQuickFilters/styles.js +16 -0
  87. package/hook-form/FormQuickFilters/types.d.ts +62 -0
  88. package/hook-form/FormQuickFilters/types.js +1 -0
  89. package/hook-form/FormQuickFilters/useLogic/useLogic.d.ts +18 -0
  90. package/hook-form/FormQuickFilters/useLogic/useLogic.js +59 -0
  91. package/hook-form/FormWizard/Footer/Footer.js +1 -1
  92. package/node/components/Badge/styles.js +5 -0
  93. package/node/components/Badge/types.d.ts +1 -1
  94. package/node/components/Chip/Chip.js +2 -2
  95. package/node/components/Chip/ChipProvider/ChipProvider.d.ts +26 -0
  96. package/node/components/Chip/ChipProvider/ChipProvider.js +17 -0
  97. package/node/components/Chip/ChipProvider/index.d.ts +1 -0
  98. package/node/components/Chip/ChipProvider/index.js +17 -0
  99. package/node/components/Chip/index.d.ts +2 -1
  100. package/node/components/Chip/index.js +3 -1
  101. package/node/components/Chip/public.d.ts +2 -1
  102. package/node/components/Chip/public.js +3 -1
  103. package/node/components/Chip/styles.d.ts +7 -3
  104. package/node/components/Chip/styles.js +27 -3
  105. package/node/components/Chip/types.d.ts +21 -1
  106. package/node/components/Chip/useLogic/useLogic.d.ts +5 -4
  107. package/node/components/Chip/useLogic/useLogic.js +10 -2
  108. package/node/components/Counter/Counter.d.ts +5 -1
  109. package/node/components/Counter/Counter.js +1 -1
  110. package/node/components/Counter/types.d.ts +1 -1
  111. package/node/components/DashboardSidebarCounter/styles.d.ts +1 -0
  112. package/node/components/DataGridPaginationContainer/styles.js +1 -1
  113. package/node/components/MenuOrganization/faker.js +112 -18
  114. package/node/components/PageContent/styles.js +1 -0
  115. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.d.ts +15 -0
  116. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.js +12 -0
  117. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/index.d.ts +1 -0
  118. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/index.js +6 -0
  119. package/node/components/PageHeader/HeaderContent/HeaderContent.js +2 -1
  120. package/node/components/PageHeader/HeaderContent/index.d.ts +1 -0
  121. package/node/components/PageHeader/HeaderContent/index.js +1 -0
  122. package/node/components/PageHeader/HeaderContent/styles.d.ts +0 -4
  123. package/node/components/PageHeader/HeaderContent/styles.js +2 -11
  124. package/node/components/PageHeader/PageActions/PageActions.js +1 -1
  125. package/node/components/PageHeader/constants.d.ts +2 -0
  126. package/node/components/PageHeader/constants.js +2 -0
  127. package/node/components/PageHeader/index.d.ts +1 -0
  128. package/node/components/PageHeader/index.js +3 -1
  129. package/node/components/PageHeader/styles.js +21 -0
  130. package/node/components/PageLayoutContainer/styles.js +6 -0
  131. package/node/components/TagBadge/styles.js +2 -1
  132. package/node/hook-form/FormFilters/AllFiltersButton/styles.d.ts +1 -0
  133. package/node/hook-form/FormFilters/AllFiltersButton/types.d.ts +1 -0
  134. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +1 -1
  135. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +27 -11
  136. package/node/hook-form/FormFilters/FormFilters.js +5 -2
  137. package/node/hook-form/FormFilters/FormFiltersDialog/FormFiltersDialog.js +3 -3
  138. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.d.ts +6 -0
  139. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.js +15 -0
  140. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.d.ts +1 -0
  141. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.js +17 -0
  142. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.d.ts +14 -0
  143. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.js +17 -0
  144. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.d.ts +1 -0
  145. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.js +17 -0
  146. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.d.ts +6 -0
  147. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.js +15 -0
  148. package/node/hook-form/FormFilters/FormFiltersDialog/styles.d.ts +1 -10
  149. package/node/hook-form/FormFilters/FormFiltersDialog/styles.js +2 -10
  150. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +4 -2
  151. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -5
  152. package/node/hook-form/FormFilters/FormFiltersSkeleton/FormFiltersSkeleton.js +4 -1
  153. package/node/hook-form/FormFilters/styles.d.ts +4 -0
  154. package/node/hook-form/FormFilters/styles.js +12 -3
  155. package/node/hook-form/FormFilters/types.d.ts +24 -4
  156. package/node/hook-form/FormFilters/useLogic/useLogic.d.ts +2 -1
  157. package/node/hook-form/FormFilters/useLogic/useLogic.js +12 -1
  158. package/node/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.d.ts +1 -0
  159. package/node/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.js +22 -0
  160. package/node/hook-form/FormFilters/utils/checkIsFilledValue/index.d.ts +1 -0
  161. package/node/hook-form/FormFilters/utils/checkIsFilledValue/index.js +5 -0
  162. package/node/hook-form/FormFilters/utils/getFilledCount/getFilledCount.d.ts +1 -0
  163. package/node/hook-form/FormFilters/utils/getFilledCount/getFilledCount.js +8 -0
  164. package/node/hook-form/FormFilters/utils/getFilledCount/index.d.ts +1 -0
  165. package/node/hook-form/FormFilters/utils/getFilledCount/index.js +5 -0
  166. package/node/hook-form/FormFilters/utils/index.d.ts +2 -0
  167. package/node/hook-form/FormFilters/utils/index.js +7 -0
  168. package/node/hook-form/FormQuickFilters/FormQuickFilters.d.ts +26 -0
  169. package/node/hook-form/FormQuickFilters/FormQuickFilters.js +50 -0
  170. package/node/hook-form/FormQuickFilters/constants.d.ts +6 -0
  171. package/node/hook-form/FormQuickFilters/constants.js +9 -0
  172. package/node/hook-form/FormQuickFilters/index.d.ts +2 -0
  173. package/node/hook-form/FormQuickFilters/index.js +5 -0
  174. package/node/hook-form/FormQuickFilters/public.d.ts +2 -0
  175. package/node/hook-form/FormQuickFilters/public.js +5 -0
  176. package/node/hook-form/FormQuickFilters/styles.d.ts +9 -0
  177. package/node/hook-form/FormQuickFilters/styles.js +19 -0
  178. package/node/hook-form/FormQuickFilters/types.d.ts +62 -0
  179. package/node/hook-form/FormQuickFilters/types.js +2 -0
  180. package/node/hook-form/FormQuickFilters/useLogic/useLogic.d.ts +18 -0
  181. package/node/hook-form/FormQuickFilters/useLogic/useLogic.js +63 -0
  182. package/node/hook-form/FormWizard/Footer/Footer.js +1 -1
  183. package/package.json +1 -1
@@ -22,6 +22,27 @@ export const Wrapper = styled.header `
22
22
 
23
23
  background-color: ${({ theme }) => theme.palette.background.default};
24
24
  }
25
+
26
+ .${pageHeaderClassnames.filters} {
27
+ grid-column: 1 / -1;
28
+ grid-row: 4;
29
+
30
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
31
+ grid-column: 3;
32
+ grid-row: 1 / -1;
33
+ }
34
+ }
35
+
36
+ .${pageHeaderClassnames.quickFilters} {
37
+ grid-column: 1 / -1;
38
+ grid-row: 5;
39
+
40
+ margin-top: ${({ theme }) => theme.spacing(4)};
41
+
42
+ ${({ theme }) => theme.breakpoints.down('sm')} {
43
+ display: none;
44
+ }
45
+ }
25
46
  `;
26
47
  export const MobileTitleWrapper = styled.div `
27
48
  display: none;
@@ -13,6 +13,12 @@ export const Wrapper = styled.div `
13
13
 
14
14
  background-color: ${({ theme }) => theme.palette.common.white};
15
15
 
16
+ ${({ theme }) => theme.breakpoints.down('laptop')} {
17
+ grid-row-gap: ${({ theme }) => theme.spacing(2)};
18
+
19
+ padding-top: ${({ theme }) => theme.spacing(3)};
20
+ }
21
+
16
22
  ${({ theme }) => theme.breakpoints.down('sm')} {
17
23
  scroll-behavior: smooth;
18
24
 
@@ -11,6 +11,7 @@ const getBadgeBgColor = ({ color, theme, variant, }) => {
11
11
  warning: theme.palette.warning[800],
12
12
  error: theme.palette.error[800],
13
13
  white: theme.palette.grey[300],
14
+ transparent: 'transparent',
14
15
  };
15
16
  return bgColor[color];
16
17
  };
@@ -24,7 +25,7 @@ const getBadgeColor = ({ color, theme, variant, isChecked, isDisabled, }) => {
24
25
  if (color === 'white') {
25
26
  return theme.palette.grey[900];
26
27
  }
27
- if (color === 'grey') {
28
+ if (color === 'grey' || color === 'transparent') {
28
29
  return variant === 'text'
29
30
  ? theme.palette.primary.contrastText
30
31
  : theme.palette.grey[900];
@@ -17,6 +17,7 @@ export declare const StyledCounter: import("../../../components/styled").StyledC
17
17
  color: import("../../../components/Counter/types").CounterColor;
18
18
  variant?: import("../../../components/Counter/types").CounterVariants | undefined;
19
19
  content?: number | undefined;
20
+ withBorder?: boolean | undefined;
20
21
  } & {
21
22
  theme?: import("@emotion/react").Theme | undefined;
22
23
  }, {}, {}>;
@@ -5,4 +5,5 @@ export type AllFiltersButtonProps<TFieldValues extends Record<string, unknown>>
5
5
  hasMainFilters: boolean;
6
6
  hasSecondaryFilters: boolean;
7
7
  hasSearch: boolean;
8
+ hasQuickFilters: boolean;
8
9
  };
@@ -1,5 +1,5 @@
1
1
  import { type AllFiltersButtonProps } from '../types';
2
- export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, }: AllFiltersButtonProps<TFieldValues>) => {
2
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, hasQuickFilters, }: AllFiltersButtonProps<TFieldValues>) => {
3
3
  allFiltersButtonClassName: string;
4
4
  counter: number;
5
5
  onOpenModal: () => void;
@@ -1,22 +1,38 @@
1
1
  import { useEffect, useMemo, useState } from 'react';
2
2
  import { useWatch } from 'react-hook-form';
3
+ import { useViewportType } from '../../../../components/useViewportType';
3
4
  import { classNames } from '../../../../components/utils/classNames';
4
5
  import { FORM_FILTERS_SEARCH_FIELD_ID } from '../../../FormFiltersSearchField/constants';
6
+ import { FORM_FILTERS_QUICK_FILTERS_ID } from '../../../FormQuickFilters/constants';
5
7
  import { formFiltersClassnames } from '../../constants';
6
- export const useLogic = ({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, }) => {
8
+ import { checkIsFilledValue, getFilledCount } from '../../utils';
9
+ export const useLogic = ({ form, onOpenModal, hasMainFilters, hasSecondaryFilters, hasSearch, hasQuickFilters, }) => {
10
+ const { isMobile } = useViewportType();
7
11
  const formValues = useWatch({
8
12
  control: form.control,
9
13
  });
10
14
  const [searchName, setSearchName] = useState('');
15
+ const [quickFiltersName, setQuickFiltersName] = useState('');
11
16
  useEffect(() => {
12
17
  const searchFieldName = document
13
18
  .getElementById(FORM_FILTERS_SEARCH_FIELD_ID)
14
19
  ?.getAttribute('name') || '';
15
20
  setSearchName(searchFieldName);
16
21
  }, [hasSearch]);
17
- // Исключаем поиск из счетчика фильтров
18
- const counter = Object.values(formValues || {}).filter(Boolean).length -
19
- (formValues?.[searchName] ? 1 : 0);
22
+ useEffect(() => {
23
+ const quickFiltersFieldName = document
24
+ .getElementById(FORM_FILTERS_QUICK_FILTERS_ID)
25
+ ?.getAttribute('name') || '';
26
+ setQuickFiltersName(quickFiltersFieldName);
27
+ }, [hasQuickFilters]);
28
+ const getCounter = () => {
29
+ const filledValuesCount = getFilledCount(formValues);
30
+ // Исключаем поиск и quickFilters из счётчика — они видны на странице
31
+ // quickFilters учитывается только на мобильных устройствах
32
+ const searchValue = formValues?.[searchName];
33
+ const quickFiltersValue = !isMobile && checkIsFilledValue(formValues?.[quickFiltersName]);
34
+ return (filledValuesCount - (searchValue ? 1 : 0) - (quickFiltersValue ? 1 : 0));
35
+ };
20
36
  const allFiltersButtonClassName = useMemo(() => {
21
37
  return classNames({
22
38
  [formFiltersClassnames.showAllFiltersButtonOnDesktop]: hasSecondaryFilters,
@@ -28,7 +44,7 @@ export const useLogic = ({ form, onOpenModal, hasMainFilters, hasSecondaryFilter
28
44
  }, [hasMainFilters, hasSecondaryFilters, hasSearch]);
29
45
  return {
30
46
  allFiltersButtonClassName,
31
- counter,
47
+ counter: getCounter(),
32
48
  onOpenModal,
33
49
  };
34
50
  };
@@ -1,19 +1,22 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import { FormFiltersLayoutContext } from '../../components/PageHeader';
2
4
  import { Form } from '../Form';
3
5
  import { FormControlProvider } from '../FormControlProvider';
4
6
  import { AllFiltersButton } from './AllFiltersButton';
5
7
  import { formFiltersClassnames } from './constants';
6
8
  import { FormFiltersDialog } from './FormFiltersDialog';
7
9
  import { FormFiltersSkeleton } from './FormFiltersSkeleton';
8
- import { MainFiltersWrapper, SubmitButtonWrapper, Wrapper } from './styles';
10
+ import { MainFiltersWrapper, QuickFiltersWrapper, SubmitButtonWrapper, Wrapper, } from './styles';
9
11
  import { useLogic } from './useLogic';
10
12
  /**
11
13
  * Компонент для отображения фильтров формы
12
14
  */
13
15
  export const FormFilters = (props) => {
14
- const { form, onSubmit, searchField: SearchField, mainFilters: MainFilters, submitButton: SubmitButton, secondaryFilters: SecondaryFilters, onOpenModal, dialogProps, mainFiltersColumns, isLoading, } = useLogic(props);
16
+ const { form, onSubmit, searchField: SearchField, mainFilters: MainFilters, quickFilters: QuickFilters, submitButton: SubmitButton, secondaryFilters: SecondaryFilters, onOpenModal, dialogProps, mainFiltersColumns, isLoading, } = useLogic(props);
17
+ const { filtersClassName, quickFiltersClassName } = useContext(FormFiltersLayoutContext) ?? {};
15
18
  if (isLoading) {
16
19
  return _jsx(FormFiltersSkeleton, {});
17
20
  }
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 })] }));
21
+ return (_jsxs(_Fragment, { children: [_jsx(FormControlProvider, { size: "small", hideHelperText: true, children: _jsx(Form, { name: "astral-ui-form-filters", form: form, onSubmit: form.handleSubmit(onSubmit || (() => undefined)), className: filtersClassName, 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), hasQuickFilters: Boolean(QuickFilters) }), _jsx(MainFiltersWrapper, { columns: mainFiltersColumns, children: MainFilters && (_jsx(MainFilters, { control: form.control, isModal: false })) }), SubmitButton && (_jsx(SubmitButtonWrapper, { children: _jsx(SubmitButton, { size: "medium", className: formFiltersClassnames.submitButton }) }))] }) }) }), QuickFilters && (_jsx(QuickFiltersWrapper, { className: quickFiltersClassName, children: _jsx(QuickFilters, { control: form.control }) })), _jsx(FormFiltersDialog, { ...dialogProps })] }));
19
22
  };
@@ -3,13 +3,13 @@ import { Button } from '../../../components/Button';
3
3
  import { DialogContent } from '../../../components/DialogContent';
4
4
  import { Form } from '../../Form';
5
5
  import { formFiltersClassnames } from '../constants';
6
- import { DesktopResetButton, FiltersModalContent, MobileResetButton, StyledDialog, StyledDialogContent, } from './styles';
6
+ import { ResetButton } from './ResetButton';
7
+ import { FiltersModalContent, QuickFiltersWrapper, StyledDialog, StyledDialogContent, } from './styles';
7
8
  import { useLogic } from './useLogic';
8
9
  /**
9
10
  * Компонент для отображения фильтров формы
10
11
  */
11
12
  export const FormFiltersDialog = (props) => {
12
- const { modalForm, onCloseModal, onResetModal, onSubmitModal, mainFilters: MainFilters, secondaryFilters: SecondaryFilters, isModalOpen, isResetButtonDisabled, } = useLogic(props);
13
- const headerContent = (_jsx(MobileResetButton, { variant: "text", onClick: onResetModal, size: "large", disabled: isResetButtonDisabled, children: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C" }));
14
- return (_jsx(StyledDialog, { open: isModalOpen, onClose: onCloseModal, title: "\u0424\u0438\u043B\u044C\u0442\u0440\u044B", size: "md", headerContent: headerContent, children: _jsxs(Form, { form: modalForm, onSubmit: modalForm.handleSubmit(onSubmitModal), children: [_jsx(DialogContent, { children: _jsxs(FiltersModalContent, { className: formFiltersClassnames.modalFilters, children: [MainFilters && (_jsx(MainFilters, { control: modalForm.control, isModal: true })), SecondaryFilters && (_jsx(SecondaryFilters, { control: modalForm.control }))] }) }), _jsxs(StyledDialogContent, { children: [_jsx(DesktopResetButton, { children: _jsx(Button, { variant: "text", onClick: onResetModal, size: "large", disabled: isResetButtonDisabled, children: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C" }) }), _jsx(Button, { variant: "text", onClick: onCloseModal, size: "large", children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { type: "submit", variant: "contained", size: "large", children: "\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C" })] })] }) }));
13
+ const { modalForm, onCloseModal, onResetModal, onSubmitModal, mainFilters: MainFilters, quickFilters: QuickFilters, secondaryFilters: SecondaryFilters, isModalOpen, } = useLogic(props);
14
+ return (_jsx(StyledDialog, { open: isModalOpen, onClose: onCloseModal, title: "\u0424\u0438\u043B\u044C\u0442\u0440\u044B", size: "md", headerContent: _jsx(ResetButton, { onResetModal: onResetModal, modalForm: modalForm, isMobile: true }), children: _jsxs(Form, { form: modalForm, onSubmit: modalForm.handleSubmit(onSubmitModal), children: [_jsx(DialogContent, { children: _jsxs(FiltersModalContent, { className: formFiltersClassnames.modalFilters, children: [MainFilters && (_jsx(MainFilters, { control: modalForm.control, isModal: true })), SecondaryFilters && (_jsx(SecondaryFilters, { control: modalForm.control })), QuickFilters && (_jsx(QuickFiltersWrapper, { children: _jsx(QuickFilters, { control: modalForm.control }) }))] }) }), _jsxs(StyledDialogContent, { children: [_jsx(ResetButton, { onResetModal: onResetModal, modalForm: modalForm }), _jsx(Button, { variant: "text", onClick: onCloseModal, size: "large", children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsx(Button, { type: "submit", variant: "contained", size: "large", children: "\u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C" })] })] }) }));
15
15
  };
@@ -0,0 +1,6 @@
1
+ import { type UseFormReturn } from 'react-hook-form';
2
+ export declare const ResetButton: <TFieldValues extends Record<string, unknown>>({ onResetModal, modalForm, isMobile, }: {
3
+ onResetModal: () => void;
4
+ modalForm: UseFormReturn<TFieldValues>;
5
+ isMobile?: boolean | undefined;
6
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button } from '../../../../components/Button';
3
+ import { DesktopResetButtonWrapper, MobileResetButtonWrapper } from './styles';
4
+ import { useLogic } from './useLogic';
5
+ export const ResetButton = ({ onResetModal, modalForm, isMobile = false, }) => {
6
+ const { isResetButtonDisabled } = useLogic({ modalForm });
7
+ if (isMobile) {
8
+ return (_jsx(MobileResetButtonWrapper, { variant: "text", onClick: onResetModal, size: "large", disabled: isResetButtonDisabled, children: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C" }));
9
+ }
10
+ return (_jsx(DesktopResetButtonWrapper, { children: _jsx(Button, { variant: "text", onClick: onResetModal, size: "large", disabled: isResetButtonDisabled, color: "error", children: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C" }) }));
11
+ };
@@ -0,0 +1 @@
1
+ export * from './ResetButton';
@@ -0,0 +1 @@
1
+ export * from './ResetButton';
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ export declare const MobileResetButtonWrapper: import("../../../../components/styled").StyledComponent<Omit<import("../../../..").WithoutEmotionSpecific<import("@mui/material").ButtonProps>, "color" | "component" | "variant" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple"> & {
3
+ variant?: "light" | "link" | "text" | "contained" | "outlined" | undefined;
4
+ loading?: boolean | undefined;
5
+ color?: "primary" | "success" | "warning" | "error" | "grey" | undefined;
6
+ component?: import("react").ElementType | undefined;
7
+ selected?: boolean | undefined;
8
+ } & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, ""> & import("react").RefAttributes<HTMLButtonElement> & {
9
+ theme?: import("@emotion/react").Theme | undefined;
10
+ }, {}, {}>;
11
+ export declare const DesktopResetButtonWrapper: import("../../../../components/styled").StyledComponent<{
12
+ theme?: import("@emotion/react").Theme | undefined;
13
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
14
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -0,0 +1,14 @@
1
+ import { Button } from '../../../../components/Button';
2
+ import { styled } from '../../../../components/styled';
3
+ export const MobileResetButtonWrapper = styled(Button) `
4
+ margin-left: auto;
5
+
6
+ ${({ theme }) => theme.breakpoints.up('sm')} {
7
+ display: none;
8
+ }
9
+ `;
10
+ export const DesktopResetButtonWrapper = styled.div `
11
+ ${({ theme }) => theme.breakpoints.down('sm')} {
12
+ display: none;
13
+ }
14
+ `;
@@ -0,0 +1 @@
1
+ export * from './useLogic';
@@ -0,0 +1 @@
1
+ export * from './useLogic';
@@ -0,0 +1,6 @@
1
+ import { type UseFormReturn } from 'react-hook-form';
2
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ modalForm, }: {
3
+ modalForm: UseFormReturn<TFieldValues>;
4
+ }) => {
5
+ isResetButtonDisabled: boolean;
6
+ };
@@ -0,0 +1,11 @@
1
+ import { useWatch } from 'react-hook-form';
2
+ import { getFilledCount } from '../../../utils';
3
+ export const useLogic = ({ modalForm, }) => {
4
+ const formValues = useWatch({
5
+ control: modalForm.control,
6
+ });
7
+ const isResetButtonDisabled = getFilledCount(formValues) === 0;
8
+ return {
9
+ isResetButtonDisabled,
10
+ };
11
+ };
@@ -3,16 +3,7 @@ export declare const FiltersModalContent: import("../../../components/styled").S
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 MobileResetButton: import("../../../components/styled").StyledComponent<Omit<import("../../..").WithoutEmotionSpecific<import("@mui/material").ButtonProps>, "color" | "component" | "variant" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple"> & {
7
- variant?: "light" | "link" | "text" | "contained" | "outlined" | undefined;
8
- loading?: boolean | undefined;
9
- color?: "primary" | "success" | "warning" | "error" | "grey" | undefined;
10
- component?: import("react").ElementType | undefined;
11
- selected?: boolean | undefined;
12
- } & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, ""> & import("react").RefAttributes<HTMLButtonElement> & {
13
- theme?: import("@emotion/react").Theme | undefined;
14
- }, {}, {}>;
15
- export declare const DesktopResetButton: import("../../../components/styled").StyledComponent<{
6
+ export declare const QuickFiltersWrapper: import("../../../components/styled").StyledComponent<{
16
7
  theme?: import("@emotion/react").Theme | undefined;
17
8
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
18
9
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -1,23 +1,15 @@
1
1
  import { dialogClasses } from '@mui/material/Dialog';
2
- import { Button } from '../../../components/Button';
3
2
  import { Dialog } from '../../../components/Dialog';
4
3
  import { DialogActions } from '../../../components/DialogActions';
5
4
  import { styled } from '../../../components/styled';
6
5
  export const FiltersModalContent = styled.div `
7
6
  display: grid;
8
7
  `;
9
- export const MobileResetButton = styled(Button) `
10
- margin-left: auto;
11
-
8
+ export const QuickFiltersWrapper = styled.div `
12
9
  ${({ theme }) => theme.breakpoints.up('sm')} {
13
10
  display: none;
14
11
  }
15
12
  `;
16
- export const DesktopResetButton = styled.div `
17
- ${({ theme }) => theme.breakpoints.down('sm')} {
18
- display: none;
19
- }
20
- `;
21
13
  export const StyledDialog = styled(Dialog) `
22
14
  .${dialogClasses.paper} {
23
15
  min-width: 500px;
@@ -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, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, onSubmit, form, }: FormFiltersDialogProps<TFieldValues>) => {
3
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ validationSchema, defaultValues, mainFilters, quickFilters, 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;
@@ -10,9 +10,11 @@ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({
10
10
  } & {
11
11
  isModal?: boolean | undefined;
12
12
  }) => import("react").ReactNode) | undefined;
13
+ quickFilters: ((props: Pick<{
14
+ control: import("react-hook-form").Control<TFieldValues>;
15
+ }, "control">) => import("react").ReactNode) | undefined;
13
16
  secondaryFilters: ((props: {
14
17
  control: import("react-hook-form").Control<TFieldValues>;
15
18
  }) => import("react").ReactNode) | undefined;
16
19
  isModalOpen: boolean;
17
- isResetButtonDisabled: boolean;
18
20
  };
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from 'react';
2
2
  import { useForm } from '../../../useForm';
3
- export const useLogic = ({ validationSchema, mainFilters, secondaryFilters, isModalOpen, setIsModalOpen, onSubmit, form, }) => {
3
+ export const useLogic = ({ validationSchema, defaultValues, mainFilters, quickFilters, secondaryFilters, isModalOpen, setIsModalOpen, onSubmit, form, }) => {
4
4
  const modalForm = useForm({
5
5
  validationSchema,
6
6
  defaultValues: form.getValues(),
@@ -10,16 +10,15 @@ export const useLogic = ({ validationSchema, mainFilters, secondaryFilters, isMo
10
10
  modalForm.reset();
11
11
  };
12
12
  const onResetModal = () => {
13
- modalForm.reset(form.getValues());
13
+ modalForm.reset(defaultValues);
14
14
  };
15
15
  const onSubmitModal = (submittedValues) => {
16
16
  onSubmit(submittedValues);
17
17
  setIsModalOpen(false);
18
18
  };
19
- const isResetButtonDisabled = !modalForm.formState.isDirty;
20
19
  useEffect(() => {
21
20
  if (isModalOpen) {
22
- onResetModal();
21
+ modalForm.reset(form.getValues());
23
22
  }
24
23
  }, [isModalOpen]);
25
24
  return {
@@ -28,8 +27,8 @@ export const useLogic = ({ validationSchema, mainFilters, secondaryFilters, isMo
28
27
  onResetModal,
29
28
  onSubmitModal,
30
29
  mainFilters,
30
+ quickFilters,
31
31
  secondaryFilters,
32
32
  isModalOpen,
33
- isResetButtonDisabled,
34
33
  };
35
34
  };
@@ -1,6 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import { FormFiltersLayoutContext } from '../../../components/PageHeader';
2
4
  import { Skeleton } from '../../../components/Skeleton';
3
5
  import { SkeletonWrapper } from './styles';
4
6
  export const FormFiltersSkeleton = () => {
5
- return (_jsxs(SkeletonWrapper, { children: [_jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" })] }));
7
+ const { filtersClassName } = useContext(FormFiltersLayoutContext) ?? {};
8
+ return (_jsxs(SkeletonWrapper, { className: filtersClassName, children: [_jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" }), _jsx(Skeleton, { variant: "rounded" })] }));
6
9
  };
@@ -13,3 +13,7 @@ export declare const SubmitButtonWrapper: import("../../components/styled").Styl
13
13
  theme?: import("@emotion/react").Theme | undefined;
14
14
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
15
15
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
16
+ export declare const QuickFiltersWrapper: import("../../components/styled").StyledComponent<{
17
+ theme?: import("@emotion/react").Theme | undefined;
18
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
19
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -7,13 +7,13 @@ export const Wrapper = styled.div `
7
7
  gap: ${({ theme }) => theme.spacing(2)};
8
8
  justify-content: space-between;
9
9
 
10
- width: 100%;
10
+ width: 100%;
11
11
  margin-top: ${({ theme }) => theme.spacing(4)};
12
12
 
13
13
  .${formLabelClasses.root} {
14
14
  display: none;
15
15
  }
16
-
16
+
17
17
  ${({ theme }) => theme.breakpoints.down('laptop')} {
18
18
  margin-top: 0;
19
19
  padding-right: ${({ theme }) => theme.spacing(2)};
@@ -52,3 +52,12 @@ export const SubmitButtonWrapper = styled.div `
52
52
  display: none;
53
53
  }
54
54
  `;
55
+ export const QuickFiltersWrapper = styled.div `
56
+ display: flex;
57
+
58
+ width: 100%;
59
+
60
+ ${({ theme }) => theme.breakpoints.down('sm')} {
61
+ display: none;
62
+ }
63
+ `;
@@ -18,18 +18,38 @@ export type FormFiltersProps<TFieldValues extends Record<string, unknown>> = {
18
18
  * @example
19
19
  * ```ts
20
20
  * <FormFilters
21
- * SearchField={({control}) => <FormFiltersSearchField control={control} placeholder="Поиск..." />}
21
+ * searchField={({control}) => <FormFiltersSearchField control={control} placeholder="Поиск..." />}
22
22
  * />
23
23
  * ```
24
24
  */
25
25
  searchField?: (props: InputsProps<TFieldValues>) => ReactNode;
26
+ /**
27
+ * Быстрые фильтры — группа чипов.
28
+ * На больших экранах отображаются строкой чипов под mainFilters,
29
+ * на маленьких разрешениях — последним элементом внутри модалки (как Select).
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * <FormFilters
34
+ * quickFilters={({ control }) => (
35
+ * <FormQuickFilters
36
+ * control={control}
37
+ * name="status"
38
+ * label="Статус"
39
+ * options={[{ label: 'Активные', value: 'active' }]}
40
+ * />
41
+ * )}
42
+ * />
43
+ * ```
44
+ */
45
+ quickFilters?: (props: Pick<InputsProps<TFieldValues>, 'control'>) => ReactNode;
26
46
  /**
27
47
  * Основные фильтры
28
48
  *
29
49
  * @example
30
50
  * ```ts
31
51
  * <FormFilters
32
- * MainFilters={({ control, isModal }) =>
52
+ * mainFilters={({ control, isModal }) =>
33
53
  * <FormTextField
34
54
  * control={control}
35
55
  * name="name"
@@ -48,7 +68,7 @@ export type FormFiltersProps<TFieldValues extends Record<string, unknown>> = {
48
68
  * @example
49
69
  * ```ts
50
70
  * <FormFilters
51
- * SecondaryFilters={({ control }) => <FormTextField control={control} name="name" label="Название" placeholder="Введите название" />}
71
+ * secondaryFilters={({ control }) => <FormTextField control={control} name="name" label="Название" placeholder="Введите название" />}
52
72
  * />
53
73
  * ```
54
74
  */
@@ -59,7 +79,7 @@ export type FormFiltersProps<TFieldValues extends Record<string, unknown>> = {
59
79
  * @example
60
80
  * ```ts
61
81
  * <FormFilters
62
- * SubmitButton={(props) => <Button {...props} loading={isLoading}>Применить</Button>}
82
+ * submitButton={(props) => <Button {...props} loading={isLoading}>Применить</Button>}
63
83
  * />
64
84
  * ```
65
85
  */
@@ -6,6 +6,7 @@ type UseLogicReturn<TFieldValues extends Record<string, unknown>> = {
6
6
  onSubmit?: (values: TFieldValues) => void;
7
7
  searchField: FormFiltersProps<TFieldValues>['searchField'];
8
8
  mainFilters: FormFiltersProps<TFieldValues>['mainFilters'];
9
+ quickFilters: FormFiltersProps<TFieldValues>['quickFilters'];
9
10
  submitButton: FormFiltersProps<TFieldValues>['submitButton'];
10
11
  secondaryFilters: FormFiltersProps<TFieldValues>['secondaryFilters'];
11
12
  onOpenModal: () => void;
@@ -13,5 +14,5 @@ type UseLogicReturn<TFieldValues extends Record<string, unknown>> = {
13
14
  mainFiltersColumns?: string;
14
15
  isLoading?: boolean;
15
16
  };
16
- export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onSubmit, validationSchema, searchField, mainFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }: FormFiltersProps<TFieldValues>) => UseLogicReturn<TFieldValues>;
17
+ export declare const useLogic: <TFieldValues extends Record<string, unknown>>({ form, onSubmit, validationSchema, searchField, mainFilters, quickFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }: FormFiltersProps<TFieldValues>) => UseLogicReturn<TFieldValues>;
17
18
  export {};
@@ -1,6 +1,14 @@
1
- import { useState } from 'react';
2
- export const useLogic = ({ form, onSubmit, validationSchema, searchField, mainFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }) => {
1
+ import { useEffect, useState } from 'react';
2
+ import { useFirstMountAfterLoading } from './hooks';
3
+ export const useLogic = ({ form, onSubmit, validationSchema, searchField, mainFilters, quickFilters, secondaryFilters, submitButton, mainFiltersColumns, isLoading, }) => {
3
4
  const [isModalOpen, setIsModalOpen] = useState(false);
5
+ const [defaultValues, setDefaultValues] = useState({});
6
+ const isFirstMountAfterLoading = useFirstMountAfterLoading(isLoading);
7
+ useEffect(() => {
8
+ if (isFirstMountAfterLoading) {
9
+ setDefaultValues(form.getValues());
10
+ }
11
+ }, [form]);
4
12
  const onOpenModal = () => {
5
13
  setIsModalOpen(true);
6
14
  };
@@ -12,16 +20,19 @@ export const useLogic = ({ form, onSubmit, validationSchema, searchField, mainFi
12
20
  validationSchema,
13
21
  form,
14
22
  mainFilters,
23
+ quickFilters,
15
24
  secondaryFilters,
16
25
  onSubmit: onSubmitModal,
17
26
  isModalOpen,
18
27
  setIsModalOpen,
28
+ defaultValues,
19
29
  };
20
30
  return {
21
31
  form,
22
32
  onSubmit,
23
33
  searchField,
24
34
  mainFilters,
35
+ quickFilters,
25
36
  secondaryFilters,
26
37
  submitButton,
27
38
  onOpenModal,
@@ -0,0 +1 @@
1
+ export declare function checkIsFilledValue(value: unknown): boolean;
@@ -0,0 +1,18 @@
1
+ export function checkIsFilledValue(value) {
2
+ if (value === null || value === undefined) {
3
+ return false;
4
+ }
5
+ if (typeof value === 'string') {
6
+ return value.trim() !== '';
7
+ }
8
+ if (Array.isArray(value)) {
9
+ return Boolean(value?.length);
10
+ }
11
+ if (typeof value === 'object') {
12
+ return Object.values(value).some((v) => checkIsFilledValue(v));
13
+ }
14
+ if (typeof value === 'number') {
15
+ return Number.isFinite(value);
16
+ }
17
+ return Boolean(value);
18
+ }
@@ -0,0 +1 @@
1
+ export { checkIsFilledValue } from './checkIsFilledValue';
@@ -0,0 +1 @@
1
+ export { checkIsFilledValue } from './checkIsFilledValue';
@@ -0,0 +1 @@
1
+ export declare const getFilledCount: (formValues: Record<string, unknown>) => number;
@@ -0,0 +1,4 @@
1
+ import { checkIsFilledValue } from '../checkIsFilledValue/checkIsFilledValue';
2
+ export const getFilledCount = (formValues) => {
3
+ return Object.values(formValues || {}).filter(checkIsFilledValue).length;
4
+ };
@@ -0,0 +1 @@
1
+ export { getFilledCount } from './getFilledCount';
@@ -0,0 +1 @@
1
+ export { getFilledCount } from './getFilledCount';
@@ -0,0 +1,2 @@
1
+ export { checkIsFilledValue } from './checkIsFilledValue';
2
+ export { getFilledCount } from './getFilledCount';
@@ -0,0 +1,2 @@
1
+ export { checkIsFilledValue } from './checkIsFilledValue';
2
+ export { getFilledCount } from './getFilledCount';
@@ -0,0 +1,26 @@
1
+ import type { FormQuickFiltersProps } from './types';
2
+ /**
3
+ * Группа чипов для быстрых фильтров внутри FormFilters (слот quickFilters).
4
+ *
5
+ * Поведение чипов задаётся параметром `multiple` через `ChipProvider mode`:
6
+ * - false (default) — `single` (radio)
7
+ * - true — `multiple` (checkbox)
8
+ *
9
+ * - На мобильных устройствах отображается как Select
10
+ *
11
+ * @example
12
+ * <FormFilters
13
+ * quickFilters={({ control }) => (
14
+ * <FormQuickFilters
15
+ * control={control}
16
+ * name="status"
17
+ * label="Статус"
18
+ * options={[
19
+ * { label: 'Активные', value: 'active' },
20
+ * { label: 'Архив', value: 'archived' },
21
+ * ]}
22
+ * />
23
+ * )}
24
+ * />
25
+ */
26
+ export declare const FormQuickFilters: <TFieldValues extends object>(props: FormQuickFiltersProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;