Merged in chore/eslint-curly-braces (pull request #3304)

Chore/eslint curly braces

* Add eslint rule for curly braces

* run eslint --fix for all files


Approved-by: Linus Flood
This commit is contained in:
Joakim Jäderberg
2025-12-08 07:56:21 +00:00
parent 5986828580
commit de4b3c1c3c
54 changed files with 139 additions and 104 deletions

View File

@@ -38,7 +38,7 @@ export default async function Home(props: PageArgs<LangParams>) {
<section className={styles.mainContent}> <section className={styles.mainContent}>
<div className={styles.contentContainer}> <div className={styles.contentContainer}>
<section className={styles.bookingWidgetWrapper}> <section className={styles.bookingWidgetWrapper}>
<Typography variant={"Title/lg"}> <Typography variant="Title/lg">
<h1 className={styles.heading}> <h1 className={styles.heading}>
{intl.formatMessage({ {intl.formatMessage({
id: "partnerSas.startPage.heading", id: "partnerSas.startPage.heading",
@@ -64,7 +64,7 @@ export default async function Home(props: PageArgs<LangParams>) {
defaultMessage: defaultMessage:
"Collect new SAS EuroBonus points with your bookings.", "Collect new SAS EuroBonus points with your bookings.",
})} })}
theme={"SAS-Blue"} theme="SAS-Blue"
icon={IconName.Diamond} icon={IconName.Diamond}
/> />
<InfoBox <InfoBox
@@ -77,7 +77,7 @@ export default async function Home(props: PageArgs<LangParams>) {
defaultMessage: defaultMessage:
"Then use your points to pay for your next Scandic stay!", "Then use your points to pay for your next Scandic stay!",
})} })}
theme={"SAS-Blue"} theme="SAS-Blue"
icon={IconName.CreditCard} icon={IconName.CreditCard}
/> />
</section> </section>

View File

@@ -64,9 +64,8 @@ export default function GlobalError({
<p> <p>
<strong> <strong>
{ While we&apos;re working hard to fix it, you can always give us a
"While we're working hard to fix it, you can always give us a call:" call:
}
</strong> </strong>
</p> </p>

View File

@@ -61,12 +61,12 @@ export function LanguageSwitcher({
return ( return (
<div className={classNames}> <div className={classNames}>
<DialogTrigger> <DialogTrigger>
<Button className={styles.triggerButton} variant={"Text"} wrapping> <Button className={styles.triggerButton} variant="Text" wrapping>
{isMobile && !isFooter ? null : ( {isMobile && !isFooter ? null : (
<MaterialIcon <MaterialIcon
icon="globe" icon="globe"
size={16} size={16}
color={"Icon/Inverted"} color="Icon/Inverted"
className={styles.globeIcon} className={styles.globeIcon}
/> />
)} )}
@@ -109,7 +109,7 @@ export function LanguageSwitcher({
<Popover <Popover
offset={isFooter ? 0 : 21} offset={isFooter ? 0 : 21}
className={styles.languageSwitcherPopover} className={styles.languageSwitcherPopover}
placement={"bottom right"} placement="bottom right"
> >
<Dialog> <Dialog>
{({ close }) => ( {({ close }) => (
@@ -158,8 +158,8 @@ function LanguageSwitcherContent({
<> <>
<div className={styles.closeModalWrapper}> <div className={styles.closeModalWrapper}>
<Button <Button
variant={"Text"} variant="Text"
size={"Medium"} size="Medium"
onPress={closeModal} onPress={closeModal}
className={styles.closeModal} className={styles.closeModal}
> >
@@ -167,17 +167,17 @@ function LanguageSwitcherContent({
icon="chevron_left" icon="chevron_left"
size={28} size={28}
className={styles.arrowBackIcon} className={styles.arrowBackIcon}
color={"CurrentColor"} color="CurrentColor"
/> />
<MaterialIcon <MaterialIcon
icon="close" icon="close"
size={32} size={32}
className={styles.closeIcon} className={styles.closeIcon}
color={"CurrentColor"} color="CurrentColor"
/> />
</Button> </Button>
</div> </div>
<Typography variant={"Title/Subtitle/md"}> <Typography variant="Title/Subtitle/md">
<h3 className={styles.title}> <h3 className={styles.title}>
{intl.formatMessage({ {intl.formatMessage({
id: "common.selectYourLanguage", id: "common.selectYourLanguage",

View File

@@ -35,7 +35,7 @@ export function MobileMenu({ children }: React.PropsWithChildren) {
/> />
<div id="close-menu-container" style={{ position: "relative" }}> <div id="close-menu-container" style={{ position: "relative" }}>
<Button <Button
variant={"Text"} variant="Text"
type="button" type="button"
className={`${styles.hamburger} ${isOpen ? styles.isExpanded : ""}`} className={`${styles.hamburger} ${isOpen ? styles.isExpanded : ""}`}
aria-label={isOpen ? closeMsg : openMsg} aria-label={isOpen ? closeMsg : openMsg}

View File

@@ -36,7 +36,7 @@ export function NavigationMenu({ isMobile = false }: { isMobile?: boolean }) {
className={`${styles.menuItem} ${styles.contactLink}`} className={`${styles.menuItem} ${styles.contactLink}`}
> >
{isMobile ? null : ( {isMobile ? null : (
<MaterialIcon icon="call" size={16} color={"CurrentColor"} /> <MaterialIcon icon="call" size={16} color="CurrentColor" />
)} )}
{intl.formatMessage({ {intl.formatMessage({
id: "common.contactUs", id: "common.contactUs",

View File

@@ -58,9 +58,9 @@ export function UserMenu({
<div className={styles.userMenu}> <div className={styles.userMenu}>
{(session.status === "loading" || isLoading) && {(session.status === "loading" || isLoading) &&
(isMobile ? ( (isMobile ? (
<SkeletonShimmer width={"4ch"} height={"4ch"} /> <SkeletonShimmer width="4ch" height="4ch" />
) : ( ) : (
<SkeletonShimmer width={"12ch"} height={"1ch"} /> <SkeletonShimmer width="12ch" height="1ch" />
))} ))}
{(session.status === "unauthenticated" || isError) && ( {(session.status === "unauthenticated" || isError) && (
<a href={loginLink} className={styles.loginLink}> <a href={loginLink} className={styles.loginLink}>
@@ -86,7 +86,7 @@ export function UserMenu({
{session.status === "authenticated" && isSuccess && profileData && ( {session.status === "authenticated" && isSuccess && profileData && (
<div> <div>
<DialogTrigger onOpenChange={onOpenChange} isOpen={isOpen}> <DialogTrigger onOpenChange={onOpenChange} isOpen={isOpen}>
<Button className={styles.userName} variant={"Text"}> <Button className={styles.userName} variant="Text">
<Avatar <Avatar
className={styles.avatar} className={styles.avatar}
initials={getInitials( initials={getInitials(
@@ -153,7 +153,7 @@ function UserMenuContent({
<> <>
<div> <div>
{isMobile && ( {isMobile && (
<Typography variant={"Title/Subtitle/md"}> <Typography variant="Title/Subtitle/md">
<h3 data-hj-suppress> <h3 data-hj-suppress>
{intl.formatMessage( {intl.formatMessage(
{ {
@@ -176,7 +176,7 @@ function UserMenuContent({
</Typography> </Typography>
<Typography variant="Title/Overline/sm"> <Typography variant="Title/Overline/sm">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<span>{"·"}</span> <span>·</span>
</Typography> </Typography>
<Typography variant="Body/Paragraph/mdRegular"> <Typography variant="Body/Paragraph/mdRegular">
<span> <span>
@@ -194,7 +194,7 @@ function UserMenuContent({
</p> </p>
</div> </div>
<Divider className={styles.menuDivider} /> <Divider className={styles.menuDivider} />
<Typography variant={"Link/md"} className={styles.logoutLink}> <Typography variant="Link/md" className={styles.logoutLink}>
{/* Link triggers rsc which doesn't reload complete page and shows logged in even after logout */} {/* Link triggers rsc which doesn't reload complete page and shows logged in even after logout */}
<a href={`/${lang}/logout`}> <a href={`/${lang}/logout`}>
{intl.formatMessage({ {intl.formatMessage({

View File

@@ -47,6 +47,14 @@ export default defineConfig([
"no-console": "warn", "no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"react/jsx-curly-brace-presence": [
"error",
{
props: "never",
children: "never",
propElementValues: "always",
},
],
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [
"warn", "warn",

View File

@@ -7,8 +7,8 @@
"dev": "NODE_OPTIONS=--openssl-legacy-provider PORT=3001 NEXT_PUBLIC_PORT=3001 next dev --turbo", "dev": "NODE_OPTIONS=--openssl-legacy-provider PORT=3001 NEXT_PUBLIC_PORT=3001 next dev --turbo",
"build": "next build", "build": "next build",
"start": "node .next/standalone/server.js", "start": "node .next/standalone/server.js",
"lint": "eslint --max-warnings 0 . && tsgo --noEmit", "lint": "eslint --max-warnings 0 .",
"lint:fix": "eslint --fix . && tsgo --noEmit", "lint:fix": "eslint --fix .",
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"typegen": "next typegen", "typegen": "next typegen",
"clean": "rm -rf .next", "clean": "rm -rf .next",

View File

@@ -6,8 +6,8 @@
"scripts": { "scripts": {
"dev": "bun --watch src/index.ts | pino-pretty -o '{if module}[{module}] {end}{msg}' -i pid,hostname", "dev": "bun --watch src/index.ts | pino-pretty -o '{if module}[{module}] {end}{msg}' -i pid,hostname",
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && tsgo --noEmit", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --ext ts,tsx --fix --report-unused-disable-directives --max-warnings 0 && tsgo --noEmit", "lint:fix": "eslint . --ext ts,tsx --fix --report-unused-disable-directives --max-warnings 0",
"format": "prettier --write ." "format": "prettier --write ."
}, },
"dependencies": { "dependencies": {

View File

@@ -18,7 +18,7 @@ export function AlreadyLinkedError() {
<SASModal> <SASModal>
<MaterialIcon <MaterialIcon
icon="check_circle" icon="check_circle"
color={"Icon/Feedback/Success"} color="Icon/Feedback/Success"
isFilled isFilled
size={64} size={64}
/> />
@@ -43,9 +43,9 @@ export function AlreadyLinkedError() {
<Typography variant="Body/Paragraph/mdBold"> <Typography variant="Body/Paragraph/mdBold">
<ButtonLink <ButtonLink
href={partnerSas[lang]} href={partnerSas[lang]}
variant={"Tertiary"} variant="Tertiary"
color={"Primary"} color="Primary"
size={"Large"} size="Large"
> >
{intl.formatMessage({ {intl.formatMessage({
id: "linkEuroBonusAccount.viewLinkedAccountsButton", id: "linkEuroBonusAccount.viewLinkedAccountsButton",

View File

@@ -54,7 +54,7 @@ export function LinkAccountForm({
<form onSubmit={handleSubmit} className={styles.form}> <form onSubmit={handleSubmit} className={styles.form}>
<div className={styles.titles}> <div className={styles.titles}>
<Image <Image
alt={"Scandic ❤️ SAS"} alt="Scandic ❤️ SAS"
height={25} height={25}
width={182} width={182}
src="/_static/img/partner/sas/sas-campaign-logo.png" src="/_static/img/partner/sas/sas-campaign-logo.png"

View File

@@ -78,9 +78,8 @@ export default function GlobalError({
<p> <p>
<strong> <strong>
{ While we&apos;re working hard to fix it, you can always give us a
"While we're working hard to fix it, you can always give us a call:" call:
}
</strong> </strong>
</p> </p>

View File

@@ -32,7 +32,7 @@ export default function Filter({
<form className={styles.filterForm}> <form className={styles.filterForm}>
<DeprecatedSelect <DeprecatedSelect
items={countryFilters} items={countryFilters}
defaultSelectedKey={""} defaultSelectedKey=""
label={intl.formatMessage({ label={intl.formatMessage({
id: "common.country", id: "common.country",
defaultMessage: "Country", defaultMessage: "Country",
@@ -46,7 +46,7 @@ export default function Filter({
/> />
<DeprecatedSelect <DeprecatedSelect
items={cityFilters} items={cityFilters}
defaultSelectedKey={""} defaultSelectedKey=""
label={intl.formatMessage({ label={intl.formatMessage({
id: "jobylonFeed.cityFilterLabel", id: "jobylonFeed.cityFilterLabel",
defaultMessage: "Location (shown in local language)", defaultMessage: "Location (shown in local language)",
@@ -60,7 +60,7 @@ export default function Filter({
/> />
<DeprecatedSelect <DeprecatedSelect
items={departmentFilters} items={departmentFilters}
defaultSelectedKey={""} defaultSelectedKey=""
label={intl.formatMessage({ label={intl.formatMessage({
id: "jobylonFeed.departmentFilterLabel", id: "jobylonFeed.departmentFilterLabel",
defaultMessage: "Hotel or office", defaultMessage: "Hotel or office",
@@ -74,7 +74,7 @@ export default function Filter({
/> />
<DeprecatedSelect <DeprecatedSelect
items={categoryFilters} items={categoryFilters}
defaultSelectedKey={""} defaultSelectedKey=""
label={intl.formatMessage({ label={intl.formatMessage({
id: "jobylonFeed.categoryFilterLabel", id: "jobylonFeed.categoryFilterLabel",
defaultMessage: "Category", defaultMessage: "Category",

View File

@@ -157,8 +157,8 @@ export default function OverviewTableClient({
<div> <div>
<div className={styles.mobileColumns}> <div className={styles.mobileColumns}>
<div className={styles.columnHeaderContainer}> <div className={styles.columnHeaderContainer}>
<MobileColumnHeader column={"A"} /> <MobileColumnHeader column="A" />
<MobileColumnHeader column={"B"} /> <MobileColumnHeader column="B" />
</div> </div>
<RewardList <RewardList
levels={[ levels={[

View File

@@ -40,7 +40,7 @@ export default function LargeTable({
return ( return (
<tr key={key + idx} className={styles.tr}> <tr key={key + idx} className={styles.tr}>
<th scope={"row"} className={styles.rewardTh}> <th scope="row" className={styles.rewardTh}>
<RewardTableHeader name={label} description={description} /> <RewardTableHeader name={label} description={description} />
</th> </th>
{levels.map((level, idx) => { {levels.map((level, idx) => {
@@ -71,7 +71,7 @@ function RewardTableHeader({ name, description }: RewardTableHeaderProps) {
<details className={styles.details}> <details className={styles.details}>
<summary className={styles.summary}> <summary className={styles.summary}>
<hgroup className={styles.rewardHeader}> <hgroup className={styles.rewardHeader}>
<Title as="h4" level="h2" textTransform={"regular"}> <Title as="h4" level="h2" textTransform="regular">
{name} {name}
</Title> </Title>
<span className={styles.chevron}> <span className={styles.chevron}>

View File

@@ -19,7 +19,7 @@ export default function RewardCard({
<details className={styles.details}> <details className={styles.details}>
<summary className={styles.summary}> <summary className={styles.summary}>
<hgroup className={styles.rewardCardHeader}> <hgroup className={styles.rewardCardHeader}>
<Title as="h4" level="h2" textTransform={"regular"}> <Title as="h4" level="h2" textTransform="regular">
{title} {title}
</Title> </Title>
<span className={styles.chevron}> <span className={styles.chevron}>

View File

@@ -11,7 +11,7 @@ export default function YourLevel() {
className={styles.script} className={styles.script}
color="peach80" color="peach80"
type="two" type="two"
textAlign={"center"} textAlign="center"
> >
{intl.formatMessage({ {intl.formatMessage({
id: "overviewTable.yourLevel", id: "overviewTable.yourLevel",

View File

@@ -27,8 +27,8 @@ export default async function PointsOverview({
link={link} link={link}
preamble={subtitle} preamble={subtitle}
title={title} title={title}
headingAs={"h3"} headingAs="h3"
headingLevel={"h1"} headingLevel="h1"
/> />
<div className={styles.membershipCardsContainer}> <div className={styles.membershipCardsContainer}>
<PointsToSpendCard user={user} /> <PointsToSpendCard user={user} />

View File

@@ -43,7 +43,7 @@ export function DestinationSearchForm({
handlePressEnter={() => { handlePressEnter={() => {
void 0 void 0
}} }}
inputName={"destinationSearch"} inputName="destinationSearch"
onSelect={(item) => { onSelect={(item) => {
if (!item.url) { if (!item.url) {
Sentry.captureMessage( Sentry.captureMessage(

View File

@@ -210,7 +210,7 @@ export default function ConfirmationStep({
onChange={(method) => { onChange={(method) => {
trackUpdatePaymentMethod({ method }) trackUpdatePaymentMethod({ method })
}} }}
formName={"paymentMethod"} formName="paymentMethod"
/> />
</> </>
)} )}

View File

@@ -28,7 +28,7 @@ export default function DeliveryMethodStep() {
</Typography> </Typography>
<Select <Select
name="deliveryTime" name="deliveryTime"
label={""} label=""
items={deliveryTimeOptions} items={deliveryTimeOptions}
registerOptions={{ required: true }} registerOptions={{ required: true }}
isNestedInModal isNestedInModal

View File

@@ -124,7 +124,7 @@ export default function Room({ booking, roomNr, user }: RoomProps) {
<div className={styles.roomHeader}> <div className={styles.roomHeader}>
{isCancelled ? ( {isCancelled ? (
<IconChip <IconChip
color={"red"} color="red"
icon={ icon={
<MaterialIcon <MaterialIcon
icon="cancel" icon="cancel"

View File

@@ -40,7 +40,7 @@ export default function SingleRoom({ user }: RoomProps) {
if (!roomNumber) { if (!roomNumber) {
return ( return (
<div className={styles.room}> <div className={styles.room}>
<SkeletonShimmer width={"200px"} height="30px" /> <SkeletonShimmer width="200px" height="30px" />
<SkeletonShimmer width="100%" height="750px" /> <SkeletonShimmer width="100%" height="750px" />
</div> </div>
) )

View File

@@ -8,15 +8,15 @@ export function MyStaySkeleton() {
return ( return (
<div className={styles.content}> <div className={styles.content}>
<div className={styles.headerSkeleton}> <div className={styles.headerSkeleton}>
<SkeletonShimmer width={"100px"} height="20px" /> <SkeletonShimmer width="100px" height="20px" />
<SkeletonShimmer width={"450px"} height="50px" /> <SkeletonShimmer width="450px" height="50px" />
<SkeletonShimmer width={"200px"} height="30px" /> <SkeletonShimmer width="200px" height="30px" />
</div> </div>
<div className={styles.cardSkeleton}> <div className={styles.cardSkeleton}>
<SkeletonShimmer width="590px" height="380px" /> <SkeletonShimmer width="590px" height="380px" />
</div> </div>
<div className={styles.section}> <div className={styles.section}>
<SkeletonShimmer width={"200px"} height="30px" /> <SkeletonShimmer width="200px" height="30px" />
<div className={styles.ancillariesSkeleton}> <div className={styles.ancillariesSkeleton}>
<SkeletonShimmer width="280px" height="200px" /> <SkeletonShimmer width="280px" height="200px" />
<SkeletonShimmer width="280px" height="200px" /> <SkeletonShimmer width="280px" height="200px" />
@@ -26,7 +26,7 @@ export function MyStaySkeleton() {
</div> </div>
</div> </div>
<div className={styles.section}> <div className={styles.section}>
<SkeletonShimmer width={"200px"} height="30px" /> <SkeletonShimmer width="200px" height="30px" />
<div> <div>
<SkeletonShimmer width="100%" height="700px" /> <SkeletonShimmer width="100%" height="700px" />
</div> </div>

View File

@@ -41,7 +41,7 @@ export default function LevelProgressModal({
<Modal <Modal
className={styles.dialog} className={styles.dialog}
trigger={ trigger={
<IconButton theme={"Black"}> <IconButton theme="Black">
<MaterialIcon <MaterialIcon
className={styles.infoButton} className={styles.infoButton}
icon="info" icon="info"

View File

@@ -15,7 +15,7 @@ function PaginationButton({
}: React.PropsWithChildren<PaginationButtonProps>) { }: React.PropsWithChildren<PaginationButtonProps>) {
return ( return (
<button <button
type={"button"} type="button"
disabled={disabled} disabled={disabled}
onClick={handleClick} onClick={handleClick}
className={`${styles.paginationButton} ${isActive ? styles.paginationButtonActive : ""}`} className={`${styles.paginationButton} ${isActive ? styles.paginationButtonActive : ""}`}

View File

@@ -171,7 +171,7 @@ export default function BookedRoomSidePeekContent({
<div className={styles.roomHeader}> <div className={styles.roomHeader}>
{isCancelled ? ( {isCancelled ? (
<IconChip <IconChip
color={"red"} color="red"
icon={ icon={
<MaterialIcon <MaterialIcon
icon="cancel" icon="cancel"

View File

@@ -26,21 +26,21 @@ export default async function JoinLoyaltyContact({
<section className={styles.joinLoyaltyContainer}> <section className={styles.joinLoyaltyContainer}>
<article className={styles.wrapper}> <article className={styles.wrapper}>
{block.title ? ( {block.title ? (
<Typography variant={"Title/Subtitle/md"}> <Typography variant="Title/Subtitle/md">
<h4 className={styles.title}>{block.title}</h4> <h4 className={styles.title}>{block.title}</h4>
</Typography> </Typography>
) : null} ) : null}
<ScandicFriends color="red" /> <ScandicFriends color="red" />
{block.preamble ? ( {block.preamble ? (
<Typography variant={"Body/Paragraph/mdRegular"}> <Typography variant="Body/Paragraph/mdRegular">
<p className={styles.preamble}>{block.preamble}</p> <p className={styles.preamble}>{block.preamble}</p>
</Typography> </Typography>
) : null} ) : null}
{block.button ? ( {block.button ? (
<Typography variant={"Body/Paragraph/mdBold"}> <Typography variant="Body/Paragraph/mdBold">
<ButtonLink <ButtonLink
className={styles.button} className={styles.button}
size={"Small"} size="Small"
wrapping wrapping
href={block.button.href} href={block.button.href}
target={block.button.openInNewTab ? "_blank" : "_self"} target={block.button.openInNewTab ? "_blank" : "_self"}
@@ -50,7 +50,7 @@ export default async function JoinLoyaltyContact({
</Typography> </Typography>
) : null} ) : null}
<section className={styles.loginContainer}> <section className={styles.loginContainer}>
<Typography variant={"Body/Paragraph/mdRegular"}> <Typography variant="Body/Paragraph/mdRegular">
<p> <p>
{intl.formatMessage({ {intl.formatMessage({
id: "loyalty.alreadyFriend", id: "loyalty.alreadyFriend",

View File

@@ -48,6 +48,14 @@ export default defineConfig([
"no-console": "warn", "no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"react/jsx-curly-brace-presence": [
"error",
{
props: "never",
children: "ignore",
propElementValues: "always",
},
],
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"simple-import-sort/imports": [ "simple-import-sort/imports": [
"warn", "warn",

View File

@@ -6,8 +6,8 @@
"scripts": { "scripts": {
"build": "next build", "build": "next build",
"dev": "NODE_OPTIONS=--openssl-legacy-provider PORT=3000 NEXT_PUBLIC_PORT=3000 next dev --turbo", "dev": "NODE_OPTIONS=--openssl-legacy-provider PORT=3000 NEXT_PUBLIC_PORT=3000 next dev --turbo",
"lint": "next typegen && eslint --max-warnings 0 . && tsgo --noEmit", "lint": "next typegen && eslint --max-warnings 0 .",
"lint:fix": "next typegen && eslint --fix --max-warnings 0 . && tsgo --noEmit", "lint:fix": "next typegen && eslint --fix --max-warnings 0 .",
"start": "node .next/standalone/server.js", "start": "node .next/standalone/server.js",
"test:setup": "yarn build && yarn start", "test:setup": "yarn build && yarn start",
"test:e2e": "playwright test", "test:e2e": "playwright test",

View File

@@ -49,6 +49,14 @@ export default defineConfig([
"no-console": "warn", "no-console": "warn",
"no-unused-vars": "off", "no-unused-vars": "off",
"react/function-component-definition": "error", "react/function-component-definition": "error",
"react/jsx-curly-brace-presence": [
"error",
{
props: "never",
children: "never",
propElementValues: "always",
},
],
"import/no-relative-packages": "error", "import/no-relative-packages": "error",
"import/no-extraneous-dependencies": [ "import/no-extraneous-dependencies": [
"warn", "warn",

View File

@@ -5,8 +5,8 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"lint": "eslint . --max-warnings 0 && tsgo --noEmit", "lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix && tsgo --noEmit", "lint:fix": "eslint . --fix",
"test": "vitest run --passWithNoTests", "test": "vitest run --passWithNoTests",
"test:watch": "vitest", "test:watch": "vitest",
"format": "prettier --write ." "format": "prettier --write ."

View File

@@ -8,7 +8,7 @@
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"lint": "eslint . --max-warnings 0 && tsgo --noEmit", "lint": "eslint . --max-warnings 0",
"format": "prettier --write ." "format": "prettier --write ."
}, },
"exports": { "exports": {

View File

@@ -2,6 +2,7 @@ import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals' import globals from 'globals'
import tsParser from '@typescript-eslint/parser' import tsParser from '@typescript-eslint/parser'
import reactRefresh from 'eslint-plugin-react-refresh' import reactRefresh from 'eslint-plugin-react-refresh'
import react from 'eslint-plugin-react'
import { FlatCompat } from '@eslint/eslintrc' import { FlatCompat } from '@eslint/eslintrc'
import js from '@eslint/js' import js from '@eslint/js'
import importPlugin from 'eslint-plugin-import' import importPlugin from 'eslint-plugin-import'
@@ -35,6 +36,7 @@ export default defineConfig([
'react-refresh': reactRefresh, 'react-refresh': reactRefresh,
import: importPlugin, import: importPlugin,
formatjs, formatjs,
react,
}, },
settings: { settings: {
// Ensure the plugin can resolve workspace packages and TS path aliases // Ensure the plugin can resolve workspace packages and TS path aliases
@@ -64,6 +66,14 @@ export default defineConfig([
allowConstantExport: true, allowConstantExport: true,
}, },
], ],
'react/jsx-curly-brace-presence': [
'error',
{
props: 'never',
children: 'never',
propElementValues: 'always',
},
],
'formatjs/enforce-default-message': ['error', 'literal'], 'formatjs/enforce-default-message': ['error', 'literal'],
'formatjs/enforce-placeholders': ['error'], 'formatjs/enforce-placeholders': ['error'],

View File

@@ -98,7 +98,7 @@ const meta: Meta<CompositionProps> = {
{showPrimaryButton && inMainArea && ( {showPrimaryButton && inMainArea && (
<Button <Button
size={'Large'} size="Large"
variant="Primary" variant="Primary"
typography="Body/Paragraph/mdBold" typography="Body/Paragraph/mdBold"
onPress={args._onPrimaryPress} onPress={args._onPrimaryPress}
@@ -109,7 +109,7 @@ const meta: Meta<CompositionProps> = {
{showPrimaryButton && !inMainArea && ( {showPrimaryButton && !inMainArea && (
<Button <Button
size={'Small'} size="Small"
variant="Tertiary" variant="Tertiary"
typography="Body/Paragraph/mdBold" typography="Body/Paragraph/mdBold"
onPress={args._onPrimaryPress} onPress={args._onPrimaryPress}

View File

@@ -44,7 +44,7 @@ export function PaymentOption({
</div> </div>
<div className={styles.cardContainer}> <div className={styles.cardContainer}>
{cardNumber && ( {cardNumber && (
<Typography variant={'Body/Supporting text (caption)/smRegular'}> <Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */} {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<span> {cardNumber}</span> <span> {cardNumber}</span>
</Typography> </Typography>

View File

@@ -7,27 +7,27 @@ export function HotelCardSkeleton() {
<article className={styles.card}> <article className={styles.card}>
{/* image container */} {/* image container */}
<div className={styles.imageContainer}> <div className={styles.imageContainer}>
<SkeletonShimmer width={'100%'} height="100%" /> <SkeletonShimmer width="100%" height="100%" />
</div> </div>
<div className={styles.content}> <div className={styles.content}>
<SkeletonShimmer height={'65px'} /> <SkeletonShimmer height="65px" />
<div className={styles.text}> <div className={styles.text}>
<SkeletonShimmer height={'20px'} /> <SkeletonShimmer height="20px" />
<SkeletonShimmer height={'20px'} /> <SkeletonShimmer height="20px" />
<SkeletonShimmer height={'20px'} /> <SkeletonShimmer height="20px" />
<SkeletonShimmer height={'20px'} /> <SkeletonShimmer height="20px" />
</div> </div>
<SkeletonShimmer height={'56px'} /> <SkeletonShimmer height="56px" />
<SkeletonShimmer height={'52px'} width={'150px'} /> <SkeletonShimmer height="52px" width="150px" />
</div> </div>
<div className={styles.priceVariants}> <div className={styles.priceVariants}>
{/* price variants */} {/* price variants */}
{Array.from({ length: 2 }).map((_, index) => ( {Array.from({ length: 2 }).map((_, index) => (
<SkeletonShimmer key={index} height={'100px'} /> <SkeletonShimmer key={index} height="100px" />
))} ))}
<SkeletonShimmer height={'40px'} /> <SkeletonShimmer height="40px" />
</div> </div>
</article> </article>
) )

View File

@@ -40,8 +40,9 @@ export default function HotelChequeCard({
</Subtitle> </Subtitle>
<Caption color="uiTextHighContrast">{CurrencyEnum.CC}</Caption> <Caption color="uiTextHighContrast">{CurrencyEnum.CC}</Caption>
{productTypeCheque.localPrice.additionalPricePerStay > 0 ? ( {productTypeCheque.localPrice.additionalPricePerStay > 0 ? (
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
<> <>
{'+'} +
<Subtitle type="two" color="uiTextHighContrast"> <Subtitle type="two" color="uiTextHighContrast">
{productTypeCheque.localPrice.additionalPricePerStay} {productTypeCheque.localPrice.additionalPricePerStay}
</Subtitle> </Subtitle>
@@ -61,7 +62,7 @@ export default function HotelChequeCard({
defaultMessage: 'Approx.', defaultMessage: 'Approx.',
})} })}
</Caption> </Caption>
<Caption color={'uiTextMediumContrast'}> <Caption color="uiTextMediumContrast">
{productTypeCheque.requestedPrice.numberOfCheques} {CurrencyEnum.CC} {productTypeCheque.requestedPrice.numberOfCheques} {CurrencyEnum.CC}
{productTypeCheque.requestedPrice.additionalPricePerStay {productTypeCheque.requestedPrice.additionalPricePerStay
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx ? // eslint-disable-next-line formatjs/no-literal-string-in-jsx

View File

@@ -69,8 +69,8 @@ export const Default: Story = {
none: null, none: null,
button: ( button: (
<Button <Button
variant={'Text'} variant="Text"
typography={'Body/Supporting text (caption)/smBold'} typography="Body/Supporting text (caption)/smBold"
onPress={() => fn()} onPress={() => fn()}
> >
Read more <MaterialIcon icon="chevron_right" /> Read more <MaterialIcon icon="chevron_right" />

View File

@@ -65,7 +65,7 @@ function ImageGallery({
onError={() => setImageError(true)} onError={() => setImageError(true)}
{...imageProps} {...imageProps}
/> />
<Typography variant={'Body/Supporting text (caption)/smRegular'}> <Typography variant="Body/Supporting text (caption)/smRegular">
<span <span
className={`${styles.imageCount} ${ className={`${styles.imageCount} ${
imageCountPosition === 'top' imageCountPosition === 'top'

View File

@@ -41,7 +41,7 @@ export function InfoBox({ heading, text, theme, icon }: Props) {
<article className={infoBoxVariants({ theme })}> <article className={infoBoxVariants({ theme })}>
{icon && ( {icon && (
<div className={iconVariants({ theme })}> <div className={iconVariants({ theme })}>
<IconByIconName iconName={icon} color={'CurrentColor'} /> <IconByIconName iconName={icon} color="CurrentColor" />
</div> </div>
)} )}
<div className={styles.content}> <div className={styles.content}>

View File

@@ -29,7 +29,7 @@ export function LinkListItem({
return ( return (
<Link <Link
href={href} href={href}
target={'_blank'} target="_blank"
onClick={onClick} onClick={onClick}
className={cx(styles.content, { className={cx(styles.content, {
[styles.graphic]: illustration, [styles.graphic]: illustration,

View File

@@ -156,7 +156,7 @@ export const Examples: Story = {
}} }}
> >
<HotelMarkerByType {...args} {...exampleArgs} /> <HotelMarkerByType {...args} {...exampleArgs} />
<Typography variant={'Label/xsRegular'}> <Typography variant="Label/xsRegular">
<p>{exampleArgs.name}</p> <p>{exampleArgs.name}</p>
</Typography> </Typography>
</div> </div>

View File

@@ -68,7 +68,7 @@ export const All: Story = {
}} }}
> >
<PaymentMethodIcon {...args} paymentMethod={m} /> <PaymentMethodIcon {...args} paymentMethod={m} />
<Typography variant={'Label/xsRegular'}> <Typography variant="Label/xsRegular">
<p>{m}</p> <p>{m}</p>
</Typography> </Typography>
</div> </div>

View File

@@ -94,7 +94,7 @@ export default function CampaignRateCard({
> >
{rateTermDetails.map((termGroup) => ( {rateTermDetails.map((termGroup) => (
<div key={termGroup.title} className={styles.terms}> <div key={termGroup.title} className={styles.terms}>
<Typography variant={'Body/Paragraph/mdBold'}> <Typography variant="Body/Paragraph/mdBold">
<p>{termGroup.title}</p> <p>{termGroup.title}</p>
</Typography> </Typography>
{termGroup.terms.map((term) => ( {termGroup.terms.map((term) => (

View File

@@ -84,7 +84,7 @@ export default function CodeRateCard({
> >
{rateTermDetails.map((termGroup) => ( {rateTermDetails.map((termGroup) => (
<div key={termGroup.title} className={styles.terms}> <div key={termGroup.title} className={styles.terms}>
<Typography variant={'Body/Paragraph/mdBold'}> <Typography variant="Body/Paragraph/mdBold">
<p>{termGroup.title}</p> <p>{termGroup.title}</p>
</Typography> </Typography>
{termGroup.terms.map((term) => ( {termGroup.terms.map((term) => (

View File

@@ -59,7 +59,7 @@ function InnerModal({
<MotionOverlay <MotionOverlay
animate={animation} animate={animation}
className={styles.overlay} className={styles.overlay}
initial={'hidden'} initial="hidden"
isDismissable isDismissable
isExiting={animation === AnimationStateEnum.hidden} isExiting={animation === AnimationStateEnum.hidden}
onAnimationComplete={modalStateHandler} onAnimationComplete={modalStateHandler}
@@ -71,7 +71,7 @@ function InnerModal({
className={styles.modal} className={styles.modal}
variants={slideInOut} variants={slideInOut}
animate={animation} animate={animation}
initial={'hidden'} initial="hidden"
> >
<Dialog className={styles.dialog}> <Dialog className={styles.dialog}>
{({ close }) => ( {({ close }) => (

View File

@@ -70,7 +70,7 @@ export default function PointsRateCard({
> >
{rateTermDetails.map((termGroup) => ( {rateTermDetails.map((termGroup) => (
<div key={termGroup.title} className={styles.terms}> <div key={termGroup.title} className={styles.terms}>
<Typography variant={'Body/Paragraph/mdBold'}> <Typography variant="Body/Paragraph/mdBold">
<p>{termGroup.title}</p> <p>{termGroup.title}</p>
</Typography> </Typography>
{termGroup.terms.map((term) => ( {termGroup.terms.map((term) => (

View File

@@ -79,7 +79,7 @@ export default function RegularRateCard({
> >
{rateTermDetails.map((termGroup) => ( {rateTermDetails.map((termGroup) => (
<div key={termGroup.title} className={styles.terms}> <div key={termGroup.title} className={styles.terms}>
<Typography variant={'Body/Paragraph/mdBold'}> <Typography variant="Body/Paragraph/mdBold">
<p>{termGroup.title}</p> <p>{termGroup.title}</p>
</Typography> </Typography>
{termGroup.terms.map((term) => ( {termGroup.terms.map((term) => (

View File

@@ -31,7 +31,7 @@ export function Toast({ children, message, onClose, variant }: ToastsProps) {
<div className={className} role={getRole(variant)} aria-atomic="true"> <div className={className} role={getRole(variant)} aria-atomic="true">
<div className={styles.iconContainer}>{Icon && Icon}</div> <div className={styles.iconContainer}>{Icon && Icon}</div>
{message ? ( {message ? (
<Typography variant={'Body/Paragraph/mdRegular'}> <Typography variant="Body/Paragraph/mdRegular">
<p className={styles.message}>{message}</p> <p className={styles.message}>{message}</p>
</Typography> </Typography>
) : ( ) : (

View File

@@ -213,8 +213,8 @@
"generate": "cd generate && jiti generate.ts && yarn format", "generate": "cd generate && jiti generate.ts && yarn format",
"format": "prettier . --write", "format": "prettier . --write",
"build": "yarn build-storybook", "build": "yarn build-storybook",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && tsc", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --ext ts,tsx --report-unused-disable-directives --fix --max-warnings 0 && tsc", "lint:fix": "eslint . --ext ts,tsx --report-unused-disable-directives --fix --max-warnings 0",
"storybook": "yarn run generate && storybook dev -p 6006", "storybook": "yarn run generate && storybook dev -p 6006",
"build-storybook": "storybook build", "build-storybook": "storybook build",
"test": "vitest run --passWithNoTests", "test": "vitest run --passWithNoTests",
@@ -272,6 +272,7 @@
"eslint": "^9", "eslint": "^9",
"eslint-plugin-formatjs": "^5.3.1", "eslint-plugin-formatjs": "^5.3.1",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",
"eslint-plugin-storybook": "^10.0.8", "eslint-plugin-storybook": "^10.0.8",

View File

@@ -8,7 +8,7 @@
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"lint": "eslint . --max-warnings 0 && tsgo --noEmit", "lint": "eslint . --max-warnings 0",
"format": "prettier --write ." "format": "prettier --write ."
}, },
"exports": { "exports": {

View File

@@ -5,8 +5,8 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"check-types": "tsgo --noEmit", "check-types": "tsgo --noEmit",
"lint": "eslint . --max-warnings 0 && tsgo --noEmit", "lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix && tsgo --noEmit", "lint:fix": "eslint . --fix",
"test": "vitest run", "test": "vitest run",
"test:watch": "vitest", "test:watch": "vitest",
"format": "prettier --write ." "format": "prettier --write ."

View File

@@ -5314,6 +5314,7 @@ __metadata:
eslint: "npm:^9" eslint: "npm:^9"
eslint-plugin-formatjs: "npm:^5.3.1" eslint-plugin-formatjs: "npm:^5.3.1"
eslint-plugin-import: "npm:^2.31.0" eslint-plugin-import: "npm:^2.31.0"
eslint-plugin-react: "npm:^7.37.5"
eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-react-hooks: "npm:^5.2.0"
eslint-plugin-react-refresh: "npm:^0.4.20" eslint-plugin-react-refresh: "npm:^0.4.20"
eslint-plugin-storybook: "npm:^10.0.8" eslint-plugin-storybook: "npm:^10.0.8"
@@ -10424,7 +10425,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-react@npm:^7.37.0": "eslint-plugin-react@npm:^7.37.0, eslint-plugin-react@npm:^7.37.5":
version: 7.37.5 version: 7.37.5
resolution: "eslint-plugin-react@npm:7.37.5" resolution: "eslint-plugin-react@npm:7.37.5"
dependencies: dependencies: