@astral/ui 4.34.1 → 4.35.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 (175) 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/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.d.ts +15 -0
  22. package/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.js +8 -0
  23. package/components/PageHeader/HeaderContent/FormFiltersProvider/index.d.ts +1 -0
  24. package/components/PageHeader/HeaderContent/FormFiltersProvider/index.js +1 -0
  25. package/components/PageHeader/HeaderContent/HeaderContent.js +3 -2
  26. package/components/PageHeader/HeaderContent/index.d.ts +1 -0
  27. package/components/PageHeader/HeaderContent/index.js +1 -0
  28. package/components/PageHeader/HeaderContent/styles.d.ts +0 -4
  29. package/components/PageHeader/HeaderContent/styles.js +1 -10
  30. package/components/PageHeader/PageActions/PageActions.js +1 -1
  31. package/components/PageHeader/constants.d.ts +2 -0
  32. package/components/PageHeader/constants.js +2 -0
  33. package/components/PageHeader/index.d.ts +1 -0
  34. package/components/PageHeader/index.js +1 -0
  35. package/components/PageHeader/styles.js +25 -0
  36. package/components/TagBadge/styles.js +2 -1
  37. package/hook-form/FormFilters/AllFiltersButton/styles.d.ts +1 -0
  38. package/hook-form/FormFilters/AllFiltersButton/types.d.ts +1 -0
  39. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +1 -1
  40. package/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +21 -5
  41. package/hook-form/FormFilters/FormFilters.js +7 -4
  42. package/hook-form/FormFilters/FormFiltersDialog/FormFiltersDialog.js +4 -4
  43. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.d.ts +6 -0
  44. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.js +11 -0
  45. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.d.ts +1 -0
  46. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.js +1 -0
  47. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.d.ts +14 -0
  48. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.js +14 -0
  49. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.d.ts +1 -0
  50. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.js +1 -0
  51. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.d.ts +6 -0
  52. package/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.js +11 -0
  53. package/hook-form/FormFilters/FormFiltersDialog/styles.d.ts +1 -10
  54. package/hook-form/FormFilters/FormFiltersDialog/styles.js +1 -9
  55. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +4 -2
  56. package/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -5
  57. package/hook-form/FormFilters/FormFiltersSkeleton/FormFiltersSkeleton.js +4 -1
  58. package/hook-form/FormFilters/styles.d.ts +4 -0
  59. package/hook-form/FormFilters/styles.js +11 -2
  60. package/hook-form/FormFilters/types.d.ts +24 -4
  61. package/hook-form/FormFilters/useLogic/useLogic.d.ts +2 -1
  62. package/hook-form/FormFilters/useLogic/useLogic.js +13 -2
  63. package/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.d.ts +1 -0
  64. package/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.js +18 -0
  65. package/hook-form/FormFilters/utils/checkIsFilledValue/index.d.ts +1 -0
  66. package/hook-form/FormFilters/utils/checkIsFilledValue/index.js +1 -0
  67. package/hook-form/FormFilters/utils/getFilledCount/getFilledCount.d.ts +1 -0
  68. package/hook-form/FormFilters/utils/getFilledCount/getFilledCount.js +4 -0
  69. package/hook-form/FormFilters/utils/getFilledCount/index.d.ts +1 -0
  70. package/hook-form/FormFilters/utils/getFilledCount/index.js +1 -0
  71. package/hook-form/FormFilters/utils/index.d.ts +2 -0
  72. package/hook-form/FormFilters/utils/index.js +2 -0
  73. package/hook-form/FormQuickFilters/FormQuickFilters.d.ts +26 -0
  74. package/hook-form/FormQuickFilters/FormQuickFilters.js +46 -0
  75. package/hook-form/FormQuickFilters/constants.d.ts +6 -0
  76. package/hook-form/FormQuickFilters/constants.js +6 -0
  77. package/hook-form/FormQuickFilters/index.d.ts +2 -0
  78. package/hook-form/FormQuickFilters/index.js +1 -0
  79. package/hook-form/FormQuickFilters/public.d.ts +2 -0
  80. package/hook-form/FormQuickFilters/public.js +1 -0
  81. package/hook-form/FormQuickFilters/styles.d.ts +9 -0
  82. package/hook-form/FormQuickFilters/styles.js +16 -0
  83. package/hook-form/FormQuickFilters/types.d.ts +62 -0
  84. package/hook-form/FormQuickFilters/types.js +1 -0
  85. package/hook-form/FormQuickFilters/useLogic/useLogic.d.ts +18 -0
  86. package/hook-form/FormQuickFilters/useLogic/useLogic.js +59 -0
  87. package/hook-form/FormWizard/Footer/Footer.js +1 -1
  88. package/node/components/Badge/styles.js +5 -0
  89. package/node/components/Badge/types.d.ts +1 -1
  90. package/node/components/Chip/Chip.js +2 -2
  91. package/node/components/Chip/ChipProvider/ChipProvider.d.ts +26 -0
  92. package/node/components/Chip/ChipProvider/ChipProvider.js +17 -0
  93. package/node/components/Chip/ChipProvider/index.d.ts +1 -0
  94. package/node/components/Chip/ChipProvider/index.js +17 -0
  95. package/node/components/Chip/index.d.ts +2 -1
  96. package/node/components/Chip/index.js +3 -1
  97. package/node/components/Chip/public.d.ts +2 -1
  98. package/node/components/Chip/public.js +3 -1
  99. package/node/components/Chip/styles.d.ts +7 -3
  100. package/node/components/Chip/styles.js +27 -3
  101. package/node/components/Chip/types.d.ts +21 -1
  102. package/node/components/Chip/useLogic/useLogic.d.ts +5 -4
  103. package/node/components/Chip/useLogic/useLogic.js +10 -2
  104. package/node/components/Counter/Counter.d.ts +5 -1
  105. package/node/components/Counter/Counter.js +1 -1
  106. package/node/components/Counter/types.d.ts +1 -1
  107. package/node/components/DashboardSidebarCounter/styles.d.ts +1 -0
  108. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.d.ts +15 -0
  109. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/FormFiltersProvider.js +12 -0
  110. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/index.d.ts +1 -0
  111. package/node/components/PageHeader/HeaderContent/FormFiltersProvider/index.js +6 -0
  112. package/node/components/PageHeader/HeaderContent/HeaderContent.js +2 -1
  113. package/node/components/PageHeader/HeaderContent/index.d.ts +1 -0
  114. package/node/components/PageHeader/HeaderContent/index.js +1 -0
  115. package/node/components/PageHeader/HeaderContent/styles.d.ts +0 -4
  116. package/node/components/PageHeader/HeaderContent/styles.js +2 -11
  117. package/node/components/PageHeader/PageActions/PageActions.js +1 -1
  118. package/node/components/PageHeader/constants.d.ts +2 -0
  119. package/node/components/PageHeader/constants.js +2 -0
  120. package/node/components/PageHeader/index.d.ts +1 -0
  121. package/node/components/PageHeader/index.js +3 -1
  122. package/node/components/PageHeader/styles.js +25 -0
  123. package/node/components/TagBadge/styles.js +2 -1
  124. package/node/hook-form/FormFilters/AllFiltersButton/styles.d.ts +1 -0
  125. package/node/hook-form/FormFilters/AllFiltersButton/types.d.ts +1 -0
  126. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.d.ts +1 -1
  127. package/node/hook-form/FormFilters/AllFiltersButton/useLogic/useLogic.js +27 -11
  128. package/node/hook-form/FormFilters/FormFilters.js +5 -2
  129. package/node/hook-form/FormFilters/FormFiltersDialog/FormFiltersDialog.js +3 -3
  130. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.d.ts +6 -0
  131. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/ResetButton.js +15 -0
  132. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.d.ts +1 -0
  133. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/index.js +17 -0
  134. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.d.ts +14 -0
  135. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/styles.js +17 -0
  136. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.d.ts +1 -0
  137. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/index.js +17 -0
  138. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.d.ts +6 -0
  139. package/node/hook-form/FormFilters/FormFiltersDialog/ResetButton/useLogic/useLogic.js +15 -0
  140. package/node/hook-form/FormFilters/FormFiltersDialog/styles.d.ts +1 -10
  141. package/node/hook-form/FormFilters/FormFiltersDialog/styles.js +2 -10
  142. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.d.ts +4 -2
  143. package/node/hook-form/FormFilters/FormFiltersDialog/useLogic/useLogic.js +4 -5
  144. package/node/hook-form/FormFilters/FormFiltersSkeleton/FormFiltersSkeleton.js +4 -1
  145. package/node/hook-form/FormFilters/styles.d.ts +4 -0
  146. package/node/hook-form/FormFilters/styles.js +12 -3
  147. package/node/hook-form/FormFilters/types.d.ts +24 -4
  148. package/node/hook-form/FormFilters/useLogic/useLogic.d.ts +2 -1
  149. package/node/hook-form/FormFilters/useLogic/useLogic.js +12 -1
  150. package/node/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.d.ts +1 -0
  151. package/node/hook-form/FormFilters/utils/checkIsFilledValue/checkIsFilledValue.js +22 -0
  152. package/node/hook-form/FormFilters/utils/checkIsFilledValue/index.d.ts +1 -0
  153. package/node/hook-form/FormFilters/utils/checkIsFilledValue/index.js +5 -0
  154. package/node/hook-form/FormFilters/utils/getFilledCount/getFilledCount.d.ts +1 -0
  155. package/node/hook-form/FormFilters/utils/getFilledCount/getFilledCount.js +8 -0
  156. package/node/hook-form/FormFilters/utils/getFilledCount/index.d.ts +1 -0
  157. package/node/hook-form/FormFilters/utils/getFilledCount/index.js +5 -0
  158. package/node/hook-form/FormFilters/utils/index.d.ts +2 -0
  159. package/node/hook-form/FormFilters/utils/index.js +7 -0
  160. package/node/hook-form/FormQuickFilters/FormQuickFilters.d.ts +26 -0
  161. package/node/hook-form/FormQuickFilters/FormQuickFilters.js +50 -0
  162. package/node/hook-form/FormQuickFilters/constants.d.ts +6 -0
  163. package/node/hook-form/FormQuickFilters/constants.js +9 -0
  164. package/node/hook-form/FormQuickFilters/index.d.ts +2 -0
  165. package/node/hook-form/FormQuickFilters/index.js +5 -0
  166. package/node/hook-form/FormQuickFilters/public.d.ts +2 -0
  167. package/node/hook-form/FormQuickFilters/public.js +5 -0
  168. package/node/hook-form/FormQuickFilters/styles.d.ts +9 -0
  169. package/node/hook-form/FormQuickFilters/styles.js +19 -0
  170. package/node/hook-form/FormQuickFilters/types.d.ts +62 -0
  171. package/node/hook-form/FormQuickFilters/types.js +2 -0
  172. package/node/hook-form/FormQuickFilters/useLogic/useLogic.d.ts +18 -0
  173. package/node/hook-form/FormQuickFilters/useLogic/useLogic.js +63 -0
  174. package/node/hook-form/FormWizard/Footer/Footer.js +1 -1
  175. package/package.json +1 -1
@@ -9,6 +9,7 @@ const getBgColor = ({ $customColor, theme, $variantColor, }) => {
9
9
  success: theme.palette.green[800],
10
10
  warning: theme.palette.yellow[800],
11
11
  white: theme.palette.primary.contrastText,
12
+ transparent: 'transparent',
12
13
  },
13
14
  light: {
14
15
  grey: theme.palette.grey[300],
@@ -17,6 +18,7 @@ const getBgColor = ({ $customColor, theme, $variantColor, }) => {
17
18
  success: theme.palette.green[100],
18
19
  warning: theme.palette.yellow[100],
19
20
  white: theme.palette.grey[100],
21
+ transparent: 'transparent',
20
22
  },
21
23
  };
22
24
  return colors[$variantColor][$customColor];
@@ -30,6 +32,9 @@ const getTextColor = ({ $customColor, theme, $variantColor, }) => {
30
32
  warning: theme.palette.yellow[800],
31
33
  default: theme.palette.primary.contrastText,
32
34
  };
35
+ if ($customColor === 'transparent') {
36
+ return theme.palette.grey[900];
37
+ }
33
38
  if ($customColor === 'white') {
34
39
  return theme.palette.grey[900];
35
40
  }
@@ -1,2 +1,2 @@
1
- export type BadgeColor = 'primary' | 'grey' | 'white' | 'warning' | 'error' | 'success';
1
+ export type BadgeColor = 'primary' | 'grey' | 'white' | 'warning' | 'error' | 'success' | 'transparent';
2
2
  export type BadgeVariantsColor = 'contained' | 'light';
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Typography } from '../Typography';
3
3
  import { ChipStatusIcon } from './ChipStatusIcon';
4
4
  import { chipClassnames } from './constants';
5
- import { AdornmentWrapper, Counter, HiddenInput, Label, Wrapper, } from './styles';
5
+ import { AdornmentWrapper, HiddenInput, Label, StyledCounter, Wrapper, } from './styles';
6
6
  import { useLogic } from './useLogic';
7
7
  export const Chip = (props) => {
8
- const { classnames, inputProps, label, status, icon, counter, endAdornment, hasStartAdornment, hasEndAdornment, } = useLogic(props);
8
+ const { classnames, inputProps, label, status, icon, counter, endAdornment, hasStartAdornment, hasEndAdornment, maxCount, } = useLogic(props);
9
9
  const renderStartAdornment = () => {
10
10
  if (status) {
11
11
  return _jsx(ChipStatusIcon, { status: status });
@@ -17,7 +17,7 @@ export const Chip = (props) => {
17
17
  };
18
18
  const renderEndAdornment = () => {
19
19
  if (counter) {
20
- return _jsx(Counter, { children: counter });
20
+ return (_jsx(StyledCounter, { color: "transparent", content: counter, max: maxCount, withBorder: false }));
21
21
  }
22
22
  if (endAdornment) {
23
23
  return endAdornment;
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from 'react';
2
+ export type ChipMode = 'single' | 'multiple';
3
+ export type ChipContextValue = {
4
+ mode: ChipMode;
5
+ /**
6
+ * Общий `name` для нативных `radio`/`checkbox` в группе (стрелки и семантика радио).
7
+ */
8
+ name?: string;
9
+ };
10
+ export declare const ChipContext: import("react").Context<ChipContextValue>;
11
+ type ChipProviderProps = {
12
+ mode: ChipMode;
13
+ name?: string;
14
+ children: ReactNode;
15
+ };
16
+ /**
17
+ * Задаёт режим скрытого input для вложенных `Chip`:
18
+ * - `single` — `radio`; повторный клик по выбранному чипу вызывает `onChange` со снятием выбора
19
+ * - `multiple` — `checkbox`
20
+ *
21
+ * Параметр `name` задаёт общий атрибут `name` у инпутов (группа радио, стрелки вверх/вниз между опциями).
22
+ *
23
+ * Вне провайдера используется режим `single`.
24
+ */
25
+ export declare const ChipProvider: ({ mode, name, children }: ChipProviderProps) => import("react/jsx-runtime").JSX.Element;
26
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext } from 'react';
3
+ export const ChipContext = createContext({ mode: 'single' });
4
+ /**
5
+ * Задаёт режим скрытого input для вложенных `Chip`:
6
+ * - `single` — `radio`; повторный клик по выбранному чипу вызывает `onChange` со снятием выбора
7
+ * - `multiple` — `checkbox`
8
+ *
9
+ * Параметр `name` задаёт общий атрибут `name` у инпутов (группа радио, стрелки вверх/вниз между опциями).
10
+ *
11
+ * Вне провайдера используется режим `single`.
12
+ */
13
+ export const ChipProvider = ({ mode, name, children }) => (_jsx(ChipContext.Provider, { value: { mode, name }, children: children }));
@@ -0,0 +1 @@
1
+ export * from './ChipProvider';
@@ -0,0 +1 @@
1
+ export * from './ChipProvider';
@@ -1,2 +1,3 @@
1
1
  export { Chip } from './Chip';
2
- export type { ChipProps } from './types';
2
+ export { type ChipContextValue, type ChipMode, ChipProvider, } from './ChipProvider';
3
+ export type { ChipProps, ChipStatus } from './types';
@@ -1 +1,2 @@
1
1
  export { Chip } from './Chip';
2
+ export { ChipProvider, } from './ChipProvider';
@@ -1,2 +1,3 @@
1
1
  export { Chip } from './Chip';
2
- export type { ChipProps } from './types';
2
+ export { type ChipContextValue, type ChipMode, ChipProvider, } from './ChipProvider';
3
+ export type { ChipProps, ChipStatus } from './types';
@@ -1 +1,2 @@
1
1
  export { Chip } from './Chip';
2
+ export { ChipProvider, } from './ChipProvider';
@@ -7,10 +7,14 @@ export declare const HiddenInput: import("../styled").StyledComponent<{
7
7
  theme?: import("@emotion/react").Theme | undefined;
8
8
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
9
  }, import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, {}>;
10
- export declare const Counter: import("../styled").StyledComponent<{
10
+ export declare const StyledCounter: import("../styled").StyledComponent<Omit<import("..").WithoutEmotionSpecific<import("@mui/material/Badge").BadgeProps>, "content" | "color" | "children" | "variant" | "invisible" | "anchorOrigin" | "badgeContent" | "overlap" | "withBorder"> & {
11
+ color: import("../Counter/types").CounterColor;
12
+ variant?: import("../Counter/types").CounterVariants | undefined;
13
+ content?: number | undefined;
14
+ withBorder?: boolean | undefined;
15
+ } & {
11
16
  theme?: import("@emotion/react").Theme | undefined;
12
- as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
13
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
17
+ }, {}, {}>;
14
18
  export declare const AdornmentWrapper: import("../styled").StyledComponent<import("../Typography/types").TypographyPropsBase & {
15
19
  color?: import("../Typography").TypographyColor | undefined;
16
20
  variant?: import("../Typography").TypographyVariant | undefined;
@@ -1,3 +1,5 @@
1
+ import { badgeClasses } from '@mui/material/Badge';
2
+ import { Counter } from '../Counter';
1
3
  import { styled } from '../styled';
2
4
  import { Typography } from '../Typography';
3
5
  import { chipClassnames, chipSize } from './constants';
@@ -110,9 +112,12 @@ export const Wrapper = styled.div `
110
112
  }
111
113
  `;
112
114
  export const HiddenInput = styled.input `
113
- display: none;
115
+ position: absolute;
116
+
117
+ width: 0;
118
+ height: 0;
114
119
  `;
115
- export const Counter = styled.div `
120
+ export const StyledCounter = styled(Counter) `
116
121
  display: flex;
117
122
  align-items: center;
118
123
 
@@ -131,6 +136,18 @@ export const Counter = styled.div `
131
136
  background-color: ${({ theme }) => theme.palette.grey[800]};
132
137
  border-radius: 50%;
133
138
  }
139
+
140
+ .${badgeClasses.badge} {
141
+ min-width: unset;
142
+ padding: 0;
143
+
144
+ font-size: ${({ theme }) => theme.typography.body1.fontSize};
145
+ font-weight: ${({ theme }) => theme.typography.body1.fontWeight};
146
+
147
+ ${({ theme }) => theme.breakpoints.down('sm')} {
148
+ font-size: ${({ theme }) => theme.typography.body2.fontSize};
149
+ }
150
+ }
134
151
  `;
135
152
  export const AdornmentWrapper = styled(Typography) `
136
153
  display: flex;
@@ -139,4 +156,11 @@ export const AdornmentWrapper = styled(Typography) `
139
156
  export const Label = styled.label `
140
157
  /* Убираем подсветку при нажатии на компонент */
141
158
  -webkit-tap-highlight-color: transparent;
159
+
160
+ /* Причина игнора: Не критично для отображения */
161
+ /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
162
+ &:has(> input:focus-visible) .${chipClassnames.root} {
163
+ outline: 2px solid ${({ theme }) => theme.palette.components.focused};
164
+ outline-offset: 2px;
165
+ }
142
166
  `;
@@ -1,4 +1,11 @@
1
1
  import type { ChangeEvent, ReactElement, ReactNode } from 'react';
2
+ export type ChipStatus = 'success' | 'warning' | 'error';
3
+ /**
4
+ * Пропсы `Chip`.
5
+ *
6
+ * Тип скрытого поля (`radio` или `checkbox`) задаётся через `ChipProvider` (`mode`).
7
+ * Без провайдера используется `single`.
8
+ */
2
9
  export type ChipProps = {
3
10
  /**
4
11
  * Содержимое компонента
@@ -11,7 +18,7 @@ export type ChipProps = {
11
18
  /**
12
19
  * Статус компонента. Заменяет параметр `icon`
13
20
  */
14
- status?: 'success' | 'warning' | 'error';
21
+ status?: ChipStatus;
15
22
  /**
16
23
  * Иконка слева от `label`
17
24
  */
@@ -32,6 +39,10 @@ export type ChipProps = {
32
39
  * Число счетчика справа от `label`. Заменяет параметр `endAdornment`
33
40
  */
34
41
  counter?: number;
42
+ /**
43
+ * Максимальное число которое отобразится в счетчике
44
+ */
45
+ maxCount?: number;
35
46
  /**
36
47
  * Элемент, который добавляется в конец компонента
37
48
  */
@@ -40,4 +51,13 @@ export type ChipProps = {
40
51
  * Обработчик изменения состояния компонента
41
52
  */
42
53
  onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
54
+ /**
55
+ * Атрибут `name` скрытого `input` (для группы `radio` — одинаковый `name` у всех вариантов).
56
+ * Пробрасывается из `ChipProvider`, если задан там.
57
+ */
58
+ name?: string;
59
+ /**
60
+ * Атрибут `value` скрытого `input` (отметка в группе, отправка формы).
61
+ */
62
+ value?: string | number;
43
63
  };
@@ -1,20 +1,21 @@
1
1
  /// <reference types="react" />
2
2
  import { type ChipProps } from '../types';
3
- type UseLogicParams = ChipProps;
4
- export declare const useLogic: ({ className, isDisabled, isSelected, onChange, size, label, status, icon, counter, endAdornment, }: UseLogicParams) => {
3
+ export declare const useLogic: ({ className, isDisabled, isSelected, onChange, size, label, status, icon, counter, endAdornment, maxCount, name: nameProp, value: valueProp, }: ChipProps) => {
5
4
  classnames: string;
6
5
  inputProps: {
6
+ value?: string | number | undefined;
7
+ name?: string | undefined;
7
8
  checked: boolean | undefined;
8
9
  onChange: ((event: import("react").ChangeEvent<HTMLInputElement, Element>) => void) | undefined;
9
10
  type: string;
10
11
  disabled: boolean | undefined;
11
12
  };
12
13
  label: import("react").ReactNode;
13
- status: "success" | "warning" | "error" | undefined;
14
+ status: import("../types").ChipStatus | undefined;
14
15
  icon: import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | undefined;
15
16
  counter: number | undefined;
16
17
  endAdornment: import("react").ReactNode;
17
18
  hasStartAdornment: boolean;
18
19
  hasEndAdornment: boolean;
20
+ maxCount: number | undefined;
19
21
  };
20
- export {};
@@ -1,7 +1,11 @@
1
- import { useMemo } from 'react';
1
+ import { useContext, useMemo } from 'react';
2
2
  import { classNames } from '../../utils/classNames';
3
+ import { ChipContext } from '../ChipProvider';
3
4
  import { chipClassnames } from '../constants';
4
- export const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium', label, status, icon, counter, endAdornment, }) => {
5
+ export const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium', label, status, icon, counter, endAdornment, maxCount, name: nameProp, value: valueProp, }) => {
6
+ const { mode, name: contextName } = useContext(ChipContext);
7
+ const isMultiple = mode === 'multiple';
8
+ const inputName = nameProp ?? contextName;
5
9
  const classnames = useMemo(() => classNames(className, chipClassnames.root, {
6
10
  [chipClassnames.disabled]: isDisabled,
7
11
  [chipClassnames.selected]: isSelected,
@@ -15,13 +19,16 @@ export const useLogic = ({ className, isDisabled, isSelected, onChange, size = '
15
19
  }), [isSelected, isDisabled, size, status, counter, endAdornment, icon]);
16
20
  const hasStartAdornment = Boolean(status || icon);
17
21
  const hasEndAdornment = Boolean(endAdornment || counter);
22
+ const inputType = isMultiple ? 'checkbox' : 'radio';
18
23
  return {
19
24
  classnames,
20
25
  inputProps: {
21
26
  checked: isSelected,
22
27
  onChange,
23
- type: 'checkbox',
28
+ type: inputType,
24
29
  disabled: isDisabled,
30
+ ...(inputName !== undefined ? { name: inputName } : {}),
31
+ ...(valueProp !== undefined ? { value: valueProp } : {}),
25
32
  },
26
33
  label,
27
34
  status,
@@ -30,5 +37,6 @@ export const useLogic = ({ className, isDisabled, isSelected, onChange, size = '
30
37
  endAdornment,
31
38
  hasStartAdornment,
32
39
  hasEndAdornment,
40
+ maxCount,
33
41
  };
34
42
  };
@@ -14,5 +14,9 @@ export type CounterProps = Omit<WithoutEmotionSpecific<MuiBadgeProps>, 'color' |
14
14
  * Контент
15
15
  */
16
16
  content?: number;
17
+ /**
18
+ * Наличие белой рамки
19
+ */
20
+ withBorder?: boolean;
17
21
  };
18
- export declare const Counter: ({ content, color, max, variant, ...props }: CounterProps) => import("react/jsx-runtime").JSX.Element;
22
+ export declare const Counter: ({ content, color, max, variant, withBorder, ...props }: CounterProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { StyledCounter } from './styles';
3
- export const Counter = ({ content, color, max = 99, variant = 'contained', ...props }) => (_jsx(StyledCounter, { badgeContent: content, max: max, variantColor: variant, color: color, ...props }));
3
+ export const Counter = ({ content, color, max = 99, variant = 'contained', withBorder = true, ...props }) => (_jsx(StyledCounter, { badgeContent: content, max: max, variantColor: variant, color: color, withBorder: withBorder, ...props }));
@@ -1,2 +1,2 @@
1
- export type CounterColor = 'primary' | 'grey' | 'white' | 'warning' | 'error' | 'success';
1
+ export type CounterColor = 'primary' | 'grey' | 'white' | 'warning' | 'error' | 'success' | 'transparent';
2
2
  export type CounterVariants = 'contained' | 'light';
@@ -2,6 +2,7 @@ export declare const StyledCounter: import("../styled").StyledComponent<Omit<imp
2
2
  color: import("../Counter/types").CounterColor;
3
3
  variant?: import("../Counter/types").CounterVariants | undefined;
4
4
  content?: number | undefined;
5
+ withBorder?: boolean | undefined;
5
6
  } & {
6
7
  theme?: import("@emotion/react").Theme | undefined;
7
8
  } & {
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from 'react';
2
+ type FormFiltersLayoutContextValue = {
3
+ filtersClassName?: string;
4
+ quickFiltersClassName?: string;
5
+ };
6
+ export declare const FormFiltersLayoutContext: import("react").Context<FormFiltersLayoutContextValue | undefined>;
7
+ type FormFiltersProviderProps = FormFiltersLayoutContextValue & {
8
+ children: ReactNode;
9
+ };
10
+ /**
11
+ * Задаёт дополнительные классы для корня фильтров и блока быстрых фильтров
12
+ * (например, из разметки PageHeader).
13
+ */
14
+ export declare const FormFiltersProvider: ({ children, filtersClassName, quickFiltersClassName, }: FormFiltersProviderProps) => import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext } from 'react';
3
+ export const FormFiltersLayoutContext = createContext(undefined);
4
+ /**
5
+ * Задаёт дополнительные классы для корня фильтров и блока быстрых фильтров
6
+ * (например, из разметки PageHeader).
7
+ */
8
+ export const FormFiltersProvider = ({ children, filtersClassName, quickFiltersClassName, }) => (_jsx(FormFiltersLayoutContext.Provider, { value: { filtersClassName, quickFiltersClassName }, children: children }));
@@ -0,0 +1 @@
1
+ export { FormFiltersProvider, FormFiltersLayoutContext, } from './FormFiltersProvider';
@@ -0,0 +1 @@
1
+ export { FormFiltersProvider, FormFiltersLayoutContext, } from './FormFiltersProvider';
@@ -5,7 +5,8 @@ import { pageHeaderClassnames } from '../constants';
5
5
  import { PageActions } from '../PageActions';
6
6
  import { Title } from '../Title';
7
7
  import { Description } from './Description';
8
- import { BreadcrumbsWrapper, DesktopTitleWrapper, PageFilters, PageSubheader, } from './styles';
8
+ import { FormFiltersProvider } from './FormFiltersProvider';
9
+ import { BreadcrumbsWrapper, DesktopTitleWrapper, PageSubheader, } from './styles';
9
10
  export const HeaderContent = ({ backButton, description, subheader, breadcrumbs, actions, title, filters, isLoading, }) => {
10
11
  const renderBreadcrumbs = () => {
11
12
  if (!breadcrumbs) {
@@ -13,5 +14,5 @@ export const HeaderContent = ({ backButton, description, subheader, breadcrumbs,
13
14
  }
14
15
  return (_jsx(BreadcrumbsWrapper, { children: Array.isArray(breadcrumbs) ? (_jsx(Breadcrumbs, { children: breadcrumbs })) : (breadcrumbs) }));
15
16
  };
16
- return (_jsxs(_Fragment, { children: [renderBreadcrumbs(), _jsx(DesktopTitleWrapper, { children: _jsx(Title, { backButton: backButton, title: title, isLoading: isLoading, hasDescription: Boolean(description), hasBreadcrumbs: Boolean(breadcrumbs) }) }), _jsx(Description, { description: description, isLoading: isLoading }), actions && (_jsx(PageActions, { className: classNames(pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, size: "medium", withCollapseOnLaptop: Boolean(filters), ...actions })), filters && _jsx(PageFilters, { children: filters }), subheader && _jsx(PageSubheader, { children: subheader })] }));
17
+ return (_jsxs(_Fragment, { children: [renderBreadcrumbs(), _jsx(DesktopTitleWrapper, { children: _jsx(Title, { backButton: backButton, title: title, isLoading: isLoading, hasDescription: Boolean(description), hasBreadcrumbs: Boolean(breadcrumbs) }) }), _jsx(Description, { description: description, isLoading: isLoading }), actions && (_jsx(PageActions, { className: classNames(pageHeaderClassnames.pageHeaderActions), isLoading: isLoading, size: "medium", withCollapseOnLaptop: Boolean(filters), ...actions })), filters && (_jsx(FormFiltersProvider, { filtersClassName: pageHeaderClassnames.filters, quickFiltersClassName: pageHeaderClassnames.quickFilters, children: filters })), subheader && _jsx(PageSubheader, { children: subheader })] }));
17
18
  };
@@ -1 +1,2 @@
1
1
  export * from './HeaderContent';
2
+ export * from './FormFiltersProvider';
@@ -1 +1,2 @@
1
1
  export * from './HeaderContent';
2
+ export * from './FormFiltersProvider';
@@ -7,10 +7,6 @@ export declare const PageSubheader: import("../../styled").StyledComponent<{
7
7
  theme?: import("@emotion/react").Theme | undefined;
8
8
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
9
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
10
- export declare const PageFilters: import("../../styled").StyledComponent<{
11
- theme?: import("@emotion/react").Theme | undefined;
12
- as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
13
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
14
10
  export declare const DesktopTitleWrapper: import("../../styled").StyledComponent<{
15
11
  theme?: import("@emotion/react").Theme | undefined;
16
12
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
@@ -11,7 +11,7 @@ export const BreadcrumbsWrapper = styled.div `
11
11
  `;
12
12
  export const PageSubheader = styled.div `
13
13
  grid-column: 1 / -1;
14
- grid-row: 5;
14
+ grid-row: 6;
15
15
 
16
16
  padding-top: ${({ theme }) => theme.spacing(4)};
17
17
 
@@ -19,15 +19,6 @@ export const PageSubheader = styled.div `
19
19
  padding: ${({ theme }) => theme.spacing(0, 4, 4, 4)};
20
20
  }
21
21
  `;
22
- export const PageFilters = styled.div `
23
- grid-column: 1 / -1;
24
- grid-row: 4;
25
-
26
- ${({ theme }) => theme.breakpoints.down('laptop')} {
27
- grid-column: 3;
28
- grid-row: 1 / 4;
29
- }
30
- `;
31
22
  export const DesktopTitleWrapper = styled.div `
32
23
  display: contents;
33
24
 
@@ -15,6 +15,6 @@ const PageActionsInner = (props, ref) => {
15
15
  if (isLoading) {
16
16
  return (_jsx(Wrapper, { children: _jsx(PageActionSkeleton, { size: size }) }));
17
17
  }
18
- return (_jsx(Wrapper, { className: className, ref: ref, children: _jsxs(ActionWrapper, { "$spacing": spacing, children: [_jsx(Tooltip, { title: tooltipTitle, enterDelay: 400, enterNextDelay: 400, placement: "bottom-end", children: _jsx(FocusModeButton, { className: buttonClassnames, variant: "outlined", onClick: handleClick, "aria-label": tooltipTitle, color: "grey", children: isFocusedMode ? _jsx(MinimizeOutlineMd, {}) : _jsx(FullSizeOutlineMd, {}) }) }), _jsx(MainActionsWrapper, { "$spacing": spacing, className: classnames, children: _jsx(MainActions, { isDisabled: disabledAction, actions: main, size: size, spacing: spacing }) }), _jsxs(SecondaryVisibleWrapper, { "$spacing": spacing, className: classnames, children: [secondaryVisible && (_jsx(SecondaryVisibleActions, { actions: secondaryVisible, size: size })), secondary && (_jsx(SecondaryActions, { isDisabled: disabledAction, actions: secondary, size: size }))] }), collapsedActions.length > 0 && (_jsx(CollapsedActionsWrapper, { className: classnames, children: _jsx(SecondaryActions, { isDisabled: disabledAction, actions: collapsedActions, size: size }) }))] }) }));
18
+ return (_jsx(Wrapper, { className: className, ref: ref, children: _jsxs(ActionWrapper, { "$spacing": spacing, children: [_jsx(Tooltip, { title: tooltipTitle, enterDelay: 400, enterNextDelay: 400, placement: "bottom-end", children: _jsx(FocusModeButton, { className: buttonClassnames, variant: "outlined", onClick: handleClick, "aria-label": tooltipTitle, color: "grey", children: isFocusedMode ? _jsx(MinimizeOutlineMd, {}) : _jsx(FullSizeOutlineMd, {}) }) }), _jsx(MainActionsWrapper, { "$spacing": spacing, className: classnames, children: _jsx(MainActions, { isDisabled: disabledAction, actions: main, size: size, spacing: spacing }) }), (secondaryVisible || secondary) && (_jsxs(SecondaryVisibleWrapper, { "$spacing": spacing, className: classnames, children: [secondaryVisible && (_jsx(SecondaryVisibleActions, { actions: secondaryVisible, size: size })), secondary && (_jsx(SecondaryActions, { isDisabled: disabledAction, actions: secondary, size: size }))] })), collapsedActions.length > 0 && (_jsx(CollapsedActionsWrapper, { className: classnames, children: _jsx(SecondaryActions, { isDisabled: disabledAction, actions: collapsedActions, size: size }) }))] }) }));
19
19
  };
20
20
  export const PageActions = forwardRefWithGeneric(PageActionsInner);
@@ -3,5 +3,7 @@ export declare const pageHeaderClassnames: {
3
3
  pageHeaderActions: string;
4
4
  hasBackButton: string;
5
5
  hasTitle: string;
6
+ filters: string;
7
+ quickFilters: string;
6
8
  };
7
9
  export declare const PAGE_HEADER_HEIGHT_MOBILE = "48px";
@@ -4,5 +4,7 @@ export const pageHeaderClassnames = {
4
4
  pageHeaderActions: createUIKitClassname('page-header__actions'),
5
5
  hasBackButton: createUIKitClassname('page-header_has-back-button'),
6
6
  hasTitle: createUIKitClassname('page-header_has-title'),
7
+ filters: createUIKitClassname('page-header__filters'),
8
+ quickFilters: createUIKitClassname('page-header__quick-filters'),
7
9
  };
8
10
  export const PAGE_HEADER_HEIGHT_MOBILE = '48px';
@@ -2,3 +2,4 @@ export { pageHeaderClassnames } from './constants';
2
2
  export { PageActionSkeleton, PageActions, type PageActionsProps, } from './PageActions';
3
3
  export * from './PageHeader';
4
4
  export * from './types';
5
+ export { FormFiltersLayoutContext } from './HeaderContent';
@@ -2,3 +2,4 @@ export { pageHeaderClassnames } from './constants';
2
2
  export { PageActionSkeleton, PageActions, } from './PageActions';
3
3
  export * from './PageHeader';
4
4
  export * from './types';
5
+ export { FormFiltersLayoutContext } from './HeaderContent';
@@ -22,6 +22,31 @@ 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('laptop')} {
43
+ margin-top: ${({ theme }) => theme.spacing(3)};
44
+ }
45
+
46
+ ${({ theme }) => theme.breakpoints.down('sm')} {
47
+ display: none;
48
+ }
49
+ }
25
50
  `;
26
51
  export const MobileTitleWrapper = styled.div `
27
52
  display: none;
@@ -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
  };