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,11 +1,11 @@
import { useIntl } from 'react-intl'
import { useIntl } from "react-intl"
import { passwordValidators } from '@scandic-hotels/common/utils/zod/passwordValidator'
import type { PasswordValidatorKey } from '@scandic-hotels/common/utils/zod/newPassword'
import { MaterialIcon } from '../Icons/MaterialIcon'
import { Typography } from '../Typography'
import { passwordValidators } from "@scandic-hotels/common/utils/zod/passwordValidator"
import type { PasswordValidatorKey } from "@scandic-hotels/common/utils/zod/newPassword"
import { MaterialIcon } from "../Icons/MaterialIcon"
import { Typography } from "../Typography"
import styles from './passwordInput.module.css'
import styles from "./passwordInput.module.css"
export function NewPasswordValidation({
value,
@@ -22,53 +22,53 @@ export function NewPasswordValidation({
function getErrorMessage(key: PasswordValidatorKey) {
switch (key) {
case 'length':
case "length":
return intl.formatMessage(
{
id: 'passwordInput.lengthRequirement',
defaultMessage: '{min} to {max} characters',
id: "passwordInput.lengthRequirement",
defaultMessage: "{min} to {max} characters",
},
{
min: 10,
max: 40,
}
)
case 'hasUppercase':
case "hasUppercase":
return intl.formatMessage(
{
id: 'passwordInput.uppercaseRequirement',
defaultMessage: '{count} uppercase letter',
id: "passwordInput.uppercaseRequirement",
defaultMessage: "{count} uppercase letter",
},
{ count: 1 }
)
case 'hasLowercase':
case "hasLowercase":
return intl.formatMessage(
{
id: 'passwordInput.lowercaseRequirement',
defaultMessage: '{count} lowercase letter',
id: "passwordInput.lowercaseRequirement",
defaultMessage: "{count} lowercase letter",
},
{ count: 1 }
)
case 'hasNumber':
case "hasNumber":
return intl.formatMessage(
{
id: 'passwordInput.numberRequirement',
defaultMessage: '{count} number',
id: "passwordInput.numberRequirement",
defaultMessage: "{count} number",
},
{ count: 1 }
)
case 'hasSpecialChar':
case "hasSpecialChar":
return intl.formatMessage(
{
id: 'passwordInput.specialCharacterRequirement',
defaultMessage: '{count} special character',
id: "passwordInput.specialCharacterRequirement",
defaultMessage: "{count} special character",
},
{ count: 1 }
)
case 'allowedCharacters':
case "allowedCharacters":
return intl.formatMessage({
id: 'passwordInput.allowedCharactersRequirement',
defaultMessage: 'Only allowed characters',
id: "passwordInput.allowedCharactersRequirement",
defaultMessage: "Only allowed characters",
})
}
}
@@ -107,8 +107,8 @@ function Icon({ errorMessage, errors }: IconProps) {
size={20}
role="img"
aria-label={intl.formatMessage({
id: 'common.error',
defaultMessage: 'Error',
id: "common.error",
defaultMessage: "Error",
})}
/>
) : (
@@ -118,8 +118,8 @@ function Icon({ errorMessage, errors }: IconProps) {
size={20}
role="img"
aria-label={intl.formatMessage({
id: 'common.success',
defaultMessage: 'Success',
id: "common.success",
defaultMessage: "Success",
})}
/>
)

View File

@@ -1,21 +1,21 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { fn } from 'storybook/test'
import { useEffect } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import type { IntlShape } from 'react-intl'
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from "storybook/test"
import { useEffect } from "react"
import { FormProvider, useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import type { IntlShape } from "react-intl"
import { PasswordInput } from './index'
import { Button } from '../Button'
import { Typography } from '../Typography'
import { passwordValidator } from '@scandic-hotels/common/utils/zod/passwordValidator'
import { PasswordInput } from "./index"
import { Button } from "../Button"
import { Typography } from "../Typography"
import { passwordValidator } from "@scandic-hotels/common/utils/zod/passwordValidator"
// Simple error formatter for Storybook
const defaultErrorFormatter = (
_intl: IntlShape,
errorMessage?: string
): string => errorMessage ?? ''
): string => errorMessage ?? ""
// ============================================================================
// Password Form with New Password Validation
@@ -24,15 +24,15 @@ const defaultErrorFormatter = (
const passwordFormSchema = z
.object({
currentPassword: z.string().optional(),
newPassword: z.literal('').optional().or(passwordValidator()),
newPassword: z.literal("").optional().or(passwordValidator()),
confirmPassword: z.string().optional(),
})
.superRefine((data, ctx) => {
if (data.newPassword && data.newPassword !== data.confirmPassword) {
ctx.addIssue({
code: 'custom',
message: 'Passwords do not match',
path: ['confirmPassword'],
code: "custom",
message: "Passwords do not match",
path: ["confirmPassword"],
})
}
})
@@ -48,18 +48,18 @@ interface PasswordInputProps {
function PasswordInputComponent({
onSubmit,
showErrors = false,
defaultNewPassword = '',
defaultNewPassword = "",
}: PasswordInputProps) {
const methods = useForm<PasswordFormData>({
resolver: zodResolver(passwordFormSchema),
defaultValues: {
currentPassword: '',
currentPassword: "",
newPassword: defaultNewPassword,
confirmPassword: '',
confirmPassword: "",
},
mode: 'all',
criteriaMode: 'all',
reValidateMode: 'onChange',
mode: "all",
criteriaMode: "all",
reValidateMode: "onChange",
})
// Trigger validation on mount if showErrors is true
@@ -78,10 +78,10 @@ function PasswordInputComponent({
<form
onSubmit={handleSubmit}
style={{
display: 'flex',
flexDirection: 'column',
gap: '1.5rem',
maxWidth: '500px',
display: "flex",
flexDirection: "column",
gap: "1.5rem",
maxWidth: "500px",
}}
>
<Typography variant="Title/md">
@@ -115,19 +115,19 @@ function PasswordInputComponent({
}
const passwordFormMeta: Meta<typeof PasswordInputComponent> = {
title: 'Core Components/PasswordInput',
title: "Core Components/PasswordInput",
component: PasswordInputComponent,
parameters: {
layout: 'padded',
layout: "padded",
},
argTypes: {
showErrors: {
control: 'boolean',
description: 'Show validation errors on mount',
control: "boolean",
description: "Show validation errors on mount",
},
defaultNewPassword: {
control: 'text',
description: 'Default value for new password field',
control: "text",
description: "Default value for new password field",
},
},
}
@@ -141,7 +141,7 @@ export const Default: PasswordFormStory = {
args: {
onSubmit: fn(),
showErrors: false,
defaultNewPassword: '',
defaultNewPassword: "",
},
}
@@ -150,7 +150,7 @@ export const Default: PasswordFormStory = {
// ============================================================================
const showcasePasswordSchema = z.object({
empty: z.literal('').optional().or(passwordValidator()),
empty: z.literal("").optional().or(passwordValidator()),
weak: passwordValidator(),
partial: passwordValidator(),
valid: passwordValidator(),
@@ -163,31 +163,31 @@ function PasswordValidationShowcase() {
const methods = useForm<ShowcasePasswordFormData>({
resolver: zodResolver(showcasePasswordSchema),
defaultValues: {
empty: '',
weak: 'weak',
partial: 'Password1',
valid: 'ValidPassword123!',
tooLong: 'A'.repeat(41) + '1!',
empty: "",
weak: "weak",
partial: "Password1",
valid: "ValidPassword123!",
tooLong: "A".repeat(41) + "1!",
},
mode: 'all',
criteriaMode: 'all',
reValidateMode: 'onChange',
mode: "all",
criteriaMode: "all",
reValidateMode: "onChange",
})
// Trigger validation on mount to show validation states
useEffect(() => {
methods.trigger(['weak', 'partial', 'valid', 'tooLong'])
methods.trigger(["weak", "partial", "valid", "tooLong"])
}, [methods])
return (
<FormProvider {...methods}>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '3rem',
maxWidth: '800px',
padding: '2rem',
display: "flex",
flexDirection: "column",
gap: "3rem",
maxWidth: "800px",
padding: "2rem",
}}
>
<section>
@@ -196,10 +196,10 @@ function PasswordValidationShowcase() {
</Typography>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(350px, 1fr))',
gap: '2rem',
marginTop: '1rem',
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(350px, 1fr))",
gap: "2rem",
marginTop: "1rem",
}}
>
<div>
@@ -264,10 +264,10 @@ function PasswordValidationShowcase() {
}
const showcaseMeta: Meta<typeof PasswordValidationShowcase> = {
title: 'Core Components/PasswordInput',
title: "Core Components/PasswordInput",
component: PasswordValidationShowcase,
parameters: {
layout: 'fullscreen',
layout: "fullscreen",
},
}

View File

@@ -1,9 +1,9 @@
import { describe, expect, it, afterEach } from 'vitest'
import { render, screen, cleanup } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { FormProvider, useForm } from 'react-hook-form'
import { IntlProvider } from 'react-intl'
import { PasswordInput } from './PasswordInput'
import { describe, expect, it, afterEach } from "vitest"
import { render, screen, cleanup } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { FormProvider, useForm } from "react-hook-form"
import { IntlProvider } from "react-intl"
import { PasswordInput } from "./PasswordInput"
afterEach(() => {
cleanup()
@@ -11,7 +11,7 @@ afterEach(() => {
function FormWrapper({
children,
defaultValues = { password: '' },
defaultValues = { password: "" },
}: {
children: React.ReactNode
defaultValues?: Record<string, string>
@@ -37,63 +37,63 @@ const renderPasswordInput = (
)
}
describe('PasswordInput', () => {
describe('rendering', () => {
it('renders with default password label', () => {
describe("PasswordInput", () => {
describe("rendering", () => {
it("renders with default password label", () => {
renderPasswordInput()
expect(screen.getByLabelText('Password')).toBeTruthy()
expect(screen.getByLabelText("Password")).toBeTruthy()
})
it('renders with custom label', () => {
renderPasswordInput({ label: 'Enter your password' })
expect(screen.getByLabelText('Enter your password')).toBeTruthy()
it("renders with custom label", () => {
renderPasswordInput({ label: "Enter your password" })
expect(screen.getByLabelText("Enter your password")).toBeTruthy()
})
it('renders with new password label when isNewPassword is true', () => {
it("renders with new password label when isNewPassword is true", () => {
renderPasswordInput({ isNewPassword: true })
expect(screen.getByLabelText('New password')).toBeTruthy()
expect(screen.getByLabelText("New password")).toBeTruthy()
})
})
describe('visibility toggle', () => {
it('shows visibility toggle button by default', () => {
describe("visibility toggle", () => {
it("shows visibility toggle button by default", () => {
renderPasswordInput()
expect(screen.getByLabelText('Show password')).toBeTruthy()
expect(screen.getByLabelText("Show password")).toBeTruthy()
})
it('hides visibility toggle when visibilityToggleable is false', () => {
it("hides visibility toggle when visibilityToggleable is false", () => {
renderPasswordInput({ visibilityToggleable: false })
expect(screen.queryByLabelText('Show password')).toBeNull()
expect(screen.queryByLabelText('Hide password')).toBeNull()
expect(screen.queryByLabelText("Show password")).toBeNull()
expect(screen.queryByLabelText("Hide password")).toBeNull()
})
})
describe('disabled state', () => {
it('disables the input when disabled prop is true', () => {
describe("disabled state", () => {
it("disables the input when disabled prop is true", () => {
renderPasswordInput({ disabled: true })
expect(screen.getByLabelText('Password')).toHaveProperty('disabled', true)
expect(screen.getByLabelText("Password")).toHaveProperty("disabled", true)
})
})
describe('form integration', () => {
it('updates form value when typing', async () => {
describe("form integration", () => {
it("updates form value when typing", async () => {
const user = userEvent.setup()
renderPasswordInput()
const input = screen.getByLabelText('Password')
await user.type(input, 'secret123')
const input = screen.getByLabelText("Password")
await user.type(input, "secret123")
expect(input).toHaveProperty('value', 'secret123')
expect(input).toHaveProperty("value", "secret123")
})
it('uses custom name prop', async () => {
it("uses custom name prop", async () => {
const user = userEvent.setup()
renderPasswordInput({ name: 'confirmPassword' }, { confirmPassword: '' })
renderPasswordInput({ name: "confirmPassword" }, { confirmPassword: "" })
const input = screen.getByLabelText('Password')
await user.type(input, 'test')
const input = screen.getByLabelText("Password")
await user.type(input, "test")
expect(input).toHaveProperty('value', 'test')
expect(input).toHaveProperty("value", "test")
})
})
})

View File

@@ -1,26 +1,26 @@
'use client'
"use client"
import { useState } from 'react'
import { TextField } from 'react-aria-components'
import { useState } from "react"
import { TextField } from "react-aria-components"
import {
Controller,
type RegisterOptions,
useFormContext,
} from 'react-hook-form'
import { useIntl, type IntlShape } from 'react-intl'
} from "react-hook-form"
import { useIntl, type IntlShape } from "react-intl"
import { MaterialIcon } from '../Icons/MaterialIcon'
import { Input } from '../Input'
import { Typography } from '../Typography'
import { MaterialIcon } from "../Icons/MaterialIcon"
import { Input } from "../Input"
import { Typography } from "../Typography"
import { NewPasswordValidation } from './NewPasswordValidation'
import { NewPasswordValidation } from "./NewPasswordValidation"
import styles from './passwordInput.module.css'
import styles from "./passwordInput.module.css"
const defaultErrorFormatter = (
_intl: IntlShape,
errorMessage?: string
): string => errorMessage ?? ''
): string => errorMessage ?? ""
interface PasswordInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label?: string
@@ -31,15 +31,15 @@ interface PasswordInputProps extends React.InputHTMLAttributes<HTMLInputElement>
}
export const PasswordInput = ({
name = 'password',
name = "password",
label,
'aria-label': ariaLabel,
"aria-label": ariaLabel,
disabled = false,
placeholder,
registerOptions = {},
visibilityToggleable = true,
isNewPassword = false,
className = '',
className = "",
errorFormatter,
}: PasswordInputProps) => {
const { control } = useFormContext()
@@ -71,7 +71,7 @@ export const PasswordInput = ({
isNewPassword && field.value ? requirementsId : null,
]
.filter(Boolean)
.join(' ') || undefined
.join(" ") || undefined
const hasError = !!fieldState.error
const showRequirements = isNewPassword && !!field.value
@@ -91,7 +91,7 @@ export const PasswordInput = ({
validationBehavior="aria"
value={field.value}
type={
visibilityToggleable && isPasswordVisible ? 'text' : 'password'
visibilityToggleable && isPasswordVisible ? "text" : "password"
}
>
<div className={styles.inputWrapper}>
@@ -102,19 +102,19 @@ export const PasswordInput = ({
label ||
(isNewPassword
? intl.formatMessage({
id: 'passwordInput.newPasswordLabel',
defaultMessage: 'New password',
id: "passwordInput.newPasswordLabel",
defaultMessage: "New password",
})
: intl.formatMessage({
id: 'common.password',
defaultMessage: 'Password',
id: "common.password",
defaultMessage: "Password",
}))
}
placeholder={placeholder}
type={
visibilityToggleable && isPasswordVisible
? 'text'
: 'password'
? "text"
: "password"
}
/>
{visibilityToggleable ? (
@@ -124,12 +124,12 @@ export const PasswordInput = ({
aria-label={
isPasswordVisible
? intl.formatMessage({
id: 'passwordInput.hidePassword',
defaultMessage: 'Hide password',
id: "passwordInput.hidePassword",
defaultMessage: "Hide password",
})
: intl.formatMessage({
id: 'passwordInput.showPassword',
defaultMessage: 'Show password',
id: "passwordInput.showPassword",
defaultMessage: "Show password",
})
}
aria-controls={inputId}
@@ -137,7 +137,7 @@ export const PasswordInput = ({
className={styles.toggleButton}
>
<MaterialIcon
icon={isPasswordVisible ? 'visibility_off' : 'visibility'}
icon={isPasswordVisible ? "visibility_off" : "visibility"}
size={24}
/>
</button>
@@ -186,8 +186,8 @@ function ErrorMessage({
icon="info"
color="Icon/Feedback/Error"
aria-label={intl.formatMessage({
id: 'common.error',
defaultMessage: 'Error',
id: "common.error",
defaultMessage: "Error",
})}
/>
{formatErrorMessage(intl, errorMessage)}

View File

@@ -1 +1 @@
export { PasswordInput } from './PasswordInput'
export { PasswordInput } from "./PasswordInput"