@sberbusiness/triplex-next-mcp-server 1.50.0-beta → 1.53.1
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.
- package/README.md +1 -0
- package/bundle/components/AlertProcess.md +6 -3
- package/bundle/components/AlertProcessSpoiler.md +216 -0
- package/bundle/components/Badge.md +4 -3
- package/bundle/components/ButtonDropdown.md +5 -3
- package/bundle/components/Carousel.md +671 -0
- package/bundle/components/CarouselExtended.md +7 -5
- package/bundle/components/CarouselIndicators.md +666 -0
- package/bundle/components/CarouselItem.md +579 -0
- package/bundle/components/CarouselNextButton.md +633 -0
- package/bundle/components/CarouselPrevButton.md +633 -0
- package/bundle/components/CarouselViewport.md +631 -0
- package/bundle/components/CheckboxTreeExtended.md +21 -7
- package/bundle/components/CheckboxTreeExtendedCheckbox.md +591 -0
- package/bundle/components/CheckboxTreeExtendedNode.md +577 -0
- package/bundle/components/Chip.md +1 -0
- package/bundle/components/ChipDatePicker.md +332 -0
- package/bundle/components/ChipDatePickerTarget.md +316 -0
- package/bundle/components/ChipMonthYearPicker.md +4 -3
- package/bundle/components/ChipMonthYearPickerTarget.md +318 -0
- package/bundle/components/ChipMultiselect.md +63 -73
- package/bundle/components/ChipSelect.md +385 -0
- package/bundle/components/ChipSelectTarget.md +388 -0
- package/bundle/components/ChipSuggest.md +10 -16
- package/bundle/components/ChipSuggestTarget.md +506 -0
- package/bundle/components/CollapsibleTree.md +2 -1
- package/bundle/components/CollapsibleTreeExtended.md +2 -1
- package/bundle/components/DateField.md +4 -2
- package/bundle/components/DatePickerExtended.md +16 -14
- package/bundle/components/DateRange.md +17 -10
- package/bundle/components/Dropdown.md +36 -63
- package/bundle/components/EmptyView.md +9 -4
- package/bundle/components/ExpandAnimation.md +9 -5
- package/bundle/components/FormField.md +1 -1
- package/bundle/components/ImageGallery.md +19 -52
- package/bundle/components/ImageGalleryExtended.md +123 -139
- package/bundle/components/ListItemControlsButtonDropdown.md +3 -2
- package/bundle/components/LoaderSmall.md +5 -4
- package/bundle/components/MonthYearRange.md +334 -0
- package/bundle/components/MultiselectField.md +81 -143
- package/bundle/components/Notification.md +2 -1
- package/bundle/components/NotificationGrouped.md +174 -0
- package/bundle/components/NumberField.md +259 -116
- package/bundle/components/OrderedList.md +149 -112
- package/bundle/components/Overlay.md +3 -2
- package/bundle/components/PageIndicators.md +306 -0
- package/bundle/components/Pagination.md +81 -3
- package/bundle/components/PaginationExtended.md +160 -0
- package/bundle/components/Portal.md +5 -2
- package/bundle/components/Puller.md +375 -0
- package/bundle/components/SMSField.md +277 -102
- package/bundle/components/SelectExtendedField.md +11 -7
- package/bundle/components/SelectField.md +7 -4
- package/bundle/components/SmartSpot.md +259 -0
- package/bundle/components/Step.md +2 -1
- package/bundle/components/Stepper.md +7 -7
- package/bundle/components/Suggest.md +7 -6
- package/bundle/components/SuggestField.md +8 -6
- package/bundle/components/TableBasic.md +12 -14
- package/bundle/components/Tooltip.md +9 -8
- package/bundle/guides/commits.md +4 -1
- package/bundle/guides/context.md +5 -5
- package/bundle/guides/stories.md +29 -21
- package/bundle/manifest.json +145 -13
- package/bundle/release-notes/1.50.0.mdx +4 -0
- package/bundle/release-notes/1.51.0.mdx +57 -0
- package/bundle/release-notes/1.52.0.mdx +55 -0
- package/bundle/release-notes/1.53.0.mdx +60 -0
- package/bundle/release-notes/1.54.0.mdx +45 -0
- package/bundle/release-notes/1.55.0.mdx +7 -0
- package/bundle/tokens.json +377 -222
- package/dist/index.js +39 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -71,7 +71,7 @@ html-атрибуты корневого `<div>` — приходит из `Sele
|
|
|
71
71
|
| `width` | `EDropdownWidth` | `EDropdownWidth.MIN_TARGET` | Умолчание задаёт компонент; потребитель может переопределить |
|
|
72
72
|
| `size` | `EComponentSize` | из контекста | Умолчание — `size` мульти-списка; явный prop имеет приоритет |
|
|
73
73
|
| `opened`, `setOpened`, `targetRef` | — | — | Обязательные, приходят из рендер-функции `children` |
|
|
74
|
-
| `
|
|
74
|
+
| `pullerProps` | `Omit<IPullerProps, "opened" \| "setOpened">` | — | Содержимое мобильной версии. Мобильная версия включена **всегда** — см. «Инварианты» |
|
|
75
75
|
|
|
76
76
|
Умолчания `focusTrapOptions`: `clickOutsideDeactivates: true`,
|
|
77
77
|
`preventScroll: true`, `returnFocusOnDeactivate` — по признаку «блок открыт мышью».
|
|
@@ -118,7 +118,7 @@ MultiselectField.Divider_Color
|
|
|
118
118
|
- Barrel `src/components/MultiselectField/index.ts` экспортирует только `MultiselectField` и `IMultiselectFieldProps`. Части выпадающего блока публичны **через статические свойства** (`MultiselectField.Dropdown.Header` и т.д.), а не через barrel. Их типы (`IMultiselectFieldDropdownProps`, `IMultiselectFieldDropdownContentProps`, ...) в публичный API не входят — выносить их туда без отдельного решения не нужно.
|
|
119
119
|
- Статические свойства `MultiselectField.Target`, `MultiselectField.Dropdown` и `MultiselectFieldDropdown.Header` / `.Content` / `.Footer` — часть публичного API.
|
|
120
120
|
- `MultiselectField.Target` — это `SelectExtendedFieldTarget` по ссылке (`MultiselectField.Target === SelectExtendedFieldTarget`). Правки в нём затрагивают также `SelectField` и `ChipSelect`.
|
|
121
|
-
- **Мобильная версия выпадающего блока включена всегда.** `MultiselectFieldDropdown` передаёт в `Dropdown` объект `
|
|
121
|
+
- **Мобильная версия выпадающего блока включена всегда.** `MultiselectFieldDropdown` передаёт в `Dropdown` объект `pullerProps` даже когда потребитель ничего не передал — для этого есть константа-заглушка `ALWAYS_PULLER_PROPS`: `Dropdown` выбирает мобильную версию по truthiness этого prop'а. Убрать объект — значит на мобильной ширине отрендерить десктопный блок вместо шторки `Puller`. Наблюдаемое поведение, покрыто unit-тестом «Should render the mobile version on mobile width even without pullerProps». Visual-стори этот инвариант не держат: `PlaygroundExample` передаёт `pullerProps` сам, поэтому скриншоты не упадут, даже если убрать объект из компонента.
|
|
122
122
|
- Признак «открыт мышью» живёт в `mouseUsedRef` в контексте: `MultiselectField` ставит его в `true` на `mousedown`, `MultiselectFieldDropdown` сбрасывает в `false`, когда блок закрылся. Он не state — переключение не должно вызывать перерисовку.
|
|
123
123
|
- `size` из props раздаётся **только через контекст** и до поля выбора не доходит. Потребитель передаёт размер в `MultiselectField.Target` сам. Не «чинить» это без согласования: у поля и у выпадающего блока размеры могут различаться намеренно (в примерах фильтр внутри `Header` — размера SM при MD-поле).
|
|
124
124
|
- `Header` / `Content` / `Footer` объявлены как `React.FC` и `ref` **не пробрасывают** — в отличие от `MultiselectField` и `MultiselectField.Dropdown`. Перевод их на `forwardRef` обратно совместим по props, но меняет тип компонента, поэтому делается отдельной задачей, а не попутно.
|
|
@@ -133,7 +133,7 @@ MultiselectField.Divider_Color
|
|
|
133
133
|
- Пока выпадающий блок открыт, фокус заперт внутри него (`FocusTrap` из `focus-trap-react`). Содержимое обёрнуто в `<div role="presentation">` — обёртка нужна `FocusTrap` как единственный контейнер и не должна попадать в дерево доступности.
|
|
134
134
|
- `clickOutsideDeactivates: true` — нажатие вне блока снимает перехват фокуса, после чего блок закрывает уже `SelectExtendedField` по своему `mousedown`-слушателю.
|
|
135
135
|
- Возврат фокуса на поле при закрытии зависит от того, как блок открыли: после клавиатуры фокус возвращается, после мыши — нет (иначе клик вне блока повторно подсвечивал бы поле). Признак сбрасывается на каждое закрытие, поэтому следующее открытие оценивается заново.
|
|
136
|
-
- `aria-haspopup="listbox"` и `aria-expanded` выставляет `MultiselectField.Target` (то есть `SelectExtendedFieldTarget`). Клавиши открытия поля — `Space`, `Enter`, `ArrowDown`, `ArrowUp
|
|
136
|
+
- `aria-haspopup="listbox"` и `aria-expanded` выставляет `MultiselectField.Target` (то есть `SelectExtendedFieldTarget`). Клавиши открытия поля — `Space`, `Enter`, `ArrowDown`, `ArrowUp`, только когда фокус на самом поле, а не на кнопке тега.
|
|
137
137
|
- `Escape` закрывает блок из любого места страницы — слушатель `SelectExtendedField` висит на `window`.
|
|
138
138
|
- Роли и клавиатурную навигацию **внутри** блока компонент не задаёт: содержимое произвольное (чекбоксы, дерево, кнопки), связь поля со списком (`aria-controls`, `aria-activedescendant`) и `aria-label` на элементах — забота потребителя.
|
|
139
139
|
- Компонент не хардкодит текстовые строки: `fieldLabel`, `placeholder`, подписи кнопок и заголовок мобильной версии передаёт потребитель — библиотека мультиязычная.
|
|
@@ -164,7 +164,7 @@ MultiselectField.Divider_Color
|
|
|
164
164
|
|
|
165
165
|
**Инфраструктура:**
|
|
166
166
|
|
|
167
|
-
- `Dropdown` — выпадающее меню через `Portal`, позиционирование и
|
|
167
|
+
- `Dropdown` — выпадающее меню через `Portal`, позиционирование и мобильная версия в нижней шторке `Puller`.
|
|
168
168
|
- `LoaderScreen` — лоадер поверх содержимого при `Content loading`.
|
|
169
169
|
- `FormField` — визуальный контейнер поля выбора и поля фильтра в `Header`.
|
|
170
170
|
- `Tag` / `TagGroup`, `Checkbox`, `CheckboxTree` — типовое наполнение поля и выпадающего блока в примерах; частью компонента не являются.
|
|
@@ -189,7 +189,7 @@ MultiselectField.Divider_Color
|
|
|
189
189
|
| `Example` | `ProductionExample.tsx` | Приближенный к продуктовому сценарий (в Storybook — «Example: production») |
|
|
190
190
|
| `WithCheckboxTree` | `WithCheckboxTreeExample.tsx` | Дерево категорий вместо плоского списка чекбоксов (в Storybook — «Example: with CheckboxTree») |
|
|
191
191
|
| `VisualTests` | `PlaygroundExample.tsx` | Скриншот-регрессия: поле с выбранным значением и раскрытый блок |
|
|
192
|
-
| `VisualTestsNotFound` | `PlaygroundExample.tsx` | Скриншот-регрессия: пустой результат фильтра во всех размерах; на мобильной ширине —
|
|
192
|
+
| `VisualTestsNotFound` | `PlaygroundExample.tsx` | Скриншот-регрессия: пустой результат фильтра во всех размерах; на мобильной ширине — шторка `Puller` |
|
|
193
193
|
|
|
194
194
|
---
|
|
195
195
|
|
|
@@ -199,6 +199,8 @@ MultiselectField.Divider_Color
|
|
|
199
199
|
|---|---|
|
|
200
200
|
| 2026-09-03 | Создан документ AI-ready для `MultiselectField` (TRI-61). |
|
|
201
201
|
| 2026-09-03 | AI-рефакторинг (TRI-61): JSDoc на props, контексте и всех частях выпадающего блока; значение контекста обёрнуто в `useMemo`, обработчик `onMouseDown` — в `useCallback` (выигрыша в текущей связке нет: части приходят из рендер-функции `children` и пересоздаются каждый рендер независимо от контекста, — это страховка на случай `React.memo` у потребителя); объект-заглушка `mobileViewProps` вынесен в константу, чтобы инвариант «мобильная версия включена всегда» читался из самого выражения; unit-тесты разбиты по субкомпонентам и расширены с 1 до 45 кейсов. Публичный API и наблюдаемое поведение не изменены. |
|
|
202
|
+
| 2026-10-21 | **Breaking** (TRIPLEX-961): prop `mobileViewProps`, унаследованный от `Dropdown`, переименован в `pullerProps`. |
|
|
203
|
+
| 2026-10-29 | TRIPLEX-1028: клик и Enter / Space на кнопках тегов и других фокусируемых элементах внутри `MultiselectField.Target` больше не переключают выпадающий блок, `stopPropagation` в `onKeyDown` тегов для этого не нужен. Клавиши открытия — см. «Accessibility». `onClear` у `MultiselectField.Target` получает событие клика. |
|
|
202
204
|
|
|
203
205
|
---
|
|
204
206
|
|
|
@@ -226,11 +228,11 @@ import {
|
|
|
226
228
|
TagGroup,
|
|
227
229
|
Text,
|
|
228
230
|
ETextSize,
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
PullerFooter,
|
|
232
|
+
PullerBody,
|
|
233
|
+
PullerHeader,
|
|
234
|
+
PullerInput,
|
|
235
|
+
PullerClose,
|
|
234
236
|
} from "@sberbusiness/triplex-next";
|
|
235
237
|
import "../MultiselectField.less";
|
|
236
238
|
|
|
@@ -315,11 +317,6 @@ export const DefaultExample = () => {
|
|
|
315
317
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
316
318
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
317
319
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
318
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
319
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
320
|
-
event.stopPropagation();
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
320
|
|
|
324
321
|
if (!selectedOptions.length) return null;
|
|
325
322
|
if (selectedOptions.length > 3) {
|
|
@@ -330,7 +327,6 @@ export const DefaultExample = () => {
|
|
|
330
327
|
onFocus={handleTagFocus}
|
|
331
328
|
onBlur={handleTagBlur}
|
|
332
329
|
onClick={handleTagClick}
|
|
333
|
-
onKeyDown={handleTagKeyDown}
|
|
334
330
|
onRemove={handleClearAll}
|
|
335
331
|
>
|
|
336
332
|
{`Выбрано ${selectedOptions.length} значения`}
|
|
@@ -348,7 +344,6 @@ export const DefaultExample = () => {
|
|
|
348
344
|
onFocus={handleTagFocus}
|
|
349
345
|
onBlur={handleTagBlur}
|
|
350
346
|
onClick={handleTagClick}
|
|
351
|
-
onKeyDown={handleTagKeyDown}
|
|
352
347
|
onRemove={() => handleToggle(opt, false)}
|
|
353
348
|
>
|
|
354
349
|
{opt.label}
|
|
@@ -379,28 +374,26 @@ export const DefaultExample = () => {
|
|
|
379
374
|
targetRef={dropdownTargetRef}
|
|
380
375
|
ref={dropdownRef}
|
|
381
376
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
382
|
-
|
|
377
|
+
pullerProps={{
|
|
383
378
|
children: (
|
|
384
379
|
<>
|
|
385
|
-
<
|
|
386
|
-
|
|
387
|
-
>
|
|
388
|
-
<DropdownMobileInput
|
|
380
|
+
<PullerHeader controlButtons={<PullerClose onClick={() => setOpened(false)} />}>
|
|
381
|
+
<PullerInput
|
|
389
382
|
autoFocus={true}
|
|
390
383
|
placeholder="Type to proceed"
|
|
391
384
|
value={filter}
|
|
392
385
|
onChange={(event) => setFilter(event.target.value)}
|
|
393
386
|
/>
|
|
394
|
-
</
|
|
395
|
-
<
|
|
387
|
+
</PullerHeader>
|
|
388
|
+
<PullerBody>
|
|
396
389
|
{renderCheckboxList()}
|
|
397
390
|
{!!filter.trim().length && !visibleOptions.length && (
|
|
398
391
|
<Text size={ETextSize.B3} className="not-found">
|
|
399
392
|
Nothing was found.
|
|
400
393
|
</Text>
|
|
401
394
|
)}
|
|
402
|
-
</
|
|
403
|
-
<
|
|
395
|
+
</PullerBody>
|
|
396
|
+
<PullerFooter>
|
|
404
397
|
<Button
|
|
405
398
|
theme={EButtonTheme.SECONDARY}
|
|
406
399
|
size={EComponentSize.MD}
|
|
@@ -415,7 +408,7 @@ export const DefaultExample = () => {
|
|
|
415
408
|
>
|
|
416
409
|
Button link text
|
|
417
410
|
</Button>
|
|
418
|
-
</
|
|
411
|
+
</PullerFooter>
|
|
419
412
|
</>
|
|
420
413
|
),
|
|
421
414
|
}}
|
|
@@ -577,11 +570,6 @@ const SizeItem = ({ size }: ISizeItemProps) => {
|
|
|
577
570
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
578
571
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
579
572
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
580
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
581
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
582
|
-
event.stopPropagation();
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
573
|
|
|
586
574
|
if (!selectedOptions.length) return null;
|
|
587
575
|
|
|
@@ -595,7 +583,6 @@ const SizeItem = ({ size }: ISizeItemProps) => {
|
|
|
595
583
|
onFocus={handleTagFocus}
|
|
596
584
|
onBlur={handleTagBlur}
|
|
597
585
|
onClick={handleTagClick}
|
|
598
|
-
onKeyDown={handleTagKeyDown}
|
|
599
586
|
onRemove={() => handleToggle(opt, false)}
|
|
600
587
|
>
|
|
601
588
|
{opt.label}
|
|
@@ -790,11 +777,6 @@ const StatusItem = ({ idPrefix, status }: IStatusItemProps) => {
|
|
|
790
777
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
791
778
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
792
779
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
793
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
794
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
795
|
-
event.stopPropagation();
|
|
796
|
-
}
|
|
797
|
-
};
|
|
798
780
|
|
|
799
781
|
if (!selectedOptions.length) return null;
|
|
800
782
|
|
|
@@ -808,7 +790,6 @@ const StatusItem = ({ idPrefix, status }: IStatusItemProps) => {
|
|
|
808
790
|
onFocus={handleTagFocus}
|
|
809
791
|
onBlur={handleTagBlur}
|
|
810
792
|
onClick={handleTagClick}
|
|
811
|
-
onKeyDown={handleTagKeyDown}
|
|
812
793
|
onRemove={() => handleToggle(opt, false)}
|
|
813
794
|
>
|
|
814
795
|
{opt.label}
|
|
@@ -903,12 +884,12 @@ import {
|
|
|
903
884
|
ETextSize,
|
|
904
885
|
Tag,
|
|
905
886
|
TagGroup,
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
887
|
+
PullerHeader,
|
|
888
|
+
PullerClose,
|
|
889
|
+
PullerInput,
|
|
890
|
+
PullerBody,
|
|
891
|
+
PullerFooter,
|
|
892
|
+
PullerLoader,
|
|
912
893
|
} from "@sberbusiness/triplex-next";
|
|
913
894
|
import "../MultiselectField.less";
|
|
914
895
|
|
|
@@ -1010,11 +991,6 @@ const LoadingMultiselect = ({
|
|
|
1010
991
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1011
992
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1012
993
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1013
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
1014
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
1015
|
-
event.stopPropagation();
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
994
|
|
|
1019
995
|
if (!selectedOptions.length) return null;
|
|
1020
996
|
|
|
@@ -1028,7 +1004,6 @@ const LoadingMultiselect = ({
|
|
|
1028
1004
|
onFocus={handleTagFocus}
|
|
1029
1005
|
onBlur={handleTagBlur}
|
|
1030
1006
|
onClick={handleTagClick}
|
|
1031
|
-
onKeyDown={handleTagKeyDown}
|
|
1032
1007
|
onRemove={() => handleToggle(opt, false)}
|
|
1033
1008
|
>
|
|
1034
1009
|
{opt.label}
|
|
@@ -1059,33 +1034,33 @@ const LoadingMultiselect = ({
|
|
|
1059
1034
|
targetRef={dropdownTargetRef}
|
|
1060
1035
|
ref={dropdownRef}
|
|
1061
1036
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
1062
|
-
|
|
1037
|
+
pullerProps={{
|
|
1063
1038
|
children: (
|
|
1064
1039
|
<>
|
|
1065
|
-
<
|
|
1040
|
+
<PullerHeader
|
|
1066
1041
|
controlButtons={
|
|
1067
1042
|
<>
|
|
1068
|
-
<
|
|
1069
|
-
<
|
|
1043
|
+
<PullerLoader />
|
|
1044
|
+
<PullerClose onClick={() => setOpened(false)} />
|
|
1070
1045
|
</>
|
|
1071
1046
|
}
|
|
1072
1047
|
>
|
|
1073
|
-
<
|
|
1048
|
+
<PullerInput
|
|
1074
1049
|
autoFocus={true}
|
|
1075
1050
|
placeholder="Type to proceed"
|
|
1076
1051
|
value={filter}
|
|
1077
1052
|
onChange={(event) => setFilter(event.target.value)}
|
|
1078
1053
|
/>
|
|
1079
|
-
</
|
|
1080
|
-
<
|
|
1054
|
+
</PullerHeader>
|
|
1055
|
+
<PullerBody>
|
|
1081
1056
|
{renderCheckboxList()}
|
|
1082
1057
|
{!!filter.trim().length && !visibleOptions.length && (
|
|
1083
1058
|
<Text size={ETextSize.B3} className="not-found">
|
|
1084
1059
|
Nothing was found.
|
|
1085
1060
|
</Text>
|
|
1086
1061
|
)}
|
|
1087
|
-
</
|
|
1088
|
-
<
|
|
1062
|
+
</PullerBody>
|
|
1063
|
+
<PullerFooter>
|
|
1089
1064
|
<Button
|
|
1090
1065
|
theme={EButtonTheme.SECONDARY}
|
|
1091
1066
|
size={EComponentSize.MD}
|
|
@@ -1096,7 +1071,7 @@ const LoadingMultiselect = ({
|
|
|
1096
1071
|
<Button theme={EButtonTheme.LINK} size={EComponentSize.MD} onClick={handleClearAll}>
|
|
1097
1072
|
Button link text
|
|
1098
1073
|
</Button>
|
|
1099
|
-
</
|
|
1074
|
+
</PullerFooter>
|
|
1100
1075
|
</>
|
|
1101
1076
|
),
|
|
1102
1077
|
}}
|
|
@@ -1147,11 +1122,11 @@ import {
|
|
|
1147
1122
|
Button,
|
|
1148
1123
|
Checkbox,
|
|
1149
1124
|
CheckboxYGroup,
|
|
1150
|
-
DropdownMobileBody,
|
|
1151
|
-
DropdownMobileFooter,
|
|
1152
1125
|
EButtonTheme,
|
|
1153
1126
|
EComponentSize,
|
|
1154
1127
|
MultiselectField,
|
|
1128
|
+
PullerBody,
|
|
1129
|
+
PullerFooter,
|
|
1155
1130
|
Tag,
|
|
1156
1131
|
TagGroup,
|
|
1157
1132
|
} from "@sberbusiness/triplex-next";
|
|
@@ -1217,11 +1192,6 @@ export const DropdownWithoutInputExample = () => {
|
|
|
1217
1192
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1218
1193
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1219
1194
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1220
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
1221
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
1222
|
-
event.stopPropagation();
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
1195
|
|
|
1226
1196
|
if (!selectedOptions.length) return null;
|
|
1227
1197
|
|
|
@@ -1235,7 +1205,6 @@ export const DropdownWithoutInputExample = () => {
|
|
|
1235
1205
|
onFocus={handleTagFocus}
|
|
1236
1206
|
onBlur={handleTagBlur}
|
|
1237
1207
|
onClick={handleTagClick}
|
|
1238
|
-
onKeyDown={handleTagKeyDown}
|
|
1239
1208
|
onRemove={() => handleToggle(opt, false)}
|
|
1240
1209
|
>
|
|
1241
1210
|
{opt.label}
|
|
@@ -1266,11 +1235,11 @@ export const DropdownWithoutInputExample = () => {
|
|
|
1266
1235
|
targetRef={dropdownTargetRef}
|
|
1267
1236
|
ref={dropdownRef}
|
|
1268
1237
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
1269
|
-
|
|
1238
|
+
pullerProps={{
|
|
1270
1239
|
children: (
|
|
1271
1240
|
<>
|
|
1272
|
-
<
|
|
1273
|
-
<
|
|
1241
|
+
<PullerBody>{renderCheckboxList()}</PullerBody>
|
|
1242
|
+
<PullerFooter>
|
|
1274
1243
|
<Button
|
|
1275
1244
|
theme={EButtonTheme.SECONDARY}
|
|
1276
1245
|
size={EComponentSize.MD}
|
|
@@ -1285,7 +1254,7 @@ export const DropdownWithoutInputExample = () => {
|
|
|
1285
1254
|
>
|
|
1286
1255
|
Button link text
|
|
1287
1256
|
</Button>
|
|
1288
|
-
</
|
|
1257
|
+
</PullerFooter>
|
|
1289
1258
|
</>
|
|
1290
1259
|
),
|
|
1291
1260
|
}}
|
|
@@ -1333,11 +1302,11 @@ import {
|
|
|
1333
1302
|
ETextSize,
|
|
1334
1303
|
Tag,
|
|
1335
1304
|
TagGroup,
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1305
|
+
PullerHeader,
|
|
1306
|
+
PullerClose,
|
|
1307
|
+
PullerInput,
|
|
1308
|
+
PullerBody,
|
|
1309
|
+
PullerFooter,
|
|
1341
1310
|
} from "@sberbusiness/triplex-next";
|
|
1342
1311
|
import "../MultiselectField.less";
|
|
1343
1312
|
|
|
@@ -1414,11 +1383,6 @@ export const WithClearButtonExample = () => {
|
|
|
1414
1383
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1415
1384
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1416
1385
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1417
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
1418
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
1419
|
-
event.stopPropagation();
|
|
1420
|
-
}
|
|
1421
|
-
};
|
|
1422
1386
|
|
|
1423
1387
|
if (!selectedOptions.length) return null;
|
|
1424
1388
|
|
|
@@ -1432,7 +1396,6 @@ export const WithClearButtonExample = () => {
|
|
|
1432
1396
|
onFocus={handleTagFocus}
|
|
1433
1397
|
onBlur={handleTagBlur}
|
|
1434
1398
|
onClick={handleTagClick}
|
|
1435
|
-
onKeyDown={handleTagKeyDown}
|
|
1436
1399
|
onRemove={() => handleToggle(opt, false)}
|
|
1437
1400
|
>
|
|
1438
1401
|
{opt.label}
|
|
@@ -1464,28 +1427,26 @@ export const WithClearButtonExample = () => {
|
|
|
1464
1427
|
targetRef={dropdownTargetRef}
|
|
1465
1428
|
ref={dropdownRef}
|
|
1466
1429
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
1467
|
-
|
|
1430
|
+
pullerProps={{
|
|
1468
1431
|
children: (
|
|
1469
1432
|
<>
|
|
1470
|
-
<
|
|
1471
|
-
|
|
1472
|
-
>
|
|
1473
|
-
<DropdownMobileInput
|
|
1433
|
+
<PullerHeader controlButtons={<PullerClose onClick={() => setOpened(false)} />}>
|
|
1434
|
+
<PullerInput
|
|
1474
1435
|
autoFocus={true}
|
|
1475
1436
|
placeholder="Type to proceed"
|
|
1476
1437
|
value={filter}
|
|
1477
1438
|
onChange={(event) => setFilter(event.target.value)}
|
|
1478
1439
|
/>
|
|
1479
|
-
</
|
|
1480
|
-
<
|
|
1440
|
+
</PullerHeader>
|
|
1441
|
+
<PullerBody>
|
|
1481
1442
|
{renderCheckboxList()}
|
|
1482
1443
|
{!!filter.trim().length && !visibleOptions.length && (
|
|
1483
1444
|
<Text size={ETextSize.B3} className="not-found">
|
|
1484
1445
|
Nothing was found.
|
|
1485
1446
|
</Text>
|
|
1486
1447
|
)}
|
|
1487
|
-
</
|
|
1488
|
-
<
|
|
1448
|
+
</PullerBody>
|
|
1449
|
+
<PullerFooter>
|
|
1489
1450
|
<Button
|
|
1490
1451
|
theme={EButtonTheme.SECONDARY}
|
|
1491
1452
|
size={EComponentSize.MD}
|
|
@@ -1500,7 +1461,7 @@ export const WithClearButtonExample = () => {
|
|
|
1500
1461
|
>
|
|
1501
1462
|
Button link text
|
|
1502
1463
|
</Button>
|
|
1503
|
-
</
|
|
1464
|
+
</PullerFooter>
|
|
1504
1465
|
</>
|
|
1505
1466
|
),
|
|
1506
1467
|
}}
|
|
@@ -1566,11 +1527,11 @@ import {
|
|
|
1566
1527
|
ETextSize,
|
|
1567
1528
|
Tag,
|
|
1568
1529
|
TagGroup,
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1530
|
+
PullerHeader,
|
|
1531
|
+
PullerClose,
|
|
1532
|
+
PullerInput,
|
|
1533
|
+
PullerBody,
|
|
1534
|
+
PullerFooter,
|
|
1574
1535
|
IconWrapper,
|
|
1575
1536
|
} from "@sberbusiness/triplex-next";
|
|
1576
1537
|
import { DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
|
|
@@ -1648,11 +1609,6 @@ export const WithPrefixAndPostfixExample = () => {
|
|
|
1648
1609
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1649
1610
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1650
1611
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1651
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
1652
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
1653
|
-
event.stopPropagation();
|
|
1654
|
-
}
|
|
1655
|
-
};
|
|
1656
1612
|
|
|
1657
1613
|
if (!selectedOptions.length) return null;
|
|
1658
1614
|
|
|
@@ -1666,7 +1622,6 @@ export const WithPrefixAndPostfixExample = () => {
|
|
|
1666
1622
|
onFocus={handleTagFocus}
|
|
1667
1623
|
onBlur={handleTagBlur}
|
|
1668
1624
|
onClick={handleTagClick}
|
|
1669
|
-
onKeyDown={handleTagKeyDown}
|
|
1670
1625
|
onRemove={() => handleToggle(opt, false)}
|
|
1671
1626
|
>
|
|
1672
1627
|
{opt.label}
|
|
@@ -1703,28 +1658,26 @@ export const WithPrefixAndPostfixExample = () => {
|
|
|
1703
1658
|
targetRef={dropdownTargetRef}
|
|
1704
1659
|
ref={dropdownRef}
|
|
1705
1660
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
1706
|
-
|
|
1661
|
+
pullerProps={{
|
|
1707
1662
|
children: (
|
|
1708
1663
|
<>
|
|
1709
|
-
<
|
|
1710
|
-
|
|
1711
|
-
>
|
|
1712
|
-
<DropdownMobileInput
|
|
1664
|
+
<PullerHeader controlButtons={<PullerClose onClick={() => setOpened(false)} />}>
|
|
1665
|
+
<PullerInput
|
|
1713
1666
|
autoFocus={true}
|
|
1714
1667
|
placeholder="Type to proceed"
|
|
1715
1668
|
value={filter}
|
|
1716
1669
|
onChange={(event) => setFilter(event.target.value)}
|
|
1717
1670
|
/>
|
|
1718
|
-
</
|
|
1719
|
-
<
|
|
1671
|
+
</PullerHeader>
|
|
1672
|
+
<PullerBody>
|
|
1720
1673
|
{renderCheckboxList()}
|
|
1721
1674
|
{!!filter.trim().length && !visibleOptions.length && (
|
|
1722
1675
|
<Text size={ETextSize.B3} className="not-found">
|
|
1723
1676
|
Nothing was found.
|
|
1724
1677
|
</Text>
|
|
1725
1678
|
)}
|
|
1726
|
-
</
|
|
1727
|
-
<
|
|
1679
|
+
</PullerBody>
|
|
1680
|
+
<PullerFooter>
|
|
1728
1681
|
<Button
|
|
1729
1682
|
theme={EButtonTheme.SECONDARY}
|
|
1730
1683
|
size={EComponentSize.MD}
|
|
@@ -1739,7 +1692,7 @@ export const WithPrefixAndPostfixExample = () => {
|
|
|
1739
1692
|
>
|
|
1740
1693
|
Button link text
|
|
1741
1694
|
</Button>
|
|
1742
|
-
</
|
|
1695
|
+
</PullerFooter>
|
|
1743
1696
|
</>
|
|
1744
1697
|
),
|
|
1745
1698
|
}}
|
|
@@ -1791,11 +1744,6 @@ import {
|
|
|
1791
1744
|
Button,
|
|
1792
1745
|
Checkbox,
|
|
1793
1746
|
CheckboxYGroup,
|
|
1794
|
-
DropdownMobileBody,
|
|
1795
|
-
DropdownMobileClose,
|
|
1796
|
-
DropdownMobileFooter,
|
|
1797
|
-
DropdownMobileHeader,
|
|
1798
|
-
DropdownMobileInput,
|
|
1799
1747
|
EButtonTheme,
|
|
1800
1748
|
EComponentSize,
|
|
1801
1749
|
EFontType,
|
|
@@ -1810,6 +1758,11 @@ import {
|
|
|
1810
1758
|
HelpBox,
|
|
1811
1759
|
Link,
|
|
1812
1760
|
MultiselectField,
|
|
1761
|
+
PullerBody,
|
|
1762
|
+
PullerClose,
|
|
1763
|
+
PullerFooter,
|
|
1764
|
+
PullerHeader,
|
|
1765
|
+
PullerInput,
|
|
1813
1766
|
Tag,
|
|
1814
1767
|
TagGroup,
|
|
1815
1768
|
Text,
|
|
@@ -1904,11 +1857,6 @@ const ProductionMultiselect = () => {
|
|
|
1904
1857
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1905
1858
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1906
1859
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
1907
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
1908
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
1909
|
-
event.stopPropagation();
|
|
1910
|
-
}
|
|
1911
|
-
};
|
|
1912
1860
|
|
|
1913
1861
|
if (!selectedOptions.length) return null;
|
|
1914
1862
|
|
|
@@ -1922,7 +1870,6 @@ const ProductionMultiselect = () => {
|
|
|
1922
1870
|
onFocus={handleTagFocus}
|
|
1923
1871
|
onBlur={handleTagBlur}
|
|
1924
1872
|
onClick={handleTagClick}
|
|
1925
|
-
onKeyDown={handleTagKeyDown}
|
|
1926
1873
|
onRemove={() => handleToggle(opt, false)}
|
|
1927
1874
|
>
|
|
1928
1875
|
{opt.label}
|
|
@@ -1955,28 +1902,26 @@ const ProductionMultiselect = () => {
|
|
|
1955
1902
|
targetRef={dropdownTargetRef}
|
|
1956
1903
|
ref={dropdownRef}
|
|
1957
1904
|
focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
|
|
1958
|
-
|
|
1905
|
+
pullerProps={{
|
|
1959
1906
|
children: (
|
|
1960
1907
|
<>
|
|
1961
|
-
<
|
|
1962
|
-
|
|
1963
|
-
>
|
|
1964
|
-
<DropdownMobileInput
|
|
1908
|
+
<PullerHeader controlButtons={<PullerClose onClick={() => setOpened(false)} />}>
|
|
1909
|
+
<PullerInput
|
|
1965
1910
|
autoFocus={true}
|
|
1966
1911
|
placeholder="Type to proceed"
|
|
1967
1912
|
value={filter}
|
|
1968
1913
|
onChange={(event) => setFilter(event.target.value)}
|
|
1969
1914
|
/>
|
|
1970
|
-
</
|
|
1971
|
-
<
|
|
1915
|
+
</PullerHeader>
|
|
1916
|
+
<PullerBody>
|
|
1972
1917
|
{renderCheckboxList()}
|
|
1973
1918
|
{!!filter.trim().length && !visibleOptions.length && (
|
|
1974
1919
|
<Text size={ETextSize.B3} className="not-found">
|
|
1975
1920
|
Nothing was found.
|
|
1976
1921
|
</Text>
|
|
1977
1922
|
)}
|
|
1978
|
-
</
|
|
1979
|
-
<
|
|
1923
|
+
</PullerBody>
|
|
1924
|
+
<PullerFooter>
|
|
1980
1925
|
<Button
|
|
1981
1926
|
theme={EButtonTheme.SECONDARY}
|
|
1982
1927
|
size={EComponentSize.MD}
|
|
@@ -1987,7 +1932,7 @@ const ProductionMultiselect = () => {
|
|
|
1987
1932
|
<Button theme={EButtonTheme.LINK} size={EComponentSize.MD} onClick={handleClearAll}>
|
|
1988
1933
|
Button link text
|
|
1989
1934
|
</Button>
|
|
1990
|
-
</
|
|
1935
|
+
</PullerFooter>
|
|
1991
1936
|
</>
|
|
1992
1937
|
),
|
|
1993
1938
|
}}
|
|
@@ -2159,11 +2104,6 @@ export const WithCheckboxTreeExample = () => {
|
|
|
2159
2104
|
const handleTagFocus = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
2160
2105
|
const handleTagBlur = (event: React.FocusEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
2161
2106
|
const handleTagClick = (event: React.MouseEvent<HTMLSpanElement>) => event.stopPropagation();
|
|
2162
|
-
const handleTagKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
2163
|
-
if (event.code === "Enter" || event.code === "Space") {
|
|
2164
|
-
event.stopPropagation();
|
|
2165
|
-
}
|
|
2166
|
-
};
|
|
2167
2107
|
|
|
2168
2108
|
if (!selectedLeafNodes.length) return null;
|
|
2169
2109
|
if (selectedLeafNodes.length > 3) {
|
|
@@ -2174,7 +2114,6 @@ export const WithCheckboxTreeExample = () => {
|
|
|
2174
2114
|
onFocus={handleTagFocus}
|
|
2175
2115
|
onBlur={handleTagBlur}
|
|
2176
2116
|
onClick={handleTagClick}
|
|
2177
|
-
onKeyDown={handleTagKeyDown}
|
|
2178
2117
|
onRemove={() => setSelectedIds([])}
|
|
2179
2118
|
>
|
|
2180
2119
|
{`Выбрано ${selectedLeafNodes.length} значения`}
|
|
@@ -2191,7 +2130,6 @@ export const WithCheckboxTreeExample = () => {
|
|
|
2191
2130
|
onFocus={handleTagFocus}
|
|
2192
2131
|
onBlur={handleTagBlur}
|
|
2193
2132
|
onClick={handleTagClick}
|
|
2194
|
-
onKeyDown={handleTagKeyDown}
|
|
2195
2133
|
onRemove={() => setSelectedIds((prev) => prev.filter((id) => id !== node.id))}
|
|
2196
2134
|
>
|
|
2197
2135
|
{node.label}
|
|
@@ -123,7 +123,7 @@ Notification.TimeColor (цвет времени)
|
|
|
123
123
|
|
|
124
124
|
## Связанные компоненты
|
|
125
125
|
|
|
126
|
-
- `NotificationGrouped` — обёртка для отображения уведомления
|
|
126
|
+
- `NotificationGrouped` — обёртка для отображения уведомления стопкой; см. [`NotificationGrouped-ai.md`](./NotificationGrouped-ai.md).
|
|
127
127
|
- `Button` — типичное содержимое `Notification.Body.Footer`.
|
|
128
128
|
- `AlertContext` — может вкладываться в `Notification.Body.Footer`.
|
|
129
129
|
- `UnorderedList` — основа `Notification.Body.List`.
|
|
@@ -153,6 +153,7 @@ Notification.TimeColor (цвет времени)
|
|
|
153
153
|
|---|---|
|
|
154
154
|
| 2026-06-16 | Создан AI-документ. `Notification`, `NotificationGrouped`, `NotificationBody` переведены на `forwardRef` (паттерн `Object.assign`); удалены типы `INotificationSFC`/`INotificationBodySFC`; тип `Notification.Time.time` расширен с `React.ReactText` до `React.ReactNode`. Stories мигрированы на modern pattern. |
|
|
155
155
|
| 2026-09-28 | Токен `Notification.Shadow` ссылается на `Shadow.07` (светлая) и `DarkShadow.07` (тёмная) вместо литералов; в тёмной теме прозрачность 0.25 вместо 0.35. |
|
|
156
|
+
| 2026-10-15 | Добавлена ссылка на отдельный `NotificationGrouped-ai.md`. |
|
|
156
157
|
|
|
157
158
|
---
|
|
158
159
|
|