feat: upgrade to tailwindcss v4

This commit is contained in:
Aarnav Tale
2025-05-29 09:45:47 -04:00
parent e173376319
commit b7009e387b
31 changed files with 374 additions and 1228 deletions
+3 -3
View File
@@ -38,7 +38,7 @@ export default function Attribute({
'min-w-0 px-1.5 py-1 rounded-lg border border-transparent',
...(isCopyable
? [
'cursor-pointer hover:shadow-sm',
'cursor-pointer hover:shadow-xs',
'hover:bg-headplane-50 dark:hover:bg-headplane-800',
'hover:border-headplane-100 dark:hover:border-headplane-700',
]
@@ -70,8 +70,8 @@ export default function Attribute({
</div>
{isCopyable ? (
<div>
<Check className="size-4 hidden data-[copied]:block" />
<Copy className="size-4 block data-[copied]:hidden" />
<Check className="size-4 hidden data-copied:block" />
<Copy className="size-4 block data-copied:hidden" />
</div>
) : undefined}
</button>
+1 -1
View File
@@ -20,7 +20,7 @@ export default function Button({ variant = 'light', ...props }: ButtonProps) {
{...buttonProps}
className={cn(
'w-fit text-sm rounded-xl px-3 py-2',
'focus:outline-none focus:ring',
'focus:outline-hidden focus:ring-3',
props.isDisabled && 'opacity-60 cursor-not-allowed',
...(variant === 'heavy'
? [
+1 -1
View File
@@ -15,7 +15,7 @@ function Card({ variant = 'raised', ...props }: Props) {
'w-full max-w-md rounded-3xl p-5',
variant === 'flat'
? 'bg-transparent shadow-none'
: 'bg-headplane-50/50 dark:bg-headplane-950/50 shadow-sm',
: 'bg-headplane-50/50 dark:bg-headplane-950/50 shadow-xs',
'border border-headplane-100 dark:border-headplane-800',
props.className,
)}
+3 -3
View File
@@ -13,7 +13,7 @@ export default function Code({ isCopyable, children, className }: CodeProps) {
<code
className={cn(
'bg-headplane-100 dark:bg-headplane-800 px-1 py-0.5 font-mono',
'rounded-lg focus-within:outline-none focus-within:ring-2',
'rounded-lg focus-within:outline-hidden focus-within:ring-2',
isCopyable && 'relative pr-7',
className,
)}
@@ -41,8 +41,8 @@ export default function Code({ isCopyable, children, className }: CodeProps) {
}, 1000);
}}
>
<Check className="h-4.5 w-4.5 p-1 hidden data-[copied]:block" />
<Copy className="h-4.5 w-4.5 p-1 block data-[copied]:hidden" />
<Check className="h-4.5 w-4.5 p-1 hidden data-copied:block" />
<Copy className="h-4.5 w-4.5 p-1 block data-copied:hidden" />
</button>
)}
</code>
+1 -1
View File
@@ -117,7 +117,7 @@ function Panel(props: DialogPanelProps) {
method={method ?? 'POST'}
ref={ref}
className={cn(
'outline-none rounded-3xl w-full max-w-lg',
'outline-hidden rounded-3xl w-full max-w-lg',
'bg-white dark:bg-headplane-900',
)}
>
+1 -1
View File
@@ -46,7 +46,7 @@ export default function Footer({ url, debug, healthy }: FooterProps) {
tabIndex={0} // Allows keyboard focus
className={cn(
'blur-sm hover:blur-none focus:blur-none transition',
'focus:outline-none focus:ring-2 rounded-sm',
'focus:outline-hidden focus:ring-2 rounded-xs',
)}
>
{url}
+2 -2
View File
@@ -50,7 +50,7 @@ function TabLink({ name, to, icon }: TabLinkProps) {
'after:absolute after:bottom-0 after:left-3 after:right-3',
'after:h-0.5 after:bg-headplane-900 dark:after:bg-headplane-200',
'hover:bg-headplane-200 dark:hover:bg-headplane-900',
'focus:outline-none focus:ring',
'focus:outline-hidden focus:ring-3',
isActive ? 'after:visible' : 'after:invisible',
)
}
@@ -69,7 +69,7 @@ function Link({ href, text }: LinkProps) {
rel="noreferrer"
className={cn(
'hidden sm:block hover:underline text-sm',
'focus:outline-none focus:ring rounded-md',
'focus:outline-hidden focus:ring-3 rounded-md',
)}
>
{text}
+1 -1
View File
@@ -25,7 +25,7 @@ export default function IconButton({
aria-label={props.label}
className={cn(
'rounded-full flex items-center justify-center p-1',
'focus:outline-none focus:ring',
'focus:outline-hidden focus:ring-3',
props.isDisabled && 'opacity-60 cursor-not-allowed',
...(variant === 'heavy'
? [
+1 -1
View File
@@ -54,7 +54,7 @@ export default function Input(props: InputProps) {
ref={ref}
className={cn(
'rounded-xl px-3 py-2',
'focus:outline-none focus:ring',
'focus:outline-hidden focus:ring-3',
'bg-white dark:bg-headplane-900',
'border border-headplane-100 dark:border-headplane-800',
className,
+1 -1
View File
@@ -24,7 +24,7 @@ export default function Link({
'inline-flex items-center gap-x-0.5',
'text-blue-500 hover:text-blue-700',
'dark:text-blue-400 dark:hover:text-blue-300',
'focus:outline-none focus:ring rounded-md',
'focus:outline-hidden focus:ring-3 rounded-md',
className,
)}
>
+2 -2
View File
@@ -74,7 +74,7 @@ function Panel(props: MenuPanelProps) {
<ul
{...menuProps}
ref={ref}
className="pt-1 pb-1 shadow-xs rounded-md min-w-[200px] focus:outline-none"
className="pt-1 pb-1 shadow-2xs rounded-md min-w-[200px] focus:outline-hidden"
>
{[...state.collection].map((item) => (
<MenuSection
@@ -149,7 +149,7 @@ function MenuItem<T>({ item, state, isDisabled }: MenuItemProps<T>) {
ref={ref}
className={cn(
'py-2 px-3 mx-1 rounded-lg',
'focus:outline-none select-none',
'focus:outline-hidden select-none',
isFocused && 'bg-headplane-100/50 dark:bg-headplane-800',
isDisabled
? 'text-headplane-400 dark:text-headplane-600'
+2 -2
View File
@@ -50,7 +50,7 @@ export default function NumberInput(props: InputProps) {
{...groupProps}
className={cn(
'flex items-center gap-1 rounded-xl pr-1',
'focus-within:outline-none focus-within:ring',
'focus-within:outline-hidden focus-within:ring-3',
'bg-white dark:bg-headplane-900',
'border border-headplane-100 dark:border-headplane-800',
)}
@@ -60,7 +60,7 @@ export default function NumberInput(props: InputProps) {
required={props.isRequired}
ref={ref}
id={id}
className="w-full pl-3 py-2 rounded-l-xl bg-transparent focus:outline-none"
className="w-full pl-3 py-2 rounded-l-xl bg-transparent focus:outline-hidden"
/>
<input type="hidden" name={name} value={state.numberValue} />
<IconButton
+1 -1
View File
@@ -52,7 +52,7 @@ function Option({ item, state }: OptionsOptionProps) {
className={cn(
'pl-0.5 pr-2 py-0.5 rounded-lg cursor-pointer',
'aria-selected:bg-headplane-100 dark:aria-selected:bg-headplane-950',
'focus:outline-none focus:ring z-10',
'focus:outline-hidden focus:ring-3 z-10',
'border border-headplane-100 dark:border-headplane-800',
)}
>
+1 -1
View File
@@ -34,7 +34,7 @@ export default function Popover(props: PopoverProps) {
{...popoverProps}
ref={ref}
className={cn(
'z-10 shadow-sm rounded-xl',
'z-10 shadow-xs rounded-xl',
'bg-white dark:bg-headplane-900',
'border border-headplane-200 dark:border-headplane-800',
className,
+4 -4
View File
@@ -60,7 +60,7 @@ function Select(props: SelectProps) {
</label>
<div
className={cn(
'flex rounded-xl focus:outline-none focus-within:ring',
'flex rounded-xl focus:outline-hidden focus-within:ring-3',
'bg-white dark:bg-headplane-900',
'border border-headplane-100 dark:border-headplane-800',
)}
@@ -69,7 +69,7 @@ function Select(props: SelectProps) {
{...inputProps}
ref={inputRef}
id={id}
className="outline-none px-3 py-2 rounded-l-xl w-full bg-transparent"
className="outline-hidden px-3 py-2 rounded-l-xl w-full bg-transparent"
data-1p-ignore
/>
<button
@@ -127,7 +127,7 @@ function ListBox(props: ListBoxProps) {
<ul
{...listBoxProps}
ref={listBoxRef}
className="w-full max-h-72 overflow-auto outline-none pt-1"
className="w-full max-h-72 overflow-auto outline-hidden pt-1"
>
{[...state.collection].map((item) => (
<Option key={item.key} item={item} state={state} />
@@ -158,7 +158,7 @@ function Option({ item, state }: OptionProps) {
className={cn(
'flex items-center justify-between',
'py-2 px-3 mx-1 rounded-lg mb-1',
'focus:outline-none select-none',
'focus:outline-hidden select-none',
isFocused || isSelected
? 'bg-headplane-100/50 dark:bg-headplane-800'
: 'hover:bg-headplane-100/50 dark:hover:bg-headplane-800',
+2 -2
View File
@@ -51,8 +51,8 @@ export default function Switch(props: SwitchProps) {
className={cn(
'h-[18px] w-[18px] transform rounded-full',
'bg-white transition duration-50 ease-in-out',
'translate-x-0 group-selected:translate-x-[100%]',
state.isSelected && 'translate-x-[100%]',
'translate-x-0 group-selected:translate-x-full',
state.isSelected && 'translate-x-full',
)}
/>
</div>
+1 -1
View File
@@ -56,7 +56,7 @@ function Tab({ item, state }: TabsTabProps) {
className={cn(
'pl-2 pr-3 py-2.5',
'aria-selected:bg-headplane-100 dark:aria-selected:bg-headplane-950',
'focus:outline-none focus:ring z-10',
'focus:outline-hidden focus:ring-3 z-10',
'border-r border-headplane-100 dark:border-headplane-800',
'first:rounded-tl-xl last:rounded-tr-xl last:border-r-0',
)}
+2 -2
View File
@@ -38,7 +38,7 @@ function Tooltip(props: TooltipProps) {
{...triggerProps}
className={cn(
'flex items-center justify-center',
'focus:outline-none focus:ring rounded-xl',
'focus:outline-hidden focus:ring-3 rounded-xl',
)}
>
{component}
@@ -65,7 +65,7 @@ function Body({ state, className, ...props }: TooltipBodyProps) {
{...mergeProps(props, tooltipProps)}
className={cn(
'absolute z-50 p-3 top-full mt-1',
'outline-none rounded-3xl text-sm w-48',
'outline-hidden rounded-3xl text-sm w-48',
'bg-white dark:bg-headplane-950',
'text-black dark:text-white',
'shadow-lg dark:shadow-md rounded-xl',
+2 -2
View File
@@ -167,7 +167,7 @@ function Domain({ domain, id, isDragging, isDisabled }: DomainProps) {
ref={setNodeRef}
className={cn(
isSortableDragging ? 'opacity-50' : '',
isDragging ? 'ring bg-white dark:bg-headplane-900' : '',
isDragging ? 'ring-3 bg-white dark:bg-headplane-900' : '',
)}
style={{
transform: CSS.Transform.toString(transform),
@@ -179,7 +179,7 @@ function Domain({ domain, id, isDragging, isDisabled }: DomainProps) {
<GripVertical
{...attributes}
{...listeners}
className="p-0.5 focus:ring outline-none rounded-md"
className="p-0.5 focus:ring-3 outline-hidden rounded-md"
/>
)}
{domain}
+1 -1
View File
@@ -70,7 +70,7 @@ export default function Page() {
const isDisabled = data.access === false || data.writable === false;
return (
<div className="flex flex-col gap-16 max-w-screen-lg">
<div className="flex flex-col gap-16 max-w-(--breakpoint-lg)">
{data.writable ? undefined : (
<Notice>
The Headscale configuration is read-only. You cannot make changes to
@@ -49,16 +49,16 @@ export default function MachineRow({
key={node.id}
className="group hover:bg-headplane-50 dark:hover:bg-headplane-950"
>
<td className="pl-0.5 py-2 focus-within:ring">
<td className="pl-0.5 py-2 focus-within:ring-3">
<Link
to={`/machines/${node.id}`}
className={cn('group/link h-full focus:outline-none')}
className={cn('group/link h-full focus:outline-hidden')}
>
<p
className={cn(
'font-semibold leading-snug',
'group-hover/link:text-blue-600',
'group-hover/link:dark:text-blue-400',
'dark:group-hover/link:text-blue-400',
)}
>
{node.givenName}
+2 -2
View File
@@ -59,10 +59,10 @@ export default function Tags({ machine, isOpen, setIsOpen }: TagsProps) {
)}
<TableList.Item
className={cn(
'rounded-b-xl focus-within:ring',
'rounded-b-xl focus-within:ring-3',
tag.length > 0 &&
(!tag.startsWith('tag:') || tags.includes(tag)) &&
'ring ring-red-500 ring-opacity-50',
'ring-3 ring-red-500 ring-opacity-50',
)}
>
<Input
+1 -1
View File
@@ -29,7 +29,7 @@ export default function Page() {
}, [data.configured, data.onboarding]);
return (
<div className="flex flex-col gap-8 max-w-screen-lg">
<div className="flex flex-col gap-8 max-w-(--breakpoint-lg)">
{management ? (
<AgentManagement reachable={true} hostInfo={data.stats} />
) : (
+1 -1
View File
@@ -18,7 +18,7 @@ export default function Page() {
const { config, oidc } = useLoaderData<typeof loader>();
return (
<div className="flex flex-col gap-8 max-w-screen-lg">
<div className="flex flex-col gap-8 max-w-(--breakpoint-lg)">
<div className="flex flex-col w-2/3">
<h1 className="text-2xl font-medium mb-4">Settings</h1>
<p>
@@ -52,7 +52,7 @@ export default function Page() {
const isDisabled = writable ? !access : true;
return (
<div className="flex flex-col gap-4 max-w-screen-lg">
<div className="flex flex-col gap-4 max-w-(--breakpoint-lg)">
<div className="flex flex-col w-2/3">
<p className="mb-4 text-md">
<RemixLink to="/settings" className="font-medium">
+88 -3
View File
@@ -1,6 +1,91 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@plugin "tailwindcss-animate";
@plugin "tailwindcss-react-aria-components";
@theme {
--blur-xs: 2px;
--height-editor: calc(100vh - 20rem);
--font-sans: Inter, -apple-system, BlinkMacSystemFont, Helvetica, Arial,
sans-serif;
--transition-duration-25: 25ms;
--transition-duration-50: 50ms;
--color-main-50: #f8fafc;
--color-main-100: #f1f5f9;
--color-main-200: #e2e8f0;
--color-main-300: #cbd5e1;
--color-main-400: #94a3b8;
--color-main-500: #64748b;
--color-main-600: #475569;
--color-main-700: #334155;
--color-main-800: #1e293b;
--color-main-900: #0f172a;
--color-main-950: #020617;
--color-ui-50: #fafafa;
--color-ui-100: #f5f5f5;
--color-ui-200: #e5e5e5;
--color-ui-300: #d4d4d4;
--color-ui-400: #a3a3a3;
--color-ui-500: #737373;
--color-ui-600: #525252;
--color-ui-700: #404040;
--color-ui-800: #262626;
--color-ui-900: #171717;
--color-ui-950: #0a0a0a;
--color-headplane-50: #f2f2f2;
--color-headplane-100: #e6e6e6;
--color-headplane-200: #cccccc;
--color-headplane-300: #b3b3b3;
--color-headplane-400: #999999;
--color-headplane-500: #808080;
--color-headplane-600: #666666;
--color-headplane-700: #4d4d4d;
--color-headplane-800: #343434;
--color-headplane-900: #1a1a1a;
--color-headplane-950: #0d0d0d;
--animate-loading: loader 0.8s infinite ease-in-out;
@keyframes loader {
from {
transform: translateX(-100%);
}
to {
transform: translateX(100%);
}
}
}
@utility container {
margin-inline: auto;
padding-inline: 1rem;
/* biome-ignore lint/correctness/noUnknownFunction: Tailwind CSS */
@media (width >= theme(--breakpoint-sm)) {
padding-inline: 2rem;
}
/* biome-ignore lint/correctness/noUnknownFunction: Tailwind CSS */
@media (width >= theme(--breakpoint-lg)) {
padding-inline: 4rem;
}
/* biome-ignore lint/correctness/noUnknownFunction: Tailwind CSS */
@media (width >= theme(--breakpoint-xl)) {
padding-inline: 5rem;
}
/* biome-ignore lint/correctness/noUnknownFunction: Tailwind CSS */
@media (width >= theme(--breakpoint-2xl)) {
padding-inline: 6rem;
}
}
@supports (scrollbar-gutter: stable) {
html {
+6 -7
View File
@@ -22,7 +22,7 @@
"@react-aria/toast": "3.0.3",
"@react-router/node": "^7.6.1",
"@react-stately/toast": "3.1.0",
"@shopify/lang-jsonc": "^1.0.0",
"@shopify/lang-jsonc": "^1.0.1",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"@uiw/codemirror-theme-github": "^4.23.12",
@@ -45,25 +45,25 @@
"react-router-hono-server": "^2.13.0",
"react-stately": "^3.38.0",
"remix-utils": "^8.7.0",
"tailwind-merge": "^2.6.0",
"tailwind-merge": "^3.3.0",
"undici": "^7.10.0",
"usehooks-ts": "^3.1.0",
"usehooks-ts": "^3.1.1",
"yaml": "^2.8.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@react-router/dev": "^7.6.1",
"@tailwindcss/vite": "^4.1.8",
"@types/websocket": "^1.0.10",
"autoprefixer": "^10.4.21",
"lefthook": "^1.11.13",
"postcss": "^8.5.4",
"react-router-dom": "^7.6.1",
"react-scan": "^0.3.4",
"tailwindcss": "^3.4.17",
"tailwindcss": "^4.1.8",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-react-aria-components": "^2.0.0",
"typescript": "^5.8.3",
"vite": "npm:rolldown-vite@latest",
"vite": "^6.3.5",
"vite-tsconfig-paths": "^5.1.4"
},
"packageManager": "pnpm@10.4.0",
@@ -73,7 +73,6 @@
},
"pnpm": {
"patchedDependencies": {
"@shopify/lang-jsonc@1.0.0": "patches/@shopify__lang-jsonc@1.0.0.patch",
"react-router-hono-server": "patches/react-router-hono-server.patch"
},
"onlyBuiltDependencies": ["@biomejs/biome", "esbuild", "lefthook"]
-44
View File
@@ -1,44 +0,0 @@
diff --git a/dist/esm/index.js b/dist/esm/index.js
index 8b5b71f8eee6606ca8de47c15eef0ce73c01d93f..2bfa4e7c7ff650b35b1bdee75c28bd6fbf6c6704 100644
--- a/dist/esm/index.js
+++ b/dist/esm/index.js
@@ -1,3 +1,3 @@
-export { jsonc, jsoncLanguage } from './jsonc';
-export { parser } from './parser';
+export { jsonc, jsoncLanguage } from './jsonc.js';
+export { parser } from './parser.js';
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/dist/esm/jsonc.js b/dist/esm/jsonc.js
index 5f968887d47696122c6bbfc4b98f94af6477f37a..b144021c4b5d4504c73f6c2172e8d1c2ddbfe3ac 100644
--- a/dist/esm/jsonc.js
+++ b/dist/esm/jsonc.js
@@ -1,4 +1,4 @@
-import { parser } from './parser';
+import { parser } from './parser.js';
import { continuedIndent, indentNodeProp, foldNodeProp, foldInside, LRLanguage, LanguageSupport, } from '@codemirror/language';
/// A language provider that provides JSON parsing.
export const jsoncLanguage = LRLanguage.define({
diff --git a/dist/esm/parser.js b/dist/esm/parser.js
index 3d966fcf7c55003b1ba6c2b3f531b7c9b8045cb8..f6e8f56c3506f76f31571a49af8cd44364a864a3 100644
--- a/dist/esm/parser.js
+++ b/dist/esm/parser.js
@@ -1,6 +1,6 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr"
-import {jsonHighlighting} from "./highlight"
+import {jsonHighlighting} from "./highlight.js"
export const parser = LRParser.deserialize({
version: 14,
states: "$zO]QPOOOOQO'#Cd'#CdOtQPO'#CgO|QPO'#ClOOQO'#Cr'#CrQOQPOOOOQO'#Ci'#CiO!TQPO'#ChO!YQPO'#CtOOQO,59R,59RO!bQPO,59RO!gQPO'#CwOOQO,59W,59WO!oQPO,59WO]QPO,59SO!tQPO,59`O!|QPO,59`OOQO1G.m1G.mO#UQPO,59cO#]QPO,59cOOQO1G.r1G.rOOQO1G.n1G.nOOQO,59X,59XO#eQPO1G.zOOQO-E6k-E6kOOQO,59Y,59YO#mQPO1G.}OOQO-E6l-E6lPwQPO'#CmP]QPO'#Cn",
diff --git a/package.json b/package.json
index 9c3a56db25535b7eb0b1f951abe486d530a2714f..5e858500f155c16ecb068854552a71e1da5f04fc 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"name": "@shopify/lang-jsonc",
+ "type": "module",
"version": "1.0.0",
"description": "JSONC language support for CodeMirror",
"publishConfig": {
+232 -1051
View File
File diff suppressed because it is too large Load Diff
-74
View File
@@ -1,74 +0,0 @@
/* eslint-disable @typescript-eslint/naming-convention */
import type { Config } from 'tailwindcss';
import colors from 'tailwindcss/colors';
import animate from 'tailwindcss-animate';
import aria from 'tailwindcss-react-aria-components';
export default {
content: ['./app/**/*.{js,jsx,ts,tsx}'],
theme: {
container: {
center: true,
padding: {
DEFAULT: '1rem',
sm: '2rem',
lg: '4rem',
xl: '5rem',
'2xl': '6rem',
},
},
extend: {
blur: {
xs: '2px',
},
height: {
editor: 'calc(100vh - 20rem)',
},
fontFamily: {
sans: [
'Inter',
'-apple-system',
'BlinkMacSystemFont',
'Helvetica',
'Arial',
'sans-serif',
],
},
transitionDuration: {
25: '25ms',
50: '50ms',
},
colors: {
main: colors.slate,
ui: colors.neutral,
headplane: {
50: '#F2F2F2',
100: '#E6E6E6',
200: '#CCCCCC',
300: '#B3B3B3',
400: '#999999',
500: '#808080',
600: '#666666',
700: '#4D4D4D',
800: '#343434',
900: '#1A1A1A',
950: '#0D0D0D',
},
},
keyframes: {
loader: {
from: {
transform: 'translateX(-100%)',
},
to: {
transform: 'translateX(100%)',
},
},
},
animation: {
loading: 'loader 0.8s infinite ease-in-out',
},
},
},
plugins: [animate, aria],
} satisfies Config;
+7 -8
View File
@@ -1,8 +1,7 @@
import { readFile } from 'node:fs/promises';
import { reactRouter } from '@react-router/dev/vite';
import autoprefixer from 'autoprefixer';
import tailwindcss from '@tailwindcss/vite';
import { reactRouterHonoServer } from 'react-router-hono-server/dev';
import tailwindcss from 'tailwindcss';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { parse } from 'yaml';
@@ -25,16 +24,16 @@ const { server } = parse(config);
export default defineConfig(({ isSsrBuild }) => ({
base: isSsrBuild ? `${prefix}/` : undefined,
plugins: [reactRouterHonoServer(), reactRouter(), tsconfigPaths()],
plugins: [
reactRouterHonoServer(),
reactRouter(),
tailwindcss(),
tsconfigPaths(),
],
server: {
host: server.host,
port: server.port,
},
css: {
postcss: {
plugins: [tailwindcss, autoprefixer],
},
},
ssr: {
target: 'node',
noExternal: isSsrBuild ? true : undefined,