Merged in fix/3697-prettier-configs (pull request #3396)

fix(SW-3691): Setup one prettier config for whole repo

* Setup prettierrc in root and remove other configs


Approved-by: Joakim Jäderberg
Approved-by: Linus Flood
This commit is contained in:
Rasmus Langvad
2026-01-07 12:45:50 +00:00
parent 932413412b
commit d0546926a9
500 changed files with 18367 additions and 18419 deletions

View File

@@ -1,69 +1,69 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from 'storybook/test'
import { VideoPlayerButton } from '.'
import { videoPlayerButtonIconNames } from './types'
import { config } from './variants'
import { fn } from "storybook/test"
import { VideoPlayerButton } from "."
import { videoPlayerButtonIconNames } from "./types"
import { config } from "./variants"
const meta: Meta<typeof VideoPlayerButton> = {
title: 'Core Components/Video/VideoPlayerButton',
title: "Core Components/Video/VideoPlayerButton",
component: VideoPlayerButton,
parameters: {
docs: {
description: {
component:
'A component to display a VideoPlayer and content inside a card connected to the video. The size and gaps are determined by the parent container.',
"A component to display a VideoPlayer and content inside a card connected to the video. The size and gaps are determined by the parent container.",
},
},
},
argTypes: {
onPress: {
table: {
type: { summary: 'function' },
type: { summary: "function" },
},
defaultValue: { summary: 'undefined' },
defaultValue: { summary: "undefined" },
},
size: {
control: 'select',
control: "select",
options: Object.keys(config.variants.size),
table: {
defaultValue: {
summary: config.defaultVariants.size,
},
type: {
summary: Object.keys(config.variants.size).join(' | '),
summary: Object.keys(config.variants.size).join(" | "),
},
},
description: 'The size of the button.',
description: "The size of the button.",
},
iconName: {
control: 'select',
control: "select",
options: videoPlayerButtonIconNames,
table: {
defaultValue: {
summary: 'undefined',
summary: "undefined",
},
type: {
summary: videoPlayerButtonIconNames.join(' | '),
summary: videoPlayerButtonIconNames.join(" | "),
},
},
description:
'This decides the background color and text color of the card.',
"This decides the background color and text color of the card.",
},
},
}
export default meta
function renderAllIcons(args: Story['args']) {
function renderAllIcons(args: Story["args"]) {
return (
<div
style={{
display: 'flex',
gap: '16px',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
display: "flex",
gap: "16px",
alignItems: "center",
justifyContent: "center",
flexWrap: "wrap",
}}
>
{videoPlayerButtonIconNames.map((iconName) => (
@@ -76,20 +76,20 @@ function renderAllIcons(args: Story['args']) {
type Story = StoryObj<typeof VideoPlayerButton>
export const Default: Story = {
args: { iconName: 'play_arrow', onPress: fn() },
args: { iconName: "play_arrow", onPress: fn() },
}
export const Small: Story = {
args: { ...Default.args, size: 'sm' },
args: { ...Default.args, size: "sm" },
render: (args) => renderAllIcons(args),
}
export const Medium: Story = {
args: { ...Default.args, size: 'md' },
args: { ...Default.args, size: "md" },
render: (args) => renderAllIcons(args),
}
export const Large: Story = {
args: { ...Default.args, size: 'lg' },
args: { ...Default.args, size: "lg" },
render: (args) => renderAllIcons(args),
}

View File

@@ -1,10 +1,10 @@
'use client'
"use client"
import { Button as ButtonRAC } from 'react-aria-components'
import { MaterialIcon } from '../../Icons/MaterialIcon'
import { VideoPlayerButtonProps } from './types'
import { variants } from './variants'
import styles from './videoPlayerButton.module.css'
import { Button as ButtonRAC } from "react-aria-components"
import { MaterialIcon } from "../../Icons/MaterialIcon"
import { VideoPlayerButtonProps } from "./types"
import { variants } from "./variants"
import styles from "./videoPlayerButton.module.css"
export function VideoPlayerButton({
iconName,
@@ -32,13 +32,13 @@ export function VideoPlayerButton({
)
}
function getIconSize(size: VideoPlayerButtonProps['size']) {
function getIconSize(size: VideoPlayerButtonProps["size"]) {
switch (size) {
case 'sm':
case "sm":
return 28
case 'lg':
case "lg":
return 40
case 'md':
case "md":
default:
return 32
}

View File

@@ -1,22 +1,22 @@
import type { VariantProps } from 'class-variance-authority'
import { Button as ButtonRAC } from 'react-aria-components'
import type { VariantProps } from "class-variance-authority"
import { Button as ButtonRAC } from "react-aria-components"
import { ComponentProps } from 'react'
import type { SymbolCodepoints } from '../../Icons/MaterialIcon/MaterialSymbol/types'
import type { variants } from './variants'
import { ComponentProps } from "react"
import type { SymbolCodepoints } from "../../Icons/MaterialIcon/MaterialSymbol/types"
import type { variants } from "./variants"
export const videoPlayerButtonIconNames = [
'play_arrow',
'pause',
'volume_up',
'volume_off',
"play_arrow",
"pause",
"volume_up",
"volume_off",
] satisfies SymbolCodepoints[]
type VideoPlayerButtonIconName = (typeof videoPlayerButtonIconNames)[number]
export interface VideoPlayerButtonProps
extends
Omit<ComponentProps<typeof ButtonRAC>, 'children'>,
Omit<ComponentProps<typeof ButtonRAC>, "children">,
VariantProps<typeof variants> {
iconName: VideoPlayerButtonIconName
}

View File

@@ -1,17 +1,17 @@
import { cva } from 'class-variance-authority'
import { cva } from "class-variance-authority"
import styles from './videoPlayerButton.module.css'
import styles from "./videoPlayerButton.module.css"
export const config = {
variants: {
size: {
sm: styles['size-sm'],
md: styles['size-md'],
lg: styles['size-lg'],
sm: styles["size-sm"],
md: styles["size-md"],
lg: styles["size-lg"],
},
},
defaultVariants: {
size: 'md',
size: "md",
},
} as const

View File

@@ -32,7 +32,7 @@
outline-offset: 2px;
&::before {
content: '';
content: "";
position: absolute;
inset: -2px;
border: 2px solid var(--Border-Interactive-Focus);

View File

@@ -1,18 +1,18 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Lang } from '@scandic-hotels/common/constants/language'
import { VideoPlayer } from '.'
import { config as videoPlayerConfig } from './variants'
import { Lang } from "@scandic-hotels/common/constants/language"
import { VideoPlayer } from "."
import { config as videoPlayerConfig } from "./variants"
const meta: Meta<typeof VideoPlayer> = {
title: 'Core Components/Video/VideoPlayer',
title: "Core Components/Video/VideoPlayer",
component: VideoPlayer,
parameters: {
docs: {
description: {
component:
'This component is not ready for production use. It is still under development and may undergo significant changes.',
"This component is not ready for production use. It is still under development and may undergo significant changes.",
},
},
},
@@ -25,60 +25,60 @@ const meta: Meta<typeof VideoPlayer> = {
},
sources: {
table: {
type: { summary: '{src: string; type: string}[]' },
type: { summary: "{src: string; type: string}[]" },
},
description:
'The different sources of the video, including their formats.',
"The different sources of the video, including their formats.",
},
poster: {
table: {
type: {
summary:
'{src: string, dimensions?: { width: number; height: number }}',
"{src: string, dimensions?: { width: number; height: number }}",
},
},
description:
'The poster image to be displayed before playback. Default behavior in iOS is that the first frame of the video is not visible until playback starts, so providing a poster image is recommended for better user experience.',
"The poster image to be displayed before playback. Default behavior in iOS is that the first frame of the video is not visible until playback starts, so providing a poster image is recommended for better user experience.",
},
captions: {
table: {
type: {
summary: 'Caption[]',
detail: '{ src: string; srcLang: Lang; isDefault: boolean }[]',
summary: "Caption[]",
detail: "{ src: string; srcLang: Lang; isDefault: boolean }[]",
},
},
description:
'An array of caption objects for the video. Since this functionality only works when the controls are visible, captions are only supported in the inline variant.',
"An array of caption objects for the video. Since this functionality only works when the controls are visible, captions are only supported in the inline variant.",
},
variant: {
control: 'select',
control: "select",
options: Object.keys(videoPlayerConfig.variants.variant),
table: {
defaultValue: {
summary: videoPlayerConfig.defaultVariants.variant,
},
type: {
summary: 'string',
detail: Object.keys(videoPlayerConfig.variants.variant).join(' | '),
summary: "string",
detail: Object.keys(videoPlayerConfig.variants.variant).join(" | "),
},
},
description:
'The variant of the video player, which determines its style and behavior. The hero variant is typically used for large, prominent video displays and defaults to autoplay and muted playback.',
"The variant of the video player, which determines its style and behavior. The hero variant is typically used for large, prominent video displays and defaults to autoplay and muted playback.",
},
focalPoint: {
table: {
type: { summary: 'FocalPoint', detail: '{ x: number; y: number }' },
defaultValue: { summary: '{ x: 50, y: 50 }' },
type: { summary: "FocalPoint", detail: "{ x: number; y: number }" },
defaultValue: { summary: "{ x: 50, y: 50 }" },
},
description: 'The focal point of the video thumbnail.',
description: "The focal point of the video thumbnail.",
},
autoPlay: {
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' },
type: { summary: "boolean" },
defaultValue: { summary: "false" },
},
description:
'Whether the video should autoplay. Note that autoplay might be ignored by browsers unless the video is muted, which is the default behavior for this component.',
"Whether the video should autoplay. Note that autoplay might be ignored by browsers unless the video is muted, which is the default behavior for this component.",
},
},
}
@@ -89,35 +89,35 @@ type Story = StoryObj<typeof VideoPlayer>
const inlineSources = [
{
src: 'https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltf1f715c41793a9fb/6943e943ca0c69c3d00bd620/Scandic_EB_Video.mp4',
type: 'video/mp4',
src: "https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltf1f715c41793a9fb/6943e943ca0c69c3d00bd620/Scandic_EB_Video.mp4",
type: "video/mp4",
},
]
const heroSources = [
{
src: 'https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltc3aa53ac9bf6798c/693ad4b65b0889d6348893f3/Test_video.mp4',
type: 'video/mp4',
src: "https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltc3aa53ac9bf6798c/693ad4b65b0889d6348893f3/Test_video.mp4",
type: "video/mp4",
},
{
src: 'https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/blt029be07ddd444eea/693c251c09e17b33c93c1dd6/hero-banner-1920-vp9.webm',
type: 'video/webm',
src: "https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/blt029be07ddd444eea/693c251c09e17b33c93c1dd6/hero-banner-1920-vp9.webm",
type: "video/webm",
},
]
const defaultArgs = {
sources: inlineSources,
poster: {
src: 'https://imagevault.scandichotels.com/publishedmedia/dtpv2wgm6jhix2pqpp88/Scandic_Downtown_Camper_restaurang_bar_The_Nest_lounge_eld.jpg',
src: "https://imagevault.scandichotels.com/publishedmedia/dtpv2wgm6jhix2pqpp88/Scandic_Downtown_Camper_restaurang_bar_The_Nest_lounge_eld.jpg",
},
captions: [
{
src: './video/captions_en.vtt',
src: "./video/captions_en.vtt",
srcLang: Lang.en,
isDefault: false,
},
{
src: './video/captions_sv.vtt',
src: "./video/captions_sv.vtt",
srcLang: Lang.sv,
isDefault: false,
},
@@ -129,16 +129,16 @@ export const Default: Story = {
}
export const Inline: Story = {
args: { ...Default.args, variant: 'inline' },
args: { ...Default.args, variant: "inline" },
}
export const BareHero: Story = {
args: {
...Default.args,
variant: 'hero',
variant: "hero",
sources: heroSources,
},
name: 'Hero (barebones)',
name: "Hero (barebones)",
parameters: {
docs: {
description: {
@@ -156,11 +156,11 @@ export const Hero: Story = {
render: (args) => (
<div
style={{
width: 'min(100%, 1200px)',
height: 'max(20vh, 300px)',
borderRadius: 'var(--Corner-radius-lg)',
margin: 'auto',
overflow: 'hidden',
width: "min(100%, 1200px)",
height: "max(20vh, 300px)",
borderRadius: "var(--Corner-radius-lg)",
margin: "auto",
overflow: "hidden",
}}
>
<VideoPlayer {...args} />

View File

@@ -1,91 +1,91 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Lang } from '@scandic-hotels/common/constants/language'
import { VideoWithCard } from '.'
import { config } from './variants'
import { Lang } from "@scandic-hotels/common/constants/language"
import { VideoWithCard } from "."
import { config } from "./variants"
const meta: Meta<typeof VideoWithCard> = {
title: 'Core Components/Video/VideoWithCard',
title: "Core Components/Video/VideoWithCard",
component: VideoWithCard,
parameters: {
docs: {
description: {
component:
'A component to display a VideoPlayer and content inside a card connected to the video. The size and gaps are determined by the parent container.',
"A component to display a VideoPlayer and content inside a card connected to the video. The size and gaps are determined by the parent container.",
},
},
},
argTypes: {
variant: {
control: 'select',
control: "select",
options: Object.keys(config.variants.variant),
table: {
defaultValue: {
summary: config.defaultVariants.variant,
},
type: {
summary: Object.keys(config.variants.variant).join(' | '),
summary: Object.keys(config.variants.variant).join(" | "),
},
},
description:
'The variant of the card, which determines its style of the text and what content is shown.',
"The variant of the card, which determines its style of the text and what content is shown.",
},
style: {
control: 'select',
control: "select",
options: Object.keys(config.variants.style),
table: {
defaultValue: {
summary: config.defaultVariants.style,
},
type: {
summary: Object.keys(config.variants.style).join(' | '),
summary: Object.keys(config.variants.style).join(" | "),
},
},
description:
'This decides the background color and text color of the card.',
"This decides the background color and text color of the card.",
},
heading: {
table: {
type: { summary: 'string' },
type: { summary: "string" },
},
description: 'The heading text. Only applicable for the text variant.',
description: "The heading text. Only applicable for the text variant.",
},
text: {
table: {
type: { summary: 'string' },
type: { summary: "string" },
},
description: 'The body text. Only applicable for the text variant.',
description: "The body text. Only applicable for the text variant.",
},
quote: {
table: {
type: { summary: 'string' },
type: { summary: "string" },
},
description: 'The quote text. Only applicable for the quote variant.',
description: "The quote text. Only applicable for the quote variant.",
},
author: {
table: {
type: { summary: 'string' },
type: { summary: "string" },
},
description:
'The author of the quote. Only applicable for the quote variant.',
"The author of the quote. Only applicable for the quote variant.",
},
authorDescription: {
table: {
type: { summary: 'string' },
type: { summary: "string" },
},
description:
'The description of the author. Only applicable for the quote variant.',
"The description of the author. Only applicable for the quote variant.",
},
video: {
control: false,
table: {
type: {
summary:
'{ sources: { src: string; type: string }[]; poster?: { src: string; dimensions?: { width: number; height: number } }; captions?: Caption[]; focalPoint?: FocalPoint}',
"{ sources: { src: string; type: string }[]; poster?: { src: string; dimensions?: { width: number; height: number } }; captions?: Caption[]; focalPoint?: FocalPoint}",
},
},
description:
'The video props including source URL, captions and focal point. Please note that not all props from the VideoPlayer component are supported in this wrapper component.',
"The video props including source URL, captions and focal point. Please note that not all props from the VideoPlayer component are supported in this wrapper component.",
},
},
}
@@ -97,25 +97,25 @@ type Story = StoryObj<typeof VideoWithCard>
const videoProps = {
sources: [
{
src: 'https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltc3aa53ac9bf6798c/693ad4b65b0889d6348893f3/Test_video.mp4',
type: 'video/mp4',
src: "https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/bltc3aa53ac9bf6798c/693ad4b65b0889d6348893f3/Test_video.mp4",
type: "video/mp4",
},
{
src: 'https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/blt029be07ddd444eea/693c251c09e17b33c93c1dd6/hero-banner-1920-vp9.webm',
type: 'video/webm',
src: "https://eu-assets.contentstack.com/v3/assets/bltfd73aa2de3a5c4e3/blt029be07ddd444eea/693c251c09e17b33c93c1dd6/hero-banner-1920-vp9.webm",
type: "video/webm",
},
],
poster: {
src: 'https://imagevault.scandichotels.com/publishedmedia/dtpv2wgm6jhix2pqpp88/Scandic_Downtown_Camper_restaurang_bar_The_Nest_lounge_eld.jpg',
src: "https://imagevault.scandichotels.com/publishedmedia/dtpv2wgm6jhix2pqpp88/Scandic_Downtown_Camper_restaurang_bar_The_Nest_lounge_eld.jpg",
},
captions: [
{
src: './video/captions_en.vtt',
src: "./video/captions_en.vtt",
srcLang: Lang.en,
isDefault: false,
},
{
src: './video/captions_sv.vtt',
src: "./video/captions_sv.vtt",
srcLang: Lang.sv,
isDefault: false,
},
@@ -124,25 +124,25 @@ const videoProps = {
}
const quoteCardProps = {
variant: 'quote' as const,
quote: 'Download our membership App for smoother & richer experience',
author: 'Hans Christian Andersen',
authorDescription: 'The famed Danish storyteller.',
variant: "quote" as const,
quote: "Download our membership App for smoother & richer experience",
author: "Hans Christian Andersen",
authorDescription: "The famed Danish storyteller.",
video: videoProps,
}
const textCardProps = {
variant: 'text' as const,
heading: 'Download our membership App now',
text: 'Hans Christian Andersen, the famed Danish storyteller, spent many years of his life in Nyhavn, drawing inspiration from its lively atmosphere and picturesque setting.',
variant: "text" as const,
heading: "Download our membership App now",
text: "Hans Christian Andersen, the famed Danish storyteller, spent many years of his life in Nyhavn, drawing inspiration from its lively atmosphere and picturesque setting.",
video: videoProps,
}
const smallDecorator = (Story: React.FC) => (
<div
style={{
width: '792px',
paddingRight: '2rem',
width: "792px",
paddingRight: "2rem",
}}
>
<Story />
@@ -152,8 +152,8 @@ const smallDecorator = (Story: React.FC) => (
const largeDecorator = (Story: React.FC) => (
<div
style={{
width: '1200px',
paddingRight: '2rem',
width: "1200px",
paddingRight: "2rem",
}}
>
<Story />
@@ -163,7 +163,7 @@ const largeDecorator = (Story: React.FC) => (
export const QuotePrimary1Small: Story = {
args: {
...quoteCardProps,
style: 'primary-1',
style: "primary-1",
},
decorators: [smallDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -172,7 +172,7 @@ export const QuotePrimary1Small: Story = {
export const QuotePrimary2Small: Story = {
args: {
...quoteCardProps,
style: 'primary-2',
style: "primary-2",
},
decorators: [smallDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -181,7 +181,7 @@ export const QuotePrimary2Small: Story = {
export const TextPrimary1Small: Story = {
args: {
...textCardProps,
style: 'primary-1',
style: "primary-1",
},
decorators: [smallDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -190,7 +190,7 @@ export const TextPrimary1Small: Story = {
export const TextPrimary2Small: Story = {
args: {
...textCardProps,
style: 'primary-2',
style: "primary-2",
},
decorators: [smallDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -199,7 +199,7 @@ export const TextPrimary2Small: Story = {
export const QuotePrimary1Large: Story = {
args: {
...quoteCardProps,
style: 'primary-1',
style: "primary-1",
},
decorators: [largeDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -208,7 +208,7 @@ export const QuotePrimary1Large: Story = {
export const QuotePrimary2Large: Story = {
args: {
...quoteCardProps,
style: 'primary-2',
style: "primary-2",
},
decorators: [largeDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -217,7 +217,7 @@ export const QuotePrimary2Large: Story = {
export const TextPrimary1Large: Story = {
args: {
...textCardProps,
style: 'primary-1',
style: "primary-1",
},
decorators: [largeDecorator],
render: (args) => <VideoWithCard {...args} />,
@@ -226,7 +226,7 @@ export const TextPrimary1Large: Story = {
export const TextPrimary2Large: Story = {
args: {
...textCardProps,
style: 'primary-2',
style: "primary-2",
},
decorators: [largeDecorator],
render: (args) => <VideoWithCard {...args} />,

View File

@@ -1,17 +1,17 @@
import { VariantProps } from 'class-variance-authority'
import { Typography } from '../../Typography'
import { variants } from './variants'
import { VariantProps } from "class-variance-authority"
import { Typography } from "../../Typography"
import { variants } from "./variants"
import { VideoPlayer } from '..'
import { VideoPlayerProps } from '../types'
import styles from './videoWithCard.module.css'
import { VideoPlayer } from ".."
import { VideoPlayerProps } from "../types"
import styles from "./videoWithCard.module.css"
interface TextCardProps {
variant: 'text'
variant: "text"
heading: string
text?: string
}
interface QuoteCardProps {
variant: 'quote'
variant: "quote"
quote: string
author: string
authorDescription?: string
@@ -19,7 +19,7 @@ interface QuoteCardProps {
type VideoWithCardProps = VariantProps<typeof variants> &
(TextCardProps | QuoteCardProps) & {
video: Pick<VideoPlayerProps, 'sources' | 'captions' | 'focalPoint'>
video: Pick<VideoPlayerProps, "sources" | "captions" | "focalPoint">
}
export function VideoWithCard(props: VideoWithCardProps) {
@@ -42,7 +42,7 @@ export function VideoWithCard(props: VideoWithCardProps) {
}
function CardContent(props: VideoWithCardProps) {
if (props.variant === 'quote') {
if (props.variant === "quote") {
const { quote, author, authorDescription } = props
return (

View File

@@ -1,21 +1,21 @@
import { cva } from 'class-variance-authority'
import { cva } from "class-variance-authority"
import styles from './videoWithCard.module.css'
import styles from "./videoWithCard.module.css"
export const config = {
variants: {
variant: {
text: styles['variant-text'],
quote: styles['variant-quote'],
text: styles["variant-text"],
quote: styles["variant-quote"],
},
style: {
'primary-1': styles['style-primary-1'],
'primary-2': styles['style-primary-2'],
"primary-1": styles["style-primary-1"],
"primary-2": styles["style-primary-2"],
},
},
defaultVariants: {
style: 'primary-1',
variant: 'text',
style: "primary-1",
variant: "text",
},
} as const

View File

@@ -71,10 +71,10 @@
.blockquote {
&::before {
content: '“';
content: "“";
}
&::after {
content: '”';
content: "”";
}
}

View File

@@ -1,24 +1,24 @@
'use client'
"use client"
import { cx } from 'class-variance-authority'
import { useCallback, useEffect, useRef, useState } from 'react'
import { cx } from "class-variance-authority"
import { useCallback, useEffect, useRef, useState } from "react"
import { languages } from '@scandic-hotels/common/constants/language'
import { useIntl } from 'react-intl'
import Image from '../Image'
import { VideoPlayerButton } from './Button'
import { VideoPlayerProps } from './types'
import { useVideoDimensions } from './useVideoDimensions'
import { getVideoPropsByVariant } from './utils'
import { variants } from './variants'
import styles from './videoPlayer.module.css'
import { languages } from "@scandic-hotels/common/constants/language"
import { useIntl } from "react-intl"
import Image from "../Image"
import { VideoPlayerButton } from "./Button"
import { VideoPlayerProps } from "./types"
import { useVideoDimensions } from "./useVideoDimensions"
import { getVideoPropsByVariant } from "./utils"
import { variants } from "./variants"
import styles from "./videoPlayer.module.css"
export function VideoPlayer({
sources,
captions,
focalPoint = { x: 50, y: 50 },
className,
variant = 'inline',
variant = "inline",
poster,
autoPlay,
hasOverlay,
@@ -26,7 +26,7 @@ export function VideoPlayer({
const intl = useIntl()
const videoRef = useRef<HTMLVideoElement>(null)
const shouldAutoPlay =
(variant === 'hero' && (autoPlay ?? true)) || !!autoPlay
(variant === "hero" && (autoPlay ?? true)) || !!autoPlay
const [hasManuallyPlayed, setHasManuallyPlayed] = useState(false)
const [hasToggledMute, setHasToggledMute] = useState(false)
const [isPlaying, setIsPlaying] = useState(shouldAutoPlay)
@@ -51,9 +51,9 @@ export function VideoPlayer({
})
const showPlayButton =
!hasError &&
(variant === 'hero' || (variant === 'inline' && !hasManuallyPlayed))
(variant === "hero" || (variant === "inline" && !hasManuallyPlayed))
const showMuteButton =
!hasError && variant === 'inline' && hasManuallyPlayed && !hasToggledMute
!hasError && variant === "inline" && hasManuallyPlayed && !hasToggledMute
const handleIntersection = useCallback(
(entries: IntersectionObserverEntry[]) => {
@@ -71,7 +71,7 @@ export function VideoPlayer({
function togglePlay() {
const videoElement = videoRef.current
if (videoElement) {
if (variant === 'hero') {
if (variant === "hero") {
if (videoElement.paused) {
setUserPaused(false)
videoElement.play()
@@ -112,7 +112,7 @@ export function VideoPlayer({
useEffect(() => {
const videoElement = videoRef.current
if (!videoElement || variant !== 'hero') {
if (!videoElement || variant !== "hero") {
return
}
@@ -133,8 +133,8 @@ export function VideoPlayer({
// Sort sources to prioritize WebM format for better compression
const sortedSources = [...sources].sort((a, b) => {
const aIsWebM = a.type.includes('webm')
const bIsWebM = b.type.includes('webm')
const aIsWebM = a.type.includes("webm")
const bIsWebM = b.type.includes("webm")
return aIsWebM === bIsWebM ? 0 : aIsWebM ? -1 : 1
})
@@ -190,7 +190,7 @@ export function VideoPlayer({
sizes={
containerWidth
? `${containerWidth}px`
: `(min-width: 1367px) ${variant === 'inline' ? '700px' : '100vw'}, 100vw`
: `(min-width: 1367px) ${variant === "inline" ? "700px" : "100vw"}, 100vw`
}
/>
) : null}
@@ -198,17 +198,17 @@ export function VideoPlayer({
<VideoPlayerButton
className={styles.playButton}
onPress={togglePlay}
iconName={isPlaying ? 'pause' : 'play_arrow'}
size={variant === 'hero' ? 'sm' : 'lg'}
iconName={isPlaying ? "pause" : "play_arrow"}
size={variant === "hero" ? "sm" : "lg"}
aria-label={
isPlaying
? intl.formatMessage({
id: 'videoPlayer.pause',
defaultMessage: 'Pause video',
id: "videoPlayer.pause",
defaultMessage: "Pause video",
})
: intl.formatMessage({
id: 'videoPlayer.play',
defaultMessage: 'Play video',
id: "videoPlayer.play",
defaultMessage: "Play video",
})
}
/>
@@ -217,17 +217,17 @@ export function VideoPlayer({
<VideoPlayerButton
className={styles.muteButton}
onPress={handleMuteToggle}
iconName={isMuted ? 'volume_off' : 'volume_up'}
iconName={isMuted ? "volume_off" : "volume_up"}
size="sm"
aria-label={
isMuted
? intl.formatMessage({
id: 'videoPlayer.mute',
defaultMessage: 'Mute video',
id: "videoPlayer.mute",
defaultMessage: "Mute video",
})
: intl.formatMessage({
id: 'videoPlayer.unmute',
defaultMessage: 'Unmute video',
id: "videoPlayer.unmute",
defaultMessage: "Unmute video",
})
}
/>

View File

@@ -1,7 +1,7 @@
import { Lang } from '@scandic-hotels/common/constants/language'
import { FocalPoint } from '@scandic-hotels/common/utils/imageVault'
import { VariantProps } from 'class-variance-authority'
import { variants } from './variants'
import { Lang } from "@scandic-hotels/common/constants/language"
import { FocalPoint } from "@scandic-hotels/common/utils/imageVault"
import { VariantProps } from "class-variance-authority"
import { variants } from "./variants"
interface Caption {
src: string

View File

@@ -1,4 +1,4 @@
import { useRef, useState } from 'react'
import { useRef, useState } from "react"
/**
* Hook to measure container width for optimizing poster image sizes.

View File

@@ -1,26 +1,26 @@
import { VideoHTMLAttributes } from 'react'
import { VideoPlayerProps } from './types'
import { VideoHTMLAttributes } from "react"
import { VideoPlayerProps } from "./types"
export function getVideoPropsByVariant(
variant: VideoPlayerProps['variant'],
variant: VideoPlayerProps["variant"],
hasManuallyPlayed: boolean,
shouldAutoPlay: boolean
): VideoHTMLAttributes<HTMLVideoElement> {
switch (variant) {
case 'hero':
case "hero":
return {
controls: false,
controlsList: 'nodownload nofullscreen noremoteplayback',
controlsList: "nodownload nofullscreen noremoteplayback",
autoPlay: shouldAutoPlay,
muted: true,
loop: true,
playsInline: true,
}
case 'inline':
case "inline":
default:
return {
controls: hasManuallyPlayed,
controlsList: 'nodownload noremoteplayback',
controlsList: "nodownload noremoteplayback",
autoPlay: shouldAutoPlay,
muted: true,
loop: false,

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority'
import { cva } from "class-variance-authority"
import styles from './videoPlayer.module.css'
import styles from "./videoPlayer.module.css"
export const config = {
variants: {
@@ -10,7 +10,7 @@ export const config = {
},
},
defaultVariants: {
variant: 'inline',
variant: "inline",
},
} as const

View File

@@ -26,7 +26,7 @@
}
&.hasOverlay::after {
content: '';
content: "";
position: absolute;
inset: 0;
background: linear-gradient(