Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 22 additions & 17 deletions packages/plasma-temple/src/components/Grid/Grid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import styled from 'styled-components';
import { detectDevice } from '@sberdevices/plasma-ui';
import styled, { css } from 'styled-components';
import { mediaQuery } from '@sberdevices/plasma-ui';

import { FullScreenBackground } from '../FullScreenBackground/FullScreenBackground';

Expand All @@ -9,35 +9,40 @@ interface BackgroundProps {
src: string;
}

export interface GridProps {
interface GridColumns {
/** Количество колонок при разрешении XL */
columnXL?: number;
/** Количество колонок при разрешении M */
columnM?: number;
/** Количество колонок при разрешении S */
columnS?: number;
}
export interface GridProps extends GridColumns {
/** Фоновое изображение */
background?: BackgroundProps;
className?: string;
}

const StyledContainer = styled.div<{ columns: number }>`
const StyledContainer = styled.div<Required<GridColumns>>`
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(${({ columns }) => columns}, 1fr);
grid-auto-rows: 1fr;
`;
grid-template-columns: repeat(2, 1fr);

const getColumnCount = ({ columnXL, columnM, columnS }: { columnXL: number; columnM: number; columnS: number }) => {
switch (detectDevice()) {
case 'sberBox':
return columnXL;
case 'sberPortal':
return columnM;
default:
return columnS;
}
};
${({ columnXL, columnM, columnS }) => {
return [
mediaQuery('XL')(css`
grid-template-columns: repeat(${columnXL}, 1fr);
`),
mediaQuery('M')(css`
grid-template-columns: repeat(${columnM}, 1fr);
`),
mediaQuery('S')(css`
grid-template-columns: repeat(${columnS}, 1fr);
`),
];
}};
`;

/** Компонент для отображения однотипного контента (обычно карточки) в виде сетки с заданным количеством колонок */
export function Grid({
Expand All @@ -49,7 +54,7 @@ export function Grid({
background,
}: React.PropsWithChildren<GridProps>) {
return (
<StyledContainer className={className} columns={getColumnCount({ columnXL, columnM, columnS })}>
<StyledContainer className={className} columnXL={columnXL} columnM={columnM} columnS={columnS}>
{background && <FullScreenBackground src={background.src} />}
{children}
</StyledContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface VideoPlayerProps extends React.VideoHTMLAttributes<HTMLVideoEle
posterClassName?: string;
children?: (props: CustomMediaPlayerControlsProps<HTMLVideoElement>) => React.ReactElement;
src: string;
insets?: Insets;
}

const opacityMixin = css<{ hidden: boolean }>`
Expand Down Expand Up @@ -117,9 +118,11 @@ export const VideoPlayer = React.memo(
videoFit = 'contain',
posterClassName = '',
className,
insets,
...restProps
}: VideoPlayerProps) => {
const insets = useInsets();
// TODO: удалить не работает без PlasmaApp, использовать проп insets
const plasmaAppInsets = useInsets();
const playerRef = React.useRef<HTMLVideoElement>(null);
const { actions, state } = useMediaPlayer(playerRef, {
start: startTime,
Expand Down Expand Up @@ -193,11 +196,11 @@ export const VideoPlayer = React.memo(
actions: customControlsActions,
})}
{isControlVisible(ControlType.HEADER, visibleControlList) && (
<StyledHeader hidden={isControlsHidden} insets={insets}>
<StyledHeader hidden={isControlsHidden} insets={insets ?? plasmaAppInsets}>
{header}
</StyledHeader>
)}
<StyledControlsWrapper hidden={isControlsHidden} insets={insets}>
<StyledControlsWrapper hidden={isControlsHidden} insets={insets ?? plasmaAppInsets}>
<MediaPlayerControls
playback={playback}
goBack={goBack}
Expand Down
1 change: 1 addition & 0 deletions packages/plasma-temple/src/components/index@mobile.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { StateLayoutMobile as StateLayout } from './StateLayout/StateLayout@mobile';
export * from './Item/index@mobile';
export { Grid } from './Grid/Grid';
2 changes: 2 additions & 0 deletions packages/plasma-temple/src/components/index@sberbox.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { StateLayoutSberBox as StateLayout } from './StateLayout/StateLayout@sberbox';
export * from './Item/index@sberbox';
export { Grid } from './Grid/Grid';
export { HeroSliderSberbox as HeroSlider } from './HeroSlider/HeroSlider@sberbox';
2 changes: 2 additions & 0 deletions packages/plasma-temple/src/components/index@sberportal.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { StateLayoutSberPortal as StateLayout } from './StateLayout/StateLayout@sberportal';
export * from './Item/index@sberportal';
export { Grid } from './Grid/Grid';
export { HeroSliderSberportal as HeroSlider } from './HeroSlider/HeroSlider@sberportal';
1 change: 1 addition & 0 deletions packages/plasma-temple/src/index@mobile.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './components/index@mobile';
export * from './pages/index@mobile';
1 change: 1 addition & 0 deletions packages/plasma-temple/src/index@sberbox.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './components/index@sberbox';
export * from './pages/index@sberbox';
1 change: 1 addition & 0 deletions packages/plasma-temple/src/index@sberportal.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './components/index@sberportal';
export * from './pages/index@sberportal';
88 changes: 15 additions & 73 deletions packages/plasma-temple/src/pages/ErrorPage/ErrorPage.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,17 @@
import React from 'react';
import styled, { css } from 'styled-components';
import { mediaQuery } from '@sberdevices/plasma-ui/utils';

import { useFocusOnMount } from '../../hooks/useFocusOnMount';
import { THROTTLE_WAIT } from '../../hooks/useThrottledCallback';
import { StateLayout } from '../../components/StateLayout/StateLayout';
import { HeaderProps } from '../../components/Header/types';
import { isSberBoxLike } from '../../utils/deviceFamily';

import iconWarn from './ErrorPage.assets/warning-circle.svg';

export interface ErrorPageProps {
/** @deprecated работает только с PlasmaApp */
header?: HeaderProps;
/** Основной и дополнительный текст об ошибке */
error: {
status: string;
message?: string;
};
/** Дополнительный контент, обычно кнопки для выполнения какого-либо действия */
buttons?: ((focusedRef: React.Ref<HTMLButtonElement>) => React.ReactNode) | React.ReactNode;
className?: string;
}

const StyledWarningIcon = styled.div`
width: 252px;
height: 252px;

${mediaQuery('M')(css`
width: 168px;
height: 168px;
`)}

${mediaQuery('S')(css`
width: 84px;
height: 84px;
`)}

background-image: url(${iconWarn});
background-size: contain;
`;

/** Компонент страницы для отображения состояния ошибки */
export const ErrorPage: React.FC<ErrorPageProps> = ({ header, error, buttons, className }) => {
const buttonRef = React.useRef<HTMLButtonElement>(null);

useFocusOnMount<HTMLButtonElement>(buttonRef, {
delay: THROTTLE_WAIT,
prevent: !isSberBoxLike(),
});

const buttonsToRender = React.useMemo<React.ReactNode>(() => {
if (typeof buttons === 'function') {
return buttons(buttonRef);
}

if (React.isValidElement(buttons)) {
return buttons;
}

return null;
}, [buttons]);

return (
<StateLayout
className={className}
header={header}
title={error.status}
text={error.message}
button={buttonsToRender}
image={<StyledWarningIcon />}
/>
);
};
import { DeviceComponent } from '../../components/DeviceComponent/DeviceComponent';

import { ErrorPageProps } from './ErrorPage@common';
import { ErrorPageMobile } from './ErrorPage@mobile';
import { ErrorPageSberBox } from './ErrorPage@sberbox';
import { ErrorPageSberPortal } from './ErrorPage@sberportal';

export const ErrorPage: React.FC<ErrorPageProps> = (props) => (
<DeviceComponent
sberbox={ErrorPageSberBox}
sberportal={ErrorPageSberPortal}
mobile={ErrorPageMobile}
props={props}
/>
);
86 changes: 86 additions & 0 deletions packages/plasma-temple/src/pages/ErrorPage/ErrorPage@common.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import styled, { css } from 'styled-components';
import { mediaQuery } from '@sberdevices/plasma-ui/utils';

import { useFocusOnMount } from '../../hooks/useFocusOnMount';
import { THROTTLE_WAIT } from '../../hooks/useThrottledCallback';
import { HeaderProps } from '../../components/Header/types';
import { isSberBoxLike } from '../../utils/deviceFamily';
import { UnifiedComponentProps } from '../../registry/types';
import { StateLayoutProps } from '../../components';

import iconWarn from './ErrorPage.assets/warning-circle.svg';

type PlatformComponents = {
StateLayout: StateLayoutProps;
};

export interface ErrorPageProps {
/** @deprecated работает только с PlasmaApp */
header?: HeaderProps;
/** Основной и дополнительный текст об ошибке */
error: {
status: string;
message?: string;
};
/** Дополнительный контент, обычно кнопки для выполнения какого-либо действия */
buttons?: ((focusedRef: React.Ref<HTMLButtonElement>) => React.ReactNode) | React.ReactNode;
className?: string;
}

const StyledWarningIcon = styled.div`
width: 252px;
height: 252px;

${mediaQuery('M')(css`
width: 168px;
height: 168px;
`)}

${mediaQuery('S')(css`
width: 84px;
height: 84px;
`)}

background-image: url(${iconWarn});
background-size: contain;
`;

/** Компонент страницы для отображения состояния ошибки */
export const ErrorPageCommon: React.FC<UnifiedComponentProps<ErrorPageProps, PlatformComponents>> = ({
header,
error,
buttons,
className,
platformComponents: { StateLayout },
}) => {
const buttonRef = React.useRef<HTMLButtonElement>(null);

useFocusOnMount<HTMLButtonElement>(buttonRef, {
delay: THROTTLE_WAIT,
prevent: !isSberBoxLike(),
});

const buttonsToRender = React.useMemo<React.ReactNode>(() => {
if (typeof buttons === 'function') {
return buttons(buttonRef);
}

if (React.isValidElement(buttons)) {
return buttons;
}

return null;
}, [buttons]);

return (
<StateLayout
className={className}
header={header}
title={error.status}
text={error.message}
button={buttonsToRender}
image={<StyledWarningIcon />}
/>
);
};
13 changes: 13 additions & 0 deletions packages/plasma-temple/src/pages/ErrorPage/ErrorPage@mobile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

import { StateLayoutMobile } from '../../components/StateLayout/StateLayout@mobile';

import { ErrorPageCommon, ErrorPageProps } from './ErrorPage@common';

const platformComponents = {
StateLayout: StateLayoutMobile,
};

export const ErrorPageMobile: React.FC<ErrorPageProps> = (props) => (
<ErrorPageCommon {...props} platformComponents={platformComponents} />
);
13 changes: 13 additions & 0 deletions packages/plasma-temple/src/pages/ErrorPage/ErrorPage@sberbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

import { StateLayoutSberBox } from '../../components/StateLayout/StateLayout@sberbox';

import { ErrorPageCommon, ErrorPageProps } from './ErrorPage@common';

const platformComponents = {
StateLayout: StateLayoutSberBox,
};

export const ErrorPageSberBox: React.FC<ErrorPageProps> = (props) => (
<ErrorPageCommon {...props} platformComponents={platformComponents} />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

import { StateLayoutSberPortal } from '../../components/StateLayout/StateLayout@sberportal';

import { ErrorPageCommon, ErrorPageProps } from './ErrorPage@common';

const platformComponents = {
StateLayout: StateLayoutSberPortal,
};

export const ErrorPageSberPortal: React.FC<ErrorPageProps> = (props) => (
<ErrorPageCommon {...props} platformComponents={platformComponents} />
);
Loading