@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
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Checkbox } from '../../components/Checkbox';
3
+ import { Chip, ChipProvider } from '../../components/Chip';
4
+ import { ListItemIcon } from '../../components/ListItemIcon';
5
+ import { MenuItem } from '../../components/MenuItem';
6
+ import { FormSelect } from '../FormSelect';
7
+ import { FORM_FILTERS_QUICK_FILTERS_ID, FORM_QUICK_FILTERS_ALL_CHIP_KEY, FORM_QUICK_FILTERS_ALL_VALUE, } from './constants';
8
+ import { MobileWrapper, Wrapper } from './styles';
9
+ import { useLogic } from './useLogic/useLogic';
10
+ /**
11
+ * Группа чипов для быстрых фильтров внутри FormFilters (слот quickFilters).
12
+ *
13
+ * Поведение чипов задаётся параметром `multiple` через `ChipProvider mode`:
14
+ * - false (default) — `single` (radio)
15
+ * - true — `multiple` (checkbox)
16
+ *
17
+ * - На мобильных устройствах отображается как Select
18
+ *
19
+ * @example
20
+ * <FormFilters
21
+ * quickFilters={({ control }) => (
22
+ * <FormQuickFilters
23
+ * control={control}
24
+ * name="status"
25
+ * label="Статус"
26
+ * options={[
27
+ * { label: 'Активные', value: 'active' },
28
+ * { label: 'Архив', value: 'archived' },
29
+ * ]}
30
+ * />
31
+ * )}
32
+ * />
33
+ */
34
+ export const FormQuickFilters = (props) => {
35
+ const { field, filterOptions, checkIsAllSelected, handleChipChange, isSelected, label, allLabel, allCounter, multiple, maxCount, name, placeholder, control, getOptionLabel, getCounterLabel, } = useLogic(props);
36
+ const renderMultipleOptions = () => {
37
+ return filterOptions.map((option) => {
38
+ const checked = control._formValues[name]?.includes(option.value);
39
+ return (_jsxs(MenuItem, { value: option.value, children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { checked: checked }) }), option.label, getCounterLabel(option)] }, option.value));
40
+ });
41
+ };
42
+ const renderSingleOptions = () => {
43
+ return filterOptions.map((option) => (_jsxs(MenuItem, { value: option.value, children: [option.label, getCounterLabel(option)] }, option.value)));
44
+ };
45
+ return (_jsxs(_Fragment, { children: [_jsx(Wrapper, { children: _jsxs(ChipProvider, { mode: multiple ? 'multiple' : 'single', name: name, children: [_jsx(Chip, { label: allLabel, isSelected: checkIsAllSelected(), onChange: () => handleChipChange(FORM_QUICK_FILTERS_ALL_VALUE), counter: allCounter, size: "medium", maxCount: maxCount, value: FORM_QUICK_FILTERS_ALL_VALUE }, FORM_QUICK_FILTERS_ALL_CHIP_KEY), filterOptions.map((option) => (_jsx(Chip, { label: option.label, isSelected: isSelected(option.value), onChange: () => handleChipChange(option.value), status: option.status, counter: option.counter, size: "medium", maxCount: maxCount, value: String(option.value) }, option.value)))] }) }), _jsx(MobileWrapper, { children: _jsx(FormSelect, { control: control, name: name, inputProps: { id: FORM_FILTERS_QUICK_FILTERS_ID }, label: label, getOptionLabel: getOptionLabel, multiple: multiple, onChange: field.onChange, onBlur: field.onBlur, fullWidth: true, placeholder: placeholder, children: multiple ? renderMultipleOptions() : renderSingleOptions() }) })] }));
46
+ };
@@ -0,0 +1,6 @@
1
+ export declare const FORM_FILTERS_QUICK_FILTERS_ID = "form-filters-quick-filters";
2
+ /** Значение поля при выборе «Все» (ничего не выбрано) */
3
+ export declare const FORM_QUICK_FILTERS_ALL_VALUE = "";
4
+ export declare const FORM_QUICK_FILTERS_DEFAULT_ALL_LABEL = "\u0412\u0441\u0435";
5
+ /** Стабильный key для чипа «Все» (value поля при этом остаётся пустой строкой) */
6
+ export declare const FORM_QUICK_FILTERS_ALL_CHIP_KEY = "form_quick_filters_all_key";
@@ -0,0 +1,6 @@
1
+ export const FORM_FILTERS_QUICK_FILTERS_ID = 'form-filters-quick-filters';
2
+ /** Значение поля при выборе «Все» (ничего не выбрано) */
3
+ export const FORM_QUICK_FILTERS_ALL_VALUE = '';
4
+ export const FORM_QUICK_FILTERS_DEFAULT_ALL_LABEL = 'Все';
5
+ /** Стабильный key для чипа «Все» (value поля при этом остаётся пустой строкой) */
6
+ export const FORM_QUICK_FILTERS_ALL_CHIP_KEY = 'form_quick_filters_all_key';
@@ -0,0 +1,2 @@
1
+ export { FormQuickFilters } from './FormQuickFilters';
2
+ export type { FormQuickFiltersProps, QuickFilterOption } from './types';
@@ -0,0 +1 @@
1
+ export { FormQuickFilters } from './FormQuickFilters';
@@ -0,0 +1,2 @@
1
+ export { FormQuickFilters } from './FormQuickFilters';
2
+ export type { FormQuickFiltersProps, QuickFilterOption } from './types';
@@ -0,0 +1 @@
1
+ export { FormQuickFilters } from './FormQuickFilters';
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ export declare const Wrapper: 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 MobileWrapper: 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>, {}>;
@@ -0,0 +1,16 @@
1
+ import { styled } from '../../components/styled';
2
+ export const Wrapper = styled.div `
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ gap: ${({ theme }) => theme.spacing(2)};
6
+ align-items: center;
7
+
8
+ ${({ theme }) => theme.breakpoints.down('sm')} {
9
+ display: none;
10
+ }
11
+ `;
12
+ export const MobileWrapper = styled.div `
13
+ ${({ theme }) => theme.breakpoints.up('sm')} {
14
+ display: none;
15
+ }
16
+ `;
@@ -0,0 +1,62 @@
1
+ import type { Control, Path } from 'react-hook-form';
2
+ import type { ChipStatus } from '../../components/Chip';
3
+ export type QuickFilterValue = string | number;
4
+ export type QuickFilterOption = {
5
+ /**
6
+ * Текст чипа / пункта списка
7
+ */
8
+ label: string;
9
+ /**
10
+ * Значение опции
11
+ */
12
+ value: QuickFilterValue;
13
+ /**
14
+ * Статус чипа
15
+ */
16
+ status?: ChipStatus;
17
+ /**
18
+ * Число счетчика справа от `label`
19
+ */
20
+ counter?: number;
21
+ };
22
+ export type FormQuickFiltersProps<TFieldValues extends object> = {
23
+ /**
24
+ * Объект control из react-hook-form
25
+ */
26
+ control: Control<TFieldValues>;
27
+ /**
28
+ * Имя поля формы
29
+ */
30
+ name: Path<TFieldValues>;
31
+ /**
32
+ * Лейбл — отображается в заголовке Select-режима (внутри модалки на мобиле)
33
+ */
34
+ label: string;
35
+ /**
36
+ * Список опций (без пункта «Все» — он добавляется автоматически и соответствует пустому значению поля)
37
+ */
38
+ options: QuickFilterOption[];
39
+ /**
40
+ * Подпись встроенного чипа «Все»
41
+ * @default 'Все'
42
+ */
43
+ allLabel?: string;
44
+ /**
45
+ * Счётчик у чипа «Все»
46
+ */
47
+ allCounter?: number;
48
+ /**
49
+ * Максимальное чисто счетчика у чипов
50
+ */
51
+ maxCount?: number;
52
+ /**
53
+ * Режим мультивыбора.
54
+ * - false (default) — одиночный выбор (radio-поведение)
55
+ * - true — множественный выбор (checkbox-поведение)
56
+ */
57
+ multiple?: boolean;
58
+ /**
59
+ * Плейсхолдер для Select-режима (внутри модалки на мобиле)
60
+ */
61
+ placeholder?: string;
62
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { FormQuickFiltersProps, QuickFilterOption, QuickFilterValue } from '../types';
2
+ export declare const useLogic: <TFieldValues extends object>({ control, name, label, options, allLabel, allCounter, multiple, maxCount, placeholder, }: FormQuickFiltersProps<TFieldValues>) => {
3
+ field: import("react-hook-form").ControllerRenderProps<TFieldValues, import("react-hook-form").Path<TFieldValues>>;
4
+ filterOptions: QuickFilterOption[];
5
+ checkIsAllSelected: () => boolean;
6
+ handleChipChange: (optionValue: QuickFilterValue) => void;
7
+ isSelected: (optionValue: QuickFilterValue) => boolean;
8
+ label: string;
9
+ allLabel: string;
10
+ allCounter: number | undefined;
11
+ multiple: boolean;
12
+ maxCount: number | undefined;
13
+ name: import("react-hook-form").Path<TFieldValues>;
14
+ placeholder: string | undefined;
15
+ control: import("react-hook-form").Control<TFieldValues>;
16
+ getOptionLabel: (value: string | number) => string | number;
17
+ getCounterLabel: (option: QuickFilterOption) => string;
18
+ };
@@ -0,0 +1,59 @@
1
+ import { useController } from 'react-hook-form';
2
+ import { FORM_QUICK_FILTERS_ALL_VALUE, FORM_QUICK_FILTERS_DEFAULT_ALL_LABEL, } from '../constants';
3
+ export const useLogic = ({ control, name, label, options, allLabel = FORM_QUICK_FILTERS_DEFAULT_ALL_LABEL, allCounter, multiple = false, maxCount, placeholder, }) => {
4
+ const { field } = useController({ control, name });
5
+ const filterOptions = options.filter((option) => option.value !== FORM_QUICK_FILTERS_ALL_VALUE);
6
+ const checkIsAllSelected = () => {
7
+ if (multiple) {
8
+ return !(field.value ?? []).length;
9
+ }
10
+ return field.value === FORM_QUICK_FILTERS_ALL_VALUE || field.value == null;
11
+ };
12
+ const handleChipChange = (optionValue) => {
13
+ if (optionValue === FORM_QUICK_FILTERS_ALL_VALUE) {
14
+ field.onChange(multiple ? [] : FORM_QUICK_FILTERS_ALL_VALUE);
15
+ return;
16
+ }
17
+ if (multiple) {
18
+ const current = field.value ?? [];
19
+ field.onChange(current.includes(optionValue)
20
+ ? current.filter((v) => v !== optionValue)
21
+ : [...current, optionValue]);
22
+ }
23
+ else {
24
+ field.onChange(field.value === optionValue
25
+ ? FORM_QUICK_FILTERS_ALL_VALUE
26
+ : optionValue);
27
+ }
28
+ };
29
+ const isSelected = (optionValue) => {
30
+ if (multiple) {
31
+ return (field.value ?? []).includes(optionValue);
32
+ }
33
+ return field.value === optionValue;
34
+ };
35
+ const getOptionLabel = (value) => {
36
+ const optionLabel = filterOptions.find((option) => option.value === value);
37
+ return optionLabel?.label || value;
38
+ };
39
+ const getCounterLabel = (option) => {
40
+ return option.counter ? ` (${option.counter})` : '';
41
+ };
42
+ return {
43
+ field,
44
+ filterOptions,
45
+ checkIsAllSelected,
46
+ handleChipChange,
47
+ isSelected,
48
+ label,
49
+ allLabel,
50
+ allCounter,
51
+ multiple,
52
+ maxCount,
53
+ name,
54
+ placeholder,
55
+ control,
56
+ getOptionLabel,
57
+ getCounterLabel,
58
+ };
59
+ };
@@ -6,5 +6,5 @@ import { PrevButton, Wrapper } from './styles';
6
6
  export const Footer = (props) => {
7
7
  const { isDisabled, isFirstStep, isLastStep, prevButtonText, submitButtonText, onPrevStep, } = props;
8
8
  const renderNextIcon = () => (isLastStep ? null : _jsx(ArrowROutlineMd, {}));
9
- return (_jsxs(Wrapper, { children: [!isFirstStep && (_jsx(PrevButton, { disabled: isDisabled, variant: "light", startIcon: _jsx(ArrowLOutlineMd, {}), onClick: onPrevStep, children: prevButtonText })), _jsx(FormSubmitButton, { disabled: isDisabled, endIcon: renderNextIcon(), children: submitButtonText })] }));
9
+ return (_jsxs(Wrapper, { children: [!isFirstStep && (_jsx(PrevButton, { disabled: isDisabled, variant: "outlined", color: "grey", startIcon: _jsx(ArrowLOutlineMd, {}), onClick: onPrevStep, children: prevButtonText })), _jsx(FormSubmitButton, { disabled: isDisabled, endIcon: renderNextIcon(), children: submitButtonText })] }));
10
10
  };
@@ -15,6 +15,7 @@ const getBgColor = ({ $customColor, theme, $variantColor, }) => {
15
15
  success: theme.palette.green[800],
16
16
  warning: theme.palette.yellow[800],
17
17
  white: theme.palette.primary.contrastText,
18
+ transparent: 'transparent',
18
19
  },
19
20
  light: {
20
21
  grey: theme.palette.grey[300],
@@ -23,6 +24,7 @@ const getBgColor = ({ $customColor, theme, $variantColor, }) => {
23
24
  success: theme.palette.green[100],
24
25
  warning: theme.palette.yellow[100],
25
26
  white: theme.palette.grey[100],
27
+ transparent: 'transparent',
26
28
  },
27
29
  };
28
30
  return colors[$variantColor][$customColor];
@@ -36,6 +38,9 @@ const getTextColor = ({ $customColor, theme, $variantColor, }) => {
36
38
  warning: theme.palette.yellow[800],
37
39
  default: theme.palette.primary.contrastText,
38
40
  };
41
+ if ($customColor === 'transparent') {
42
+ return theme.palette.grey[900];
43
+ }
39
44
  if ($customColor === 'white') {
40
45
  return theme.palette.grey[900];
41
46
  }
@@ -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';
@@ -8,7 +8,7 @@ const constants_1 = require("./constants");
8
8
  const styles_1 = require("./styles");
9
9
  const useLogic_1 = require("./useLogic");
10
10
  const Chip = (props) => {
11
- const { classnames, inputProps, label, status, icon, counter, endAdornment, hasStartAdornment, hasEndAdornment, } = (0, useLogic_1.useLogic)(props);
11
+ const { classnames, inputProps, label, status, icon, counter, endAdornment, hasStartAdornment, hasEndAdornment, maxCount, } = (0, useLogic_1.useLogic)(props);
12
12
  const renderStartAdornment = () => {
13
13
  if (status) {
14
14
  return (0, jsx_runtime_1.jsx)(ChipStatusIcon_1.ChipStatusIcon, { status: status });
@@ -20,7 +20,7 @@ const Chip = (props) => {
20
20
  };
21
21
  const renderEndAdornment = () => {
22
22
  if (counter) {
23
- return (0, jsx_runtime_1.jsx)(styles_1.Counter, { children: counter });
23
+ return ((0, jsx_runtime_1.jsx)(styles_1.StyledCounter, { color: "transparent", content: counter, max: maxCount, withBorder: false }));
24
24
  }
25
25
  if (endAdornment) {
26
26
  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,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChipProvider = exports.ChipContext = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ exports.ChipContext = (0, react_1.createContext)({ mode: 'single' });
7
+ /**
8
+ * Задаёт режим скрытого input для вложенных `Chip`:
9
+ * - `single` — `radio`; повторный клик по выбранному чипу вызывает `onChange` со снятием выбора
10
+ * - `multiple` — `checkbox`
11
+ *
12
+ * Параметр `name` задаёт общий атрибут `name` у инпутов (группа радио, стрелки вверх/вниз между опциями).
13
+ *
14
+ * Вне провайдера используется режим `single`.
15
+ */
16
+ const ChipProvider = ({ mode, name, children }) => ((0, jsx_runtime_1.jsx)(exports.ChipContext.Provider, { value: { mode, name }, children: children }));
17
+ exports.ChipProvider = ChipProvider;
@@ -0,0 +1 @@
1
+ export * from './ChipProvider';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./ChipProvider"), exports);
@@ -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,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Chip = void 0;
3
+ exports.ChipProvider = exports.Chip = void 0;
4
4
  var Chip_1 = require("./Chip");
5
5
  Object.defineProperty(exports, "Chip", { enumerable: true, get: function () { return Chip_1.Chip; } });
6
+ var ChipProvider_1 = require("./ChipProvider");
7
+ Object.defineProperty(exports, "ChipProvider", { enumerable: true, get: function () { return ChipProvider_1.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,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Chip = void 0;
3
+ exports.ChipProvider = exports.Chip = void 0;
4
4
  var Chip_1 = require("./Chip");
5
5
  Object.defineProperty(exports, "Chip", { enumerable: true, get: function () { return Chip_1.Chip; } });
6
+ var ChipProvider_1 = require("./ChipProvider");
7
+ Object.defineProperty(exports, "ChipProvider", { enumerable: true, get: function () { return ChipProvider_1.ChipProvider; } });
@@ -7,10 +7,14 @@ export declare const HiddenInput: import("@emotion/styled/dist/declarations/src/
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("@emotion/styled/dist/declarations/src/types").StyledComponent<{
10
+ export declare const StyledCounter: import("@emotion/styled/dist/declarations/src/types").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("@emotion/styled/dist/declarations/src/types").StyledComponent<import("../Typography/types").TypographyPropsBase & {
15
19
  color?: import("../Typography").TypographyColor | undefined;
16
20
  variant?: import("../Typography").TypographyVariant | undefined;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Label = exports.AdornmentWrapper = exports.Counter = exports.HiddenInput = exports.Wrapper = void 0;
3
+ exports.Label = exports.AdornmentWrapper = exports.StyledCounter = exports.HiddenInput = exports.Wrapper = void 0;
4
+ const Badge_1 = require("@mui/material/Badge");
5
+ const Counter_1 = require("../Counter");
4
6
  const styled_1 = require("../styled");
5
7
  const Typography_1 = require("../Typography");
6
8
  const constants_1 = require("./constants");
@@ -113,9 +115,12 @@ exports.Wrapper = styled_1.styled.div `
113
115
  }
114
116
  `;
115
117
  exports.HiddenInput = styled_1.styled.input `
116
- display: none;
118
+ position: absolute;
119
+
120
+ width: 0;
121
+ height: 0;
117
122
  `;
118
- exports.Counter = styled_1.styled.div `
123
+ exports.StyledCounter = (0, styled_1.styled)(Counter_1.Counter) `
119
124
  display: flex;
120
125
  align-items: center;
121
126
 
@@ -134,6 +139,18 @@ exports.Counter = styled_1.styled.div `
134
139
  background-color: ${({ theme }) => theme.palette.grey[800]};
135
140
  border-radius: 50%;
136
141
  }
142
+
143
+ .${Badge_1.badgeClasses.badge} {
144
+ min-width: unset;
145
+ padding: 0;
146
+
147
+ font-size: ${({ theme }) => theme.typography.body1.fontSize};
148
+ font-weight: ${({ theme }) => theme.typography.body1.fontWeight};
149
+
150
+ ${({ theme }) => theme.breakpoints.down('sm')} {
151
+ font-size: ${({ theme }) => theme.typography.body2.fontSize};
152
+ }
153
+ }
137
154
  `;
138
155
  exports.AdornmentWrapper = (0, styled_1.styled)(Typography_1.Typography) `
139
156
  display: flex;
@@ -142,4 +159,11 @@ exports.AdornmentWrapper = (0, styled_1.styled)(Typography_1.Typography) `
142
159
  exports.Label = styled_1.styled.label `
143
160
  /* Убираем подсветку при нажатии на компонент */
144
161
  -webkit-tap-highlight-color: transparent;
162
+
163
+ /* Причина игнора: Не критично для отображения */
164
+ /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
165
+ &:has(> input:focus-visible) .${constants_1.chipClassnames.root} {
166
+ outline: 2px solid ${({ theme }) => theme.palette.components.focused};
167
+ outline-offset: 2px;
168
+ }
145
169
  `;
@@ -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 {};
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useLogic = void 0;
4
4
  const react_1 = require("react");
5
5
  const classNames_1 = require("../../utils/classNames");
6
+ const ChipProvider_1 = require("../ChipProvider");
6
7
  const constants_1 = require("../constants");
7
- const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium', label, status, icon, counter, endAdornment, }) => {
8
+ const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium', label, status, icon, counter, endAdornment, maxCount, name: nameProp, value: valueProp, }) => {
9
+ const { mode, name: contextName } = (0, react_1.useContext)(ChipProvider_1.ChipContext);
10
+ const isMultiple = mode === 'multiple';
11
+ const inputName = nameProp ?? contextName;
8
12
  const classnames = (0, react_1.useMemo)(() => (0, classNames_1.classNames)(className, constants_1.chipClassnames.root, {
9
13
  [constants_1.chipClassnames.disabled]: isDisabled,
10
14
  [constants_1.chipClassnames.selected]: isSelected,
@@ -18,13 +22,16 @@ const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium'
18
22
  }), [isSelected, isDisabled, size, status, counter, endAdornment, icon]);
19
23
  const hasStartAdornment = Boolean(status || icon);
20
24
  const hasEndAdornment = Boolean(endAdornment || counter);
25
+ const inputType = isMultiple ? 'checkbox' : 'radio';
21
26
  return {
22
27
  classnames,
23
28
  inputProps: {
24
29
  checked: isSelected,
25
30
  onChange,
26
- type: 'checkbox',
31
+ type: inputType,
27
32
  disabled: isDisabled,
33
+ ...(inputName !== undefined ? { name: inputName } : {}),
34
+ ...(valueProp !== undefined ? { value: valueProp } : {}),
28
35
  },
29
36
  label,
30
37
  status,
@@ -33,6 +40,7 @@ const useLogic = ({ className, isDisabled, isSelected, onChange, size = 'medium'
33
40
  endAdornment,
34
41
  hasStartAdornment,
35
42
  hasEndAdornment,
43
+ maxCount,
36
44
  };
37
45
  };
38
46
  exports.useLogic = useLogic;
@@ -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;
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Counter = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const styles_1 = require("./styles");
6
- const Counter = ({ content, color, max = 99, variant = 'contained', ...props }) => ((0, jsx_runtime_1.jsx)(styles_1.StyledCounter, { badgeContent: content, max: max, variantColor: variant, color: color, ...props }));
6
+ const Counter = ({ content, color, max = 99, variant = 'contained', withBorder = true, ...props }) => ((0, jsx_runtime_1.jsx)(styles_1.StyledCounter, { badgeContent: content, max: max, variantColor: variant, color: color, withBorder: withBorder, ...props }));
7
7
  exports.Counter = Counter;
@@ -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("@emotion/styled/dist/declarations/sr
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
  } & {