From bccf4bbfbd2c4203e5673a6196f01c73e20dca98 Mon Sep 17 00:00:00 2001
From: Tim Neutkens
Date: Thu, 29 Jan 2026 15:16:31 +0100
Subject: [PATCH 01/40] Add @tailwindcss/webpack loader for Tailwind CSS v4
(#19610)
## Summary
This PR adds a new `@tailwindcss/webpack` package that provides a
dedicated webpack loader for Tailwind CSS v4. This loader works with
both standard webpack and Turbopack's webpack loader compatibility
layer.
### Why a dedicated loader?
The current webpack integration uses `postcss-loader` +
`@tailwindcss/postcss`. While this works, a dedicated loader:
- **Eliminates PostCSS as a middleman** - works directly with CSS
strings (no AST conversions)
- **Simpler and more efficient** - follows the same pattern as
`@tailwindcss/vite`
- **Better for Turbopack** - gives direct control over dependency
reporting via webpack's loader API
### How it works
The loader mirrors the Vite plugin's approach:
1. Uses `compile()` from `@tailwindcss/node` to parse CSS and resolve
`@apply` directives
2. Uses `Scanner` from `@tailwindcss/oxide` to scan content files for
utility candidates
3. Reports dependencies via `this.addDependency()` and
`this.addContextDependency()`
4. Optionally optimizes output with Lightning CSS
### Usage
```javascript
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'@tailwindcss/webpack', // No PostCSS needed!
],
},
],
},
}
```
### Options
- `base` - The base directory to scan for class candidates (defaults to
`process.cwd()`)
- `optimize` - Whether to optimize/minify the output CSS (defaults to
`true` in production)
### Files added
- `packages/@tailwindcss-webpack/` - New package
- `src/index.ts` - Main loader implementation
- `src/index.cts` - CommonJS entry point for webpack compatibility
- `package.json`, `tsconfig.json`, `tsup.config.ts`, `README.md`
- `integrations/webpack/loader.test.ts` - Integration tests
- `integrations/utils.ts` - Added webpack override for transitive
dependencies
### Test plan
- [x] Build test - verifies basic compilation
- [x] Watch test - verifies HMR when adding new Tailwind classes
- [x] `@apply` test - verifies `@apply` directives work correctly
- [x] Optimization test - verifies minification works
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
integrations/utils.ts | 1 +
integrations/webpack/loader.test.ts | 420 +++++++++++++++++
packages/@tailwindcss-postcss/README.md | 12 +-
packages/@tailwindcss-webpack/README.md | 64 +++
packages/@tailwindcss-webpack/package.json | 46 ++
packages/@tailwindcss-webpack/src/index.cts | 5 +
packages/@tailwindcss-webpack/src/index.ts | 282 ++++++++++++
packages/@tailwindcss-webpack/tsconfig.json | 3 +
packages/@tailwindcss-webpack/tsup.config.ts | 19 +
pnpm-lock.yaml | 447 ++++++++++++++++++-
pnpm-workspace.yaml | 1 +
12 files changed, 1286 insertions(+), 15 deletions(-)
create mode 100644 integrations/webpack/loader.test.ts
create mode 100644 packages/@tailwindcss-webpack/README.md
create mode 100644 packages/@tailwindcss-webpack/package.json
create mode 100644 packages/@tailwindcss-webpack/src/index.cts
create mode 100644 packages/@tailwindcss-webpack/src/index.ts
create mode 100644 packages/@tailwindcss-webpack/tsconfig.json
create mode 100644 packages/@tailwindcss-webpack/tsup.config.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b66ebaea00dd..9d6710ddca43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
+- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
## [4.1.18] - 2025-12-11
diff --git a/integrations/utils.ts b/integrations/utils.ts
index a2fc0d58af9a..c5d3306c4677 100644
--- a/integrations/utils.ts
+++ b/integrations/utils.ts
@@ -498,6 +498,7 @@ async function overwriteVersionsInPackageJson(content: string): Promise
json.pnpm.overrides['@tailwindcss/cli>tailwindcss'] = resolveVersion(pkg)
json.pnpm.overrides['@tailwindcss/postcss>tailwindcss'] = resolveVersion(pkg)
json.pnpm.overrides['@tailwindcss/vite>tailwindcss'] = resolveVersion(pkg)
+ json.pnpm.overrides['@tailwindcss/webpack>tailwindcss'] = resolveVersion(pkg)
} else {
json.pnpm.overrides[pkg] = resolveVersion(pkg)
}
diff --git a/integrations/webpack/loader.test.ts b/integrations/webpack/loader.test.ts
new file mode 100644
index 000000000000..3a3782c0d7a3
--- /dev/null
+++ b/integrations/webpack/loader.test.ts
@@ -0,0 +1,420 @@
+import { css, html, js, json, test } from '../utils'
+
+test(
+ '@tailwindcss/webpack loader (build)',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.html': html`
+
+ `,
+ 'src/index.css': css`
+ @import 'tailwindcss/theme';
+ @import 'tailwindcss/utilities';
+ `,
+ },
+ },
+ async ({ fs, exec, expect }) => {
+ await exec('pnpm webpack --mode=development')
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ .flex {
+ display: flex;
+ }
+ "
+ `)
+ },
+)
+
+test(
+ '@tailwindcss/webpack loader (watch)',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.html': html`
+
+ `,
+ 'src/index.css': css`
+ @import 'tailwindcss/theme';
+ @import 'tailwindcss/utilities';
+ `,
+ },
+ },
+ async ({ fs, spawn, exec, expect }) => {
+ // Generate the initial build so output CSS files exist on disk
+ await exec('pnpm webpack --mode=development')
+
+ let process = await spawn('pnpm webpack --mode=development --watch')
+ await process.onStdout((m) => m.includes('compiled successfully in'))
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ .flex {
+ display: flex;
+ }
+ "
+ `)
+
+ // Add a new Tailwind class to the HTML file
+ await fs.write('src/index.html', html`
+
+ `)
+ await process.onStdout((m) => m.includes('compiled successfully in'))
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ .flex {
+ display: flex;
+ }
+ .underline {
+ text-decoration-line: underline;
+ }
+ "
+ `)
+ },
+)
+
+test(
+ '@tailwindcss/webpack loader with @apply',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.css': css`
+ @import 'tailwindcss/theme';
+
+ .btn {
+ @apply flex items-center px-4 py-2 rounded-md;
+ }
+ `,
+ },
+ },
+ async ({ fs, exec, expect }) => {
+ await exec('pnpm webpack --mode=development')
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ :root, :host {
+ --spacing: 0.25rem;
+ --radius-md: 0.375rem;
+ }
+ .btn {
+ display: flex;
+ align-items: center;
+ border-radius: var(--radius-md);
+ padding-inline: calc(var(--spacing) * 4);
+ padding-block: calc(var(--spacing) * 2);
+ }
+ "
+ `)
+ },
+)
+
+test(
+ '@tailwindcss/webpack loader with optimization',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [
+ MiniCssExtractPlugin.loader,
+ 'css-loader',
+ {
+ loader: '@tailwindcss/webpack',
+ options: {
+ optimize: true,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.html': html`
+
+ `,
+ 'src/index.css': css`
+ @import 'tailwindcss/theme';
+ @import 'tailwindcss/utilities';
+ `,
+ },
+ },
+ async ({ fs, exec, expect }) => {
+ await exec('pnpm webpack --mode=development')
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ .flex{display:flex}
+ "
+ `)
+ },
+)
+
+test(
+ '@tailwindcss/webpack loader with CSS @import',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.html': html`
+
+ `,
+ 'src/index.css': css`
+ @import './custom.css';
+ @import 'tailwindcss/theme';
+ @import 'tailwindcss/utilities';
+ `,
+ 'src/custom.css': css`
+ /**/
+ @utility custom-util {
+ color: var(--color-red-500);
+ }
+ `,
+ },
+ },
+ async ({ fs, exec, expect }) => {
+ await exec('pnpm webpack --mode=development')
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ :root, :host {
+ --color-red-500: oklch(63.7% 0.237 25.331);
+ }
+ .flex {
+ display: flex;
+ }
+ .custom-util {
+ color: var(--color-red-500);
+ }
+ "
+ `)
+ },
+)
+
+test(
+ '@tailwindcss/webpack loader with @plugin',
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "main": "./src/index.js",
+ "browser": "./src/index.js",
+ "dependencies": {
+ "css-loader": "^6",
+ "webpack": "^5",
+ "webpack-cli": "^5",
+ "mini-css-extract-plugin": "^2",
+ "tailwindcss": "workspace:^",
+ "@tailwindcss/webpack": "workspace:^"
+ }
+ }
+ `,
+ 'webpack.config.js': js`
+ let MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+ module.exports = {
+ output: {
+ clean: true,
+ },
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+ }
+ `,
+ 'src/index.js': js`import './index.css'`,
+ 'src/index.html': html`
+
+ `,
+ 'src/index.css': css`
+ @import 'tailwindcss/utilities';
+ @plugin './plugin.js';
+ `,
+ 'src/plugin.js': js`
+ export default function ({ addUtilities }) {
+ addUtilities({
+ '.custom-underline': {
+ 'border-bottom': '1px solid green',
+ },
+ })
+ }
+ `,
+ },
+ },
+ async ({ fs, exec, expect }) => {
+ await exec('pnpm webpack --mode=development')
+
+ expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
+ "
+ --- ./dist/main.css ---
+ .custom-underline {
+ border-bottom: 1px solid green;
+ }
+ "
+ `)
+ },
+)
diff --git a/packages/@tailwindcss-postcss/README.md b/packages/@tailwindcss-postcss/README.md
index db2a6b9a007d..867389f0ea79 100644
--- a/packages/@tailwindcss-postcss/README.md
+++ b/packages/@tailwindcss-postcss/README.md
@@ -44,14 +44,14 @@ If you're interested in contributing to Tailwind CSS, please read our [contribut
You can use the `base` option (defaults to the current working directory) to change the directory in which the plugin searches for source files:
```js
-import tailwindcss from "@tailwindcss/postcss"
+import tailwindcss from '@tailwindcss/postcss'
export default {
- plugins: [
- tailwindcss({
- base: path.resolve(__dirname, "./path")
- })
- ]
+ plugins: [
+ tailwindcss({
+ base: path.resolve(__dirname, './path'),
+ }),
+ ],
}
```
diff --git a/packages/@tailwindcss-webpack/README.md b/packages/@tailwindcss-webpack/README.md
new file mode 100644
index 000000000000..55e60562203c
--- /dev/null
+++ b/packages/@tailwindcss-webpack/README.md
@@ -0,0 +1,64 @@
+# @tailwindcss/webpack
+
+A webpack loader for Tailwind CSS v4.
+
+## Installation
+
+```sh
+npm install @tailwindcss/webpack
+```
+
+## Usage
+
+```javascript
+// webpack.config.js
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+
+module.exports = {
+ plugins: [new MiniCssExtractPlugin()],
+ module: {
+ rules: [
+ {
+ test: /\.css$/i,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', '@tailwindcss/webpack'],
+ },
+ ],
+ },
+}
+```
+
+Then create a CSS file that imports Tailwind:
+
+```css
+/* src/index.css */
+@import 'tailwindcss/theme';
+@import 'tailwindcss/utilities';
+```
+
+## Options
+
+### `base`
+
+The base directory to scan for class candidates. Defaults to the current working directory.
+
+```javascript
+{
+ loader: '@tailwindcss/webpack',
+ options: {
+ base: process.cwd(),
+ },
+}
+```
+
+### `optimize`
+
+Whether to optimize and minify the output CSS. Defaults to `true` in production mode.
+
+```javascript
+{
+ loader: '@tailwindcss/webpack',
+ options: {
+ optimize: true, // or { minify: true }
+ },
+}
+```
diff --git a/packages/@tailwindcss-webpack/package.json b/packages/@tailwindcss-webpack/package.json
new file mode 100644
index 000000000000..e22cb79355d1
--- /dev/null
+++ b/packages/@tailwindcss-webpack/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "@tailwindcss/webpack",
+ "version": "4.1.18",
+ "description": "A webpack loader for Tailwind CSS v4.",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/tailwindlabs/tailwindcss.git",
+ "directory": "packages/@tailwindcss-webpack"
+ },
+ "bugs": "https://github.com/tailwindlabs/tailwindcss/issues",
+ "homepage": "https://tailwindcss.com",
+ "scripts": {
+ "build": "tsup-node",
+ "dev": "pnpm run build -- --watch"
+ },
+ "files": [
+ "dist/"
+ ],
+ "publishConfig": {
+ "provenance": true,
+ "access": "public"
+ },
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.js"
+ }
+ },
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "workspace:*",
+ "@tailwindcss/oxide": "workspace:*",
+ "tailwindcss": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/node": "catalog:",
+ "webpack": "catalog:"
+ },
+ "peerDependencies": {
+ "webpack": "^5"
+ }
+}
diff --git a/packages/@tailwindcss-webpack/src/index.cts b/packages/@tailwindcss-webpack/src/index.cts
new file mode 100644
index 000000000000..dbdded748a92
--- /dev/null
+++ b/packages/@tailwindcss-webpack/src/index.cts
@@ -0,0 +1,5 @@
+import tailwindLoader from './index.ts'
+
+// CommonJS export for webpack loaders - must be the function directly
+// @ts-ignore
+export = tailwindLoader
diff --git a/packages/@tailwindcss-webpack/src/index.ts b/packages/@tailwindcss-webpack/src/index.ts
new file mode 100644
index 000000000000..2c78a552b9e7
--- /dev/null
+++ b/packages/@tailwindcss-webpack/src/index.ts
@@ -0,0 +1,282 @@
+import QuickLRU from '@alloc/quick-lru'
+import {
+ compile,
+ env,
+ Features,
+ Instrumentation,
+ normalizePath,
+ optimize,
+ Polyfills,
+} from '@tailwindcss/node'
+import { clearRequireCache } from '@tailwindcss/node/require-cache'
+import { Scanner } from '@tailwindcss/oxide'
+import fs from 'node:fs'
+import path from 'node:path'
+import type { LoaderContext } from 'webpack'
+
+const DEBUG = env.DEBUG
+
+export interface LoaderOptions {
+ /**
+ * The base directory to scan for class candidates.
+ *
+ * Defaults to the current working directory.
+ */
+ base?: string
+
+ /**
+ * Optimize and minify the output CSS.
+ */
+ optimize?: boolean | { minify?: boolean }
+}
+
+interface CacheEntry {
+ mtimes: Map
+ compiler: null | Awaited>
+ scanner: null | Scanner
+ candidates: Set
+ fullRebuildPaths: string[]
+}
+
+const cache = new QuickLRU({ maxSize: 50 })
+
+function getContextFromCache(inputFile: string, opts: LoaderOptions): CacheEntry {
+ let key = `${inputFile}:${opts.base ?? ''}:${JSON.stringify(opts.optimize)}`
+ if (cache.has(key)) return cache.get(key)!
+ let entry: CacheEntry = {
+ mtimes: new Map(),
+ compiler: null,
+ scanner: null,
+ candidates: new Set(),
+ fullRebuildPaths: [],
+ }
+ cache.set(key, entry)
+ return entry
+}
+
+export default async function tailwindLoader(
+ this: LoaderContext,
+ source: string,
+): Promise {
+ let callback = this.async()
+ let options = this.getOptions() ?? {}
+ let inputFile = this.resourcePath
+ let base = options.base ?? process.cwd()
+ let shouldOptimize = options.optimize ?? process.env.NODE_ENV === 'production'
+ let isCSSModuleFile = inputFile.endsWith('.module.css')
+
+ using I = new Instrumentation()
+
+ DEBUG && I.start(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+
+ // Bail out early if this is guaranteed to be a non-Tailwind CSS file.
+ {
+ DEBUG && I.start('Quick bail check')
+ let canBail = !/@(import|reference|theme|variant|config|plugin|apply|tailwind)\b/.test(source)
+ if (canBail) {
+ DEBUG && I.end('Quick bail check')
+ DEBUG && I.end(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+ callback(null, source)
+ return
+ }
+ DEBUG && I.end('Quick bail check')
+ }
+
+ try {
+ let context = getContextFromCache(inputFile, options)
+ let inputBasePath = path.dirname(path.resolve(inputFile))
+
+ // Whether this is the first build or not
+ let isInitialBuild = context.compiler === null
+
+ async function createCompiler() {
+ DEBUG && I.start('Setup compiler')
+ if (context.fullRebuildPaths.length > 0 && !isInitialBuild) {
+ clearRequireCache(context.fullRebuildPaths)
+ }
+
+ context.fullRebuildPaths = []
+
+ DEBUG && I.start('Create compiler')
+ let compiler = await compile(source, {
+ from: inputFile,
+ base: inputBasePath,
+ shouldRewriteUrls: true,
+ onDependency: (depPath) => context.fullRebuildPaths.push(depPath),
+ // In CSS Module files, we have to disable the `@property` polyfill since these will
+ // emit global `*` rules which are considered to be non-pure and will cause builds
+ // to fail.
+ polyfills: isCSSModuleFile ? Polyfills.All ^ Polyfills.AtProperty : Polyfills.All,
+ })
+ DEBUG && I.end('Create compiler')
+
+ DEBUG && I.end('Setup compiler')
+ return compiler
+ }
+
+ // Setup the compiler if it doesn't exist yet
+ context.compiler ??= await createCompiler()
+
+ // Early exit if no Tailwind features are used
+ if (context.compiler.features === Features.None) {
+ DEBUG && I.end(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+ callback(null, source)
+ return
+ }
+
+ let rebuildStrategy: 'full' | 'incremental' = 'incremental'
+
+ // Track file modification times to CSS files
+ DEBUG && I.start('Register full rebuild paths')
+ {
+ // Report dependencies for config files, plugins, etc.
+ for (let file of context.fullRebuildPaths) {
+ this.addDependency(path.resolve(file))
+ }
+
+ let files = [...context.fullRebuildPaths, inputFile]
+
+ for (let file of files) {
+ let changedTime: number | null = null
+ try {
+ changedTime = fs.statSync(file)?.mtimeMs ?? null
+ } catch {
+ // File might not exist
+ }
+
+ if (changedTime === null) {
+ if (file === inputFile) {
+ rebuildStrategy = 'full'
+ }
+ continue
+ }
+
+ let prevTime = context.mtimes.get(file)
+ if (prevTime === changedTime) continue
+
+ rebuildStrategy = 'full'
+ context.mtimes.set(file, changedTime)
+ }
+ }
+ DEBUG && I.end('Register full rebuild paths')
+
+ if (rebuildStrategy === 'full' && !isInitialBuild) {
+ context.compiler = await createCompiler()
+ }
+
+ let compiler = context.compiler
+
+ // Check if we need to process this file at all
+ if (
+ !(
+ compiler.features &
+ (Features.AtApply | Features.JsPluginCompat | Features.ThemeFunction | Features.Utilities)
+ )
+ ) {
+ DEBUG && I.end(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+ callback(null, source)
+ return
+ }
+
+ // Setup or update scanner if needed
+ if (context.scanner === null || rebuildStrategy === 'full') {
+ DEBUG && I.start('Setup scanner')
+ let sources = (() => {
+ // Disable auto source detection
+ if (compiler.root === 'none') {
+ return []
+ }
+
+ // No root specified, use the base directory
+ if (compiler.root === null) {
+ return [{ base, pattern: '**/*', negated: false }]
+ }
+
+ // Use the specified root
+ return [{ ...compiler.root, negated: false }]
+ })().concat(compiler.sources)
+
+ context.scanner = new Scanner({ sources })
+ DEBUG && I.end('Setup scanner')
+ }
+
+ // Scan for candidates if utilities are used
+ if (compiler.features & Features.Utilities) {
+ DEBUG && I.start('Scan for candidates')
+ for (let candidate of context.scanner.scan()) {
+ context.candidates.add(candidate)
+ }
+ DEBUG && I.end('Scan for candidates')
+
+ DEBUG && I.start('Register dependency messages')
+ // Add all found files as direct dependencies
+ let resolvedInputFile = path.resolve(base, inputFile)
+ for (let file of context.scanner.files) {
+ let absolutePath = path.resolve(file)
+ // The CSS file cannot be a dependency of itself
+ if (absolutePath === resolvedInputFile) {
+ continue
+ }
+ this.addDependency(absolutePath)
+ }
+
+ // Register context dependencies for glob patterns
+ for (let glob of context.scanner.globs) {
+ // Skip negated patterns
+ if (glob.pattern[0] === '!') continue
+
+ // Avoid adding a dependency on the base directory itself
+ if (glob.pattern === '*' && base === glob.base) {
+ continue
+ }
+
+ this.addContextDependency(path.resolve(glob.base))
+ }
+
+ // Validate that source(...) paths are directories
+ let root = compiler.root
+ if (root !== 'none' && root !== null) {
+ let basePath = normalizePath(path.resolve(root.base, root.pattern))
+ try {
+ let stats = fs.statSync(basePath)
+ if (!stats.isDirectory()) {
+ throw new Error(
+ `The path given to \`source(…)\` must be a directory but got \`source(${basePath})\` instead.`,
+ )
+ }
+ } catch (err) {
+ if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
+ throw err
+ }
+ // Directory doesn't exist yet, which is fine
+ }
+ }
+ DEBUG && I.end('Register dependency messages')
+ }
+
+ DEBUG && I.start('Build utilities')
+ let css = compiler.build([...context.candidates])
+ DEBUG && I.end('Build utilities')
+
+ // Optionally optimize the output
+ let result = css
+ if (shouldOptimize) {
+ DEBUG && I.start('Optimization')
+ let optimized = optimize(css, {
+ minify: typeof shouldOptimize === 'object' ? shouldOptimize.minify : true,
+ })
+ result = optimized.code
+ DEBUG && I.end('Optimization')
+ }
+
+ DEBUG && I.end(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+ callback(null, result)
+ } catch (error) {
+ // Clear the cache entry on error to force a full rebuild next time
+ let key = `${inputFile}:${options.base ?? ''}:${JSON.stringify(options.optimize)}`
+ cache.delete(key)
+
+ DEBUG && I.end(`[@tailwindcss/webpack] ${path.relative(base, inputFile)}`)
+ callback(error as Error)
+ }
+}
diff --git a/packages/@tailwindcss-webpack/tsconfig.json b/packages/@tailwindcss-webpack/tsconfig.json
new file mode 100644
index 000000000000..6ae022f65bf0
--- /dev/null
+++ b/packages/@tailwindcss-webpack/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../tsconfig.base.json",
+}
diff --git a/packages/@tailwindcss-webpack/tsup.config.ts b/packages/@tailwindcss-webpack/tsup.config.ts
new file mode 100644
index 000000000000..998eebe4fe0d
--- /dev/null
+++ b/packages/@tailwindcss-webpack/tsup.config.ts
@@ -0,0 +1,19 @@
+import { defineConfig } from 'tsup'
+
+export default defineConfig([
+ {
+ format: ['esm'],
+ clean: true,
+ minify: true,
+ cjsInterop: true,
+ dts: true,
+ entry: ['src/index.ts'],
+ },
+ {
+ format: ['cjs'],
+ minify: true,
+ cjsInterop: true,
+ dts: true,
+ entry: ['src/index.cts'],
+ },
+])
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d32bc3c6495f..a7d9cf6f1ac4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -39,6 +39,9 @@ catalogs:
vite:
specifier: ^7.0.0
version: 7.0.0
+ webpack:
+ specifier: ^5
+ version: 5.104.1
patchedDependencies:
'@parcel/watcher@2.5.1':
@@ -445,6 +448,28 @@ importers:
specifier: 'catalog:'
version: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ packages/@tailwindcss-webpack:
+ dependencies:
+ '@alloc/quick-lru':
+ specifier: ^5.2.0
+ version: 5.2.0
+ '@tailwindcss/node':
+ specifier: workspace:*
+ version: link:../@tailwindcss-node
+ '@tailwindcss/oxide':
+ specifier: workspace:*
+ version: link:../../crates/node
+ tailwindcss:
+ specifier: workspace:*
+ version: link:../tailwindcss
+ devDependencies:
+ '@types/node':
+ specifier: 'catalog:'
+ version: 20.19.1
+ webpack:
+ specifier: 'catalog:'
+ version: 5.104.1(esbuild@0.27.0)
+
packages/internal-example-plugin: {}
packages/tailwindcss:
@@ -2333,6 +2358,12 @@ packages:
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+ '@types/eslint-scope@3.7.7':
+ resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
+
+ '@types/eslint@9.6.1':
+ resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
@@ -2456,6 +2487,63 @@ packages:
'@vitest/utils@4.0.12':
resolution: {integrity: sha512-DVS/TLkLdvGvj1avRy0LSmKfrcI9MNFvNGN6ECjTUHWJdlcgPDOXhjMis5Dh7rBH62nAmSXnkPbE+DZ5YD75Rw==}
+ '@webassemblyjs/ast@1.14.1':
+ resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
+
+ '@webassemblyjs/floating-point-hex-parser@1.13.2':
+ resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==}
+
+ '@webassemblyjs/helper-api-error@1.13.2':
+ resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==}
+
+ '@webassemblyjs/helper-buffer@1.14.1':
+ resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==}
+
+ '@webassemblyjs/helper-numbers@1.13.2':
+ resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==}
+
+ '@webassemblyjs/helper-wasm-bytecode@1.13.2':
+ resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==}
+
+ '@webassemblyjs/helper-wasm-section@1.14.1':
+ resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==}
+
+ '@webassemblyjs/ieee754@1.13.2':
+ resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==}
+
+ '@webassemblyjs/leb128@1.13.2':
+ resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==}
+
+ '@webassemblyjs/utf8@1.13.2':
+ resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==}
+
+ '@webassemblyjs/wasm-edit@1.14.1':
+ resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==}
+
+ '@webassemblyjs/wasm-gen@1.14.1':
+ resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==}
+
+ '@webassemblyjs/wasm-opt@1.14.1':
+ resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==}
+
+ '@webassemblyjs/wasm-parser@1.14.1':
+ resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==}
+
+ '@webassemblyjs/wast-printer@1.14.1':
+ resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==}
+
+ '@xtuc/ieee754@1.2.0':
+ resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
+
+ '@xtuc/long@4.2.2':
+ resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
+
+ acorn-import-phases@1.0.4:
+ resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==}
+ engines: {node: '>=10.13.0'}
+ peerDependencies:
+ acorn: ^8.14.0
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2471,9 +2559,25 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ ajv-formats@2.1.1:
+ resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv-keywords@5.1.0:
+ resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==}
+ peerDependencies:
+ ajv: ^8.8.2
+
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ ajv@8.17.1:
+ resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
+
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -2669,6 +2773,10 @@ packages:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
+ chrome-trace-event@1.0.4:
+ resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
+ engines: {node: '>=6.0'}
+
citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
@@ -2873,6 +2981,9 @@ packages:
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+ es-module-lexer@2.0.0:
+ resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==}
+
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
@@ -2989,6 +3100,10 @@ packages:
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+ eslint-scope@5.1.1:
+ resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+ engines: {node: '>=8.0.0'}
+
eslint-scope@8.4.0:
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3023,6 +3138,10 @@ packages:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
+ estraverse@4.3.0:
+ resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
+ engines: {node: '>=4.0'}
+
estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
@@ -3034,6 +3153,10 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ events@3.3.0:
+ resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+ engines: {node: '>=0.8.x'}
+
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
@@ -3069,6 +3192,9 @@ packages:
fast-stringify@4.0.0:
resolution: {integrity: sha512-lE2DIivBaLysf6hK5WH/VfMgqRbvBVHcpGVVTmA5Zi8oWIjq9YxIt6lYGdUgP1HNSXxTIat7HEIDnrSvXSeKQw==}
+ fast-uri@3.1.0:
+ resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
+
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
@@ -3180,6 +3306,9 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ glob-to-regexp@0.4.1:
+ resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
@@ -3430,6 +3559,10 @@ packages:
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+ jest-worker@27.5.1:
+ resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
+ engines: {node: '>= 10.13.0'}
+
jiti@1.21.6:
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
hasBin: true
@@ -3461,9 +3594,15 @@ packages:
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
@@ -3576,6 +3715,10 @@ packages:
resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ loader-runner@4.3.1:
+ resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==}
+ engines: {node: '>=6.11.5'}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -3618,6 +3761,14 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
mimic-fn@4.0.0:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
@@ -3673,6 +3824,9 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ neo-async@2.6.2:
+ resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
next@16.1.0:
resolution: {integrity: sha512-Y+KbmDbefYtHDDQKLNrmzE/YYzG2msqo2VXhzh5yrJ54tx/6TmGdkR5+kP9ma7i7LwZpZMfoY3m/AoPPPKxtVw==}
engines: {node: '>=20.9.0'}
@@ -3987,6 +4141,9 @@ packages:
radix3@1.1.2:
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
+ randombytes@2.1.0:
+ resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+
react-dom@19.2.3:
resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
peerDependencies:
@@ -4022,6 +4179,10 @@ packages:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@@ -4057,6 +4218,9 @@ packages:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'}
@@ -4071,6 +4235,10 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+ schema-utils@4.3.3:
+ resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==}
+ engines: {node: '>= 10.13.0'}
+
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -4080,6 +4248,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ serialize-javascript@6.0.2:
+ resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -4232,6 +4403,10 @@ packages:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
+ supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -4253,6 +4428,26 @@ packages:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
+ tapable@2.3.0:
+ resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
+ engines: {node: '>=6'}
+
+ terser-webpack-plugin@5.3.16:
+ resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==}
+ engines: {node: '>= 10.13.0'}
+ peerDependencies:
+ '@swc/core': '*'
+ esbuild: '*'
+ uglify-js: '*'
+ webpack: ^5.1.0
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ esbuild:
+ optional: true
+ uglify-js:
+ optional: true
+
terser@5.31.6:
resolution: {integrity: sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==}
engines: {node: '>=10'}
@@ -4558,6 +4753,24 @@ packages:
jsdom:
optional: true
+ watchpack@2.5.1:
+ resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==}
+ engines: {node: '>=10.13.0'}
+
+ webpack-sources@3.3.3:
+ resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==}
+ engines: {node: '>=10.13.0'}
+
+ webpack@5.104.1:
+ resolution: {integrity: sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ peerDependencies:
+ webpack-cli: '*'
+ peerDependenciesMeta:
+ webpack-cli:
+ optional: true
+
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -5293,7 +5506,6 @@ snapshots:
dependencies:
'@jridgewell/gen-mapping': 0.3.12
'@jridgewell/trace-mapping': 0.3.29
- optional: true
'@jridgewell/sourcemap-codec@1.5.0': {}
@@ -5941,6 +6153,16 @@ snapshots:
'@types/deep-eql@4.0.2': {}
+ '@types/eslint-scope@3.7.7':
+ dependencies:
+ '@types/eslint': 9.6.1
+ '@types/estree': 1.0.8
+
+ '@types/eslint@9.6.1':
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+
'@types/estree@1.0.8': {}
'@types/json-schema@7.0.15': {}
@@ -6194,6 +6416,90 @@ snapshots:
'@vitest/pretty-format': 4.0.12
tinyrainbow: 3.0.3
+ '@webassemblyjs/ast@1.14.1':
+ dependencies:
+ '@webassemblyjs/helper-numbers': 1.13.2
+ '@webassemblyjs/helper-wasm-bytecode': 1.13.2
+
+ '@webassemblyjs/floating-point-hex-parser@1.13.2': {}
+
+ '@webassemblyjs/helper-api-error@1.13.2': {}
+
+ '@webassemblyjs/helper-buffer@1.14.1': {}
+
+ '@webassemblyjs/helper-numbers@1.13.2':
+ dependencies:
+ '@webassemblyjs/floating-point-hex-parser': 1.13.2
+ '@webassemblyjs/helper-api-error': 1.13.2
+ '@xtuc/long': 4.2.2
+
+ '@webassemblyjs/helper-wasm-bytecode@1.13.2': {}
+
+ '@webassemblyjs/helper-wasm-section@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/helper-buffer': 1.14.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.13.2
+ '@webassemblyjs/wasm-gen': 1.14.1
+
+ '@webassemblyjs/ieee754@1.13.2':
+ dependencies:
+ '@xtuc/ieee754': 1.2.0
+
+ '@webassemblyjs/leb128@1.13.2':
+ dependencies:
+ '@xtuc/long': 4.2.2
+
+ '@webassemblyjs/utf8@1.13.2': {}
+
+ '@webassemblyjs/wasm-edit@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/helper-buffer': 1.14.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.13.2
+ '@webassemblyjs/helper-wasm-section': 1.14.1
+ '@webassemblyjs/wasm-gen': 1.14.1
+ '@webassemblyjs/wasm-opt': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+ '@webassemblyjs/wast-printer': 1.14.1
+
+ '@webassemblyjs/wasm-gen@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/helper-wasm-bytecode': 1.13.2
+ '@webassemblyjs/ieee754': 1.13.2
+ '@webassemblyjs/leb128': 1.13.2
+ '@webassemblyjs/utf8': 1.13.2
+
+ '@webassemblyjs/wasm-opt@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/helper-buffer': 1.14.1
+ '@webassemblyjs/wasm-gen': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+
+ '@webassemblyjs/wasm-parser@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/helper-api-error': 1.13.2
+ '@webassemblyjs/helper-wasm-bytecode': 1.13.2
+ '@webassemblyjs/ieee754': 1.13.2
+ '@webassemblyjs/leb128': 1.13.2
+ '@webassemblyjs/utf8': 1.13.2
+
+ '@webassemblyjs/wast-printer@1.14.1':
+ dependencies:
+ '@webassemblyjs/ast': 1.14.1
+ '@xtuc/long': 4.2.2
+
+ '@xtuc/ieee754@1.2.0': {}
+
+ '@xtuc/long@4.2.2': {}
+
+ acorn-import-phases@1.0.4(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
acorn: 8.15.0
@@ -6202,6 +6508,15 @@ snapshots:
acorn@8.15.0: {}
+ ajv-formats@2.1.1(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
+
+ ajv-keywords@5.1.0(ajv@8.17.1):
+ dependencies:
+ ajv: 8.17.1
+ fast-deep-equal: 3.1.3
+
ajv@6.12.6:
dependencies:
fast-deep-equal: 3.1.3
@@ -6209,6 +6524,13 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
+ ajv@8.17.1:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-uri: 3.1.0
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+
ansi-regex@5.0.1: {}
ansi-regex@6.0.1: {}
@@ -6359,8 +6681,7 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
- buffer-from@1.1.2:
- optional: true
+ buffer-from@1.1.2: {}
bun-types@1.3.5:
dependencies:
@@ -6437,6 +6758,8 @@ snapshots:
dependencies:
readdirp: 4.1.1
+ chrome-trace-event@1.0.4: {}
+
citty@0.1.6:
dependencies:
consola: 3.2.3
@@ -6463,8 +6786,7 @@ snapshots:
colorette@2.0.20: {}
- commander@2.20.3:
- optional: true
+ commander@2.20.3: {}
commander@4.1.1: {}
@@ -6666,6 +6988,8 @@ snapshots:
es-module-lexer@1.7.0: {}
+ es-module-lexer@2.0.0: {}
+
es-object-atoms@1.1.1:
dependencies:
es-errors: 1.3.0
@@ -6994,6 +7318,11 @@ snapshots:
string.prototype.matchall: 4.0.11
string.prototype.repeat: 1.0.0
+ eslint-scope@5.1.1:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+
eslint-scope@8.4.0:
dependencies:
esrecurse: 4.3.0
@@ -7058,6 +7387,8 @@ snapshots:
dependencies:
estraverse: 5.3.0
+ estraverse@4.3.0: {}
+
estraverse@5.3.0: {}
estree-walker@3.0.3:
@@ -7066,6 +7397,8 @@ snapshots:
esutils@2.0.3: {}
+ events@3.3.0: {}
+
execa@8.0.1:
dependencies:
cross-spawn: 7.0.6
@@ -7108,6 +7441,8 @@ snapshots:
fast-stringify@4.0.0: {}
+ fast-uri@3.1.0: {}
+
fastq@1.17.1:
dependencies:
reusify: 1.0.4
@@ -7220,6 +7555,8 @@ snapshots:
dependencies:
is-glob: 4.0.3
+ glob-to-regexp@0.4.1: {}
+
glob@10.4.5:
dependencies:
foreground-child: 3.3.0
@@ -7468,6 +7805,12 @@ snapshots:
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
+ jest-worker@27.5.1:
+ dependencies:
+ '@types/node': 20.19.1
+ merge-stream: 2.0.0
+ supports-color: 8.1.1
+
jiti@1.21.6: {}
jiti@2.4.2: {}
@@ -7486,8 +7829,12 @@ snapshots:
json-buffer@3.0.1: {}
+ json-parse-even-better-errors@2.3.1: {}
+
json-schema-traverse@0.4.1: {}
+ json-schema-traverse@1.0.0: {}
+
json-stable-stringify-without-jsonify@1.0.1: {}
json5@1.0.2:
@@ -7589,6 +7936,8 @@ snapshots:
load-tsconfig@0.2.5: {}
+ loader-runner@4.3.1: {}
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
@@ -7630,6 +7979,12 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
mimic-fn@4.0.0: {}
mini-svg-data-uri@1.4.4: {}
@@ -7678,6 +8033,8 @@ snapshots:
natural-compare@1.4.0: {}
+ neo-async@2.6.2: {}
+
next@16.1.0(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
'@next/env': 16.1.0
@@ -7972,6 +8329,10 @@ snapshots:
radix3@1.1.2: {}
+ randombytes@2.1.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
react-dom@19.2.3(react@19.2.3):
dependencies:
react: 19.2.3
@@ -8013,6 +8374,8 @@ snapshots:
gopd: 1.2.0
set-function-name: 2.0.2
+ require-from-string@2.0.2: {}
+
resolve-from@4.0.0: {}
resolve-from@5.0.0: {}
@@ -8071,6 +8434,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
+ safe-buffer@5.2.1: {}
+
safe-push-apply@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -8086,10 +8451,21 @@ snapshots:
scheduler@0.27.0: {}
+ schema-utils@4.3.3:
+ dependencies:
+ '@types/json-schema': 7.0.15
+ ajv: 8.17.1
+ ajv-formats: 2.1.1(ajv@8.17.1)
+ ajv-keywords: 5.1.0(ajv@8.17.1)
+
semver@6.3.1: {}
semver@7.7.3: {}
+ serialize-javascript@6.0.2:
+ dependencies:
+ randombytes: 2.1.0
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -8190,10 +8566,8 @@ snapshots:
dependencies:
buffer-from: 1.1.2
source-map: 0.6.1
- optional: true
- source-map@0.6.1:
- optional: true
+ source-map@0.6.1: {}
source-map@0.7.6: {}
@@ -8302,6 +8676,10 @@ snapshots:
dependencies:
has-flag: 4.0.0
+ supports-color@8.1.1:
+ dependencies:
+ has-flag: 4.0.0
+
supports-preserve-symlinks-flag@1.0.0: {}
system-architecture@0.1.0: {}
@@ -8337,13 +8715,25 @@ snapshots:
tapable@2.2.1: {}
+ tapable@2.3.0: {}
+
+ terser-webpack-plugin@5.3.16(esbuild@0.27.0)(webpack@5.104.1(esbuild@0.27.0)):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.29
+ jest-worker: 27.5.1
+ schema-utils: 4.3.3
+ serialize-javascript: 6.0.2
+ terser: 5.31.6
+ webpack: 5.104.1(esbuild@0.27.0)
+ optionalDependencies:
+ esbuild: 0.27.0
+
terser@5.31.6:
dependencies:
'@jridgewell/source-map': 0.3.6
acorn: 8.15.0
commander: 2.20.3
source-map-support: 0.5.21
- optional: true
thenify-all@1.6.0:
dependencies:
@@ -8650,6 +9040,45 @@ snapshots:
- tsx
- yaml
+ watchpack@2.5.1:
+ dependencies:
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+
+ webpack-sources@3.3.3: {}
+
+ webpack@5.104.1(esbuild@0.27.0):
+ dependencies:
+ '@types/eslint-scope': 3.7.7
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/wasm-edit': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+ acorn: 8.15.0
+ acorn-import-phases: 1.0.4(acorn@8.15.0)
+ browserslist: 4.28.1
+ chrome-trace-event: 1.0.4
+ enhanced-resolve: 5.18.4
+ es-module-lexer: 2.0.0
+ eslint-scope: 5.1.1
+ events: 3.3.0
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+ json-parse-even-better-errors: 2.3.1
+ loader-runner: 4.3.1
+ mime-types: 2.1.35
+ neo-async: 2.6.2
+ schema-utils: 4.3.3
+ tapable: 2.3.0
+ terser-webpack-plugin: 5.3.16(esbuild@0.27.0)(webpack@5.104.1(esbuild@0.27.0))
+ watchpack: 2.5.1
+ webpack-sources: 3.3.3
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 8f662c07fc67..ba9aedcb6660 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -9,6 +9,7 @@ catalog:
'@types/node': ^20.19.0
prettier: 3.6.2
vite: ^7.0.0
+ webpack: ^5
lightningcss: 1.30.2
lightningcss-darwin-arm64: 1.30.2
lightningcss-darwin-x64: 1.30.2
From e3e85b364fc62a19b97a4250854580132e7967c7 Mon Sep 17 00:00:00 2001
From: Tim Neutkens
Date: Thu, 29 Jan 2026 15:17:50 +0100
Subject: [PATCH 02/40] [tailwindcss-vite] Add Register dependency messages
logline (#19611)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The PostCSS implementation has a debug logline for registering
dependencies but this is missing for @tailwindcss/vite.
## Summary
Adds the "Register dependency messages" instrumentation span to the Vite
plugin's dependency registration code, matching the existing
implementation in @tailwindcss/postcss.
This ensures consistent debug instrumentation across both bundler
integrations when DEBUG is enabled.
## Test plan
---
packages/@tailwindcss-vite/src/index.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts
index 341c662b164e..4ad70ba43a34 100644
--- a/packages/@tailwindcss-vite/src/index.ts
+++ b/packages/@tailwindcss-vite/src/index.ts
@@ -375,6 +375,7 @@ class Root {
}
if (this.compiler.features & Features.Utilities) {
+ DEBUG && I.start('Register dependency messages')
// Watch individual files found via custom `@source` paths
for (let file of this.scanner.files) {
addWatchFile(file)
@@ -411,6 +412,7 @@ class Root {
}
}
}
+ DEBUG && I.end('Register dependency messages')
}
DEBUG && I.start('Build CSS')
From 566eea4ff92dbac61a5f03f83d804c87a31ebc01 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Thu, 29 Jan 2026 15:49:31 +0100
Subject: [PATCH 03/40] Improve walk performance (#19614)
This PR improves the walk performance by a little bit, but also reduces
memory usage. It's a tiny change and all the APIs remain the same. Not
the most important PR, but we had this idea on the backburner so we
decided to just implement it.
Thanks @thecrypticace!
## Test plan
- All the existing tests should pass.
Co-authored-by: Jordan Pittman
---
packages/tailwindcss/src/walk.ts | 33 +++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/packages/tailwindcss/src/walk.ts b/packages/tailwindcss/src/walk.ts
index ccb384256c3f..97c30db90be1 100644
--- a/packages/tailwindcss/src/walk.ts
+++ b/packages/tailwindcss/src/walk.ts
@@ -52,42 +52,53 @@ export function walk(
else walkImplementation(ast, hooks.enter, hooks.exit)
}
+interface Stack {
+ value: T
+ prev: Stack | null
+}
+
function walkImplementation(
ast: T[],
enter: (node: T, ctx: VisitContext) => EnterResult | void = () => WalkAction.Continue,
exit: (node: T, ctx: VisitContext) => ExitResult | void = () => WalkAction.Continue,
) {
- let stack: [nodes: T[], offset: number, parent: Parent | null][] = [[ast, 0, null]]
+ type StackFrame = [nodes: T[], offset: number, parent: Parent | null]
+ let stack: Stack | null = { value: [ast, 0, null], prev: null }
+
let ctx: VisitContext = {
parent: null,
depth: 0,
path() {
let path: T[] = []
- for (let i = 1; i < stack.length; i++) {
- let parent = stack[i][2]
+ let frames: Stack | null = stack
+
+ while (frames) {
+ let parent = frames.value[2]
if (parent) path.push(parent)
+ frames = frames.prev
}
+ path.reverse()
+
return path
},
}
- while (stack.length > 0) {
- let depth = stack.length - 1
- let frame = stack[depth]
+ while (stack !== null) {
+ let frame = stack.value
let nodes = frame[0]
let offset = frame[1]
let parent = frame[2]
// Done with this level
if (offset >= nodes.length) {
- stack.pop()
+ stack = stack.prev
+ ctx.depth -= 1
continue
}
ctx.parent = parent
- ctx.depth = depth
// Enter phase (offsets are positive)
if (offset >= 0) {
@@ -97,7 +108,11 @@ function walkImplementation(
switch (result.kind) {
case WalkKind.Continue: {
if (node.nodes && node.nodes.length > 0) {
- stack.push([node.nodes, 0, node as Parent])
+ ctx.depth += 1
+ stack = {
+ value: [node.nodes, 0, node as Parent],
+ prev: stack,
+ }
}
frame[1] = ~offset // Prepare for exit phase, same offset
From 991072fcacbf3ea6d141a240312768cd808697b1 Mon Sep 17 00:00:00 2001
From: Adam Wathan
Date: Fri, 30 Jan 2026 14:37:51 +0100
Subject: [PATCH 04/40] Add logical block-start/block-end border, margin, and
padding utilities (#19601)
## Summary
This PR adds support for logical block-start and block-end CSS
properties in Tailwind CSS utilities. These properties are part of the
CSS Logical Properties specification and provide writing-mode-aware
alternatives to physical top/bottom properties.
The following new utilities are added:
- **Border utilities**: `border-bs-*` and `border-be-*` (for
`border-block-start` and `border-block-end`)
- **Margin utilities**: `mbs-*` and `mbe-*` (for `margin-block-start`
and `margin-block-end`)
- **Scroll margin utilities**: `scroll-mbs-*` and `scroll-mbe-*` (for
`scroll-margin-block-start` and `scroll-margin-block-end`)
- **Scroll padding utilities**: `scroll-pbs-*` and `scroll-pbe-*` (for
`scroll-padding-block-start` and `scroll-padding-block-end`)
- **Padding utilities**: `pbs-*` and `pbe-*` (for `padding-block-start`
and `padding-block-end`)
These utilities follow the same patterns as their existing
inline-start/inline-end counterparts and support all standard modifiers
(arbitrary values, negative values, opacity modifiers, etc.).
## Changes
1. **utilities.ts**: Added new utility definitions for all
block-start/block-end properties
2. **property-order.ts**: Updated CSS property ordering to include the
new logical properties in the correct cascade order
3. **utilities.test.ts**: Added comprehensive test cases for all new
utilities
4. **utilities.test.ts.snap**: Updated snapshots showing generated CSS
for the new utilities
## Test plan
All changes are covered by existing test infrastructure:
- Unit tests verify correct CSS generation for each utility variant
- Snapshot tests validate the complete output for border utilities
- Invalid modifier combinations are tested to ensure proper error
handling
- Tests cover standard values, arbitrary values, negative values, and
opacity modifiers
https://claude.ai/code/session_01V89HxEtppGVvMtuPbYrayM
---------
Co-authored-by: Claude
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
.../__snapshots__/intellisense.test.ts.snap | 606 ++++++++++++++++++
.../src/__snapshots__/utilities.test.ts.snap | 370 +++++++++++
packages/tailwindcss/src/property-order.ts | 14 +
packages/tailwindcss/src/utilities.test.ts | 412 ++++++++++++
packages/tailwindcss/src/utilities.ts | 24 +
6 files changed, 1427 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d6710ddca43..cc4d2a301536 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
+- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
diff --git a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
index 690b1cb1f0eb..759d91443c1c 100644
--- a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
@@ -739,6 +739,76 @@ exports[`getClassList 1`] = `
"-mb-80",
"-mb-96",
"-mb-px",
+ "-mbe-0",
+ "-mbe-0.5",
+ "-mbe-1",
+ "-mbe-1.5",
+ "-mbe-2",
+ "-mbe-2.5",
+ "-mbe-3",
+ "-mbe-3.5",
+ "-mbe-4",
+ "-mbe-5",
+ "-mbe-6",
+ "-mbe-7",
+ "-mbe-8",
+ "-mbe-9",
+ "-mbe-10",
+ "-mbe-11",
+ "-mbe-12",
+ "-mbe-14",
+ "-mbe-16",
+ "-mbe-20",
+ "-mbe-24",
+ "-mbe-28",
+ "-mbe-32",
+ "-mbe-36",
+ "-mbe-40",
+ "-mbe-44",
+ "-mbe-48",
+ "-mbe-52",
+ "-mbe-56",
+ "-mbe-60",
+ "-mbe-64",
+ "-mbe-72",
+ "-mbe-80",
+ "-mbe-96",
+ "-mbe-px",
+ "-mbs-0",
+ "-mbs-0.5",
+ "-mbs-1",
+ "-mbs-1.5",
+ "-mbs-2",
+ "-mbs-2.5",
+ "-mbs-3",
+ "-mbs-3.5",
+ "-mbs-4",
+ "-mbs-5",
+ "-mbs-6",
+ "-mbs-7",
+ "-mbs-8",
+ "-mbs-9",
+ "-mbs-10",
+ "-mbs-11",
+ "-mbs-12",
+ "-mbs-14",
+ "-mbs-16",
+ "-mbs-20",
+ "-mbs-24",
+ "-mbs-28",
+ "-mbs-32",
+ "-mbs-36",
+ "-mbs-40",
+ "-mbs-44",
+ "-mbs-48",
+ "-mbs-52",
+ "-mbs-56",
+ "-mbs-60",
+ "-mbs-64",
+ "-mbs-72",
+ "-mbs-80",
+ "-mbs-96",
+ "-mbs-px",
"-me-0",
"-me-0.5",
"-me-1",
@@ -1239,6 +1309,76 @@ exports[`getClassList 1`] = `
"-scroll-mb-80",
"-scroll-mb-96",
"-scroll-mb-px",
+ "-scroll-mbe-0",
+ "-scroll-mbe-0.5",
+ "-scroll-mbe-1",
+ "-scroll-mbe-1.5",
+ "-scroll-mbe-2",
+ "-scroll-mbe-2.5",
+ "-scroll-mbe-3",
+ "-scroll-mbe-3.5",
+ "-scroll-mbe-4",
+ "-scroll-mbe-5",
+ "-scroll-mbe-6",
+ "-scroll-mbe-7",
+ "-scroll-mbe-8",
+ "-scroll-mbe-9",
+ "-scroll-mbe-10",
+ "-scroll-mbe-11",
+ "-scroll-mbe-12",
+ "-scroll-mbe-14",
+ "-scroll-mbe-16",
+ "-scroll-mbe-20",
+ "-scroll-mbe-24",
+ "-scroll-mbe-28",
+ "-scroll-mbe-32",
+ "-scroll-mbe-36",
+ "-scroll-mbe-40",
+ "-scroll-mbe-44",
+ "-scroll-mbe-48",
+ "-scroll-mbe-52",
+ "-scroll-mbe-56",
+ "-scroll-mbe-60",
+ "-scroll-mbe-64",
+ "-scroll-mbe-72",
+ "-scroll-mbe-80",
+ "-scroll-mbe-96",
+ "-scroll-mbe-px",
+ "-scroll-mbs-0",
+ "-scroll-mbs-0.5",
+ "-scroll-mbs-1",
+ "-scroll-mbs-1.5",
+ "-scroll-mbs-2",
+ "-scroll-mbs-2.5",
+ "-scroll-mbs-3",
+ "-scroll-mbs-3.5",
+ "-scroll-mbs-4",
+ "-scroll-mbs-5",
+ "-scroll-mbs-6",
+ "-scroll-mbs-7",
+ "-scroll-mbs-8",
+ "-scroll-mbs-9",
+ "-scroll-mbs-10",
+ "-scroll-mbs-11",
+ "-scroll-mbs-12",
+ "-scroll-mbs-14",
+ "-scroll-mbs-16",
+ "-scroll-mbs-20",
+ "-scroll-mbs-24",
+ "-scroll-mbs-28",
+ "-scroll-mbs-32",
+ "-scroll-mbs-36",
+ "-scroll-mbs-40",
+ "-scroll-mbs-44",
+ "-scroll-mbs-48",
+ "-scroll-mbs-52",
+ "-scroll-mbs-56",
+ "-scroll-mbs-60",
+ "-scroll-mbs-64",
+ "-scroll-mbs-72",
+ "-scroll-mbs-80",
+ "-scroll-mbs-96",
+ "-scroll-mbs-px",
"-scroll-me-0",
"-scroll-me-0.5",
"-scroll-me-1",
@@ -2693,6 +2833,190 @@ exports[`getClassList 1`] = `
"border-b-transparent/90",
"border-b-transparent/95",
"border-b-transparent/100",
+ "border-be",
+ "border-be/0",
+ "border-be/5",
+ "border-be/10",
+ "border-be/15",
+ "border-be/20",
+ "border-be/25",
+ "border-be/30",
+ "border-be/35",
+ "border-be/40",
+ "border-be/45",
+ "border-be/50",
+ "border-be/55",
+ "border-be/60",
+ "border-be/65",
+ "border-be/70",
+ "border-be/75",
+ "border-be/80",
+ "border-be/85",
+ "border-be/90",
+ "border-be/95",
+ "border-be/100",
+ "border-be-0",
+ "border-be-2",
+ "border-be-4",
+ "border-be-8",
+ "border-be-current",
+ "border-be-current/0",
+ "border-be-current/5",
+ "border-be-current/10",
+ "border-be-current/15",
+ "border-be-current/20",
+ "border-be-current/25",
+ "border-be-current/30",
+ "border-be-current/35",
+ "border-be-current/40",
+ "border-be-current/45",
+ "border-be-current/50",
+ "border-be-current/55",
+ "border-be-current/60",
+ "border-be-current/65",
+ "border-be-current/70",
+ "border-be-current/75",
+ "border-be-current/80",
+ "border-be-current/85",
+ "border-be-current/90",
+ "border-be-current/95",
+ "border-be-current/100",
+ "border-be-inherit",
+ "border-be-inherit/0",
+ "border-be-inherit/5",
+ "border-be-inherit/10",
+ "border-be-inherit/15",
+ "border-be-inherit/20",
+ "border-be-inherit/25",
+ "border-be-inherit/30",
+ "border-be-inherit/35",
+ "border-be-inherit/40",
+ "border-be-inherit/45",
+ "border-be-inherit/50",
+ "border-be-inherit/55",
+ "border-be-inherit/60",
+ "border-be-inherit/65",
+ "border-be-inherit/70",
+ "border-be-inherit/75",
+ "border-be-inherit/80",
+ "border-be-inherit/85",
+ "border-be-inherit/90",
+ "border-be-inherit/95",
+ "border-be-inherit/100",
+ "border-be-transparent",
+ "border-be-transparent/0",
+ "border-be-transparent/5",
+ "border-be-transparent/10",
+ "border-be-transparent/15",
+ "border-be-transparent/20",
+ "border-be-transparent/25",
+ "border-be-transparent/30",
+ "border-be-transparent/35",
+ "border-be-transparent/40",
+ "border-be-transparent/45",
+ "border-be-transparent/50",
+ "border-be-transparent/55",
+ "border-be-transparent/60",
+ "border-be-transparent/65",
+ "border-be-transparent/70",
+ "border-be-transparent/75",
+ "border-be-transparent/80",
+ "border-be-transparent/85",
+ "border-be-transparent/90",
+ "border-be-transparent/95",
+ "border-be-transparent/100",
+ "border-bs",
+ "border-bs/0",
+ "border-bs/5",
+ "border-bs/10",
+ "border-bs/15",
+ "border-bs/20",
+ "border-bs/25",
+ "border-bs/30",
+ "border-bs/35",
+ "border-bs/40",
+ "border-bs/45",
+ "border-bs/50",
+ "border-bs/55",
+ "border-bs/60",
+ "border-bs/65",
+ "border-bs/70",
+ "border-bs/75",
+ "border-bs/80",
+ "border-bs/85",
+ "border-bs/90",
+ "border-bs/95",
+ "border-bs/100",
+ "border-bs-0",
+ "border-bs-2",
+ "border-bs-4",
+ "border-bs-8",
+ "border-bs-current",
+ "border-bs-current/0",
+ "border-bs-current/5",
+ "border-bs-current/10",
+ "border-bs-current/15",
+ "border-bs-current/20",
+ "border-bs-current/25",
+ "border-bs-current/30",
+ "border-bs-current/35",
+ "border-bs-current/40",
+ "border-bs-current/45",
+ "border-bs-current/50",
+ "border-bs-current/55",
+ "border-bs-current/60",
+ "border-bs-current/65",
+ "border-bs-current/70",
+ "border-bs-current/75",
+ "border-bs-current/80",
+ "border-bs-current/85",
+ "border-bs-current/90",
+ "border-bs-current/95",
+ "border-bs-current/100",
+ "border-bs-inherit",
+ "border-bs-inherit/0",
+ "border-bs-inherit/5",
+ "border-bs-inherit/10",
+ "border-bs-inherit/15",
+ "border-bs-inherit/20",
+ "border-bs-inherit/25",
+ "border-bs-inherit/30",
+ "border-bs-inherit/35",
+ "border-bs-inherit/40",
+ "border-bs-inherit/45",
+ "border-bs-inherit/50",
+ "border-bs-inherit/55",
+ "border-bs-inherit/60",
+ "border-bs-inherit/65",
+ "border-bs-inherit/70",
+ "border-bs-inherit/75",
+ "border-bs-inherit/80",
+ "border-bs-inherit/85",
+ "border-bs-inherit/90",
+ "border-bs-inherit/95",
+ "border-bs-inherit/100",
+ "border-bs-transparent",
+ "border-bs-transparent/0",
+ "border-bs-transparent/5",
+ "border-bs-transparent/10",
+ "border-bs-transparent/15",
+ "border-bs-transparent/20",
+ "border-bs-transparent/25",
+ "border-bs-transparent/30",
+ "border-bs-transparent/35",
+ "border-bs-transparent/40",
+ "border-bs-transparent/45",
+ "border-bs-transparent/50",
+ "border-bs-transparent/55",
+ "border-bs-transparent/60",
+ "border-bs-transparent/65",
+ "border-bs-transparent/70",
+ "border-bs-transparent/75",
+ "border-bs-transparent/80",
+ "border-bs-transparent/85",
+ "border-bs-transparent/90",
+ "border-bs-transparent/95",
+ "border-bs-transparent/100",
"border-collapse",
"border-current",
"border-current/0",
@@ -7614,6 +7938,78 @@ exports[`getClassList 1`] = `
"mb-96",
"mb-auto",
"mb-px",
+ "mbe-0",
+ "mbe-0.5",
+ "mbe-1",
+ "mbe-1.5",
+ "mbe-2",
+ "mbe-2.5",
+ "mbe-3",
+ "mbe-3.5",
+ "mbe-4",
+ "mbe-5",
+ "mbe-6",
+ "mbe-7",
+ "mbe-8",
+ "mbe-9",
+ "mbe-10",
+ "mbe-11",
+ "mbe-12",
+ "mbe-14",
+ "mbe-16",
+ "mbe-20",
+ "mbe-24",
+ "mbe-28",
+ "mbe-32",
+ "mbe-36",
+ "mbe-40",
+ "mbe-44",
+ "mbe-48",
+ "mbe-52",
+ "mbe-56",
+ "mbe-60",
+ "mbe-64",
+ "mbe-72",
+ "mbe-80",
+ "mbe-96",
+ "mbe-auto",
+ "mbe-px",
+ "mbs-0",
+ "mbs-0.5",
+ "mbs-1",
+ "mbs-1.5",
+ "mbs-2",
+ "mbs-2.5",
+ "mbs-3",
+ "mbs-3.5",
+ "mbs-4",
+ "mbs-5",
+ "mbs-6",
+ "mbs-7",
+ "mbs-8",
+ "mbs-9",
+ "mbs-10",
+ "mbs-11",
+ "mbs-12",
+ "mbs-14",
+ "mbs-16",
+ "mbs-20",
+ "mbs-24",
+ "mbs-28",
+ "mbs-32",
+ "mbs-36",
+ "mbs-40",
+ "mbs-44",
+ "mbs-48",
+ "mbs-52",
+ "mbs-56",
+ "mbs-60",
+ "mbs-64",
+ "mbs-72",
+ "mbs-80",
+ "mbs-96",
+ "mbs-auto",
+ "mbs-px",
"me-0",
"me-0.5",
"me-1",
@@ -8298,6 +8694,76 @@ exports[`getClassList 1`] = `
"pb-80",
"pb-96",
"pb-px",
+ "pbe-0",
+ "pbe-0.5",
+ "pbe-1",
+ "pbe-1.5",
+ "pbe-2",
+ "pbe-2.5",
+ "pbe-3",
+ "pbe-3.5",
+ "pbe-4",
+ "pbe-5",
+ "pbe-6",
+ "pbe-7",
+ "pbe-8",
+ "pbe-9",
+ "pbe-10",
+ "pbe-11",
+ "pbe-12",
+ "pbe-14",
+ "pbe-16",
+ "pbe-20",
+ "pbe-24",
+ "pbe-28",
+ "pbe-32",
+ "pbe-36",
+ "pbe-40",
+ "pbe-44",
+ "pbe-48",
+ "pbe-52",
+ "pbe-56",
+ "pbe-60",
+ "pbe-64",
+ "pbe-72",
+ "pbe-80",
+ "pbe-96",
+ "pbe-px",
+ "pbs-0",
+ "pbs-0.5",
+ "pbs-1",
+ "pbs-1.5",
+ "pbs-2",
+ "pbs-2.5",
+ "pbs-3",
+ "pbs-3.5",
+ "pbs-4",
+ "pbs-5",
+ "pbs-6",
+ "pbs-7",
+ "pbs-8",
+ "pbs-9",
+ "pbs-10",
+ "pbs-11",
+ "pbs-12",
+ "pbs-14",
+ "pbs-16",
+ "pbs-20",
+ "pbs-24",
+ "pbs-28",
+ "pbs-32",
+ "pbs-36",
+ "pbs-40",
+ "pbs-44",
+ "pbs-48",
+ "pbs-52",
+ "pbs-56",
+ "pbs-60",
+ "pbs-64",
+ "pbs-72",
+ "pbs-80",
+ "pbs-96",
+ "pbs-px",
"pe-0",
"pe-0.5",
"pe-1",
@@ -9097,6 +9563,76 @@ exports[`getClassList 1`] = `
"scroll-mb-80",
"scroll-mb-96",
"scroll-mb-px",
+ "scroll-mbe-0",
+ "scroll-mbe-0.5",
+ "scroll-mbe-1",
+ "scroll-mbe-1.5",
+ "scroll-mbe-2",
+ "scroll-mbe-2.5",
+ "scroll-mbe-3",
+ "scroll-mbe-3.5",
+ "scroll-mbe-4",
+ "scroll-mbe-5",
+ "scroll-mbe-6",
+ "scroll-mbe-7",
+ "scroll-mbe-8",
+ "scroll-mbe-9",
+ "scroll-mbe-10",
+ "scroll-mbe-11",
+ "scroll-mbe-12",
+ "scroll-mbe-14",
+ "scroll-mbe-16",
+ "scroll-mbe-20",
+ "scroll-mbe-24",
+ "scroll-mbe-28",
+ "scroll-mbe-32",
+ "scroll-mbe-36",
+ "scroll-mbe-40",
+ "scroll-mbe-44",
+ "scroll-mbe-48",
+ "scroll-mbe-52",
+ "scroll-mbe-56",
+ "scroll-mbe-60",
+ "scroll-mbe-64",
+ "scroll-mbe-72",
+ "scroll-mbe-80",
+ "scroll-mbe-96",
+ "scroll-mbe-px",
+ "scroll-mbs-0",
+ "scroll-mbs-0.5",
+ "scroll-mbs-1",
+ "scroll-mbs-1.5",
+ "scroll-mbs-2",
+ "scroll-mbs-2.5",
+ "scroll-mbs-3",
+ "scroll-mbs-3.5",
+ "scroll-mbs-4",
+ "scroll-mbs-5",
+ "scroll-mbs-6",
+ "scroll-mbs-7",
+ "scroll-mbs-8",
+ "scroll-mbs-9",
+ "scroll-mbs-10",
+ "scroll-mbs-11",
+ "scroll-mbs-12",
+ "scroll-mbs-14",
+ "scroll-mbs-16",
+ "scroll-mbs-20",
+ "scroll-mbs-24",
+ "scroll-mbs-28",
+ "scroll-mbs-32",
+ "scroll-mbs-36",
+ "scroll-mbs-40",
+ "scroll-mbs-44",
+ "scroll-mbs-48",
+ "scroll-mbs-52",
+ "scroll-mbs-56",
+ "scroll-mbs-60",
+ "scroll-mbs-64",
+ "scroll-mbs-72",
+ "scroll-mbs-80",
+ "scroll-mbs-96",
+ "scroll-mbs-px",
"scroll-me-0",
"scroll-me-0.5",
"scroll-me-1",
@@ -9412,6 +9948,76 @@ exports[`getClassList 1`] = `
"scroll-pb-80",
"scroll-pb-96",
"scroll-pb-px",
+ "scroll-pbe-0",
+ "scroll-pbe-0.5",
+ "scroll-pbe-1",
+ "scroll-pbe-1.5",
+ "scroll-pbe-2",
+ "scroll-pbe-2.5",
+ "scroll-pbe-3",
+ "scroll-pbe-3.5",
+ "scroll-pbe-4",
+ "scroll-pbe-5",
+ "scroll-pbe-6",
+ "scroll-pbe-7",
+ "scroll-pbe-8",
+ "scroll-pbe-9",
+ "scroll-pbe-10",
+ "scroll-pbe-11",
+ "scroll-pbe-12",
+ "scroll-pbe-14",
+ "scroll-pbe-16",
+ "scroll-pbe-20",
+ "scroll-pbe-24",
+ "scroll-pbe-28",
+ "scroll-pbe-32",
+ "scroll-pbe-36",
+ "scroll-pbe-40",
+ "scroll-pbe-44",
+ "scroll-pbe-48",
+ "scroll-pbe-52",
+ "scroll-pbe-56",
+ "scroll-pbe-60",
+ "scroll-pbe-64",
+ "scroll-pbe-72",
+ "scroll-pbe-80",
+ "scroll-pbe-96",
+ "scroll-pbe-px",
+ "scroll-pbs-0",
+ "scroll-pbs-0.5",
+ "scroll-pbs-1",
+ "scroll-pbs-1.5",
+ "scroll-pbs-2",
+ "scroll-pbs-2.5",
+ "scroll-pbs-3",
+ "scroll-pbs-3.5",
+ "scroll-pbs-4",
+ "scroll-pbs-5",
+ "scroll-pbs-6",
+ "scroll-pbs-7",
+ "scroll-pbs-8",
+ "scroll-pbs-9",
+ "scroll-pbs-10",
+ "scroll-pbs-11",
+ "scroll-pbs-12",
+ "scroll-pbs-14",
+ "scroll-pbs-16",
+ "scroll-pbs-20",
+ "scroll-pbs-24",
+ "scroll-pbs-28",
+ "scroll-pbs-32",
+ "scroll-pbs-36",
+ "scroll-pbs-40",
+ "scroll-pbs-44",
+ "scroll-pbs-48",
+ "scroll-pbs-52",
+ "scroll-pbs-56",
+ "scroll-pbs-60",
+ "scroll-pbs-64",
+ "scroll-pbs-72",
+ "scroll-pbs-80",
+ "scroll-pbs-96",
+ "scroll-pbs-px",
"scroll-pe-0",
"scroll-pe-0.5",
"scroll-pe-1",
diff --git a/packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap b/packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap
index 6adc96113d46..12bf1312a0cd 100644
--- a/packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap
@@ -370,6 +370,376 @@ exports[`border-b-* 1`] = `
}"
`;
+exports[`border-be-* 1`] = `
+"@layer properties {
+ @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
+ *, :before, :after, ::backdrop {
+ --tw-border-style: solid;
+ }
+ }
+}
+
+:root, :host {
+ --color-red-500: #ef4444;
+ --border-color-blue-500: #3b82f6;
+}
+
+.border-be {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 1px;
+}
+
+.border-be-0 {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 0;
+}
+
+.border-be-2 {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 2px;
+}
+
+.border-be-4 {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 4px;
+}
+
+.border-be-123 {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 123px;
+}
+
+.border-be-\\[0_1\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 0 1;
+}
+
+.border-be-\\[0_2px_0_2px\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 0 2px 0 2px;
+}
+
+.border-be-\\[12px\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 12px;
+}
+
+.border-be-\\[12px_8px\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: 12px 8px;
+}
+
+.border-be-\\[length\\:var\\(--my-width\\)\\], .border-be-\\[line-width\\:var\\(--my-width\\)\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: var(--my-width);
+}
+
+.border-be-\\[medium\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: medium;
+}
+
+.border-be-\\[thick\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: thick;
+}
+
+.border-be-\\[thin\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: thin;
+}
+
+.border-be-\\[thin_2px\\] {
+ border-block-end-style: var(--tw-border-style);
+ border-block-end-width: thin 2px;
+}
+
+.border-be-\\[\\#0088cc\\] {
+ border-block-end-color: #08c;
+}
+
+.border-be-\\[\\#0088cc\\]\\/50 {
+ border-block-end-color: oklab(59.9824% -.067 -.124 / .5);
+}
+
+.border-be-\\[color\\:var\\(--my-color\\)\\], .border-be-\\[color\\:var\\(--my-color\\)\\]\\/50 {
+ border-block-end-color: var(--my-color);
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-\\[color\\:var\\(--my-color\\)\\]\\/50 {
+ border-block-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
+ }
+}
+
+.border-be-\\[var\\(--my-color\\)\\], .border-be-\\[var\\(--my-color\\)\\]\\/50 {
+ border-block-end-color: var(--my-color);
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-\\[var\\(--my-color\\)\\]\\/50 {
+ border-block-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
+ }
+}
+
+.border-be-blue-500 {
+ border-block-end-color: var(--border-color-blue-500);
+}
+
+.border-be-current, .border-be-current\\/50 {
+ border-block-end-color: currentColor;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-current\\/50 {
+ border-block-end-color: color-mix(in oklab, currentcolor 50%, transparent);
+ }
+}
+
+.border-be-inherit {
+ border-block-end-color: inherit;
+}
+
+.border-be-red-500 {
+ border-block-end-color: var(--color-red-500);
+}
+
+.border-be-red-500\\/2\\.5 {
+ border-block-end-color: #ef444406;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-red-500\\/2\\.5 {
+ border-block-end-color: color-mix(in oklab, var(--color-red-500) 2.5%, transparent);
+ }
+}
+
+.border-be-red-500\\/2\\.25 {
+ border-block-end-color: #ef444406;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-red-500\\/2\\.25 {
+ border-block-end-color: color-mix(in oklab, var(--color-red-500) 2.25%, transparent);
+ }
+}
+
+.border-be-red-500\\/2\\.75 {
+ border-block-end-color: #ef444407;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-red-500\\/2\\.75 {
+ border-block-end-color: color-mix(in oklab, var(--color-red-500) 2.75%, transparent);
+ }
+}
+
+.border-be-red-500\\/50 {
+ border-block-end-color: #ef444480;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-be-red-500\\/50 {
+ border-block-end-color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
+ }
+}
+
+.border-be-transparent {
+ border-block-end-color: #0000;
+}
+
+@property --tw-border-style {
+ syntax: "*";
+ inherits: false;
+ initial-value: solid;
+}"
+`;
+
+exports[`border-bs-* 1`] = `
+"@layer properties {
+ @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
+ *, :before, :after, ::backdrop {
+ --tw-border-style: solid;
+ }
+ }
+}
+
+:root, :host {
+ --color-red-500: #ef4444;
+ --border-color-blue-500: #3b82f6;
+}
+
+.border-bs {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 1px;
+}
+
+.border-bs-0 {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 0;
+}
+
+.border-bs-2 {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 2px;
+}
+
+.border-bs-4 {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 4px;
+}
+
+.border-bs-123 {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 123px;
+}
+
+.border-bs-\\[0_1\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 0 1;
+}
+
+.border-bs-\\[0_2px_0_2px\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 0 2px 0 2px;
+}
+
+.border-bs-\\[12px\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 12px;
+}
+
+.border-bs-\\[12px_8px\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: 12px 8px;
+}
+
+.border-bs-\\[length\\:var\\(--my-width\\)\\], .border-bs-\\[line-width\\:var\\(--my-width\\)\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: var(--my-width);
+}
+
+.border-bs-\\[medium\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: medium;
+}
+
+.border-bs-\\[thick\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: thick;
+}
+
+.border-bs-\\[thin\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: thin;
+}
+
+.border-bs-\\[thin_2px\\] {
+ border-block-start-style: var(--tw-border-style);
+ border-block-start-width: thin 2px;
+}
+
+.border-bs-\\[\\#0088cc\\] {
+ border-block-start-color: #08c;
+}
+
+.border-bs-\\[\\#0088cc\\]\\/50 {
+ border-block-start-color: oklab(59.9824% -.067 -.124 / .5);
+}
+
+.border-bs-\\[color\\:var\\(--my-color\\)\\], .border-bs-\\[color\\:var\\(--my-color\\)\\]\\/50 {
+ border-block-start-color: var(--my-color);
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-\\[color\\:var\\(--my-color\\)\\]\\/50 {
+ border-block-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
+ }
+}
+
+.border-bs-\\[var\\(--my-color\\)\\], .border-bs-\\[var\\(--my-color\\)\\]\\/50 {
+ border-block-start-color: var(--my-color);
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-\\[var\\(--my-color\\)\\]\\/50 {
+ border-block-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
+ }
+}
+
+.border-bs-blue-500 {
+ border-block-start-color: var(--border-color-blue-500);
+}
+
+.border-bs-current, .border-bs-current\\/50 {
+ border-block-start-color: currentColor;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-current\\/50 {
+ border-block-start-color: color-mix(in oklab, currentcolor 50%, transparent);
+ }
+}
+
+.border-bs-inherit {
+ border-block-start-color: inherit;
+}
+
+.border-bs-red-500 {
+ border-block-start-color: var(--color-red-500);
+}
+
+.border-bs-red-500\\/2\\.5 {
+ border-block-start-color: #ef444406;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-red-500\\/2\\.5 {
+ border-block-start-color: color-mix(in oklab, var(--color-red-500) 2.5%, transparent);
+ }
+}
+
+.border-bs-red-500\\/2\\.25 {
+ border-block-start-color: #ef444406;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-red-500\\/2\\.25 {
+ border-block-start-color: color-mix(in oklab, var(--color-red-500) 2.25%, transparent);
+ }
+}
+
+.border-bs-red-500\\/2\\.75 {
+ border-block-start-color: #ef444407;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-red-500\\/2\\.75 {
+ border-block-start-color: color-mix(in oklab, var(--color-red-500) 2.75%, transparent);
+ }
+}
+
+.border-bs-red-500\\/50 {
+ border-block-start-color: #ef444480;
+}
+
+@supports (color: color-mix(in lab, red, red)) {
+ .border-bs-red-500\\/50 {
+ border-block-start-color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
+ }
+}
+
+.border-bs-transparent {
+ border-block-start-color: #0000;
+}
+
+@property --tw-border-style {
+ syntax: "*";
+ inherits: false;
+ initial-value: solid;
+}"
+`;
+
exports[`border-e-* 1`] = `
"@layer properties {
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
diff --git a/packages/tailwindcss/src/property-order.ts b/packages/tailwindcss/src/property-order.ts
index f024f69771a0..03d0440ae083 100644
--- a/packages/tailwindcss/src/property-order.ts
+++ b/packages/tailwindcss/src/property-order.ts
@@ -39,6 +39,8 @@ export default [
'margin-block',
'margin-inline-start',
'margin-inline-end',
+ 'margin-block-start',
+ 'margin-block-end',
'margin-top',
'margin-right',
'margin-bottom',
@@ -108,6 +110,8 @@ export default [
'scroll-margin-block',
'scroll-margin-inline-start',
'scroll-margin-inline-end',
+ 'scroll-margin-block-start',
+ 'scroll-margin-block-end',
'scroll-margin-top',
'scroll-margin-right',
'scroll-margin-bottom',
@@ -118,6 +122,8 @@ export default [
'scroll-padding-block',
'scroll-padding-inline-start',
'scroll-padding-inline-end',
+ 'scroll-padding-block-start',
+ 'scroll-padding-block-end',
'scroll-padding-top',
'scroll-padding-right',
'scroll-padding-bottom',
@@ -196,6 +202,8 @@ export default [
'border-block-width',
'border-inline-start-width',
'border-inline-end-width',
+ 'border-block-start-width',
+ 'border-block-end-width',
'border-top-width',
'border-right-width',
'border-bottom-width',
@@ -206,6 +214,8 @@ export default [
'border-block-style',
'border-inline-start-style',
'border-inline-end-style',
+ 'border-block-start-style',
+ 'border-block-end-style',
'border-top-style',
'border-right-style',
'border-bottom-style',
@@ -216,6 +226,8 @@ export default [
'border-block-color',
'border-inline-start-color',
'border-inline-end-color',
+ 'border-block-start-color',
+ 'border-block-end-color',
'border-top-color',
'border-right-color',
'border-bottom-color',
@@ -317,6 +329,8 @@ export default [
'padding-block',
'padding-inline-start',
'padding-inline-end',
+ 'padding-block-start',
+ 'padding-block-end',
'padding-top',
'padding-right',
'padding-bottom',
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index cff2284f45c9..a5991ebfac7a 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -2216,6 +2216,178 @@ test('me', async () => {
).toEqual('')
})
+test('mbs', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing: 0.25rem;
+ --spacing-big: 100rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'mbs-1',
+ 'mbs-99',
+ 'mbs-2.5',
+ 'mbs-big',
+ 'mbs-[4px]',
+ '-mbs-4',
+ '-mbs-2.5',
+ '-mbs-big',
+ '-mbs-[4px]',
+ 'mbs-[var(--my-var)]',
+ '-mbs-[var(--my-var)]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing: .25rem;
+ --spacing-big: 100rem;
+ }
+
+ .-mbs-2\\.5 {
+ margin-block-start: calc(var(--spacing) * -2.5);
+ }
+
+ .-mbs-4 {
+ margin-block-start: calc(var(--spacing) * -4);
+ }
+
+ .-mbs-\\[4px\\] {
+ margin-block-start: -4px;
+ }
+
+ .-mbs-\\[var\\(--my-var\\)\\] {
+ margin-block-start: calc(var(--my-var) * -1);
+ }
+
+ .-mbs-big {
+ margin-block-start: calc(var(--spacing-big) * -1);
+ }
+
+ .mbs-1 {
+ margin-block-start: calc(var(--spacing) * 1);
+ }
+
+ .mbs-2\\.5 {
+ margin-block-start: calc(var(--spacing) * 2.5);
+ }
+
+ .mbs-99 {
+ margin-block-start: calc(var(--spacing) * 99);
+ }
+
+ .mbs-\\[4px\\] {
+ margin-block-start: 4px;
+ }
+
+ .mbs-\\[var\\(--my-var\\)\\] {
+ margin-block-start: var(--my-var);
+ }
+
+ .mbs-big {
+ margin-block-start: var(--spacing-big);
+ }"
+ `)
+ expect(
+ await run([
+ 'mbs',
+ 'mbs-auto/foo',
+ 'mbs-4/foo',
+ 'mbs-[4px]/foo',
+ '-mbs-4/foo',
+ '-mbs-[var(--value)]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('mbe', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing: 0.25rem;
+ --spacing-big: 100rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'mbe-1',
+ 'mbe-99',
+ 'mbe-2.5',
+ 'mbe-big',
+ 'mbe-[4px]',
+ '-mbe-4',
+ '-mbe-2.5',
+ '-mbe-big',
+ '-mbe-[4px]',
+ 'mbe-[var(--my-var)]',
+ '-mbe-[var(--my-var)]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing: .25rem;
+ --spacing-big: 100rem;
+ }
+
+ .-mbe-2\\.5 {
+ margin-block-end: calc(var(--spacing) * -2.5);
+ }
+
+ .-mbe-4 {
+ margin-block-end: calc(var(--spacing) * -4);
+ }
+
+ .-mbe-\\[4px\\] {
+ margin-block-end: -4px;
+ }
+
+ .-mbe-\\[var\\(--my-var\\)\\] {
+ margin-block-end: calc(var(--my-var) * -1);
+ }
+
+ .-mbe-big {
+ margin-block-end: calc(var(--spacing-big) * -1);
+ }
+
+ .mbe-1 {
+ margin-block-end: calc(var(--spacing) * 1);
+ }
+
+ .mbe-2\\.5 {
+ margin-block-end: calc(var(--spacing) * 2.5);
+ }
+
+ .mbe-99 {
+ margin-block-end: calc(var(--spacing) * 99);
+ }
+
+ .mbe-\\[4px\\] {
+ margin-block-end: 4px;
+ }
+
+ .mbe-\\[var\\(--my-var\\)\\] {
+ margin-block-end: var(--my-var);
+ }
+
+ .mbe-big {
+ margin-block-end: var(--spacing-big);
+ }"
+ `)
+ expect(
+ await run([
+ 'mbe',
+ 'mbe-auto/foo',
+ 'mbe-4/foo',
+ 'mbe-[4px]/foo',
+ '-mbe-4/foo',
+ '-mbe-[var(--value)]/foo',
+ ]),
+ ).toEqual('')
+})
+
test('mr', async () => {
expect(
await compileCss(
@@ -6669,6 +6841,92 @@ test('scroll-me', async () => {
).toEqual('')
})
+test('scroll-mbs', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ ['scroll-mbs-4', 'scroll-mbs-[4px]', '-scroll-mbs-4', '-scroll-mbs-[var(--value)]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .-scroll-mbs-4 {
+ scroll-margin-block-start: calc(var(--spacing-4) * -1);
+ }
+
+ .-scroll-mbs-\\[var\\(--value\\)\\] {
+ scroll-margin-block-start: calc(var(--value) * -1);
+ }
+
+ .scroll-mbs-4 {
+ scroll-margin-block-start: var(--spacing-4);
+ }
+
+ .scroll-mbs-\\[4px\\] {
+ scroll-margin-block-start: 4px;
+ }"
+ `)
+ expect(
+ await run([
+ 'scroll-mbs',
+ 'scroll-mbs-4/foo',
+ 'scroll-mbs-[4px]/foo',
+ '-scroll-mbs-4/foo',
+ '-scroll-mbs-[var(--value)]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('scroll-mbe', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ ['scroll-mbe-4', 'scroll-mbe-[4px]', '-scroll-mbe-4', '-scroll-mbe-[var(--value)]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .-scroll-mbe-4 {
+ scroll-margin-block-end: calc(var(--spacing-4) * -1);
+ }
+
+ .-scroll-mbe-\\[var\\(--value\\)\\] {
+ scroll-margin-block-end: calc(var(--value) * -1);
+ }
+
+ .scroll-mbe-4 {
+ scroll-margin-block-end: var(--spacing-4);
+ }
+
+ .scroll-mbe-\\[4px\\] {
+ scroll-margin-block-end: 4px;
+ }"
+ `)
+ expect(
+ await run([
+ 'scroll-mbe',
+ 'scroll-mbe-4/foo',
+ 'scroll-mbe-[4px]/foo',
+ '-scroll-mbe-4/foo',
+ '-scroll-mbe-[var(--value)]/foo',
+ ]),
+ ).toEqual('')
+})
+
test('scroll-mt', async () => {
expect(
await compileCss(
@@ -7016,6 +7274,76 @@ test('scroll-pe', async () => {
).toEqual('')
})
+test('scroll-pbs', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ ['scroll-pbs-4', 'scroll-pbs-[4px]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .scroll-pbs-4 {
+ scroll-padding-block-start: var(--spacing-4);
+ }
+
+ .scroll-pbs-\\[4px\\] {
+ scroll-padding-block-start: 4px;
+ }"
+ `)
+ expect(
+ await run([
+ 'scroll-pbs',
+ 'scroll-pbs-4/foo',
+ 'scroll-pbs-[4px]/foo',
+ '-scroll-pbs-4',
+ '-scroll-pbs-[var(--value)]',
+ ]),
+ ).toEqual('')
+})
+
+test('scroll-pbe', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ ['scroll-pbe-4', 'scroll-pbe-[4px]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .scroll-pbe-4 {
+ scroll-padding-block-end: var(--spacing-4);
+ }
+
+ .scroll-pbe-\\[4px\\] {
+ scroll-padding-block-end: 4px;
+ }"
+ `)
+ expect(
+ await run([
+ 'scroll-pbe',
+ 'scroll-pbe-4/foo',
+ 'scroll-pbe-[4px]/foo',
+ '-scroll-pbe-4',
+ '-scroll-pbe-[var(--value)]',
+ ]),
+ ).toEqual('')
+})
+
test('scroll-pt', async () => {
expect(
await compileCss(
@@ -11119,6 +11447,8 @@ const prefixes = [
'border-y',
'border-s',
'border-e',
+ 'border-bs',
+ 'border-be',
'border-t',
'border-r',
'border-b',
@@ -20693,6 +21023,88 @@ test('pe', async () => {
expect(await run(['pe', '-pe-4', '-pe-[4px]', 'pe-4/foo', 'pe-[4px]/foo'])).toEqual('')
})
+test('pbs', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing: 0.25rem;
+ --spacing-big: 100rem;
+ }
+ @tailwind utilities;
+ `,
+ ['pbs-1', 'pbs-4', 'pbs-99', 'pbs-big', 'pbs-[4px]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing: .25rem;
+ --spacing-big: 100rem;
+ }
+
+ .pbs-1 {
+ padding-block-start: calc(var(--spacing) * 1);
+ }
+
+ .pbs-4 {
+ padding-block-start: calc(var(--spacing) * 4);
+ }
+
+ .pbs-99 {
+ padding-block-start: calc(var(--spacing) * 99);
+ }
+
+ .pbs-\\[4px\\] {
+ padding-block-start: 4px;
+ }
+
+ .pbs-big {
+ padding-block-start: var(--spacing-big);
+ }"
+ `)
+ expect(await run(['pbs', '-pbs-4', '-pbs-[4px]', 'pbs-4/foo', 'pbs-[4px]/foo'])).toEqual('')
+})
+
+test('pbe', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing: 0.25rem;
+ --spacing-big: 100rem;
+ }
+ @tailwind utilities;
+ `,
+ ['pbe-1', 'pbe-4', 'pbe-99', 'pbe-big', 'pbe-[4px]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing: .25rem;
+ --spacing-big: 100rem;
+ }
+
+ .pbe-1 {
+ padding-block-end: calc(var(--spacing) * 1);
+ }
+
+ .pbe-4 {
+ padding-block-end: calc(var(--spacing) * 4);
+ }
+
+ .pbe-99 {
+ padding-block-end: calc(var(--spacing) * 99);
+ }
+
+ .pbe-\\[4px\\] {
+ padding-block-end: 4px;
+ }
+
+ .pbe-big {
+ padding-block-end: var(--spacing-big);
+ }"
+ `)
+ expect(await run(['pbe', '-pbe-4', '-pbe-[4px]', 'pbe-4/foo', 'pbe-[4px]/foo'])).toEqual('')
+})
+
test('pr', async () => {
expect(
await compileCss(
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index e1c84ce00890..be6a4ebe7080 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -888,6 +888,8 @@ export function createUtilities(theme: Theme) {
['my', 'margin-block'],
['ms', 'margin-inline-start'],
['me', 'margin-inline-end'],
+ ['mbs', 'margin-block-start'],
+ ['mbe', 'margin-block-end'],
['mt', 'margin-top'],
['mr', 'margin-right'],
['mb', 'margin-bottom'],
@@ -1774,6 +1776,8 @@ export function createUtilities(theme: Theme) {
['scroll-my', 'scroll-margin-block'],
['scroll-ms', 'scroll-margin-inline-start'],
['scroll-me', 'scroll-margin-inline-end'],
+ ['scroll-mbs', 'scroll-margin-block-start'],
+ ['scroll-mbe', 'scroll-margin-block-end'],
['scroll-mt', 'scroll-margin-top'],
['scroll-mr', 'scroll-margin-right'],
['scroll-mb', 'scroll-margin-bottom'],
@@ -1798,6 +1802,8 @@ export function createUtilities(theme: Theme) {
['scroll-py', 'scroll-padding-block'],
['scroll-ps', 'scroll-padding-inline-start'],
['scroll-pe', 'scroll-padding-inline-end'],
+ ['scroll-pbs', 'scroll-padding-block-start'],
+ ['scroll-pbe', 'scroll-padding-block-end'],
['scroll-pt', 'scroll-padding-top'],
['scroll-pr', 'scroll-padding-right'],
['scroll-pb', 'scroll-padding-bottom'],
@@ -2344,6 +2350,22 @@ export function createUtilities(theme: Theme) {
color: (value) => [decl('border-inline-end-color', value)],
})
+ borderSideUtility('border-bs', {
+ width: (value) => [
+ decl('border-block-start-style', 'var(--tw-border-style)'),
+ decl('border-block-start-width', value),
+ ],
+ color: (value) => [decl('border-block-start-color', value)],
+ })
+
+ borderSideUtility('border-be', {
+ width: (value) => [
+ decl('border-block-end-style', 'var(--tw-border-style)'),
+ decl('border-block-end-width', value),
+ ],
+ color: (value) => [decl('border-block-end-color', value)],
+ })
+
borderSideUtility('border-t', {
width: (value) => [
decl('border-top-style', 'var(--tw-border-style)'),
@@ -3706,6 +3728,8 @@ export function createUtilities(theme: Theme) {
['py', 'padding-block'],
['ps', 'padding-inline-start'],
['pe', 'padding-inline-end'],
+ ['pbs', 'padding-block-start'],
+ ['pbe', 'padding-block-end'],
['pt', 'padding-top'],
['pr', 'padding-right'],
['pb', 'padding-bottom'],
From 3d1e654c022362f75643a00f9b6407e4822f5202 Mon Sep 17 00:00:00 2001
From: Adam Wathan
Date: Fri, 30 Jan 2026 14:46:37 +0100
Subject: [PATCH 05/40] Add logical sizing utilities (inline-size, block-size)
(#19612)
## Summary
Adds new utilities for CSS logical properties that provide
writing-direction-aware alternatives to width and height:
- `inline-*` for `inline-size` (logical equivalent of width)
- `min-inline-*` for `min-inline-size` (logical equivalent of min-width)
- `max-inline-*` for `max-inline-size` (logical equivalent of max-width)
- `block-*` for `block-size` (logical equivalent of height)
- `min-block-*` for `min-block-size` (logical equivalent of min-height)
- `max-block-*` for `max-block-size` (logical equivalent of max-height)
## New Utilities
### inline-size utilities
| Class | CSS Property |
|-------|-------------|
| `inline-auto` | `inline-size: auto` |
| `inline-full` | `inline-size: 100%` |
| `inline-min` | `inline-size: min-content` |
| `inline-max` | `inline-size: max-content` |
| `inline-fit` | `inline-size: fit-content` |
| `inline-screen` | `inline-size: 100vw` |
| `inline-svw` | `inline-size: 100svw` |
| `inline-lvw` | `inline-size: 100lvw` |
| `inline-dvw` | `inline-size: 100dvw` |
| `inline-{spacing}` | `inline-size: {value}` (e.g., `inline-4`,
`inline-px`) |
| `inline-{fraction}` | `inline-size: {percent}` (e.g., `inline-1/2`,
`inline-3/4`) |
| `inline-[{value}]` | `inline-size: {value}` (arbitrary values) |
### min-inline-size utilities
| Class | CSS Property |
|-------|-------------|
| `min-inline-auto` | `min-inline-size: auto` |
| `min-inline-full` | `min-inline-size: 100%` |
| `min-inline-min` | `min-inline-size: min-content` |
| `min-inline-max` | `min-inline-size: max-content` |
| `min-inline-fit` | `min-inline-size: fit-content` |
| `min-inline-screen` | `min-inline-size: 100vw` |
| `min-inline-svw` | `min-inline-size: 100svw` |
| `min-inline-lvw` | `min-inline-size: 100lvw` |
| `min-inline-dvw` | `min-inline-size: 100dvw` |
| `min-inline-{spacing}` | `min-inline-size: {value}` |
| `min-inline-[{value}]` | `min-inline-size: {value}` (arbitrary values)
|
### max-inline-size utilities
| Class | CSS Property |
|-------|-------------|
| `max-inline-none` | `max-inline-size: none` |
| `max-inline-full` | `max-inline-size: 100%` |
| `max-inline-min` | `max-inline-size: min-content` |
| `max-inline-max` | `max-inline-size: max-content` |
| `max-inline-fit` | `max-inline-size: fit-content` |
| `max-inline-screen` | `max-inline-size: 100vw` |
| `max-inline-svw` | `max-inline-size: 100svw` |
| `max-inline-lvw` | `max-inline-size: 100lvw` |
| `max-inline-dvw` | `max-inline-size: 100dvw` |
| `max-inline-{spacing}` | `max-inline-size: {value}` |
| `max-inline-[{value}]` | `max-inline-size: {value}` (arbitrary values)
|
### block-size utilities
| Class | CSS Property |
|-------|-------------|
| `block-auto` | `block-size: auto` |
| `block-full` | `block-size: 100%` |
| `block-min` | `block-size: min-content` |
| `block-max` | `block-size: max-content` |
| `block-fit` | `block-size: fit-content` |
| `block-screen` | `block-size: 100vh` |
| `block-lh` | `block-size: 1lh` |
| `block-svh` | `block-size: 100svh` |
| `block-lvh` | `block-size: 100lvh` |
| `block-dvh` | `block-size: 100dvh` |
| `block-{spacing}` | `block-size: {value}` (e.g., `block-4`,
`block-px`) |
| `block-{fraction}` | `block-size: {percent}` (e.g., `block-1/2`,
`block-3/4`) |
| `block-[{value}]` | `block-size: {value}` (arbitrary values) |
### min-block-size utilities
| Class | CSS Property |
|-------|-------------|
| `min-block-auto` | `min-block-size: auto` |
| `min-block-full` | `min-block-size: 100%` |
| `min-block-min` | `min-block-size: min-content` |
| `min-block-max` | `min-block-size: max-content` |
| `min-block-fit` | `min-block-size: fit-content` |
| `min-block-screen` | `min-block-size: 100vh` |
| `min-block-lh` | `min-block-size: 1lh` |
| `min-block-svh` | `min-block-size: 100svh` |
| `min-block-lvh` | `min-block-size: 100lvh` |
| `min-block-dvh` | `min-block-size: 100dvh` |
| `min-block-{spacing}` | `min-block-size: {value}` |
| `min-block-[{value}]` | `min-block-size: {value}` (arbitrary values) |
### max-block-size utilities
| Class | CSS Property |
|-------|-------------|
| `max-block-none` | `max-block-size: none` |
| `max-block-full` | `max-block-size: 100%` |
| `max-block-min` | `max-block-size: min-content` |
| `max-block-max` | `max-block-size: max-content` |
| `max-block-fit` | `max-block-size: fit-content` |
| `max-block-screen` | `max-block-size: 100vh` |
| `max-block-lh` | `max-block-size: 1lh` |
| `max-block-svh` | `max-block-size: 100svh` |
| `max-block-lvh` | `max-block-size: 100lvh` |
| `max-block-dvh` | `max-block-size: 100dvh` |
| `max-block-{spacing}` | `max-block-size: {value}` |
| `max-block-[{value}]` | `max-block-size: {value}` (arbitrary values) |
## Test plan
- [x] Added comprehensive unit tests for all new utilities
- [ ] Verify utilities work correctly in RTL layouts
- [ ] Test with vertical writing modes
---------
Co-authored-by: Claude
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
.../__snapshots__/intellisense.test.ts.snap | 429 ++++++++++++++
packages/tailwindcss/src/utilities.test.ts | 555 ++++++++++++++++++
packages/tailwindcss/src/utilities.ts | 76 +++
4 files changed, 1061 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc4d2a301536..607302b3042b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
+- Add `inline-*`, `min-inline-*`, `max-inline-*`, `block-*`, `min-block-*`, `max-block-*` utilities for `inline-size`, `min-inline-size`, `max-inline-size`, `block-size`, `min-block-size`, and `max-block-size` ([#19612](https://github.com/tailwindlabs/tailwindcss/pull/19612))
## [4.1.18] - 2025-12-11
diff --git a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
index 759d91443c1c..87d882840d6c 100644
--- a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
@@ -2714,6 +2714,77 @@ exports[`getClassList 1`] = `
"bg-transparent/95",
"bg-transparent/100",
"block",
+ "block-0",
+ "block-0.5",
+ "block-1",
+ "block-1.5",
+ "block-2",
+ "block-2.5",
+ "block-3",
+ "block-3.5",
+ "block-4",
+ "block-5",
+ "block-6",
+ "block-7",
+ "block-8",
+ "block-9",
+ "block-10",
+ "block-11",
+ "block-12",
+ "block-14",
+ "block-16",
+ "block-20",
+ "block-24",
+ "block-28",
+ "block-32",
+ "block-36",
+ "block-40",
+ "block-44",
+ "block-48",
+ "block-52",
+ "block-56",
+ "block-60",
+ "block-64",
+ "block-72",
+ "block-80",
+ "block-96",
+ "block-1/2",
+ "block-1/3",
+ "block-1/4",
+ "block-1/5",
+ "block-1/6",
+ "block-1/12",
+ "block-2/3",
+ "block-2/4",
+ "block-2/5",
+ "block-2/6",
+ "block-2/12",
+ "block-3/4",
+ "block-3/5",
+ "block-3/6",
+ "block-3/12",
+ "block-4/5",
+ "block-4/6",
+ "block-4/12",
+ "block-5/6",
+ "block-5/12",
+ "block-6/12",
+ "block-7/12",
+ "block-8/12",
+ "block-9/12",
+ "block-10/12",
+ "block-11/12",
+ "block-auto",
+ "block-dvh",
+ "block-fit",
+ "block-full",
+ "block-lh",
+ "block-lvh",
+ "block-max",
+ "block-min",
+ "block-px",
+ "block-screen",
+ "block-svh",
"blur-none",
"border",
"border/0",
@@ -4952,9 +5023,81 @@ exports[`getClassList 1`] = `
"indent-96",
"indent-px",
"inline",
+ "inline-0",
+ "inline-0.5",
+ "inline-1",
+ "inline-1.5",
+ "inline-2",
+ "inline-2.5",
+ "inline-3",
+ "inline-3.5",
+ "inline-4",
+ "inline-5",
+ "inline-6",
+ "inline-7",
+ "inline-8",
+ "inline-9",
+ "inline-10",
+ "inline-11",
+ "inline-12",
+ "inline-14",
+ "inline-16",
+ "inline-20",
+ "inline-24",
+ "inline-28",
+ "inline-32",
+ "inline-36",
+ "inline-40",
+ "inline-44",
+ "inline-48",
+ "inline-52",
+ "inline-56",
+ "inline-60",
+ "inline-64",
+ "inline-72",
+ "inline-80",
+ "inline-96",
+ "inline-auto",
"inline-block",
+ "inline-dvw",
+ "inline-fit",
"inline-flex",
+ "inline-full",
"inline-grid",
+ "inline-lg",
+ "inline-lvw",
+ "inline-max",
+ "inline-md",
+ "inline-1/2",
+ "inline-1/3",
+ "inline-1/4",
+ "inline-1/5",
+ "inline-1/6",
+ "inline-1/12",
+ "inline-2/3",
+ "inline-2/4",
+ "inline-2/5",
+ "inline-2/6",
+ "inline-2/12",
+ "inline-3/4",
+ "inline-3/5",
+ "inline-3/6",
+ "inline-3/12",
+ "inline-4/5",
+ "inline-4/6",
+ "inline-4/12",
+ "inline-5/6",
+ "inline-5/12",
+ "inline-6/12",
+ "inline-7/12",
+ "inline-8/12",
+ "inline-9/12",
+ "inline-10/12",
+ "inline-11/12",
+ "inline-min",
+ "inline-px",
+ "inline-screen",
+ "inline-svw",
"inline-table",
"inset-0",
"inset-0.5",
@@ -7754,6 +7897,77 @@ exports[`getClassList 1`] = `
"mask-y-to-transparent/90",
"mask-y-to-transparent/95",
"mask-y-to-transparent/100",
+ "max-block-0",
+ "max-block-0.5",
+ "max-block-1",
+ "max-block-1.5",
+ "max-block-2",
+ "max-block-2.5",
+ "max-block-3",
+ "max-block-3.5",
+ "max-block-4",
+ "max-block-5",
+ "max-block-6",
+ "max-block-7",
+ "max-block-8",
+ "max-block-9",
+ "max-block-10",
+ "max-block-11",
+ "max-block-12",
+ "max-block-14",
+ "max-block-16",
+ "max-block-20",
+ "max-block-24",
+ "max-block-28",
+ "max-block-32",
+ "max-block-36",
+ "max-block-40",
+ "max-block-44",
+ "max-block-48",
+ "max-block-52",
+ "max-block-56",
+ "max-block-60",
+ "max-block-64",
+ "max-block-72",
+ "max-block-80",
+ "max-block-96",
+ "max-block-1/2",
+ "max-block-1/3",
+ "max-block-1/4",
+ "max-block-1/5",
+ "max-block-1/6",
+ "max-block-1/12",
+ "max-block-2/3",
+ "max-block-2/4",
+ "max-block-2/5",
+ "max-block-2/6",
+ "max-block-2/12",
+ "max-block-3/4",
+ "max-block-3/5",
+ "max-block-3/6",
+ "max-block-3/12",
+ "max-block-4/5",
+ "max-block-4/6",
+ "max-block-4/12",
+ "max-block-5/6",
+ "max-block-5/12",
+ "max-block-6/12",
+ "max-block-7/12",
+ "max-block-8/12",
+ "max-block-9/12",
+ "max-block-10/12",
+ "max-block-11/12",
+ "max-block-dvh",
+ "max-block-fit",
+ "max-block-full",
+ "max-block-lh",
+ "max-block-lvh",
+ "max-block-max",
+ "max-block-min",
+ "max-block-none",
+ "max-block-px",
+ "max-block-screen",
+ "max-block-svh",
"max-h-0",
"max-h-0.5",
"max-h-1",
@@ -7828,6 +8042,78 @@ exports[`getClassList 1`] = `
"max-h-screen",
"max-h-svh",
"max-h-svw",
+ "max-inline-0",
+ "max-inline-0.5",
+ "max-inline-1",
+ "max-inline-1.5",
+ "max-inline-2",
+ "max-inline-2.5",
+ "max-inline-3",
+ "max-inline-3.5",
+ "max-inline-4",
+ "max-inline-5",
+ "max-inline-6",
+ "max-inline-7",
+ "max-inline-8",
+ "max-inline-9",
+ "max-inline-10",
+ "max-inline-11",
+ "max-inline-12",
+ "max-inline-14",
+ "max-inline-16",
+ "max-inline-20",
+ "max-inline-24",
+ "max-inline-28",
+ "max-inline-32",
+ "max-inline-36",
+ "max-inline-40",
+ "max-inline-44",
+ "max-inline-48",
+ "max-inline-52",
+ "max-inline-56",
+ "max-inline-60",
+ "max-inline-64",
+ "max-inline-72",
+ "max-inline-80",
+ "max-inline-96",
+ "max-inline-dvw",
+ "max-inline-fit",
+ "max-inline-full",
+ "max-inline-lg",
+ "max-inline-lvw",
+ "max-inline-max",
+ "max-inline-md",
+ "max-inline-1/2",
+ "max-inline-1/3",
+ "max-inline-1/4",
+ "max-inline-1/5",
+ "max-inline-1/6",
+ "max-inline-1/12",
+ "max-inline-2/3",
+ "max-inline-2/4",
+ "max-inline-2/5",
+ "max-inline-2/6",
+ "max-inline-2/12",
+ "max-inline-3/4",
+ "max-inline-3/5",
+ "max-inline-3/6",
+ "max-inline-3/12",
+ "max-inline-4/5",
+ "max-inline-4/6",
+ "max-inline-4/12",
+ "max-inline-5/6",
+ "max-inline-5/12",
+ "max-inline-6/12",
+ "max-inline-7/12",
+ "max-inline-8/12",
+ "max-inline-9/12",
+ "max-inline-10/12",
+ "max-inline-11/12",
+ "max-inline-min",
+ "max-inline-none",
+ "max-inline-px",
+ "max-inline-screen",
+ "max-inline-svw",
"max-w-0",
"max-w-0.5",
"max-w-1",
@@ -8046,6 +8332,77 @@ exports[`getClassList 1`] = `
"me-96",
"me-auto",
"me-px",
+ "min-block-0",
+ "min-block-0.5",
+ "min-block-1",
+ "min-block-1.5",
+ "min-block-2",
+ "min-block-2.5",
+ "min-block-3",
+ "min-block-3.5",
+ "min-block-4",
+ "min-block-5",
+ "min-block-6",
+ "min-block-7",
+ "min-block-8",
+ "min-block-9",
+ "min-block-10",
+ "min-block-11",
+ "min-block-12",
+ "min-block-14",
+ "min-block-16",
+ "min-block-20",
+ "min-block-24",
+ "min-block-28",
+ "min-block-32",
+ "min-block-36",
+ "min-block-40",
+ "min-block-44",
+ "min-block-48",
+ "min-block-52",
+ "min-block-56",
+ "min-block-60",
+ "min-block-64",
+ "min-block-72",
+ "min-block-80",
+ "min-block-96",
+ "min-block-1/2",
+ "min-block-1/3",
+ "min-block-1/4",
+ "min-block-1/5",
+ "min-block-1/6",
+ "min-block-1/12",
+ "min-block-2/3",
+ "min-block-2/4",
+ "min-block-2/5",
+ "min-block-2/6",
+ "min-block-2/12",
+ "min-block-3/4",
+ "min-block-3/5",
+ "min-block-3/6",
+ "min-block-3/12",
+ "min-block-4/5",
+ "min-block-4/6",
+ "min-block-4/12",
+ "min-block-5/6",
+ "min-block-5/12",
+ "min-block-6/12",
+ "min-block-7/12",
+ "min-block-8/12",
+ "min-block-9/12",
+ "min-block-10/12",
+ "min-block-11/12",
+ "min-block-auto",
+ "min-block-dvh",
+ "min-block-fit",
+ "min-block-full",
+ "min-block-lh",
+ "min-block-lvh",
+ "min-block-max",
+ "min-block-min",
+ "min-block-px",
+ "min-block-screen",
+ "min-block-svh",
"min-h-0",
"min-h-0.5",
"min-h-1",
@@ -8120,6 +8477,78 @@ exports[`getClassList 1`] = `
"min-h-screen",
"min-h-svh",
"min-h-svw",
+ "min-inline-0",
+ "min-inline-0.5",
+ "min-inline-1",
+ "min-inline-1.5",
+ "min-inline-2",
+ "min-inline-2.5",
+ "min-inline-3",
+ "min-inline-3.5",
+ "min-inline-4",
+ "min-inline-5",
+ "min-inline-6",
+ "min-inline-7",
+ "min-inline-8",
+ "min-inline-9",
+ "min-inline-10",
+ "min-inline-11",
+ "min-inline-12",
+ "min-inline-14",
+ "min-inline-16",
+ "min-inline-20",
+ "min-inline-24",
+ "min-inline-28",
+ "min-inline-32",
+ "min-inline-36",
+ "min-inline-40",
+ "min-inline-44",
+ "min-inline-48",
+ "min-inline-52",
+ "min-inline-56",
+ "min-inline-60",
+ "min-inline-64",
+ "min-inline-72",
+ "min-inline-80",
+ "min-inline-96",
+ "min-inline-auto",
+ "min-inline-dvw",
+ "min-inline-fit",
+ "min-inline-full",
+ "min-inline-lg",
+ "min-inline-lvw",
+ "min-inline-max",
+ "min-inline-md",
+ "min-inline-1/2",
+ "min-inline-1/3",
+ "min-inline-1/4",
+ "min-inline-1/5",
+ "min-inline-1/6",
+ "min-inline-1/12",
+ "min-inline-2/3",
+ "min-inline-2/4",
+ "min-inline-2/5",
+ "min-inline-2/6",
+ "min-inline-2/12",
+ "min-inline-3/4",
+ "min-inline-3/5",
+ "min-inline-3/6",
+ "min-inline-3/12",
+ "min-inline-4/5",
+ "min-inline-4/6",
+ "min-inline-4/12",
+ "min-inline-5/6",
+ "min-inline-5/12",
+ "min-inline-6/12",
+ "min-inline-7/12",
+ "min-inline-8/12",
+ "min-inline-9/12",
+ "min-inline-10/12",
+ "min-inline-11/12",
+ "min-inline-min",
+ "min-inline-px",
+ "min-inline-screen",
+ "min-inline-svw",
"min-w-0",
"min-w-0.5",
"min-w-1",
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index a5991ebfac7a..a6c1ce91e850 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -3662,6 +3662,561 @@ test('max-height', async () => {
).toEqual('')
})
+test('inline-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --width-xl: 36rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'inline-full',
+ 'inline-auto',
+ 'inline-screen',
+ 'inline-svw',
+ 'inline-lvw',
+ 'inline-dvw',
+ 'inline-min',
+ 'inline-max',
+ 'inline-fit',
+ 'inline-4',
+ 'inline-xl',
+ 'inline-1/2',
+ 'inline-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --width-xl: 36rem;
+ }
+
+ .inline-1\\/2 {
+ inline-size: 50%;
+ }
+
+ .inline-4 {
+ inline-size: var(--spacing-4);
+ }
+
+ .inline-\\[4px\\] {
+ inline-size: 4px;
+ }
+
+ .inline-auto {
+ inline-size: auto;
+ }
+
+ .inline-dvw {
+ inline-size: 100dvw;
+ }
+
+ .inline-fit {
+ inline-size: fit-content;
+ }
+
+ .inline-full {
+ inline-size: 100%;
+ }
+
+ .inline-lvw {
+ inline-size: 100lvw;
+ }
+
+ .inline-max {
+ inline-size: max-content;
+ }
+
+ .inline-min {
+ inline-size: min-content;
+ }
+
+ .inline-screen {
+ inline-size: 100vw;
+ }
+
+ .inline-svw {
+ inline-size: 100svw;
+ }
+
+ .inline-xl {
+ inline-size: var(--width-xl);
+ }"
+ `)
+ expect(
+ await run([
+ 'inline--1',
+ 'inline--1/2',
+ 'inline--1/-2',
+ 'inline-1/-2',
+ '-inline-4',
+ '-inline-1/2',
+ '-inline-[4px]',
+ 'inline-full/foo',
+ 'inline-auto/foo',
+ 'inline-screen/foo',
+ 'inline-svw/foo',
+ 'inline-lvw/foo',
+ 'inline-dvw/foo',
+ 'inline-min/foo',
+ 'inline-max/foo',
+ 'inline-fit/foo',
+ 'inline-4/foo',
+ 'inline-xl/foo',
+ 'inline-1/2/foo',
+ 'inline-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('min-inline-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --container-xl: 36rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'min-inline-full',
+ 'min-inline-auto',
+ 'min-inline-min',
+ 'min-inline-max',
+ 'min-inline-fit',
+ 'min-inline-4',
+ 'min-inline-xl',
+ 'min-inline-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --container-xl: 36rem;
+ }
+
+ .min-inline-4 {
+ min-inline-size: var(--spacing-4);
+ }
+
+ .min-inline-\\[4px\\] {
+ min-inline-size: 4px;
+ }
+
+ .min-inline-auto {
+ min-inline-size: auto;
+ }
+
+ .min-inline-fit {
+ min-inline-size: fit-content;
+ }
+
+ .min-inline-full {
+ min-inline-size: 100%;
+ }
+
+ .min-inline-max {
+ min-inline-size: max-content;
+ }
+
+ .min-inline-min {
+ min-inline-size: min-content;
+ }
+
+ .min-inline-xl {
+ min-inline-size: var(--container-xl);
+ }"
+ `)
+ expect(
+ await run([
+ 'min-inline',
+ '-min-inline-4',
+ '-min-inline-[4px]',
+ 'min-inline-auto/foo',
+ 'min-inline-full/foo',
+ 'min-inline-min/foo',
+ 'min-inline-max/foo',
+ 'min-inline-fit/foo',
+ 'min-inline-4/foo',
+ 'min-inline-xl/foo',
+ 'min-inline-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('max-inline-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --container-xl: 36rem;
+ }
+ @tailwind utilities;
+ `,
+ ['max-inline-none', 'max-inline-full', 'max-inline-max', 'max-inline-fit', 'max-inline-4', 'max-inline-xl', 'max-inline-[4px]'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --container-xl: 36rem;
+ }
+
+ .max-inline-4 {
+ max-inline-size: var(--spacing-4);
+ }
+
+ .max-inline-\\[4px\\] {
+ max-inline-size: 4px;
+ }
+
+ .max-inline-fit {
+ max-inline-size: fit-content;
+ }
+
+ .max-inline-full {
+ max-inline-size: 100%;
+ }
+
+ .max-inline-max {
+ max-inline-size: max-content;
+ }
+
+ .max-inline-none {
+ max-inline-size: none;
+ }
+
+ .max-inline-xl {
+ max-inline-size: var(--container-xl);
+ }"
+ `)
+ expect(
+ await run([
+ 'max-inline',
+ 'max-inline-auto',
+ '-max-inline-4',
+ '-max-inline-[4px]',
+ 'max-inline-none/foo',
+ 'max-inline-full/foo',
+ 'max-inline-max/foo',
+ 'max-inline-max/foo',
+ 'max-inline-fit/foo',
+ 'max-inline-4/foo',
+ 'max-inline-xl/foo',
+ 'max-inline-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('block-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'block-full',
+ 'block-auto',
+ 'block-screen',
+ 'block-svh',
+ 'block-lvh',
+ 'block-dvh',
+ 'block-min',
+ 'block-lh',
+ 'block-max',
+ 'block-fit',
+ 'block-4',
+ 'block-1/2',
+ 'block-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .block-1\\/2 {
+ block-size: 50%;
+ }
+
+ .block-4 {
+ block-size: var(--spacing-4);
+ }
+
+ .block-\\[4px\\] {
+ block-size: 4px;
+ }
+
+ .block-auto {
+ block-size: auto;
+ }
+
+ .block-dvh {
+ block-size: 100dvh;
+ }
+
+ .block-fit {
+ block-size: fit-content;
+ }
+
+ .block-full {
+ block-size: 100%;
+ }
+
+ .block-lh {
+ block-size: 1lh;
+ }
+
+ .block-lvh {
+ block-size: 100lvh;
+ }
+
+ .block-max {
+ block-size: max-content;
+ }
+
+ .block-min {
+ block-size: min-content;
+ }
+
+ .block-screen {
+ block-size: 100vh;
+ }
+
+ .block-svh {
+ block-size: 100svh;
+ }"
+ `)
+ expect(
+ await run([
+ '-block-4',
+ 'block--1',
+ 'block--1/2',
+ 'block--1/-2',
+ 'block-1/-2',
+ '-block-1/2',
+ '-block-[4px]',
+ 'block-full/foo',
+ 'block-auto/foo',
+ 'block-screen/foo',
+ 'block-svh/foo',
+ 'block-lvh/foo',
+ 'block-dvh/foo',
+ 'block-lh/foo',
+ 'block-min/foo',
+ 'block-max/foo',
+ 'block-fit/foo',
+ 'block-4/foo',
+ 'block-1/2/foo',
+ 'block-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('min-block-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'min-block-full',
+ 'min-block-auto',
+ 'min-block-screen',
+ 'min-block-svh',
+ 'min-block-lvh',
+ 'min-block-dvh',
+ 'min-block-min',
+ 'min-block-lh',
+ 'min-block-max',
+ 'min-block-fit',
+ 'min-block-4',
+ 'min-block-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .min-block-4 {
+ min-block-size: var(--spacing-4);
+ }
+
+ .min-block-\\[4px\\] {
+ min-block-size: 4px;
+ }
+
+ .min-block-auto {
+ min-block-size: auto;
+ }
+
+ .min-block-dvh {
+ min-block-size: 100dvh;
+ }
+
+ .min-block-fit {
+ min-block-size: fit-content;
+ }
+
+ .min-block-full {
+ min-block-size: 100%;
+ }
+
+ .min-block-lh {
+ min-block-size: 1lh;
+ }
+
+ .min-block-lvh {
+ min-block-size: 100lvh;
+ }
+
+ .min-block-max {
+ min-block-size: max-content;
+ }
+
+ .min-block-min {
+ min-block-size: min-content;
+ }
+
+ .min-block-screen {
+ min-block-size: 100vh;
+ }
+
+ .min-block-svh {
+ min-block-size: 100svh;
+ }"
+ `)
+ expect(
+ await run([
+ 'min-block',
+ '-min-block-4',
+ '-min-block-[4px]',
+ 'min-block-auto/foo',
+ 'min-block-full/foo',
+ 'min-block-screen/foo',
+ 'min-block-svh/foo',
+ 'min-block-lvh/foo',
+ 'min-block-dvh/foo',
+ 'min-block-lh/foo',
+ 'min-block-min/foo',
+ 'min-block-max/foo',
+ 'min-block-fit/foo',
+ 'min-block-4/foo',
+ 'min-block-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
+test('max-block-size', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'max-block-none',
+ 'max-block-full',
+ 'max-block-screen',
+ 'max-block-svh',
+ 'max-block-lvh',
+ 'max-block-dvh',
+ 'max-block-lh',
+ 'max-block-min',
+ 'max-block-max',
+ 'max-block-fit',
+ 'max-block-4',
+ 'max-block-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ }
+
+ .max-block-4 {
+ max-block-size: var(--spacing-4);
+ }
+
+ .max-block-\\[4px\\] {
+ max-block-size: 4px;
+ }
+
+ .max-block-dvh {
+ max-block-size: 100dvh;
+ }
+
+ .max-block-fit {
+ max-block-size: fit-content;
+ }
+
+ .max-block-full {
+ max-block-size: 100%;
+ }
+
+ .max-block-lh {
+ max-block-size: 1lh;
+ }
+
+ .max-block-lvh {
+ max-block-size: 100lvh;
+ }
+
+ .max-block-max {
+ max-block-size: max-content;
+ }
+
+ .max-block-min {
+ max-block-size: min-content;
+ }
+
+ .max-block-none {
+ max-block-size: none;
+ }
+
+ .max-block-screen {
+ max-block-size: 100vh;
+ }
+
+ .max-block-svh {
+ max-block-size: 100svh;
+ }"
+ `)
+ expect(
+ await run([
+ 'max-block',
+ 'max-block-auto',
+ '-max-block-4',
+ '-max-block-[4px]',
+ 'max-block-none/foo',
+ 'max-block-full/foo',
+ 'max-block-screen/foo',
+ 'max-block-svh/foo',
+ 'max-block-lvh/foo',
+ 'max-block-dvh/foo',
+ 'max-block-lh/foo',
+ 'max-block-min/foo',
+ 'max-block-max/foo',
+ 'max-block-fit/foo',
+ 'max-block-4/foo',
+ 'max-block-[4px]/foo',
+ ]),
+ ).toEqual('')
+})
+
describe('container', () => {
test('creates the right media queries and sorts it before width', async () => {
expect(
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index be6a4ebe7080..0661a910912f 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -1069,6 +1069,82 @@ export function createUtilities(theme: Theme) {
})
}
+ /**
+ * @css `inline-size`
+ * @css `min-inline-size`
+ * @css `max-inline-size`
+ * @css `block-size`
+ * @css `min-block-size`
+ * @css `max-block-size`
+ */
+ for (let [key, value] of [
+ ['full', '100%'],
+ ['min', 'min-content'],
+ ['max', 'max-content'],
+ ['fit', 'fit-content'],
+ ]) {
+ staticUtility(`inline-${key}`, [['inline-size', value]])
+ staticUtility(`block-${key}`, [['block-size', value]])
+ staticUtility(`min-inline-${key}`, [['min-inline-size', value]])
+ staticUtility(`min-block-${key}`, [['min-block-size', value]])
+ staticUtility(`max-inline-${key}`, [['max-inline-size', value]])
+ staticUtility(`max-block-${key}`, [['max-block-size', value]])
+ }
+
+ // inline-size viewport units (like width)
+ for (let [key, value] of [
+ ['svw', '100svw'],
+ ['lvw', '100lvw'],
+ ['dvw', '100dvw'],
+ ]) {
+ staticUtility(`inline-${key}`, [['inline-size', value]])
+ staticUtility(`min-inline-${key}`, [['min-inline-size', value]])
+ staticUtility(`max-inline-${key}`, [['max-inline-size', value]])
+ }
+
+ // block-size viewport units (like height)
+ for (let [key, value] of [
+ ['svh', '100svh'],
+ ['lvh', '100lvh'],
+ ['dvh', '100dvh'],
+ ]) {
+ staticUtility(`block-${key}`, [['block-size', value]])
+ staticUtility(`min-block-${key}`, [['min-block-size', value]])
+ staticUtility(`max-block-${key}`, [['max-block-size', value]])
+ }
+
+ staticUtility(`inline-auto`, [['inline-size', 'auto']])
+ staticUtility(`block-auto`, [['block-size', 'auto']])
+ staticUtility(`min-inline-auto`, [['min-inline-size', 'auto']])
+ staticUtility(`min-block-auto`, [['min-block-size', 'auto']])
+
+ staticUtility(`block-lh`, [['block-size', '1lh']])
+ staticUtility(`min-block-lh`, [['min-block-size', '1lh']])
+ staticUtility(`max-block-lh`, [['max-block-size', '1lh']])
+
+ staticUtility(`inline-screen`, [['inline-size', '100vw']])
+ staticUtility(`min-inline-screen`, [['min-inline-size', '100vw']])
+ staticUtility(`max-inline-screen`, [['max-inline-size', '100vw']])
+ staticUtility(`block-screen`, [['block-size', '100vh']])
+ staticUtility(`min-block-screen`, [['min-block-size', '100vh']])
+ staticUtility(`max-block-screen`, [['max-block-size', '100vh']])
+
+ staticUtility(`max-inline-none`, [['max-inline-size', 'none']])
+ staticUtility(`max-block-none`, [['max-block-size', 'none']])
+
+ for (let [name, namespaces, property] of [
+ ['inline', ['--width', '--spacing', '--container'], 'inline-size'],
+ ['min-inline', ['--min-width', '--spacing', '--container'], 'min-inline-size'],
+ ['max-inline', ['--max-width', '--spacing', '--container'], 'max-inline-size'],
+ ['block', ['--height', '--spacing'], 'block-size'],
+ ['min-block', ['--min-height', '--height', '--spacing'], 'min-block-size'],
+ ['max-block', ['--max-height', '--height', '--spacing'], 'max-block-size'],
+ ] as [string, ThemeKey[], string][]) {
+ spacingUtility(name, namespaces, (value) => [decl(property, value)], {
+ supportsFractions: true,
+ })
+ }
+
utilities.static('container', () => {
let breakpoints = [...theme.namespace('--breakpoint').values()]
breakpoints.sort((a, z) => compareBreakpoints(a, z, 'asc'))
From 5395c7e7646ac09d9accf5517a0d07e13792dcbf Mon Sep 17 00:00:00 2001
From: Adam Wathan
Date: Fri, 30 Jan 2026 15:13:56 +0100
Subject: [PATCH 06/40] Add logical inset utilities (inset-s, inset-e,
inset-bs, inset-be) (#19613)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
This PR adds support for logical inset utilities that map to CSS logical
properties:
- `inset-s` → `inset-inline-start`
- `inset-e` → `inset-inline-end`
- `inset-bs` → `inset-block-start`
- `inset-be` → `inset-block-end`
These utilities complement the existing `inset-x` (inline) and `inset-y`
(block) utilities, providing more granular control over positioning in a
direction-aware manner. This aligns with CSS logical properties and
improves support for internationalization (RTL/LTR languages).
### Changes
1. **property-order.ts**: Added `inset-block-start` and
`inset-block-end` to the property ordering list to ensure consistent
cascade ordering
2. **utilities.ts**: Added four new utility mappings for the logical
inset properties
3. **utilities.test.ts**: Added comprehensive test coverage for all four
new utilities, including:
- Valid class generation with various value types (custom spacing,
percentages, arbitrary values)
- Negative value support
- Invalid class rejection (malformed syntax, invalid modifiers)
## Test plan
All changes are covered by unit tests in `utilities.test.ts`:
- `inset-s` test: 8 valid classes + 13 invalid class assertions
- `inset-e` test: 8 valid classes + 13 invalid class assertions
- `inset-bs` test: 8 valid classes + 13 invalid class assertions
- `inset-be` test: 8 valid classes + 13 invalid class assertions
Each test verifies correct CSS output generation and proper rejection of
malformed utilities.
https://claude.ai/code/session_01JcYXVAMawRuntKatjku1WZ
---------
Co-authored-by: Claude
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 7 +-
.../__snapshots__/intellisense.test.ts.snap | 740 ++++++++++++------
.../src/compat/legacy-utilities.test.ts | 174 ++++
.../src/compat/legacy-utilities.ts | 67 +-
packages/tailwindcss/src/property-order.ts | 2 +
packages/tailwindcss/src/utilities.test.ts | 304 +++++--
packages/tailwindcss/src/utilities.ts | 6 +-
7 files changed, 995 insertions(+), 305 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 607302b3042b..93f0446eb918 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,10 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
-- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
+- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
- Add `inline-*`, `min-inline-*`, `max-inline-*`, `block-*`, `min-block-*`, `max-block-*` utilities for `inline-size`, `min-inline-size`, `max-inline-size`, `block-size`, `min-block-size`, and `max-block-size` ([#19612](https://github.com/tailwindlabs/tailwindcss/pull/19612))
+- Add `inset-s-*`, `inset-e-*`, `inset-bs-*`, `inset-be-*` utilities for `inset-inline-start`, `inset-inline-end`, `inset-block-start`, and `inset-block-end` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
+
+### Deprecated
+
+- Deprecate `start-*` and `end-*` utilities in favor of `inline-s-*` and `inline-e-*` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
## [4.1.18] - 2025-12-11
diff --git a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
index 87d882840d6c..3bf7905409b2 100644
--- a/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap
@@ -306,66 +306,6 @@ exports[`getClassList 1`] = `
"-col-start-11",
"-col-start-12",
"-col-start-13",
- "-end-0",
- "-end-0.5",
- "-end-1",
- "-end-1.5",
- "-end-2",
- "-end-2.5",
- "-end-3",
- "-end-3.5",
- "-end-4",
- "-end-5",
- "-end-6",
- "-end-7",
- "-end-8",
- "-end-9",
- "-end-10",
- "-end-11",
- "-end-12",
- "-end-14",
- "-end-16",
- "-end-20",
- "-end-24",
- "-end-28",
- "-end-32",
- "-end-36",
- "-end-40",
- "-end-44",
- "-end-48",
- "-end-52",
- "-end-56",
- "-end-60",
- "-end-64",
- "-end-72",
- "-end-80",
- "-end-96",
- "-end-1/2",
- "-end-1/3",
- "-end-1/4",
- "-end-1/5",
- "-end-1/6",
- "-end-1/12",
- "-end-2/3",
- "-end-2/4",
- "-end-2/5",
- "-end-2/6",
- "-end-2/12",
- "-end-3/4",
- "-end-3/5",
- "-end-3/6",
- "-end-3/12",
- "-end-4/5",
- "-end-4/6",
- "-end-4/12",
- "-end-5/6",
- "-end-5/12",
- "-end-6/12",
- "-end-7/12",
- "-end-8/12",
- "-end-9/12",
- "-end-10/12",
- "-end-11/12",
"-end-full",
"-end-px",
"-indent-0",
@@ -463,8 +403,256 @@ exports[`getClassList 1`] = `
"-inset-9/12",
"-inset-10/12",
"-inset-11/12",
+ "-inset-be-0",
+ "-inset-be-0.5",
+ "-inset-be-1",
+ "-inset-be-1.5",
+ "-inset-be-2",
+ "-inset-be-2.5",
+ "-inset-be-3",
+ "-inset-be-3.5",
+ "-inset-be-4",
+ "-inset-be-5",
+ "-inset-be-6",
+ "-inset-be-7",
+ "-inset-be-8",
+ "-inset-be-9",
+ "-inset-be-10",
+ "-inset-be-11",
+ "-inset-be-12",
+ "-inset-be-14",
+ "-inset-be-16",
+ "-inset-be-20",
+ "-inset-be-24",
+ "-inset-be-28",
+ "-inset-be-32",
+ "-inset-be-36",
+ "-inset-be-40",
+ "-inset-be-44",
+ "-inset-be-48",
+ "-inset-be-52",
+ "-inset-be-56",
+ "-inset-be-60",
+ "-inset-be-64",
+ "-inset-be-72",
+ "-inset-be-80",
+ "-inset-be-96",
+ "-inset-be-1/2",
+ "-inset-be-1/3",
+ "-inset-be-1/4",
+ "-inset-be-1/5",
+ "-inset-be-1/6",
+ "-inset-be-1/12",
+ "-inset-be-2/3",
+ "-inset-be-2/4",
+ "-inset-be-2/5",
+ "-inset-be-2/6",
+ "-inset-be-2/12",
+ "-inset-be-3/4",
+ "-inset-be-3/5",
+ "-inset-be-3/6",
+ "-inset-be-3/12",
+ "-inset-be-4/5",
+ "-inset-be-4/6",
+ "-inset-be-4/12",
+ "-inset-be-5/6",
+ "-inset-be-5/12",
+ "-inset-be-6/12",
+ "-inset-be-7/12",
+ "-inset-be-8/12",
+ "-inset-be-9/12",
+ "-inset-be-10/12",
+ "-inset-be-11/12",
+ "-inset-be-full",
+ "-inset-be-px",
+ "-inset-bs-0",
+ "-inset-bs-0.5",
+ "-inset-bs-1",
+ "-inset-bs-1.5",
+ "-inset-bs-2",
+ "-inset-bs-2.5",
+ "-inset-bs-3",
+ "-inset-bs-3.5",
+ "-inset-bs-4",
+ "-inset-bs-5",
+ "-inset-bs-6",
+ "-inset-bs-7",
+ "-inset-bs-8",
+ "-inset-bs-9",
+ "-inset-bs-10",
+ "-inset-bs-11",
+ "-inset-bs-12",
+ "-inset-bs-14",
+ "-inset-bs-16",
+ "-inset-bs-20",
+ "-inset-bs-24",
+ "-inset-bs-28",
+ "-inset-bs-32",
+ "-inset-bs-36",
+ "-inset-bs-40",
+ "-inset-bs-44",
+ "-inset-bs-48",
+ "-inset-bs-52",
+ "-inset-bs-56",
+ "-inset-bs-60",
+ "-inset-bs-64",
+ "-inset-bs-72",
+ "-inset-bs-80",
+ "-inset-bs-96",
+ "-inset-bs-1/2",
+ "-inset-bs-1/3",
+ "-inset-bs-1/4",
+ "-inset-bs-1/5",
+ "-inset-bs-1/6",
+ "-inset-bs-1/12",
+ "-inset-bs-2/3",
+ "-inset-bs-2/4",
+ "-inset-bs-2/5",
+ "-inset-bs-2/6",
+ "-inset-bs-2/12",
+ "-inset-bs-3/4",
+ "-inset-bs-3/5",
+ "-inset-bs-3/6",
+ "-inset-bs-3/12",
+ "-inset-bs-4/5",
+ "-inset-bs-4/6",
+ "-inset-bs-4/12",
+ "-inset-bs-5/6",
+ "-inset-bs-5/12",
+ "-inset-bs-6/12",
+ "-inset-bs-7/12",
+ "-inset-bs-8/12",
+ "-inset-bs-9/12",
+ "-inset-bs-10/12",
+ "-inset-bs-11/12",
+ "-inset-bs-full",
+ "-inset-bs-px",
+ "-inset-e-0",
+ "-inset-e-0.5",
+ "-inset-e-1",
+ "-inset-e-1.5",
+ "-inset-e-2",
+ "-inset-e-2.5",
+ "-inset-e-3",
+ "-inset-e-3.5",
+ "-inset-e-4",
+ "-inset-e-5",
+ "-inset-e-6",
+ "-inset-e-7",
+ "-inset-e-8",
+ "-inset-e-9",
+ "-inset-e-10",
+ "-inset-e-11",
+ "-inset-e-12",
+ "-inset-e-14",
+ "-inset-e-16",
+ "-inset-e-20",
+ "-inset-e-24",
+ "-inset-e-28",
+ "-inset-e-32",
+ "-inset-e-36",
+ "-inset-e-40",
+ "-inset-e-44",
+ "-inset-e-48",
+ "-inset-e-52",
+ "-inset-e-56",
+ "-inset-e-60",
+ "-inset-e-64",
+ "-inset-e-72",
+ "-inset-e-80",
+ "-inset-e-96",
+ "-inset-e-1/2",
+ "-inset-e-1/3",
+ "-inset-e-1/4",
+ "-inset-e-1/5",
+ "-inset-e-1/6",
+ "-inset-e-1/12",
+ "-inset-e-2/3",
+ "-inset-e-2/4",
+ "-inset-e-2/5",
+ "-inset-e-2/6",
+ "-inset-e-2/12",
+ "-inset-e-3/4",
+ "-inset-e-3/5",
+ "-inset-e-3/6",
+ "-inset-e-3/12",
+ "-inset-e-4/5",
+ "-inset-e-4/6",
+ "-inset-e-4/12",
+ "-inset-e-5/6",
+ "-inset-e-5/12",
+ "-inset-e-6/12",
+ "-inset-e-7/12",
+ "-inset-e-8/12",
+ "-inset-e-9/12",
+ "-inset-e-10/12",
+ "-inset-e-11/12",
+ "-inset-e-full",
+ "-inset-e-px",
"-inset-full",
"-inset-px",
+ "-inset-s-0",
+ "-inset-s-0.5",
+ "-inset-s-1",
+ "-inset-s-1.5",
+ "-inset-s-2",
+ "-inset-s-2.5",
+ "-inset-s-3",
+ "-inset-s-3.5",
+ "-inset-s-4",
+ "-inset-s-5",
+ "-inset-s-6",
+ "-inset-s-7",
+ "-inset-s-8",
+ "-inset-s-9",
+ "-inset-s-10",
+ "-inset-s-11",
+ "-inset-s-12",
+ "-inset-s-14",
+ "-inset-s-16",
+ "-inset-s-20",
+ "-inset-s-24",
+ "-inset-s-28",
+ "-inset-s-32",
+ "-inset-s-36",
+ "-inset-s-40",
+ "-inset-s-44",
+ "-inset-s-48",
+ "-inset-s-52",
+ "-inset-s-56",
+ "-inset-s-60",
+ "-inset-s-64",
+ "-inset-s-72",
+ "-inset-s-80",
+ "-inset-s-96",
+ "-inset-s-1/2",
+ "-inset-s-1/3",
+ "-inset-s-1/4",
+ "-inset-s-1/5",
+ "-inset-s-1/6",
+ "-inset-s-1/12",
+ "-inset-s-2/3",
+ "-inset-s-2/4",
+ "-inset-s-2/5",
+ "-inset-s-2/6",
+ "-inset-s-2/12",
+ "-inset-s-3/4",
+ "-inset-s-3/5",
+ "-inset-s-3/6",
+ "-inset-s-3/12",
+ "-inset-s-4/5",
+ "-inset-s-4/6",
+ "-inset-s-4/12",
+ "-inset-s-5/6",
+ "-inset-s-5/12",
+ "-inset-s-6/12",
+ "-inset-s-7/12",
+ "-inset-s-8/12",
+ "-inset-s-9/12",
+ "-inset-s-10/12",
+ "-inset-s-11/12",
+ "-inset-s-full",
+ "-inset-s-px",
"-inset-x-0",
"-inset-x-0.5",
"-inset-x-1",
@@ -1712,66 +1900,6 @@ exports[`getClassList 1`] = `
"-space-y-80",
"-space-y-96",
"-space-y-px",
- "-start-0",
- "-start-0.5",
- "-start-1",
- "-start-1.5",
- "-start-2",
- "-start-2.5",
- "-start-3",
- "-start-3.5",
- "-start-4",
- "-start-5",
- "-start-6",
- "-start-7",
- "-start-8",
- "-start-9",
- "-start-10",
- "-start-11",
- "-start-12",
- "-start-14",
- "-start-16",
- "-start-20",
- "-start-24",
- "-start-28",
- "-start-32",
- "-start-36",
- "-start-40",
- "-start-44",
- "-start-48",
- "-start-52",
- "-start-56",
- "-start-60",
- "-start-64",
- "-start-72",
- "-start-80",
- "-start-96",
- "-start-1/2",
- "-start-1/3",
- "-start-1/4",
- "-start-1/5",
- "-start-1/6",
- "-start-1/12",
- "-start-2/3",
- "-start-2/4",
- "-start-2/5",
- "-start-2/6",
- "-start-2/12",
- "-start-3/4",
- "-start-3/5",
- "-start-3/6",
- "-start-3/12",
- "-start-4/5",
- "-start-4/6",
- "-start-4/12",
- "-start-5/6",
- "-start-5/12",
- "-start-6/12",
- "-start-7/12",
- "-start-8/12",
- "-start-9/12",
- "-start-10/12",
- "-start-11/12",
"-start-full",
"-start-px",
"-top-0",
@@ -4457,66 +4585,6 @@ exports[`getClassList 1`] = `
"duration-initial",
"ease-initial",
"ease-linear",
- "end-0",
- "end-0.5",
- "end-1",
- "end-1.5",
- "end-2",
- "end-2.5",
- "end-3",
- "end-3.5",
- "end-4",
- "end-5",
- "end-6",
- "end-7",
- "end-8",
- "end-9",
- "end-10",
- "end-11",
- "end-12",
- "end-14",
- "end-16",
- "end-20",
- "end-24",
- "end-28",
- "end-32",
- "end-36",
- "end-40",
- "end-44",
- "end-48",
- "end-52",
- "end-56",
- "end-60",
- "end-64",
- "end-72",
- "end-80",
- "end-96",
- "end-1/2",
- "end-1/3",
- "end-1/4",
- "end-1/5",
- "end-1/6",
- "end-1/12",
- "end-2/3",
- "end-2/4",
- "end-2/5",
- "end-2/6",
- "end-2/12",
- "end-3/4",
- "end-3/5",
- "end-3/6",
- "end-3/12",
- "end-4/5",
- "end-4/6",
- "end-4/12",
- "end-5/6",
- "end-5/12",
- "end-6/12",
- "end-7/12",
- "end-8/12",
- "end-9/12",
- "end-10/12",
- "end-11/12",
"end-auto",
"end-full",
"end-px",
@@ -5160,6 +5228,195 @@ exports[`getClassList 1`] = `
"inset-10/12",
"inset-11/12",
"inset-auto",
+ "inset-be-0",
+ "inset-be-0.5",
+ "inset-be-1",
+ "inset-be-1.5",
+ "inset-be-2",
+ "inset-be-2.5",
+ "inset-be-3",
+ "inset-be-3.5",
+ "inset-be-4",
+ "inset-be-5",
+ "inset-be-6",
+ "inset-be-7",
+ "inset-be-8",
+ "inset-be-9",
+ "inset-be-10",
+ "inset-be-11",
+ "inset-be-12",
+ "inset-be-14",
+ "inset-be-16",
+ "inset-be-20",
+ "inset-be-24",
+ "inset-be-28",
+ "inset-be-32",
+ "inset-be-36",
+ "inset-be-40",
+ "inset-be-44",
+ "inset-be-48",
+ "inset-be-52",
+ "inset-be-56",
+ "inset-be-60",
+ "inset-be-64",
+ "inset-be-72",
+ "inset-be-80",
+ "inset-be-96",
+ "inset-be-1/2",
+ "inset-be-1/3",
+ "inset-be-1/4",
+ "inset-be-1/5",
+ "inset-be-1/6",
+ "inset-be-1/12",
+ "inset-be-2/3",
+ "inset-be-2/4",
+ "inset-be-2/5",
+ "inset-be-2/6",
+ "inset-be-2/12",
+ "inset-be-3/4",
+ "inset-be-3/5",
+ "inset-be-3/6",
+ "inset-be-3/12",
+ "inset-be-4/5",
+ "inset-be-4/6",
+ "inset-be-4/12",
+ "inset-be-5/6",
+ "inset-be-5/12",
+ "inset-be-6/12",
+ "inset-be-7/12",
+ "inset-be-8/12",
+ "inset-be-9/12",
+ "inset-be-10/12",
+ "inset-be-11/12",
+ "inset-be-auto",
+ "inset-be-full",
+ "inset-be-px",
+ "inset-bs-0",
+ "inset-bs-0.5",
+ "inset-bs-1",
+ "inset-bs-1.5",
+ "inset-bs-2",
+ "inset-bs-2.5",
+ "inset-bs-3",
+ "inset-bs-3.5",
+ "inset-bs-4",
+ "inset-bs-5",
+ "inset-bs-6",
+ "inset-bs-7",
+ "inset-bs-8",
+ "inset-bs-9",
+ "inset-bs-10",
+ "inset-bs-11",
+ "inset-bs-12",
+ "inset-bs-14",
+ "inset-bs-16",
+ "inset-bs-20",
+ "inset-bs-24",
+ "inset-bs-28",
+ "inset-bs-32",
+ "inset-bs-36",
+ "inset-bs-40",
+ "inset-bs-44",
+ "inset-bs-48",
+ "inset-bs-52",
+ "inset-bs-56",
+ "inset-bs-60",
+ "inset-bs-64",
+ "inset-bs-72",
+ "inset-bs-80",
+ "inset-bs-96",
+ "inset-bs-1/2",
+ "inset-bs-1/3",
+ "inset-bs-1/4",
+ "inset-bs-1/5",
+ "inset-bs-1/6",
+ "inset-bs-1/12",
+ "inset-bs-2/3",
+ "inset-bs-2/4",
+ "inset-bs-2/5",
+ "inset-bs-2/6",
+ "inset-bs-2/12",
+ "inset-bs-3/4",
+ "inset-bs-3/5",
+ "inset-bs-3/6",
+ "inset-bs-3/12",
+ "inset-bs-4/5",
+ "inset-bs-4/6",
+ "inset-bs-4/12",
+ "inset-bs-5/6",
+ "inset-bs-5/12",
+ "inset-bs-6/12",
+ "inset-bs-7/12",
+ "inset-bs-8/12",
+ "inset-bs-9/12",
+ "inset-bs-10/12",
+ "inset-bs-11/12",
+ "inset-bs-auto",
+ "inset-bs-full",
+ "inset-bs-px",
+ "inset-e-0",
+ "inset-e-0.5",
+ "inset-e-1",
+ "inset-e-1.5",
+ "inset-e-2",
+ "inset-e-2.5",
+ "inset-e-3",
+ "inset-e-3.5",
+ "inset-e-4",
+ "inset-e-5",
+ "inset-e-6",
+ "inset-e-7",
+ "inset-e-8",
+ "inset-e-9",
+ "inset-e-10",
+ "inset-e-11",
+ "inset-e-12",
+ "inset-e-14",
+ "inset-e-16",
+ "inset-e-20",
+ "inset-e-24",
+ "inset-e-28",
+ "inset-e-32",
+ "inset-e-36",
+ "inset-e-40",
+ "inset-e-44",
+ "inset-e-48",
+ "inset-e-52",
+ "inset-e-56",
+ "inset-e-60",
+ "inset-e-64",
+ "inset-e-72",
+ "inset-e-80",
+ "inset-e-96",
+ "inset-e-1/2",
+ "inset-e-1/3",
+ "inset-e-1/4",
+ "inset-e-1/5",
+ "inset-e-1/6",
+ "inset-e-1/12",
+ "inset-e-2/3",
+ "inset-e-2/4",
+ "inset-e-2/5",
+ "inset-e-2/6",
+ "inset-e-2/12",
+ "inset-e-3/4",
+ "inset-e-3/5",
+ "inset-e-3/6",
+ "inset-e-3/12",
+ "inset-e-4/5",
+ "inset-e-4/6",
+ "inset-e-4/12",
+ "inset-e-5/6",
+ "inset-e-5/12",
+ "inset-e-6/12",
+ "inset-e-7/12",
+ "inset-e-8/12",
+ "inset-e-9/12",
+ "inset-e-10/12",
+ "inset-e-11/12",
+ "inset-e-auto",
+ "inset-e-full",
+ "inset-e-px",
"inset-full",
"inset-px",
"inset-ring",
@@ -5234,6 +5491,69 @@ exports[`getClassList 1`] = `
"inset-ring-transparent/90",
"inset-ring-transparent/95",
"inset-ring-transparent/100",
+ "inset-s-0",
+ "inset-s-0.5",
+ "inset-s-1",
+ "inset-s-1.5",
+ "inset-s-2",
+ "inset-s-2.5",
+ "inset-s-3",
+ "inset-s-3.5",
+ "inset-s-4",
+ "inset-s-5",
+ "inset-s-6",
+ "inset-s-7",
+ "inset-s-8",
+ "inset-s-9",
+ "inset-s-10",
+ "inset-s-11",
+ "inset-s-12",
+ "inset-s-14",
+ "inset-s-16",
+ "inset-s-20",
+ "inset-s-24",
+ "inset-s-28",
+ "inset-s-32",
+ "inset-s-36",
+ "inset-s-40",
+ "inset-s-44",
+ "inset-s-48",
+ "inset-s-52",
+ "inset-s-56",
+ "inset-s-60",
+ "inset-s-64",
+ "inset-s-72",
+ "inset-s-80",
+ "inset-s-96",
+ "inset-s-1/2",
+ "inset-s-1/3",
+ "inset-s-1/4",
+ "inset-s-1/5",
+ "inset-s-1/6",
+ "inset-s-1/12",
+ "inset-s-2/3",
+ "inset-s-2/4",
+ "inset-s-2/5",
+ "inset-s-2/6",
+ "inset-s-2/12",
+ "inset-s-3/4",
+ "inset-s-3/5",
+ "inset-s-3/6",
+ "inset-s-3/12",
+ "inset-s-4/5",
+ "inset-s-4/6",
+ "inset-s-4/12",
+ "inset-s-5/6",
+ "inset-s-5/12",
+ "inset-s-6/12",
+ "inset-s-7/12",
+ "inset-s-8/12",
+ "inset-s-9/12",
+ "inset-s-10/12",
+ "inset-s-11/12",
+ "inset-s-auto",
+ "inset-s-full",
+ "inset-s-px",
"inset-shadow-current",
"inset-shadow-current/0",
"inset-shadow-current/5",
@@ -10957,66 +11277,6 @@ exports[`getClassList 1`] = `
"space-y-reverse",
"sr-only",
"stacked-fractions",
- "start-0",
- "start-0.5",
- "start-1",
- "start-1.5",
- "start-2",
- "start-2.5",
- "start-3",
- "start-3.5",
- "start-4",
- "start-5",
- "start-6",
- "start-7",
- "start-8",
- "start-9",
- "start-10",
- "start-11",
- "start-12",
- "start-14",
- "start-16",
- "start-20",
- "start-24",
- "start-28",
- "start-32",
- "start-36",
- "start-40",
- "start-44",
- "start-48",
- "start-52",
- "start-56",
- "start-60",
- "start-64",
- "start-72",
- "start-80",
- "start-96",
- "start-1/2",
- "start-1/3",
- "start-1/4",
- "start-1/5",
- "start-1/6",
- "start-1/12",
- "start-2/3",
- "start-2/4",
- "start-2/5",
- "start-2/6",
- "start-2/12",
- "start-3/4",
- "start-3/5",
- "start-3/6",
- "start-3/12",
- "start-4/5",
- "start-4/6",
- "start-4/12",
- "start-5/6",
- "start-5/12",
- "start-6/12",
- "start-7/12",
- "start-8/12",
- "start-9/12",
- "start-10/12",
- "start-11/12",
"start-auto",
"start-full",
"start-px",
diff --git a/packages/tailwindcss/src/compat/legacy-utilities.test.ts b/packages/tailwindcss/src/compat/legacy-utilities.test.ts
index 9a828d673b78..24222f882f75 100644
--- a/packages/tailwindcss/src/compat/legacy-utilities.test.ts
+++ b/packages/tailwindcss/src/compat/legacy-utilities.test.ts
@@ -211,3 +211,177 @@ test('flex-shrink', async () => {
]),
).toEqual('')
})
+
+test('start', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'start-shadowned',
+ 'start-auto',
+ '-start-full',
+ 'start-full',
+ 'start-3/4',
+ 'start-4',
+ '-start-4',
+ 'start-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+
+ .-start-4 {
+ inset-inline-start: calc(var(--spacing-4) * -1);
+ }
+
+ .-start-full {
+ inset-inline-start: -100%;
+ }
+
+ .start-3\\/4 {
+ inset-inline-start: 75%;
+ }
+
+ .start-4 {
+ inset-inline-start: var(--spacing-4);
+ }
+
+ .start-\\[4px\\] {
+ inset-inline-start: 4px;
+ }
+
+ .start-auto {
+ inset-inline-start: auto;
+ }
+
+ .start-full {
+ inset-inline-start: 100%;
+ }
+
+ .start-shadowned {
+ inset-inline-start: var(--inset-shadowned);
+ }"
+ `)
+ expect(
+ await compileCss(
+ css`
+ @theme reference {
+ --spacing-4: 1rem;
+ --inset-shadow-sm: inset 0 1px 1px rgb(0 0 0 / 0.05);
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'start-shadow-sm',
+ 'start',
+ 'start--1',
+ 'start--1/2',
+ 'start--1/-2',
+ 'start-1/-2',
+ 'start-auto/foo',
+ '-start-full/foo',
+ 'start-full/foo',
+ 'start-3/4/foo',
+ 'start-4/foo',
+ '-start-4/foo',
+ 'start-[4px]/foo',
+ ],
+ ),
+ ).toEqual('')
+})
+
+test('end', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'end-shadowned',
+ 'end-auto',
+ '-end-full',
+ 'end-full',
+ 'end-3/4',
+ 'end-4',
+ '-end-4',
+ 'end-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+
+ .-end-4 {
+ inset-inline-end: calc(var(--spacing-4) * -1);
+ }
+
+ .-end-full {
+ inset-inline-end: -100%;
+ }
+
+ .end-3\\/4 {
+ inset-inline-end: 75%;
+ }
+
+ .end-4 {
+ inset-inline-end: var(--spacing-4);
+ }
+
+ .end-\\[4px\\] {
+ inset-inline-end: 4px;
+ }
+
+ .end-auto {
+ inset-inline-end: auto;
+ }
+
+ .end-full {
+ inset-inline-end: 100%;
+ }
+
+ .end-shadowned {
+ inset-inline-end: var(--inset-shadowned);
+ }"
+ `)
+ expect(
+ await compileCss(
+ css`
+ @theme reference {
+ --spacing-4: 1rem;
+ --inset-shadow-sm: inset 0 1px 1px rgb(0 0 0 / 0.05);
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'end-shadow-sm',
+ 'end',
+ 'end--1',
+ 'end--1/2',
+ 'end--1/-2',
+ 'end-1/-2',
+ 'end-auto/foo',
+ '-end-full/foo',
+ 'end-full/foo',
+ 'end-3/4/foo',
+ 'end-4/foo',
+ '-end-4/foo',
+ 'end-[4px]/foo',
+ ],
+ ),
+ ).toEqual('')
+})
diff --git a/packages/tailwindcss/src/compat/legacy-utilities.ts b/packages/tailwindcss/src/compat/legacy-utilities.ts
index ffefca940e35..dc53e42179c8 100644
--- a/packages/tailwindcss/src/compat/legacy-utilities.ts
+++ b/packages/tailwindcss/src/compat/legacy-utilities.ts
@@ -1,6 +1,7 @@
import { decl } from '../ast'
import type { DesignSystem } from '../design-system'
-import { isPositiveInteger } from '../utils/infer-data-type'
+import { isPositiveInteger, isValidSpacingMultiplier } from '../utils/infer-data-type'
+import { segment } from '../utils/segment'
export function registerLegacyUtilities(designSystem: DesignSystem) {
for (let [value, direction] of [
@@ -111,4 +112,68 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
designSystem.utilities.suggest('break-words', () => [])
designSystem.utilities.static('break-words', () => [decl('overflow-wrap', 'break-word')])
+
+ // Legacy `start` and `end` inset utilities, replaced by `inset-s` and `inset-e`
+ for (let [name, property] of [
+ ['start', 'inset-inline-start'],
+ ['end', 'inset-inline-end'],
+ ] as const) {
+ designSystem.utilities.static(`${name}-auto`, () => [decl(property, 'auto')])
+ designSystem.utilities.static(`${name}-full`, () => [decl(property, '100%')])
+ designSystem.utilities.static(`-${name}-full`, () => [decl(property, '-100%')])
+ designSystem.utilities.static(`${name}-px`, () => [decl(property, '1px')])
+ designSystem.utilities.static(`-${name}-px`, () => [decl(property, '-1px')])
+
+ function handleInset({ negative }: { negative: boolean }) {
+ return (candidate: Extract ) => {
+ if (!candidate.value) {
+ if (candidate.modifier) return
+ let value = designSystem.theme.resolve(null, ['--inset', '--spacing'])
+ if (value === null) return
+ return [decl(property, negative ? `calc(${value} * -1)` : value)]
+ }
+
+ if (candidate.value.kind === 'arbitrary') {
+ if (candidate.modifier) return
+ let value = candidate.value.value
+ return [decl(property, negative ? `calc(${value} * -1)` : value)]
+ }
+
+ let value = designSystem.theme.resolve(candidate.value.fraction ?? candidate.value.value, [
+ '--inset',
+ '--spacing',
+ ])
+
+ // Handle fractions like `start-1/2`
+ if (value === null && candidate.value.fraction) {
+ let [lhs, rhs] = segment(candidate.value.fraction, '/')
+ if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return
+ value = `calc(${candidate.value.fraction} * 100%)`
+ }
+
+ // Handle bare spacing multiplier values like `start-4`
+ if (value === null && negative) {
+ let multiplier = designSystem.theme.resolve(null, ['--spacing'])
+ if (multiplier && isValidSpacingMultiplier(candidate.value.value)) {
+ value = `calc(${multiplier} * -${candidate.value.value})`
+ if (value !== null) return [decl(property, value)]
+ }
+ }
+
+ if (value === null) {
+ let multiplier = designSystem.theme.resolve(null, ['--spacing'])
+ if (multiplier && isValidSpacingMultiplier(candidate.value.value)) {
+ value = `calc(${multiplier} * ${candidate.value.value})`
+ }
+ }
+
+ if (value === null) return
+
+ return [decl(property, negative ? `calc(${value} * -1)` : value)]
+ }
+ }
+
+ designSystem.utilities.functional(`-${name}`, handleInset({ negative: true }))
+ designSystem.utilities.functional(name, handleInset({ negative: false }))
+ }
}
diff --git a/packages/tailwindcss/src/property-order.ts b/packages/tailwindcss/src/property-order.ts
index 03d0440ae083..5177d8e2f405 100644
--- a/packages/tailwindcss/src/property-order.ts
+++ b/packages/tailwindcss/src/property-order.ts
@@ -11,6 +11,8 @@ export default [
'inset-block',
'inset-inline-start',
'inset-inline-end',
+ 'inset-block-start',
+ 'inset-block-end',
'top',
'right',
'bottom',
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index a6c1ce91e850..64a1d3396d44 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -480,7 +480,7 @@ test('inset-y', async () => {
).toEqual('')
})
-test('start', async () => {
+test('inset-s', async () => {
expect(
await compileCss(
css`
@@ -491,14 +491,14 @@ test('start', async () => {
@tailwind utilities;
`,
[
- 'start-shadowned',
- 'start-auto',
- '-start-full',
- 'start-full',
- 'start-3/4',
- 'start-4',
- '-start-4',
- 'start-[4px]',
+ 'inset-s-shadowned',
+ 'inset-s-auto',
+ '-inset-s-full',
+ 'inset-s-full',
+ 'inset-s-3/4',
+ 'inset-s-4',
+ '-inset-s-4',
+ 'inset-s-[4px]',
],
),
).toMatchInlineSnapshot(`
@@ -507,35 +507,35 @@ test('start', async () => {
--inset-shadowned: 1940px;
}
- .-start-4 {
+ .-inset-s-4 {
inset-inline-start: calc(var(--spacing-4) * -1);
}
- .-start-full {
+ .-inset-s-full {
inset-inline-start: -100%;
}
- .start-3\\/4 {
+ .inset-s-3\\/4 {
inset-inline-start: 75%;
}
- .start-4 {
+ .inset-s-4 {
inset-inline-start: var(--spacing-4);
}
- .start-\\[4px\\] {
+ .inset-s-\\[4px\\] {
inset-inline-start: 4px;
}
- .start-auto {
+ .inset-s-auto {
inset-inline-start: auto;
}
- .start-full {
+ .inset-s-full {
inset-inline-start: 100%;
}
- .start-shadowned {
+ .inset-s-shadowned {
inset-inline-start: var(--inset-shadowned);
}"
`)
@@ -549,25 +549,25 @@ test('start', async () => {
@tailwind utilities;
`,
[
- 'start-shadow-sm',
- 'start',
- 'start--1',
- 'start--1/2',
- 'start--1/-2',
- 'start-1/-2',
- 'start-auto/foo',
- '-start-full/foo',
- 'start-full/foo',
- 'start-3/4/foo',
- 'start-4/foo',
- '-start-4/foo',
- 'start-[4px]/foo',
+ 'inset-s-shadow-sm',
+ 'inset-s',
+ 'inset-s--1',
+ 'inset-s--1/2',
+ 'inset-s--1/-2',
+ 'inset-s-1/-2',
+ 'inset-s-auto/foo',
+ '-inset-s-full/foo',
+ 'inset-s-full/foo',
+ 'inset-s-3/4/foo',
+ 'inset-s-4/foo',
+ '-inset-s-4/foo',
+ 'inset-s-[4px]/foo',
],
),
).toEqual('')
})
-test('end', async () => {
+test('inset-e', async () => {
expect(
await compileCss(
css`
@@ -578,14 +578,14 @@ test('end', async () => {
@tailwind utilities;
`,
[
- 'end-shadowned',
- 'end-auto',
- '-end-full',
- 'end-full',
- 'end-3/4',
- 'end-4',
- '-end-4',
- 'end-[4px]',
+ 'inset-e-shadowned',
+ 'inset-e-auto',
+ '-inset-e-full',
+ 'inset-e-full',
+ 'inset-e-3/4',
+ 'inset-e-4',
+ '-inset-e-4',
+ 'inset-e-[4px]',
],
),
).toMatchInlineSnapshot(`
@@ -594,35 +594,35 @@ test('end', async () => {
--inset-shadowned: 1940px;
}
- .-end-4 {
+ .-inset-e-4 {
inset-inline-end: calc(var(--spacing-4) * -1);
}
- .-end-full {
+ .-inset-e-full {
inset-inline-end: -100%;
}
- .end-3\\/4 {
+ .inset-e-3\\/4 {
inset-inline-end: 75%;
}
- .end-4 {
+ .inset-e-4 {
inset-inline-end: var(--spacing-4);
}
- .end-\\[4px\\] {
+ .inset-e-\\[4px\\] {
inset-inline-end: 4px;
}
- .end-auto {
+ .inset-e-auto {
inset-inline-end: auto;
}
- .end-full {
+ .inset-e-full {
inset-inline-end: 100%;
}
- .end-shadowned {
+ .inset-e-shadowned {
inset-inline-end: var(--inset-shadowned);
}"
`)
@@ -636,19 +636,193 @@ test('end', async () => {
@tailwind utilities;
`,
[
- 'end-shadow-sm',
- 'end',
- 'end--1',
- 'end--1/2',
- 'end--1/-2',
- 'end-1/-2',
- 'end-auto/foo',
- '-end-full/foo',
- 'end-full/foo',
- 'end-3/4/foo',
- 'end-4/foo',
- '-end-4/foo',
- 'end-[4px]/foo',
+ 'inset-e-shadow-sm',
+ 'inset-e',
+ 'inset-e--1',
+ 'inset-e--1/2',
+ 'inset-e--1/-2',
+ 'inset-e-1/-2',
+ 'inset-e-auto/foo',
+ '-inset-e-full/foo',
+ 'inset-e-full/foo',
+ 'inset-e-3/4/foo',
+ 'inset-e-4/foo',
+ '-inset-e-4/foo',
+ 'inset-e-[4px]/foo',
+ ],
+ ),
+ ).toEqual('')
+})
+
+test('inset-bs', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'inset-bs-shadowned',
+ 'inset-bs-auto',
+ '-inset-bs-full',
+ 'inset-bs-full',
+ 'inset-bs-3/4',
+ 'inset-bs-4',
+ '-inset-bs-4',
+ 'inset-bs-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+
+ .-inset-bs-4 {
+ inset-block-start: calc(var(--spacing-4) * -1);
+ }
+
+ .-inset-bs-full {
+ inset-block-start: -100%;
+ }
+
+ .inset-bs-3\\/4 {
+ inset-block-start: 75%;
+ }
+
+ .inset-bs-4 {
+ inset-block-start: var(--spacing-4);
+ }
+
+ .inset-bs-\\[4px\\] {
+ inset-block-start: 4px;
+ }
+
+ .inset-bs-auto {
+ inset-block-start: auto;
+ }
+
+ .inset-bs-full {
+ inset-block-start: 100%;
+ }
+
+ .inset-bs-shadowned {
+ inset-block-start: var(--inset-shadowned);
+ }"
+ `)
+ expect(
+ await compileCss(
+ css`
+ @theme reference {
+ --spacing-4: 1rem;
+ --inset-shadow-sm: inset 0 1px 1px rgb(0 0 0 / 0.05);
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'inset-bs-shadow-sm',
+ 'inset-bs',
+ 'inset-bs--1',
+ 'inset-bs--1/2',
+ 'inset-bs--1/-2',
+ 'inset-bs-1/-2',
+ 'inset-bs-auto/foo',
+ '-inset-bs-full/foo',
+ 'inset-bs-full/foo',
+ 'inset-bs-3/4/foo',
+ 'inset-bs-4/foo',
+ '-inset-bs-4/foo',
+ 'inset-bs-[4px]/foo',
+ ],
+ ),
+ ).toEqual('')
+})
+
+test('inset-be', async () => {
+ expect(
+ await compileCss(
+ css`
+ @theme {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'inset-be-shadowned',
+ 'inset-be-auto',
+ '-inset-be-full',
+ 'inset-be-full',
+ 'inset-be-3/4',
+ 'inset-be-4',
+ '-inset-be-4',
+ 'inset-be-[4px]',
+ ],
+ ),
+ ).toMatchInlineSnapshot(`
+ ":root, :host {
+ --spacing-4: 1rem;
+ --inset-shadowned: 1940px;
+ }
+
+ .-inset-be-4 {
+ inset-block-end: calc(var(--spacing-4) * -1);
+ }
+
+ .-inset-be-full {
+ inset-block-end: -100%;
+ }
+
+ .inset-be-3\\/4 {
+ inset-block-end: 75%;
+ }
+
+ .inset-be-4 {
+ inset-block-end: var(--spacing-4);
+ }
+
+ .inset-be-\\[4px\\] {
+ inset-block-end: 4px;
+ }
+
+ .inset-be-auto {
+ inset-block-end: auto;
+ }
+
+ .inset-be-full {
+ inset-block-end: 100%;
+ }
+
+ .inset-be-shadowned {
+ inset-block-end: var(--inset-shadowned);
+ }"
+ `)
+ expect(
+ await compileCss(
+ css`
+ @theme reference {
+ --spacing-4: 1rem;
+ --inset-shadow-sm: inset 0 1px 1px rgb(0 0 0 / 0.05);
+ }
+ @tailwind utilities;
+ `,
+ [
+ 'inset-be-shadow-sm',
+ 'inset-be',
+ 'inset-be--1',
+ 'inset-be--1/2',
+ 'inset-be--1/-2',
+ 'inset-be-1/-2',
+ 'inset-be-auto/foo',
+ '-inset-be-full/foo',
+ 'inset-be-full/foo',
+ 'inset-be-3/4/foo',
+ 'inset-be-4/foo',
+ '-inset-be-4/foo',
+ 'inset-be-[4px]/foo',
],
),
).toEqual('')
@@ -3858,7 +4032,15 @@ test('max-inline-size', async () => {
}
@tailwind utilities;
`,
- ['max-inline-none', 'max-inline-full', 'max-inline-max', 'max-inline-fit', 'max-inline-4', 'max-inline-xl', 'max-inline-[4px]'],
+ [
+ 'max-inline-none',
+ 'max-inline-full',
+ 'max-inline-max',
+ 'max-inline-fit',
+ 'max-inline-4',
+ 'max-inline-xl',
+ 'max-inline-[4px]',
+ ],
),
).toMatchInlineSnapshot(`
":root, :host {
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index 0661a910912f..38aec8f428e8 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -624,8 +624,10 @@ export function createUtilities(theme: Theme) {
['inset', 'inset'],
['inset-x', 'inset-inline'],
['inset-y', 'inset-block'],
- ['start', 'inset-inline-start'],
- ['end', 'inset-inline-end'],
+ ['inset-s', 'inset-inline-start'],
+ ['inset-e', 'inset-inline-end'],
+ ['inset-bs', 'inset-block-start'],
+ ['inset-be', 'inset-block-end'],
['top', 'top'],
['right', 'right'],
['bottom', 'bottom'],
From 53205f5dc5889d3a86300fee8ad8ac3ceb3ac020 Mon Sep 17 00:00:00 2001
From: Adam Wathan
Date: Fri, 30 Jan 2026 15:21:16 +0100
Subject: [PATCH 07/40] Add `font-features-*` utility for font-feature-settings
(#19623)
Add a new arbitrary-value-only utility `font-features-*` that sets the
`font-feature-settings` CSS property. This utility only accepts
arbitrary
values (e.g., `font-features-["smcp"]`,
`font-features-[var(--features)]`).
The utility is sorted directly after `font-family` in the property
order.
https://claude.ai/code/session_01EAccbTHJ9dTUJ53ttq2jc4
---------
Co-authored-by: Claude
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 17 ++++++-----
packages/tailwindcss/src/property-order.ts | 1 +
packages/tailwindcss/src/utilities.test.ts | 35 ++++++++++++++++++++++
packages/tailwindcss/src/utilities.ts | 8 +++++
4 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93f0446eb918..710d4a14f7f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
+- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
+- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
+- Add `inline-*`, `min-inline-*`, `max-inline-*`, `block-*`, `min-block-*`, `max-block-*` utilities for `inline-size`, `min-inline-size`, `max-inline-size`, `block-size`, `min-block-size`, and `max-block-size` ([#19612](https://github.com/tailwindlabs/tailwindcss/pull/19612))
+- Add `inset-s-*`, `inset-e-*`, `inset-bs-*`, `inset-be-*` utilities for `inset-inline-start`, `inset-inline-end`, `inset-block-start`, and `inset-block-end` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
+- Add `font-features-*` utility for `font-feature-settings` ([#19623](https://github.com/tailwindlabs/tailwindcss/pull/19615))
+
### Fixed
- Do not wrap `color-mix` in a `@supports` rule if one already exists ([#19450](https://github.com/tailwindlabs/tailwindcss/pull/19450))
@@ -16,14 +25,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix class extraction for Rails' strict locals ([#19525](https://github.com/tailwindlabs/tailwindcss/pull/19525))
- Align `@utility` name validation with Oxide scanner rules ([#19524](https://github.com/tailwindlabs/tailwindcss/pull/19524))
-### Added
-
-- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
-- Add `@tailwindcss/webpack` loader for Tailwind CSS v4 ([#19610](https://github.com/tailwindlabs/tailwindcss/pull/19610))
-- Add `pbs-*`, `pbe-*`, `mbs-*`, `mbe-*`, `scroll-pbs-*`, `scroll-pbe-*`, `scroll-mbs-*`, `scroll-mbe-*`, `border-bs-*`, `border-be-*` utilities for `padding-block-start`, `padding-block-end`, `margin-block-start`, `margin-block-end`, `scroll-padding-block-start`, `scroll-padding-block-end`, `scroll-margin-block-start`, `scroll-margin-block-end`, `border-block-start`, and `border-block-end` ([`#19601`](https://github.com/tailwindlabs/tailwindcss/pull/19601))
-- Add `inline-*`, `min-inline-*`, `max-inline-*`, `block-*`, `min-block-*`, `max-block-*` utilities for `inline-size`, `min-inline-size`, `max-inline-size`, `block-size`, `min-block-size`, and `max-block-size` ([#19612](https://github.com/tailwindlabs/tailwindcss/pull/19612))
-- Add `inset-s-*`, `inset-e-*`, `inset-bs-*`, `inset-be-*` utilities for `inset-inline-start`, `inset-inline-end`, `inset-block-start`, and `inset-block-end` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
-
### Deprecated
- Deprecate `start-*` and `end-*` utilities in favor of `inline-s-*` and `inline-e-*` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
diff --git a/packages/tailwindcss/src/property-order.ts b/packages/tailwindcss/src/property-order.ts
index 5177d8e2f405..e92bc374479c 100644
--- a/packages/tailwindcss/src/property-order.ts
+++ b/packages/tailwindcss/src/property-order.ts
@@ -343,6 +343,7 @@ export default [
'vertical-align',
'font-family',
+ 'font-feature-settings',
'font-size',
'line-height',
'font-weight',
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index 64a1d3396d44..ea60feeaea92 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -22218,6 +22218,41 @@ test('font', async () => {
).toEqual('')
})
+test('font-features', async () => {
+ expect(
+ await run([
+ 'font-features-["smcp"]',
+ 'font-features-["c2sc","smcp"]',
+ 'font-features-[var(--my-features)]',
+ 'font-features-(--my-features)',
+ ]),
+ ).toMatchInlineSnapshot(`
+ ".font-features-\\(--my-features\\) {
+ font-feature-settings: var(--my-features);
+ }
+
+ .font-features-\\[\\"c2sc\\"\\,\\"smcp\\"\\] {
+ font-feature-settings: "c2sc", "smcp";
+ }
+
+ .font-features-\\[\\"smcp\\"\\] {
+ font-feature-settings: "smcp";
+ }
+
+ .font-features-\\[var\\(--my-features\\)\\] {
+ font-feature-settings: var(--my-features);
+ }"
+ `)
+ expect(
+ await run([
+ 'font-features',
+ '-font-features-["smcp"]',
+ 'font-features-smcp',
+ 'font-features-["smcp"]/foo',
+ ]),
+ ).toEqual('')
+})
+
test('text-transform', async () => {
expect(await run(['uppercase', 'lowercase', 'capitalize', 'normal-case'])).toMatchInlineSnapshot(`
".capitalize {
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index 38aec8f428e8..4f54c9584796 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -3909,6 +3909,14 @@ export function createUtilities(theme: Theme) {
},
])
+ /**
+ * @css `font-feature-settings`
+ */
+ functionalUtility('font-features', {
+ themeKeys: [],
+ handle: (value) => [decl('font-feature-settings', value)],
+ })
+
staticUtility('uppercase', [['text-transform', 'uppercase']])
staticUtility('lowercase', [['text-transform', 'lowercase']])
staticUtility('capitalize', [['text-transform', 'capitalize']])
From d8b00d1114645d757c9644556e9a366d24a771c6 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Fri, 30 Jan 2026 15:31:23 +0100
Subject: [PATCH 08/40] add concurrency control to workflows
Essentially cancel previous workflows when new commits are pushed.
---
.github/workflows/ci.yml | 4 ++++
.github/workflows/integration-tests.yml | 4 ++++
.github/workflows/prepare-release.yml | 4 ++++
.github/workflows/release-insiders.yml | 4 ++++
4 files changed, 16 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d8c099873b64..f817e05a3a90 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,6 +11,10 @@ permissions:
env:
NODE_VERSION: 24
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
tests:
strategy:
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index e36f5b3abc47..1508c1effc49 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -11,6 +11,10 @@ permissions:
env:
NODE_VERSION: 24
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
tests:
strategy:
diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml
index e506ab187b7a..0af8930a3a17 100644
--- a/.github/workflows/prepare-release.yml
+++ b/.github/workflows/prepare-release.yml
@@ -14,6 +14,10 @@ env:
permissions:
contents: read
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
build:
strategy:
diff --git a/.github/workflows/release-insiders.yml b/.github/workflows/release-insiders.yml
index f7792244f520..7a506892cbe2 100644
--- a/.github/workflows/release-insiders.yml
+++ b/.github/workflows/release-insiders.yml
@@ -13,6 +13,10 @@ env:
OXIDE_LOCATION: ./crates/node
RELEASE_CHANNEL: insiders
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
build:
strategy:
From d52c94ff5faf4ab3b5a3caf878d22ff1b84e6c07 Mon Sep 17 00:00:00 2001
From: Adam Wathan
Date: Fri, 30 Jan 2026 16:40:51 +0100
Subject: [PATCH 09/40] Simplify logical sizing utility theme namespaces
(#19625)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Update inline-size and block-size utilities to only read from --spacing
and --container theme keys, removing backwards-compat references to
--width, --height, --min-width, --min-height, --max-width, and
--max-height.
Since these are new utilities with no backwards compatibility concerns,
the simpler approach is preferred:
- inline/min-inline/max-inline: --spacing, --container
- block/min-block/max-block: --spacing only
https://claude.ai/code/session_01WhrjmutxsLP753VUtFy24S
## Summary
## Test plan
Co-authored-by: Claude
---
packages/tailwindcss/src/utilities.test.ts | 6 +++---
packages/tailwindcss/src/utilities.ts | 12 ++++++------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index ea60feeaea92..f6860135890c 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -3842,7 +3842,7 @@ test('inline-size', async () => {
css`
@theme {
--spacing-4: 1rem;
- --width-xl: 36rem;
+ --container-xl: 36rem;
}
@tailwind utilities;
`,
@@ -3865,7 +3865,7 @@ test('inline-size', async () => {
).toMatchInlineSnapshot(`
":root, :host {
--spacing-4: 1rem;
- --width-xl: 36rem;
+ --container-xl: 36rem;
}
.inline-1\\/2 {
@@ -3917,7 +3917,7 @@ test('inline-size', async () => {
}
.inline-xl {
- inline-size: var(--width-xl);
+ inline-size: var(--container-xl);
}"
`)
expect(
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index 4f54c9584796..66ae59230e12 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -1135,12 +1135,12 @@ export function createUtilities(theme: Theme) {
staticUtility(`max-block-none`, [['max-block-size', 'none']])
for (let [name, namespaces, property] of [
- ['inline', ['--width', '--spacing', '--container'], 'inline-size'],
- ['min-inline', ['--min-width', '--spacing', '--container'], 'min-inline-size'],
- ['max-inline', ['--max-width', '--spacing', '--container'], 'max-inline-size'],
- ['block', ['--height', '--spacing'], 'block-size'],
- ['min-block', ['--min-height', '--height', '--spacing'], 'min-block-size'],
- ['max-block', ['--max-height', '--height', '--spacing'], 'max-block-size'],
+ ['inline', ['--spacing', '--container'], 'inline-size'],
+ ['min-inline', ['--spacing', '--container'], 'min-inline-size'],
+ ['max-inline', ['--spacing', '--container'], 'max-inline-size'],
+ ['block', ['--spacing'], 'block-size'],
+ ['min-block', ['--spacing'], 'min-block-size'],
+ ['max-block', ['--spacing'], 'max-block-size'],
] as [string, ThemeKey[], string][]) {
spacingUtility(name, namespaces, (value) => [decl(property, value)], {
supportsFractions: true,
From df96ea5eba94c801a08879cf95837b8a2b317b42 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Mon, 2 Feb 2026 14:42:31 +0100
Subject: [PATCH 10/40] Fix infinite loop when using `@variant` inside
`@custom-variant` that points to another `@custom-variant` (#19633)
This PR fixes an infinite loop when you use a `@variant` inside of a
`@custom-variant`, where the `@variant` used is another
`@custom-variant`.
The issue stems from the fact that a `@custom-variant` can use a `@slot`
that we have to replace with the proper AST nodes. However in this
setup, the AST nodes will include a `@slot` node as well, which causes
us to replace the `@slot` again, and so on, causing an infinite loop.
```css
@custom-variant a {
@slot;
}
@custom-variant b {
@variant a {
@slot;
}
}
```
The solution here is to replace the `@slot` nodes and then skip walking
the nodes that were just inserted. This does mean that we end up with a
`@slot` node in the final AST but that's not a real issue because that
will get replaced later when handling the next `@custom-variant`.
## Test plan
1. Existing tests still pass
2. Added a regression test to ensure that the infinite loop does not
happen anymore
3. Added additional tests to ensure that the behavior is correct
Thanks @wongjn for your initial debugging help and providing a test case
as well!
Fixes: #19618
---
CHANGELOG.md | 1 +
packages/tailwindcss/src/index.test.ts | 91 ++++++++++++++++++++++++++
packages/tailwindcss/src/variants.ts | 2 +-
3 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 710d4a14f7f1..74f72f10eeb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Detect utilities when containing capital letters followed by numbers ([#19465](https://github.com/tailwindlabs/tailwindcss/pull/19465))
- Fix class extraction for Rails' strict locals ([#19525](https://github.com/tailwindlabs/tailwindcss/pull/19525))
- Align `@utility` name validation with Oxide scanner rules ([#19524](https://github.com/tailwindlabs/tailwindcss/pull/19524))
+- Fix infinite loop when using `@variant` inside `@custom-variant` ([#19633](https://github.com/tailwindlabs/tailwindcss/pull/19633))
### Deprecated
diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts
index 94b17714ed25..5182cdd14714 100644
--- a/packages/tailwindcss/src/index.test.ts
+++ b/packages/tailwindcss/src/index.test.ts
@@ -4558,6 +4558,97 @@ describe('@custom-variant', () => {
`)
})
+ // https://github.com/tailwindlabs/tailwindcss/issues/19618
+ test('@custom-variant can use a @variant that eventually uses another @custom-variant', async () => {
+ expect(
+ await compileCss(
+ css`
+ @custom-variant a {
+ @slot;
+ }
+
+ @custom-variant b {
+ @variant a {
+ @slot;
+ }
+ }
+
+ @tailwind utilities;
+ `,
+ ['a:flex', 'b:flex', 'a:b:flex', 'b:a:flex'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ".a\\:flex, .b\\:flex, .a\\:b\\:flex, .b\\:a\\:flex {
+ display: flex;
+ }"
+ `)
+ })
+
+ test('@custom-variant can use a @variant that eventually uses another @custom-variant (2)', async () => {
+ expect(
+ await compileCss(
+ css`
+ @custom-variant a {
+ .a {
+ @slot;
+ }
+ }
+
+ @custom-variant b {
+ .b {
+ @variant a {
+ .a-inside-b {
+ @slot;
+ }
+ }
+ }
+ }
+
+ @tailwind utilities;
+ `,
+ ['a:flex', 'b:flex', 'a:b:flex', 'b:a:flex'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ".a\\:flex .a, .b\\:flex .b .a .a-inside-b, .a\\:b\\:flex .a .b .a .a-inside-b, .b\\:a\\:flex .b .a .a-inside-b .a {
+ display: flex;
+ }"
+ `)
+ })
+
+ // https://github.com/tailwindlabs/tailwindcss/issues/19618#issuecomment-3830775912
+ test('@custom-variant can use existing @slot @variants', async () => {
+ expect(
+ await compileCss(
+ css`
+ @custom-variant hocus {
+ @variant hover {
+ @variant focus {
+ @slot;
+ }
+ }
+ }
+
+ @custom-variant hover {
+ &:hover {
+ @slot;
+ }
+
+ &[data-hover] {
+ @slot;
+ }
+ }
+
+ @tailwind utilities;
+ `,
+ ['hocus:flex'],
+ ),
+ ).toMatchInlineSnapshot(`
+ ".hocus\\:flex:hover:focus, .hocus\\:flex[data-hover]:focus {
+ display: flex;
+ }"
+ `)
+ })
+
test('@custom-variant setup that results in a circular dependency error can be solved', async () => {
expect(
await compileCss(
diff --git a/packages/tailwindcss/src/variants.ts b/packages/tailwindcss/src/variants.ts
index 82a2b8592cfe..0b4bcb0c578c 100644
--- a/packages/tailwindcss/src/variants.ts
+++ b/packages/tailwindcss/src/variants.ts
@@ -1196,7 +1196,7 @@ export function substituteAtSlot(ast: AstNode[], nodes: AstNode[]) {
walk(ast, (node) => {
// Replace `@slot` with rule nodes
if (node.kind === 'at-rule' && node.name === '@slot') {
- return WalkAction.Replace(nodes)
+ return WalkAction.ReplaceSkip(nodes)
}
// Wrap `@keyframes` and `@property` in `AtRoot` nodes
From 1638f35c3a2bfcd65a7b3b0f8626927a76bcf685 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Wed, 4 Feb 2026 12:38:50 +0100
Subject: [PATCH 11/40] Bump dependencies (#19608)
This PR bumps a bunch of dependencies. This also moves a few
dependencies that we use in multiple packages to the pnpm catalog.
Closes: #19603, #19604, #19576, #19575, #19573, #19565, #19547, #19546,
#19545, #19609, #19581, #19620, #19619
- #19603
- #19604
- #19576
- #19575
- #19573
- #19565
- #19547
- #19546
- #19545
- #19609
- #19581
- https://github.com/tailwindlabs/tailwindcss/pull/19620
- #19620
- #19619
## Test Plan
All tests in CI should still pass. [ci-all]
---
.prettierignore | 1 +
crates/node/npm/wasm32-wasi/package.json | 6 +-
crates/node/package.json | 2 +-
package.json | 8 +-
packages/@tailwindcss-browser/package.json | 2 +-
packages/@tailwindcss-node/package.json | 2 +-
packages/@tailwindcss-postcss/package.json | 2 +-
.../src/__snapshots__/index.test.ts.snap | 6 +-
packages/@tailwindcss-standalone/package.json | 18 +-
packages/@tailwindcss-standalone/src/index.ts | 10 +-
packages/@tailwindcss-upgrade/package.json | 2 +-
packages/tailwindcss/package.json | 2 +-
.../src/__snapshots__/index.test.ts.snap | 6 +-
.../tailwindcss/src/css-functions.test.ts | 3 +-
packages/tailwindcss/src/index.test.ts | 5 +-
packages/tailwindcss/src/utilities.test.ts | 333 ++---
packages/tailwindcss/src/utilities.ts | 17 +-
packages/tailwindcss/tests/ui.spec.ts | 20 +-
...1.30.2.patch => lightningcss@1.31.1.patch} | 0
playgrounds/nextjs/package.json | 12 +-
playgrounds/v3/package.json | 14 +-
playgrounds/vite/package.json | 8 +-
pnpm-lock.yaml | 1277 ++++++++---------
pnpm-workspace.yaml | 20 +-
24 files changed, 897 insertions(+), 879 deletions(-)
rename patches/{lightningcss@1.30.2.patch => lightningcss@1.31.1.patch} (100%)
diff --git a/.prettierignore b/.prettierignore
index 3de4530ddcf2..4f50b932fbca 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -4,5 +4,6 @@ pnpm-lock.yaml
target/
crates/node/index.d.ts
crates/node/index.js
+crates/ignore/
.next
.fingerprint
diff --git a/crates/node/npm/wasm32-wasi/package.json b/crates/node/npm/wasm32-wasi/package.json
index ea06f944dd16..059735f5317d 100644
--- a/crates/node/npm/wasm32-wasi/package.json
+++ b/crates/node/npm/wasm32-wasi/package.json
@@ -28,11 +28,11 @@
"browser": "tailwindcss-oxide.wasi-browser.js",
"dependencies": {
"@napi-rs/wasm-runtime": "^1.1.1",
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1",
+ "@emnapi/core": "^1.8.1",
+ "@emnapi/runtime": "^1.8.1",
"@tybys/wasm-util": "^0.10.1",
"@emnapi/wasi-threads": "^1.1.0",
- "tslib": "^2.4.0"
+ "tslib": "^2.8.1"
},
"bundledDependencies": [
"@napi-rs/wasm-runtime",
diff --git a/crates/node/package.json b/crates/node/package.json
index 00557993d8f3..d9b07eab58c5 100644
--- a/crates/node/package.json
+++ b/crates/node/package.json
@@ -35,7 +35,7 @@
"devDependencies": {
"@napi-rs/cli": "3.4.1",
"@napi-rs/wasm-runtime": "^1.1.1",
- "emnapi": "1.7.1"
+ "emnapi": "1.8.1"
},
"engines": {
"node": ">= 20"
diff --git a/package.json b/package.json
index 1b5a50a82d97..e1e310c69d52 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
},
"license": "MIT",
"devDependencies": {
- "@playwright/test": "^1.57.0",
+ "@playwright/test": "^1.58.0",
"@types/node": "catalog:",
"postcss": "8.5.6",
"postcss-import": "^16.1.1",
@@ -56,14 +56,14 @@
"prettier-plugin-embed": "^0.5.1",
"prettier-plugin-organize-imports": "^4.3.0",
"tsup": "^8.5.1",
- "turbo": "^2.7.2",
+ "turbo": "^2.7.6",
"typescript": "^5.5.4",
- "vitest": "^4.0.3"
+ "vitest": "^4.0.18"
},
"packageManager": "pnpm@9.6.0",
"pnpm": {
"patchedDependencies": {
- "lightningcss@1.30.2": "patches/lightningcss@1.30.2.patch",
+ "lightningcss@1.31.1": "patches/lightningcss@1.31.1.patch",
"@parcel/watcher@2.5.1": "patches/@parcel__watcher@2.5.1.patch"
}
}
diff --git a/packages/@tailwindcss-browser/package.json b/packages/@tailwindcss-browser/package.json
index 6bda85f75c78..8b9b1b5e24ce 100644
--- a/packages/@tailwindcss-browser/package.json
+++ b/packages/@tailwindcss-browser/package.json
@@ -30,7 +30,7 @@
"access": "public"
},
"devDependencies": {
- "h3": "^1.15.4",
+ "h3": "^1.15.5",
"listhen": "^1.9.0",
"tailwindcss": "workspace:*"
}
diff --git a/packages/@tailwindcss-node/package.json b/packages/@tailwindcss-node/package.json
index 257b440aea3a..8afadb378108 100644
--- a/packages/@tailwindcss-node/package.json
+++ b/packages/@tailwindcss-node/package.json
@@ -37,7 +37,7 @@
}
},
"dependencies": {
- "@jridgewell/remapping": "^2.3.4",
+ "@jridgewell/remapping": "^2.3.5",
"enhanced-resolve": "^5.18.4",
"jiti": "^2.6.1",
"lightningcss": "catalog:",
diff --git a/packages/@tailwindcss-postcss/package.json b/packages/@tailwindcss-postcss/package.json
index 22e775d728ae..ff815030ab4f 100644
--- a/packages/@tailwindcss-postcss/package.json
+++ b/packages/@tailwindcss-postcss/package.json
@@ -33,7 +33,7 @@
"@alloc/quick-lru": "^5.2.0",
"@tailwindcss/node": "workspace:*",
"@tailwindcss/oxide": "workspace:*",
- "postcss": "^8.4.41",
+ "postcss": "^8.5.6",
"tailwindcss": "workspace:*"
},
"devDependencies": {
diff --git a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
index 8fdc0dbf740f..fd6db912cf4a 100644
--- a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
+++ b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
@@ -11,8 +11,10 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
@layer theme {
:root, :host {
- --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
+ "Noto Color Emoji";
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
+ monospace;
--color-black: #000;
--text-2xl: 1.5rem;
--text-2xl--line-height: calc(2 / 1.5);
diff --git a/packages/@tailwindcss-standalone/package.json b/packages/@tailwindcss-standalone/package.json
index cfe124563789..cdc83f34a622 100644
--- a/packages/@tailwindcss-standalone/package.json
+++ b/packages/@tailwindcss-standalone/package.json
@@ -35,15 +35,15 @@
},
"__notes": "These binary packages must be included so Bun can build the CLI for all supported platforms. We also rely on Lightning CSS and Parcel being patched so Bun can statically analyze the executables.",
"devDependencies": {
- "@parcel/watcher-darwin-arm64": "^2.5.1",
- "@parcel/watcher-darwin-x64": "^2.5.1",
- "@parcel/watcher-linux-arm64-glibc": "^2.5.1",
- "@parcel/watcher-linux-arm64-musl": "^2.5.1",
- "@parcel/watcher-linux-x64-glibc": "^2.5.1",
- "@parcel/watcher-linux-x64-musl": "^2.5.1",
- "@parcel/watcher-win32-x64": "^2.5.1",
- "@types/bun": "^1.3.5",
- "bun": "^1.3.5",
+ "@parcel/watcher-darwin-arm64": "^2.5.6",
+ "@parcel/watcher-darwin-x64": "^2.5.6",
+ "@parcel/watcher-linux-arm64-glibc": "^2.5.6",
+ "@parcel/watcher-linux-arm64-musl": "^2.5.6",
+ "@parcel/watcher-linux-x64-glibc": "^2.5.6",
+ "@parcel/watcher-linux-x64-musl": "^2.5.6",
+ "@parcel/watcher-win32-x64": "^2.5.6",
+ "@types/bun": "^1.3.7",
+ "bun": "^1.3.7",
"lightningcss-darwin-arm64": "catalog:",
"lightningcss-darwin-x64": "catalog:",
"lightningcss-linux-arm64-gnu": "catalog:",
diff --git a/packages/@tailwindcss-standalone/src/index.ts b/packages/@tailwindcss-standalone/src/index.ts
index ce6ba84d11fe..23a928f8b68b 100644
--- a/packages/@tailwindcss-standalone/src/index.ts
+++ b/packages/@tailwindcss-standalone/src/index.ts
@@ -75,12 +75,10 @@ Bun.plugin({
'tailwindcss/plugin': await import('tailwindcss/plugin'),
'tailwindcss/plugin.js': await import('tailwindcss/plugin'),
'tailwindcss/package.json': await import('tailwindcss/package.json'),
- 'tailwindcss/lib/util/flattenColorPalette': await import(
- 'tailwindcss/lib/util/flattenColorPalette'
- ),
- 'tailwindcss/lib/util/flattenColorPalette.js': await import(
- 'tailwindcss/lib/util/flattenColorPalette'
- ),
+ 'tailwindcss/lib/util/flattenColorPalette':
+ await import('tailwindcss/lib/util/flattenColorPalette'),
+ 'tailwindcss/lib/util/flattenColorPalette.js':
+ await import('tailwindcss/lib/util/flattenColorPalette'),
'tailwindcss/defaultTheme': await import('tailwindcss/defaultTheme'),
'tailwindcss/defaultTheme.js': await import('tailwindcss/defaultTheme'),
}
diff --git a/packages/@tailwindcss-upgrade/package.json b/packages/@tailwindcss-upgrade/package.json
index e41e40b22fcc..e1490711b622 100644
--- a/packages/@tailwindcss-upgrade/package.json
+++ b/packages/@tailwindcss-upgrade/package.json
@@ -36,7 +36,7 @@
"jiti": "^2.0.0-beta.3",
"mri": "^1.2.0",
"picocolors": "^1.1.1",
- "postcss": "^8.4.41",
+ "postcss": "^8.5.6",
"postcss-import": "^16.1.1",
"postcss-selector-parser": "^7.1.1",
"prettier": "catalog:",
diff --git a/packages/tailwindcss/package.json b/packages/tailwindcss/package.json
index a453c9a1461f..5650b1e2cd0f 100644
--- a/packages/tailwindcss/package.json
+++ b/packages/tailwindcss/package.json
@@ -127,7 +127,7 @@
"utilities.css"
],
"devDependencies": {
- "@jridgewell/remapping": "^2.3.4",
+ "@jridgewell/remapping": "^2.3.5",
"@tailwindcss/oxide": "workspace:^",
"@types/node": "catalog:",
"dedent": "1.7.1",
diff --git a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
index 70060e1e1797..88365b1ce156 100644
--- a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
@@ -129,8 +129,10 @@ exports[`compiling CSS > \`@tailwind utilities\` is replaced by utilities using
exports[`compiling CSS > prefix all CSS variables inside preflight 1`] = `
"@layer theme {
:root, :host {
- --tw-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- --tw-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ --tw-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
+ "Noto Color Emoji";
+ --tw-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
+ monospace;
--tw-default-font-family: var(--tw-font-sans);
--tw-default-mono-font-family: var(--tw-font-mono);
}
diff --git a/packages/tailwindcss/src/css-functions.test.ts b/packages/tailwindcss/src/css-functions.test.ts
index 464f058641e0..0c5a3c97e46a 100644
--- a/packages/tailwindcss/src/css-functions.test.ts
+++ b/packages/tailwindcss/src/css-functions.test.ts
@@ -313,7 +313,8 @@ describe('--theme(…)', () => {
),
).toMatchInlineSnapshot(`
":root, :host {
- --tw-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ --tw-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
+ "Segoe UI Symbol", "Noto Color Emoji";
--tw-default-font-family: var(--tw-font-sans);
}
diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts
index 5182cdd14714..1534f84cf902 100644
--- a/packages/tailwindcss/src/index.test.ts
+++ b/packages/tailwindcss/src/index.test.ts
@@ -1561,7 +1561,8 @@ describe('Parsing theme values from CSS', () => {
),
).toMatchInlineSnapshot(`
":root, :host {
- --animate-very-long-animation-name: very-long-animation-name var(--very-long-animation-name-configuration, 2.5s ease-in-out 0s infinite normal none running);
+ --animate-very-long-animation-name: very-long-animation-name
+ var(--very-long-animation-name-configuration, 2.5s ease-in-out 0s infinite normal none running);
}
.animate-very-long-animation-name {
@@ -5650,7 +5651,7 @@ describe('`color-mix(…)` polyfill', () => {
@supports (color: color-mix(in lab, red, red)) {
.text-red-500\\/50 {
- color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
+ color: color-mix(in oklab,var(--color-red-500)50%,transparent);
}
}"
`)
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index f6860135890c..29e8dae3a524 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -5764,27 +5764,27 @@ test('rotate-x', async () => {
.-rotate-x-\\(--var\\) {
--tw-rotate-x: rotateX(calc(var(--var) * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.-rotate-x-45 {
--tw-rotate-x: rotateX(calc(45deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-x-\\(--var\\) {
--tw-rotate-x: rotateX(var(--var));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-x-45 {
--tw-rotate-x: rotateX(45deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-x-\\[123deg\\] {
--tw-rotate-x: rotateX(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -5850,32 +5850,32 @@ test('rotate-y', async () => {
.-rotate-y-\\(--var\\) {
--tw-rotate-y: rotateY(calc(var(--var) * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.-rotate-y-45 {
--tw-rotate-y: rotateY(calc(45deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.-rotate-y-\\[123deg\\] {
--tw-rotate-y: rotateY(calc(123deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-y-\\(--var\\) {
--tw-rotate-y: rotateY(var(--var));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-y-45 {
--tw-rotate-y: rotateY(45deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-y-\\[123deg\\] {
--tw-rotate-y: rotateY(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -5941,32 +5941,32 @@ test('rotate-z', async () => {
.-rotate-z-\\(--var\\) {
--tw-rotate-z: rotateZ(calc(var(--var) * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.-rotate-z-45 {
--tw-rotate-z: rotateZ(calc(45deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.-rotate-z-\\[123deg\\] {
--tw-rotate-z: rotateZ(calc(123deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-z-\\(--var\\) {
--tw-rotate-z: rotateZ(var(--var));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-z-45 {
--tw-rotate-z: rotateZ(45deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.rotate-z-\\[123deg\\] {
--tw-rotate-z: rotateZ(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -6024,19 +6024,19 @@ test('skew', async () => {
.-skew-6 {
--tw-skew-x: skewX(calc(6deg * -1));
--tw-skew-y: skewY(calc(6deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-6 {
--tw-skew-x: skewX(6deg);
--tw-skew-y: skewY(6deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-\\[123deg\\] {
--tw-skew-x: skewX(123deg);
--tw-skew-y: skewY(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -6092,17 +6092,17 @@ test('skew-x', async () => {
.-skew-x-6 {
--tw-skew-x: skewX(calc(6deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-x-6 {
--tw-skew-x: skewX(6deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-x-\\[123deg\\] {
--tw-skew-x: skewX(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -6158,17 +6158,17 @@ test('skew-y', async () => {
.-skew-y-6 {
--tw-skew-y: skewY(calc(6deg * -1));
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-y-6 {
--tw-skew-y: skewY(6deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.skew-y-\\[123deg\\] {
--tw-skew-y: skewY(123deg);
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
@property --tw-rotate-x {
@@ -6551,7 +6551,7 @@ test('transform', async () => {
}
.transform {
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.transform-\\[scaleZ\\(2\\)_rotateY\\(45deg\\)\\] {
@@ -6559,11 +6559,11 @@ test('transform', async () => {
}
.transform-cpu {
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.transform-gpu {
- transform: translateZ(0) var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
+ transform: translateZ(0) var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
.transform-none {
@@ -7075,32 +7075,32 @@ test('touch-pan', async () => {
.touch-pan-left {
--tw-pan-x: pan-left;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
.touch-pan-right {
--tw-pan-x: pan-right;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
.touch-pan-x {
--tw-pan-x: pan-x;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
.touch-pan-down {
--tw-pan-y: pan-down;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
.touch-pan-up {
--tw-pan-y: pan-up;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
.touch-pan-y {
--tw-pan-y: pan-y;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
@property --tw-pan-x {
@@ -7150,7 +7150,7 @@ test('touch-pinch-zoom', async () => {
.touch-pinch-zoom {
--tw-pinch-zoom: pinch-zoom;
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
}
@property --tw-pan-x {
@@ -22139,7 +22139,8 @@ test('font', async () => {
}
:root, :host {
- --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
+ "Segoe UI Symbol", "Noto Color Emoji";
--font-weight-bold: 650;
}
@@ -22232,7 +22233,7 @@ test('font-features', async () => {
}
.font-features-\\[\\"c2sc\\"\\,\\"smcp\\"\\] {
- font-feature-settings: "c2sc", "smcp";
+ font-feature-settings: "c2sc","smcp";
}
.font-features-\\[\\"smcp\\"\\] {
@@ -23037,73 +23038,73 @@ test('filter', async () => {
.blur-\\[4px\\] {
--tw-blur: blur(4px);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.blur-none {
- --tw-blur: ;
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ --tw-blur: ;
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.blur-xl {
--tw-blur: blur(var(--blur-xl));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.brightness-50 {
--tw-brightness: brightness(50%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.brightness-\\[1\\.23\\] {
--tw-brightness: brightness(1.23);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.contrast-50 {
--tw-contrast: contrast(50%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.contrast-\\[1\\.23\\] {
--tw-contrast: contrast(1.23);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow\\/25 {
--tw-drop-shadow-alpha: 25%;
--tw-drop-shadow-size: drop-shadow(0 1px 1px var(--tw-drop-shadow-color, oklab(0% 0 0 / .25)));
--tw-drop-shadow: drop-shadow(var(--drop-shadow));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow {
--tw-drop-shadow-size: drop-shadow(0 1px 1px var(--tw-drop-shadow-color, #0000000d));
--tw-drop-shadow: drop-shadow(var(--drop-shadow));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-\\[0_0_red\\] {
--tw-drop-shadow-size: drop-shadow(0 0 var(--tw-drop-shadow-color, red));
--tw-drop-shadow: var(--tw-drop-shadow-size);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-multi {
--tw-drop-shadow-size: drop-shadow(0 1px 1px var(--tw-drop-shadow-color, #0000000d)) drop-shadow(0 9px 7px var(--tw-drop-shadow-color, #0000001a));
--tw-drop-shadow: drop-shadow(0 1px 1px #0000000d) drop-shadow(0 9px 7px #0000001a);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-xl {
--tw-drop-shadow-size: drop-shadow(0 9px 7px var(--tw-drop-shadow-color, #0000001a));
--tw-drop-shadow: drop-shadow(var(--drop-shadow-xl));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-none {
- --tw-drop-shadow: ;
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ --tw-drop-shadow: ;
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.drop-shadow-inherit {
@@ -23141,91 +23142,91 @@ test('filter', async () => {
.grayscale {
--tw-grayscale: grayscale(100%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.grayscale-0 {
--tw-grayscale: grayscale(0%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.grayscale-\\[var\\(--value\\)\\] {
--tw-grayscale: grayscale(var(--value));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.-hue-rotate-15 {
--tw-hue-rotate: hue-rotate(calc(15deg * -1));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.-hue-rotate-\\[45deg\\] {
--tw-hue-rotate: hue-rotate(calc(45deg * -1));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.hue-rotate-15 {
--tw-hue-rotate: hue-rotate(15deg);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.hue-rotate-\\[45deg\\] {
--tw-hue-rotate: hue-rotate(45deg);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.invert {
--tw-invert: invert(100%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.invert-0 {
--tw-invert: invert(0%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.invert-\\[var\\(--value\\)\\] {
--tw-invert: invert(var(--value));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.saturate-0 {
--tw-saturate: saturate(0%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.saturate-\\[1\\.75\\] {
--tw-saturate: saturate(1.75);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.saturate-\\[var\\(--value\\)\\] {
--tw-saturate: saturate(var(--value));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.sepia {
--tw-sepia: sepia(100%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.sepia-0 {
--tw-sepia: sepia(0%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.sepia-\\[50\\%\\] {
--tw-sepia: sepia(50%);
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.sepia-\\[var\\(--value\\)\\] {
--tw-sepia: sepia(var(--value));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.filter {
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
.filter-\\[var\\(--value\\)\\] {
@@ -23418,7 +23419,7 @@ test('filter', async () => {
.blur-none {
--tw-blur: blur(var(--blur-none));
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
}
@property --tw-blur {
@@ -23557,187 +23558,187 @@ test('backdrop-filter', async () => {
.backdrop-blur-\\[4px\\] {
--tw-backdrop-blur: blur(4px);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-blur-none {
- --tw-backdrop-blur: ;
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ --tw-backdrop-blur: ;
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-blur-xl {
--tw-backdrop-blur: blur(var(--blur-xl));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-brightness-50 {
--tw-backdrop-brightness: brightness(50%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-brightness-\\[1\\.23\\] {
--tw-backdrop-brightness: brightness(1.23);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-contrast-50 {
--tw-backdrop-contrast: contrast(50%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-contrast-\\[1\\.23\\] {
--tw-backdrop-contrast: contrast(1.23);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-grayscale {
--tw-backdrop-grayscale: grayscale(100%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-grayscale-0 {
--tw-backdrop-grayscale: grayscale(0%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-grayscale-\\[var\\(--value\\)\\] {
--tw-backdrop-grayscale: grayscale(var(--value));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.-backdrop-hue-rotate-15 {
--tw-backdrop-hue-rotate: hue-rotate(calc(15deg * -1));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.-backdrop-hue-rotate-\\[45deg\\] {
--tw-backdrop-hue-rotate: hue-rotate(calc(45deg * -1));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-hue-rotate-15 {
--tw-backdrop-hue-rotate: hue-rotate(15deg);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-hue-rotate-\\[45deg\\] {
--tw-backdrop-hue-rotate: hue-rotate(45deg);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-invert {
--tw-backdrop-invert: invert(100%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-invert-0 {
--tw-backdrop-invert: invert(0%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-invert-\\[var\\(--value\\)\\] {
--tw-backdrop-invert: invert(var(--value));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-1\\.25 {
--tw-backdrop-opacity: opacity(1.25%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-2\\.5 {
--tw-backdrop-opacity: opacity(2.5%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-3\\.75 {
--tw-backdrop-opacity: opacity(3.75%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-50 {
--tw-backdrop-opacity: opacity(50%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-71 {
--tw-backdrop-opacity: opacity(71%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-opacity-\\[0\\.5\\] {
--tw-backdrop-opacity: opacity(.5);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-saturate-0 {
--tw-backdrop-saturate: saturate(0%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-saturate-\\[1\\.75\\] {
--tw-backdrop-saturate: saturate(1.75);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-saturate-\\[var\\(--value\\)\\] {
--tw-backdrop-saturate: saturate(var(--value));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-sepia {
--tw-backdrop-sepia: sepia(100%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-sepia-0 {
--tw-backdrop-sepia: sepia(0%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-sepia-\\[50\\%\\] {
--tw-backdrop-sepia: sepia(50%);
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-sepia-\\[var\\(--value\\)\\] {
--tw-backdrop-sepia: sepia(var(--value));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-filter {
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
.backdrop-filter-\\[var\\(--value\\)\\] {
@@ -23901,8 +23902,8 @@ test('backdrop-filter', async () => {
.backdrop-blur-none {
--tw-backdrop-blur: blur(var(--backdrop-blur-none));
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
}
@property --tw-backdrop-blur {
@@ -24369,27 +24370,27 @@ test('contain', async () => {
.contain-inline-size {
--tw-contain-size: inline-size;
- contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
+ contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
}
.contain-layout {
--tw-contain-layout: layout;
- contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
+ contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
}
.contain-paint {
--tw-contain-paint: paint;
- contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
+ contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
}
.contain-size {
--tw-contain-size: size;
- contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
+ contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
}
.contain-style {
--tw-contain-style: style;
- contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
+ contain: var(--tw-contain-size, ) var(--tw-contain-layout, ) var(--tw-contain-paint, ) var(--tw-contain-style, );
}
.contain-\\[unset\\] {
@@ -24717,42 +24718,42 @@ test('font-variant-numeric', async () => {
.diagonal-fractions {
--tw-numeric-fraction: diagonal-fractions;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.lining-nums {
--tw-numeric-figure: lining-nums;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.oldstyle-nums {
--tw-numeric-figure: oldstyle-nums;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.ordinal {
--tw-ordinal: ordinal;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.proportional-nums {
--tw-numeric-spacing: proportional-nums;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.slashed-zero {
--tw-slashed-zero: slashed-zero;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.stacked-fractions {
--tw-numeric-fraction: stacked-fractions;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.tabular-nums {
--tw-numeric-spacing: tabular-nums;
- font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
+ font-variant-numeric: var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, );
}
.normal-nums {
@@ -27124,37 +27125,37 @@ test('ring', async () => {
}
.ring {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-0 {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-1 {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-2 {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-4 {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-\\[12px\\] {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(12px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(12px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.ring-\\[length\\:var\\(--my-width\\)\\] {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(var(--my-width) + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(var(--my-width) + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
@@ -27448,7 +27449,7 @@ test('ring', async () => {
}
.ring {
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
@@ -28018,32 +28019,32 @@ test('ring-offset', async () => {
.ring-offset-0 {
--tw-ring-offset-width: 0px;
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-1 {
--tw-ring-offset-width: 1px;
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-2 {
--tw-ring-offset-width: 2px;
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-4 {
--tw-ring-offset-width: 4px;
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-\\[12px\\] {
--tw-ring-offset-width: 12px;
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-\\[length\\:var\\(--my-width\\)\\] {
--tw-ring-offset-width: var(--my-width);
- --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-offset-shadow: var(--tw-ring-inset, ) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
}
.ring-offset-\\[\\#0088cc\\] {
@@ -28599,7 +28600,7 @@ describe('custom utilities', () => {
.text-sm {
font-size: var(--text-sm, .8755rem);
line-height: var(--text-sm--line-height, 1.255rem);
- text-rendering: optimizeLegibility;
+ text-rendering: optimizelegibility;
font-size: var(--text-sm, .875rem);
line-height: var(--tw-leading, var(--text-sm--line-height, 1.25rem));
}
@@ -29582,7 +29583,7 @@ describe('custom utilities', () => {
}
.example-\\[7\\/9\\] {
- --value: 7 / 9;
+ --value: 7/9;
}
.example-video {
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index 66ae59230e12..fd524f495575 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -421,7 +421,7 @@ export function createUtilities(theme: Theme) {
if (value === null && desc.supportsFractions && candidate.value.fraction) {
let [lhs, rhs] = segment(candidate.value.fraction, '/')
if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return
- value = `calc(${candidate.value.fraction} * 100%)`
+ value = `calc(${lhs} / ${rhs} * 100%)`
}
// If there is still no value but the utility supports bare values,
@@ -5607,7 +5607,7 @@ export function createUtilities(theme: Theme) {
value,
alpha,
(color) => `var(--tw-inset-shadow-color, ${color})`,
- 'inset ',
+ 'inset',
),
decl('box-shadow', cssBoxShadowValue),
]
@@ -6377,7 +6377,7 @@ function resolveValueFunction(
// Ratio must be a valid fraction, e.g.: /
if (type === 'ratio') {
- let [lhs, rhs] = segment(resolved, '/')
+ let [lhs, rhs] = segment(resolved, '/').map(Number)
if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) continue
}
@@ -6392,7 +6392,12 @@ function resolveValueFunction(
continue
}
- return { nodes: ValueParser.parse(resolved), ratio: type === 'ratio' }
+ if (type === 'ratio') {
+ let [lhs, rhs] = segment(resolved, '/')
+ return { nodes: ValueParser.parse(`${lhs.trim()} / ${rhs.trim()}`), ratio: true }
+ }
+
+ return { nodes: ValueParser.parse(resolved), ratio: false }
}
// Arbitrary value, e.g.: `--value([integer])`
@@ -6471,8 +6476,8 @@ function alphaReplacedShadowProperties(
function applyPrefix(x: string) {
if (!prefix) return x
return segment(x, ',')
- .map((value) => prefix + value)
- .join(',')
+ .map((value) => prefix.trim() + ' ' + value.trim())
+ .join(', ')
}
if (requiresFallback) {
diff --git a/packages/tailwindcss/tests/ui.spec.ts b/packages/tailwindcss/tests/ui.spec.ts
index 0c3534efd748..889848c5cb68 100644
--- a/packages/tailwindcss/tests/ui.spec.ts
+++ b/packages/tailwindcss/tests/ui.spec.ts
@@ -1911,7 +1911,7 @@ test('outline style is optional', async ({ page }) => {
html`
`,
)
- expect(await getPropertyValue('#x', 'outline')).toEqual('rgb(255, 255, 255) solid 2px')
+ expect(await getPropertyValue('#x', 'outline')).toEqual('2px solid rgb(255, 255, 255)')
})
test('outline style is preserved when changing outline width', async ({ page }) => {
@@ -1922,11 +1922,11 @@ test('outline style is preserved when changing outline width', async ({ page })
`,
)
- expect(await getPropertyValue('#x', 'outline')).toEqual('rgb(255, 255, 255) dotted 2px')
+ expect(await getPropertyValue('#x', 'outline')).toEqual('2px dotted rgb(255, 255, 255)')
await page.locator('#x').hover()
- expect(await getPropertyValue('#x', 'outline')).toEqual('rgb(255, 255, 255) dotted 4px')
+ expect(await getPropertyValue('#x', 'outline')).toEqual('4px dotted rgb(255, 255, 255)')
})
test('borders can be added without a border-style utility', async ({ page }) => {
@@ -2249,7 +2249,7 @@ async function getPropertyValue(
selector: [string, string | undefined],
property: string,
) {
- return page.evaluate(
+ let value = await page.evaluate(
([[selector, pseudo], property]) => {
return window
.getComputedStyle(document.querySelector(selector)!, pseudo)
@@ -2257,4 +2257,16 @@ async function getPropertyValue(
},
[selector, property] as const,
)
+
+ switch (property) {
+ case 'outline':
+ // Order in webkit vs chromium is different. Sort to normalize.
+ return segment(value, ' ')
+ .map((part) => part.trim())
+ .sort((a, z) => a.length - z.length)
+ .join(' ')
+
+ default:
+ return value
+ }
}
diff --git a/patches/lightningcss@1.30.2.patch b/patches/lightningcss@1.31.1.patch
similarity index 100%
rename from patches/lightningcss@1.30.2.patch
rename to patches/lightningcss@1.31.1.patch
diff --git a/playgrounds/nextjs/package.json b/playgrounds/nextjs/package.json
index 8dc97a047be5..a996f3eab11c 100644
--- a/playgrounds/nextjs/package.json
+++ b/playgrounds/nextjs/package.json
@@ -11,17 +11,17 @@
"dependencies": {
"@tailwindcss/postcss": "workspace:^",
"fast-glob": "^3.3.3",
- "next": "^16.1.0",
- "react": "^19.2.3",
- "react-dom": "^19.2.3",
+ "next": "^16.1.6",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4",
"tailwindcss": "workspace:^"
},
"devDependencies": {
"@types/node": "catalog:",
- "@types/react": "^19.2.7",
+ "@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
"eslint": "^9.39.2",
- "eslint-config-next": "^16.1.0",
- "typescript": "^5.5.4"
+ "eslint-config-next": "^16.1.6",
+ "typescript": "^5.9.3"
}
}
diff --git a/playgrounds/v3/package.json b/playgrounds/v3/package.json
index c03663b698b8..b8e1e16fc6ca 100644
--- a/playgrounds/v3/package.json
+++ b/playgrounds/v3/package.json
@@ -9,18 +9,18 @@
"upgrade": "node scripts/upgrade.mjs"
},
"dependencies": {
- "next": "^16.1.0",
- "react": "^19.2.3",
- "react-dom": "^19.2.3",
+ "next": "^16.1.6",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4",
"tailwindcss": "^3"
},
"devDependencies": {
- "@types/node": "^20.14.8",
- "@types/react": "^19.2.7",
+ "@types/node": "catalog:",
+ "@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
"autoprefixer": "^10.4.23",
"eslint": "^9.39.2",
- "eslint-config-next": "^16.1.0",
- "typescript": "^5.5.4"
+ "eslint-config-next": "^16.1.6",
+ "typescript": "^5.9.3"
}
}
diff --git a/playgrounds/vite/package.json b/playgrounds/vite/package.json
index e158445cb765..d339dc39fe8b 100644
--- a/playgrounds/vite/package.json
+++ b/playgrounds/vite/package.json
@@ -11,14 +11,14 @@
"dependencies": {
"@tailwindcss/vite": "workspace:^",
"@vitejs/plugin-react": "^5.1.2",
- "react": "^19.2.3",
- "react-dom": "^19.2.3",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4",
"tailwindcss": "workspace:^"
},
"devDependencies": {
- "@types/react": "^19.2.7",
+ "@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
- "bun": "^1.3.5",
+ "bun": "^1.3.7",
"vite": "catalog:"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a7d9cf6f1ac4..be257c0fbfe0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,35 +10,35 @@ catalogs:
specifier: ^20.19.0
version: 20.19.1
lightningcss:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-darwin-arm64:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-darwin-x64:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-linux-arm64-gnu:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-linux-arm64-musl:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-linux-x64-gnu:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-linux-x64-musl:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
lightningcss-win32-x64-msvc:
- specifier: 1.30.2
- version: 1.30.2
+ specifier: 1.31.1
+ version: 1.31.1
prettier:
- specifier: 3.6.2
- version: 3.6.2
+ specifier: 3.8.1
+ version: 3.8.1
vite:
- specifier: ^7.0.0
- version: 7.0.0
+ specifier: ^7.3.1
+ version: 7.3.1
webpack:
specifier: ^5
version: 5.104.1
@@ -47,17 +47,17 @@ patchedDependencies:
'@parcel/watcher@2.5.1':
hash: zs2vvlrje3h42xp5ed2v44fep4
path: patches/@parcel__watcher@2.5.1.patch
- lightningcss@1.30.2:
+ lightningcss@1.31.1:
hash: tzyxy3asfxcqc7ihrooumyi5fm
- path: patches/lightningcss@1.30.2.patch
+ path: patches/lightningcss@1.31.1.patch
importers:
.:
devDependencies:
'@playwright/test':
- specifier: ^1.57.0
- version: 1.57.0
+ specifier: ^1.58.0
+ version: 1.58.0
'@types/node':
specifier: 'catalog:'
version: 20.19.1
@@ -69,25 +69,25 @@ importers:
version: 16.1.1(postcss@8.5.6)
prettier:
specifier: 'catalog:'
- version: 3.6.2
+ version: 3.8.1
prettier-plugin-embed:
specifier: ^0.5.1
version: 0.5.1
prettier-plugin-organize-imports:
specifier: ^4.3.0
- version: 4.3.0(prettier@3.6.2)(typescript@5.5.4)
+ version: 4.3.0(prettier@3.8.1)(typescript@5.5.4)
tsup:
specifier: ^8.5.1
version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.19.1)(typescript@5.5.4)(yaml@2.6.0)
turbo:
- specifier: ^2.7.2
- version: 2.7.2
+ specifier: ^2.7.6
+ version: 2.7.6
typescript:
specifier: ^5.5.4
version: 5.5.4
vitest:
- specifier: ^4.0.3
- version: 4.0.12(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ specifier: ^4.0.18
+ version: 4.0.18(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
crates/node:
optionalDependencies:
@@ -130,13 +130,13 @@ importers:
devDependencies:
'@napi-rs/cli':
specifier: 3.4.1
- version: 3.4.1(@emnapi/runtime@1.7.1)(@types/node@20.19.1)(node-addon-api@8.3.0)
+ version: 3.4.1(@emnapi/runtime@1.8.1)(@types/node@20.19.1)(node-addon-api@8.3.0)
'@napi-rs/wasm-runtime':
specifier: ^1.1.1
version: 1.1.1
emnapi:
- specifier: 1.7.1
- version: 1.7.1(node-addon-api@8.3.0)
+ specifier: 1.8.1
+ version: 1.8.1(node-addon-api@8.3.0)
crates/node/npm/android-arm-eabi: {}
@@ -161,11 +161,11 @@ importers:
crates/node/npm/wasm32-wasi:
dependencies:
'@emnapi/core':
- specifier: ^1.7.1
- version: 1.7.1
+ specifier: ^1.8.1
+ version: 1.8.1
'@emnapi/runtime':
- specifier: ^1.7.1
- version: 1.7.1
+ specifier: ^1.8.1
+ version: 1.8.1
'@emnapi/wasi-threads':
specifier: ^1.1.0
version: 1.1.0
@@ -176,7 +176,7 @@ importers:
specifier: ^0.10.1
version: 0.10.1
tslib:
- specifier: ^2.4.0
+ specifier: ^2.8.1
version: 2.8.1
crates/node/npm/win32-arm64-msvc: {}
@@ -198,8 +198,8 @@ importers:
packages/@tailwindcss-browser:
devDependencies:
h3:
- specifier: ^1.15.4
- version: 1.15.4
+ specifier: ^1.15.5
+ version: 1.15.5
listhen:
specifier: ^1.9.0
version: 1.9.0
@@ -234,7 +234,7 @@ importers:
packages/@tailwindcss-node:
dependencies:
'@jridgewell/remapping':
- specifier: ^2.3.4
+ specifier: ^2.3.5
version: 2.3.5
enhanced-resolve:
specifier: ^5.18.4
@@ -244,7 +244,7 @@ importers:
version: 2.6.1
lightningcss:
specifier: 'catalog:'
- version: 1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
+ version: 1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
magic-string:
specifier: ^0.30.21
version: 0.30.21
@@ -267,8 +267,8 @@ importers:
specifier: workspace:*
version: link:../../crates/node
postcss:
- specifier: ^8.4.41
- version: 8.4.41
+ specifier: ^8.5.6
+ version: 8.5.6
tailwindcss:
specifier: workspace:*
version: link:../tailwindcss
@@ -287,7 +287,7 @@ importers:
version: link:../internal-example-plugin
postcss-import:
specifier: ^16.1.1
- version: 16.1.1(postcss@8.4.41)
+ version: 16.1.1(postcss@8.5.6)
packages/@tailwindcss-standalone:
dependencies:
@@ -314,53 +314,53 @@ importers:
version: link:../tailwindcss
devDependencies:
'@parcel/watcher-darwin-arm64':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-darwin-x64':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-linux-arm64-glibc':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-linux-arm64-musl':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-linux-x64-glibc':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-linux-x64-musl':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@parcel/watcher-win32-x64':
- specifier: ^2.5.1
- version: 2.5.1
+ specifier: ^2.5.6
+ version: 2.5.6
'@types/bun':
- specifier: ^1.3.5
- version: 1.3.5
+ specifier: ^1.3.7
+ version: 1.3.7
bun:
- specifier: ^1.3.5
- version: 1.3.5
+ specifier: ^1.3.7
+ version: 1.3.7
lightningcss-darwin-arm64:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-darwin-x64:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-linux-arm64-gnu:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-linux-arm64-musl:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-linux-x64-gnu:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-linux-x64-musl:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
lightningcss-win32-x64-msvc:
specifier: 'catalog:'
- version: 1.30.2
+ version: 1.31.1
packages/@tailwindcss-upgrade:
dependencies:
@@ -392,17 +392,17 @@ importers:
specifier: ^1.1.1
version: 1.1.1
postcss:
- specifier: ^8.4.41
- version: 8.4.41
+ specifier: ^8.5.6
+ version: 8.5.6
postcss-import:
specifier: ^16.1.1
- version: 16.1.1(postcss@8.4.41)
+ version: 16.1.1(postcss@8.5.6)
postcss-selector-parser:
specifier: ^7.1.1
version: 7.1.1
prettier:
specifier: 'catalog:'
- version: 3.6.2
+ version: 3.8.1
semver:
specifier: ^7.7.3
version: 7.7.3
@@ -446,7 +446,7 @@ importers:
version: 20.19.1
vite:
specifier: 'catalog:'
- version: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ version: 7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
packages/@tailwindcss-webpack:
dependencies:
@@ -475,7 +475,7 @@ importers:
packages/tailwindcss:
devDependencies:
'@jridgewell/remapping':
- specifier: ^2.3.4
+ specifier: ^2.3.5
version: 2.3.5
'@tailwindcss/oxide':
specifier: workspace:^
@@ -488,7 +488,7 @@ importers:
version: 1.7.1
lightningcss:
specifier: 'catalog:'
- version: 1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
+ version: 1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
magic-string:
specifier: ^0.30.21
version: 0.30.21
@@ -505,14 +505,14 @@ importers:
specifier: ^3.3.3
version: 3.3.3
next:
- specifier: ^16.1.0
- version: 16.1.0(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ specifier: ^16.1.6
+ version: 16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react:
- specifier: ^19.2.3
- version: 19.2.3
+ specifier: ^19.2.4
+ version: 19.2.4
react-dom:
- specifier: ^19.2.3
- version: 19.2.3(react@19.2.3)
+ specifier: ^19.2.4
+ version: 19.2.4(react@19.2.4)
tailwindcss:
specifier: workspace:^
version: link:../../packages/tailwindcss
@@ -521,57 +521,57 @@ importers:
specifier: 'catalog:'
version: 20.19.1
'@types/react':
- specifier: ^19.2.7
- version: 19.2.7
+ specifier: ^19.2.10
+ version: 19.2.10
'@types/react-dom':
specifier: ^19.2.3
- version: 19.2.3(@types/react@19.2.7)
+ version: 19.2.3(@types/react@19.2.10)
eslint:
specifier: ^9.39.2
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
- specifier: ^16.1.0
- version: 16.1.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
+ specifier: ^16.1.6
+ version: 16.1.6(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
typescript:
- specifier: ^5.5.4
- version: 5.5.4
+ specifier: ^5.9.3
+ version: 5.9.3
playgrounds/v3:
dependencies:
next:
- specifier: ^16.1.0
- version: 16.1.0(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ specifier: ^16.1.6
+ version: 16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react:
- specifier: ^19.2.3
- version: 19.2.3
+ specifier: ^19.2.4
+ version: 19.2.4
react-dom:
- specifier: ^19.2.3
- version: 19.2.3(react@19.2.3)
+ specifier: ^19.2.4
+ version: 19.2.4(react@19.2.4)
tailwindcss:
specifier: ^3
version: 3.4.14
devDependencies:
'@types/node':
- specifier: ^20.14.8
- version: 20.14.13
+ specifier: 'catalog:'
+ version: 20.19.1
'@types/react':
- specifier: ^19.2.7
- version: 19.2.7
+ specifier: ^19.2.10
+ version: 19.2.10
'@types/react-dom':
specifier: ^19.2.3
- version: 19.2.3(@types/react@19.2.7)
+ version: 19.2.3(@types/react@19.2.10)
autoprefixer:
specifier: ^10.4.23
- version: 10.4.23(postcss@8.4.47)
+ version: 10.4.23(postcss@8.5.6)
eslint:
specifier: ^9.39.2
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
- specifier: ^16.1.0
- version: 16.1.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
+ specifier: ^16.1.6
+ version: 16.1.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
typescript:
- specifier: ^5.5.4
- version: 5.6.3
+ specifier: ^5.9.3
+ version: 5.9.3
playgrounds/vite:
dependencies:
@@ -580,29 +580,29 @@ importers:
version: link:../../packages/@tailwindcss-vite
'@vitejs/plugin-react':
specifier: ^5.1.2
- version: 5.1.2(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
+ version: 5.1.2(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
react:
- specifier: ^19.2.3
- version: 19.2.3
+ specifier: ^19.2.4
+ version: 19.2.4
react-dom:
- specifier: ^19.2.3
- version: 19.2.3(react@19.2.3)
+ specifier: ^19.2.4
+ version: 19.2.4(react@19.2.4)
tailwindcss:
specifier: workspace:^
version: link:../../packages/tailwindcss
devDependencies:
'@types/react':
- specifier: ^19.2.7
- version: 19.2.7
+ specifier: ^19.2.10
+ version: 19.2.10
'@types/react-dom':
specifier: ^19.2.3
- version: 19.2.3(@types/react@19.2.7)
+ version: 19.2.3(@types/react@19.2.10)
bun:
- specifier: ^1.3.5
- version: 1.3.5
+ specifier: ^1.3.7
+ version: 1.3.7
vite:
specifier: 'catalog:'
- version: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ version: 7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
packages:
@@ -696,9 +696,15 @@ packages:
'@emnapi/core@1.7.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
+ '@emnapi/core@1.8.1':
+ resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
+
'@emnapi/runtime@1.7.1':
resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
+ '@emnapi/runtime@1.8.1':
+ resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
+
'@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
@@ -1506,9 +1512,6 @@ packages:
'@jridgewell/source-map@0.3.6':
resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
- '@jridgewell/sourcemap-codec@1.5.0':
- resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
-
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
@@ -1851,56 +1854,56 @@ packages:
resolution: {integrity: sha512-enkZYyuCdo+9jneCPE/0fjIta4wWnvVN9hBo2HuiMpRF0q3lzv1J6b/cl7i0mxZUKhBrV3aCKDBQnCOhwKbPmQ==}
engines: {node: '>= 10'}
- '@next/env@16.1.0':
- resolution: {integrity: sha512-Dd23XQeFHmhf3KBW76leYVkejHlCdB7erakC2At2apL1N08Bm+dLYNP+nNHh0tzUXfPQcNcXiQyacw0PG4Fcpw==}
+ '@next/env@16.1.6':
+ resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==}
- '@next/eslint-plugin-next@16.1.0':
- resolution: {integrity: sha512-sooC/k0LCF4/jLXYHpgfzJot04lZQqsttn8XJpTguP8N3GhqXN3wSkh68no2OcZzS/qeGwKDFTqhZ8WofdXmmQ==}
+ '@next/eslint-plugin-next@16.1.6':
+ resolution: {integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==}
- '@next/swc-darwin-arm64@16.1.0':
- resolution: {integrity: sha512-onHq8dl8KjDb8taANQdzs3XmIqQWV3fYdslkGENuvVInFQzZnuBYYOG2HGHqqtvgmEU7xWzhgndXXxnhk4Z3fQ==}
+ '@next/swc-darwin-arm64@16.1.6':
+ resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@16.1.0':
- resolution: {integrity: sha512-Am6VJTp8KhLuAH13tPrAoVIXzuComlZlMwGr++o2KDjWiKPe3VwpxYhgV6I4gKls2EnsIMggL4y7GdXyDdJcFA==}
+ '@next/swc-darwin-x64@16.1.6':
+ resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@16.1.0':
- resolution: {integrity: sha512-fVicfaJT6QfghNyg8JErZ+EMNQ812IS0lmKfbmC01LF1nFBcKfcs4Q75Yy8IqnsCqH/hZwGhqzj3IGVfWV6vpA==}
+ '@next/swc-linux-arm64-gnu@16.1.6':
+ resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@16.1.0':
- resolution: {integrity: sha512-TojQnDRoX7wJWXEEwdfuJtakMDW64Q7NrxQPviUnfYJvAx5/5wcGE+1vZzQ9F17m+SdpFeeXuOr6v3jbyusYMQ==}
+ '@next/swc-linux-arm64-musl@16.1.6':
+ resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@16.1.0':
- resolution: {integrity: sha512-quhNFVySW4QwXiZkZ34SbfzNBm27vLrxZ2HwTfFFO1BBP0OY1+pI0nbyewKeq1FriqU+LZrob/cm26lwsiAi8Q==}
+ '@next/swc-linux-x64-gnu@16.1.6':
+ resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@16.1.0':
- resolution: {integrity: sha512-6JW0z2FZUK5iOVhUIWqE4RblAhUj1EwhZ/MwteGb//SpFTOHydnhbp3868gxalwea+mbOLWO6xgxj9wA9wNvNw==}
+ '@next/swc-linux-x64-musl@16.1.6':
+ resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@16.1.0':
- resolution: {integrity: sha512-+DK/akkAvvXn5RdYN84IOmLkSy87SCmpofJPdB8vbLmf01BzntPBSYXnMvnEEv/Vcf3HYJwt24QZ/s6sWAwOMQ==}
+ '@next/swc-win32-arm64-msvc@16.1.6':
+ resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.1.0':
- resolution: {integrity: sha512-Tr0j94MphimCCks+1rtYPzQFK+faJuhHWCegU9S9gDlgyOk8Y3kPmO64UcjyzZAlligeBtYZ/2bEyrKq0d2wqQ==}
+ '@next/swc-win32-x64-msvc@16.1.6':
+ resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -1973,58 +1976,58 @@ packages:
'@octokit/types@16.0.0':
resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==}
- '@oven/bun-darwin-aarch64@1.3.5':
- resolution: {integrity: sha512-8GvNtMo0NINM7Emk9cNAviCG3teEgr3BUX9be0+GD029zIagx2Sf54jMui1Eu1IpFm7nWHODuLEefGOQNaJ0gQ==}
+ '@oven/bun-darwin-aarch64@1.3.7':
+ resolution: {integrity: sha512-Mh78f4B+vNTOhFpI7RWHRWDqSKTnFXj/MauRx7I/GmNwEfw56sUx98gWRwXyF4lkW+9VNU+33wuw6E+M22W66w==}
cpu: [arm64]
os: [darwin]
- '@oven/bun-darwin-x64-baseline@1.3.5':
- resolution: {integrity: sha512-p5q3rJk48qhLuLBOFehVc+kqCE03YrswTc6NCxbwsxiwfySXwcAvpF2KWKF/ZZObvvR8hCCvqe1F81b2p5r2dg==}
+ '@oven/bun-darwin-x64-baseline@1.3.7':
+ resolution: {integrity: sha512-bUND1aQoTCfIL+idALT7FWtuX59ltOIRo954c7p/JkESbSIJ01jY06BSNVbkGk8RQM19v/7qiqZZqi4NyO4Utw==}
cpu: [x64]
os: [darwin]
- '@oven/bun-darwin-x64@1.3.5':
- resolution: {integrity: sha512-r33eHQOHAwkuiBJIwmkXIyqONQOQMnd1GMTpDzaxx9vf9+svby80LZO9Hcm1ns6KT/TBRFyODC/0loA7FAaffg==}
+ '@oven/bun-darwin-x64@1.3.7':
+ resolution: {integrity: sha512-dFfKdSVz6Ois5zjEJboUC7igcYAVd+c//ajotd0L6WUQAKQrHMVq/+6LjOj/0zjC6VPFNGWzeF8erymNo1y0Jw==}
cpu: [x64]
os: [darwin]
- '@oven/bun-linux-aarch64-musl@1.3.5':
- resolution: {integrity: sha512-HKBeUlJdNduRkzJKZ5DXM+pPqntfC50/Hu2X65jVX0Y7hu/6IC8RaUTqpr8FtCZqqmc9wDK0OTL+Mbi9UQIKYQ==}
+ '@oven/bun-linux-aarch64-musl@1.3.7':
+ resolution: {integrity: sha512-QDxrROdUnC1d/uoilXtUeFHaLhYdRN7dRIzw/Iqj/vrrhnkA6VS+HYoCWtyyVvci/K+JrPmDwxOWlSRpmV4INA==}
cpu: [arm64]
os: [linux]
- '@oven/bun-linux-aarch64@1.3.5':
- resolution: {integrity: sha512-zkcHPI23QxJ1TdqafhgkXt1NOEN8o5C460sVeNnrhfJ43LwZgtfcvcQE39x/pBedu67fatY8CU0iY00nOh46ZQ==}
+ '@oven/bun-linux-aarch64@1.3.7':
+ resolution: {integrity: sha512-m03OtzEs+/RkWtk6tBf8yw0GW4P8ajfzTXnTt984tQBgkMubGQYUyUnFasWgr3mD2820LhkVjhYeBf1rkz/biQ==}
cpu: [arm64]
os: [linux]
- '@oven/bun-linux-x64-baseline@1.3.5':
- resolution: {integrity: sha512-FeCQyBU62DMuB0nn01vPnf3McXrKOsrK9p7sHaBFYycw0mmoU8kCq/WkBkGMnLuvQljJSyen8QBTx+fXdNupWg==}
+ '@oven/bun-linux-x64-baseline@1.3.7':
+ resolution: {integrity: sha512-Jlb/AcrIFU3QDeR3EL4UVT1CIKqnLJDgbU+R0k/+NaSWMrBEpZV+gJJT5L1cmEKTNhU/d+c7hudxkjtqA7XXqA==}
cpu: [x64]
os: [linux]
- '@oven/bun-linux-x64-musl-baseline@1.3.5':
- resolution: {integrity: sha512-TJiYC7KCr0XxFTsxgwQOeE7dncrEL/RSyL0EzSL3xRkrxJMWBCvCSjQn7LV1i6T7hFst0+3KoN3VWvD5BinqHA==}
+ '@oven/bun-linux-x64-musl-baseline@1.3.7':
+ resolution: {integrity: sha512-lySQQ7zJJsoa5hQH+PE5bQyQaTI8G2Erszhu4iQuDtsocwy3zSxjB6TxGWTd4HmetPl9aRvg3nb2KR8RVAd7ug==}
cpu: [x64]
os: [linux]
- '@oven/bun-linux-x64-musl@1.3.5':
- resolution: {integrity: sha512-XkCCHkByYn8BIDvoxnny898znju4xnW2kvFE8FT5+0Y62cWdcBGMZ9RdsEUTeRz16k8hHtJpaSfLcEmNTFIwRQ==}
+ '@oven/bun-linux-x64-musl@1.3.7':
+ resolution: {integrity: sha512-aK8fvkCosrHRG3CNdVqMom1C8Rj3XkqZp0ZFSBXgaXlKP22RkxlEE9tS7OmSq9yVgEk6euTB3dW4NFo/jlXqeg==}
cpu: [x64]
os: [linux]
- '@oven/bun-linux-x64@1.3.5':
- resolution: {integrity: sha512-n7zhKTSDZS0yOYg5Rq8easZu5Y/o47sv0c7yGr2ciFdcie9uYV55fZ7QMqhWMGK33ezCSikh5EDkUMCIvfWpjA==}
+ '@oven/bun-linux-x64@1.3.7':
+ resolution: {integrity: sha512-uttKQ/eIRVGc4uBtLRqmQqXGf57/dmQaF0AEd37RQNRRRd1P/VYnFMiMcVaot3HJ6IFjHjGtcPO9ekT49LxBYQ==}
cpu: [x64]
os: [linux]
- '@oven/bun-windows-x64-baseline@1.3.5':
- resolution: {integrity: sha512-rtVQB9/1XK8FWJgFtsOthbPifRMYypgJwxu+pK3NHx8WvFKmq7HcPDqNr8xLzGULjQEO7eAo2aOZfONOwYz+5g==}
+ '@oven/bun-windows-x64-baseline@1.3.7':
+ resolution: {integrity: sha512-wMgELfW5vFceh4qEOYb5iV5TjrjjnBJzE383ixA3kqGKzaubksSxNc11eZhS0ptcJ5a0UjN5hfbMh6sYoh+cRQ==}
cpu: [x64]
os: [win32]
- '@oven/bun-windows-x64@1.3.5':
- resolution: {integrity: sha512-T3xkODItb/0ftQPFsZDc7EAX2D6A4TEazQ2YZyofZToO8Q7y8YT8ooWdhd0BQiTCd66uEvgE1DCZetynwg2IoA==}
+ '@oven/bun-windows-x64@1.3.7':
+ resolution: {integrity: sha512-3QdIGdSn3fkssCq/vPjtPLAQxo+eMUzcwJedn1c5mXDy1AoisjhoxhWnbVl8+uk+wt9N6JUPdISoe0N4OdwXfg==}
cpu: [x64]
os: [win32]
@@ -2049,6 +2052,12 @@ packages:
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@parcel/watcher-darwin-arm64@2.5.6':
+ resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
+ engines: {node: '>= 10.0.0'}
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.0':
@@ -2060,6 +2069,12 @@ packages:
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@parcel/watcher-darwin-x64@2.5.6':
+ resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
+ engines: {node: '>= 10.0.0'}
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.0':
@@ -2107,6 +2122,12 @@ packages:
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6':
+ resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
+ engines: {node: '>= 10.0.0'}
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.0':
@@ -2118,6 +2139,12 @@ packages:
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6':
+ resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
+ engines: {node: '>= 10.0.0'}
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.0':
@@ -2129,6 +2156,12 @@ packages:
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6':
+ resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
+ engines: {node: '>= 10.0.0'}
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.0':
@@ -2140,6 +2173,12 @@ packages:
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-musl@2.5.6':
+ resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
+ engines: {node: '>= 10.0.0'}
os: [linux]
'@parcel/watcher-wasm@2.5.0':
@@ -2181,6 +2220,12 @@ packages:
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@parcel/watcher-win32-x64@2.5.6':
+ resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
+ engines: {node: '>= 10.0.0'}
os: [win32]
'@parcel/watcher@2.5.0':
@@ -2195,8 +2240,8 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@playwright/test@1.57.0':
- resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==}
+ '@playwright/test@1.58.0':
+ resolution: {integrity: sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==}
engines: {node: '>=18'}
hasBin: true
@@ -2349,8 +2394,8 @@ packages:
'@types/braces@3.0.5':
resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==}
- '@types/bun@1.3.5':
- resolution: {integrity: sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==}
+ '@types/bun@1.3.7':
+ resolution: {integrity: sha512-lmNuMda+Z9b7tmhA0tohwy8ZWFSnmQm1UDWXtH5r9F7wZCfkeO3Jx7wKQ1EOiKq43yHts7ky6r8SDJQWRNupkA==}
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
@@ -2373,9 +2418,6 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
- '@types/node@20.14.13':
- resolution: {integrity: sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==}
-
'@types/node@20.19.1':
resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==}
@@ -2387,8 +2429,8 @@ packages:
peerDependencies:
'@types/react': ^19.2.0
- '@types/react@19.2.7':
- resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
+ '@types/react@19.2.10':
+ resolution: {integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==}
'@types/semver@7.7.1':
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==}
@@ -2458,11 +2500,11 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
- '@vitest/expect@4.0.12':
- resolution: {integrity: sha512-is+g0w8V3/ZhRNrRizrJNr8PFQKwYmctWlU4qg8zy5r9aIV5w8IxXLlfbbxJCwSpsVl2PXPTm2/zruqTqz3QSg==}
+ '@vitest/expect@4.0.18':
+ resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==}
- '@vitest/mocker@4.0.12':
- resolution: {integrity: sha512-GsmA/tD5Ht3RUFoz41mZsMU1AXch3lhmgbTnoSPTdH231g7S3ytNN1aU0bZDSyxWs8WA7KDyMPD5L4q6V6vj9w==}
+ '@vitest/mocker@4.0.18':
+ resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==}
peerDependencies:
msw: ^2.4.9
vite: ^6.0.0 || ^7.0.0-0
@@ -2472,20 +2514,20 @@ packages:
vite:
optional: true
- '@vitest/pretty-format@4.0.12':
- resolution: {integrity: sha512-R7nMAcnienG17MvRN8TPMJiCG8rrZJblV9mhT7oMFdBXvS0x+QD6S1G4DxFusR2E0QIS73f7DqSR1n87rrmE+g==}
+ '@vitest/pretty-format@4.0.18':
+ resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==}
- '@vitest/runner@4.0.12':
- resolution: {integrity: sha512-hDlCIJWuwlcLumfukPsNfPDOJokTv79hnOlf11V+n7E14rHNPz0Sp/BO6h8sh9qw4/UjZiKyYpVxK2ZNi+3ceQ==}
+ '@vitest/runner@4.0.18':
+ resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==}
- '@vitest/snapshot@4.0.12':
- resolution: {integrity: sha512-2jz9zAuBDUSbnfyixnyOd1S2YDBrZO23rt1bicAb6MA/ya5rHdKFRikPIDpBj/Dwvh6cbImDmudegnDAkHvmRQ==}
+ '@vitest/snapshot@4.0.18':
+ resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==}
- '@vitest/spy@4.0.12':
- resolution: {integrity: sha512-GZjI9PPhiOYNX8Nsyqdw7JQB+u0BptL5fSnXiottAUBHlcMzgADV58A7SLTXXQwcN1yZ6gfd1DH+2bqjuUlCzw==}
+ '@vitest/spy@4.0.18':
+ resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==}
- '@vitest/utils@4.0.12':
- resolution: {integrity: sha512-DVS/TLkLdvGvj1avRy0LSmKfrcI9MNFvNGN6ECjTUHWJdlcgPDOXhjMis5Dh7rBH62nAmSXnkPbE+DZ5YD75Rw==}
+ '@vitest/utils@4.0.18':
+ resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==}
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -2710,11 +2752,11 @@ packages:
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
- bun-types@1.3.5:
- resolution: {integrity: sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw==}
+ bun-types@1.3.7:
+ resolution: {integrity: sha512-qyschsA03Qz+gou+apt6HNl6HnI+sJJLL4wLDke4iugsE6584CMupOtTY1n+2YC9nGVrEKUlTs99jjRLKgWnjQ==}
- bun@1.3.5:
- resolution: {integrity: sha512-c1YHIGUfgvYPJmLug5QiLzNWlX2Dg7X/67JWu1Va+AmMXNXzC/KQn2lgQ7rD+n1u1UqDpJMowVGGxTNpbPydNw==}
+ bun@1.3.7:
+ resolution: {integrity: sha512-ha86NG8WiAXYR7eQw/9S+7V7Lo8KfD36XutWJNS1VndzaipWS0QIen5n3K9MT3PpP/sdGmmHjhkrU0sCM2lGGQ==}
os: [darwin, linux, win32]
hasBin: true
@@ -2748,9 +2790,6 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
- caniuse-lite@1.0.30001755:
- resolution: {integrity: sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==}
-
caniuse-lite@1.0.30001761:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
@@ -2913,10 +2952,6 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
- detect-libc@2.0.4:
- resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
- engines: {node: '>=8'}
-
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -2944,8 +2979,8 @@ packages:
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
- emnapi@1.7.1:
- resolution: {integrity: sha512-wlLK2xFq+T+rCBlY6+lPlFVDEyE93b7hSn9dMrfWBIcPf4ArwUvymvvMnN9M5WWuiryYQe9M+UJrkqw4trdyRA==}
+ emnapi@1.8.1:
+ resolution: {integrity: sha512-34i2BbgHx1LnEO4JCGQYo6h6s4e4KrdWtdTHfllBNLbXSHPmdIHplxKejfabsRK+ukNciqVdalB+fxMibqHdaQ==}
peerDependencies:
node-addon-api: '>= 6.1.0'
peerDependenciesMeta:
@@ -3026,8 +3061,8 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
- eslint-config-next@16.1.0:
- resolution: {integrity: sha512-RlPb8E2uO/Ix/w3kizxz6+6ogw99WqtNzTG0ArRZ5NEkIYcsfRb8U0j7aTG7NjRvcrsak5QtUSuxGNN2UcA58g==}
+ eslint-config-next@16.1.6:
+ resolution: {integrity: sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==}
peerDependencies:
eslint: '>=9.0.0'
typescript: '>=3.3.1'
@@ -3339,8 +3374,8 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
- h3@1.15.4:
- resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==}
+ h3@1.15.5:
+ resolution: {integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==}
has-bigints@1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
@@ -3633,67 +3668,74 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
- lightningcss-android-arm64@1.30.2:
- resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
+ lightningcss-android-arm64@1.31.1:
+ resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [android]
- lightningcss-darwin-arm64@1.30.2:
- resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
+ lightningcss-darwin-arm64@1.31.1:
+ resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
os: [darwin]
- lightningcss-darwin-x64@1.30.2:
- resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
+ lightningcss-darwin-x64@1.31.1:
+ resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
engines: {node: '>= 12.0.0'}
+ cpu: [x64]
os: [darwin]
- lightningcss-freebsd-x64@1.30.2:
- resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
+ lightningcss-freebsd-x64@1.31.1:
+ resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
- lightningcss-linux-arm-gnueabihf@1.30.2:
- resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
+ lightningcss-linux-arm-gnueabihf@1.31.1:
+ resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
- lightningcss-linux-arm64-gnu@1.30.2:
- resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
+ lightningcss-linux-arm64-gnu@1.31.1:
+ resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
os: [linux]
- lightningcss-linux-arm64-musl@1.30.2:
- resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
+ lightningcss-linux-arm64-musl@1.31.1:
+ resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
os: [linux]
- lightningcss-linux-x64-gnu@1.30.2:
- resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
+ lightningcss-linux-x64-gnu@1.31.1:
+ resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
+ cpu: [x64]
os: [linux]
- lightningcss-linux-x64-musl@1.30.2:
- resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
+ lightningcss-linux-x64-musl@1.31.1:
+ resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
+ cpu: [x64]
os: [linux]
- lightningcss-win32-arm64-msvc@1.30.2:
- resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
+ lightningcss-win32-arm64-msvc@1.31.1:
+ resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
- lightningcss-win32-x64-msvc@1.30.2:
- resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
+ lightningcss-win32-x64-msvc@1.31.1:
+ resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
engines: {node: '>= 12.0.0'}
+ cpu: [x64]
os: [win32]
- lightningcss@1.30.2:
- resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
+ lightningcss@1.31.1:
+ resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
engines: {node: '>= 12.0.0'}
lilconfig@2.1.0:
@@ -3816,19 +3858,14 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- nanoid@3.3.7:
- resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
- next@16.1.0:
- resolution: {integrity: sha512-Y+KbmDbefYtHDDQKLNrmzE/YYzG2msqo2VXhzh5yrJ54tx/6TmGdkR5+kP9ma7i7LwZpZMfoY3m/AoPPPKxtVw==}
+ next@16.1.6:
+ resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -3871,8 +3908,8 @@ packages:
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
- node-mock-http@1.0.2:
- resolution: {integrity: sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==}
+ node-mock-http@1.0.4:
+ resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
@@ -3921,6 +3958,9 @@ packages:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
+ obug@2.1.1:
+ resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+
onetime@6.0.0:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
@@ -4007,13 +4047,13 @@ packages:
pkg-types@1.3.0:
resolution: {integrity: sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==}
- playwright-core@1.57.0:
- resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==}
+ playwright-core@1.58.0:
+ resolution: {integrity: sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==}
engines: {node: '>=18'}
hasBin: true
- playwright@1.57.0:
- resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==}
+ playwright@1.58.0:
+ resolution: {integrity: sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==}
engines: {node: '>=18'}
hasBin: true
@@ -4094,14 +4134,6 @@ packages:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
- postcss@8.4.41:
- resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==}
- engines: {node: ^10 || ^12 || >=14}
-
- postcss@8.4.47:
- resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
- engines: {node: ^10 || ^12 || >=14}
-
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -4123,8 +4155,8 @@ packages:
vue-tsc:
optional: true
- prettier@3.6.2:
- resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
+ prettier@3.8.1:
+ resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
engines: {node: '>=14'}
hasBin: true
@@ -4144,10 +4176,10 @@ packages:
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
- react-dom@19.2.3:
- resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
+ react-dom@19.2.4:
+ resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
peerDependencies:
- react: ^19.2.3
+ react: ^19.2.4
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -4156,8 +4188,8 @@ packages:
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
engines: {node: '>=0.10.0'}
- react@19.2.3:
- resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
+ react@19.2.4:
+ resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
read-cache@1.0.0:
@@ -4469,6 +4501,10 @@ packages:
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+ tinyexec@1.0.2:
+ resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ engines: {node: '>=18'}
+
tinyglobby@0.2.14:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'}
@@ -4547,38 +4583,38 @@ packages:
engines: {node: '>=18.0.0'}
hasBin: true
- turbo-darwin-64@2.7.2:
- resolution: {integrity: sha512-dxY3X6ezcT5vm3coK6VGixbrhplbQMwgNsCsvZamS/+/6JiebqW9DKt4NwpgYXhDY2HdH00I7FWs3wkVuan4rA==}
+ turbo-darwin-64@2.7.6:
+ resolution: {integrity: sha512-bYu0qnWju2Ha3EbIkPCk1SMLT3sltKh1P/Jy5FER6BmH++H5z+T5MHh3W1Xoers9rk4N1VdKvog9FO1pxQyjhw==}
cpu: [x64]
os: [darwin]
- turbo-darwin-arm64@2.7.2:
- resolution: {integrity: sha512-1bXmuwPLqNFt3mzrtYcVx1sdJ8UYb124Bf48nIgcpMCGZy3kDhgxNv1503kmuK/37OGOZbsWSQFU4I08feIuSg==}
+ turbo-darwin-arm64@2.7.6:
+ resolution: {integrity: sha512-KCxTf3Y1hgNLYIWRLw8bwH8Zie9RyCGoxAlXYsCBI/YNqBSR+ZZK9KYzFxAqDaVaNvTwLFv3rJRGsXOFWg4+Uw==}
cpu: [arm64]
os: [darwin]
- turbo-linux-64@2.7.2:
- resolution: {integrity: sha512-kP+TiiMaiPugbRlv57VGLfcjFNsFbo8H64wMBCPV2270Or2TpDCBULMzZrvEsvWFjT3pBFvToYbdp8/Kw0jAQg==}
+ turbo-linux-64@2.7.6:
+ resolution: {integrity: sha512-vjoU8zIfNgvJR3cMitgw7inEoi6bmuVuFawDl5yKtxjAEhDktFdRBpGS3WojD4l3BklBbIK689ssXcGf21LxRA==}
cpu: [x64]
os: [linux]
- turbo-linux-arm64@2.7.2:
- resolution: {integrity: sha512-VDJwQ0+8zjAfbyY6boNaWfP6RIez4ypKHxwkuB6SrWbOSk+vxTyW5/hEjytTwK8w/TsbKVcMDyvpora8tEsRFw==}
+ turbo-linux-arm64@2.7.6:
+ resolution: {integrity: sha512-TcMpBvTqZf+1DptrVYLbZls7WY1UVNDTGaf0bo7/GCgWYv5eZHCVo4Td7kCJeDU4glbXg67REX0md0S0V6ghMg==}
cpu: [arm64]
os: [linux]
- turbo-windows-64@2.7.2:
- resolution: {integrity: sha512-rPjqQXVnI6A6oxgzNEE8DNb6Vdj2Wwyhfv3oDc+YM3U9P7CAcBIlKv/868mKl4vsBtz4ouWpTQNXG8vljgJO+w==}
+ turbo-windows-64@2.7.6:
+ resolution: {integrity: sha512-1/MhkYldiihjneY8QnnDMbAkHXn/udTWSVYS94EMlkE9AShozsLTTOT1gDOpX06EfEW5njP09suhMvxbvwuwpQ==}
cpu: [x64]
os: [win32]
- turbo-windows-arm64@2.7.2:
- resolution: {integrity: sha512-tcnHvBhO515OheIFWdxA+qUvZzNqqcHbLVFc1+n+TJ1rrp8prYicQtbtmsiKgMvr/54jb9jOabU62URAobnB7g==}
+ turbo-windows-arm64@2.7.6:
+ resolution: {integrity: sha512-0wDVnUJLFAWm4ZzOQFDkbyyUqaszorTGf3Rdc22IRIyJTTLd6ajqdb+cWD89UZ1RKr953+PZR1gqgWQY4PDuhA==}
cpu: [arm64]
os: [win32]
- turbo@2.7.2:
- resolution: {integrity: sha512-5JIA5aYBAJSAhrhbyag1ZuMSgUZnHtI+Sq3H8D3an4fL8PeF+L1yYvbEJg47akP1PFfATMf5ehkqFnxfkmuwZQ==}
+ turbo@2.7.6:
+ resolution: {integrity: sha512-PO9AvJLEsNLO+EYhF4zB+v10hOjsJe5kJW+S6tTbRv+TW7gf1Qer4mfjP9h3/y9h8ZiPvOrenxnEgDtFgaM5zw==}
hasBin: true
typanion@3.14.0:
@@ -4620,8 +4656,8 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- typescript@5.6.3:
- resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
@@ -4631,6 +4667,9 @@ packages:
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
+ ufo@1.6.3:
+ resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
+
unbox-primitive@1.1.0:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
@@ -4638,9 +4677,6 @@ packages:
uncrypto@0.1.3:
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
- undici-types@5.26.5:
- resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
-
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
@@ -4716,19 +4752,58 @@ packages:
yaml:
optional: true
- vitest@4.0.12:
- resolution: {integrity: sha512-pmW4GCKQ8t5Ko1jYjC3SqOr7TUKN7uHOHB/XGsAIb69eYu6d1ionGSsb5H9chmPf+WeXt0VE7jTXsB1IvWoNbw==}
+ vite@7.3.1:
+ resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@4.0.18:
+ resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@opentelemetry/api': ^1.9.0
- '@types/debug': ^4.1.12
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 4.0.12
- '@vitest/browser-preview': 4.0.12
- '@vitest/browser-webdriverio': 4.0.12
- '@vitest/ui': 4.0.12
+ '@vitest/browser-playwright': 4.0.18
+ '@vitest/browser-preview': 4.0.18
+ '@vitest/browser-webdriverio': 4.0.18
+ '@vitest/ui': 4.0.18
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -4736,8 +4811,6 @@ packages:
optional: true
'@opentelemetry/api':
optional: true
- '@types/debug':
- optional: true
'@types/node':
optional: true
'@vitest/browser-playwright':
@@ -4959,10 +5032,19 @@ snapshots:
'@emnapi/wasi-threads': 1.1.0
tslib: 2.8.1
+ '@emnapi/core@1.8.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+
'@emnapi/runtime@1.7.1':
dependencies:
tslib: 2.8.1
+ '@emnapi/runtime@1.8.1':
+ dependencies:
+ tslib: 2.8.1
+
'@emnapi/wasi-threads@1.1.0':
dependencies:
tslib: 2.8.1
@@ -5336,7 +5418,7 @@ snapshots:
'@img/sharp-wasm32@0.34.5':
dependencies:
- '@emnapi/runtime': 1.7.1
+ '@emnapi/runtime': 1.8.1
optional: true
'@img/sharp-win32-arm64@0.34.5':
@@ -5484,7 +5566,7 @@ snapshots:
'@jridgewell/gen-mapping@0.3.12':
dependencies:
- '@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.29
'@jridgewell/gen-mapping@0.3.5':
@@ -5507,8 +5589,6 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.12
'@jridgewell/trace-mapping': 0.3.29
- '@jridgewell/sourcemap-codec@1.5.0': {}
-
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.25':
@@ -5519,9 +5599,9 @@ snapshots:
'@jridgewell/trace-mapping@0.3.29':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/sourcemap-codec': 1.5.5
- '@napi-rs/cli@3.4.1(@emnapi/runtime@1.7.1)(@types/node@20.19.1)(node-addon-api@8.3.0)':
+ '@napi-rs/cli@3.4.1(@emnapi/runtime@1.8.1)(@types/node@20.19.1)(node-addon-api@8.3.0)':
dependencies:
'@inquirer/prompts': 7.10.1(@types/node@20.19.1)
'@napi-rs/cross-toolchain': 1.0.3
@@ -5530,13 +5610,13 @@ snapshots:
clipanion: 4.0.0-rc.4(typanion@3.14.0)
colorette: 2.0.20
debug: 4.4.3
- emnapi: 1.7.1(node-addon-api@8.3.0)
+ emnapi: 1.8.1(node-addon-api@8.3.0)
es-toolkit: 1.43.0
js-yaml: 4.1.0
semver: 7.7.3
typanion: 3.14.0
optionalDependencies:
- '@emnapi/runtime': 1.7.1
+ '@emnapi/runtime': 1.8.1
transitivePeerDependencies:
- '@napi-rs/cross-toolchain-arm64-target-aarch64'
- '@napi-rs/cross-toolchain-arm64-target-armv7'
@@ -5765,34 +5845,34 @@ snapshots:
'@napi-rs/wasm-tools-win32-ia32-msvc': 1.0.1
'@napi-rs/wasm-tools-win32-x64-msvc': 1.0.1
- '@next/env@16.1.0': {}
+ '@next/env@16.1.6': {}
- '@next/eslint-plugin-next@16.1.0':
+ '@next/eslint-plugin-next@16.1.6':
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@16.1.0':
+ '@next/swc-darwin-arm64@16.1.6':
optional: true
- '@next/swc-darwin-x64@16.1.0':
+ '@next/swc-darwin-x64@16.1.6':
optional: true
- '@next/swc-linux-arm64-gnu@16.1.0':
+ '@next/swc-linux-arm64-gnu@16.1.6':
optional: true
- '@next/swc-linux-arm64-musl@16.1.0':
+ '@next/swc-linux-arm64-musl@16.1.6':
optional: true
- '@next/swc-linux-x64-gnu@16.1.0':
+ '@next/swc-linux-x64-gnu@16.1.6':
optional: true
- '@next/swc-linux-x64-musl@16.1.0':
+ '@next/swc-linux-x64-musl@16.1.6':
optional: true
- '@next/swc-win32-arm64-msvc@16.1.0':
+ '@next/swc-win32-arm64-msvc@16.1.6':
optional: true
- '@next/swc-win32-x64-msvc@16.1.0':
+ '@next/swc-win32-x64-msvc@16.1.6':
optional: true
'@nodelib/fs.scandir@2.1.5':
@@ -5871,37 +5951,37 @@ snapshots:
dependencies:
'@octokit/openapi-types': 27.0.0
- '@oven/bun-darwin-aarch64@1.3.5':
+ '@oven/bun-darwin-aarch64@1.3.7':
optional: true
- '@oven/bun-darwin-x64-baseline@1.3.5':
+ '@oven/bun-darwin-x64-baseline@1.3.7':
optional: true
- '@oven/bun-darwin-x64@1.3.5':
+ '@oven/bun-darwin-x64@1.3.7':
optional: true
- '@oven/bun-linux-aarch64-musl@1.3.5':
+ '@oven/bun-linux-aarch64-musl@1.3.7':
optional: true
- '@oven/bun-linux-aarch64@1.3.5':
+ '@oven/bun-linux-aarch64@1.3.7':
optional: true
- '@oven/bun-linux-x64-baseline@1.3.5':
+ '@oven/bun-linux-x64-baseline@1.3.7':
optional: true
- '@oven/bun-linux-x64-musl-baseline@1.3.5':
+ '@oven/bun-linux-x64-musl-baseline@1.3.7':
optional: true
- '@oven/bun-linux-x64-musl@1.3.5':
+ '@oven/bun-linux-x64-musl@1.3.7':
optional: true
- '@oven/bun-linux-x64@1.3.5':
+ '@oven/bun-linux-x64@1.3.7':
optional: true
- '@oven/bun-windows-x64-baseline@1.3.5':
+ '@oven/bun-windows-x64-baseline@1.3.7':
optional: true
- '@oven/bun-windows-x64@1.3.5':
+ '@oven/bun-windows-x64@1.3.7':
optional: true
'@parcel/watcher-android-arm64@2.5.0':
@@ -5913,12 +5993,18 @@ snapshots:
'@parcel/watcher-darwin-arm64@2.5.0':
optional: true
- '@parcel/watcher-darwin-arm64@2.5.1': {}
+ '@parcel/watcher-darwin-arm64@2.5.1':
+ optional: true
+
+ '@parcel/watcher-darwin-arm64@2.5.6': {}
'@parcel/watcher-darwin-x64@2.5.0':
optional: true
- '@parcel/watcher-darwin-x64@2.5.1': {}
+ '@parcel/watcher-darwin-x64@2.5.1':
+ optional: true
+
+ '@parcel/watcher-darwin-x64@2.5.6': {}
'@parcel/watcher-freebsd-x64@2.5.0':
optional: true
@@ -5941,22 +6027,34 @@ snapshots:
'@parcel/watcher-linux-arm64-glibc@2.5.0':
optional: true
- '@parcel/watcher-linux-arm64-glibc@2.5.1': {}
+ '@parcel/watcher-linux-arm64-glibc@2.5.1':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6': {}
'@parcel/watcher-linux-arm64-musl@2.5.0':
optional: true
- '@parcel/watcher-linux-arm64-musl@2.5.1': {}
+ '@parcel/watcher-linux-arm64-musl@2.5.1':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6': {}
'@parcel/watcher-linux-x64-glibc@2.5.0':
optional: true
- '@parcel/watcher-linux-x64-glibc@2.5.1': {}
+ '@parcel/watcher-linux-x64-glibc@2.5.1':
+ optional: true
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6': {}
'@parcel/watcher-linux-x64-musl@2.5.0':
optional: true
- '@parcel/watcher-linux-x64-musl@2.5.1': {}
+ '@parcel/watcher-linux-x64-musl@2.5.1':
+ optional: true
+
+ '@parcel/watcher-linux-x64-musl@2.5.6': {}
'@parcel/watcher-wasm@2.5.0':
dependencies:
@@ -5978,7 +6076,10 @@ snapshots:
'@parcel/watcher-win32-x64@2.5.0':
optional: true
- '@parcel/watcher-win32-x64@2.5.1': {}
+ '@parcel/watcher-win32-x64@2.5.1':
+ optional: true
+
+ '@parcel/watcher-win32-x64@2.5.6': {}
'@parcel/watcher@2.5.0':
dependencies:
@@ -6025,9 +6126,9 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
- '@playwright/test@1.57.0':
+ '@playwright/test@1.58.0':
dependencies:
- playwright: 1.57.0
+ playwright: 1.58.0
'@rolldown/pluginutils@1.0.0-beta.53': {}
@@ -6142,9 +6243,9 @@ snapshots:
'@types/braces@3.0.5': {}
- '@types/bun@1.3.5':
+ '@types/bun@1.3.7':
dependencies:
- bun-types: 1.3.5
+ bun-types: 1.3.7
'@types/chai@5.2.3':
dependencies:
@@ -6169,101 +6270,59 @@ snapshots:
'@types/json5@0.0.29': {}
- '@types/node@20.14.13':
- dependencies:
- undici-types: 5.26.5
-
'@types/node@20.19.1':
dependencies:
undici-types: 6.21.0
'@types/postcss-import@14.0.3':
dependencies:
- postcss: 8.4.41
+ postcss: 8.5.6
- '@types/react-dom@19.2.3(@types/react@19.2.7)':
+ '@types/react-dom@19.2.3(@types/react@19.2.10)':
dependencies:
- '@types/react': 19.2.7
+ '@types/react': 19.2.10
- '@types/react@19.2.7':
+ '@types/react@19.2.10':
dependencies:
csstype: 3.2.3
'@types/semver@7.7.1': {}
- '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)':
- dependencies:
- '@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- '@typescript-eslint/scope-manager': 8.47.0
- '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- '@typescript-eslint/visitor-keys': 8.47.0
- eslint: 9.39.2(jiti@2.6.1)
- graphemer: 1.4.0
- ignore: 7.0.5
- natural-compare: 1.4.0
- ts-api-utils: 2.1.0(typescript@5.5.4)
- typescript: 5.5.4
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)':
+ '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.47.0
- '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
+ '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.47.0
eslint: 9.39.2(jiti@2.6.1)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
- ts-api-utils: 2.1.0(typescript@5.6.3)
- typescript: 5.6.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.47.0
- '@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.5.4)
- '@typescript-eslint/visitor-keys': 8.47.0
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.5.4
+ ts-api-utils: 2.1.0(typescript@5.9.3)
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)':
+ '@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.47.0
'@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.6.3)
+ '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.47.0
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.6.3
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.47.0(typescript@5.5.4)':
+ '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.5.4)
+ '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3)
'@typescript-eslint/types': 8.47.0
debug: 4.4.3
- typescript: 5.5.4
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/project-service@8.47.0(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.6.3)
- '@typescript-eslint/types': 8.47.0
- debug: 4.4.3
- typescript: 5.6.3
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -6272,44 +6331,28 @@ snapshots:
'@typescript-eslint/types': 8.47.0
'@typescript-eslint/visitor-keys': 8.47.0
- '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.5.4)':
- dependencies:
- typescript: 5.5.4
-
- '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.6.3)':
+ '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)':
dependencies:
- typescript: 5.6.3
+ typescript: 5.9.3
- '@typescript-eslint/type-utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)':
+ '@typescript-eslint/type-utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.5.4)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
+ '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
- ts-api-utils: 2.1.0(typescript@5.5.4)
- typescript: 5.5.4
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/type-utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.6.3)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- ts-api-utils: 2.1.0(typescript@5.6.3)
- typescript: 5.6.3
+ ts-api-utils: 2.1.0(typescript@5.9.3)
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.47.0': {}
- '@typescript-eslint/typescript-estree@8.47.0(typescript@5.5.4)':
+ '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/project-service': 8.47.0(typescript@5.5.4)
- '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.5.4)
+ '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3)
'@typescript-eslint/types': 8.47.0
'@typescript-eslint/visitor-keys': 8.47.0
debug: 4.4.3
@@ -6317,46 +6360,19 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.3
- ts-api-utils: 2.1.0(typescript@5.5.4)
- typescript: 5.5.4
+ ts-api-utils: 2.1.0(typescript@5.9.3)
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.47.0(typescript@5.6.3)':
- dependencies:
- '@typescript-eslint/project-service': 8.47.0(typescript@5.6.3)
- '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.6.3)
- '@typescript-eslint/types': 8.47.0
- '@typescript-eslint/visitor-keys': 8.47.0
- debug: 4.4.3
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.7.3
- ts-api-utils: 2.1.0(typescript@5.6.3)
- typescript: 5.6.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)':
+ '@typescript-eslint/utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.47.0
'@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.5.4)
+ '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.5.4
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.47.0
- '@typescript-eslint/types': 8.47.0
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.6.3)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.6.3
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -6365,7 +6381,7 @@ snapshots:
'@typescript-eslint/types': 8.47.0
eslint-visitor-keys: 4.2.1
- '@vitejs/plugin-react@5.1.2(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
+ '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
@@ -6373,47 +6389,47 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.53
'@types/babel__core': 7.20.5
react-refresh: 0.18.0
- vite: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ vite: 7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
transitivePeerDependencies:
- supports-color
- '@vitest/expect@4.0.12':
+ '@vitest/expect@4.0.18':
dependencies:
'@standard-schema/spec': 1.0.0
'@types/chai': 5.2.3
- '@vitest/spy': 4.0.12
- '@vitest/utils': 4.0.12
+ '@vitest/spy': 4.0.18
+ '@vitest/utils': 4.0.18
chai: 6.2.1
tinyrainbow: 3.0.3
- '@vitest/mocker@4.0.12(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
+ '@vitest/mocker@4.0.18(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
dependencies:
- '@vitest/spy': 4.0.12
+ '@vitest/spy': 4.0.18
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ vite: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
- '@vitest/pretty-format@4.0.12':
+ '@vitest/pretty-format@4.0.18':
dependencies:
tinyrainbow: 3.0.3
- '@vitest/runner@4.0.12':
+ '@vitest/runner@4.0.18':
dependencies:
- '@vitest/utils': 4.0.12
+ '@vitest/utils': 4.0.18
pathe: 2.0.3
- '@vitest/snapshot@4.0.12':
+ '@vitest/snapshot@4.0.18':
dependencies:
- '@vitest/pretty-format': 4.0.12
+ '@vitest/pretty-format': 4.0.18
magic-string: 0.30.21
pathe: 2.0.3
- '@vitest/spy@4.0.12': {}
+ '@vitest/spy@4.0.18': {}
- '@vitest/utils@4.0.12':
+ '@vitest/utils@4.0.18':
dependencies:
- '@vitest/pretty-format': 4.0.12
+ '@vitest/pretty-format': 4.0.18
tinyrainbow: 3.0.3
'@webassemblyjs/ast@1.14.1':
@@ -6625,13 +6641,13 @@ snapshots:
ast-types-flow@0.0.8: {}
- autoprefixer@10.4.23(postcss@8.4.47):
+ autoprefixer@10.4.23(postcss@8.5.6):
dependencies:
browserslist: 4.28.1
caniuse-lite: 1.0.30001761
fraction.js: 5.3.4
picocolors: 1.1.1
- postcss: 8.4.47
+ postcss: 8.5.6
postcss-value-parser: 4.2.0
available-typed-arrays@1.0.7:
@@ -6683,23 +6699,23 @@ snapshots:
buffer-from@1.1.2: {}
- bun-types@1.3.5:
+ bun-types@1.3.7:
dependencies:
'@types/node': 20.19.1
- bun@1.3.5:
+ bun@1.3.7:
optionalDependencies:
- '@oven/bun-darwin-aarch64': 1.3.5
- '@oven/bun-darwin-x64': 1.3.5
- '@oven/bun-darwin-x64-baseline': 1.3.5
- '@oven/bun-linux-aarch64': 1.3.5
- '@oven/bun-linux-aarch64-musl': 1.3.5
- '@oven/bun-linux-x64': 1.3.5
- '@oven/bun-linux-x64-baseline': 1.3.5
- '@oven/bun-linux-x64-musl': 1.3.5
- '@oven/bun-linux-x64-musl-baseline': 1.3.5
- '@oven/bun-windows-x64': 1.3.5
- '@oven/bun-windows-x64-baseline': 1.3.5
+ '@oven/bun-darwin-aarch64': 1.3.7
+ '@oven/bun-darwin-x64': 1.3.7
+ '@oven/bun-darwin-x64-baseline': 1.3.7
+ '@oven/bun-linux-aarch64': 1.3.7
+ '@oven/bun-linux-aarch64-musl': 1.3.7
+ '@oven/bun-linux-x64': 1.3.7
+ '@oven/bun-linux-x64-baseline': 1.3.7
+ '@oven/bun-linux-x64-musl': 1.3.7
+ '@oven/bun-linux-x64-musl-baseline': 1.3.7
+ '@oven/bun-windows-x64': 1.3.7
+ '@oven/bun-windows-x64-baseline': 1.3.7
bundle-require@5.1.0(esbuild@0.27.0):
dependencies:
@@ -6729,8 +6745,6 @@ snapshots:
camelcase-css@2.0.1: {}
- caniuse-lite@1.0.30001755: {}
-
caniuse-lite@1.0.30001761: {}
chai@6.2.1: {}
@@ -6870,10 +6884,7 @@ snapshots:
detect-libc@1.0.3: {}
- detect-libc@2.0.4: {}
-
- detect-libc@2.1.2:
- optional: true
+ detect-libc@2.1.2: {}
didyoumean@1.2.2: {}
@@ -6895,7 +6906,7 @@ snapshots:
electron-to-chromium@1.5.267: {}
- emnapi@1.7.1(node-addon-api@8.3.0):
+ emnapi@1.8.1(node-addon-api@8.3.0):
optionalDependencies:
node-addon-api: 8.3.0
@@ -7102,29 +7113,29 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-config-next@16.1.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4):
+ eslint-config-next@16.1.6(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@next/eslint-plugin-next': 16.1.0
+ '@next/eslint-plugin-next': 16.1.6
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.1(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1))
globals: 16.4.0
- typescript-eslint: 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
+ typescript-eslint: 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
optionalDependencies:
- typescript: 5.5.4
+ typescript: 5.9.3
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-webpack
- eslint-plugin-import-x
- supports-color
- eslint-config-next@16.1.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3):
+ eslint-config-next@16.1.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@next/eslint-plugin-next': 16.1.0
+ '@next/eslint-plugin-next': 16.1.6
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.3(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
@@ -7133,9 +7144,9 @@ snapshots:
eslint-plugin-react: 7.37.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1))
globals: 16.4.0
- typescript-eslint: 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
+ typescript-eslint: 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
optionalDependencies:
- typescript: 5.6.3
+ typescript: 5.9.3
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-webpack
@@ -7150,19 +7161,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
enhanced-resolve: 5.18.4
eslint: 9.39.2(jiti@2.6.1)
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
fast-glob: 3.3.3
get-tsconfig: 4.10.0
is-bun-module: 1.2.1
is-glob: 4.0.3
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-node
@@ -7188,14 +7199,14 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
+ '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
@@ -7209,7 +7220,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -7220,7 +7231,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -7232,7 +7243,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
+ '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -7590,16 +7601,16 @@ snapshots:
graphemer@1.4.0: {}
- h3@1.15.4:
+ h3@1.15.5:
dependencies:
cookie-es: 1.2.2
crossws: 0.3.5
defu: 6.1.4
destr: 2.0.5
iron-webcrypto: 1.2.1
- node-mock-http: 1.0.2
+ node-mock-http: 1.0.4
radix3: 1.1.2
- ufo: 1.6.1
+ ufo: 1.6.3
uncrypto: 0.1.3
has-bigints@1.0.2: {}
@@ -7865,47 +7876,47 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
- lightningcss-android-arm64@1.30.2:
+ lightningcss-android-arm64@1.31.1:
optional: true
- lightningcss-darwin-arm64@1.30.2: {}
+ lightningcss-darwin-arm64@1.31.1: {}
- lightningcss-darwin-x64@1.30.2: {}
+ lightningcss-darwin-x64@1.31.1: {}
- lightningcss-freebsd-x64@1.30.2:
+ lightningcss-freebsd-x64@1.31.1:
optional: true
- lightningcss-linux-arm-gnueabihf@1.30.2:
+ lightningcss-linux-arm-gnueabihf@1.31.1:
optional: true
- lightningcss-linux-arm64-gnu@1.30.2: {}
+ lightningcss-linux-arm64-gnu@1.31.1: {}
- lightningcss-linux-arm64-musl@1.30.2: {}
+ lightningcss-linux-arm64-musl@1.31.1: {}
- lightningcss-linux-x64-gnu@1.30.2: {}
+ lightningcss-linux-x64-gnu@1.31.1: {}
- lightningcss-linux-x64-musl@1.30.2: {}
+ lightningcss-linux-x64-musl@1.31.1: {}
- lightningcss-win32-arm64-msvc@1.30.2:
+ lightningcss-win32-arm64-msvc@1.31.1:
optional: true
- lightningcss-win32-x64-msvc@1.30.2: {}
+ lightningcss-win32-x64-msvc@1.31.1: {}
- lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm):
+ lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm):
dependencies:
- detect-libc: 2.0.4
+ detect-libc: 2.1.2
optionalDependencies:
- lightningcss-android-arm64: 1.30.2
- lightningcss-darwin-arm64: 1.30.2
- lightningcss-darwin-x64: 1.30.2
- lightningcss-freebsd-x64: 1.30.2
- lightningcss-linux-arm-gnueabihf: 1.30.2
- lightningcss-linux-arm64-gnu: 1.30.2
- lightningcss-linux-arm64-musl: 1.30.2
- lightningcss-linux-x64-gnu: 1.30.2
- lightningcss-linux-x64-musl: 1.30.2
- lightningcss-win32-arm64-msvc: 1.30.2
- lightningcss-win32-x64-msvc: 1.30.2
+ lightningcss-android-arm64: 1.31.1
+ lightningcss-darwin-arm64: 1.31.1
+ lightningcss-darwin-x64: 1.31.1
+ lightningcss-freebsd-x64: 1.31.1
+ lightningcss-linux-arm-gnueabihf: 1.31.1
+ lightningcss-linux-arm64-gnu: 1.31.1
+ lightningcss-linux-arm64-musl: 1.31.1
+ lightningcss-linux-x64-gnu: 1.31.1
+ lightningcss-linux-x64-musl: 1.31.1
+ lightningcss-win32-arm64-msvc: 1.31.1
+ lightningcss-win32-x64-msvc: 1.31.1
lilconfig@2.1.0: {}
@@ -7923,7 +7934,7 @@ snapshots:
crossws: 0.3.1
defu: 6.1.4
get-port-please: 3.1.2
- h3: 1.15.4
+ h3: 1.15.5
http-shutdown: 1.2.2
jiti: 2.4.2
mlly: 1.7.3
@@ -8029,32 +8040,30 @@ snapshots:
nanoid@3.3.11: {}
- nanoid@3.3.7: {}
-
natural-compare@1.4.0: {}
neo-async@2.6.2: {}
- next@16.1.0(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ next@16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
- '@next/env': 16.1.0
+ '@next/env': 16.1.6
'@swc/helpers': 0.5.15
- baseline-browser-mapping: 2.8.29
- caniuse-lite: 1.0.30001755
+ baseline-browser-mapping: 2.9.11
+ caniuse-lite: 1.0.30001761
postcss: 8.4.31
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- styled-jsx: 5.1.6(react@19.2.3)
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ styled-jsx: 5.1.6(react@19.2.4)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.1.0
- '@next/swc-darwin-x64': 16.1.0
- '@next/swc-linux-arm64-gnu': 16.1.0
- '@next/swc-linux-arm64-musl': 16.1.0
- '@next/swc-linux-x64-gnu': 16.1.0
- '@next/swc-linux-x64-musl': 16.1.0
- '@next/swc-win32-arm64-msvc': 16.1.0
- '@next/swc-win32-x64-msvc': 16.1.0
- '@playwright/test': 1.57.0
+ '@next/swc-darwin-arm64': 16.1.6
+ '@next/swc-darwin-x64': 16.1.6
+ '@next/swc-linux-arm64-gnu': 16.1.6
+ '@next/swc-linux-arm64-musl': 16.1.6
+ '@next/swc-linux-x64-gnu': 16.1.6
+ '@next/swc-linux-x64-musl': 16.1.6
+ '@next/swc-win32-arm64-msvc': 16.1.6
+ '@next/swc-win32-x64-msvc': 16.1.6
+ '@playwright/test': 1.58.0
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
@@ -8072,7 +8081,7 @@ snapshots:
node-gyp-build@4.8.4: {}
- node-mock-http@1.0.2: {}
+ node-mock-http@1.0.4: {}
node-releases@2.0.27: {}
@@ -8125,6 +8134,8 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
+ obug@2.1.1: {}
+
onetime@6.0.0:
dependencies:
mimic-fn: 4.0.0
@@ -8199,26 +8210,19 @@ snapshots:
mlly: 1.7.3
pathe: 1.1.2
- playwright-core@1.57.0: {}
+ playwright-core@1.58.0: {}
- playwright@1.57.0:
+ playwright@1.58.0:
dependencies:
- playwright-core: 1.57.0
+ playwright-core: 1.58.0
optionalDependencies:
fsevents: 2.3.2
possible-typed-array-names@1.0.0: {}
- postcss-import@15.1.0(postcss@8.4.47):
+ postcss-import@15.1.0(postcss@8.5.6):
dependencies:
- postcss: 8.4.47
- postcss-value-parser: 4.2.0
- read-cache: 1.0.0
- resolve: 1.22.8
-
- postcss-import@16.1.1(postcss@8.4.41):
- dependencies:
- postcss: 8.4.41
+ postcss: 8.5.6
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.8
@@ -8230,17 +8234,17 @@ snapshots:
read-cache: 1.0.0
resolve: 1.22.8
- postcss-js@4.0.1(postcss@8.4.47):
+ postcss-js@4.0.1(postcss@8.5.6):
dependencies:
camelcase-css: 2.0.1
- postcss: 8.4.47
+ postcss: 8.5.6
- postcss-load-config@4.0.2(postcss@8.4.47):
+ postcss-load-config@4.0.2(postcss@8.5.6):
dependencies:
lilconfig: 3.1.2
yaml: 2.6.0
optionalDependencies:
- postcss: 8.4.47
+ postcss: 8.5.6
postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.19.1)(yaml@2.6.0):
dependencies:
@@ -8251,9 +8255,9 @@ snapshots:
tsx: 4.19.1
yaml: 2.6.0
- postcss-nested@6.2.0(postcss@8.4.47):
+ postcss-nested@6.2.0(postcss@8.5.6):
dependencies:
- postcss: 8.4.47
+ postcss: 8.5.6
postcss-selector-parser: 6.1.2
postcss-selector-parser@6.0.10:
@@ -8279,18 +8283,6 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
- postcss@8.4.41:
- dependencies:
- nanoid: 3.3.7
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- postcss@8.4.47:
- dependencies:
- nanoid: 3.3.7
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
postcss@8.5.6:
dependencies:
nanoid: 3.3.11
@@ -8310,12 +8302,12 @@ snapshots:
transitivePeerDependencies:
- babel-plugin-macros
- prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.5.4):
+ prettier-plugin-organize-imports@4.3.0(prettier@3.8.1)(typescript@5.5.4):
dependencies:
- prettier: 3.6.2
+ prettier: 3.8.1
typescript: 5.5.4
- prettier@3.6.2: {}
+ prettier@3.8.1: {}
prop-types@15.8.1:
dependencies:
@@ -8333,16 +8325,16 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
- react-dom@19.2.3(react@19.2.3):
+ react-dom@19.2.4(react@19.2.4):
dependencies:
- react: 19.2.3
+ react: 19.2.4
scheduler: 0.27.0
react-is@16.13.1: {}
react-refresh@0.18.0: {}
- react@19.2.3: {}
+ react@19.2.4: {}
read-cache@1.0.0:
dependencies:
@@ -8657,10 +8649,10 @@ snapshots:
strip-json-comments@3.1.1: {}
- styled-jsx@5.1.6(react@19.2.3):
+ styled-jsx@5.1.6(react@19.2.4):
dependencies:
client-only: 0.0.1
- react: 19.2.3
+ react: 19.2.4
sucrase@3.35.0:
dependencies:
@@ -8702,11 +8694,11 @@ snapshots:
normalize-path: 3.0.0
object-hash: 3.0.0
picocolors: 1.1.1
- postcss: 8.4.47
- postcss-import: 15.1.0(postcss@8.4.47)
- postcss-js: 4.0.1(postcss@8.4.47)
- postcss-load-config: 4.0.2(postcss@8.4.47)
- postcss-nested: 6.2.0(postcss@8.4.47)
+ postcss: 8.5.6
+ postcss-import: 15.1.0(postcss@8.5.6)
+ postcss-js: 4.0.1(postcss@8.5.6)
+ postcss-load-config: 4.0.2(postcss@8.5.6)
+ postcss-nested: 6.2.0(postcss@8.5.6)
postcss-selector-parser: 6.1.2
resolve: 1.22.8
sucrase: 3.35.0
@@ -8749,6 +8741,8 @@ snapshots:
tinyexec@0.3.2: {}
+ tinyexec@1.0.2: {}
+
tinyglobby@0.2.14:
dependencies:
fdir: 6.4.6(picomatch@4.0.2)
@@ -8787,13 +8781,9 @@ snapshots:
node-addon-api: 8.3.0
node-gyp-build: 4.8.4
- ts-api-utils@2.1.0(typescript@5.5.4):
+ ts-api-utils@2.1.0(typescript@5.9.3):
dependencies:
- typescript: 5.5.4
-
- ts-api-utils@2.1.0(typescript@5.6.3):
- dependencies:
- typescript: 5.6.3
+ typescript: 5.9.3
ts-interface-checker@0.1.13: {}
@@ -8842,32 +8832,32 @@ snapshots:
fsevents: 2.3.3
optional: true
- turbo-darwin-64@2.7.2:
+ turbo-darwin-64@2.7.6:
optional: true
- turbo-darwin-arm64@2.7.2:
+ turbo-darwin-arm64@2.7.6:
optional: true
- turbo-linux-64@2.7.2:
+ turbo-linux-64@2.7.6:
optional: true
- turbo-linux-arm64@2.7.2:
+ turbo-linux-arm64@2.7.6:
optional: true
- turbo-windows-64@2.7.2:
+ turbo-windows-64@2.7.6:
optional: true
- turbo-windows-arm64@2.7.2:
+ turbo-windows-arm64@2.7.6:
optional: true
- turbo@2.7.2:
+ turbo@2.7.6:
optionalDependencies:
- turbo-darwin-64: 2.7.2
- turbo-darwin-arm64: 2.7.2
- turbo-linux-64: 2.7.2
- turbo-linux-arm64: 2.7.2
- turbo-windows-64: 2.7.2
- turbo-windows-arm64: 2.7.2
+ turbo-darwin-64: 2.7.6
+ turbo-darwin-arm64: 2.7.6
+ turbo-linux-64: 2.7.6
+ turbo-linux-arm64: 2.7.6
+ turbo-windows-64: 2.7.6
+ turbo-windows-arm64: 2.7.6
typanion@3.14.0: {}
@@ -8912,36 +8902,27 @@ snapshots:
possible-typed-array-names: 1.0.0
reflect.getprototypeof: 1.0.10
- typescript-eslint@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4))(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.5.4)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.5.4)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.5.4
- transitivePeerDependencies:
- - supports-color
-
- typescript-eslint@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3):
+ typescript-eslint@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
- '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
- '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.6.3)
- '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.6.3)
+ '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.6.3
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
typescript@5.5.4: {}
- typescript@5.6.3: {}
+ typescript@5.9.3: {}
ufo@1.5.4: {}
ufo@1.6.1: {}
+ ufo@1.6.3: {}
+
unbox-primitive@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -8951,8 +8932,6 @@ snapshots:
uncrypto@0.1.3: {}
- undici-types@5.26.5: {}
-
undici-types@6.21.0: {}
unicorn-magic@0.3.0: {}
@@ -8985,44 +8964,61 @@ snapshots:
util-deprecate@1.0.2: {}
- vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0):
+ vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0):
dependencies:
esbuild: 0.25.0
- fdir: 6.4.6(picomatch@4.0.2)
- picomatch: 4.0.2
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
postcss: 8.5.6
rollup: 4.44.0
- tinyglobby: 0.2.14
+ tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 20.19.1
fsevents: 2.3.3
jiti: 2.6.1
- lightningcss: 1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
+ lightningcss: 1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
terser: 5.31.6
tsx: 4.19.1
yaml: 2.6.0
- vitest@4.0.12(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0):
+ vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0):
dependencies:
- '@vitest/expect': 4.0.12
- '@vitest/mocker': 4.0.12(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
- '@vitest/pretty-format': 4.0.12
- '@vitest/runner': 4.0.12
- '@vitest/snapshot': 4.0.12
- '@vitest/spy': 4.0.12
- '@vitest/utils': 4.0.12
- debug: 4.4.3
+ esbuild: 0.27.0
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.44.0
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 20.19.1
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm)
+ terser: 5.31.6
+ tsx: 4.19.1
+ yaml: 2.6.0
+
+ vitest@4.0.18(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0):
+ dependencies:
+ '@vitest/expect': 4.0.18
+ '@vitest/mocker': 4.0.18(vite@7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
+ '@vitest/pretty-format': 4.0.18
+ '@vitest/runner': 4.0.18
+ '@vitest/snapshot': 4.0.18
+ '@vitest/spy': 4.0.18
+ '@vitest/utils': 4.0.18
es-module-lexer: 1.7.0
expect-type: 1.2.2
magic-string: 0.30.21
+ obug: 2.1.1
pathe: 2.0.3
picomatch: 4.0.3
std-env: 3.10.0
tinybench: 2.9.0
- tinyexec: 0.3.2
+ tinyexec: 1.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
- vite: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.30.2(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
+ vite: 7.0.0(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 20.19.1
@@ -9035,7 +9031,6 @@ snapshots:
- sass-embedded
- stylus
- sugarss
- - supports-color
- terser
- tsx
- yaml
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index ba9aedcb6660..4752226d9c0a 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -7,14 +7,14 @@ packages:
catalog:
'@types/node': ^20.19.0
- prettier: 3.6.2
- vite: ^7.0.0
+ prettier: 3.8.1
+ vite: ^7.3.1
webpack: ^5
- lightningcss: 1.30.2
- lightningcss-darwin-arm64: 1.30.2
- lightningcss-darwin-x64: 1.30.2
- lightningcss-linux-arm64-gnu: 1.30.2
- lightningcss-linux-arm64-musl: 1.30.2
- lightningcss-linux-x64-gnu: 1.30.2
- lightningcss-linux-x64-musl: 1.30.2
- lightningcss-win32-x64-msvc: 1.30.2
+ lightningcss: 1.31.1
+ lightningcss-darwin-arm64: 1.31.1
+ lightningcss-darwin-x64: 1.31.1
+ lightningcss-linux-arm64-gnu: 1.31.1
+ lightningcss-linux-arm64-musl: 1.31.1
+ lightningcss-linux-x64-gnu: 1.31.1
+ lightningcss-linux-x64-musl: 1.31.1
+ lightningcss-win32-x64-msvc: 1.31.1
From 23d01bc4746c614a4e2c0ecd5ba4e89c72f7c569 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Wed, 4 Feb 2026 13:06:44 +0100
Subject: [PATCH 12/40] only notify Discord once
If we're in a matrix, and one of the jobs fail, then we only want to
notify Discord once instead of for each failure.
---
.github/workflows/ci.yml | 8 ++++++--
.github/workflows/integration-tests.yml | 8 ++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f817e05a3a90..fca477c08bec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -110,9 +110,13 @@ jobs:
- name: Run Playwright tests
run: npm run test:ui
+ notify:
+ if: ${{ always() && github.ref == 'refs/heads/main' && needs.tests.result == 'failure' }}
+ needs: tests
+ runs-on: ubuntu-latest
+ steps:
- name: Notify Discord
- if: failure() && github.ref == 'refs/heads/main'
uses: discord-actions/message@v2
with:
webhookUrl: ${{ secrets.DISCORD_WEBHOOK_URL }}
- message: 'The [most recent build](<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>) on the `main` branch has failed.'
+ message: 'The [most recent ${{ github.workflow }} workflow](<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>) on the `main` branch has failed.'
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 1508c1effc49..3b2cf8f1b80a 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -113,9 +113,13 @@ jobs:
env:
GITHUB_WORKSPACE: ${{ github.workspace }}
+ notify:
+ if: ${{ always() && github.ref == 'refs/heads/main' && needs.tests.result == 'failure' }}
+ needs: tests
+ runs-on: ubuntu-latest
+ steps:
- name: Notify Discord
- if: failure() && github.ref == 'refs/heads/main'
uses: discord-actions/message@v2
with:
webhookUrl: ${{ secrets.DISCORD_WEBHOOK_URL }}
- message: 'The [most recent build](<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>) on the `main` branch has failed.'
+ message: 'The [most recent ${{ github.workflow }} workflow](<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>) on the `main` branch has failed.'
From ddb47e84da39598edcf07c6048a034abfa104ef2 Mon Sep 17 00:00:00 2001
From: Pavan Shinde
Date: Thu, 5 Feb 2026 21:29:10 +0530
Subject: [PATCH 13/40] Fix README license badge link (#19638)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
The README license badge linked to a non-existent `master` branch (and
the wrong org).
This updates the link to the current location:
tailwindlabs/tailwindcss/blob/main/LICENSE.
## Test plan
- Opened `README.md` and clicked the license badge/link to confirm it
resolves to the LICENSE file on the `main` branch.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7d21bd88385a..6e676ed2afaa 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
-
+
---
From e73c2472fd32411c811529cab451bb0212910999 Mon Sep 17 00:00:00 2001
From: Pavan Shinde
Date: Fri, 6 Feb 2026 21:21:07 +0530
Subject: [PATCH 14/40] Fix README links to use main branch (#19641)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
The README still referenced the `next` branch for the CI badge and
contributing docs link, but the `next` branch no longer exists upstream.
This updates those URLs to point to `main` so the badge and contributing
docs link work correctly.
## Test plan
N/A, docs only change
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 6e676ed2afaa..3dc5032fda5e 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
-
+
@@ -33,4 +33,4 @@ For help, discussion about best practices, or feature ideas:
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
From 8ed67bf5510d8435d2be766b25245abe15b3bcef Mon Sep 17 00:00:00 2001
From: Pavan Shinde
Date: Sun, 8 Feb 2026 05:56:38 +0530
Subject: [PATCH 15/40] Fix Tailwind CSS package README GitHub links (#19644)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
These package READMEs referenced the wrong GitHub org
(tailwindcss/tailwindcss) and outdated branches (master/next) for common
project links.
Update them to point at tailwindlabs/tailwindcss on main for releases,
license, discussions, and contributing docs.
## Test plan
Docs-only change: No test required.
---
packages/@tailwindcss-browser/README.md | 8 ++++----
packages/@tailwindcss-cli/README.md | 8 ++++----
packages/@tailwindcss-node/README.md | 8 ++++----
packages/@tailwindcss-postcss/README.md | 8 ++++----
packages/@tailwindcss-upgrade/README.md | 8 ++++----
packages/@tailwindcss-vite/README.md | 8 ++++----
packages/tailwindcss/README.md | 8 ++++----
7 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/packages/@tailwindcss-browser/README.md b/packages/@tailwindcss-browser/README.md
index 7d21bd88385a..4c2e56fffa13 100644
--- a/packages/@tailwindcss-browser/README.md
+++ b/packages/@tailwindcss-browser/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
diff --git a/packages/@tailwindcss-cli/README.md b/packages/@tailwindcss-cli/README.md
index 7d21bd88385a..4c2e56fffa13 100644
--- a/packages/@tailwindcss-cli/README.md
+++ b/packages/@tailwindcss-cli/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
diff --git a/packages/@tailwindcss-node/README.md b/packages/@tailwindcss-node/README.md
index 7d21bd88385a..4c2e56fffa13 100644
--- a/packages/@tailwindcss-node/README.md
+++ b/packages/@tailwindcss-node/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
diff --git a/packages/@tailwindcss-postcss/README.md b/packages/@tailwindcss-postcss/README.md
index 867389f0ea79..2313ccb7725f 100644
--- a/packages/@tailwindcss-postcss/README.md
+++ b/packages/@tailwindcss-postcss/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,11 +29,11 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
---
diff --git a/packages/@tailwindcss-upgrade/README.md b/packages/@tailwindcss-upgrade/README.md
index 7d21bd88385a..4c2e56fffa13 100644
--- a/packages/@tailwindcss-upgrade/README.md
+++ b/packages/@tailwindcss-upgrade/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
diff --git a/packages/@tailwindcss-vite/README.md b/packages/@tailwindcss-vite/README.md
index 53e03ab47e89..6e3688b875ef 100644
--- a/packages/@tailwindcss-vite/README.md
+++ b/packages/@tailwindcss-vite/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,11 +29,11 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
---
diff --git a/packages/tailwindcss/README.md b/packages/tailwindcss/README.md
index 7d21bd88385a..4c2e56fffa13 100644
--- a/packages/tailwindcss/README.md
+++ b/packages/tailwindcss/README.md
@@ -15,8 +15,8 @@
-
-
+
+
---
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/next/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
From 4614f5eaa7c8bd4bd446de885577af8a40814f63 Mon Sep 17 00:00:00 2001
From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com>
Date: Mon, 9 Feb 2026 12:20:25 -0500
Subject: [PATCH 16/40] =?UTF-8?q?Update=20autoprefixer=2010.4.23=20?=
=?UTF-8?q?=E2=86=92=2010.4.24=20(patch)=20(#19642)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.
### What changed?
#### ✳️ autoprefixer (10.4.23 → 10.4.24) ·
[Repo](https://github.com/postcss/autoprefixer) ·
[Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
Release Notes
Made Autoprefixer a little faster (by @Cherry ).
Does any of this look wrong? Please let
us know.
Commits
See
the full diff on Github . The new version differs by 3 commits:
---

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.
All Depfu comment commands
@depfu rebase Rebases against your default branch and
redoes this update
@depfu recreate Recreates this PR, overwriting any edits
that you've made to it
@depfu merge Merges this PR once your tests are passing and
conflicts are resolved
@depfu cancel merge Cancels automatic merging of this
PR
@depfu close Closes this PR and deletes the branch
@depfu reopen Restores the branch and reopens this PR (if
it's closed)
@depfu pause Ignores all future updates for this dependency
and closes this PR
@depfu pause [minor|major] Ignores all future minor/major
updates for this dependency and closes this PR
@depfu resume Future versions of this dependency will
create PRs again (leaves this PR as is)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
---
playgrounds/v3/package.json | 2 +-
pnpm-lock.yaml | 34 ++++++++++++++++++++++++----------
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/playgrounds/v3/package.json b/playgrounds/v3/package.json
index b8e1e16fc6ca..b54e5fae5af2 100644
--- a/playgrounds/v3/package.json
+++ b/playgrounds/v3/package.json
@@ -18,7 +18,7 @@
"@types/node": "catalog:",
"@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
- "autoprefixer": "^10.4.23",
+ "autoprefixer": "^10.4.24",
"eslint": "^9.39.2",
"eslint-config-next": "^16.1.6",
"typescript": "^5.9.3"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index be257c0fbfe0..0b8282efaa29 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -561,8 +561,8 @@ importers:
specifier: ^19.2.3
version: 19.2.3(@types/react@19.2.10)
autoprefixer:
- specifier: ^10.4.23
- version: 10.4.23(postcss@8.5.6)
+ specifier: ^10.4.24
+ version: 10.4.24(postcss@8.5.6)
eslint:
specifier: ^9.39.2
version: 9.39.2(jiti@2.6.1)
@@ -2058,6 +2058,7 @@ packages:
'@parcel/watcher-darwin-arm64@2.5.6':
resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.0':
@@ -2075,6 +2076,7 @@ packages:
'@parcel/watcher-darwin-x64@2.5.6':
resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.0':
@@ -2128,6 +2130,7 @@ packages:
'@parcel/watcher-linux-arm64-glibc@2.5.6':
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.0':
@@ -2145,6 +2148,7 @@ packages:
'@parcel/watcher-linux-arm64-musl@2.5.6':
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.0':
@@ -2162,6 +2166,7 @@ packages:
'@parcel/watcher-linux-x64-glibc@2.5.6':
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.0':
@@ -2179,6 +2184,7 @@ packages:
'@parcel/watcher-linux-x64-musl@2.5.6':
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
os: [linux]
'@parcel/watcher-wasm@2.5.0':
@@ -2226,6 +2232,7 @@ packages:
'@parcel/watcher-win32-x64@2.5.6':
resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
engines: {node: '>= 10.0.0'}
+ cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.0':
@@ -2692,8 +2699,8 @@ packages:
ast-types-flow@0.0.8:
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
- autoprefixer@10.4.23:
- resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==}
+ autoprefixer@10.4.24:
+ resolution: {integrity: sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
@@ -2757,6 +2764,7 @@ packages:
bun@1.3.7:
resolution: {integrity: sha512-ha86NG8WiAXYR7eQw/9S+7V7Lo8KfD36XutWJNS1VndzaipWS0QIen5n3K9MT3PpP/sdGmmHjhkrU0sCM2lGGQ==}
+ cpu: [arm64, x64]
os: [darwin, linux, win32]
hasBin: true
@@ -2793,6 +2801,9 @@ packages:
caniuse-lite@1.0.30001761:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
+ caniuse-lite@1.0.30001769:
+ resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==}
+
chai@6.2.1:
resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==}
engines: {node: '>=18'}
@@ -3346,6 +3357,7 @@ packages:
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
globals@14.0.0:
@@ -6641,10 +6653,10 @@ snapshots:
ast-types-flow@0.0.8: {}
- autoprefixer@10.4.23(postcss@8.5.6):
+ autoprefixer@10.4.24(postcss@8.5.6):
dependencies:
browserslist: 4.28.1
- caniuse-lite: 1.0.30001761
+ caniuse-lite: 1.0.30001769
fraction.js: 5.3.4
picocolors: 1.1.1
postcss: 8.5.6
@@ -6684,7 +6696,7 @@ snapshots:
browserslist@4.28.0:
dependencies:
baseline-browser-mapping: 2.8.29
- caniuse-lite: 1.0.30001761
+ caniuse-lite: 1.0.30001769
electron-to-chromium: 1.5.255
node-releases: 2.0.27
update-browserslist-db: 1.1.4(browserslist@4.28.0)
@@ -6747,6 +6759,8 @@ snapshots:
caniuse-lite@1.0.30001761: {}
+ caniuse-lite@1.0.30001769: {}
+
chai@6.2.1: {}
chalk@4.1.2:
@@ -7119,7 +7133,7 @@ snapshots:
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.1(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1))
@@ -7173,7 +7187,7 @@ snapshots:
is-bun-module: 1.2.1
is-glob: 4.0.3
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-node
@@ -7220,7 +7234,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
From 257dc581ba4a45eb34578eddad69905166bf8388 Mon Sep 17 00:00:00 2001
From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com>
Date: Mon, 9 Feb 2026 12:20:45 -0500
Subject: [PATCH 17/40] =?UTF-8?q?Update=20@vitejs/plugin-react=205.1.2=20?=
=?UTF-8?q?=E2=86=92=205.1.3=20(patch)=20(#19651)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Here is everything you need to know about this update. Please take a
good look at what changed and the test results before merging this pull
request.
### What changed?
#### ✳️ @vitejs/plugin-react (5.1.2 → 5.1.3) ·
[Repo](https://github.com/vitejs/vite-plugin-react) ·
[Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
---

[Depfu](https://depfu.com) will automatically keep this PR
conflict-free, as long as you don't add any commits to this branch
yourself. You can also trigger a rebase manually by commenting with
`@depfu rebase`.
All Depfu comment commands
@depfu rebase Rebases against your default branch and
redoes this update
@depfu recreate Recreates this PR, overwriting any edits
that you've made to it
@depfu merge Merges this PR once your tests are passing and
conflicts are resolved
@depfu cancel merge Cancels automatic merging of this
PR
@depfu close Closes this PR and deletes the branch
@depfu reopen Restores the branch and reopens this PR (if
it's closed)
@depfu pause Ignores all future updates for this dependency
and closes this PR
@depfu pause [minor|major] Ignores all future minor/major
updates for this dependency and closes this PR
@depfu resume Future versions of this dependency will
create PRs again (leaves this PR as is)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
---
playgrounds/vite/package.json | 2 +-
pnpm-lock.yaml | 203 +++++++++++++++++++++++++++++-----
2 files changed, 175 insertions(+), 30 deletions(-)
diff --git a/playgrounds/vite/package.json b/playgrounds/vite/package.json
index d339dc39fe8b..1219e79b9f64 100644
--- a/playgrounds/vite/package.json
+++ b/playgrounds/vite/package.json
@@ -10,7 +10,7 @@
},
"dependencies": {
"@tailwindcss/vite": "workspace:^",
- "@vitejs/plugin-react": "^5.1.2",
+ "@vitejs/plugin-react": "^5.1.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"tailwindcss": "workspace:^"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0b8282efaa29..a65a5ce8502b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -506,7 +506,7 @@ importers:
version: 3.3.3
next:
specifier: ^16.1.6
- version: 16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ version: 16.1.6(@babel/core@7.28.5)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react:
specifier: ^19.2.4
version: 19.2.4
@@ -531,7 +531,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: ^16.1.6
- version: 16.1.6(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 16.1.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
typescript:
specifier: ^5.9.3
version: 5.9.3
@@ -540,7 +540,7 @@ importers:
dependencies:
next:
specifier: ^16.1.6
- version: 16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ version: 16.1.6(@babel/core@7.28.5)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
react:
specifier: ^19.2.4
version: 19.2.4
@@ -568,7 +568,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: ^16.1.6
- version: 16.1.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 16.1.6(@typescript-eslint/parser@8.47.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
typescript:
specifier: ^5.9.3
version: 5.9.3
@@ -579,8 +579,8 @@ importers:
specifier: workspace:^
version: link:../../packages/@tailwindcss-vite
'@vitejs/plugin-react':
- specifier: ^5.1.2
- version: 5.1.2(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
+ specifier: ^5.1.3
+ version: 5.1.3(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))
react:
specifier: ^19.2.4
version: 19.2.4
@@ -614,22 +614,42 @@ packages:
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
+ '@babel/code-frame@7.29.0':
+ resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/compat-data@7.27.5':
resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==}
engines: {node: '>=6.9.0'}
+ '@babel/compat-data@7.29.0':
+ resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/core@7.28.5':
resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==}
engines: {node: '>=6.9.0'}
+ '@babel/core@7.29.0':
+ resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/generator@7.28.5':
resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
engines: {node: '>=6.9.0'}
+ '@babel/generator@7.29.1':
+ resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-compilation-targets@7.27.2':
resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-compilation-targets@7.28.6':
+ resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-globals@7.28.0':
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
engines: {node: '>=6.9.0'}
@@ -638,12 +658,22 @@ packages:
resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-module-imports@7.28.6':
+ resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-module-transforms@7.28.3':
resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-module-transforms@7.28.6':
+ resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-plugin-utils@7.27.1':
resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
engines: {node: '>=6.9.0'}
@@ -664,11 +694,20 @@ packages:
resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
engines: {node: '>=6.9.0'}
+ '@babel/helpers@7.28.6':
+ resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/parser@7.28.5':
resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.29.0':
+ resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/plugin-transform-react-jsx-self@7.27.1':
resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
engines: {node: '>=6.9.0'}
@@ -685,14 +724,26 @@ packages:
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
+ '@babel/template@7.28.6':
+ resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/traverse@7.28.5':
resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.29.0':
+ resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.28.5':
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.29.0':
+ resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+ engines: {node: '>=6.9.0'}
+
'@emnapi/core@1.7.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
@@ -2252,8 +2303,8 @@ packages:
engines: {node: '>=18'}
hasBin: true
- '@rolldown/pluginutils@1.0.0-beta.53':
- resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==}
+ '@rolldown/pluginutils@1.0.0-rc.2':
+ resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==}
'@rollup/rollup-android-arm-eabi@4.44.0':
resolution: {integrity: sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==}
@@ -2501,8 +2552,8 @@ packages:
resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@vitejs/plugin-react@5.1.2':
- resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==}
+ '@vitejs/plugin-react@5.1.3':
+ resolution: {integrity: sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg==}
engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
@@ -4933,8 +4984,16 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
+ '@babel/code-frame@7.29.0':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
'@babel/compat-data@7.27.5': {}
+ '@babel/compat-data@7.29.0': {}
+
'@babel/core@7.28.5':
dependencies:
'@babel/code-frame': 7.27.1
@@ -4955,6 +5014,26 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/core@7.29.0':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.1
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
+ '@babel/helpers': 7.28.6
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/generator@7.28.5':
dependencies:
'@babel/parser': 7.28.5
@@ -4963,6 +5042,14 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.29
jsesc: 3.1.0
+ '@babel/generator@7.29.1':
+ dependencies:
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+ jsesc: 3.1.0
+
'@babel/helper-compilation-targets@7.27.2':
dependencies:
'@babel/compat-data': 7.27.5
@@ -4971,6 +5058,14 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
+ '@babel/helper-compilation-targets@7.28.6':
+ dependencies:
+ '@babel/compat-data': 7.29.0
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.28.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
'@babel/helper-globals@7.28.0': {}
'@babel/helper-module-imports@7.27.1':
@@ -4980,6 +5075,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-imports@7.28.6':
+ dependencies:
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -4989,6 +5091,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-plugin-utils@7.27.1': {}
'@babel/helper-string-parser@7.27.1': {}
@@ -5002,18 +5113,27 @@ snapshots:
'@babel/template': 7.27.2
'@babel/types': 7.28.5
+ '@babel/helpers@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+
'@babel/parser@7.28.5':
dependencies:
'@babel/types': 7.28.5
- '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)':
+ '@babel/parser@7.29.0':
dependencies:
- '@babel/core': 7.28.5
+ '@babel/types': 7.29.0
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)':
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)':
dependencies:
- '@babel/core': 7.28.5
+ '@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/template@7.27.2':
@@ -5022,6 +5142,12 @@ snapshots:
'@babel/parser': 7.28.5
'@babel/types': 7.28.5
+ '@babel/template@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+
'@babel/traverse@7.28.5':
dependencies:
'@babel/code-frame': 7.27.1
@@ -5034,11 +5160,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/traverse@7.29.0':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.1
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/types@7.28.5':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
+ '@babel/types@7.29.0':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
'@emnapi/core@1.7.1':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@@ -6142,7 +6285,7 @@ snapshots:
dependencies:
playwright: 1.58.0
- '@rolldown/pluginutils@1.0.0-beta.53': {}
+ '@rolldown/pluginutils@1.0.0-rc.2': {}
'@rollup/rollup-android-arm-eabi@4.44.0':
optional: true
@@ -6234,24 +6377,24 @@ snapshots:
'@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
'@types/babel__generator': 7.6.8
'@types/babel__template': 7.4.4
'@types/babel__traverse': 7.20.6
'@types/babel__generator@7.6.8':
dependencies:
- '@babel/types': 7.28.5
+ '@babel/types': 7.29.0
'@types/babel__template@7.4.4':
dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
'@types/babel__traverse@7.20.6':
dependencies:
- '@babel/types': 7.28.5
+ '@babel/types': 7.29.0
'@types/braces@3.0.5': {}
@@ -6393,12 +6536,12 @@ snapshots:
'@typescript-eslint/types': 8.47.0
eslint-visitor-keys: 4.2.1
- '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
+ '@vitejs/plugin-react@5.1.3(vite@7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0))':
dependencies:
- '@babel/core': 7.28.5
- '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
- '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
- '@rolldown/pluginutils': 1.0.0-beta.53
+ '@babel/core': 7.29.0
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0)
+ '@rolldown/pluginutils': 1.0.0-rc.2
'@types/babel__core': 7.20.5
react-refresh: 0.18.0
vite: 7.3.1(@types/node@20.19.1)(jiti@2.6.1)(lightningcss@1.31.1(patch_hash=tzyxy3asfxcqc7ihrooumyi5fm))(terser@5.31.6)(tsx@4.19.1)(yaml@2.6.0)
@@ -8058,7 +8201,7 @@ snapshots:
neo-async@2.6.2: {}
- next@16.1.6(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ next@16.1.6(@babel/core@7.28.5)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
'@next/env': 16.1.6
'@swc/helpers': 0.5.15
@@ -8067,7 +8210,7 @@ snapshots:
postcss: 8.4.31
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
- styled-jsx: 5.1.6(react@19.2.4)
+ styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.4)
optionalDependencies:
'@next/swc-darwin-arm64': 16.1.6
'@next/swc-darwin-x64': 16.1.6
@@ -8663,10 +8806,12 @@ snapshots:
strip-json-comments@3.1.1: {}
- styled-jsx@5.1.6(react@19.2.4):
+ styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.4):
dependencies:
client-only: 0.0.1
react: 19.2.4
+ optionalDependencies:
+ '@babel/core': 7.28.5
sucrase@3.35.0:
dependencies:
From 99a7c602f2629f2b02645acd5980df1ee7e172b6 Mon Sep 17 00:00:00 2001
From: Pavan Shinde
Date: Tue, 17 Feb 2026 17:36:49 +0530
Subject: [PATCH 18/40] docs: fix GitHub links to tailwindlabs org (#19686)
## Summary
Fix outdated GitHub links that still point to
`github.com/tailwindcss/tailwindcss` (old org). This updates references
across the README, contributing guide, and PR template to the canonical
`tailwindlabs/tailwindcss` URLs to avoid redirects/404s and keep repo
metadata consistent
## Test Plan
This change is docs-only.
---
.github/CONTRIBUTING.md | 2 +-
.github/PULL_REQUEST_TEMPLATE.md | 2 +-
README.md | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 42645aa492d5..4dfe6eba98fe 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -50,7 +50,7 @@ If you open a pull request for a new feature, we're likely to close it not becau
## Coding standards
-Our code formatting rules are defined in the `"prettier"` section of [package.json](https://github.com/tailwindcss/tailwindcss/blob/main/package.json). You can check your code against these standards by running:
+Our code formatting rules are defined in the `"prettier"` section of [package.json](https://github.com/tailwindlabs/tailwindcss/blob/main/package.json). You can check your code against these standards by running:
```sh
pnpm run lint
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index ee9d3f9abcc0..aa0793aa39f8 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -8,7 +8,7 @@ It's never a fun experience to have your pull request declined after investing a
For more info, check out the contributing guide:
-https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md
+https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md
-->
diff --git a/README.md b/README.md
index 3dc5032fda5e..5f532607d00a 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
-
+
@@ -29,8 +29,8 @@ For full documentation, visit [tailwindcss.com](https://tailwindcss.com).
For help, discussion about best practices, or feature ideas:
-[Discuss Tailwind CSS on GitHub](https://github.com/tailwindcss/tailwindcss/discussions)
+[Discuss Tailwind CSS on GitHub](https://github.com/tailwindlabs/tailwindcss/discussions)
## Contributing
-If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
+If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**.
From d74f8b83926bb78c05e6bb51cf6d5f149ec4c65f Mon Sep 17 00:00:00 2001
From: Benjamin Bock
Date: Tue, 17 Feb 2026 18:09:59 +0100
Subject: [PATCH 19/40] Add '.jj' to ignored content directories (#19687)
Ignore .jj directory, just like .git, .hg, .svn.
https://www.jj-vcs.dev/latest/
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
.../scanner/fixtures/ignored-content-dirs.txt | 17 +++++++++--------
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74f72f10eeb3..55cec3e08f5e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `inline-*`, `min-inline-*`, `max-inline-*`, `block-*`, `min-block-*`, `max-block-*` utilities for `inline-size`, `min-inline-size`, `max-inline-size`, `block-size`, `min-block-size`, and `max-block-size` ([#19612](https://github.com/tailwindlabs/tailwindcss/pull/19612))
- Add `inset-s-*`, `inset-e-*`, `inset-bs-*`, `inset-be-*` utilities for `inset-inline-start`, `inset-inline-end`, `inset-block-start`, and `inset-block-end` ([#19613](https://github.com/tailwindlabs/tailwindcss/pull/19613))
- Add `font-features-*` utility for `font-feature-settings` ([#19623](https://github.com/tailwindlabs/tailwindcss/pull/19615))
+- Add '.jj' to ignored content directories ([#19687](https://github.com/tailwindlabs/tailwindcss/pull/19687))
### Fixed
diff --git a/crates/oxide/src/scanner/fixtures/ignored-content-dirs.txt b/crates/oxide/src/scanner/fixtures/ignored-content-dirs.txt
index 0921d2ff8c8e..79f01ecc117a 100644
--- a/crates/oxide/src/scanner/fixtures/ignored-content-dirs.txt
+++ b/crates/oxide/src/scanner/fixtures/ignored-content-dirs.txt
@@ -1,14 +1,15 @@
.git
.hg
-.svn
-node_modules
-.yarn
-.venv
-venv
+.jj
.next
-.turbo
.parcel-cache
-__pycache__
-.svelte-kit
.pnpm-store
+.svelte-kit
+.svn
+.turbo
+.venv
.vercel
+.yarn
+__pycache__
+node_modules
+venv
From 6eb3b324340f451a14389b7ed97f43a264ad4487 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Tue, 17 Feb 2026 13:32:31 -0500
Subject: [PATCH 20/40] Allow multiples of `.25` in `aspect-*` fractions
(#19688)
This PR reduces the restrictions of the `aspect-*` utilities when
dealing with fractional values.
Up until now, the numbers had to be positive integers, so `aspect-1/2`
was valid, but `aspect-8.5/11` was not.
This PR allows for any multiple of `.25` as a valid value, so
`aspect-8.5/11` is now valid, but `aspect-8.3/11` is not, this will
still require `aspect-[8.3/11]` arbitrary value syntax to be valid.
This behavior of allowing multiples of `.25` is consistent with other
utilities that handle bare values such as `w-2.5`.
## Test plan
1. Existing tests pass
2. Added a test for `aspect-8.5/11`
Fixes: #19663
Closes: #19680, #19669
---
CHANGELOG.md | 1 +
packages/tailwindcss/src/utilities.test.ts | 7 ++++++-
packages/tailwindcss/src/utilities.ts | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55cec3e08f5e..2eb00b020469 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix class extraction for Rails' strict locals ([#19525](https://github.com/tailwindlabs/tailwindcss/pull/19525))
- Align `@utility` name validation with Oxide scanner rules ([#19524](https://github.com/tailwindlabs/tailwindcss/pull/19524))
- Fix infinite loop when using `@variant` inside `@custom-variant` ([#19633](https://github.com/tailwindlabs/tailwindcss/pull/19633))
+- Allow multiples of `.25` in `aspect-*` fractions ([#19688](https://github.com/tailwindlabs/tailwindcss/pull/19688))
### Deprecated
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index 29e8dae3a524..7bd03b577f66 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -3156,7 +3156,7 @@ test('aspect-ratio', async () => {
}
@tailwind utilities;
`,
- ['aspect-video', 'aspect-[10/9]', 'aspect-4/3'],
+ ['aspect-video', 'aspect-[10/9]', 'aspect-4/3', 'aspect-8.5/11'],
),
).toMatchInlineSnapshot(`
":root, :host {
@@ -3167,6 +3167,10 @@ test('aspect-ratio', async () => {
aspect-ratio: 4 / 3;
}
+ .aspect-8\\.5\\/11 {
+ aspect-ratio: 8.5 / 11;
+ }
+
.aspect-\\[10\\/9\\] {
aspect-ratio: 10 / 9;
}
@@ -3188,6 +3192,7 @@ test('aspect-ratio', async () => {
'aspect--4/3',
'aspect--4/-3',
'aspect-4/-3',
+ 'aspect-1.23/4.56',
]),
).toEqual('')
})
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index fd524f495575..015821e4e833 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -981,7 +981,7 @@ export function createUtilities(theme: Theme) {
handleBareValue: ({ fraction }) => {
if (fraction === null) return null
let [lhs, rhs] = segment(fraction, '/')
- if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return null
+ if (!isValidSpacingMultiplier(lhs) || !isValidSpacingMultiplier(rhs)) return null
return fraction
},
handle: (value) => [decl('aspect-ratio', value)],
From f212b0fc22c3e6f93a5068654e67bd2818109b95 Mon Sep 17 00:00:00 2001
From: "Arsher. {Zach}"
Date: Tue, 17 Feb 2026 19:04:17 +0000
Subject: [PATCH 21/40] fix: restore full page reload for watched external
files on Vite 7.1+ (#19670)
# PR: Fix @source file changes not triggering full page reload on Vite
7.1+
## Description
This PR addresses issue #19637 where template files (PHP, HTML, Blade,
etc.) watched via the `@source` directive fail to trigger a full page
reload when using Vite 7.1 or newer.
## Root Cause
Vite 7.1 introduced the Environment API, which supersedes the legacy
WebSocket API for HMR. Specifically:
- `server.ws.send` is deprecated/ignored for certain external file
updates in favor of `server.hot.send`.
- The `@tailwindcss/vite` plugin currently collects `ViteDevServer`
instances but lacks a `handleHotUpdate` hook to explicitly trigger
reloads for non-module files added via `addWatchFile`.
## Changes
- Implemented a `handleHotUpdate` hook in the `@tailwindcss/vite`
plugin.
- The hook identifies changes to files that are not part of the standard
Vite module graph (e.g., `.php`, `.html`) but are watched by Tailwind.
- Triggers a `full-reload` using the new `server.hot.send` API if
available (Vite 7.1+), with a fallback to `server.ws.send` for backward
compatibility.
## Verification
- Reproduced the issue in a standalone Vite 7.1.0 project using a mock
plugin with the legacy API.
- Confirmed that the browser fails to reload upon editing a watched
`.php` file.
- Verified that migrating to `server.hot.send` restores the expected
reload behavior.
[ci-all]
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
integrations/vite/index.test.ts | 112 +++++++++++++++++++++++
packages/@tailwindcss-vite/src/index.ts | 114 ++++++++++++++++++++++++
3 files changed, 227 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2eb00b020469..a549a1232d65 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Align `@utility` name validation with Oxide scanner rules ([#19524](https://github.com/tailwindlabs/tailwindcss/pull/19524))
- Fix infinite loop when using `@variant` inside `@custom-variant` ([#19633](https://github.com/tailwindlabs/tailwindcss/pull/19633))
- Allow multiples of `.25` in `aspect-*` fractions ([#19688](https://github.com/tailwindlabs/tailwindcss/pull/19688))
+- Ensure changes to external files listed via `@source` trigger a full page reload when using `@tailwindcss/vite` ([#19670](https://github.com/tailwindlabs/tailwindcss/pull/19670))
### Deprecated
diff --git a/integrations/vite/index.test.ts b/integrations/vite/index.test.ts
index b8b2ad6e39df..81236579d378 100644
--- a/integrations/vite/index.test.ts
+++ b/integrations/vite/index.test.ts
@@ -7,6 +7,7 @@ import {
html,
js,
json,
+ jsx,
retryAssertion,
test,
ts,
@@ -472,6 +473,117 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
},
)
+ describe.sequential.each([['^6'], ['7.0.8'], ['7.1.12'], ['7.3.1']])(
+ 'Using Vite %s',
+ (version) => {
+ test(
+ 'external source file changes trigger a full reload',
+ {
+ fs: {
+ 'package.json': json`{}`,
+ 'pnpm-workspace.yaml': yaml`
+ #
+ packages:
+ - project-a
+ `,
+ 'project-a/package.json': json`
+ {
+ "type": "module",
+ "dependencies": {
+ "@tailwindcss/vite": "workspace:^",
+ "tailwindcss": "workspace:^"
+ },
+ "devDependencies": {
+ ${transformer === 'lightningcss' ? `"lightningcss": "^1",` : ''}
+ "vite": "${version}"
+ }
+ }
+ `,
+ 'project-a/vite.config.ts': ts`
+ import fs from 'node:fs'
+ import path from 'node:path'
+ import tailwindcss from '@tailwindcss/vite'
+ import { defineConfig } from 'vite'
+
+ export default defineConfig({
+ css: ${transformer === 'postcss' ? '{}' : "{ transformer: 'lightningcss' }"},
+ build: { cssMinify: false },
+ plugins: [tailwindcss()],
+ logLevel: 'info',
+ })
+ `,
+ 'project-a/index.html': html`
+
+
+
+
+
+
+
+
+
+ `,
+ 'project-a/src/main.ts': jsx`import { classes } from './app'`,
+ 'project-a/src/app.ts': jsx`export let classes = "content-['project-a/src/app.ts']"`,
+ 'project-a/src/index.css': css`
+ @import 'tailwindcss';
+ @source '../../project-b/**/*.php';
+ `,
+ 'project-b/src/index.php': html`
+
+ `,
+ },
+ },
+ async ({ root, spawn, fs, expect }) => {
+ let process = await spawn('pnpm vite dev --debug hmr', {
+ cwd: path.join(root, 'project-a'),
+ })
+ await process.onStdout((m) => m.includes('ready in'))
+
+ let url = ''
+ await process.onStdout((m) => {
+ let match = /Local:\s*(http.*)\//.exec(m)
+ if (match) url = match[1]
+ return Boolean(url)
+ })
+
+ await retryAssertion(async () => {
+ let styles = await fetchStyles(url, '/index.html')
+ expect(styles).toContain(candidate`content-['project-b/src/index.php']`)
+ })
+
+ // Flush all messages so that we can be sure the next messages are from
+ // the file changes we're about to make
+ process.flush()
+
+ // Changing an external .php file should trigger a full reload
+ {
+ await fs.write(
+ 'project-b/src/index.php',
+ txt`
`,
+ )
+
+ // Ensure the page reloaded
+ if (version === '^6' || version === '7.0.8') {
+ await process.onStdout((m) => m.includes('page reload') && m.includes('index.php'))
+ } else {
+ await process.onStderr(
+ (m) => m.includes('vite:hmr (client)') && m.includes('index.php'),
+ )
+ }
+ await process.onStderr((m) => m.includes('vite:hmr (ssr)') && m.includes('index.php'))
+
+ // Ensure the styles were regenerated with the new content
+ let styles = await fetchStyles(url, '/index.html')
+ expect(styles).toContain(candidate`content-['updated:project-b/src/index.php']`)
+ }
+ },
+ )
+ },
+ )
+
test(
`source(none) disables looking at the module graph`,
{
diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts
index 4ad70ba43a34..d7d46c77222a 100644
--- a/packages/@tailwindcss-vite/src/index.ts
+++ b/packages/@tailwindcss-vite/src/index.ts
@@ -9,6 +9,7 @@ import {
} from '@tailwindcss/node'
import { clearRequireCache } from '@tailwindcss/node/require-cache'
import { Scanner } from '@tailwindcss/oxide'
+import { realpathSync } from 'node:fs'
import fs from 'node:fs/promises'
import path from 'node:path'
import type { Environment, Plugin, ResolvedConfig, ViteDevServer } from 'vite'
@@ -151,6 +152,64 @@ export default function tailwindcss(opts: PluginOptions = {}): Plugin[] {
return result
},
},
+
+ hotUpdate({ file, modules, timestamp, server }) {
+ // Ensure full-reloads are triggered for files that are being watched by
+ // Tailwind but aren't part of the module graph (like PHP or HTML
+ // files). If we don't do this, then changes to those files won't
+ // trigger a reload at all since Vite doesn't know about them.
+ {
+ // It's a little bit confusing, because due to the `addWatchFile`
+ // calls, it _is_ part of the module graph but nothing is really
+ // handling those files. These modules typically have an id of
+ // undefined and/or have a type of 'asset'.
+ //
+ // If we call `addWatchFile` on a file that is part of the actual
+ // module graph, then we will see a module for it with a type of `js`
+ // and a type of `asset`. We are only interested if _all_ of them are
+ // missing an id and/or have a type of 'asset', which is a strong
+ // signal that the changed file is not being handled by Vite or any of
+ // the plugins.
+ //
+ // Note: in Vite v7.0.6 the modules here will have a type of `js`, not
+ // 'asset'. But it will also have a `HARD_INVALIDATED` state and will
+ // do a full page reload already.
+ let isExternalFile = modules.every((mod) => mod.type === 'asset' || mod.id === undefined)
+ if (!isExternalFile) return
+
+ for (let env of new Set([this.environment.name, 'client'])) {
+ let roots = rootsByEnv.get(env)
+ if (roots.size === 0) continue
+
+ // If the file is not being watched by any of the roots, then we can
+ // skip the reload since it's not relevant to Tailwind CSS.
+ if (!isScannedFile(file, modules, roots)) {
+ continue
+ }
+
+ // https://vite.dev/changes/hotupdate-hook#migration-guide
+ let invalidatedModules = new Set()
+ for (let mod of modules) {
+ this.environment.moduleGraph.invalidateModule(
+ mod,
+ invalidatedModules,
+ timestamp,
+ true,
+ )
+ }
+
+ if (env === this.environment.name) {
+ this.environment.hot.send({ type: 'full-reload' })
+ } else if (server.hot.send) {
+ server.hot.send({ type: 'full-reload' })
+ } else if (server.ws.send) {
+ server.ws.send({ type: 'full-reload' })
+ }
+
+ return []
+ }
+ }
+ },
},
{
@@ -271,6 +330,10 @@ class Root {
private customJsResolver: (id: string, base: string) => Promise,
) {}
+ get scannedFiles() {
+ return this.scanner?.files ?? []
+ }
+
// Generate the CSS for the root file. This can return false if the file is
// not considered a Tailwind root. When this happened, the root can be GCed.
public async generate(
@@ -452,3 +515,54 @@ class Root {
return false
}
}
+
+function isScannedFile(
+ file: string,
+ modules: vite.EnvironmentModuleNode[],
+ roots: Map,
+) {
+ let seen = new Set()
+ let q = [...modules]
+ let checks = {
+ file,
+ get realpath() {
+ try {
+ let realpath = realpathSync(file)
+ Object.defineProperty(checks, 'realpath', { value: realpath })
+ return realpath
+ } catch {
+ return null
+ }
+ },
+ }
+
+ while (q.length > 0) {
+ let module = q.shift()!
+ if (seen.has(module)) continue
+ seen.add(module)
+
+ if (module.id) {
+ let root = roots.get(module.id)
+
+ if (root) {
+ // If the file is part of the scanned files for this root, then we know
+ // for sure that it's being watched by any of the Tailwind CSS roots. It
+ // doesn't matter which root it is since it's only used to know whether
+ // we should trigger a full reload or not.
+ if (
+ root.scannedFiles.includes(checks.file) ||
+ (checks.realpath && root.scannedFiles.includes(checks.realpath))
+ ) {
+ return true
+ }
+ }
+ }
+
+ // Keep walking up the tree until we find a root.
+ for (let importer of module.importers) {
+ q.push(importer)
+ }
+ }
+
+ return false
+}
From 095ff96ba35de0824313fd150b6e70695d300dd1 Mon Sep 17 00:00:00 2001
From: Robin Malfait
Date: Tue, 17 Feb 2026 14:15:20 -0500
Subject: [PATCH 22/40] Improve performance in bigger projects (#19632)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR improves the performance of Oxide when scanning large codebases.
The `Oxide` API, looks something like this:
```ts
let scanner = new Scanner({ sources })
let candidates = scanner.scan() // Found candidates
let files = scanner.files // Scanned files
let globs = scanner.globs // Scanned globs
```
The `files` and `globs` are used to tell PostCSS, Vite, webpack etc
which files to watch for changes.
The `.scan()` operation extracts the candidates from the source files.
You can think of these as potential Tailwind CSS classes.
In all these scenarios we have to walk the file system and find files
that match the `sources`.
### 1. Prevent multiple file system walks
The first big win came from the fact that accessing `.files` after a
`.scan()` also does an entire walk of the file system (for the given
`sources`), which is unnecessary because we just walked the file system.
This is something that's not really an issue in smaller codebases
because we have `mtime` tracking. We don't re-scan a file if its `mtime`
hasn't changed since the last scan. However, in large codebases with
thousands of files, even walking the file system to check `mtime`s can
be expensive.
### 2. Use parallel file system walking
Another big win is to use a parallel file system walker instead of a
synchronous one. The big problem here is that the parallel build has
20ms-50ms of overhead which is noticeable on small codebases. We don't
really know if you have a small or big codebase ahead of time, so maybe
some kind of hint in the future would be useful.
So the solution I settled on right now is to use a synchronous walker
for the initial scan, and then switch to a parallel walker for
subsequent scans (think dev mode). This gives us the best of both
worlds: fast initial scan on small codebases, and fast re-scans on large
codebases.
Caveat: if you use the `@tailwindcss/cli` we know exactly which files
changed so we can just re-scan those files directly without walking the
file system at all. But in `@tailwindcss/postcss` we don't know which
files changed, so we have to walk the file system to check `mtime`s.
While this improvement is nice, it resulted in an annoying issue related
to `mtime` tracking. Since the parallel walker processes files in
parallel, the `mtime` was typed as `Arc>>` so to avoid locking, I decided to only walk the files
here and collect their paths. Then later we check the `mtime` to know
whether to re-scan them or not.
Initially I just removed the `mtime` tracking altogether. But it did
have an impact when actually extracting candidates from those files, so
I added it back later.
### 3. Delaying work
I was still a bit annoyed by the fact that we had to track `mtime`
values for every file. This seems like annoying overhead, especially
when doing a single build (no dev mode).
So the trick I applied here is to only start tracking `mtime` values
after the initial scan.
This means that, in dev mode, we would do this:
1. Walk entire file system to track files.
2. On a subsequent scan, walk entire file system (again) and start
tracking `mtime` values. This time, we use the parallel walker instead
of the synchronous one.
3. On further scans, only re-scan files whose `mtime` has changed
The trade-off here is that on the second scan we always re-scan all
files, even if they haven't changed. Since this typically only happens
in dev mode, I think this is an acceptable trade-off especially if the
initial build is therefor faster this way.
### 3. Small wins
There are also a few small wins in here that I would like to mention but
that are less significant:
1. Pre-computed normalized `source` patterns instead of in every walker
filter call.
2. Tried to avoid some allocations in various places. For example the
`pre_process_input` always called `content.to_vec()` which allocates.
Instead we now accept an owned `Vec` so we don't have to call
`.to_vec()` in the default case (in my testing, this is ~92% of the time
in the codebases I checked).
3. Made the `Cursor` struct smaller, which is used a lot during
candidate extraction.
### Benchmarks
Now for the fun stuff, the benchmarks!
The code for the benchmarks
```ts
import path from 'node:path'
import { bench, boxplot, do_not_optimize, run, summary } from 'mitata'
import { Scanner as ScannerPr } from '/path/to/repo/with/pr/branch/tailwindcss/crates/node'
import { Scanner as ScannerMain } from '/path/to/repo/with/main/branch/tailwindcss/crates/node'
let base = '/path/to/some/codebase'
let sources = [{ base, pattern: '**/*', negated: false }]
// Verify the results are the same before benchmarking
let scannerPr = new ScannerPr({ sources })
let scannerMain = new ScannerMain({ sources })
{
let aCandidates = scannerPr.scan()
let bCandidates = scannerMain.scan()
if (aCandidates.length !== bCandidates.length) {
throw new Error(`Mismatch in candidate count: ${aCandidates.length} vs ${bCandidates.length}`)
}
for (let i = 0; i < aCandidates.length; i++) {
if (aCandidates[i] !== bCandidates[i]) {
throw new Error(`Mismatch in candidate at index ${i}: ${aCandidates[i]} vs ${bCandidates[i]}`)
}
}
let aFiles = scannerPr.files
let bFiles = scannerMain.files
if (aFiles.length !== bFiles.length) {
throw new Error(`Mismatch in file count: ${aFiles.length} vs ${bFiles.length}`)
}
for (let i = 0; i < aFiles.length; i++) {
if (aFiles[i] !== bFiles[i]) {
throw new Error(`Mismatch in file at index ${i}: ${aFiles[i]} vs ${bFiles[i]}`)
}
}
console.log('Scanned', aFiles.length, 'files')
console.log('Extracted', aCandidates.length, 'candidates')
console.log('Base =', base)
console.log()
}
summary(() => {
boxplot(() => {
bench('PR (build, .scan()))', function* () {
yield {
[0]() {
return new ScannerPr({ sources })
},
bench(scanner: ScannerPr) {
do_not_optimize(scanner.scan())
},
}
})
bench('main (build, .scan()))', function* () {
yield {
[0]() {
return new ScannerMain({ sources })
},
bench(scanner: ScannerMain) {
do_not_optimize(scanner.scan())
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (build, .scan() + .files)', function* () {
yield {
[0]() {
return new ScannerPr({ sources })
},
bench(scanner: ScannerPr) {
do_not_optimize(scanner.scan())
do_not_optimize(scanner.files)
},
}
})
bench('main (build, .scan() + .files)', function* () {
yield {
[0]() {
return new ScannerMain({ sources })
},
bench(scanner: ScannerMain) {
do_not_optimize(scanner.scan())
do_not_optimize(scanner.files)
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (watch, .scan()))', function* () {
yield {
bench() {
do_not_optimize(scannerPr.scan())
},
}
})
bench('main (watch, .scan()))', function* () {
yield {
bench() {
do_not_optimize(scannerMain.scan())
},
}
})
})
})
summary(() => {
boxplot(() => {
bench('PR (watch, .scan() + .files)', function* () {
yield {
bench() {
do_not_optimize(scannerPr.scan())
do_not_optimize(scannerPr.files)
},
}
})
bench('main (watch, .scan() + .files)', function* () {
yield {
bench() {
do_not_optimize(scannerMain.scan())
do_not_optimize(scannerMain.files)
},
}
})
})
})
await run()
```
#### tailwindcss.com codebase
```
Scanned 462 files
Extracted 13200 candidates
Base = /Users/robin/github.com/tailwindlabs/tailwindcss.com
clk: ~3.09 GHz
cpu: Apple M1 Max
runtime: bun 1.3.3 (arm64-darwin)
```
In these benchmarks the `PR` one is consistently faster than `main`.
It's not by a lot but that's mainly because the codebase itself isn't
that big. It is a codebase with _a lot_ of candidates though, but not
that many files.
The candidate extraction was already pretty fast, so the wins here
mainly come from avoiding re-walking the file system when accessing
`.files`, and from delaying `mtime` tracking until after the initial
scan.
**Single initial build**:
It's not a lot, but it's a bit faster. This is due to avoiding tracking
the `mtime` values initially and making some small optimizations related
to the struct size and allocations.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan())) 22.87 ms/iter 23.28 ms █
(21.49 ms … 25.68 ms) 23.98 ms ▂ ▂ ▂ █ ▂▂
(832.00 kb … 2.69 mb) 1.41 mb ▆▆▆▆█▆▆█▁▆▆█▁▁█▁▆██▁▆
main (build, .scan())) 25.67 ms/iter 26.12 ms █ █ █
(24.54 ms … 27.74 ms) 27.06 ms █ █ █ ███
(432.00 kb … 2.78 mb) 996.00 kb ██▁████▁█▁████▁█▁▁█▁█
┌ ┐
╷ ┌─────┬──┐ ╷
PR (build, .scan())) ├────┤ │ ├─────┤
╵ └─────┴──┘ ╵
╷ ┌─────┬──┐ ╷
main (build, .scan())) ├──┤ │ ├───────┤
╵ └─────┴──┘ ╵
└ ┘
21.49 ms 24.28 ms 27.06 ms
summary
PR (build, .scan()))
1.12x faster than main (build, .scan()))
```
**Single initial build + accessing `.files`**:
We don't have to re-walk the entire file system even if we're just
dealing with ~462 scanned files.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan() + .files) 22.54 ms/iter 22.99 ms █ ▂
(21.41 ms … 25.86 ms) 24.26 ms █ ▅ ▅▅█▅ ▅▅
(368.00 kb … 2.05 mb) 853.00 kb █▇█▇▇████▇▇██▁▁▇▁▁▇▁▇
main (build, .scan() + .files) 32.15 ms/iter 32.17 ms █ ▂
(30.78 ms … 36.22 ms) 35.75 ms ▅█ ▅█ ▅
(400.00 kb … 2.45 mb) 952.00 kb ██▁██▇▇█▇▁▁▁▁▁▁▁▁▁▁▁▇
┌ ┐
╷┌──┬┐ ╷
PR (build, .scan() + .files) ├┤ │├───┤
╵└──┴┘ ╵
╷┌───┬ ╷
main (build, .scan() + .files) ├┤ │──────────┤
╵└───┴ ╵
└ ┘
21.41 ms 28.58 ms 35.75 ms
summary
PR (build, .scan() + .files)
1.43x faster than main (build, .scan() + .files)
```
**Watch/dev mode, only scanning**:
This now switches to the parallel walker, but since it's not a super big
codebase we don't see a huge win here yet.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan())) 6.85 ms/iter 7.22 ms █▄
(6.34 ms … 7.94 ms) 7.91 ms ▄██▃
( 64.00 kb … 688.00 kb) 452.82 kb ▃████▆▂▂▁▂▁▂▁▁▁▅█▆▃▅▃
main (watch, .scan())) 7.92 ms/iter 8.08 ms █ █ ▃ █▃▃
(7.41 ms … 8.71 ms) 8.68 ms █▆█▆▃█████
( 0.00 b … 64.00 kb) 19.20 kb ▆▄██████████▆▁▆▆█▄▄▄▆
┌ ┐
╷ ┌──────┬──────┐ ╷
PR (watch, .scan())) ├──┤ │ ├────────────┤
╵ └──────┴──────┘ ╵
╷ ┌───┬──┐ ╷
main (watch, .scan())) ├────┤ │ ├───────────┤
╵ └───┴──┘ ╵
└ ┘
6.34 ms 7.51 ms 8.68 ms
summary
PR (watch, .scan()))
1.16x faster than main (watch, .scan()))
```
**Watch/dev mode, scanning + accessing `.files`**:
Again we avoid re-walking the entire file system when accessing
`.files`.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan() + .files) 12.10 ms/iter 12.74 ms █ █ █ █ ▃▃▃
(10.69 ms … 13.89 ms) 13.81 ms █ █▂▂▂ ▇█▂█▂███▇
(128.00 kb … 10.73 mb) 5.23 mb █▆████▁█████████▆▆▆▆▆
main (watch, .scan() + .files) 14.44 ms/iter 14.74 ms █
(13.93 ms … 15.33 ms) 15.18 ms ███▅ █ ▅ ▅
( 16.00 kb … 80.00 kb) 39.51 kb █▅████▁███▅▁█████▅▁▅▅
┌ ┐
╷ ┌──────┬──────┐ ╷
PR (watch, .scan() + .files) ├──────┤ │ ├─────────┤
╵ └──────┴──────┘ ╵
╷ ┌───┬──┐ ╷
main (watch, .scan() + .files) ├─┤ │ ├───┤
╵ └───┴──┘ ╵
└ ┘
10.69 ms 12.93 ms 15.18 ms
summary
PR (watch, .scan() + .files)
1.19x faster than main (watch, .scan() + .files)
```
#### Synthetic 5000 files codebase
Based on the instructions from #19616 I created a codebase with 5000
files. Each file contains a `flex` class and a unique class like
`content-['/path/to/file']` to ensure we have a decent amount of unique
candidates.
You can test the script yourself by running this:
```
mkdir -p fixtures/app-5000/src/components/{auth,dashboard,settings,profile,notifications,messages,search,navigation,footer,sidebar}/sub{001..500} && for dir in fixtures/app-5000/src/components/*/sub*; do echo "export const Component = () => test
" > "$dir/index.tsx"; done && find fixtures/app-5000/src/components -type f | wc -lc
```
```
Scanned 5000 files
Extracted 5005 candidates
Base = /Users/robin/github.com/RobinMalfait/playground/scanner-benchmarks/fixtures/app-5000
clk: ~3.08 GHz
cpu: Apple M1 Max
runtime: bun 1.3.3 (arm64-darwin)
```
**Single initial build**:
As expected not a super big win here because it's a single build. But
there is a noticeable improvement.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan())) 217.27 ms/iter 211.97 ms █
(205.99 ms … 289.53 ms) 214.33 ms ▅ ▅ ▅▅▅▅█▅▅ ▅
( 3.34 mb … 4.25 mb) 3.72 mb █▁▁▁▁▁▁█▁███████▁▁▁▁█
main (build, .scan())) 249.26 ms/iter 239.88 ms █
(231.51 ms … 381.66 ms) 241.01 ms ▅ ▅ ▅▅ ▅ █▅ ▅▅▅
( 4.22 mb … 4.78 mb) 4.49 mb █▁▁▁▁█▁██▁▁█▁▁██▁▁███
┌ ┐
╷ ┌─────╷──┬
PR (build, .scan())) ├────┤ ┤ │
╵ └─────╵──┴
╷ ┌───────╷
main (build, .scan())) ├───┤ ┤
╵ └───────╵
└ ┘
205.99 ms 223.50 ms 241.01 ms
summary
PR (build, .scan()))
1.15x faster than main (build, .scan()))
```
**Single initial build + accessing `.files`**:
Now things are getting interesting. Almost a 2x speedup by avoiding
re-walking the file system when accessing `.files`.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (build, .scan() + .files) 216.35 ms/iter 214.53 ms █ █ █
(211.00 ms … 242.64 ms) 221.45 ms █ █▅█ ▅▅ ▅ ▅
( 2.97 mb … 4.47 mb) 3.97 mb █▁███▁██▁▁▁▁▁▁█▁▁▁▁▁█
main (build, .scan() + .files) 414.79 ms/iter 406.05 ms ██
(396.72 ms … 542.30 ms) 413.69 ms ▅ ██▅ ▅▅ ▅ ▅ ▅
( 5.19 mb … 6.03 mb) 5.63 mb █▁▁▁███▁██▁█▁█▁▁▁▁▁▁█
┌ ┐
┌┬╷
PR (build, .scan() + .files) ││┤
└┴╵
╷┌──╷
main (build, .scan() + .files) ├┤ ┤
╵└──╵
└ ┘
211.00 ms 312.34 ms 413.69 ms
summary
PR (build, .scan() + .files)
1.92x faster than main (build, .scan() + .files)
```
**Watch/dev mode, only scanning**:
This is where we see bigger wins because now we're using the parallel
walker.
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan())) 76.26 ms/iter 77.41 ms █
(73.56 ms … 79.02 ms) 77.81 ms ▅ ▅ ▅ ▅▅ ▅▅▅ ▅ █
( 2.53 mb … 5.52 mb) 3.06 mb █▁▁▁█▁▁█▁██▁███▁▁▁█▁█
main (watch, .scan())) 166.71 ms/iter 165.14 ms █ █
(161.49 ms … 198.26 ms) 168.99 ms █ ▅█ ▅▅▅ ▅ ▅ ▅
( 1.08 mb … 2.72 mb) 1.24 mb █▁██▁███▁▁█▁▁█▁▁▁▁▁▁█
┌ ┐
╷┬┐
PR (watch, .scan())) ├││
╵┴┘
╷┌─┬╷
main (watch, .scan())) ├┤ │┤
╵└─┴╵
└ ┘
73.56 ms 121.28 ms 168.99 ms
summary
PR (watch, .scan()))
2.19x faster than main (watch, .scan()))
```
**Watch/dev mode, scanning + accessing `.files`**:
This is the biggest win of them all because we have all the benefits
combined:
1. Avoiding re-walking the file system when accessing `.files`
2. Using the parallel walker for faster file system walking
```
benchmark avg (min … max) p75 / p99 (min … top 1%)
--------------------------------------------- -------------------------------
PR (watch, .scan() + .files) 84.04 ms/iter 84.84 ms █
(80.96 ms … 87.53 ms) 87.27 ms ▅▅ ▅▅ ▅▅ █▅ ▅ ▅
( 15.42 mb … 31.34 mb) 22.16 mb ██▁▁▁██▁██▁██▁█▁▁▁▁▁█
main (watch, .scan() + .files) 338.59 ms/iter 353.89 ms █
(321.87 ms … 378.43 ms) 358.70 ms █ █
( 2.39 mb … 2.45 mb) 2.42 mb ███▁▁██▁▁▁▁▁▁▁▁▁▁██▁█
┌ ┐
┬┐
PR (watch, .scan() + .files) ││
┴┘
┌──┬─┐╷
main (watch, .scan() + .files) │ │ ├┤
└──┴─┘╵
└ ┘
80.96 ms 219.83 ms 358.70 ms
summary
PR (watch, .scan() + .files)
4.03x faster than main (watch, .scan() + .files)
```
## Test plan
1. All existing tests still pass
2. All public APIs remain the same
3. In the benchmarks I'm sharing, I first verify that the candidates
returned and the files returned are the same before and after the
change.
4. Benchmarked against real codebases, and against a synthetic large
codebase (5000 files).
Fixes: #19616
---
CHANGELOG.md | 1 +
crates/oxide/src/cursor.rs | 130 ++---
.../extractor/arbitrary_property_machine.rs | 18 +-
.../src/extractor/arbitrary_value_machine.rs | 12 +-
.../extractor/arbitrary_variable_machine.rs | 22 +-
.../oxide/src/extractor/candidate_machine.rs | 6 +-
.../src/extractor/css_variable_machine.rs | 8 +-
crates/oxide/src/extractor/mod.rs | 8 +-
.../oxide/src/extractor/modifier_machine.rs | 8 +-
.../src/extractor/named_utility_machine.rs | 30 +-
.../src/extractor/named_variant_machine.rs | 20 +-
.../src/extractor/pre_processors/clojure.rs | 30 +-
.../src/extractor/pre_processors/elixir.rs | 14 +-
.../src/extractor/pre_processors/haml.rs | 28 +-
.../src/extractor/pre_processors/json.rs | 4 +-
.../src/extractor/pre_processors/markdown.rs | 2 +-
.../oxide/src/extractor/pre_processors/pug.rs | 12 +-
.../src/extractor/pre_processors/ruby.rs | 27 +-
.../src/extractor/pre_processors/rust.rs | 10 +-
.../src/extractor/pre_processors/slim.rs | 20 +-
.../oxide/src/extractor/pre_processors/vue.rs | 3 +-
crates/oxide/src/extractor/string_machine.rs | 10 +-
crates/oxide/src/extractor/utility_machine.rs | 10 +-
crates/oxide/src/extractor/variant_machine.rs | 4 +-
crates/oxide/src/fast_skip.rs | 2 +-
crates/oxide/src/scanner/detect_sources.rs | 8 +-
crates/oxide/src/scanner/init_tracing.rs | 70 +++
crates/oxide/src/scanner/mod.rs | 541 ++++++++++--------
28 files changed, 579 insertions(+), 479 deletions(-)
create mode 100644 crates/oxide/src/scanner/init_tracing.rs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a549a1232d65..0657008292ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix infinite loop when using `@variant` inside `@custom-variant` ([#19633](https://github.com/tailwindlabs/tailwindcss/pull/19633))
- Allow multiples of `.25` in `aspect-*` fractions ([#19688](https://github.com/tailwindlabs/tailwindcss/pull/19688))
- Ensure changes to external files listed via `@source` trigger a full page reload when using `@tailwindcss/vite` ([#19670](https://github.com/tailwindlabs/tailwindcss/pull/19670))
+- Improve performance Oxide scanner in bigger projects ([#19632](https://github.com/tailwindlabs/tailwindcss/pull/19632))
### Deprecated
diff --git a/crates/oxide/src/cursor.rs b/crates/oxide/src/cursor.rs
index 818a0ef1b450..71cdccdf6aeb 100644
--- a/crates/oxide/src/cursor.rs
+++ b/crates/oxide/src/cursor.rs
@@ -1,44 +1,49 @@
use std::{ascii::escape_default, fmt::Display};
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
pub struct Cursor<'a> {
// The input we're scanning
pub input: &'a [u8],
// The location of the cursor in the input
pub pos: usize,
-
- /// Is the cursor at the start of the input
- pub at_start: bool,
-
- /// Is the cursor at the end of the input
- pub at_end: bool,
-
- /// The previously consumed character
- /// If `at_start` is true, this will be NUL
- pub prev: u8,
-
- /// The current character
- pub curr: u8,
-
- /// The upcoming character (if any)
- /// If `at_end` is true, this will be NUL
- pub next: u8,
}
impl<'a> Cursor<'a> {
+ #[inline(always)]
pub fn new(input: &'a [u8]) -> Self {
- let mut cursor = Self {
- input,
- pos: 0,
- at_start: true,
- at_end: false,
- prev: 0x00,
- curr: 0x00,
- next: 0x00,
- };
- cursor.move_to(0);
- cursor
+ Self { input, pos: 0 }
+ }
+
+ /// The current byte at `pos`, or 0x00 if past the end.
+ #[inline(always)]
+ pub fn curr(&self) -> u8 {
+ if self.pos < self.input.len() {
+ unsafe { *self.input.get_unchecked(self.pos) }
+ } else {
+ 0x00
+ }
+ }
+
+ /// The next byte at `pos + 1`, or 0x00 if past the end.
+ #[inline(always)]
+ pub fn next(&self) -> u8 {
+ let next_pos = self.pos + 1;
+ if next_pos < self.input.len() {
+ unsafe { *self.input.get_unchecked(next_pos) }
+ } else {
+ 0x00
+ }
+ }
+
+ /// The previous byte at `pos - 1`, or 0x00 if at the start.
+ #[inline(always)]
+ pub fn prev(&self) -> u8 {
+ if self.pos > 0 {
+ unsafe { *self.input.get_unchecked(self.pos - 1) }
+ } else {
+ 0x00
+ }
}
pub fn advance_by(&mut self, amount: usize) {
@@ -48,38 +53,15 @@ impl<'a> Cursor<'a> {
#[inline(always)]
pub fn advance(&mut self) {
self.pos += 1;
-
- self.prev = self.curr;
- self.curr = self.next;
- self.next = *self
- .input
- .get(self.pos.saturating_add(1))
- .unwrap_or(&0x00u8);
}
#[inline(always)]
pub fn advance_twice(&mut self) {
self.pos += 2;
-
- self.prev = self.next;
- self.curr = *self.input.get(self.pos).unwrap_or(&0x00u8);
- self.next = *self
- .input
- .get(self.pos.saturating_add(1))
- .unwrap_or(&0x00u8);
}
pub fn move_to(&mut self, pos: usize) {
- let len = self.input.len();
- let pos = pos.clamp(0, len);
-
- self.pos = pos;
- self.at_start = pos == 0;
- self.at_end = pos + 1 >= len;
-
- self.prev = *self.input.get(pos.wrapping_sub(1)).unwrap_or(&0x00u8);
- self.curr = *self.input.get(pos).unwrap_or(&0x00u8);
- self.next = *self.input.get(pos.saturating_add(1)).unwrap_or(&0x00u8);
+ self.pos = pos.min(self.input.len());
}
}
@@ -90,9 +72,9 @@ impl Display for Cursor<'_> {
let pos = format!("{: >len_count$}", self.pos, len_count = len.len());
write!(f, "{}/{} ", pos, len)?;
- if self.at_start {
+ if self.pos == 0 {
write!(f, "S ")?;
- } else if self.at_end {
+ } else if self.pos + 1 >= self.input.len() {
write!(f, "E ")?;
} else {
write!(f, "M ")?;
@@ -109,9 +91,9 @@ impl Display for Cursor<'_> {
write!(
f,
"[{} {} {}]",
- to_str(self.prev),
- to_str(self.curr),
- to_str(self.next)
+ to_str(self.prev()),
+ to_str(self.curr()),
+ to_str(self.next())
)
}
}
@@ -125,36 +107,28 @@ mod test {
fn test_cursor() {
let mut cursor = Cursor::new(b"hello world");
assert_eq!(cursor.pos, 0);
- assert!(cursor.at_start);
- assert!(!cursor.at_end);
- assert_eq!(cursor.prev, 0x00);
- assert_eq!(cursor.curr, b'h');
- assert_eq!(cursor.next, b'e');
+ assert_eq!(cursor.prev(), 0x00);
+ assert_eq!(cursor.curr(), b'h');
+ assert_eq!(cursor.next(), b'e');
cursor.advance_by(1);
assert_eq!(cursor.pos, 1);
- assert!(!cursor.at_start);
- assert!(!cursor.at_end);
- assert_eq!(cursor.prev, b'h');
- assert_eq!(cursor.curr, b'e');
- assert_eq!(cursor.next, b'l');
+ assert_eq!(cursor.prev(), b'h');
+ assert_eq!(cursor.curr(), b'e');
+ assert_eq!(cursor.next(), b'l');
// Advancing too far should stop at the end
cursor.advance_by(10);
assert_eq!(cursor.pos, 11);
- assert!(!cursor.at_start);
- assert!(cursor.at_end);
- assert_eq!(cursor.prev, b'd');
- assert_eq!(cursor.curr, 0x00);
- assert_eq!(cursor.next, 0x00);
+ assert_eq!(cursor.prev(), b'd');
+ assert_eq!(cursor.curr(), 0x00);
+ assert_eq!(cursor.next(), 0x00);
// Can't advance past the end
cursor.advance_by(1);
assert_eq!(cursor.pos, 11);
- assert!(!cursor.at_start);
- assert!(cursor.at_end);
- assert_eq!(cursor.prev, b'd');
- assert_eq!(cursor.curr, 0x00);
- assert_eq!(cursor.next, 0x00);
+ assert_eq!(cursor.prev(), b'd');
+ assert_eq!(cursor.curr(), 0x00);
+ assert_eq!(cursor.next(), 0x00);
}
}
diff --git a/crates/oxide/src/extractor/arbitrary_property_machine.rs b/crates/oxide/src/extractor/arbitrary_property_machine.rs
index 8fd13e39405f..a4325333925c 100644
--- a/crates/oxide/src/extractor/arbitrary_property_machine.rs
+++ b/crates/oxide/src/extractor/arbitrary_property_machine.rs
@@ -74,7 +74,7 @@ impl Machine for ArbitraryPropertyMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Start of an arbitrary property
Class::OpenBracket => {
self.start_pos = cursor.pos;
@@ -97,8 +97,8 @@ impl Machine for ArbitraryPropertyMachine {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Dash => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Dash => match cursor.next().into() {
// Start of a CSS variable
//
// E.g.: `[--my-color:red]`
@@ -137,7 +137,7 @@ impl ArbitraryPropertyMachine {
fn parse_property_variable(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.css_variable_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// End of the CSS variable, must be followed by a `:`
//
// E.g.: `[--my-color:red]`
@@ -165,8 +165,8 @@ impl Machine for ArbitraryPropertyMachine {
let len = cursor.input.len();
let start_of_value_pos = cursor.pos;
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Escape => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Escape => match cursor.next().into() {
// An escaped whitespace character is not allowed
//
// E.g.: `[color:var(--my-\ color)]`
@@ -181,7 +181,7 @@ impl Machine for ArbitraryPropertyMachine {
},
Class::OpenParen | Class::OpenBracket | Class::OpenCurly => {
- if !self.bracket_stack.push(cursor.curr) {
+ if !self.bracket_stack.push(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -190,7 +190,7 @@ impl Machine for ArbitraryPropertyMachine {
Class::CloseParen | Class::CloseBracket | Class::CloseCurly
if !self.bracket_stack.is_empty() =>
{
- if !self.bracket_stack.pop(cursor.curr) {
+ if !self.bracket_stack.pop(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -227,7 +227,7 @@ impl Machine for ArbitraryPropertyMachine {
Class::Slash if start_of_value_pos == cursor.pos => return self.restart(),
// String interpolation-like syntax is not allowed. E.g.: `[${x}]`
- Class::Dollar if matches!(cursor.next.into(), Class::OpenCurly) => {
+ Class::Dollar if matches!(cursor.next().into(), Class::OpenCurly) => {
return self.restart()
}
diff --git a/crates/oxide/src/extractor/arbitrary_value_machine.rs b/crates/oxide/src/extractor/arbitrary_value_machine.rs
index f5a612df13f2..cbef62c42681 100644
--- a/crates/oxide/src/extractor/arbitrary_value_machine.rs
+++ b/crates/oxide/src/extractor/arbitrary_value_machine.rs
@@ -32,7 +32,7 @@ impl Machine for ArbitraryValueMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
// An arbitrary value must start with an open bracket
- if Class::OpenBracket != cursor.curr.into() {
+ if Class::OpenBracket != cursor.curr().into() {
return MachineState::Idle;
}
@@ -42,8 +42,8 @@ impl Machine for ArbitraryValueMachine {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Escape => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Escape => match cursor.next().into() {
// An escaped whitespace character is not allowed
//
// E.g.: `[color:var(--my-\ color)]`
@@ -61,7 +61,7 @@ impl Machine for ArbitraryValueMachine {
},
Class::OpenParen | Class::OpenBracket | Class::OpenCurly => {
- if !self.bracket_stack.push(cursor.curr) {
+ if !self.bracket_stack.push(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -70,7 +70,7 @@ impl Machine for ArbitraryValueMachine {
Class::CloseParen | Class::CloseBracket | Class::CloseCurly
if !self.bracket_stack.is_empty() =>
{
- if !self.bracket_stack.pop(cursor.curr) {
+ if !self.bracket_stack.pop(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -96,7 +96,7 @@ impl Machine for ArbitraryValueMachine {
Class::Whitespace => return self.restart(),
// String interpolation-like syntax is not allowed. E.g.: `[${x}]`
- Class::Dollar if matches!(cursor.next.into(), Class::OpenCurly) => {
+ Class::Dollar if matches!(cursor.next().into(), Class::OpenCurly) => {
return self.restart()
}
diff --git a/crates/oxide/src/extractor/arbitrary_variable_machine.rs b/crates/oxide/src/extractor/arbitrary_variable_machine.rs
index 6990e110b087..e8d4755571c7 100644
--- a/crates/oxide/src/extractor/arbitrary_variable_machine.rs
+++ b/crates/oxide/src/extractor/arbitrary_variable_machine.rs
@@ -80,13 +80,13 @@ impl Machine for ArbitraryVariableMachine {
#[inline(always)]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Arbitrary variables start with `(` followed by a CSS variable
//
// E.g.: `(--my-variable)`
// ^^
//
- Class::OpenParen => match cursor.next.into() {
+ Class::OpenParen => match cursor.next().into() {
Class::Dash => {
self.start_pos = cursor.pos;
cursor.advance();
@@ -117,7 +117,7 @@ impl Machine for ArbitraryVariableMachine {
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.css_variable_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// A CSS variable followed by a `,` means that there is a fallback
//
// E.g.: `(--my-color,red)`
@@ -134,7 +134,7 @@ impl Machine for ArbitraryVariableMachine {
_ => {
cursor.advance();
- match cursor.curr.into() {
+ match cursor.curr().into() {
// End of an arbitrary variable, must be followed by `)`
Class::CloseParen => self.done(self.start_pos, cursor),
@@ -156,7 +156,7 @@ impl Machine for ArbitraryVariableMachine {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Valid data type characters
//
// E.g.: `(length:--my-length)`
@@ -169,7 +169,7 @@ impl Machine for ArbitraryVariableMachine {
//
// E.g.: `(length:--my-length)`
// ^
- Class::Colon => match cursor.next.into() {
+ Class::Colon => match cursor.next().into() {
Class::Dash => {
cursor.advance();
return self.transition::().next(cursor);
@@ -196,8 +196,8 @@ impl Machine for ArbitraryVariableMachine {
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Escape => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Escape => match cursor.next().into() {
// An escaped whitespace character is not allowed
//
// E.g.: `(--my-\ color)`
@@ -212,7 +212,7 @@ impl Machine for ArbitraryVariableMachine {
},
Class::OpenParen | Class::OpenBracket | Class::OpenCurly => {
- if !self.bracket_stack.push(cursor.curr) {
+ if !self.bracket_stack.push(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -221,7 +221,7 @@ impl Machine for ArbitraryVariableMachine {
Class::CloseParen | Class::CloseBracket | Class::CloseCurly
if !self.bracket_stack.is_empty() =>
{
- if !self.bracket_stack.pop(cursor.curr) {
+ if !self.bracket_stack.pop(cursor.curr()) {
return self.restart();
}
cursor.advance();
@@ -253,7 +253,7 @@ impl Machine for ArbitraryVariableMachine {
Class::Whitespace => return self.restart(),
// String interpolation-like syntax is not allowed. E.g.: `[${x}]`
- Class::Dollar if matches!(cursor.next.into(), Class::OpenCurly) => {
+ Class::Dollar if matches!(cursor.next().into(), Class::OpenCurly) => {
return self.restart()
}
diff --git a/crates/oxide/src/extractor/candidate_machine.rs b/crates/oxide/src/extractor/candidate_machine.rs
index c82cc3707993..a755cf02a2b5 100644
--- a/crates/oxide/src/extractor/candidate_machine.rs
+++ b/crates/oxide/src/extractor/candidate_machine.rs
@@ -32,14 +32,14 @@ impl Machine for CandidateMachine {
while cursor.pos < len {
// Skip ahead for known characters that will never be part of a candidate. No need to
// run any sub-machines.
- if cursor.curr.is_ascii_whitespace() {
+ if cursor.curr().is_ascii_whitespace() {
self.reset();
cursor.advance();
continue;
}
// Candidates don't start with these characters, so we can skip ahead.
- if matches!(cursor.curr, b':' | b'"' | b'\'' | b'`') {
+ if matches!(cursor.curr(), b':' | b'"' | b'\'' | b'`') {
self.reset();
cursor.advance();
continue;
@@ -56,7 +56,7 @@ impl Machine for CandidateMachine {
// E.g.: `Some Class`
// ^ ^ Invalid, we can jump ahead to the next boundary
//
- if matches!(cursor.curr, b'<' | b'A'..=b'Z') {
+ if matches!(cursor.curr(), b'<' | b'A'..=b'Z') {
if let Some(offset) = cursor.input[cursor.pos..]
.iter()
.position(|&c| is_valid_before_boundary(&c))
diff --git a/crates/oxide/src/extractor/css_variable_machine.rs b/crates/oxide/src/extractor/css_variable_machine.rs
index 4e19c7111f5d..7beb827ee84b 100644
--- a/crates/oxide/src/extractor/css_variable_machine.rs
+++ b/crates/oxide/src/extractor/css_variable_machine.rs
@@ -20,7 +20,7 @@ impl Machine for CssVariableMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
// CSS Variables must start with `--`
- if Class::Dash != cursor.curr.into() || Class::Dash != cursor.next.into() {
+ if Class::Dash != cursor.curr().into() || Class::Dash != cursor.next().into() {
return MachineState::Idle;
}
@@ -30,11 +30,11 @@ impl Machine for CssVariableMachine {
cursor.advance_twice();
while cursor.pos < len {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
//
Class::AllowedCharacter | Class::Dash => {
- match cursor.next.into() {
+ match cursor.next().into() {
// Valid character followed by a valid character or an escape character
//
// E.g.: `--my-variable`
@@ -58,7 +58,7 @@ impl Machine for CssVariableMachine {
}
}
- Class::Escape => match cursor.next.into() {
+ Class::Escape => match cursor.next().into() {
// An escaped whitespace character is not allowed
//
// In CSS it is allowed, but in the context of a class it's not because then we
diff --git a/crates/oxide/src/extractor/mod.rs b/crates/oxide/src/extractor/mod.rs
index add0de4acaca..a37d6a0a49b3 100644
--- a/crates/oxide/src/extractor/mod.rs
+++ b/crates/oxide/src/extractor/mod.rs
@@ -86,7 +86,7 @@ impl<'a> Extractor<'a> {
{
let cursor = &mut self.cursor.clone();
while cursor.pos < len {
- if cursor.curr.is_ascii_whitespace() {
+ if cursor.curr().is_ascii_whitespace() {
cursor.advance();
continue;
}
@@ -104,7 +104,7 @@ impl<'a> Extractor<'a> {
let cursor = &mut self.cursor.clone();
while cursor.pos < len {
- if cursor.curr.is_ascii_whitespace() {
+ if cursor.curr().is_ascii_whitespace() {
cursor.advance();
continue;
}
@@ -147,7 +147,7 @@ impl<'a> Extractor<'a> {
let cursor = &mut self.cursor.clone();
while cursor.pos < len {
- if cursor.curr.is_ascii_whitespace() {
+ if cursor.curr().is_ascii_whitespace() {
cursor.advance();
continue;
}
@@ -238,7 +238,7 @@ mod tests {
use std::hint::black_box;
fn pre_process_input(input: &str, extension: &str) -> String {
- let input = crate::scanner::pre_process_input(input.as_bytes(), extension);
+ let input = crate::scanner::pre_process_input(input.as_bytes().to_vec(), extension);
String::from_utf8(input).unwrap()
}
diff --git a/crates/oxide/src/extractor/modifier_machine.rs b/crates/oxide/src/extractor/modifier_machine.rs
index 22668a828749..811bc9ded9e0 100644
--- a/crates/oxide/src/extractor/modifier_machine.rs
+++ b/crates/oxide/src/extractor/modifier_machine.rs
@@ -31,14 +31,14 @@ impl Machine for ModifierMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
// A modifier must start with a `/`, everything else is not a valid start of a modifier
- if Class::Slash != cursor.curr.into() {
+ if Class::Slash != cursor.curr().into() {
return MachineState::Idle;
}
let start_pos = cursor.pos;
cursor.advance();
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Start of an arbitrary value:
//
// ```
@@ -70,9 +70,9 @@ impl Machine for ModifierMachine {
Class::ValidStart => {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
+ match cursor.curr().into() {
Class::ValidStart | Class::ValidInside => {
- match cursor.next.into() {
+ match cursor.next().into() {
// Only valid characters are allowed, if followed by another valid character
Class::ValidStart | Class::ValidInside => cursor.advance(),
diff --git a/crates/oxide/src/extractor/named_utility_machine.rs b/crates/oxide/src/extractor/named_utility_machine.rs
index d218dbeb7a9b..24dc027b2d69 100644
--- a/crates/oxide/src/extractor/named_utility_machine.rs
+++ b/crates/oxide/src/extractor/named_utility_machine.rs
@@ -52,8 +52,8 @@ impl Machine for NamedUtilityMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
- Class::AlphaLower => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::AlphaLower => match cursor.next().into() {
// Valid single character utility in between quotes
//
// E.g.: `
`
@@ -90,7 +90,7 @@ impl Machine for NamedUtilityMachine {
//
// E.g.: `-mx-2.5`
// ^^
- Class::Dash => match cursor.next.into() {
+ Class::Dash => match cursor.next().into() {
Class::AlphaLower => {
self.start_pos = cursor.pos;
cursor.advance();
@@ -118,7 +118,7 @@ impl Machine for NamedUtilityMachine {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Followed by a boundary character, we are at the end of the utility.
//
// E.g.: `'flex'`
@@ -132,14 +132,14 @@ impl Machine for NamedUtilityMachine {
// E.g.: `:div="{ flex: true }"` (JavaScript object syntax)
// ^
Class::AlphaLower | Class::AlphaUpper => {
- if is_valid_after_boundary(&cursor.next) || {
+ if is_valid_after_boundary(&cursor.next()) || {
// Or any of these characters
//
// - `:`, because of JS object keys
// - `/`, because of modifiers
// - `!`, because of important
matches!(
- cursor.next.into(),
+ cursor.next().into(),
Class::Colon | Class::Slash | Class::Exclamation
)
} {
@@ -150,7 +150,7 @@ impl Machine for NamedUtilityMachine {
cursor.advance()
}
- Class::Dash => match cursor.next.into() {
+ Class::Dash => match cursor.next().into() {
// Start of an arbitrary value
//
// E.g.: `bg-[#0088cc]`
@@ -196,7 +196,7 @@ impl Machine for NamedUtilityMachine {
_ => return self.restart(),
},
- Class::Underscore => match cursor.next.into() {
+ Class::Underscore => match cursor.next().into() {
// Valid characters _if_ followed by another valid character. These characters are
// only valid inside of the utility but not at the end of the utility.
//
@@ -225,14 +225,14 @@ impl Machine for NamedUtilityMachine {
// ^
// E.g.: `:div="{ flex: true }"` (JavaScript object syntax)
// ^
- _ if is_valid_after_boundary(&cursor.next) || {
+ _ if is_valid_after_boundary(&cursor.next()) || {
// Or any of these characters
//
// - `:`, because of JS object keys
// - `/`, because of modifiers
// - `!`, because of important
matches!(
- cursor.next.into(),
+ cursor.next().into(),
Class::Colon | Class::Slash | Class::Exclamation
)
} =>
@@ -249,11 +249,11 @@ impl Machine for NamedUtilityMachine {
// E.g.: `px-2.5`
// ^^^
Class::Dot => {
- if !matches!(cursor.prev.into(), Class::Number) {
+ if !matches!(cursor.prev().into(), Class::Number) {
return self.restart();
}
- if !matches!(cursor.next.into(), Class::Number) {
+ if !matches!(cursor.next().into(), Class::Number) {
return self.restart();
}
@@ -278,7 +278,7 @@ impl Machine for NamedUtilityMachine {
//
Class::Number => {
if !matches!(
- cursor.prev.into(),
+ cursor.prev().into(),
Class::Dash
| Class::Underscore
| Class::Dot
@@ -290,7 +290,7 @@ impl Machine for NamedUtilityMachine {
}
if !matches!(
- cursor.next.into(),
+ cursor.next().into(),
Class::Dot
| Class::Number
| Class::AlphaLower
@@ -314,7 +314,7 @@ impl Machine for NamedUtilityMachine {
// ^^
// ```
Class::Percent => {
- if !matches!(cursor.prev.into(), Class::Number) {
+ if !matches!(cursor.prev().into(), Class::Number) {
return self.restart();
}
diff --git a/crates/oxide/src/extractor/named_variant_machine.rs b/crates/oxide/src/extractor/named_variant_machine.rs
index b6de8220b4cb..285fe6ab51a6 100644
--- a/crates/oxide/src/extractor/named_variant_machine.rs
+++ b/crates/oxide/src/extractor/named_variant_machine.rs
@@ -81,8 +81,8 @@ impl Machine for NamedVariantMachine {
#[inline(always)]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
- Class::AlphaLower | Class::Star => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::AlphaLower | Class::Star => match cursor.next().into() {
// Valid single character variant, must be followed by a `:`
//
// E.g.: `
`
@@ -134,8 +134,8 @@ impl Machine for NamedVariantMachine {
let len = cursor.input.len();
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Dash => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Dash => match cursor.next().into() {
// Start of an arbitrary value
//
// E.g.: `data-[state=pending]:`.
@@ -192,7 +192,7 @@ impl Machine for NamedVariantMachine {
};
}
- Class::Underscore => match cursor.next.into() {
+ Class::Underscore => match cursor.next().into() {
// Valid characters _if_ followed by another valid character. These characters are
// only valid inside of the variant but not at the end of the variant.
//
@@ -240,11 +240,11 @@ impl Machine for NamedVariantMachine {
// E.g.: `2.5xl:flex`
// ^^^
Class::Dot => {
- if !matches!(cursor.prev.into(), Class::Number) {
+ if !matches!(cursor.prev().into(), Class::Number) {
return self.restart();
}
- if !matches!(cursor.next.into(), Class::Number) {
+ if !matches!(cursor.next().into(), Class::Number) {
return self.restart();
}
@@ -263,7 +263,7 @@ impl Machine for NamedVariantMachine {
impl NamedVariantMachine {
#[inline(always)]
fn parse_arbitrary_end(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.next.into() {
+ match cursor.next().into() {
Class::Slash => {
cursor.advance();
self.transition::().next(cursor)
@@ -285,7 +285,7 @@ impl Machine for NamedVariantMachine {
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.modifier_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// Modifier must be followed by a `:`
//
// E.g.: `group-hover/name:`
@@ -308,7 +308,7 @@ impl Machine for NamedVariantMachine {
#[inline(always)]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// The end of a variant must be the `:`
//
// E.g.: `hover:`
diff --git a/crates/oxide/src/extractor/pre_processors/clojure.rs b/crates/oxide/src/extractor/pre_processors/clojure.rs
index ecf02b4ff634..3fb4ce601cd6 100644
--- a/crates/oxide/src/extractor/pre_processors/clojure.rs
+++ b/crates/oxide/src/extractor/pre_processors/clojure.rs
@@ -32,14 +32,14 @@ impl PreProcessor for Clojure {
let mut cursor = cursor::Cursor::new(&content);
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Consume strings as-is
b'"' => {
result[cursor.pos] = b' ';
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
@@ -57,8 +57,8 @@ impl PreProcessor for Clojure {
// Discard line comments until the end of the line.
// Comments start with `;;`
- b';' if matches!(cursor.next, b';') => {
- while cursor.pos < len && cursor.curr != b'\n' {
+ b';' if matches!(cursor.next(), b';') => {
+ while cursor.pos < len && cursor.curr() != b'\n' {
result[cursor.pos] = b' ';
cursor.advance();
}
@@ -70,7 +70,7 @@ impl PreProcessor for Clojure {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// A `.` surrounded by digits is a decimal number, so we don't want to replace it.
//
// E.g.:
@@ -78,8 +78,8 @@ impl PreProcessor for Clojure {
// gap-1.5
// ^
// ```
- b'.' if cursor.prev.is_ascii_digit()
- && cursor.next.is_ascii_digit() =>
+ b'.' if cursor.prev().is_ascii_digit()
+ && cursor.next().is_ascii_digit() =>
{
// Keep the `.` as-is
}
@@ -95,7 +95,7 @@ impl PreProcessor for Clojure {
result[cursor.pos] = b' ';
}
// End of keyword.
- _ if !is_keyword_character(cursor.curr) => {
+ _ if !is_keyword_character(cursor.curr()) => {
result[cursor.pos] = b' ';
break;
}
@@ -110,11 +110,11 @@ impl PreProcessor for Clojure {
// Handle quote with a list, e.g.: `'(…)`
// and with a vector, e.g.: `'[…]`
- b'\'' if matches!(cursor.next, b'[' | b'(') => {
+ b'\'' if matches!(cursor.next(), b'[' | b'(') => {
result[cursor.pos] = b' ';
cursor.advance();
result[cursor.pos] = b' ';
- let end = match cursor.curr {
+ let end = match cursor.curr() {
b'[' => b']',
b'(' => b')',
_ => unreachable!(),
@@ -122,7 +122,7 @@ impl PreProcessor for Clojure {
// Consume until the closing `]`
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
x if x == end => {
result[cursor.pos] = b' ';
break;
@@ -134,7 +134,7 @@ impl PreProcessor for Clojure {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
@@ -157,14 +157,14 @@ impl PreProcessor for Clojure {
}
// Handle quote with a keyword, e.g.: `'bg-white`
- b'\'' if !cursor.next.is_ascii_whitespace() => {
+ b'\'' if !cursor.next().is_ascii_whitespace() => {
result[cursor.pos] = b' ';
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// End of keyword.
- _ if !is_keyword_character(cursor.curr) => {
+ _ if !is_keyword_character(cursor.curr()) => {
result[cursor.pos] = b' ';
break;
}
diff --git a/crates/oxide/src/extractor/pre_processors/elixir.rs b/crates/oxide/src/extractor/pre_processors/elixir.rs
index 87b89a2a9dda..7737a6b2d1ae 100644
--- a/crates/oxide/src/extractor/pre_processors/elixir.rs
+++ b/crates/oxide/src/extractor/pre_processors/elixir.rs
@@ -13,13 +13,13 @@ impl PreProcessor for Elixir {
while cursor.pos < content.len() {
// Look for a sigil marker
- if cursor.curr != b'~' {
+ if cursor.curr() != b'~' {
cursor.advance();
continue;
}
// Scan charlists, strings, and wordlists
- if !matches!(cursor.next, b'c' | b'C' | b's' | b'S' | b'w' | b'W') {
+ if !matches!(cursor.next(), b'c' | b'C' | b's' | b'S' | b'w' | b'W') {
cursor.advance();
continue;
}
@@ -27,7 +27,7 @@ impl PreProcessor for Elixir {
cursor.advance_twice();
// Match the opening for a sigil
- if !matches!(cursor.curr, b'(' | b'[' | b'{') {
+ if !matches!(cursor.curr(), b'(' | b'[' | b'{') {
continue;
}
@@ -35,19 +35,19 @@ impl PreProcessor for Elixir {
result[cursor.pos] = b' ';
// Scan until we find a balanced closing one and replace it too
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
while cursor.pos < content.len() {
cursor.advance();
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
b'(' | b'[' | b'{' => {
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b')' | b']' | b'}' if !bracket_stack.is_empty() => {
- bracket_stack.pop(cursor.curr);
+ bracket_stack.pop(cursor.curr());
if bracket_stack.is_empty() {
// Replace the closing bracket with a space
diff --git a/crates/oxide/src/extractor/pre_processors/haml.rs b/crates/oxide/src/extractor/pre_processors/haml.rs
index a131618abe66..99b7bd052302 100644
--- a/crates/oxide/src/extractor/pre_processors/haml.rs
+++ b/crates/oxide/src/extractor/pre_processors/haml.rs
@@ -101,7 +101,7 @@ impl PreProcessor for Haml {
let mut last_newline_position = 0;
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escape the next character
b'\\' => {
cursor.advance_twice();
@@ -119,7 +119,7 @@ impl PreProcessor for Haml {
b'-' if cursor.input[last_newline_position..cursor.pos]
.iter()
.all(u8::is_ascii_whitespace)
- && matches!(cursor.next, b'#') =>
+ && matches!(cursor.next(), b'#') =>
{
// Just consume the comment
let updated_last_newline_position =
@@ -159,7 +159,7 @@ impl PreProcessor for Haml {
// Override the last known newline position
last_newline_position = end;
- let replaced = pre_process_input(ruby_code, "rb");
+ let replaced = pre_process_input(ruby_code.to_vec(), "rb");
result.replace_range(start..end, replaced);
}
@@ -190,7 +190,7 @@ impl PreProcessor for Haml {
// digit.
// E.g.: `bg-red-500.2xl:flex`
// ^^^
- if cursor.prev.is_ascii_digit() && cursor.next.is_ascii_digit() {
+ if cursor.prev().is_ascii_digit() && cursor.next().is_ascii_digit() {
let mut next_cursor = cursor.clone();
next_cursor.advance();
@@ -213,11 +213,11 @@ impl PreProcessor for Haml {
if bracket_stack.is_empty() {
result[cursor.pos] = b' ';
}
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b')' | b']' | b'}' if !bracket_stack.is_empty() => {
- bracket_stack.pop(cursor.curr);
+ bracket_stack.pop(cursor.curr());
// Replace closing bracket with a space
if bracket_stack.is_empty() {
@@ -257,7 +257,7 @@ impl Haml {
// :url => { :action => "add", :id => product.id },
// :update => { :success => "cart", :failure => "error" }
// ```
- let evaluation_type = cursor.curr;
+ let evaluation_type = cursor.curr();
let block_indentation_level = cursor
.pos
@@ -267,17 +267,17 @@ impl Haml {
let mut last_newline_position = last_known_newline_position;
// Consume until the end of the line first
- while cursor.pos < len && cursor.curr != b'\n' {
+ while cursor.pos < len && cursor.curr() != b'\n' {
cursor.advance();
}
// Block is already done, aka just a line
- if evaluation_type == b'=' && cursor.prev != b',' {
+ if evaluation_type == b'=' && cursor.prev() != b',' {
return cursor.pos;
}
'outer: while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escape the next character
b'\\' => {
cursor.advance_twice();
@@ -289,7 +289,7 @@ impl Haml {
last_newline_position = cursor.pos;
// We are done with this block
- if evaluation_type == b'=' && cursor.prev != b',' {
+ if evaluation_type == b'=' && cursor.prev() != b',' {
break;
}
@@ -300,11 +300,11 @@ impl Haml {
// Skip whitespace and compute the indentation level
x if x.is_ascii_whitespace() => {
// Find first non-whitespace character
- while cursor.pos < len && cursor.curr.is_ascii_whitespace() {
- if cursor.curr == b'\n' {
+ while cursor.pos < len && cursor.curr().is_ascii_whitespace() {
+ if cursor.curr() == b'\n' {
last_newline_position = cursor.pos;
- if evaluation_type == b'=' && cursor.prev != b',' {
+ if evaluation_type == b'=' && cursor.prev() != b',' {
// We are done with this block
break 'outer;
}
diff --git a/crates/oxide/src/extractor/pre_processors/json.rs b/crates/oxide/src/extractor/pre_processors/json.rs
index 809eb501e679..cd457050c5fc 100644
--- a/crates/oxide/src/extractor/pre_processors/json.rs
+++ b/crates/oxide/src/extractor/pre_processors/json.rs
@@ -11,13 +11,13 @@ impl PreProcessor for Json {
let mut cursor = cursor::Cursor::new(content);
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Consume strings as-is
b'"' => {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
diff --git a/crates/oxide/src/extractor/pre_processors/markdown.rs b/crates/oxide/src/extractor/pre_processors/markdown.rs
index 63dc37d1eb4b..d2acc6a58738 100644
--- a/crates/oxide/src/extractor/pre_processors/markdown.rs
+++ b/crates/oxide/src/extractor/pre_processors/markdown.rs
@@ -13,7 +13,7 @@ impl PreProcessor for Markdown {
let mut in_directive = false;
while cursor.pos < len {
- match (in_directive, cursor.curr) {
+ match (in_directive, cursor.curr()) {
(false, b'{') => {
result[cursor.pos] = b' ';
in_directive = true;
diff --git a/crates/oxide/src/extractor/pre_processors/pug.rs b/crates/oxide/src/extractor/pre_processors/pug.rs
index 7b44fcf5be04..70dfe5683197 100644
--- a/crates/oxide/src/extractor/pre_processors/pug.rs
+++ b/crates/oxide/src/extractor/pre_processors/pug.rs
@@ -15,7 +15,7 @@ impl PreProcessor for Pug {
let mut bracket_stack = BracketStack::default();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Only replace `.` with a space if it's not surrounded by numbers. E.g.:
//
// ```diff
@@ -43,7 +43,7 @@ impl PreProcessor for Pug {
// digit.
// E.g.: `bg-red-500.2xl:flex`
// ^^^
- if cursor.prev.is_ascii_digit() && cursor.next.is_ascii_digit() {
+ if cursor.prev().is_ascii_digit() && cursor.next().is_ascii_digit() {
let mut next_cursor = cursor.clone();
next_cursor.advance();
@@ -68,17 +68,17 @@ impl PreProcessor for Pug {
//
// However, we also need to make sure that we keep the parens that are part of the
// utility class. E.g.: `bg-(--my-color)`.
- b'(' if bracket_stack.is_empty() && !matches!(cursor.prev, b'-' | b'/') => {
+ b'(' if bracket_stack.is_empty() && !matches!(cursor.prev(), b'-' | b'/') => {
result[cursor.pos] = b' ';
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b'(' | b'[' | b'{' => {
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b')' | b']' | b'}' if !bracket_stack.is_empty() => {
- bracket_stack.pop(cursor.curr);
+ bracket_stack.pop(cursor.curr());
}
// Consume everything else
diff --git a/crates/oxide/src/extractor/pre_processors/ruby.rs b/crates/oxide/src/extractor/pre_processors/ruby.rs
index 89ac1ee7b1c6..1f2221414ff4 100644
--- a/crates/oxide/src/extractor/pre_processors/ruby.rs
+++ b/crates/oxide/src/extractor/pre_processors/ruby.rs
@@ -68,7 +68,8 @@ impl PreProcessor for Ruby {
}
let body = &content_as_str[body_start..body_end];
- let replaced = pre_process_input(body.as_bytes(), &lang.to_ascii_lowercase());
+ let replaced =
+ pre_process_input(body.as_bytes().to_vec(), &lang.to_ascii_lowercase());
result.replace_range(body_start..body_end, replaced);
break;
@@ -77,12 +78,12 @@ impl PreProcessor for Ruby {
// Ruby extraction
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
b'"' => {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
@@ -102,7 +103,7 @@ impl PreProcessor for Ruby {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
@@ -123,12 +124,12 @@ impl PreProcessor for Ruby {
// Except for strict locals, these are defined in a `<%# locals: … %>`. Checking if
// the comment is preceded by a `%` should be enough without having to perform more
// parsing logic. Worst case we _do_ scan a few comments.
- b'#' if !matches!(cursor.prev, b'%') => {
+ b'#' if !matches!(cursor.prev(), b'%') => {
result[cursor.pos] = b' ';
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// End of the comment
b'\n' => break,
@@ -148,7 +149,7 @@ impl PreProcessor for Ruby {
}
// Looking for `%w`, `%W`, or `%p`
- if cursor.curr != b'%' || !matches!(cursor.next, b'w' | b'W' | b'p') {
+ if cursor.curr() != b'%' || !matches!(cursor.next(), b'w' | b'W' | b'p') {
cursor.advance();
continue;
}
@@ -156,7 +157,7 @@ impl PreProcessor for Ruby {
cursor.advance_twice();
// Boundary character
- let boundary = match cursor.curr {
+ let boundary = match cursor.curr() {
b'[' => b']',
b'(' => b')',
b'{' => b'}',
@@ -177,11 +178,11 @@ impl PreProcessor for Ruby {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Skip escaped characters
b'\\' => {
// Use backslash to embed spaces in the strings.
- if cursor.next == b' ' {
+ if cursor.next() == b' ' {
result[cursor.pos] = b' ';
}
@@ -190,19 +191,19 @@ impl PreProcessor for Ruby {
// Start of a nested bracket
b'[' | b'(' | b'{' => {
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
// End of a nested bracket
b']' | b')' | b'}' if !bracket_stack.is_empty() => {
- if !bracket_stack.pop(cursor.curr) {
+ if !bracket_stack.pop(cursor.curr()) {
// Unbalanced
cursor.advance();
}
}
// End of the pattern, replace the boundary character with a space
- _ if cursor.curr == boundary => {
+ _ if cursor.curr() == boundary => {
if boundary != b'\n' {
result[cursor.pos] = b' ';
}
diff --git a/crates/oxide/src/extractor/pre_processors/rust.rs b/crates/oxide/src/extractor/pre_processors/rust.rs
index 6404fffb5e29..34c9e0c916b7 100644
--- a/crates/oxide/src/extractor/pre_processors/rust.rs
+++ b/crates/oxide/src/extractor/pre_processors/rust.rs
@@ -33,7 +33,7 @@ impl Rust {
let mut bracket_stack = bracket_stack::BracketStack::default();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => {
cursor.advance_twice();
@@ -46,7 +46,7 @@ impl Rust {
cursor.advance();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),
@@ -89,7 +89,7 @@ impl Rust {
// digit.
// E.g.: `bg-red-500.2xl:flex`
// ^^^
- if cursor.prev.is_ascii_digit() && cursor.next.is_ascii_digit() {
+ if cursor.prev().is_ascii_digit() && cursor.next().is_ascii_digit() {
let mut next_cursor = cursor.clone();
next_cursor.advance();
@@ -103,11 +103,11 @@ impl Rust {
}
b'[' => {
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b']' if !bracket_stack.is_empty() => {
- bracket_stack.pop(cursor.curr);
+ bracket_stack.pop(cursor.curr());
}
// Consume everything else
diff --git a/crates/oxide/src/extractor/pre_processors/slim.rs b/crates/oxide/src/extractor/pre_processors/slim.rs
index 6d41e5a09b72..eacfb55eedfd 100644
--- a/crates/oxide/src/extractor/pre_processors/slim.rs
+++ b/crates/oxide/src/extractor/pre_processors/slim.rs
@@ -15,7 +15,7 @@ impl PreProcessor for Slim {
let mut bracket_stack = BracketStack::default();
while cursor.pos < len {
- match cursor.curr {
+ match cursor.curr() {
// Only replace `.` with a space if it's not surrounded by numbers. E.g.:
//
// ```diff
@@ -43,7 +43,7 @@ impl PreProcessor for Slim {
// digit.
// E.g.: `bg-red-500.2xl:flex`
// ^^^
- if cursor.prev.is_ascii_digit() && cursor.next.is_ascii_digit() {
+ if cursor.prev().is_ascii_digit() && cursor.next().is_ascii_digit() {
let mut next_cursor = cursor.clone();
next_cursor.advance();
@@ -65,7 +65,7 @@ impl PreProcessor for Slim {
// class=%w[bg-blue-500 w-10 h-10]
// ]
// ```
- b'%' if matches!(cursor.next, b'w' | b'W')
+ b'%' if matches!(cursor.next(), b'w' | b'W')
&& matches!(cursor.input.get(cursor.pos + 2), Some(b'[' | b'(' | b'{')) =>
{
result[cursor.pos] = b' '; // Replace `%`
@@ -73,7 +73,7 @@ impl PreProcessor for Slim {
result[cursor.pos] = b' '; // Replace `w`
cursor.advance();
result[cursor.pos] = b' '; // Replace `[` or `(` or `{`
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
cursor.advance(); // Move past the bracket
continue;
}
@@ -96,10 +96,10 @@ impl PreProcessor for Slim {
// Instead of listing all boundary characters, let's list the characters we know
// will be invalid instead.
b'[' if bracket_stack.is_empty()
- && matches!(cursor.prev, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') =>
+ && matches!(cursor.prev(), b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') =>
{
result[cursor.pos] = b' ';
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
// In Slim the class name shorthand can be followed by a parenthesis. E.g.:
@@ -114,17 +114,17 @@ impl PreProcessor for Slim {
//
// However, we also need to make sure that we keep the parens that are part of the
// utility class. E.g.: `bg-(--my-color)`.
- b'(' if bracket_stack.is_empty() && !matches!(cursor.prev, b'-' | b'/') => {
+ b'(' if bracket_stack.is_empty() && !matches!(cursor.prev(), b'-' | b'/') => {
result[cursor.pos] = b' ';
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b'(' | b'[' | b'{' => {
- bracket_stack.push(cursor.curr);
+ bracket_stack.push(cursor.curr());
}
b')' | b']' | b'}' if !bracket_stack.is_empty() => {
- bracket_stack.pop(cursor.curr);
+ bracket_stack.pop(cursor.curr());
}
// Consume everything else
diff --git a/crates/oxide/src/extractor/pre_processors/vue.rs b/crates/oxide/src/extractor/pre_processors/vue.rs
index 119e2a3d2079..1b9bf1668cb4 100644
--- a/crates/oxide/src/extractor/pre_processors/vue.rs
+++ b/crates/oxide/src/extractor/pre_processors/vue.rs
@@ -14,13 +14,12 @@ pub struct Vue;
impl PreProcessor for Vue {
fn process(&self, content: &[u8]) -> Vec {
let mut result = content.to_vec();
-
let content_as_str = std::str::from_utf8(content).unwrap();
for (_, [lang, body]) in TEMPLATE_REGEX
.captures_iter(content_as_str)
.map(|c| c.extract())
{
- let replaced = pre_process_input(body.as_bytes(), lang);
+ let replaced = pre_process_input(body.as_bytes().to_vec(), lang);
result = result.replace(body, replaced);
}
diff --git a/crates/oxide/src/extractor/string_machine.rs b/crates/oxide/src/extractor/string_machine.rs
index 9148a1fbf619..4fad49faae19 100644
--- a/crates/oxide/src/extractor/string_machine.rs
+++ b/crates/oxide/src/extractor/string_machine.rs
@@ -30,20 +30,20 @@ impl Machine for StringMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- if Class::Quote != cursor.curr.into() {
+ if Class::Quote != cursor.curr().into() {
return MachineState::Idle;
}
// Start of a string
let len = cursor.input.len();
let start_pos = cursor.pos;
- let end_char = cursor.curr;
+ let end_char = cursor.curr();
cursor.advance();
while cursor.pos < len {
- match cursor.curr.into() {
- Class::Escape => match cursor.next.into() {
+ match cursor.curr().into() {
+ Class::Escape => match cursor.next().into() {
// An escaped whitespace character is not allowed
Class::Whitespace => return MachineState::Idle,
@@ -52,7 +52,7 @@ impl Machine for StringMachine {
},
// End of the string
- Class::Quote if cursor.curr == end_char => return self.done(start_pos, cursor),
+ Class::Quote if cursor.curr() == end_char => return self.done(start_pos, cursor),
// Any kind of whitespace is not allowed
Class::Whitespace => return MachineState::Idle,
diff --git a/crates/oxide/src/extractor/utility_machine.rs b/crates/oxide/src/extractor/utility_machine.rs
index b9b1038cdb3a..c116ec4e4226 100644
--- a/crates/oxide/src/extractor/utility_machine.rs
+++ b/crates/oxide/src/extractor/utility_machine.rs
@@ -27,12 +27,12 @@ impl Machine for UtilityMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// LEGACY: Important marker
Class::Exclamation => {
self.legacy_important = true;
- match cursor.next.into() {
+ match cursor.next().into() {
// Start of an arbitrary property
//
// E.g.: `![color:red]`
@@ -78,7 +78,7 @@ impl UtilityMachine {
fn parse_arbitrary_property(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.arbitrary_property_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// End of arbitrary property, but there is a potential modifier.
//
// E.g.: `[color:#0088cc]/`
@@ -109,7 +109,7 @@ impl UtilityMachine {
fn parse_named_utility(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.named_utility_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// End of a named utility, but there is a potential modifier.
//
// E.g.: `bg-red-500/`
@@ -140,7 +140,7 @@ impl UtilityMachine {
fn parse_modifier(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
match self.modifier_machine.next(cursor) {
MachineState::Idle => self.restart(),
- MachineState::Done(_) => match cursor.next.into() {
+ MachineState::Done(_) => match cursor.next().into() {
// A modifier followed by a modifier is invalid
Class::Slash => self.restart(),
diff --git a/crates/oxide/src/extractor/variant_machine.rs b/crates/oxide/src/extractor/variant_machine.rs
index 23aa61798643..9ec2adc0922a 100644
--- a/crates/oxide/src/extractor/variant_machine.rs
+++ b/crates/oxide/src/extractor/variant_machine.rs
@@ -16,7 +16,7 @@ impl Machine for VariantMachine {
#[inline]
fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
- match cursor.curr.into() {
+ match cursor.curr().into() {
// Start of an arbitrary variant
//
// E.g.: `[&:hover]:`
@@ -48,7 +48,7 @@ impl VariantMachine {
start_pos: usize,
cursor: &mut cursor::Cursor<'_>,
) -> MachineState {
- match cursor.next.into() {
+ match cursor.next().into() {
// End of an arbitrary value, must be followed by a `:`
//
// E.g.: `[&:hover]:`
diff --git a/crates/oxide/src/fast_skip.rs b/crates/oxide/src/fast_skip.rs
index 488e61bd68da..54930548c620 100644
--- a/crates/oxide/src/fast_skip.rs
+++ b/crates/oxide/src/fast_skip.rs
@@ -10,7 +10,7 @@ pub fn fast_skip(cursor: &Cursor) -> Option {
return None;
}
- if !cursor.curr.is_ascii_whitespace() {
+ if !cursor.curr().is_ascii_whitespace() {
return None;
}
diff --git a/crates/oxide/src/scanner/detect_sources.rs b/crates/oxide/src/scanner/detect_sources.rs
index 9dc340fbaf47..c519cd00d788 100644
--- a/crates/oxide/src/scanner/detect_sources.rs
+++ b/crates/oxide/src/scanner/detect_sources.rs
@@ -30,11 +30,9 @@ fn sort_by_dir_and_name(a: &DirEntry, z: &DirEntry) -> Ordering {
pub fn resolve_globs(
base: PathBuf,
- dirs: &[PathBuf],
+ dirs: &FxHashSet,
extensions: &FxHashSet,
) -> Vec {
- let allowed_paths: FxHashSet = FxHashSet::from_iter(dirs.iter().cloned());
-
// A list of known extensions + a list of extensions we found in the project.
let mut found_extensions: FxHashSet =
FxHashSet::from_iter(KNOWN_EXTENSIONS.iter().map(|x| x.to_string()));
@@ -72,7 +70,7 @@ pub fn resolve_globs(
continue;
}
- if !allowed_paths.contains(path) {
+ if !dirs.contains(path) {
let mut path = path;
while let Some(parent) = path.parent() {
if parent == base {
@@ -113,7 +111,7 @@ pub fn resolve_globs(
continue;
}
- if !allowed_paths.contains(path) {
+ if !dirs.contains(path) {
continue;
}
diff --git a/crates/oxide/src/scanner/init_tracing.rs b/crates/oxide/src/scanner/init_tracing.rs
new file mode 100644
index 000000000000..2a570ff20188
--- /dev/null
+++ b/crates/oxide/src/scanner/init_tracing.rs
@@ -0,0 +1,70 @@
+use std::fs::OpenOptions;
+use std::io::{self, Write};
+use std::path::Path;
+use std::sync::{self, Arc, Mutex};
+use tracing_subscriber::fmt::writer::BoxMakeWriter;
+
+pub static SHOULD_TRACE: sync::LazyLock = sync::LazyLock::new(
+ || matches!(std::env::var("DEBUG"), Ok(value) if value.eq("*") || (value.contains("tailwindcss:oxide") && !value.contains("-tailwindcss:oxide"))),
+);
+
+fn dim(input: &str) -> String {
+ format!("\u{001b}[2m{input}\u{001b}[22m")
+}
+
+fn blue(input: &str) -> String {
+ format!("\u{001b}[34m{input}\u{001b}[39m")
+}
+
+fn highlight(input: &str) -> String {
+ format!("{}{}{}", dim(&blue("`")), blue(input), dim(&blue("`")))
+}
+
+struct MutexWriter(Arc>);
+
+impl Write for MutexWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ self.0.lock().unwrap().write(buf)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.0.lock().unwrap().flush()
+ }
+}
+
+pub fn init_tracing() {
+ if !*SHOULD_TRACE {
+ return;
+ }
+
+ let file_path = format!("tailwindcss-{}.log", std::process::id());
+ let file = OpenOptions::new()
+ .create(true)
+ .append(true)
+ .open(&file_path)
+ .unwrap_or_else(|_| panic!("Failed to open {file_path}"));
+
+ let file_path = Path::new(&file_path);
+ let absolute_file_path = dunce::canonicalize(file_path)
+ .unwrap_or_else(|_| panic!("Failed to canonicalize {file_path:?}"));
+ eprintln!(
+ "{} Writing debug info to: {}\n",
+ dim("[DEBUG]"),
+ highlight(absolute_file_path.as_path().to_str().unwrap())
+ );
+
+ let file = Arc::new(Mutex::new(file));
+
+ let writer: BoxMakeWriter = BoxMakeWriter::new({
+ let file = file.clone();
+ move || Box::new(MutexWriter(file.clone())) as Box
+ });
+
+ _ = tracing_subscriber::fmt()
+ .with_max_level(tracing::Level::INFO)
+ .with_span_events(tracing_subscriber::fmt::format::FmtSpan::ACTIVE)
+ .with_writer(writer)
+ .with_ansi(false)
+ .compact()
+ .try_init();
+}
diff --git a/crates/oxide/src/scanner/mod.rs b/crates/oxide/src/scanner/mod.rs
index ec6aea642481..6d6cabc2aa80 100644
--- a/crates/oxide/src/scanner/mod.rs
+++ b/crates/oxide/src/scanner/mod.rs
@@ -1,5 +1,6 @@
pub mod auto_source_detection;
pub mod detect_sources;
+pub mod init_tracing;
pub mod sources;
use crate::extractor::{Extracted, Extractor};
@@ -14,15 +15,13 @@ use bstr::ByteSlice;
use fast_glob::glob_match;
use fxhash::{FxHashMap, FxHashSet};
use ignore::{gitignore::GitignoreBuilder, WalkBuilder};
+use init_tracing::{init_tracing, SHOULD_TRACE};
use rayon::prelude::*;
use std::collections::{BTreeMap, BTreeSet};
-use std::fs::OpenOptions;
-use std::io::{self, Write};
use std::path::{Path, PathBuf};
-use std::sync::{self, Arc, Mutex};
+use std::sync::{Arc, Mutex};
use std::time::SystemTime;
use tracing::event;
-use tracing_subscriber::fmt::writer::BoxMakeWriter;
// @source "some/folder"; // This is auto source detection
// @source "some/folder/**/*"; // This is auto source detection
@@ -34,70 +33,6 @@ use tracing_subscriber::fmt::writer::BoxMakeWriter;
//
// @source "do-include-me.bin"; // `.bin` is typically ignored, but now it's explicit so should be included
// @source "git-ignored.html"; // A git ignored file that is listed explicitly, should be scanned
-static SHOULD_TRACE: sync::LazyLock = sync::LazyLock::new(
- || matches!(std::env::var("DEBUG"), Ok(value) if value.eq("*") || (value.contains("tailwindcss:oxide") && !value.contains("-tailwindcss:oxide"))),
-);
-
-fn dim(input: &str) -> String {
- format!("\u{001b}[2m{input}\u{001b}[22m")
-}
-
-fn blue(input: &str) -> String {
- format!("\u{001b}[34m{input}\u{001b}[39m")
-}
-
-fn highlight(input: &str) -> String {
- format!("{}{}{}", dim(&blue("`")), blue(input), dim(&blue("`")))
-}
-
-fn init_tracing() {
- if !*SHOULD_TRACE {
- return;
- }
-
- let file_path = format!("tailwindcss-{}.log", std::process::id());
- let file = OpenOptions::new()
- .create(true)
- .append(true)
- .open(&file_path)
- .unwrap_or_else(|_| panic!("Failed to open {file_path}"));
-
- let file_path = Path::new(&file_path);
- let absolute_file_path = dunce::canonicalize(file_path)
- .unwrap_or_else(|_| panic!("Failed to canonicalize {file_path:?}"));
- eprintln!(
- "{} Writing debug info to: {}\n",
- dim("[DEBUG]"),
- highlight(absolute_file_path.as_path().to_str().unwrap())
- );
-
- let file = Arc::new(Mutex::new(file));
-
- let writer: BoxMakeWriter = BoxMakeWriter::new({
- let file = file.clone();
- move || Box::new(MutexWriter(file.clone())) as Box
- });
-
- _ = tracing_subscriber::fmt()
- .with_max_level(tracing::Level::INFO)
- .with_span_events(tracing_subscriber::fmt::format::FmtSpan::ACTIVE)
- .with_writer(writer)
- .with_ansi(false)
- .compact()
- .try_init();
-}
-
-struct MutexWriter(Arc>);
-
-impl Write for MutexWriter {
- fn write(&mut self, buf: &[u8]) -> io::Result {
- self.0.lock().unwrap().write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.0.lock().unwrap().flush()
- }
-}
#[derive(Debug, Clone)]
pub enum ChangedContent {
@@ -129,26 +64,32 @@ pub struct Scanner {
/// The walker to detect all files that we have to scan
walker: Option,
- /// All changed content that we have to parse
- changed_content: Vec,
-
/// All found extensions
extensions: FxHashSet,
- /// All CSS files we want to scan for CSS variable usage
- css_files: Vec,
-
/// All files that we have to scan
- files: Vec,
+ files: FxHashSet,
/// All directories, sub-directories, etc… we saw during source detection
- dirs: Vec,
+ dirs: FxHashSet,
/// All generated globs, used for setting up watchers
globs: Option>,
/// Track unique set of candidates
candidates: FxHashSet,
+
+ /// Track mtimes for files so re-scans can skip unchanged files.
+ /// Only populated after the first scan completes (to avoid unnecessary
+ /// metadata calls on initial build).
+ mtimes: FxHashMap,
+
+ /// Whether we've completed at least one full scan. When false, we skip
+ /// mtime tracking entirely so the initial build stays fast.
+ has_scanned_once: bool,
+
+ /// Whether sources have been scanned since the last `scan()` call
+ sources_scanned: bool,
}
impl Scanner {
@@ -163,7 +104,6 @@ impl Scanner {
}
let sources = Sources::new(public_source_entries_to_private_source_entries(sources));
-
if *SHOULD_TRACE {
event!(tracing::Level::INFO, "Optimized sources:");
for source in sources.iter() {
@@ -171,29 +111,26 @@ impl Scanner {
}
}
+ let walker = create_walker(&sources);
+
Self {
- sources: sources.clone(),
- walker: create_walker(sources),
+ sources,
+ walker,
..Default::default()
}
}
pub fn scan(&mut self) -> Vec {
- self.scan_sources();
+ self.sources_scanned = false;
- // TODO: performance improvement, bail early if we don't have any changed content
- // if self.changed_content.is_empty() {
- // return vec![];
- // }
+ let (scanned_blobs, css_files) = self.discover_sources();
- let _new_candidates = self.extract_candidates();
+ self.extract_candidates(scanned_blobs, css_files);
- // Make sure we have a sorted list of candidates
- let mut candidates = self.candidates.iter().cloned().collect::<_>>();
- candidates.par_sort_unstable();
-
- // Return all candidates instead of only the new ones
- candidates
+ // Return all candidates sorted
+ let mut result = self.candidates.iter().cloned().collect::<_>>();
+ result.par_sort_unstable();
+ result
}
#[tracing::instrument(skip_all)]
@@ -208,7 +145,7 @@ impl Scanner {
// Raw content can be parsed directly, no need to verify if the file exists and is allowed
// to be scanned.
- self.changed_content.extend(changed_contents);
+ let mut content_to_scan: Vec = changed_contents;
// Fully resolve all files
let changed_files = changed_files
@@ -232,7 +169,7 @@ impl Scanner {
});
// All known files are allowed to be scanned
- self.changed_content.extend(known_files);
+ content_to_scan.extend(known_files);
// Figure out if the new unknown files are allowed to be scanned
if !new_unknown_files.is_empty() {
@@ -252,8 +189,8 @@ impl Scanner {
// When the file is found on disk it means that all the rules pass. We can
// extract the current file and remove it from the list of passed in files.
if file == path {
- self.files.push(path.to_path_buf()); // Track for future use
- self.changed_content.push(changed_file.clone()); // Track for parsing
+ self.files.insert(path.to_path_buf()); // Track for future use
+ content_to_scan.push(changed_file.clone()); // Track for parsing
drop_file_indexes.push(idx);
}
}
@@ -274,18 +211,17 @@ impl Scanner {
}
}
- self.extract_candidates()
+ // Read all content into blobs for extraction
+ let blobs = read_all_files(content_to_scan);
+ self.extract_candidates(blobs, vec![])
}
#[tracing::instrument(skip_all)]
- fn extract_candidates(&mut self) -> Vec {
- let changed_content = self.changed_content.drain(..).collect::<_>>();
-
- // Extract all candidates from the changed content
- let mut new_candidates = parse_all_blobs(read_all_files(changed_content));
+ fn extract_candidates(&mut self, blobs: Vec>, css_files: Vec) -> Vec {
+ // Extract all candidates from the pre-read blobs
+ let mut new_candidates = parse_all_blobs(blobs);
// Extract all CSS variables from the CSS files
- let css_files = self.css_files.drain(..).collect::<_>>();
if !css_files.is_empty() {
let css_variables = extract_css_variables(read_all_files(
css_files
@@ -297,63 +233,23 @@ impl Scanner {
new_candidates.extend(css_variables);
}
- // Only compute the new candidates and ignore the ones we already have. This is for
- // subsequent calls to prevent serializing the entire set of candidates every time.
- let mut new_candidates = new_candidates
- .into_par_iter()
- .filter(|candidate| !self.candidates.contains(candidate))
- .collect::<_>>();
-
- new_candidates.par_sort_unstable();
+ // Only keep candidates we haven't seen before
+ for existing in self.candidates.iter() {
+ new_candidates.remove(existing);
+ }
// Track new candidates for subsequent calls
- self.candidates.par_extend(new_candidates.clone());
-
- new_candidates
- }
-
- #[tracing::instrument(skip_all)]
- fn scan_sources(&mut self) {
- let Some(walker) = &mut self.walker else {
- return;
- };
+ self.candidates.extend(new_candidates.iter().cloned());
- for entry in walker.build().filter_map(Result::ok) {
- let path = entry.into_path();
- let Ok(metadata) = path.metadata() else {
- continue;
- };
- if metadata.is_dir() {
- self.dirs.push(path);
- } else if metadata.is_file() {
- let extension = path
- .extension()
- .and_then(|x| x.to_str())
- .unwrap_or_default(); // In case the file has no extension
+ let mut result: Vec = new_candidates.into_iter().collect();
+ result.par_sort_unstable();
- match extension {
- // Special handing for CSS files, we don't want to extract candidates from
- // these files, but we do want to extract used CSS variables.
- "css" => {
- self.css_files.push(path.clone());
- }
- _ => {
- self.changed_content.push(ChangedContent::File(
- path.to_path_buf(),
- extension.to_owned(),
- ));
- }
- }
-
- self.extensions.insert(extension.to_owned());
- self.files.push(path);
- }
- }
+ result
}
#[tracing::instrument(skip_all)]
pub fn get_files(&mut self) -> Vec {
- self.scan_sources();
+ let _ = self.discover_sources();
self.files
.par_iter()
@@ -367,7 +263,7 @@ impl Scanner {
return globs.clone();
}
- self.scan_sources();
+ let _ = self.discover_sources();
let mut globs = vec![];
for source in self.sources.iter() {
@@ -456,6 +352,99 @@ impl Scanner {
})
.collect()
}
+
+ #[tracing::instrument(skip_all)]
+ fn discover_sources(&mut self) -> (Vec>, Vec) {
+ if self.sources_scanned {
+ return (vec![], vec![]);
+ }
+ self.sources_scanned = true;
+
+ let Some(walker) = &mut self.walker else {
+ return (vec![], vec![]);
+ };
+
+ // Use synchronous walk for the initial build (lower overhead) and parallel
+ // walk for subsequent calls (watch mode) where the overhead is amortised.
+ let all_entries = if self.has_scanned_once {
+ walk_parallel(walker)
+ } else {
+ walk_synchronous(walker)
+ };
+
+ let mut css_files: Vec = vec![];
+ let mut content_paths: Vec<(PathBuf, String)> = Vec::new();
+ let mut seen_files: FxHashSet = FxHashSet::default();
+
+ for (path, is_dir, extension) in all_entries {
+ if is_dir {
+ self.dirs.insert(path);
+ } else {
+ // Deduplicate: parallel walk can visit the same file from multiple threads
+ if !seen_files.insert(path.clone()) {
+ continue;
+ }
+
+ // On re-scans, check mtime to skip unchanged files.
+ // On the first scan we skip this entirely to avoid extra
+ // metadata syscalls.
+ let changed = if self.has_scanned_once {
+ let current_mtime = std::fs::metadata(&path)
+ .ok()
+ .and_then(|m| m.modified().ok());
+
+ match current_mtime {
+ Some(mtime) => {
+ let prev = self.mtimes.insert(path.clone(), mtime);
+ prev.is_none_or(|prev| prev != mtime)
+ }
+ None => true,
+ }
+ } else {
+ true
+ };
+
+ match extension.as_str() {
+ // Special handing for CSS files, we don't want to extract candidates from
+ // these files, but we do want to extract used CSS variables.
+ "css" => {
+ if changed {
+ css_files.push(path.clone());
+ }
+ }
+ _ => {
+ if changed {
+ content_paths.push((path.clone(), extension.clone()));
+ }
+ }
+ }
+
+ self.extensions.insert(extension);
+ self.files.insert(path);
+ }
+ }
+
+ // Read + preprocess all discovered files in parallel
+ let scanned_blobs: Vec> = content_paths
+ .into_par_iter()
+ .filter_map(|(path, ext)| {
+ let content = std::fs::read(&path).ok()?;
+ event!(tracing::Level::INFO, "Reading {:?}", path);
+ let processed = pre_process_input(content, &ext);
+ if processed.is_empty() {
+ None
+ } else {
+ Some(processed)
+ }
+ })
+ .collect();
+
+ if !self.has_scanned_once {
+ self.has_scanned_once = true;
+ }
+
+ (scanned_blobs, css_files)
+ }
}
fn read_changed_content(c: ChangedContent) -> Option> {
@@ -474,26 +463,26 @@ fn read_changed_content(c: ChangedContent) -> Option> {
ChangedContent::Content(contents, extension) => (contents.into_bytes(), extension),
};
- Some(pre_process_input(&content, &extension))
+ Some(pre_process_input(content, &extension))
}
-pub fn pre_process_input(content: &[u8], extension: &str) -> Vec {
+pub fn pre_process_input(content: Vec, extension: &str) -> Vec {
use crate::extractor::pre_processors::*;
match extension {
- "clj" | "cljs" | "cljc" => Clojure.process(content),
- "heex" | "eex" | "ex" | "exs" => Elixir.process(content),
- "cshtml" | "razor" => Razor.process(content),
- "haml" => Haml.process(content),
- "json" => Json.process(content),
- "md" | "mdx" => Markdown.process(content),
- "pug" => Pug.process(content),
- "rb" | "erb" => Ruby.process(content),
- "slim" | "slang" => Slim.process(content),
- "svelte" => Svelte.process(content),
- "rs" => Rust.process(content),
- "vue" => Vue.process(content),
- _ => content.to_vec(),
+ "clj" | "cljs" | "cljc" => Clojure.process(&content),
+ "heex" | "eex" | "ex" | "exs" => Elixir.process(&content),
+ "cshtml" | "razor" => Razor.process(&content),
+ "haml" => Haml.process(&content),
+ "json" => Json.process(&content),
+ "md" | "mdx" => Markdown.process(&content),
+ "pug" => Pug.process(&content),
+ "rb" | "erb" => Ruby.process(&content),
+ "slim" | "slang" => Slim.process(&content),
+ "svelte" => Svelte.process(&content),
+ "rs" => Rust.process(&content),
+ "vue" => Vue.process(&content),
+ _ => content,
}
}
@@ -512,23 +501,23 @@ fn read_all_files(changed_content: Vec) -> Vec> {
}
#[tracing::instrument(skip_all)]
-fn extract_css_variables(blobs: Vec>) -> Vec {
+fn extract_css_variables(blobs: Vec>) -> FxHashSet {
extract(blobs, |mut extractor| {
extractor.extract_variables_from_css()
})
}
#[tracing::instrument(skip_all)]
-fn parse_all_blobs(blobs: Vec>) -> Vec {
+fn parse_all_blobs(blobs: Vec>) -> FxHashSet {
extract(blobs, |mut extractor| extractor.extract())
}
#[tracing::instrument(skip_all)]
-fn extract(blobs: Vec>, handle: H) -> Vec
+fn extract(blobs: Vec>, handle: H) -> FxHashSet
where
H: Fn(Extractor) -> Vec + std::marker::Sync,
{
- let mut result: Vec<_> = blobs
+ blobs
.par_iter()
.flat_map(|blob| blob.par_split(|x| *x == b'\n'))
.filter_map(|blob| {
@@ -554,22 +543,97 @@ where
})
.into_iter()
.map(|s| unsafe { String::from_utf8_unchecked(s.to_vec()) })
- .collect();
+ .collect()
+}
+
+type WalkEntry = (PathBuf, bool, String);
- // SAFETY: Unstable sort is faster and in this scenario it's also safe because we are
- // guaranteed to have unique candidates.
- result.par_sort_unstable();
+/// Walk the file system synchronously. Used for the initial build where the overhead of spawning
+/// parallel walker threads is not worth it.
+#[tracing::instrument(skip_all)]
+fn walk_synchronous(walker: &mut WalkBuilder) -> Vec {
+ let mut entries = Vec::new();
+
+ for entry in walker.build().filter_map(Result::ok) {
+ let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
+ let path = entry.into_path();
+
+ if is_dir {
+ entries.push((path, true, String::new()));
+ } else {
+ let ext = path
+ .extension()
+ .and_then(|x| x.to_str())
+ .unwrap_or_default()
+ .to_owned();
+ entries.push((path, false, ext));
+ }
+ }
- result
+ entries
}
-/// Create a walker for the given sources to detect all the files that we have to scan.
+/// Walk the file system in parallel. Used in watch mode where the parallel walker overhead is
+/// amortised across many rebuilds and subsequent calls are much faster.
+#[tracing::instrument(skip_all)]
+fn walk_parallel(walker: &mut WalkBuilder) -> Vec {
+ struct FlushOnDrop {
+ local: Vec,
+ shared: Arc>>,
+ }
+
+ impl Drop for FlushOnDrop {
+ fn drop(&mut self) {
+ if !self.local.is_empty() {
+ self.shared.lock().unwrap().append(&mut self.local);
+ }
+ }
+ }
+
+ let collected: Arc>> = Arc::new(Mutex::new(Vec::new()));
+
+ walker.build_parallel().run(|| {
+ let mut buf = FlushOnDrop {
+ local: Vec::with_capacity(256),
+ shared: collected.clone(),
+ };
+
+ Box::new(move |entry| {
+ let Ok(entry) = entry else {
+ return ignore::WalkState::Continue;
+ };
+
+ let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
+ let path = entry.into_path();
+
+ if is_dir {
+ buf.local.push((path, true, String::new()));
+ } else {
+ let ext = path
+ .extension()
+ .and_then(|x| x.to_str())
+ .unwrap_or_default()
+ .to_owned();
+ buf.local.push((path, false, ext));
+ }
+
+ if buf.local.len() >= 256 {
+ buf.shared.lock().unwrap().append(&mut buf.local);
+ }
+
+ ignore::WalkState::Continue
+ })
+ });
+
+ // All threads have finished and flushed their buffers via FlushOnDrop::drop
+ Arc::try_unwrap(collected).unwrap().into_inner().unwrap()
+}
+
+/// Sets up a WalkBuilder with all source roots, gitignore rules, and source pattern matching.
///
-/// The `mtimes` map is used to keep track of the last modified time of each file. This is used to
-/// determine if a file or folder has changed since the last scan and we can skip folders that
-/// haven't changed.
-fn create_walker(sources: Sources) -> Option {
- let mtimes: Arc>> = Default::default();
+/// This is the common setup shared between the full walker (with mtime tracking for re-scans)
+/// and the parallel walker (without mtime tracking for the initial scan).
+fn create_walker(sources: &Sources) -> Option {
let mut other_roots: FxHashSet<&PathBuf> = FxHashSet::default();
let mut first_root: Option<&PathBuf> = None;
let mut ignores: BTreeMap<&PathBuf, BTreeSet> = Default::default();
@@ -717,75 +781,68 @@ fn create_walker(sources: Sources) -> Option {
builder.add_gitignore(ignore);
}
- builder.filter_entry({
- move |entry| {
- let path = entry.path();
-
- // Ensure the entries are matching any of the provided source patterns (this is
- // necessary for manual-patterns that can filter the file extension)
- if path.is_file() {
- let mut matches = false;
- for source in sources.iter() {
- match source {
- SourceEntry::Auto { base } | SourceEntry::External { base } => {
- if path.starts_with(base) {
- matches = true;
- break;
- }
- }
- SourceEntry::Pattern { base, pattern } => {
- let mut pattern = pattern.to_string();
- // Ensure that the pattern is pinned to the base path.
- if !pattern.starts_with("/") {
- pattern = format!("/{pattern}");
- }
-
- // Check if path starts with base, if so, remove the prefix and check the remainder against the pattern
- let remainder = path.strip_prefix(base);
- if remainder.is_ok_and(|remainder| {
- let mut path_str = remainder.to_string_lossy().to_string();
- if !path_str.starts_with("/") {
- path_str = format!("/{path_str}");
- }
- glob_match(pattern, path_str.as_bytes())
- }) {
- matches = true;
- break;
- }
- }
- _ => {}
- }
- }
+ // Pre-compute source matching data to avoid allocations in the hot filter_entry path
+ let auto_bases: Vec = sources
+ .iter()
+ .filter_map(|source| match source {
+ SourceEntry::Auto { base } | SourceEntry::External { base } => Some(base.clone()),
+ _ => None,
+ })
+ .collect();
- if !matches {
- return false;
- }
+ let pattern_sources: Vec<(PathBuf, String)> = sources
+ .iter()
+ .filter_map(|source| match source {
+ SourceEntry::Pattern { base, pattern } => {
+ let normalized = if pattern.starts_with("/") {
+ pattern.to_string()
+ } else {
+ format!("/{pattern}")
+ };
+ Some((base.clone(), normalized))
}
+ _ => None,
+ })
+ .collect();
- let mut mtimes = mtimes.lock().unwrap();
- let current_time = match entry.metadata() {
- Ok(metadata) if metadata.is_file() => {
- if let Ok(time) = metadata.modified() {
- Some(time)
- } else {
- None
- }
- }
- _ => None,
- };
+ // Source pattern matching filter (lock-free, safe for parallel walking)
+ builder.filter_entry(move |entry| {
+ let path = entry.path();
- let previous_time =
- current_time.and_then(|time| mtimes.insert(entry.clone().into_path(), time));
+ // Ensure the entries are matching any of the provided source patterns (this is
+ // necessary for manual-patterns that can filter the file extension)
+ if path.is_file() {
+ let mut matches = false;
- match (current_time, previous_time) {
- (Some(current), Some(prev)) if prev == current => false,
- _ => {
- event!(tracing::Level::INFO, "Discovering {:?}", path);
+ for base in &auto_bases {
+ if path.starts_with(base) {
+ matches = true;
+ break;
+ }
+ }
- true
+ if !matches {
+ for (base, pattern) in &pattern_sources {
+ let remainder = path.strip_prefix(base);
+ if remainder.is_ok_and(|remainder| {
+ let mut path_str = remainder.to_string_lossy().to_string();
+ if !path_str.starts_with("/") {
+ path_str = format!("/{path_str}");
+ }
+ glob_match(pattern, path_str.as_bytes())
+ }) {
+ matches = true;
+ break;
+ }
}
}
+
+ if !matches {
+ return false;
+ }
}
+
+ true
});
Some(builder)
From bc6e4b85bf1dce84e2947f81cbb9881a77427de7 Mon Sep 17 00:00:00 2001
From: Andrey Viktorov
Date: Wed, 18 Feb 2026 02:59:57 +0700
Subject: [PATCH 23/40] Fallback to `config.createResolver` for `client` and
`ssr` environments in `@tailwindcss/vite` (#19679)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
Sometimes even if Vite Envrionment API is available, some plugins are
still override `config.createResolver` function to inject own aliases
Since technically `config.createResolver` was only [properly
deprecated](https://github.com/vitejs/vite/pull/20031) in Vite 7.0.0,
it's still a valid(-ish) to do so, even if it wasn't ever officially
supported
Vite already handles this in its internal css resolvers, but not exposes
the code to do so as part of public API, so I've copied and adapted it
Fixes #19677
## Test plan
Tested by copying built package into my repro from the issue, also ran
vite integration tests
---------
Co-authored-by: Robin Malfait
---
CHANGELOG.md | 1 +
integrations/vite/astro.test.ts | 72 ++++++++++++++++++++++++-
packages/@tailwindcss-vite/src/index.ts | 40 ++++++++++++--
3 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0657008292ef..3feec133112d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow multiples of `.25` in `aspect-*` fractions ([#19688](https://github.com/tailwindlabs/tailwindcss/pull/19688))
- Ensure changes to external files listed via `@source` trigger a full page reload when using `@tailwindcss/vite` ([#19670](https://github.com/tailwindlabs/tailwindcss/pull/19670))
- Improve performance Oxide scanner in bigger projects ([#19632](https://github.com/tailwindlabs/tailwindcss/pull/19632))
+- Ensure import aliases in Astro v5 work without crashing ([#19677](https://github.com/tailwindlabs/tailwindcss/issues/19677))
### Deprecated
diff --git a/integrations/vite/astro.test.ts b/integrations/vite/astro.test.ts
index 43406624c316..f828b5071b60 100644
--- a/integrations/vite/astro.test.ts
+++ b/integrations/vite/astro.test.ts
@@ -1,4 +1,4 @@
-import { candidate, fetchStyles, html, js, json, retryAssertion, test, ts } from '../utils'
+import { candidate, css, fetchStyles, html, js, json, retryAssertion, test, ts } from '../utils'
test(
'dev mode',
@@ -129,3 +129,73 @@ test(
await fs.expectFileToContain(files[0][0], [candidate`underline`, candidate`overline`])
},
)
+
+// https://github.com/tailwindlabs/tailwindcss/issues/19677
+test(
+ 'import aliases should work in
+
+
+ Astro
+
+