@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
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: CarouselItem
|
|
3
|
+
category: Carousel
|
|
4
|
+
related: [Carousel]
|
|
5
|
+
tokens: []
|
|
6
|
+
stories: stories/Carousel/Carousel.stories.tsx
|
|
7
|
+
version: "1.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# CarouselItem
|
|
11
|
+
|
|
12
|
+
## Назначение
|
|
13
|
+
|
|
14
|
+
Слайд составного `Carousel`. Регистрирует свой DOM-узел по `index`, по этим
|
|
15
|
+
узлам родитель измеряет слайды и рассчитывает страницы и границы прокрутки.
|
|
16
|
+
|
|
17
|
+
Используй внутри `Carousel.Track`, вложенного в `Carousel.Viewport`.
|
|
18
|
+
Не используй вне `Carousel`: без родителя слайд не измеряется и не участвует
|
|
19
|
+
в навигации.
|
|
20
|
+
|
|
21
|
+
Доступен только как `Carousel.Item`: именованного экспорта `CarouselItem`
|
|
22
|
+
из пакета нет, `ICarouselItemProps` экспортируется.
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { Carousel } from "@sberbusiness/triplex-next";
|
|
26
|
+
|
|
27
|
+
<Carousel style={{ width: 320, height: 180 }}>
|
|
28
|
+
<Carousel.Viewport>
|
|
29
|
+
<Carousel.Track>
|
|
30
|
+
{items.map((item, index) => (
|
|
31
|
+
<Carousel.Item key={item.id} index={index} aria-label={item.title} style={{ width: 280 }}>
|
|
32
|
+
{item.title}
|
|
33
|
+
</Carousel.Item>
|
|
34
|
+
))}
|
|
35
|
+
</Carousel.Track>
|
|
36
|
+
</Carousel.Viewport>
|
|
37
|
+
</Carousel>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Варианты и props
|
|
43
|
+
|
|
44
|
+
### Обязательные props
|
|
45
|
+
|
|
46
|
+
| Prop | Тип | Описание |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `index` | `number` | Позиция слайда с нуля. Ключ регистрации для геометрии, не HTML-атрибут |
|
|
49
|
+
|
|
50
|
+
Остальные props — атрибуты `<div>`, передаются на корень слайда.
|
|
51
|
+
|
|
52
|
+
### Индексы
|
|
53
|
+
|
|
54
|
+
- Индексы уникальны, идут подряд (`0, 1, 2, …`) и совпадают с DOM-порядком.
|
|
55
|
+
Пропуск, дубликат или несовпадение с порядком ломают расчёт страниц;
|
|
56
|
+
компонент такой ввод не проверяет.
|
|
57
|
+
- `index` берётся из позиции в `map`, `key` — из стабильного id данных. После
|
|
58
|
+
удаления, вставки или перестановки потребитель пересчитывает индексы.
|
|
59
|
+
- Регистрация не запускает пересчёт геометрии. Кэш размеров слайдов
|
|
60
|
+
сбрасывается при изменении размеров `Viewport` или `Track`
|
|
61
|
+
(`ResizeObserver`) и при смене `gap`, `scrollMode` или `orientation`:
|
|
62
|
+
после перестановки слайдов без этих изменений в кэше остаются прежние
|
|
63
|
+
размеры по индексам.
|
|
64
|
+
- Размер слайда задаёт потребитель или содержимое; родитель измеряет ширину
|
|
65
|
+
в горизонтальной карусели и высоту в вертикальной.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Дизайн-токены
|
|
70
|
+
|
|
71
|
+
Собственных токенов нет.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Инварианты
|
|
76
|
+
|
|
77
|
+
- `forwardRef` указывает на корневой `<div>` слайда; внешний ref объединяется
|
|
78
|
+
с регистрационным callback.
|
|
79
|
+
- `displayName` — `"Carousel.Item"`, CSS-класс — `slide`.
|
|
80
|
+
- При смене `index` и размонтировании прежняя запись удаляется из реестра:
|
|
81
|
+
родитель считает слайды по числу записей, а не по `children`.
|
|
82
|
+
- `role="group"` задан до spread, потребитель может его переопределить.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Accessibility
|
|
87
|
+
|
|
88
|
+
- Роль по умолчанию — `group`; доступное имя задаёт потребитель через
|
|
89
|
+
`aria-label` или `aria-labelledby`.
|
|
90
|
+
- `index` не даёт `aria-posinset` / `aria-setsize` и связей с индикаторами.
|
|
91
|
+
- Слайды за пределами видимой области не получают `aria-hidden`, `inert`
|
|
92
|
+
или `tabIndex={-1}`: их содержимое остаётся в Tab-порядке.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Связанные компоненты
|
|
97
|
+
|
|
98
|
+
- `Carousel` — владелец контекста, геометрии и навигации.
|
|
99
|
+
- `Carousel.Track` — лента слайдов, задаёт `gap` и смещение.
|
|
100
|
+
- `Carousel.Viewport` — видимая область и touch-жесты.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Stories
|
|
105
|
+
|
|
106
|
+
Основные истории: `stories/Carousel/Carousel.stories.tsx`
|
|
107
|
+
Файлы примеров: `stories/Carousel/examples/`
|
|
108
|
+
|
|
109
|
+
| Story | Example file | Что демонстрирует |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `Playground` | `Playground.tsx` | Слайды при смене ориентации, режима прокрутки и зазора |
|
|
112
|
+
| `Default` | `Default.tsx` | Слайды разной ширины |
|
|
113
|
+
| `ScrollModes` | `ScrollModes.tsx` | Слайды в режимах `ITEM` и `PAGE` |
|
|
114
|
+
| `Orientations` | `Orientations.tsx` | Ширина горизонтальных и высота вертикальных слайдов |
|
|
115
|
+
| `Production` | `Production.tsx` | Слайды с карточками и вложенными кнопками |
|
|
116
|
+
| `DynamicIndicators` | `DynamicIndicators.tsx` | Длинная лента слайдов |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## История изменений
|
|
121
|
+
|
|
122
|
+
| Дата | Изменение |
|
|
123
|
+
|---|---|
|
|
124
|
+
| 2026-10-20 | Создан документ |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Примеры использования
|
|
129
|
+
|
|
130
|
+
### Default
|
|
131
|
+
|
|
132
|
+
`stories/Carousel/examples/Default.tsx`
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import React from "react";
|
|
136
|
+
import { Carousel } from "@sberbusiness/triplex-next";
|
|
137
|
+
|
|
138
|
+
const BASE_ITEM_STYLE: React.CSSProperties = {
|
|
139
|
+
display: "flex",
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
justifyContent: "center",
|
|
142
|
+
boxSizing: "border-box",
|
|
143
|
+
borderRadius: "8px",
|
|
144
|
+
color: "#ffffff",
|
|
145
|
+
fontSize: "24px",
|
|
146
|
+
fontWeight: "bold",
|
|
147
|
+
userSelect: "none",
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const Default = () => {
|
|
151
|
+
const itemSizes = [92, 168, 220, 244, 252, 256, 252, 244, 220, 168, 92];
|
|
152
|
+
const items = itemSizes.map((size, index) => {
|
|
153
|
+
const totalItems = itemSizes.length;
|
|
154
|
+
const hue = (index / (totalItems - 1)) * 280;
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
id: index + 1,
|
|
158
|
+
size,
|
|
159
|
+
backgroundColor: `hsl(${hue}, 50%, 50%)`,
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const boxStyle: React.CSSProperties = {
|
|
164
|
+
width: "100%",
|
|
165
|
+
height: "256px",
|
|
166
|
+
maxWidth: "512px",
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<div style={boxStyle}>
|
|
171
|
+
<Carousel>
|
|
172
|
+
<Carousel.Viewport>
|
|
173
|
+
<Carousel.Track>
|
|
174
|
+
{items.map((item, index) => (
|
|
175
|
+
<Carousel.Item
|
|
176
|
+
key={item.id}
|
|
177
|
+
index={index}
|
|
178
|
+
style={{
|
|
179
|
+
...BASE_ITEM_STYLE,
|
|
180
|
+
width: item.size,
|
|
181
|
+
height: "100%",
|
|
182
|
+
backgroundColor: item.backgroundColor,
|
|
183
|
+
}}
|
|
184
|
+
>
|
|
185
|
+
{item.id}
|
|
186
|
+
</Carousel.Item>
|
|
187
|
+
))}
|
|
188
|
+
</Carousel.Track>
|
|
189
|
+
<Carousel.PrevButton aria-label="Previous slide" />
|
|
190
|
+
<Carousel.NextButton aria-label="Next slide" />
|
|
191
|
+
</Carousel.Viewport>
|
|
192
|
+
</Carousel>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### ScrollModes
|
|
199
|
+
|
|
200
|
+
`stories/Carousel/examples/ScrollModes.tsx`
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import React from "react";
|
|
204
|
+
import { Carousel, ECarouselScrollMode } from "@sberbusiness/triplex-next";
|
|
205
|
+
|
|
206
|
+
interface ScrollModeItemProps {
|
|
207
|
+
scrollMode: ECarouselScrollMode;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const BASE_ITEM_STYLE: React.CSSProperties = {
|
|
211
|
+
display: "flex",
|
|
212
|
+
alignItems: "center",
|
|
213
|
+
justifyContent: "center",
|
|
214
|
+
boxSizing: "border-box",
|
|
215
|
+
height: "256px",
|
|
216
|
+
borderRadius: "8px",
|
|
217
|
+
color: "#ffffff",
|
|
218
|
+
fontSize: "24px",
|
|
219
|
+
fontWeight: "bold",
|
|
220
|
+
userSelect: "none",
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const ScrollModeItem = ({ scrollMode }: ScrollModeItemProps) => {
|
|
224
|
+
const itemSizes = [92, 168, 220, 244, 252, 256, 252, 244, 220, 168, 92];
|
|
225
|
+
const items = itemSizes.map((size, index) => {
|
|
226
|
+
const totalItems = itemSizes.length;
|
|
227
|
+
const hue = (index / (totalItems - 1)) * 280;
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
id: index + 1,
|
|
231
|
+
size,
|
|
232
|
+
backgroundColor: `hsl(${hue}, 50%, 50%)`,
|
|
233
|
+
};
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const containerStyle: React.CSSProperties = {
|
|
237
|
+
maxWidth: "512px",
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<div style={containerStyle}>
|
|
242
|
+
<div style={{ marginBottom: 8, fontSize: 16, fontWeight: 700 }}>{scrollMode.toUpperCase()}</div>
|
|
243
|
+
<Carousel scrollMode={scrollMode}>
|
|
244
|
+
<Carousel.Viewport>
|
|
245
|
+
<Carousel.Track>
|
|
246
|
+
{items.map((item, index) => (
|
|
247
|
+
<Carousel.Item
|
|
248
|
+
key={item.id}
|
|
249
|
+
index={index}
|
|
250
|
+
style={{
|
|
251
|
+
...BASE_ITEM_STYLE,
|
|
252
|
+
width: item.size,
|
|
253
|
+
backgroundColor: item.backgroundColor,
|
|
254
|
+
}}
|
|
255
|
+
>
|
|
256
|
+
{item.id}
|
|
257
|
+
</Carousel.Item>
|
|
258
|
+
))}
|
|
259
|
+
</Carousel.Track>
|
|
260
|
+
<Carousel.PrevButton aria-label="Previous slide" />
|
|
261
|
+
<Carousel.NextButton aria-label="Next slide" />
|
|
262
|
+
</Carousel.Viewport>
|
|
263
|
+
<Carousel.Indicators />
|
|
264
|
+
</Carousel>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const SCROLL_MODES = Object.values(ECarouselScrollMode);
|
|
270
|
+
|
|
271
|
+
export const ScrollModes = () => (
|
|
272
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
|
273
|
+
{SCROLL_MODES.map((scrollMode) => (
|
|
274
|
+
<ScrollModeItem key={scrollMode} scrollMode={scrollMode} />
|
|
275
|
+
))}
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Orientations
|
|
281
|
+
|
|
282
|
+
`stories/Carousel/examples/Orientations.tsx`
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
import React from "react";
|
|
286
|
+
import { Carousel, EOrientation } from "@sberbusiness/triplex-next";
|
|
287
|
+
|
|
288
|
+
interface OrientationItemProps {
|
|
289
|
+
orientation: EOrientation;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const BASE_ITEM_STYLE: React.CSSProperties = {
|
|
293
|
+
display: "flex",
|
|
294
|
+
alignItems: "center",
|
|
295
|
+
justifyContent: "center",
|
|
296
|
+
boxSizing: "border-box",
|
|
297
|
+
borderRadius: "8px",
|
|
298
|
+
color: "#ffffff",
|
|
299
|
+
fontSize: "24px",
|
|
300
|
+
fontWeight: "bold",
|
|
301
|
+
userSelect: "none",
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const ORIENTATION_TO_ITEM_DIMENSIONS_MAP: Record<EOrientation, (size: number) => React.CSSProperties> = {
|
|
305
|
+
[EOrientation.HORIZONTAL]: (size) => ({
|
|
306
|
+
width: size,
|
|
307
|
+
height: "100%",
|
|
308
|
+
}),
|
|
309
|
+
[EOrientation.VERTICAL]: (size) => ({
|
|
310
|
+
width: "100%",
|
|
311
|
+
height: size / 2,
|
|
312
|
+
}),
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const ORIENTATION_TO_GAP_MAP: Record<EOrientation, number> = {
|
|
316
|
+
[EOrientation.HORIZONTAL]: 16,
|
|
317
|
+
[EOrientation.VERTICAL]: 8,
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const OrientationItem = ({ orientation }: OrientationItemProps) => {
|
|
321
|
+
const itemSizes = [92, 168, 220, 244, 252, 256, 252, 244, 220, 168, 92];
|
|
322
|
+
const items = itemSizes.map((size, index) => {
|
|
323
|
+
const totalItems = itemSizes.length;
|
|
324
|
+
const hue = (index / (totalItems - 1)) * 280;
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
id: index + 1,
|
|
328
|
+
size,
|
|
329
|
+
backgroundColor: `hsl(${hue}, 50%, 50%)`,
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const containerStyle: React.CSSProperties = {
|
|
334
|
+
maxWidth: "512px",
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
const viewportStyle: React.CSSProperties = {
|
|
338
|
+
height: "256px",
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
return (
|
|
342
|
+
<div style={containerStyle}>
|
|
343
|
+
<div style={{ marginBottom: 8, fontSize: 16, fontWeight: 700 }}>{orientation.toUpperCase()}</div>
|
|
344
|
+
<Carousel orientation={orientation} gap={ORIENTATION_TO_GAP_MAP[orientation]}>
|
|
345
|
+
<Carousel.Viewport style={viewportStyle}>
|
|
346
|
+
<Carousel.Track>
|
|
347
|
+
{items.map((item, index) => {
|
|
348
|
+
const itemStyle: React.CSSProperties = {
|
|
349
|
+
...BASE_ITEM_STYLE,
|
|
350
|
+
...ORIENTATION_TO_ITEM_DIMENSIONS_MAP[orientation](item.size),
|
|
351
|
+
backgroundColor: item.backgroundColor,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
return (
|
|
355
|
+
<Carousel.Item key={item.id} index={index} style={itemStyle}>
|
|
356
|
+
{item.id}
|
|
357
|
+
</Carousel.Item>
|
|
358
|
+
);
|
|
359
|
+
})}
|
|
360
|
+
</Carousel.Track>
|
|
361
|
+
<Carousel.PrevButton aria-label="Previous slide" />
|
|
362
|
+
<Carousel.NextButton aria-label="Next slide" />
|
|
363
|
+
</Carousel.Viewport>
|
|
364
|
+
<Carousel.Indicators />
|
|
365
|
+
</Carousel>
|
|
366
|
+
</div>
|
|
367
|
+
);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const ORIENTATIONS = Object.values(EOrientation);
|
|
371
|
+
|
|
372
|
+
export const Orientations = () => (
|
|
373
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
|
374
|
+
{ORIENTATIONS.map((orientation) => (
|
|
375
|
+
<OrientationItem key={orientation} orientation={orientation} />
|
|
376
|
+
))}
|
|
377
|
+
</div>
|
|
378
|
+
);
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Production
|
|
382
|
+
|
|
383
|
+
`stories/Carousel/examples/Production.tsx`
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
import React, { useState } from "react";
|
|
387
|
+
import {
|
|
388
|
+
Carousel,
|
|
389
|
+
CardAction,
|
|
390
|
+
ECardRoundingSize,
|
|
391
|
+
ECardTheme,
|
|
392
|
+
ECardContentPaddingSize,
|
|
393
|
+
Title,
|
|
394
|
+
ETitleSize,
|
|
395
|
+
EFontWeightTitle,
|
|
396
|
+
Text,
|
|
397
|
+
ETextSize,
|
|
398
|
+
EFontType,
|
|
399
|
+
Gap,
|
|
400
|
+
Link,
|
|
401
|
+
Button,
|
|
402
|
+
EButtonTheme,
|
|
403
|
+
EComponentSize,
|
|
404
|
+
} from "@sberbusiness/triplex-next";
|
|
405
|
+
import { DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
|
|
406
|
+
|
|
407
|
+
const CARDS_IDS = Array.from({ length: 6 }, (_, i) => i);
|
|
408
|
+
|
|
409
|
+
const CardBody = () => (
|
|
410
|
+
<CardAction.Content.Body>
|
|
411
|
+
{[1, 2, 3].map((item) => (
|
|
412
|
+
<div key={item} style={{ display: "flex", alignItems: "center", marginTop: item > 1 ? "16px" : "0" }}>
|
|
413
|
+
<DefaulticonStrokePrdIcon20 paletteIndex={5} />
|
|
414
|
+
<Text size={ETextSize.B3} style={{ marginLeft: "8px" }}>
|
|
415
|
+
List item text
|
|
416
|
+
</Text>
|
|
417
|
+
</div>
|
|
418
|
+
))}
|
|
419
|
+
<Gap size={8} />
|
|
420
|
+
<Text tag="div" type={EFontType.SECONDARY} size={ETextSize.B4}>
|
|
421
|
+
This message provides additional context or highlights important information to note.
|
|
422
|
+
</Text>
|
|
423
|
+
<Gap size={8} />
|
|
424
|
+
<Text tag="div" type={EFontType.PRIMARY} size={ETextSize.B3}>
|
|
425
|
+
<Link onKeyDown={(event) => event.stopPropagation()} onClick={(event) => event.stopPropagation()}>
|
|
426
|
+
Link text
|
|
427
|
+
</Link>
|
|
428
|
+
</Text>
|
|
429
|
+
</CardAction.Content.Body>
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
export const Production = () => {
|
|
433
|
+
const [selectedId, setSelectedId] = useState<number | null>(null);
|
|
434
|
+
|
|
435
|
+
return (
|
|
436
|
+
<div style={{ width: "100%", maxWidth: "752px" }}>
|
|
437
|
+
<Carousel viewportPadding={8}>
|
|
438
|
+
<Carousel.Viewport>
|
|
439
|
+
<Carousel.Track>
|
|
440
|
+
{CARDS_IDS.map((id, index) => {
|
|
441
|
+
const selected = selectedId === id;
|
|
442
|
+
|
|
443
|
+
return (
|
|
444
|
+
<Carousel.Item
|
|
445
|
+
key={id}
|
|
446
|
+
index={index}
|
|
447
|
+
style={{
|
|
448
|
+
width: "216px",
|
|
449
|
+
height: "100%",
|
|
450
|
+
boxSizing: "border-box",
|
|
451
|
+
}}
|
|
452
|
+
>
|
|
453
|
+
<CardAction
|
|
454
|
+
roundingSize={ECardRoundingSize.MD}
|
|
455
|
+
theme={ECardTheme.GENERAL}
|
|
456
|
+
selected={selected}
|
|
457
|
+
toggle={() => setSelectedId(selected ? null : id)}
|
|
458
|
+
>
|
|
459
|
+
<CardAction.Media
|
|
460
|
+
style={{
|
|
461
|
+
backgroundImage: "url(assets/images/evotor.png)",
|
|
462
|
+
height: "129px",
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
<CardAction.Content paddingSize={ECardContentPaddingSize.SM}>
|
|
466
|
+
<CardAction.Content.Header>
|
|
467
|
+
<Title tag="div" size={ETitleSize.H3} weight={EFontWeightTitle.REGULAR}>
|
|
468
|
+
Title Text
|
|
469
|
+
</Title>
|
|
470
|
+
</CardAction.Content.Header>
|
|
471
|
+
|
|
472
|
+
<CardBody />
|
|
473
|
+
|
|
474
|
+
<CardAction.Content.Footer>
|
|
475
|
+
<Button
|
|
476
|
+
theme={
|
|
477
|
+
selected ? EButtonTheme.SECONDARY_LIGHT : EButtonTheme.SECONDARY
|
|
478
|
+
}
|
|
479
|
+
size={EComponentSize.SM}
|
|
480
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
481
|
+
onClick={(event) => event.stopPropagation()}
|
|
482
|
+
>
|
|
483
|
+
Button text
|
|
484
|
+
</Button>
|
|
485
|
+
</CardAction.Content.Footer>
|
|
486
|
+
</CardAction.Content>
|
|
487
|
+
</CardAction>
|
|
488
|
+
</Carousel.Item>
|
|
489
|
+
);
|
|
490
|
+
})}
|
|
491
|
+
</Carousel.Track>
|
|
492
|
+
<Carousel.PrevButton aria-label="Previous slide" />
|
|
493
|
+
<Carousel.NextButton aria-label="Next slide" />
|
|
494
|
+
</Carousel.Viewport>
|
|
495
|
+
</Carousel>
|
|
496
|
+
</div>
|
|
497
|
+
);
|
|
498
|
+
};
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### DynamicIndicators
|
|
502
|
+
|
|
503
|
+
`stories/Carousel/examples/DynamicIndicators.tsx`
|
|
504
|
+
|
|
505
|
+
```tsx
|
|
506
|
+
import React from "react";
|
|
507
|
+
import { Carousel, ECarouselScrollMode } from "@sberbusiness/triplex-next";
|
|
508
|
+
|
|
509
|
+
const BASE_ITEM_STYLE: React.CSSProperties = {
|
|
510
|
+
display: "flex",
|
|
511
|
+
alignItems: "center",
|
|
512
|
+
justifyContent: "center",
|
|
513
|
+
boxSizing: "border-box",
|
|
514
|
+
borderRadius: "8px",
|
|
515
|
+
color: "#ffffff",
|
|
516
|
+
fontSize: "24px",
|
|
517
|
+
fontWeight: "bold",
|
|
518
|
+
userSelect: "none",
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
export const DynamicIndicators = () => {
|
|
522
|
+
const itemSizes = Array.from({ length: 20 }, () => 128);
|
|
523
|
+
|
|
524
|
+
const items = itemSizes.map((size, index) => {
|
|
525
|
+
const totalItems = itemSizes.length;
|
|
526
|
+
const hue = (index / (totalItems - 1)) * 280;
|
|
527
|
+
|
|
528
|
+
return {
|
|
529
|
+
id: index + 1,
|
|
530
|
+
size,
|
|
531
|
+
backgroundColor: `hsl(${hue}, 50%, 50%)`,
|
|
532
|
+
};
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
const boxStyle: React.CSSProperties = {
|
|
536
|
+
display: "flex",
|
|
537
|
+
flexDirection: "column",
|
|
538
|
+
gap: "16px",
|
|
539
|
+
width: "100%",
|
|
540
|
+
maxWidth: "512px",
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
const containerStyle: React.CSSProperties = {
|
|
544
|
+
width: "100%",
|
|
545
|
+
height: "256px",
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
return (
|
|
549
|
+
<div style={boxStyle}>
|
|
550
|
+
<div style={containerStyle}>
|
|
551
|
+
<Carousel scrollMode={ECarouselScrollMode.PAGE}>
|
|
552
|
+
<Carousel.Viewport>
|
|
553
|
+
<Carousel.Track>
|
|
554
|
+
{items.map((item, index) => (
|
|
555
|
+
<Carousel.Item
|
|
556
|
+
key={item.id}
|
|
557
|
+
index={index}
|
|
558
|
+
style={{
|
|
559
|
+
...BASE_ITEM_STYLE,
|
|
560
|
+
width: item.size,
|
|
561
|
+
height: "100%",
|
|
562
|
+
backgroundColor: item.backgroundColor,
|
|
563
|
+
}}
|
|
564
|
+
>
|
|
565
|
+
{item.id}
|
|
566
|
+
</Carousel.Item>
|
|
567
|
+
))}
|
|
568
|
+
</Carousel.Track>
|
|
569
|
+
<Carousel.PrevButton aria-label="Previous slide" />
|
|
570
|
+
<Carousel.NextButton aria-label="Next slide" />
|
|
571
|
+
</Carousel.Viewport>
|
|
572
|
+
<Carousel.Indicators />
|
|
573
|
+
</Carousel>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
);
|
|
577
|
+
};
|
|
578
|
+
```
|
|
579
|
+
|