@cloud-ru/ds-popup-private 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +201 -0
- package/README.md +163 -0
- package/dist/cjs/components/FooterActions/FooterActions.d.ts +44 -0
- package/dist/cjs/components/FooterActions/FooterActions.js +44 -0
- package/dist/cjs/components/FooterActions/index.d.ts +1 -0
- package/dist/cjs/components/FooterActions/index.js +17 -0
- package/dist/cjs/components/FooterActions/styles.module.css +20 -0
- package/dist/cjs/components/PopupBody/PopupBody.d.ts +3 -0
- package/dist/cjs/components/PopupBody/PopupBody.js +15 -0
- package/dist/cjs/components/PopupBody/index.d.ts +1 -0
- package/dist/cjs/components/PopupBody/index.js +17 -0
- package/dist/cjs/components/PopupBody/styles.module.css +16 -0
- package/dist/cjs/components/PopupCloseButton/PopupCloseButton.d.ts +11 -0
- package/dist/cjs/components/PopupCloseButton/PopupCloseButton.js +16 -0
- package/dist/cjs/components/PopupCloseButton/index.d.ts +1 -0
- package/dist/cjs/components/PopupCloseButton/index.js +17 -0
- package/dist/cjs/components/PopupCloseButton/styles.module.css +109 -0
- package/dist/cjs/components/PopupFooter/PopupFooter.d.ts +3 -0
- package/dist/cjs/components/PopupFooter/PopupFooter.js +17 -0
- package/dist/cjs/components/PopupFooter/index.d.ts +1 -0
- package/dist/cjs/components/PopupFooter/index.js +17 -0
- package/dist/cjs/components/PopupFooter/styles.module.css +32 -0
- package/dist/cjs/components/PopupHeader/PopupHeader.d.ts +3 -0
- package/dist/cjs/components/PopupHeader/PopupHeader.js +37 -0
- package/dist/cjs/components/PopupHeader/index.d.ts +1 -0
- package/dist/cjs/components/PopupHeader/index.js +17 -0
- package/dist/cjs/components/PopupHeader/styles.module.css +128 -0
- package/dist/cjs/components/PopupMedia/PopupMedia.d.ts +7 -0
- package/dist/cjs/components/PopupMedia/PopupMedia.js +14 -0
- package/dist/cjs/components/PopupMedia/index.d.ts +1 -0
- package/dist/cjs/components/PopupMedia/index.js +17 -0
- package/dist/cjs/components/PopupMedia/styles.module.css +27 -0
- package/dist/cjs/components/index.d.ts +6 -0
- package/dist/cjs/components/index.js +22 -0
- package/dist/cjs/constants.d.ts +68 -0
- package/dist/cjs/constants.js +73 -0
- package/dist/cjs/context/overlaySurface.d.ts +35 -0
- package/dist/cjs/context/overlaySurface.js +45 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/style.css +332 -0
- package/dist/cjs/types.d.ts +95 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/components/FooterActions/FooterActions.d.ts +44 -0
- package/dist/esm/components/FooterActions/FooterActions.js +38 -0
- package/dist/esm/components/FooterActions/index.d.ts +1 -0
- package/dist/esm/components/FooterActions/index.js +1 -0
- package/dist/esm/components/FooterActions/styles.module.css +20 -0
- package/dist/esm/components/PopupBody/PopupBody.d.ts +3 -0
- package/dist/esm/components/PopupBody/PopupBody.js +9 -0
- package/dist/esm/components/PopupBody/index.d.ts +1 -0
- package/dist/esm/components/PopupBody/index.js +1 -0
- package/dist/esm/components/PopupBody/styles.module.css +16 -0
- package/dist/esm/components/PopupCloseButton/PopupCloseButton.d.ts +11 -0
- package/dist/esm/components/PopupCloseButton/PopupCloseButton.js +10 -0
- package/dist/esm/components/PopupCloseButton/index.d.ts +1 -0
- package/dist/esm/components/PopupCloseButton/index.js +1 -0
- package/dist/esm/components/PopupCloseButton/styles.module.css +109 -0
- package/dist/esm/components/PopupFooter/PopupFooter.d.ts +3 -0
- package/dist/esm/components/PopupFooter/PopupFooter.js +11 -0
- package/dist/esm/components/PopupFooter/index.d.ts +1 -0
- package/dist/esm/components/PopupFooter/index.js +1 -0
- package/dist/esm/components/PopupFooter/styles.module.css +32 -0
- package/dist/esm/components/PopupHeader/PopupHeader.d.ts +3 -0
- package/dist/esm/components/PopupHeader/PopupHeader.js +31 -0
- package/dist/esm/components/PopupHeader/index.d.ts +1 -0
- package/dist/esm/components/PopupHeader/index.js +1 -0
- package/dist/esm/components/PopupHeader/styles.module.css +128 -0
- package/dist/esm/components/PopupMedia/PopupMedia.d.ts +7 -0
- package/dist/esm/components/PopupMedia/PopupMedia.js +8 -0
- package/dist/esm/components/PopupMedia/index.d.ts +1 -0
- package/dist/esm/components/PopupMedia/index.js +1 -0
- package/dist/esm/components/PopupMedia/styles.module.css +27 -0
- package/dist/esm/components/index.d.ts +6 -0
- package/dist/esm/components/index.js +6 -0
- package/dist/esm/constants.d.ts +68 -0
- package/dist/esm/constants.js +70 -0
- package/dist/esm/context/overlaySurface.d.ts +35 -0
- package/dist/esm/context/overlaySurface.js +38 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/style.css +332 -0
- package/dist/esm/types.d.ts +95 -0
- package/dist/esm/types.js +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +46 -0
- package/src/components/FooterActions/FooterActions.tsx +111 -0
- package/src/components/FooterActions/index.ts +1 -0
- package/src/components/FooterActions/styles.module.scss +32 -0
- package/src/components/PopupBody/PopupBody.tsx +20 -0
- package/src/components/PopupBody/index.ts +1 -0
- package/src/components/PopupBody/styles.module.scss +24 -0
- package/src/components/PopupCloseButton/PopupCloseButton.tsx +37 -0
- package/src/components/PopupCloseButton/index.ts +1 -0
- package/src/components/PopupCloseButton/styles.module.scss +39 -0
- package/src/components/PopupFooter/PopupFooter.tsx +24 -0
- package/src/components/PopupFooter/index.ts +1 -0
- package/src/components/PopupFooter/styles.module.scss +49 -0
- package/src/components/PopupHeader/PopupHeader.tsx +125 -0
- package/src/components/PopupHeader/index.ts +1 -0
- package/src/components/PopupHeader/styles.module.scss +158 -0
- package/src/components/PopupMedia/PopupMedia.tsx +18 -0
- package/src/components/PopupMedia/index.ts +1 -0
- package/src/components/PopupMedia/styles.module.scss +33 -0
- package/src/components/index.ts +6 -0
- package/src/constants.ts +72 -0
- package/src/context/overlaySurface.tsx +65 -0
- package/src/index.ts +4 -0
- package/src/types.ts +110 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ValueOf } from '@cloud-ru/ds-utils';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
/** Поверхность overlay'я, в которой рендерятся общие слоты (`Header` / `Body` / `Footer` / `Media`). */
|
|
4
|
+
export declare const OVERLAY_SURFACE: {
|
|
5
|
+
readonly Modal: "modal";
|
|
6
|
+
readonly Drawer: "drawer";
|
|
7
|
+
readonly Sheet: "sheet";
|
|
8
|
+
};
|
|
9
|
+
export type OverlaySurface = ValueOf<typeof OVERLAY_SURFACE>;
|
|
10
|
+
/**
|
|
11
|
+
* Сегмент коллекции `popupPrivate.anatomy.*`, из которого слоты берут токены раскладки.
|
|
12
|
+
* Modal и Drawer(desktop) рисуются мастером `window`; Sheet — `bottomSheet`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SURFACE_TOKEN_SEGMENT: {
|
|
15
|
+
readonly modal: "window";
|
|
16
|
+
readonly drawer: "window";
|
|
17
|
+
readonly sheet: "bottomSheet";
|
|
18
|
+
};
|
|
19
|
+
export type SurfaceTokenSegment = ValueOf<typeof SURFACE_TOKEN_SEGMENT>;
|
|
20
|
+
type OverlaySurfaceProviderProps = {
|
|
21
|
+
/** Поверхность, в которой рендерятся дочерние слоты. */
|
|
22
|
+
surface: OverlaySurface;
|
|
23
|
+
/** Только drawer: высота панели по контенту → `Body` (drawer-ветка) добавляет соответствующий класс. */
|
|
24
|
+
bodyHeightAuto?: boolean;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
};
|
|
27
|
+
/** Провайдер поверхности overlay'я. Frame (sheet / modal / drawer) оборачивает в него свои слоты. */
|
|
28
|
+
export declare function OverlaySurfaceProvider({ surface, bodyHeightAuto, children }: OverlaySurfaceProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
/** Текущая поверхность overlay'я. Без провайдера возвращает `'sheet'`. */
|
|
30
|
+
export declare function useOverlaySurface(): OverlaySurface;
|
|
31
|
+
/** Только drawer-ветка `Body`: высота панели по контенту (из `DrawerFrame`). */
|
|
32
|
+
export declare function useOverlayBodyHeightAuto(): boolean;
|
|
33
|
+
/** Токен-сегмент текущей поверхности (`window` / `bottomSheet`). Без провайдера — `bottomSheet`. */
|
|
34
|
+
export declare function useSurfaceTokenSegment(): SurfaceTokenSegment;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SURFACE_TOKEN_SEGMENT = exports.OVERLAY_SURFACE = void 0;
|
|
4
|
+
exports.OverlaySurfaceProvider = OverlaySurfaceProvider;
|
|
5
|
+
exports.useOverlaySurface = useOverlaySurface;
|
|
6
|
+
exports.useOverlayBodyHeightAuto = useOverlayBodyHeightAuto;
|
|
7
|
+
exports.useSurfaceTokenSegment = useSurfaceTokenSegment;
|
|
8
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
/** Поверхность overlay'я, в которой рендерятся общие слоты (`Header` / `Body` / `Footer` / `Media`). */
|
|
11
|
+
exports.OVERLAY_SURFACE = {
|
|
12
|
+
Modal: 'modal',
|
|
13
|
+
Drawer: 'drawer',
|
|
14
|
+
Sheet: 'sheet',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Сегмент коллекции `popupPrivate.anatomy.*`, из которого слоты берут токены раскладки.
|
|
18
|
+
* Modal и Drawer(desktop) рисуются мастером `window`; Sheet — `bottomSheet`.
|
|
19
|
+
*/
|
|
20
|
+
exports.SURFACE_TOKEN_SEGMENT = {
|
|
21
|
+
[exports.OVERLAY_SURFACE.Modal]: 'window',
|
|
22
|
+
[exports.OVERLAY_SURFACE.Drawer]: 'window',
|
|
23
|
+
[exports.OVERLAY_SURFACE.Sheet]: 'bottomSheet',
|
|
24
|
+
};
|
|
25
|
+
// Дефолт `'sheet'`: слоты без провайдера ведут себя как bottom-sheet.
|
|
26
|
+
const OverlaySurfaceContext = (0, react_1.createContext)({
|
|
27
|
+
surface: exports.OVERLAY_SURFACE.Sheet,
|
|
28
|
+
bodyHeightAuto: false,
|
|
29
|
+
});
|
|
30
|
+
/** Провайдер поверхности overlay'я. Frame (sheet / modal / drawer) оборачивает в него свои слоты. */
|
|
31
|
+
function OverlaySurfaceProvider({ surface, bodyHeightAuto = false, children }) {
|
|
32
|
+
return ((0, jsx_runtime_1.jsx)(OverlaySurfaceContext.Provider, { value: { surface, bodyHeightAuto }, children: children }));
|
|
33
|
+
}
|
|
34
|
+
/** Текущая поверхность overlay'я. Без провайдера возвращает `'sheet'`. */
|
|
35
|
+
function useOverlaySurface() {
|
|
36
|
+
return (0, react_1.useContext)(OverlaySurfaceContext).surface;
|
|
37
|
+
}
|
|
38
|
+
/** Только drawer-ветка `Body`: высота панели по контенту (из `DrawerFrame`). */
|
|
39
|
+
function useOverlayBodyHeightAuto() {
|
|
40
|
+
return (0, react_1.useContext)(OverlaySurfaceContext).bodyHeightAuto;
|
|
41
|
+
}
|
|
42
|
+
/** Токен-сегмент текущей поверхности (`window` / `bottomSheet`). Без провайдера — `bottomSheet`. */
|
|
43
|
+
function useSurfaceTokenSegment() {
|
|
44
|
+
return exports.SURFACE_TOKEN_SEGMENT[useOverlaySurface()];
|
|
45
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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("./components"), exports);
|
|
18
|
+
__exportStar(require("./constants"), exports);
|
|
19
|
+
__exportStar(require("./context/overlaySurface"), exports);
|
|
20
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
.actions{
|
|
2
|
+
width:100%;
|
|
3
|
+
}
|
|
4
|
+
.actions > *{
|
|
5
|
+
max-width:100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.single{
|
|
9
|
+
justify-content:flex-end;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.compact{
|
|
13
|
+
align-self:flex-end;
|
|
14
|
+
justify-content:flex-end;
|
|
15
|
+
width:auto;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.actions.stackInverted{
|
|
19
|
+
flex-direction:column;
|
|
20
|
+
}
|
|
21
|
+
.root{
|
|
22
|
+
touch-action:pan-y;
|
|
23
|
+
overflow-y:auto;
|
|
24
|
+
overscroll-behavior:contain;
|
|
25
|
+
flex:1 1 auto;
|
|
26
|
+
box-sizing:border-box;
|
|
27
|
+
min-height:0;
|
|
28
|
+
padding:var(--sn-bottomSheet-anatomy-container-content-bodyWrapper-paddingTop, var(--sn-density-spacing-interval-m, var(--sn-primitive-dimension-16, 16px))) var(--sn-bottomSheet-anatomy-container-content-bodyWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px))) var(--sn-bottomSheet-anatomy-container-content-bodyWrapper-paddingBottom, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px))) var(--sn-bottomSheet-anatomy-container-content-bodyWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
29
|
+
color:var(--sn-theme-color-neutral-text, var(--sn-brand-color-neutral-45, var(--sn-primitive-color-gray-45, #81869c)));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.root[data-no-padding]{
|
|
33
|
+
padding-top:0;
|
|
34
|
+
padding-right:0;
|
|
35
|
+
padding-left:0;
|
|
36
|
+
}
|
|
37
|
+
@charset "UTF-8";
|
|
38
|
+
.stateLayer{
|
|
39
|
+
visibility:initial;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.root{
|
|
43
|
+
cursor:pointer;
|
|
44
|
+
position:relative;
|
|
45
|
+
display:flex;
|
|
46
|
+
align-items:center;
|
|
47
|
+
justify-content:center;
|
|
48
|
+
box-sizing:border-box;
|
|
49
|
+
margin:var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-paddingTop, var(--sn-brand-anatomy-spacing-window-badgeButtonClosed-paddingTop, var(--sn-primitive-dimension-48, 48px))) var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-paddingRight, var(--sn-brand-anatomy-spacing-window-badgeButtonClosed-paddingRight, var(--sn-primitive-dimension-48, 48px))) var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-paddingBottom, var(--sn-brand-anatomy-spacing-window-badgeButtonClosed-paddingBottom, var(--sn-primitive-dimension-0, 0px))) var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-paddingLeft, var(--sn-brand-anatomy-spacing-window-badgeButtonClosed-paddingLeft, var(--sn-primitive-dimension-0, 0px)));
|
|
50
|
+
padding:0;
|
|
51
|
+
border:0 solid transparent;
|
|
52
|
+
color:var(--sn-theme-color-neutral-text, var(--sn-brand-color-neutral-45, var(--sn-primitive-color-gray-45, #81869c)));
|
|
53
|
+
background:transparent;
|
|
54
|
+
outline:0;
|
|
55
|
+
min-width:var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-buttonClosed-minWidth, var(--sn-primitive-dimension-32, 32px));
|
|
56
|
+
min-height:var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-buttonClosed-minHeight, var(--sn-primitive-dimension-32, 32px));
|
|
57
|
+
border-radius:var(--sn-popupPrivate-anatomy-window-badgeButtonClosed-buttonClosed-borderRadius, var(--sn-brand-anatomy-radius-window-buttonClosed-m, var(--sn-primitive-dimension-full, 10000px)));
|
|
58
|
+
}
|
|
59
|
+
.root .stateLayer{
|
|
60
|
+
position:absolute;
|
|
61
|
+
inset:0;
|
|
62
|
+
border-radius:inherit;
|
|
63
|
+
}
|
|
64
|
+
.root .stateLayer[data-state=borderOnBackground]{
|
|
65
|
+
border-color:var(--sn-theme-color-material-stateLayer-neutral-border-default-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843)));
|
|
66
|
+
border-style:solid;
|
|
67
|
+
border-width:var(--sn-primitive-strokeWeight-strokeRegular, 1px);
|
|
68
|
+
}
|
|
69
|
+
.root .stateLayer[data-state=emptyNeutralOnBackground]{
|
|
70
|
+
background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-defaultEmpty-filled, var(--sn-brand-color-state-neutral-forLightMode-default-background, rgba(120, 123, 138, 0)));
|
|
71
|
+
}
|
|
72
|
+
.root .stateLayer[data-state=activatedOnBackground]{
|
|
73
|
+
background:var(--sn-theme-color-material-stateLayer-activated-default-filled, var(--sn-brand-color-state-activated-default-background, var(--sn-brandRole-color-brandA-backgroundActivatedDefault, rgba(56, 159, 116, 0.1490196078))));
|
|
74
|
+
}
|
|
75
|
+
.root .stateLayer[data-state=versionOnColor]{
|
|
76
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-default-filled, rgba(0, 0, 0, 0.0509803922));
|
|
77
|
+
}
|
|
78
|
+
.root .stateLayer[data-state=emptyVersionOnColor]{
|
|
79
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-defaultEmpty-filled, rgba(0, 0, 0, 0));
|
|
80
|
+
}
|
|
81
|
+
.root .stateLayer[data-state=inversionOnColor]{
|
|
82
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-default-filled, rgba(255, 255, 255, 0.1019607843));
|
|
83
|
+
}
|
|
84
|
+
.root .stateLayer[data-state=emptyInversionOnColor]{
|
|
85
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-defaultEmpty-filled, rgba(255, 255, 255, 0));
|
|
86
|
+
}
|
|
87
|
+
.root .stateLayer[data-state=emptyDarkOnAccent]{
|
|
88
|
+
background:var(--sn-theme-color-material-stateLayer-darkOnAccent-defaultEmpty-filled, rgba(0, 0, 0, 0));
|
|
89
|
+
}
|
|
90
|
+
@media (hover: hover){
|
|
91
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=borderOnBackground]{
|
|
92
|
+
border-color:var(--sn-theme-color-material-stateLayer-neutral-border-hovered-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-hovered-borderColor, rgba(159, 166, 198, 0.6509803922)));
|
|
93
|
+
}
|
|
94
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyNeutralOnBackground]{
|
|
95
|
+
background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-hovered-filled, var(--sn-brand-color-state-neutral-forLightMode-hovered-background, rgba(188, 195, 220, 0.1490196078)));
|
|
96
|
+
}
|
|
97
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=activatedOnBackground]{
|
|
98
|
+
background:var(--sn-theme-color-material-stateLayer-activated-hovered-filled, var(--sn-brand-color-state-activated-hovered-background, var(--sn-brandRole-color-brandA-backgroundActivatedHovered, rgba(56, 159, 116, 0.3490196078))));
|
|
99
|
+
}
|
|
100
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=versionOnColor]{
|
|
101
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-hovered-filled, rgba(0, 0, 0, 0.1019607843));
|
|
102
|
+
}
|
|
103
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyVersionOnColor]{
|
|
104
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-hovered-filled, rgba(0, 0, 0, 0.1019607843));
|
|
105
|
+
}
|
|
106
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=inversionOnColor]{
|
|
107
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-hovered-filled, rgba(255, 255, 255, 0.1490196078));
|
|
108
|
+
}
|
|
109
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyInversionOnColor]{
|
|
110
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-hovered-filled, rgba(255, 255, 255, 0.1490196078));
|
|
111
|
+
}
|
|
112
|
+
.root:hover:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyDarkOnAccent]{
|
|
113
|
+
background:var(--sn-theme-color-material-stateLayer-darkOnAccent-hovered-filled, rgba(0, 0, 0, 0.0588235294));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
.root{
|
|
117
|
+
}
|
|
118
|
+
.root[data-loading] .stateLayer[data-state=borderOnBackground], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=borderOnBackground], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=borderOnBackground]{
|
|
119
|
+
border-color:var(--sn-theme-color-material-stateLayer-neutral-border-pressed-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-pressed-borderColor, rgba(159, 166, 198, 0.8)));
|
|
120
|
+
}
|
|
121
|
+
.root[data-loading] .stateLayer[data-state=emptyNeutralOnBackground], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyNeutralOnBackground], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyNeutralOnBackground]{
|
|
122
|
+
background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-pressed-filled, var(--sn-brand-color-state-neutral-forLightMode-pressed-background, rgba(188, 195, 220, 0.3019607843)));
|
|
123
|
+
}
|
|
124
|
+
.root[data-loading] .stateLayer[data-state=activatedOnBackground], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=activatedOnBackground], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=activatedOnBackground]{
|
|
125
|
+
background:var(--sn-theme-color-material-stateLayer-activated-pressed-filled, var(--sn-brand-color-state-activated-pressed-background, var(--sn-brandRole-color-brandA-backgroundActivatedPressed, rgba(56, 159, 116, 0.4509803922))));
|
|
126
|
+
}
|
|
127
|
+
.root[data-loading] .stateLayer[data-state=versionOnColor], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=versionOnColor], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=versionOnColor]{
|
|
128
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-pressed-filled, rgba(0, 0, 0, 0.1490196078));
|
|
129
|
+
}
|
|
130
|
+
.root[data-loading] .stateLayer[data-state=emptyVersionOnColor], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyVersionOnColor], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyVersionOnColor]{
|
|
131
|
+
background:var(--sn-theme-color-material-stateLayer-versionOnColor-pressed-filled, rgba(0, 0, 0, 0.1490196078));
|
|
132
|
+
}
|
|
133
|
+
.root[data-loading] .stateLayer[data-state=inversionOnColor], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=inversionOnColor], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=inversionOnColor]{
|
|
134
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-pressed-filled, rgba(255, 255, 255, 0.0509803922));
|
|
135
|
+
}
|
|
136
|
+
.root[data-loading] .stateLayer[data-state=emptyInversionOnColor], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyInversionOnColor], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyInversionOnColor]{
|
|
137
|
+
background:var(--sn-theme-color-material-stateLayer-inversionOnColor-pressed-filled, rgba(255, 255, 255, 0.0509803922));
|
|
138
|
+
}
|
|
139
|
+
.root[data-loading] .stateLayer[data-state=emptyDarkOnAccent], .root:active:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyDarkOnAccent], .root[data-pressed=true]:not([data-disabled], [data-loading]) .stateLayer[data-state=emptyDarkOnAccent]{
|
|
140
|
+
background:var(--sn-theme-color-material-stateLayer-darkOnAccent-pressed-filled, rgba(0, 0, 0, 0.1215686275));
|
|
141
|
+
}
|
|
142
|
+
.root:focus-visible{
|
|
143
|
+
outline:var(--sn-theme-color-available-complementary, #000000) solid var(--sn-primitive-strokeWeight-strokeSemiBold, 2px);
|
|
144
|
+
outline-offset:var(--sn-primitive-strokeWeight-strokeSemiBold, 2px);
|
|
145
|
+
}
|
|
146
|
+
.root{
|
|
147
|
+
display:flex;
|
|
148
|
+
flex-shrink:0;
|
|
149
|
+
box-sizing:border-box;
|
|
150
|
+
}
|
|
151
|
+
.root[data-surface=bottomSheet]{
|
|
152
|
+
touch-action:none;
|
|
153
|
+
flex-direction:column;
|
|
154
|
+
align-items:stretch;
|
|
155
|
+
justify-content:center;
|
|
156
|
+
padding:var(--sn-popupPrivate-anatomy-bottomSheet-footer-paddingTop, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px))) var(--sn-popupPrivate-anatomy-bottomSheet-footer-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px))) var(--sn-popupPrivate-anatomy-bottomSheet-footer-paddingBottom, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px))) var(--sn-popupPrivate-anatomy-bottomSheet-footer-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
157
|
+
}
|
|
158
|
+
.root[data-surface=window]{
|
|
159
|
+
align-items:center;
|
|
160
|
+
align-self:stretch;
|
|
161
|
+
padding-left:var(--sn-popupPrivate-anatomy-window-footer-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
162
|
+
padding-right:var(--sn-popupPrivate-anatomy-window-footer-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
163
|
+
padding-bottom:var(--sn-popupPrivate-anatomy-window-footer-paddingBottom, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.contentWrapper{
|
|
167
|
+
display:flex;
|
|
168
|
+
flex-direction:column;
|
|
169
|
+
}
|
|
170
|
+
[data-surface=bottomSheet] .contentWrapper{
|
|
171
|
+
gap:var(--sn-density-spacing-interval-m, var(--sn-primitive-dimension-16, 16px));
|
|
172
|
+
}
|
|
173
|
+
[data-surface=window] .contentWrapper{
|
|
174
|
+
flex:1 0 0;
|
|
175
|
+
align-items:flex-start;
|
|
176
|
+
justify-content:center;
|
|
177
|
+
}
|
|
178
|
+
.root{
|
|
179
|
+
display:flex;
|
|
180
|
+
flex-direction:column;
|
|
181
|
+
flex-shrink:0;
|
|
182
|
+
box-sizing:border-box;
|
|
183
|
+
}
|
|
184
|
+
.root[data-surface=bottomSheet]{
|
|
185
|
+
gap:var(--sn-popupPrivate-anatomy-bottomSheet-header-gap, var(--sn-density-spacing-interval-xs, var(--sn-primitive-dimension-4, 4px)));
|
|
186
|
+
padding-top:var(--sn-popupPrivate-anatomy-bottomSheet-header-paddingTop, var(--sn-density-spacing-interval-m, var(--sn-primitive-dimension-16, 16px)));
|
|
187
|
+
padding-bottom:var(--sn-popupPrivate-anatomy-bottomSheet-header-paddingBottom, var(--sn-density-spacing-interval-m, var(--sn-primitive-dimension-16, 16px)));
|
|
188
|
+
}
|
|
189
|
+
.root[data-surface=window]{
|
|
190
|
+
align-items:flex-start;
|
|
191
|
+
align-self:stretch;
|
|
192
|
+
justify-content:center;
|
|
193
|
+
gap:var(--sn-popupPrivate-anatomy-window-header-gap, var(--sn-density-spacing-interval-xs, var(--sn-primitive-dimension-4, 4px)));
|
|
194
|
+
padding-bottom:var(--sn-popupPrivate-anatomy-window-header-paddingBottom, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
195
|
+
}
|
|
196
|
+
.root[data-surface=window]:not([data-with-before]){
|
|
197
|
+
gap:0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.headlineWrapper{
|
|
201
|
+
display:flex;
|
|
202
|
+
align-items:center;
|
|
203
|
+
}
|
|
204
|
+
[data-surface=bottomSheet] .headlineWrapper{
|
|
205
|
+
touch-action:none;
|
|
206
|
+
gap:0;
|
|
207
|
+
}
|
|
208
|
+
[data-surface=bottomSheet] .headlineWrapper[data-with-before], [data-surface=bottomSheet] .headlineWrapper[data-with-after]{
|
|
209
|
+
gap:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
210
|
+
}
|
|
211
|
+
[data-surface=bottomSheet] .headlineWrapper[data-with-before]{
|
|
212
|
+
padding-left:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-paddingLeft, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
213
|
+
}
|
|
214
|
+
[data-surface=bottomSheet] .headlineWrapper[data-with-after]{
|
|
215
|
+
padding-right:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-paddingRight, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
216
|
+
}
|
|
217
|
+
[data-surface=window] .headlineWrapper{
|
|
218
|
+
align-self:stretch;
|
|
219
|
+
gap:var(--sn-popupPrivate-anatomy-window-header-headline-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
220
|
+
height:var(--sn-popupPrivate-anatomy-window-header-headline-height, var(--sn-density-size-m, var(--sn-primitive-dimension-56, 56px)));
|
|
221
|
+
padding-left:var(--sn-popupPrivate-anatomy-window-header-headline-paddingHorizontal, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
222
|
+
padding-right:var(--sn-popupPrivate-anatomy-window-header-headline-paddingHorizontal, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
223
|
+
padding-right:0;
|
|
224
|
+
}
|
|
225
|
+
[data-surface=window] .headlineWrapper:not([data-with-before]){
|
|
226
|
+
padding-left:0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.headline{
|
|
230
|
+
display:flex;
|
|
231
|
+
align-items:center;
|
|
232
|
+
box-sizing:border-box;
|
|
233
|
+
min-width:0;
|
|
234
|
+
}
|
|
235
|
+
[data-surface=bottomSheet] .headline{
|
|
236
|
+
flex:1 1 auto;
|
|
237
|
+
gap:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
238
|
+
padding-top:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-paddingVertical, var(--sn-primitive-dimension-10, 10px));
|
|
239
|
+
padding-bottom:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-paddingVertical, var(--sn-primitive-dimension-10, 10px));
|
|
240
|
+
}
|
|
241
|
+
[data-surface=window] .headline{
|
|
242
|
+
flex:1 0 0;
|
|
243
|
+
gap:var(--sn-popupPrivate-anatomy-window-header-headline-headlineWrapper-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px)));
|
|
244
|
+
padding-left:var(--sn-popupPrivate-anatomy-window-header-headline-headlineWrapper-paddingLeft, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
245
|
+
padding-right:var(--sn-popupPrivate-anatomy-window-header-headline-headlineWrapper-paddingRight, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
[data-surface=bottomSheet] .headlineWrapper:not([data-with-before]) .headline{
|
|
249
|
+
padding-left:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-paddingLeft, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
[data-surface=bottomSheet] .headlineWrapper:not([data-with-after]) .headline{
|
|
253
|
+
padding-right:var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-paddingRight, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
[data-surface=window] .headlineWrapper[data-with-before] .headline{
|
|
257
|
+
padding-left:0;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.title{
|
|
261
|
+
flex:0 1 auto;
|
|
262
|
+
min-width:0;
|
|
263
|
+
color:var(--sn-theme-color-available-version-textMain, var(--sn-brand-color-text-version-main, #41424e));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.slotAfterTitle{
|
|
267
|
+
display:inline-flex;
|
|
268
|
+
flex:1 1 auto;
|
|
269
|
+
align-items:center;
|
|
270
|
+
min-width:0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.actionButton{
|
|
274
|
+
display:inline-flex;
|
|
275
|
+
flex-shrink:0;
|
|
276
|
+
align-items:center;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.subtitleWrapper{
|
|
280
|
+
display:flex;
|
|
281
|
+
flex-direction:column;
|
|
282
|
+
align-items:flex-start;
|
|
283
|
+
box-sizing:border-box;
|
|
284
|
+
}
|
|
285
|
+
[data-surface=bottomSheet] .subtitleWrapper{
|
|
286
|
+
padding-right:var(--sn-popupPrivate-anatomy-bottomSheet-header-subHeadlineWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
287
|
+
padding-left:var(--sn-popupPrivate-anatomy-bottomSheet-header-subHeadlineWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
288
|
+
}
|
|
289
|
+
[data-surface=window] .subtitleWrapper{
|
|
290
|
+
align-self:stretch;
|
|
291
|
+
padding-left:var(--sn-popupPrivate-anatomy-window-header-subHeadlineWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
292
|
+
padding-right:var(--sn-popupPrivate-anatomy-window-header-subHeadlineWrapper-paddingHorizontal, var(--sn-density-spacing-interval-l, var(--sn-primitive-dimension-24, 24px)));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.subtitle{
|
|
296
|
+
color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.secondWrapper{
|
|
300
|
+
box-sizing:border-box;
|
|
301
|
+
}
|
|
302
|
+
[data-surface=bottomSheet] .secondWrapper{
|
|
303
|
+
padding-left:var(--sn-popupPrivate-anatomy-bottomSheet-header-secondWrapper-paddingHorizontal, var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px))));
|
|
304
|
+
padding-right:var(--sn-popupPrivate-anatomy-bottomSheet-header-secondWrapper-paddingHorizontal, var(--sn-popupPrivate-anatomy-bottomSheet-header-headline-headlineWrapper-gap, var(--sn-density-spacing-interval-s, var(--sn-primitive-dimension-8, 8px))));
|
|
305
|
+
}
|
|
306
|
+
.wrapper{
|
|
307
|
+
touch-action:none;
|
|
308
|
+
overflow:hidden;
|
|
309
|
+
display:flex;
|
|
310
|
+
flex-shrink:0;
|
|
311
|
+
align-items:center;
|
|
312
|
+
justify-content:center;
|
|
313
|
+
box-sizing:border-box;
|
|
314
|
+
width:100%;
|
|
315
|
+
}
|
|
316
|
+
.wrapper[data-media-kind=icon]{
|
|
317
|
+
padding-top:var(--sn-popupPrivate-anatomy-window-media-icon-paddingTop, var(--sn-primitive-dimension-32, 32px));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.image{
|
|
321
|
+
display:block;
|
|
322
|
+
width:100%;
|
|
323
|
+
min-height:184px;
|
|
324
|
+
-o-object-fit:cover;
|
|
325
|
+
object-fit:cover;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.icon{
|
|
329
|
+
display:block;
|
|
330
|
+
max-width:100%;
|
|
331
|
+
height:auto;
|
|
332
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ButtonProps } from '@cloud-ru/ds-button';
|
|
2
|
+
import { ValueOf, WithSupportProps } from '@cloud-ru/ds-utils';
|
|
3
|
+
import { PropsWithChildren, ReactNode } from 'react';
|
|
4
|
+
import { FOOTER_ACTIONS_ORIENTATION, MEDIA_KIND } from './constants';
|
|
5
|
+
/**
|
|
6
|
+
* Пропсы action-кнопки футера — объект пропсов `Button` из `@cloud-ru/ds-button`. `view` / `appearance` имеют
|
|
7
|
+
* дефолты по слоту (переопределяемы); `size` (m) и full-width задаёт `ButtonGroup`, поэтому исключены.
|
|
8
|
+
* `data-test-id` слота фиксирует `TEST_IDS` (через `WithSupportProps` у `ButtonGroup`).
|
|
9
|
+
*
|
|
10
|
+
* По умолчанию рендерится как `<button>`. Для CTA-ссылки передайте `as='a'` + `href` (`Button`
|
|
11
|
+
* полиморфен и отрендерит `<a>` — доступен middle-click / контекстное меню). Union `button | anchor`
|
|
12
|
+
* ниже раскрывает анкорные атрибуты. Для нестандартного футера остаётся `footer: ReactNode`.
|
|
13
|
+
*/
|
|
14
|
+
export type BottomSheetActionButton = Omit<ButtonProps<'button'>, 'fullWidth' | 'size'> | Omit<ButtonProps<'a'>, 'fullWidth' | 'size'>;
|
|
15
|
+
export type MediaKind = ValueOf<typeof MEDIA_KIND>;
|
|
16
|
+
export type FooterActionsOrientation = ValueOf<typeof FOOTER_ACTIONS_ORIENTATION>;
|
|
17
|
+
export type PopupMediaProps = {
|
|
18
|
+
/** URL изображения / иконки. */
|
|
19
|
+
src: string;
|
|
20
|
+
/** Альтернативный текст (a11y). */
|
|
21
|
+
alt: string;
|
|
22
|
+
/**
|
|
23
|
+
* Режим:
|
|
24
|
+
* - `'image'` — изображение во всю ширину (высота `184px`), прижато к шапке (убирается
|
|
25
|
+
* верхний отступ контент-блока). Горизонтальные паддинги body не затрагивает — для edge-to-edge body
|
|
26
|
+
* используйте `bodyPadding={false}` отдельно.
|
|
27
|
+
* - `'icon'` — иконка с `padding-top: 24px`.
|
|
28
|
+
* @default 'image'
|
|
29
|
+
*/
|
|
30
|
+
kind?: MediaKind;
|
|
31
|
+
};
|
|
32
|
+
export type PopupHeaderProps = WithSupportProps<{
|
|
33
|
+
/** Заголовок. Типографика зависит от поверхности: `title-l` на sheet, `headline-s` на window (modal/drawer). */
|
|
34
|
+
title?: ReactNode;
|
|
35
|
+
/** `id` заголовка — для связи с `aria-labelledby` dialog'а (accessible name). */
|
|
36
|
+
titleId?: string;
|
|
37
|
+
/** Slot справа от title (например, `QuestionTooltip` из `@cloud-ru/ds-tooltip`). */
|
|
38
|
+
slotAfterTitle?: ReactNode;
|
|
39
|
+
/** Текстовая строка-подзаголовок под title (Figma `subtitleWrapper`). Рендерится на всех поверхностях. */
|
|
40
|
+
subtitle?: ReactNode;
|
|
41
|
+
/**
|
|
42
|
+
* Slot под подзаголовком (Figma `secondWrapper`) — типично `SearchBar`, `SegmentControl` или `Filter`.
|
|
43
|
+
* Есть только в мастере `bottomSheet`, поэтому рендерится **только** на sheet-поверхности.
|
|
44
|
+
*/
|
|
45
|
+
slotSecondTitle?: ReactNode;
|
|
46
|
+
/**
|
|
47
|
+
* Callback клика на back-кнопку (слева в шапке).
|
|
48
|
+
* Наличие callback'а авто-рендерит `Button view='function' icon={<ArrowLeftSVG />}`.
|
|
49
|
+
*/
|
|
50
|
+
onBackButtonClick?(): void;
|
|
51
|
+
/** Slot справа от headline-строки (любой `ReactNode`, обычно `Button` с иконкой). */
|
|
52
|
+
actionButton?: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* Усечение строковых `title`/`subtitle` через `TruncateString` (число строк). Применяется только
|
|
55
|
+
* когда задано — по умолчанию текст не усекается. Актуально для window-поверхности (modal/drawer),
|
|
56
|
+
* где длинный заголовок иначе переносится на несколько строк.
|
|
57
|
+
*/
|
|
58
|
+
truncate?: {
|
|
59
|
+
title?: number;
|
|
60
|
+
subtitle?: number;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Переопределение `data-test-id` слотов шапки. Каждый пропущенный ключ берётся из `TEST_IDS`.
|
|
64
|
+
* Потребитель-обёртка (drawer/modal) прокидывает сюда свои id, чтобы сохранить публичный контракт.
|
|
65
|
+
*/
|
|
66
|
+
testIds?: PopupHeaderTestIds;
|
|
67
|
+
/** CSS-класс контейнера header'а. */
|
|
68
|
+
className?: string;
|
|
69
|
+
}>;
|
|
70
|
+
/** `data-test-id` слотов `PopupHeader` — для переопределения потребителем. */
|
|
71
|
+
export type PopupHeaderTestIds = {
|
|
72
|
+
header?: string;
|
|
73
|
+
title?: string;
|
|
74
|
+
slotAfterTitle?: string;
|
|
75
|
+
subtitle?: string;
|
|
76
|
+
slotSecondTitle?: string;
|
|
77
|
+
backButton?: string;
|
|
78
|
+
actionButton?: string;
|
|
79
|
+
};
|
|
80
|
+
export type PopupBodyProps = WithSupportProps<PropsWithChildren<{
|
|
81
|
+
/** Содержимое body (альтернатива `children`). */
|
|
82
|
+
content?: ReactNode;
|
|
83
|
+
/**
|
|
84
|
+
* Горизонтальные паддинги body. При `false` контент идёт во всю ширину sheet'а (edge-to-edge) —
|
|
85
|
+
* для карт, изображений, списков без отступов. Соответствует Figma-оси `padding=false`.
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
bodyPadding?: boolean;
|
|
89
|
+
/** CSS-класс контейнера body. */
|
|
90
|
+
className?: string;
|
|
91
|
+
}>>;
|
|
92
|
+
export type PopupFooterProps = WithSupportProps<PropsWithChildren<{
|
|
93
|
+
/** CSS-класс контейнера footer'а. */
|
|
94
|
+
className?: string;
|
|
95
|
+
}>>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Size } from '@cloud-ru/ds-button';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { SurfaceTokenSegment } from '../../context/overlaySurface.js';
|
|
4
|
+
import { BottomSheetActionButton, FooterActionsOrientation } from '../../types.js';
|
|
5
|
+
/** Идентификаторы слотов кнопок футера. */
|
|
6
|
+
export type FooterActionsTestIds = {
|
|
7
|
+
approve: string;
|
|
8
|
+
cancel: string;
|
|
9
|
+
additional: string;
|
|
10
|
+
};
|
|
11
|
+
export type FooterActionsProps = {
|
|
12
|
+
/** Основная кнопка (по умолчанию `view='filled'`, `appearance='primary'`). */
|
|
13
|
+
approveButton?: BottomSheetActionButton;
|
|
14
|
+
/** Кнопка отмены (по умолчанию `view='outline'`, `appearance='neutral'`). */
|
|
15
|
+
cancelButton?: BottomSheetActionButton;
|
|
16
|
+
/** Дополнительная (третья) кнопка (по умолчанию `view='simple'`, `appearance='neutral'`). */
|
|
17
|
+
additionalButton?: BottomSheetActionButton;
|
|
18
|
+
/**
|
|
19
|
+
* Размер кнопок футера. Задаётся на уровне группы (как в `ButtonGroup`), не по кнопке —
|
|
20
|
+
* в макетах все действия футера одного размера. Нужен потребителям с собственной осью
|
|
21
|
+
* размера (календарные дропдауны: 24 / 32 / 40 при s / m / l). У modal, drawer и
|
|
22
|
+
* bottom-sheet своей оси нет, но кит рисует их футеры на `l` — эти поверхности
|
|
23
|
+
* передают `size='l'` явно.
|
|
24
|
+
*/
|
|
25
|
+
size?: Size;
|
|
26
|
+
/** Ориентация кнопок при ровно двух действиях. */
|
|
27
|
+
footerActionsOrientation?: FooterActionsOrientation;
|
|
28
|
+
/** Идентификаторы слотов конкретного компонента (`bottom-sheet` / `modal` / `drawer`). */
|
|
29
|
+
testIds: FooterActionsTestIds;
|
|
30
|
+
/** Доп. CSS-класс на `ButtonGroup` (поверх встроенной раскладки по числу действий). */
|
|
31
|
+
actionsClassName?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Поверхность overlay'я — определяет раскладку кнопок:
|
|
34
|
+
* - `window` (desktop, дефолт): 1–2 кнопки компактно вправо, 3 — стопка (primary сверху).
|
|
35
|
+
* - `bottomSheet` (mobile): 1 → вправо, 2 → space-between, 3 → стопка с инверсией (primary внизу).
|
|
36
|
+
*/
|
|
37
|
+
surface?: SurfaceTokenSegment;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Группа кнопок футера (approve / cancel / additional) с раскладкой по поверхности и числу действий.
|
|
41
|
+
* Единый источник правды для `BottomSheet`, `Modal` и `Drawer` (adaptive-маппинг 1:1).
|
|
42
|
+
* Возвращает `null`, если ни одной кнопки не передано.
|
|
43
|
+
*/
|
|
44
|
+
export declare function FooterActions({ approveButton, cancelButton, additionalButton, size, footerActionsOrientation, testIds, actionsClassName, surface, }: FooterActionsProps): ReactNode;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { APPEARANCE, ButtonGroup, VIEW } from '@cloud-ru/ds-button';
|
|
3
|
+
import cn from 'classnames';
|
|
4
|
+
import { FOOTER_ACTIONS_ORIENTATION } from '../../constants.js';
|
|
5
|
+
import styles from './styles.module.css';
|
|
6
|
+
/**
|
|
7
|
+
* Группа кнопок футера (approve / cancel / additional) с раскладкой по поверхности и числу действий.
|
|
8
|
+
* Единый источник правды для `BottomSheet`, `Modal` и `Drawer` (adaptive-маппинг 1:1).
|
|
9
|
+
* Возвращает `null`, если ни одной кнопки не передано.
|
|
10
|
+
*/
|
|
11
|
+
export function FooterActions({ approveButton, cancelButton, additionalButton, size, footerActionsOrientation = FOOTER_ACTIONS_ORIENTATION.Horizontal, testIds, actionsClassName, surface = 'window', }) {
|
|
12
|
+
const actionCount = [approveButton, cancelButton, additionalButton].filter(Boolean).length;
|
|
13
|
+
if (actionCount === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const isMobile = surface === 'bottomSheet';
|
|
17
|
+
const isVerticalActions = footerActionsOrientation === FOOTER_ACTIONS_ORIENTATION.Vertical || actionCount === 3;
|
|
18
|
+
const hasTertiary = Boolean(additionalButton);
|
|
19
|
+
// Раскладка кнопок футера зависит от поверхности:
|
|
20
|
+
// - desktop (window): пара `cancel + approve` → компактно вправо (`compact`); пара с tertiary
|
|
21
|
+
// (`additional + approve`) → space-between, tertiary слева / primary справа (Figma
|
|
22
|
+
// `popupDropdownFooter` — календарные дропдауны); 3 → стопка, primary сверху (ButtonGroup default).
|
|
23
|
+
// - mobile (bottomSheet): 1 → вправо (`single`); 2 → space-between (`break`); 3 → стопка, инверсия (`stackInverted`).
|
|
24
|
+
const useBreak = !isVerticalActions && actionCount === 2 && (isMobile || (!isMobile && hasTertiary));
|
|
25
|
+
const isSingle = isMobile && actionCount === 1;
|
|
26
|
+
const isCompact = !isMobile && !isVerticalActions && !useBreak;
|
|
27
|
+
const isStackInverted = isMobile && isVerticalActions;
|
|
28
|
+
return (_jsx(ButtonGroup, { className: cn(styles.actions, isSingle && styles.single, isCompact && styles.compact, isStackInverted && styles.stackInverted, actionsClassName), size: size, vertical: isVerticalActions, break: useBreak, primaryAction: approveButton ? { ...approveButton, 'data-test-id': testIds.approve } : undefined, secondaryAction: cancelButton
|
|
29
|
+
? { view: VIEW.Outline, appearance: APPEARANCE.Neutral, ...cancelButton, 'data-test-id': testIds.cancel }
|
|
30
|
+
: undefined, tertiaryAction: additionalButton
|
|
31
|
+
? {
|
|
32
|
+
view: VIEW.Simple,
|
|
33
|
+
appearance: APPEARANCE.Neutral,
|
|
34
|
+
...additionalButton,
|
|
35
|
+
'data-test-id': testIds.additional,
|
|
36
|
+
}
|
|
37
|
+
: undefined }));
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './FooterActions.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './FooterActions.js';
|