diff --git a/composer.json b/composer.json index 09002de3..af701b21 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,7 @@ "components", "material", "material-design", - "material-3", - "tailwindcss" + "material-3" ], "homepage": "https://gitea.nonameweb.ch/noNameWEB/livewire-material", "authors": [ diff --git a/package-lock.json b/package-lock.json index 5809fbba..5a0e6ddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,12 +6,10 @@ "": { "devDependencies": { "@material/material-color-utilities": "^0.4.0", - "@tailwindcss/vite": "^4.3.3", "esbuild": "^0.28.2", "fontkit": "^2.0.4", "laravel-vite-plugin": "^3.2.0", "playwright": "^1.62.1", - "tailwindcss": "^4.3.3", "vite": "^8.2.2" } }, @@ -457,56 +455,6 @@ "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", - "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@material/material-color-utilities": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.4.0.tgz", @@ -814,290 +762,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@tailwindcss/node": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", - "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.24.1", - "jiti": "^2.7.0", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", - "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-arm64": "4.3.3", - "@tailwindcss/oxide-darwin-x64": "4.3.3", - "@tailwindcss/oxide-freebsd-x64": "4.3.3", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", - "@tailwindcss/oxide-linux-x64-musl": "4.3.3", - "@tailwindcss/oxide-wasm32-wasi": "4.3.3", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", - "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", - "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", - "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", - "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", - "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", - "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", - "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", - "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", - "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", - "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.11.1", - "@emnapi/runtime": "^1.11.1", - "@emnapi/wasi-threads": "^1.2.2", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.2", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", - "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", - "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", - "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tailwindcss/node": "4.3.3", - "@tailwindcss/oxide": "4.3.3", - "tailwindcss": "4.3.3" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7 || ^8" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1156,20 +820,6 @@ "dev": true, "license": "MIT" }, - "node_modules/enhanced-resolve": { - "version": "5.25.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.0.tgz", - "integrity": "sha512-ghq3mhs649mvbarTCAlZn2wRhbfHmzAFiKxoWA14B3VtqnxtZt+wz8BroKXU0tF3GiJsnUldjVncQGZ8qk4rdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/esbuild": { "version": "0.28.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", @@ -1270,23 +920,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, "node_modules/laravel-vite-plugin": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-3.2.0.tgz", @@ -1314,289 +947,6 @@ } } }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, "node_modules/nanoid": { "version": "3.3.19", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", @@ -1752,27 +1102,6 @@ "node": ">=0.10.0" } }, - "node_modules/tailwindcss": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", - "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", diff --git a/package.json b/package.json index bf2b93d5..4f752471 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,10 @@ }, "devDependencies": { "@material/material-color-utilities": "^0.4.0", - "@tailwindcss/vite": "^4.3.3", "esbuild": "^0.28.2", "fontkit": "^2.0.4", "laravel-vite-plugin": "^3.2.0", "playwright": "^1.62.1", - "tailwindcss": "^4.3.3", "vite": "^8.2.2" } } diff --git a/resources/boost/skills/livewire-material-development/SKILL.md b/resources/boost/skills/livewire-material-development/SKILL.md index 2e616aa8..75587a04 100644 --- a/resources/boost/skills/livewire-material-development/SKILL.md +++ b/resources/boost/skills/livewire-material-development/SKILL.md @@ -24,8 +24,6 @@ Composer packages must be installed before the Vite build (in Dockerfiles and CI `foundation.css` is required and first; then one stylesheet per component the views render, under `resources/css/components/` or `resources/css/layout/`, named like the component (`` is drawn by `tabs.css`, and `` needs none). Each imports the stylesheets of the components it draws (a split button's button and menu), and Vite keeps a file several of them import once. `resources/css/all.css` stands for the foundation and every component at once. A component rendered without its stylesheet is unstyled, so add the import with the tag. -While the application's own views still write Tailwind classes, Tailwind goes in a second entry, never beside these imports (`@tailwindcss/vite` would repeat every shared stylesheet): `@import 'tailwindcss'`, `resources/css/tailwind.css` and the two `@source` lines for `resources/views` and `src`, with `@layer properties, theme, base, material, components, utilities;` at the top of both entries. - ```js // resources/js/app.js import '../../vendor/nonameweb/livewire-material/resources/js/material.js' diff --git a/resources/css/tailwind.css b/resources/css/tailwind.css deleted file mode 100644 index 1a4c6074..00000000 --- a/resources/css/tailwind.css +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Livewire Material's Tailwind half: the theme that turns the tokens into utilities and the token - * utilities themselves (`state-layer`, `focus-ring`, `touch-target`, `link`, `type-*`), for a view - * that still writes Tailwind classes — the showcase until step 38, and an application's own views - * until it drops Tailwind. Every component stylesheet is plain CSS (plan step 36) and needs - * nothing from here. This file goes when the last Tailwind class leaves (step 39). - * - * It carries no tokens, so it builds beside the package's CSS without declaring them twice, in an - * entry of its own — `@tailwindcss/vite` inlines the imports of an entry that uses Tailwind without - * deduplicating them, so the package's stylesheets stay in another (the Workbench's package.css). - * The Workbench's Tailwind entry, like an application's: - * - * @layer properties, theme, base, material, components, utilities; - * @import 'tailwindcss' source(none); - * @import '../../../resources/css/tailwind.css'; - * - * with the same layer statement at the top of the package's entry. It replaces nothing of the 1.x - * `material.css` shortcut, which is gone: the components come from `all.css` or their own files. - */ - -@import './tokens/theme.css'; -@import './tokens/utilities.css'; diff --git a/resources/css/tokens/theme.css b/resources/css/tokens/theme.css deleted file mode 100644 index a4f16a43..00000000 --- a/resources/css/tokens/theme.css +++ /dev/null @@ -1,179 +0,0 @@ -/* - * The Tailwind theme: every token as a utility. - * - * `--color-*: initial` clears Tailwind's default palette, so every colour a template can name - * is an M3 role (bg-primary, text-on-surface-variant, border-outline-variant…) and a - * `text-red-600` compiles to nothing. White and black come back as the two absolutes. An - * application that wants more colours adds them in its own @theme after importing this file. - * - * The colour blocks are `@theme inline`: `bg-primary` compiles to - * `background-color: var(--md-sys-color-primary)`, resolved on the element itself. Without - * `inline` it compiles to `var(--color-primary)`, a variable computed once on :root — the - * page-wide theme still switches, but a `data-theme="dark"` section inside a light page keeps - * the light colours. Only blocks whose values are variables may be inline; a literal value in - * an inline block would be copied into every utility and lose its variable. - */ - -@theme { - --color-*: initial; - --color-white: #ffffff; - --color-black: #000000; - - --font-sans: var(--md-ref-typeface-brand); -} - -/* - * Breakpoints are M3's window size classes, and only those: compact is below `medium`, then - * medium 600, expanded 840, large 1200 and extra-large 1600 (`medium:`, `expanded:`, `large:`, - * `extra-large:`, and `max-medium:` … for "below"). Tailwind's sm/md/lg/xl/2xl are cleared — - * a `sm:` compiles to nothing — because a layout decision keyed on 640px means nothing in M3. - * resources/js/breakpoints.js carries the same four numbers for scripts. - */ -@theme { - --breakpoint-*: initial; - --breakpoint-medium: 600px; - --breakpoint-expanded: 840px; - --breakpoint-large: 1200px; - --breakpoint-extra-large: 1600px; -} - -/* - * Only M3's scales compile. Tailwind's default radius, shadow, text-size, weight, leading, - * tracking and easing utilities are cleared like its palette, so `rounded-lg`, `text-sm`, - * `font-medium`, `shadow-md` or `ease-in-out` compile to nothing; the M3 sets are declared - * below (`rounded-corner-*`, `shadow-elevation-*`, `type-*`, `ease-spatial-*`…). The 4px - * spacing scale stays: it is M3's spacing grid. - */ -@theme { - --radius-*: initial; - --shadow-*: initial; - --inset-shadow-*: initial; - --drop-shadow-*: initial; - --text-*: initial; - --font-weight-*: initial; - --leading-*: initial; - --tracking-*: initial; - --ease-*: initial; -} - -/* The colour roles, as generated by `php artisan material:scheme`. */ -@theme inline { - --color-background: var(--md-sys-color-background); - --color-on-background: var(--md-sys-color-on-background); - --color-surface: var(--md-sys-color-surface); - --color-surface-dim: var(--md-sys-color-surface-dim); - --color-surface-bright: var(--md-sys-color-surface-bright); - --color-surface-container-lowest: var(--md-sys-color-surface-container-lowest); - --color-surface-container-low: var(--md-sys-color-surface-container-low); - --color-surface-container: var(--md-sys-color-surface-container); - --color-surface-container-high: var(--md-sys-color-surface-container-high); - --color-surface-container-highest: var(--md-sys-color-surface-container-highest); - --color-on-surface: var(--md-sys-color-on-surface); - --color-on-surface-variant: var(--md-sys-color-on-surface-variant); - --color-outline: var(--md-sys-color-outline); - --color-outline-variant: var(--md-sys-color-outline-variant); - --color-inverse-surface: var(--md-sys-color-inverse-surface); - --color-inverse-on-surface: var(--md-sys-color-inverse-on-surface); - --color-primary: var(--md-sys-color-primary); - --color-primary-dim: var(--md-sys-color-primary-dim); - --color-on-primary: var(--md-sys-color-on-primary); - --color-primary-container: var(--md-sys-color-primary-container); - --color-on-primary-container: var(--md-sys-color-on-primary-container); - --color-primary-fixed: var(--md-sys-color-primary-fixed); - --color-primary-fixed-dim: var(--md-sys-color-primary-fixed-dim); - --color-on-primary-fixed: var(--md-sys-color-on-primary-fixed); - --color-on-primary-fixed-variant: var(--md-sys-color-on-primary-fixed-variant); - --color-inverse-primary: var(--md-sys-color-inverse-primary); - --color-secondary: var(--md-sys-color-secondary); - --color-secondary-dim: var(--md-sys-color-secondary-dim); - --color-on-secondary: var(--md-sys-color-on-secondary); - --color-secondary-container: var(--md-sys-color-secondary-container); - --color-on-secondary-container: var(--md-sys-color-on-secondary-container); - --color-secondary-fixed: var(--md-sys-color-secondary-fixed); - --color-secondary-fixed-dim: var(--md-sys-color-secondary-fixed-dim); - --color-on-secondary-fixed: var(--md-sys-color-on-secondary-fixed); - --color-on-secondary-fixed-variant: var(--md-sys-color-on-secondary-fixed-variant); - --color-tertiary: var(--md-sys-color-tertiary); - --color-tertiary-dim: var(--md-sys-color-tertiary-dim); - --color-on-tertiary: var(--md-sys-color-on-tertiary); - --color-tertiary-container: var(--md-sys-color-tertiary-container); - --color-on-tertiary-container: var(--md-sys-color-on-tertiary-container); - --color-tertiary-fixed: var(--md-sys-color-tertiary-fixed); - --color-tertiary-fixed-dim: var(--md-sys-color-tertiary-fixed-dim); - --color-on-tertiary-fixed: var(--md-sys-color-on-tertiary-fixed); - --color-on-tertiary-fixed-variant: var(--md-sys-color-on-tertiary-fixed-variant); - --color-error: var(--md-sys-color-error); - --color-error-dim: var(--md-sys-color-error-dim); - --color-on-error: var(--md-sys-color-on-error); - --color-error-container: var(--md-sys-color-error-container); - --color-on-error-container: var(--md-sys-color-on-error-container); - --color-success: var(--md-sys-color-success); - --color-on-success: var(--md-sys-color-on-success); - --color-success-container: var(--md-sys-color-success-container); - --color-on-success-container: var(--md-sys-color-on-success-container); - --color-warning: var(--md-sys-color-warning); - --color-on-warning: var(--md-sys-color-on-warning); - --color-warning-container: var(--md-sys-color-warning-container); - --color-on-warning-container: var(--md-sys-color-on-warning-container); - --color-info: var(--md-sys-color-info); - --color-on-info: var(--md-sys-color-on-info); - --color-info-container: var(--md-sys-color-info-container); - --color-on-info-container: var(--md-sys-color-on-info-container); - --color-inverse-error: var(--md-sys-color-inverse-error); - --color-inverse-success: var(--md-sys-color-inverse-success); - --color-inverse-warning: var(--md-sys-color-inverse-warning); - --color-inverse-info: var(--md-sys-color-inverse-info); - --color-shadow: var(--md-sys-color-shadow); - --color-scrim: var(--md-sys-color-scrim); -} - -/* - * Ink and lines by what they are: body copy, metadata, decoration; a structural line, a line - * around chrome, a divider. Each is an M3 role, never an opacity: M3 marks emphasis with - * on-surface-variant and outline, and reserves 38% for disabled content, so an ink dimmed by - * opacity reads as disabled and loses its contrast guarantee. - */ -@theme inline { - --color-body: var(--md-sys-color-on-surface-variant); - --color-meta: var(--md-sys-color-on-surface-variant); - --color-quiet: var(--md-sys-color-outline); - --color-structure: var(--md-sys-color-outline-variant); - --color-chrome: var(--md-sys-color-outline-variant); - --color-divider: var(--md-sys-color-outline-variant); -} - -@theme { - --radius-corner-none: var(--md-sys-shape-corner-none); - --radius-corner-xs: var(--md-sys-shape-corner-xs); - --radius-corner-sm: var(--md-sys-shape-corner-sm); - --radius-corner-md: var(--md-sys-shape-corner-md); - --radius-corner-lg: var(--md-sys-shape-corner-lg); - --radius-corner-lg-increased: var(--md-sys-shape-corner-lg-increased); - --radius-corner-xl: var(--md-sys-shape-corner-xl); - --radius-corner-xl-increased: var(--md-sys-shape-corner-xl-increased); - --radius-corner-xxl: var(--md-sys-shape-corner-xxl); - --radius-corner-full: var(--md-sys-shape-corner-full); - - --shadow-elevation-1: var(--md-sys-elevation-1); - --shadow-elevation-2: var(--md-sys-elevation-2); - --shadow-elevation-3: var(--md-sys-elevation-3); - --shadow-elevation-4: var(--md-sys-elevation-4); - --shadow-elevation-5: var(--md-sys-elevation-5); - - --ease-spatial-fast: var(--md-sys-motion-spatial-fast); - --ease-spatial-default: var(--md-sys-motion-spatial-default); - --ease-spatial-slow: var(--md-sys-motion-spatial-slow); - --ease-effects-fast: var(--md-sys-motion-effects-fast); - --ease-effects-default: var(--md-sys-motion-effects-default); - --ease-effects-slow: var(--md-sys-motion-effects-slow); - --ease-standard: var(--md-sys-motion-easing-standard); - --ease-emphasized: var(--md-sys-motion-easing-emphasized); - --ease-emphasized-decelerate: var(--md-sys-motion-easing-emphasized-decelerate); - --ease-emphasized-accelerate: var(--md-sys-motion-easing-emphasized-accelerate); -} - -/* - * `dark:` follows the page's theme, not the operating system: has already - * resolved `system` into data-theme, and the OS was never meant to be a second voice. - */ -@custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *)); diff --git a/resources/css/tokens/utilities.css b/resources/css/tokens/utilities.css deleted file mode 100644 index b935f04e..00000000 --- a/resources/css/tokens/utilities.css +++ /dev/null @@ -1,286 +0,0 @@ -/* - * The token utilities, for the components still written in Tailwind. - * - * Tailwind's side of tokens/state.css and tokens/type.css, kept apart so that the token files the - * foundation imports carry no Tailwind directive. tailwind.css imports this file after Tailwind; - * it goes when the last component leaves Tailwind. New markup uses the plain-CSS classes instead, - * which carry the same declarations: `md-state-layer`, `md-focus-ring`, `md-touch-target` and - * `md-link` (foundation/interaction.css), and `md-type-*` (text.css). - * - * `state-layer` puts M3's state layer on an element. Hover only where the pointer can hover, - * because a touch screen keeps the last hover after a tap; `data-dragged` on the element draws - * the dragged layer. The layer is a ::before, so the element becomes `position: relative` and - * `isolation: isolate`; never pass `static` or a z-index to it. - * - * `touch-target` extends an element's pointer target to M3's 48×48px minimum without changing - * what is drawn: a ::after centred on it, at least 48px each way. It is `::after`-based, so a - * component that already draws with ::after wraps its control in an element carrying it. - * - * `focus-ring` is M3's focus indicator — 3px in secondary, 2px out, drawn only for keyboard - * focus. The site gives no thickness or offset; the values are @material/web's focus ring - * tokens (Apache-2.0, © Google LLC). `link` is a link in running text: underlined in the - * colour of the words around it. - * - * `type-*` is one of M3's 30 type styles (tokens/type.css): size, line height, weight and - * tracking together. M3 asks for emphasis one element at a time, and `font-variation-settings` - * inherits, so every regular utility resets it: body copy inside an emphasized heading reads as - * itself again. - */ - -@utility state-layer { - position: relative; - isolation: isolate; - - &::before { - content: ''; - position: absolute; - inset: 0; - z-index: -1; - border-radius: inherit; - background-color: currentColor; - opacity: 0; - pointer-events: none; - transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); - } - - @media (hover: hover) { - &:hover::before { - opacity: var(--md-sys-state-hover-state-layer-opacity); - } - } - - &:focus-visible::before { - opacity: var(--md-sys-state-focus-state-layer-opacity); - } - - &:active::before { - opacity: var(--md-sys-state-pressed-state-layer-opacity); - } - - &[data-dragged]::before { - opacity: var(--md-sys-state-dragged-state-layer-opacity); - } - - &:disabled::before, - &[aria-disabled='true']::before { - display: none; - } -} - -@utility touch-target { - position: relative; - - &::after { - content: ''; - position: absolute; - top: 50%; - left: 50%; - width: 100%; - height: 100%; - min-width: 3rem; - min-height: 3rem; - transform: translate(-50%, -50%); - } -} - -@utility focus-ring { - outline: none; - - &:focus-visible { - outline: 3px solid var(--md-sys-color-secondary); - outline-offset: 2px; - } -} - -@utility link { - cursor: pointer; - text-decoration-line: underline; - text-decoration-thickness: from-font; - text-underline-offset: 0.15em; - border-radius: var(--md-sys-shape-corner-xs); - - &:focus-visible { - outline: 3px solid var(--md-sys-color-secondary); - outline-offset: 2px; - } -} - -@utility type-display-lg { - font: var(--md-sys-typescale-display-lg); - letter-spacing: var(--md-sys-typescale-display-lg-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-display-lg { - font: var(--md-sys-typescale-emphasized-display-lg); - letter-spacing: var(--md-sys-typescale-emphasized-display-lg-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-display-md { - font: var(--md-sys-typescale-display-md); - letter-spacing: var(--md-sys-typescale-display-md-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-display-md { - font: var(--md-sys-typescale-emphasized-display-md); - letter-spacing: var(--md-sys-typescale-emphasized-display-md-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-display-sm { - font: var(--md-sys-typescale-display-sm); - letter-spacing: var(--md-sys-typescale-display-sm-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-display-sm { - font: var(--md-sys-typescale-emphasized-display-sm); - letter-spacing: var(--md-sys-typescale-emphasized-display-sm-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-headline-lg { - font: var(--md-sys-typescale-headline-lg); - letter-spacing: var(--md-sys-typescale-headline-lg-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-headline-lg { - font: var(--md-sys-typescale-emphasized-headline-lg); - letter-spacing: var(--md-sys-typescale-emphasized-headline-lg-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-headline-md { - font: var(--md-sys-typescale-headline-md); - letter-spacing: var(--md-sys-typescale-headline-md-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-headline-md { - font: var(--md-sys-typescale-emphasized-headline-md); - letter-spacing: var(--md-sys-typescale-emphasized-headline-md-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-headline-sm { - font: var(--md-sys-typescale-headline-sm); - letter-spacing: var(--md-sys-typescale-headline-sm-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-headline-sm { - font: var(--md-sys-typescale-emphasized-headline-sm); - letter-spacing: var(--md-sys-typescale-emphasized-headline-sm-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-title-lg { - font: var(--md-sys-typescale-title-lg); - letter-spacing: var(--md-sys-typescale-title-lg-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-title-lg { - font: var(--md-sys-typescale-emphasized-title-lg); - letter-spacing: var(--md-sys-typescale-emphasized-title-lg-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-title-md { - font: var(--md-sys-typescale-title-md); - letter-spacing: var(--md-sys-typescale-title-md-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-title-md { - font: var(--md-sys-typescale-emphasized-title-md); - letter-spacing: var(--md-sys-typescale-emphasized-title-md-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-title-sm { - font: var(--md-sys-typescale-title-sm); - letter-spacing: var(--md-sys-typescale-title-sm-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-title-sm { - font: var(--md-sys-typescale-emphasized-title-sm); - letter-spacing: var(--md-sys-typescale-emphasized-title-sm-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-body-lg { - font: var(--md-sys-typescale-body-lg); - letter-spacing: var(--md-sys-typescale-body-lg-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-body-lg { - font: var(--md-sys-typescale-emphasized-body-lg); - letter-spacing: var(--md-sys-typescale-emphasized-body-lg-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-body-md { - font: var(--md-sys-typescale-body-md); - letter-spacing: var(--md-sys-typescale-body-md-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-body-md { - font: var(--md-sys-typescale-emphasized-body-md); - letter-spacing: var(--md-sys-typescale-emphasized-body-md-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-body-sm { - font: var(--md-sys-typescale-body-sm); - letter-spacing: var(--md-sys-typescale-body-sm-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-body-sm { - font: var(--md-sys-typescale-emphasized-body-sm); - letter-spacing: var(--md-sys-typescale-emphasized-body-sm-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-label-lg { - font: var(--md-sys-typescale-label-lg); - letter-spacing: var(--md-sys-typescale-label-lg-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-label-lg { - font: var(--md-sys-typescale-emphasized-label-lg); - letter-spacing: var(--md-sys-typescale-emphasized-label-lg-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-label-md { - font: var(--md-sys-typescale-label-md); - letter-spacing: var(--md-sys-typescale-label-md-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-label-md { - font: var(--md-sys-typescale-emphasized-label-md); - letter-spacing: var(--md-sys-typescale-emphasized-label-md-tracking); - font-variation-settings: "ROND" 100; -} - -@utility type-label-sm { - font: var(--md-sys-typescale-label-sm); - letter-spacing: var(--md-sys-typescale-label-sm-tracking); - font-variation-settings: normal; -} - -@utility type-emphasized-label-sm { - font: var(--md-sys-typescale-emphasized-label-sm); - letter-spacing: var(--md-sys-typescale-emphasized-label-sm-tracking); - font-variation-settings: "ROND" 100; -} diff --git a/src/Testing/DesignGuard.php b/src/Testing/DesignGuard.php index 682235b5..97e64b3c 100644 --- a/src/Testing/DesignGuard.php +++ b/src/Testing/DesignGuard.php @@ -10,9 +10,9 @@ use Symfony\Component\Finder\Finder; * Finds what compiles to nothing and fails silently: maryUI tags, daisyUI classes, colours the * theme does not declare, icon names that are not Material Symbols, Tailwind's breakpoint * prefixes and the radius, shadow, type-size, weight, leading, tracking, easing and duration - * scales that tokens/theme.css clears for M3's own, and colours written as a literal value - * instead of a role — plus whatever an application bans on top (roles its own design rules - * leave out, the two absolutes, opacity used as emphasis, patterns it has retired). + * scales M3's own sets replace, and colours written as a literal value instead of a role — plus + * whatever an application bans on top (roles its own design rules leave out, the two absolutes, + * opacity used as emphasis, patterns it has retired). * * expect(DesignGuard::scan([resource_path('views'), resource_path('js'), app_path()]) * ->forbidColours(['tertiary', 'primary-container']) @@ -52,10 +52,10 @@ class DesignGuard protected const string OPACITY_INK = '/(? 'medium', @@ -293,7 +293,7 @@ class DesignGuard /** * The radius, shadow, type-size, weight, leading, tracking, easing and duration utilities - * Tailwind ships and tokens/theme.css clears. + * Tailwind ships and M3's own scales replace. * * @return list */ diff --git a/tests/Feature/Components/ActionStylesheetsTest.php b/tests/Feature/Components/ActionStylesheetsTest.php index 618064f9..4d1a050c 100644 --- a/tests/Feature/Components/ActionStylesheetsTest.php +++ b/tests/Feature/Components/ActionStylesheetsTest.php @@ -61,8 +61,8 @@ it('imports the stylesheet of every component its view renders', function (strin preg_match_all('/unique() - // A component still written for Tailwind has no stylesheet of its own to import yet; its - // old stylesheet, if it has one, lives in tailwind.css without the layer statement. + // A rendered tag that is not a components/ stylesheet at all (a layout component's, e.g. + // ) has no import of its own to check here. ->filter(fn (string $tag): bool => is_file(ComponentStylesheet::path($tag)) && str_contains(File::get(ComponentStylesheet::path($tag)), '@layer material.components')) ->map(fn (string $tag): string => "./{$tag}.css") ->values() diff --git a/tests/Feature/Components/ContainmentStylesheetsTest.php b/tests/Feature/Components/ContainmentStylesheetsTest.php index 9fccff7c..afa7d382 100644 --- a/tests/Feature/Components/ContainmentStylesheetsTest.php +++ b/tests/Feature/Components/ContainmentStylesheetsTest.php @@ -90,8 +90,8 @@ it('imports the stylesheet of every component its view renders', function (strin preg_match_all('/unique() - // A component still written for Tailwind has no stylesheet of its own to import yet; its - // old stylesheet, if it has one, lives in tailwind.css without the layer statement. + // A rendered tag that is not a components/ stylesheet at all (a layout component's, e.g. + // ) has no import of its own to check here. ->filter(fn (string $tag): bool => is_file(ComponentStylesheet::path($tag)) && str_contains(File::get(ComponentStylesheet::path($tag)), '@layer material.components')) ->map(fn (string $tag): string => "./{$tag}.css") ->values() diff --git a/tests/Feature/Components/DataTest.php b/tests/Feature/Components/DataTest.php index 72ef1918..f606d757 100644 --- a/tests/Feature/Components/DataTest.php +++ b/tests/Feature/Components/DataTest.php @@ -26,8 +26,7 @@ it('draws 52px rows, 36px dense ones, from its stylesheet in the components laye ->toMatch('/\\[data-md-table\\] \\{\\s*--cell-x: 12px;\\s*--cell-y: var\\(--md-sys-measurement-space200\\);/') ->toMatch('/\\[data-md-table\\]\\[data-md-dense\\] \\{\\s*--cell-y: var\\(--md-sys-measurement-space100\\);/') ->toContain('[data-md-table] :where(tbody tr[aria-selected=\'true\'])') - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/table.css';") - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/tailwind.css'))->not->toContain('table.css'); + ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/table.css';"); }); it('sorts by its column, ascending first and then flipping', function () { diff --git a/tests/Feature/Components/FieldTest.php b/tests/Feature/Components/FieldTest.php index 116b5f74..87d27290 100644 --- a/tests/Feature/Components/FieldTest.php +++ b/tests/Feature/Components/FieldTest.php @@ -235,8 +235,7 @@ it('keeps the field\'s chrome in its own stylesheet in the components layer', fu ->toContain("@import './icon.css';") ->toContain('[data-md-field-box]') ->not->toMatch('/(?and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/field.css';") - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/tailwind.css'))->not->toContain('field.css'); + ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/field.css';"); }); it('takes a custom control marked as the field\'s control, and a hint class', function () { diff --git a/tests/Feature/Components/InputStylesheetsTest.php b/tests/Feature/Components/InputStylesheetsTest.php index ba1fb401..6c5d8feb 100644 --- a/tests/Feature/Components/InputStylesheetsTest.php +++ b/tests/Feature/Components/InputStylesheetsTest.php @@ -136,8 +136,8 @@ it('imports the stylesheet of every component its view renders', function (strin preg_match_all('/unique() - // A component still written for Tailwind has no stylesheet of its own to import yet; its - // old stylesheet, if it has one, lives in tailwind.css without the layer statement. + // A rendered tag that is not a components/ stylesheet at all (a layout component's, e.g. + // ) has no import of its own to check here. ->filter(fn (string $tag): bool => is_file(ComponentStylesheet::path($tag)) && str_contains(File::get(ComponentStylesheet::path($tag)), '@layer material.components')) ->map(fn (string $tag): string => "./{$tag}.css") ->values() @@ -193,6 +193,8 @@ it('imports the stylesheet of every component pagination\'s views render', funct preg_match_all('/unique() + // A rendered tag that is not a components/ stylesheet at all (a layout component's, e.g. + // ) has no import of its own to check here. ->filter(fn (string $tag): bool => is_file(ComponentStylesheet::path($tag)) && str_contains(File::get(ComponentStylesheet::path($tag)), '@layer material.components')) ->map(fn (string $tag): string => "./{$tag}.css") ->values() diff --git a/tests/Feature/Components/NavigationStylesheetsTest.php b/tests/Feature/Components/NavigationStylesheetsTest.php index bd8801a6..c014164c 100644 --- a/tests/Feature/Components/NavigationStylesheetsTest.php +++ b/tests/Feature/Components/NavigationStylesheetsTest.php @@ -128,8 +128,8 @@ it('imports the stylesheet of every component its view renders', function (strin return $tags[1]; }) ->unique() - // A component still written for Tailwind has no stylesheet of its own to import yet; its - // old stylesheet, if it has one, lives in tailwind.css without the layer statement. + // A rendered tag that is not a components/ stylesheet at all (a layout component's, e.g. + // ) has no import of its own to check here. ->filter(fn (string $tag): bool => is_file(ComponentStylesheet::path($tag)) && str_contains(File::get(ComponentStylesheet::path($tag)), '@layer material.components')) ->map(fn (string $tag): string => "./{$tag}.css") ->values() diff --git a/tests/Feature/Components/OverlayTest.php b/tests/Feature/Components/OverlayTest.php index ddc1f86e..8985c8bf 100644 --- a/tests/Feature/Components/OverlayTest.php +++ b/tests/Feature/Components/OverlayTest.php @@ -101,7 +101,6 @@ it('divides a scrolling body from its header and actions only while content is h // A token that reduced motion sets to zero, so there the rule simply appears. ->toContain('transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);') ->and(File::get(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/modal.css';") - ->and(File::get(__DIR__.'/../../../resources/css/tailwind.css'))->not->toContain('dialog.css') ->and(File::get(__DIR__.'/../../../resources/js/material.js'))->toContain("import './dialog.js'") ->and(File::get(__DIR__.'/../../../resources/js/dialog.js')) ->toContain("directive('dialog-dividers'") diff --git a/tests/Feature/Components/SearchTest.php b/tests/Feature/Components/SearchTest.php index bce71f3a..d7534a11 100644 --- a/tests/Feature/Components/SearchTest.php +++ b/tests/Feature/Components/SearchTest.php @@ -114,6 +114,5 @@ it('draws the bar and the view from its stylesheet, at M3\'s widths', function ( ->toContain('[data-md-search][data-md-full-screen] [data-md-search-view] {') ->toContain("[data-md-search][data-md-trigger='icon']:not([data-md-open]) [data-md-search-bar] {") ->not->toMatch('/\\d(?:\\.\\d+)?rem/') - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/search.css';") - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/tailwind.css'))->not->toContain('search.css'); + ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/search.css';"); }); diff --git a/tests/Feature/Components/SelectionTest.php b/tests/Feature/Components/SelectionTest.php index 2b3b539e..dbf23aa9 100644 --- a/tests/Feature/Components/SelectionTest.php +++ b/tests/Feature/Components/SelectionTest.php @@ -151,8 +151,7 @@ it('draws the checkbox from its stylesheet, on the row the selection controls sh ->and((string) file_get_contents(__DIR__.'/../../../resources/css/components/selection.css')) ->toContain('[data-md-selection-row]') ->toContain('@layer material.components') - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/checkbox.css';") - ->and((string) file_get_contents(__DIR__.'/../../../resources/css/tailwind.css'))->not->toContain('selection.css'); + ->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './components/checkbox.css';"); }); it('lays the radio group out from its stylesheet, inline only from 600px', function () { diff --git a/tests/Feature/ErrorPagesTest.php b/tests/Feature/ErrorPagesTest.php index 88dce129..151f76ec 100644 --- a/tests/Feature/ErrorPagesTest.php +++ b/tests/Feature/ErrorPagesTest.php @@ -97,7 +97,6 @@ it('lets the application\'s own error view win', function () { it('loads the application\'s Vite entries', function () { File::ensureDirectoryExists($this->temporary.'/build'); File::put($this->temporary.'/build/manifest.json', json_encode([ - 'workbench/resources/css/package.css' => ['file' => 'assets/package-probe.css', 'src' => 'workbench/resources/css/package.css', 'isEntry' => true], 'workbench/resources/css/app.css' => ['file' => 'assets/app-probe.css', 'src' => 'workbench/resources/css/app.css', 'isEntry' => true], 'workbench/resources/js/app.js' => ['file' => 'assets/app-probe.js', 'src' => 'workbench/resources/js/app.js', 'isEntry' => true], ])); @@ -107,7 +106,6 @@ it('loads the application\'s Vite entries', function () { $this->get('/abort/404') ->assertNotFound() - ->assertSee('build/assets/package-probe.css', false) ->assertSee('build/assets/app-probe.css', false) ->assertSee('build/assets/app-probe.js', false) ->assertDontSee('data-md-error-fallback', false); diff --git a/tests/Feature/StylesheetsTest.php b/tests/Feature/StylesheetsTest.php index 537d590d..c539c538 100644 --- a/tests/Feature/StylesheetsTest.php +++ b/tests/Feature/StylesheetsTest.php @@ -10,14 +10,13 @@ use NoNameWeb\LivewireMaterial\Support\Layout; * would nest the layer twice); then its own `@layer material.` blocks. The only rules outside * a layer are foundation/hidden.css's two `!important` ones. * - * Every package component and layout stylesheet is plain CSS now (plan step 36), so the shape, - * Tailwind-free and breakpoint checks below run over the whole tree `all.css` reaches (foundation, - * layout and components together) rather than the foundation alone — everything but - * `tailwind.css` and `tokens/theme.css`/`tokens/utilities.css`, which stay Tailwind until plan - * step 39 and are simply never reached from `all.css`. A component's own values (colours as - * roles, shadows as elevation levels, and so on) are each group's own concern, in - * tests/Feature/Components/*StylesheetsTest.php; `bundle()`, the PHP bundler `all.css` is built - * for, is tests/Feature/StylesheetsBundleTest.php's. + * Every package component and layout stylesheet is plain CSS now (plan step 36), and Tailwind + * itself is gone from the package (plan step 39), so the shape, Tailwind-free and breakpoint checks + * below run over the whole tree `all.css` reaches (foundation, layout and components together) + * rather than the foundation alone, and — one file it does not reach — `showcase.css`, checked on + * its own further down. A component's own values (colours as roles, shadows as elevation levels, + * and so on) are each group's own concern, in tests/Feature/Components/*StylesheetsTest.php; + * `bundle()`, the PHP bundler `all.css` is built for, is tests/Feature/StylesheetsBundleTest.php's. */ const MATERIAL_LAYER_STATEMENT = '@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;'; @@ -178,9 +177,9 @@ function foundationStylesheets(): array /** * Everything all.css reaches: the foundation, every layout stylesheet and every component - * stylesheet, each once. What a check runs over now that every one of them is plain CSS (plan - * step 36) — `tailwind.css` and its two token files are never in this tree, since all.css does - * not import them. + * stylesheet, each once. Every one of them is plain CSS (plan step 36), and Tailwind itself is + * gone from the package (plan step 39) — `tailwindcss`, `tailwind.css` and its two token files no + * longer exist, so there is nothing left for this tree to exclude. * * @return list */ @@ -194,7 +193,7 @@ function stylesheetName(string $file): string return substr($file, strlen(stylesheetPath()) + 1); } -it('brings every foundation file and text.css into the foundation, and nothing of Tailwind', function () { +it('brings every foundation file and text.css into the foundation, and nothing else', function () { $foundation = array_map(stylesheetName(...), foundationStylesheets()); $parts = collect(File::files(stylesheetPath('foundation'))) @@ -207,11 +206,24 @@ it('brings every foundation file and text.css into the foundation, and nothing o ->toBe(['reset.css', 'hidden.css', 'tokens.css', 'base.css', 'interaction.css', 'text.css']) ->and($foundation) ->toContain('tokens/scheme.css', 'tokens/shape.css', 'tokens/elevation.css', 'tokens/motion.css', 'tokens/type.css', 'tokens/state.css', 'tokens/spacing.css', 'tokens/font.css') - // The Tailwind half: the theme, the token utilities and the components still written for it. - ->and(array_values(array_intersect($foundation, ['tokens/theme.css', 'tokens/utilities.css', 'tailwind.css'])))->toBe([]) ->and(array_values(preg_grep('/^components\//', $foundation)))->toBe([]); }); +it('leaves no stylesheet under resources/css/ outside all.css or showcase.css', function () { + // The full tree now that Tailwind is gone (plan step 39): every .css file on disk, not just the + // ones a bundler happens to reach — a stray or orphaned file would show up here even though + // nothing imports it, which the checks above (walking @import from all.css) cannot catch. + $onDisk = collect(File::allFiles(stylesheetPath())) + ->filter(fn (SplFileInfo $file): bool => $file->getExtension() === 'css') + ->map(fn (SplFileInfo $file): string => stylesheetName((string) $file->getRealPath())) + ->sort() + ->values(); + + $reached = collect(allStylesheets())->map(stylesheetName(...))->push('showcase.css')->sort()->values(); + + expect($onDisk->all())->toBe($reached->all()); +}); + it('opens every stylesheet all.css reaches with a header, the layer statement and plain imports', function () { foreach (allStylesheets() as $file) { $name = stylesheetName($file); @@ -548,17 +560,19 @@ it('hides an element below and from every breakpoint but compact, and nothing el expect($actual)->toBe($expected); }); -it('gives every md-type class the declarations of its type utility', function () { - preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(stylesheetPath('tokens/utilities.css')), $matches, PREG_SET_ORDER); +it('gives every md-type class exactly font, letter-spacing and font-variation-settings', function () { + // Tailwind's tokens/utilities.css used to declare the same 30 styles as `type-*` utility + // blocks, and this test proved text.css's `.md-type-*` classes matched them; deleted with + // Tailwind (plan step 39), text.css is the only copy left, so the shape it gives each class is + // asserted directly rather than cross-checked against a second copy. + preg_match_all('/\.md-(type-[\w-]+) \{\n(.*?)\n {4}\}/s', File::get(stylesheetPath('text.css')), $matches, PREG_SET_ORDER); - $utilities = collect($matches)->mapWithKeys(fn (array $match): array => ["md-{$match[1]}" => stylesheetDeclarations($match[2])]); - $text = File::get(stylesheetPath('text.css')); + $classes = collect($matches)->mapWithKeys(fn (array $match): array => ["md-{$match[1]}" => stylesheetDeclarations($match[2])]); - expect($utilities)->toHaveCount(30); + expect($classes)->toHaveCount(30); - foreach ($utilities as $class => $declarations) { - expect(stylesheetDeclarations(stylesheetBlock($text, ".{$class}")))->toBe($declarations, $class) - ->and(array_keys($declarations))->toBe(['font', 'letter-spacing', 'font-variation-settings']); + foreach ($classes as $class => $declarations) { + expect(array_keys($declarations))->toBe(['font', 'letter-spacing', 'font-variation-settings'], $class); } }); @@ -611,57 +625,28 @@ it('ships exactly the documented text classes, each ink an M3 role', function () } }); -it('draws the interaction classes as the utilities the Tailwind components still use', function () { - $utilities = File::get(stylesheetPath('tokens/utilities.css')); - $interaction = File::get(stylesheetPath('foundation/interaction.css')); +// A test used to prove foundation/interaction.css's `.md-*` classes matched tokens/utilities.css's +// utility blocks byte for byte apart from two deliberate differences, because the components +// still written in Tailwind read the utilities while every other component read the classes. +// Deleted with Tailwind (plan step 39): every component reads the classes now, there is no second +// copy left to drift from, and interaction.css's own StylesheetsTest coverage above (the layer it +// writes into, no Tailwind directive) already holds it to the same shape every other foundation +// file keeps to. - $normalise = fn (string $body): string => trim((string) preg_replace('/\s+/', ' ', $body)); - - foreach (['state-layer', 'focus-ring', 'touch-target', 'link'] as $name) { - $class = stylesheetBlock($interaction, ".md-{$name}"); - - expect($normalise(str_replace( - // The two deliberate differences: the data-md-* hook in place of the old one, and M3's - // 48 CSS pixels for the target where the utility reads 3rem. - ['&[data-md-dragged]', 'var(--md-sys-measurement-space600)'], - ['&[data-dragged]', '3rem'], - $class, - )))->toBe($normalise(stylesheetBlock($utilities, "@utility {$name}")), $name); - } - - expect(stylesheetBlock($interaction, '.md-state-layer'))->toContain('&[data-md-dragged]::before') - ->not->toContain('[data-dragged]') - ->and(stylesheetBlock($interaction, '.md-touch-target'))->toContain('min-width: var(--md-sys-measurement-space600);'); -}); - -it('builds the package in a Workbench entry of its own, with the material layers between Tailwind\'s preflight and its utilities', function () { - $package = stylesheetWithoutComments(File::get(__DIR__.'/../../workbench/resources/css/package.css')); +it('builds the package in the Workbench\'s one CSS entry, with no Tailwind left to sit between', function () { $app = stylesheetWithoutComments(File::get(__DIR__.'/../../workbench/resources/css/app.css')); - // Both entries open by ordering the layers, so the order holds whichever the page links first: - // above preflight, whose `* { padding: 0 }` would otherwise beat a component's padding, and - // below the utilities. - foreach (['package.css' => $package, 'app.css' => $app] as $name => $css) { - expect(trim($css))->toStartWith('@layer properties, theme, base, material, components, utilities;', $name); - } - - // The package's CSS never shares an entry with Tailwind: `@tailwindcss/vite` inlines the - // imports of an entry that uses Tailwind without deduplicating them, so every shared component - // stylesheet would repeat later in the cascade instead of landing once, as it does for an - // application (StylesheetsBundleTest.php pins that against a real Vite build). - expect($package)->toContain("@import '../../../resources/css/all.css';") + // Opens by ordering the layers, so the order holds whichever the page links first — an + // application with Tailwind of its own still opens its own entry the same way (its header). + expect(trim($app))->toStartWith(MATERIAL_LAYER_STATEMENT) + ->toContain("@import '../../../resources/css/all.css';") + ->toContain("@import '../../../resources/css/showcase.css';") ->toContain("@import './material-scheme.css';") - ->not->toContain('tailwind') - ->not->toMatch('/@(?:source|theme|utility|variant|custom-variant|apply)\b/') - ->and($app)->toContain("@import 'tailwindcss'") - ->toContain("@import '../../../resources/css/tailwind.css';") - ->not->toContain('all.css') - ->not->toContain('foundation.css') - ->not->toContain('/components/') - ->not->toContain('material-scheme.css') - ->and(File::get(__DIR__.'/../../vite.config.js'))->toContain("'workbench/resources/css/package.css', 'workbench/resources/css/app.css'") + ->not->toMatch('/@(?:tailwind|source|theme|utility|variant|custom-variant|apply|config|plugin|reference)\b/') + ->and(File::get(__DIR__.'/../../vite.config.js')) + ->toContain("input: ['workbench/resources/css/app.css', 'workbench/resources/js/app.js']") + ->not->toContain('tailwindcss') ->and(config('livewire-material.showcase.vite'))->toBe([ - 'workbench/resources/css/package.css', 'workbench/resources/css/app.css', 'workbench/resources/js/app.js', ]); diff --git a/tests/Feature/TokensTest.php b/tests/Feature/TokensTest.php index 84a8caf1..05f30498 100644 --- a/tests/Feature/TokensTest.php +++ b/tests/Feature/TokensTest.php @@ -37,14 +37,15 @@ function typeStyles(): array } /** - * The body of every `@utility type-…` block, keyed by utility name. The utilities live in - * tokens/utilities.css, apart from the tokens, so the foundation imports no Tailwind directive. + * The body of every `.md-type-…` class in text.css, keyed by class name without the `md-` prefix + * (`type-display-lg`, `type-emphasized-display-lg`, …). Plain CSS now (plan step 39 deleted the + * Tailwind utilities they used to be); text.css is theirs alone. * * @return array */ function typeUtilities(): array { - preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/utilities.css')), $matches, PREG_SET_ORDER); + preg_match_all('/\.md-(type-[\w-]+) \{\n(.*?)\n {4}\}/s', File::get(packageCss('text.css')), $matches, PREG_SET_ORDER); return array_combine(array_column($matches, 1), array_column($matches, 2)); } @@ -84,26 +85,20 @@ it('ships M3\'s medium and high contrast levels beside the standard one', functi } }); -it('turns every role into a Tailwind colour', function () { - $roles = array_keys(json_decode(File::get(packageCss('tokens/scheme.json')), true)['light']); - $theme = File::get(packageCss('tokens/theme.css')); - - foreach ($roles as $role) { - expect($theme)->toContain("--color-{$role}: var(--md-sys-color-{$role});"); +// Tailwind's theme.css used to turn every scheme role into a `--color-*` Tailwind colour, in an +// inline theme block so it resolved on the element and a nested data-theme still repainted it +// rather than reading a value computed once on :root. Both went with Tailwind (plan step 39): the +// first fact is already the scheme test above (every role a `--md-sys-color-*` custom property, +// light and dark); the second no longer has anything to hold, because no file replaces theme.css's +// alias — every package rule reads `--md-sys-color-*` directly at its point of use, so there is no +// second custom property that could be computed once on :root and go stale under a nested +// data-theme in the first place. +it('never aliases a colour role to a second custom property resolved once on :root', function () { + foreach (File::allFiles(packageCss()) as $file) { + expect($file->getContents())->not->toMatch('/--color-[\w-]+:\s*var\(--md-sys-color-/', $file->getRelativePathname()); } }); -it('resolves colour utilities on the element, so a nested data-theme repaints them', function () { - $theme = File::get(packageCss('tokens/theme.css')); - - preg_match_all('/@theme inline \{(.*?)\}/s', $theme, $inline); - - expect(implode("\n", $inline[1])) - ->toContain('--color-primary: var(--md-sys-color-primary);') - ->toContain('--color-body: var(--md-sys-color-on-surface-variant);') - ->not->toMatch('/--[\w-]+:\s*#/'); -}); - it('leaves the choice of theme and of contrast to the head script, never to a media query', function () { foreach (File::allFiles(packageCss()) as $file) { expect($file->getContents()) diff --git a/vite.config.js b/vite.config.js index 41cc97e1..4f152891 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,16 +1,14 @@ import { defineConfig } from 'vite' import laravel from 'laravel-vite-plugin' -import tailwindcss from '@tailwindcss/vite' // Builds the Workbench, the Laravel app the showcase and the browser tests run in. // Applications never use this file; they import the package's CSS and JS into their own build. export default defineConfig({ plugins: [ laravel({ - input: ['workbench/resources/css/package.css', 'workbench/resources/css/app.css', 'workbench/resources/js/app.js'], + input: ['workbench/resources/css/app.css', 'workbench/resources/js/app.js'], publicDirectory: 'workbench/public', refresh: ['resources/views/**', 'workbench/resources/views/**'], }), - tailwindcss(), ], }) diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php index 9fa1cfd7..55f13d10 100644 --- a/workbench/app/Providers/WorkbenchServiceProvider.php +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -19,8 +19,8 @@ class WorkbenchServiceProvider extends ServiceProvider public function boot(): void { config(['livewire-material.showcase.vite' => [ - // The package's CSS apart from Tailwind's, so Vite deduplicates its imports (package.css). - 'workbench/resources/css/package.css', + // The package's whole CSS in the Workbench's one entry now that Tailwind is gone + // (plan step 39), and the JavaScript. 'workbench/resources/css/app.css', 'workbench/resources/js/app.js', ]]); diff --git a/workbench/resources/css/app.css b/workbench/resources/css/app.css index 16fe7f68..0c4e5a72 100644 --- a/workbench/resources/css/app.css +++ b/workbench/resources/css/app.css @@ -1,11 +1,16 @@ -/* The Workbench's Tailwind entry, for the classes the showcase still writes, with explicit sources - so the plans in docs/ are not scanned for class names. tailwind.css brings the theme and token - utilities without declaring the tokens a second time. The package's own CSS is package.css, an - entry of its own (its header says why); the layer statement is the same in both, so the - `material` layers sit between Tailwind's preflight and its utilities whichever loads first. */ -@layer properties, theme, base, material, components, utilities; -@import 'tailwindcss' source(none); -@import '../../../resources/css/tailwind.css'; +/* The package's CSS for the Workbench, built the way an application without Tailwind builds it + (plan step 39: Tailwind leaves the whole stack): all.css (the foundation, every layout and every + component stylesheet), showcase.css (the showcase's own chrome, so a real Vite build — an error + page's fallback-free path, a browser-test probe page's `@vite()` — carries it too, even though + the showcase's own pages take their CSS from the bundle route instead) and the Workbench's + scheme, in the one CSS entry the Workbench now needs. Vite's own CSS pipeline inlines the + imports here and keeps a stylesheet several components import once, at its first position — the + order an application gets. -@source '../../../resources/views'; -@source '../../../src'; + Opens with the same layer statement every package stylesheet does, so the `material` layers hold + their place whichever file a page links first; an application with no Tailwind of its own needs + nothing more than this. */ +@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; +@import '../../../resources/css/all.css'; +@import '../../../resources/css/showcase.css'; +@import './material-scheme.css'; diff --git a/workbench/resources/css/package.css b/workbench/resources/css/package.css deleted file mode 100644 index debfc3e1..00000000 --- a/workbench/resources/css/package.css +++ /dev/null @@ -1,16 +0,0 @@ -/* The package's CSS for the Workbench, built the way an application without Tailwind builds it: - all.css (the foundation, every layout and every component stylesheet) and the Workbench's - scheme, in an entry Tailwind never touches. Vite's own CSS pipeline inlines the imports here and - keeps a stylesheet several components import once, at its first position — the order an - application gets. `@tailwindcss/vite` inlines the imports of an entry that uses Tailwind without - that deduplication, so all.css imported beside `tailwindcss` would repeat every shared rule later - in the cascade; app.css keeps Tailwind, for the showcase's classes, apart. - - Both entries open with the same layer statement, so the order holds whichever the page links - first: the `material` layers above Tailwind's preflight (`base`), whose `* { padding: 0 }` would - otherwise beat a component's padding, and below its `components` and `utilities`. `properties` - is the layer Tailwind hoists to the top of its output (the `--tw-*` fallbacks for a browser - without `@property`); named first, it stays lowest, as it was when both shared one entry. */ -@layer properties, theme, base, material, components, utilities; -@import '../../../resources/css/all.css'; -@import './material-scheme.css';