From d059efca258da7ae5116e829189a492824ac1d87 Mon Sep 17 00:00:00 2001 From: Romain Hamel Date: Mon, 14 Apr 2025 10:47:26 +0200 Subject: [PATCH] feat(unplugin): routing support for inertia (#3845) Co-authored-by: Benjamin Canac --- package.json | 12 +- pnpm-lock.yaml | 263 +++++++++++++++++++++++- src/plugins/components.ts | 9 + src/plugins/nuxt-environment.ts | 6 +- src/runtime/inertia/components/Link.vue | 181 ++++++++++++++++ src/runtime/inertia/stubs.ts | 98 +++++++++ src/runtime/vue/components/Link.vue | 4 +- src/unplugin.ts | 6 +- 8 files changed, 564 insertions(+), 15 deletions(-) create mode 100644 src/runtime/inertia/components/Link.vue create mode 100644 src/runtime/inertia/stubs.ts diff --git a/package.json b/package.json index a68cfdea..14513864 100644 --- a/package.json +++ b/package.json @@ -152,9 +152,7 @@ "unplugin": "^2.3.0", "unplugin-auto-import": "^19.1.2", "unplugin-vue-components": "^28.4.1", - "vaul-vue": "^0.4.1", - "vue": "^3.5.13", - "vue-router": "^4.5.0" + "vaul-vue": "^0.4.1" }, "devDependencies": { "@nuxt/eslint-config": "^1.3.0", @@ -172,14 +170,19 @@ "vue-tsc": "^2.2.0" }, "peerDependencies": { + "@inertiajs/vue3": "^2.0.7", "joi": "^17.13.0", "superstruct": "^2.0.0", "typescript": "^5.6.3", "valibot": "^1.0.0", + "vue-router": "^4.5.0", "yup": "^1.6.0", "zod": "^3.24.0" }, "peerDependenciesMeta": { + "@inertiajs/vue3": { + "optional": true + }, "joi": { "optional": true }, @@ -189,6 +192,9 @@ "superstruct": { "optional": true }, + "vue-router": { + "optional": true + }, "yup": { "optional": true }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 818deb53..045398b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,9 @@ importers: '@iconify/vue': specifier: ^4.3.0 version: 4.3.0(vue@3.5.13(typescript@5.8.3)) + '@inertiajs/vue3': + specifier: ^2.0.7 + version: 2.0.7(vue@3.5.13(typescript@5.8.3)) '@internationalized/date': specifier: ^3.7.0 version: 3.7.0 @@ -60,7 +63,7 @@ importers: version: 13.1.0(vue@3.5.13(typescript@5.8.3)) '@vueuse/integrations': specifier: ^13.1.0 - version: 13.1.0(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3)) + version: 13.1.0(axios@1.8.4)(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3)) colortranslator: specifier: ^4.1.0 version: 4.1.0 @@ -151,9 +154,6 @@ importers: vaul-vue: specifier: ^0.4.1 version: 0.4.1(reka-ui@2.2.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3)) - vue: - specifier: ^3.5.13 - version: 3.5.13(typescript@5.8.3) vue-router: specifier: ^4.5.0 version: 4.5.0(vue@3.5.13(typescript@5.8.3)) @@ -262,7 +262,7 @@ importers: version: 4.1.2(rollup@4.34.9) '@vueuse/integrations': specifier: ^13.1.0 - version: 13.1.0(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3)) + version: 13.1.0(axios@1.8.4)(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3)) '@vueuse/nuxt': specifier: ^13.1.0 version: 13.1.0(magicast@0.3.5)(nuxt@3.16.2(@parcel/watcher@2.5.1)(@types/node@22.13.14)(better-sqlite3@11.9.1)(db0@0.3.1(better-sqlite3@11.9.1))(eslint@9.24.0(jiti@2.4.2))(ioredis@5.6.0)(lightningcss@1.29.2)(magicast@0.3.5)(meow@13.2.0)(optionator@0.9.4)(rollup@4.34.9)(terser@5.39.0)(typescript@5.8.3)(vite@6.2.6(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.1))(vue-tsc@2.2.0(typescript@5.8.3))(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3)) @@ -1170,6 +1170,14 @@ packages: cpu: [x64] os: [win32] + '@inertiajs/core@2.0.7': + resolution: {integrity: sha512-3xJHeeIQCc6NW0Tsh22fqT/B8j30P2wWLpGswv0ew3w8MoyYQTCNY/MeGwYvmej5q1V+BiK1S8iB+BpRXhwpJw==} + + '@inertiajs/vue3@2.0.7': + resolution: {integrity: sha512-LaRfp/Yjt6/xhhug28iSmxtTxJg/5FoEZVTIgMRlOamMELh3qFajeQglofv7oUVUDW4kIGVxSEIOHT6sRTVKkw==} + peerDependencies: + vue: ^3.0.0 + '@inquirer/checkbox@4.1.4': resolution: {integrity: sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==} engines: {node: '>=18'} @@ -2828,6 +2836,9 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomically@2.0.3: resolution: {integrity: sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==} @@ -2838,6 +2849,9 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@1.8.4: + resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} + b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -2977,6 +2991,14 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -3123,6 +3145,10 @@ packages: colortranslator@4.1.0: resolution: {integrity: sha512-bwa5awaMnQ6dpm9D3nbsFwUr6x6FrTKmxPdolNtSYfxCNR7ZM93GG1OF5Y3Sy1LvYdalb3riKC9uTn0X5NB36g==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -3466,6 +3492,10 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -3545,6 +3575,10 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -3663,9 +3697,28 @@ packages: errx@0.1.0: resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@1.6.0: resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-toolkit@1.34.1: + resolution: {integrity: sha512-OA6cd94fJV9bm8dWhIySkWq4xV+rAQnBZUr2dnpXam0QJ8c+hurLbKA8/QooL9Mx4WCAxvIDsiEkid5KPQ5xgQ==} + esbuild@0.24.2: resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} @@ -3945,6 +3998,15 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + fontaine@0.5.0: resolution: {integrity: sha512-vPDSWKhVAfTx4hRKT777+N6Szh2pAosAuzLpbppZ6O3UdD/1m6OlHjNcC3vIbgkRTIcLjzySLHXzPeLO2rE8cA==} @@ -3955,6 +4017,10 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -4006,9 +4072,17 @@ packages: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + get-port-please@3.1.2: resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-source@2.0.12: resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} @@ -4107,6 +4181,10 @@ packages: resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} engines: {node: '>=18'} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} @@ -4136,6 +4214,14 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -4759,6 +4845,10 @@ packages: marky@1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} @@ -5198,6 +5288,10 @@ packages: engines: {node: ^14.16.0 || >=16.10.0} hasBin: true + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + ofetch@1.4.1: resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} @@ -5676,6 +5770,10 @@ packages: engines: {node: '>=18'} hasBin: true + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + quansync@0.2.10: resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} @@ -5993,6 +6091,22 @@ packages: shiki@3.2.1: resolution: {integrity: sha512-VML/2o1/KGYkEf/stJJ+s9Ypn7jUKQPomGLGYso4JJFMFxVDyPNsjsI3MB3KLjlMOeH44gyaPdXC6rik2WXvUQ==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -7817,6 +7931,22 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true + '@inertiajs/core@2.0.7': + dependencies: + axios: 1.8.4 + deepmerge: 4.3.1 + qs: 6.14.0 + transitivePeerDependencies: + - debug + + '@inertiajs/vue3@2.0.7(vue@3.5.13(typescript@5.8.3))': + dependencies: + '@inertiajs/core': 2.0.7 + es-toolkit: 1.34.1 + vue: 3.5.13(typescript@5.8.3) + transitivePeerDependencies: + - debug + '@inquirer/checkbox@4.1.4(@types/node@22.13.14)': dependencies: '@inquirer/core': 10.1.9(@types/node@22.13.14) @@ -9725,12 +9855,13 @@ snapshots: '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.8.3)) vue: 3.5.13(typescript@5.8.3) - '@vueuse/integrations@13.1.0(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3))': + '@vueuse/integrations@13.1.0(axios@1.8.4)(fuse.js@7.1.0)(sortablejs@1.15.6)(vue@3.5.13(typescript@5.8.3))': dependencies: '@vueuse/core': 13.1.0(vue@3.5.13(typescript@5.8.3)) '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.8.3)) vue: 3.5.13(typescript@5.8.3) optionalDependencies: + axios: 1.8.4 fuse.js: 7.1.0 sortablejs: 1.15.6 @@ -9902,6 +10033,8 @@ snapshots: async@3.2.6: {} + asynckit@0.4.0: {} + atomically@2.0.3: dependencies: stubborn-fs: 1.2.5 @@ -9917,6 +10050,14 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 + axios@1.8.4: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + b4a@1.6.7: {} bail@2.0.2: {} @@ -10059,6 +10200,16 @@ snapshots: cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} camelcase@8.0.0: {} @@ -10209,6 +10360,10 @@ snapshots: colortranslator@4.1.0: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} commander@10.0.1: {} @@ -10542,6 +10697,8 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 + delayed-stream@1.0.0: {} + denque@2.1.0: {} depd@2.0.0: {} @@ -10604,6 +10761,12 @@ snapshots: dotenv@16.4.7: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + duplexer@0.1.2: {} eastasianwidth@0.2.0: {} @@ -10707,8 +10870,25 @@ snapshots: errx@0.1.0: {} + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@1.6.0: {} + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-toolkit@1.34.1: {} + esbuild@0.24.2: optionalDependencies: '@esbuild/aix-ppc64': 0.24.2 @@ -11107,6 +11287,8 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.9: {} + fontaine@0.5.0: dependencies: '@capsizecss/metrics': 2.2.0 @@ -11136,6 +11318,13 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + fraction.js@4.3.7: {} framer-motion@12.5.0(react@19.1.0): @@ -11165,8 +11354,26 @@ snapshots: get-east-asian-width@1.3.0: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + get-port-please@3.1.2: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-source@2.0.12: dependencies: data-uri-to-buffer: 2.0.2 @@ -11295,6 +11502,8 @@ snapshots: slash: 5.1.0 unicorn-magic: 0.3.0 + gopd@1.2.0: {} + graceful-fs@4.2.10: {} graceful-fs@4.2.11: {} @@ -11333,6 +11542,12 @@ snapshots: has-flag@4.0.0: {} + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -12015,6 +12230,8 @@ snapshots: marky@1.2.5: {} + math-intrinsics@1.1.0: {} + mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -12864,6 +13081,8 @@ snapshots: pkg-types: 2.1.0 tinyexec: 0.3.2 + object-inspect@1.13.4: {} + ofetch@1.4.1: dependencies: destr: 2.0.5 @@ -13384,6 +13603,10 @@ snapshots: - typescript - utf-8-validate + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + quansync@0.2.10: {} queue-microtask@1.2.3: {} @@ -13894,6 +14117,34 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} signal-exit@4.1.0: {} diff --git a/src/plugins/components.ts b/src/plugins/components.ts index 51236c50..e5b96350 100644 --- a/src/plugins/components.ts +++ b/src/plugins/components.ts @@ -18,6 +18,9 @@ export default function ComponentImportPlugin(options: NuxtUIOptions & { prefix: const overrides = globSync('**/*.vue', { cwd: join(runtimeDir, 'vue/components') }) const overrideNames = new Set(overrides.map(c => `${options.prefix}${c.replace(/\.vue$/, '')}`)) + const inertiaOverrides = globSync('**/*.vue', { cwd: join(runtimeDir, 'inertia/components') }) + const inertiaOverrideNames = new Set(inertiaOverrides.map(c => `${options.prefix}${c.replace(/\.vue$/, '')}`)) + const pluginOptions = defu(options.components, { dts: options.dts ?? true, exclude: [ @@ -27,6 +30,9 @@ export default function ComponentImportPlugin(options: NuxtUIOptions & { prefix: ], resolvers: [ (componentName) => { + if (options.inertia && inertiaOverrideNames.has(componentName)) { + return { name: 'default', from: join(runtimeDir, 'inertia/components', `${componentName.slice(options.prefix.length)}.vue`) } + } if (overrideNames.has(componentName)) return { name: 'default', from: join(runtimeDir, 'vue/components', `${componentName.slice(options.prefix.length)}.vue`) } if (componentNames.has(componentName)) @@ -55,6 +61,9 @@ export default function ComponentImportPlugin(options: NuxtUIOptions & { prefix: } const filename = id.match(/([^/]+)\.vue$/)?.[1] + if (filename && options.inertia && inertiaOverrideNames.has(`${options.prefix}${filename}`)) { + return join(runtimeDir, 'inertia/components', `${filename}.vue`) + } if (filename && overrideNames.has(`${options.prefix}${filename}`)) { return join(runtimeDir, 'vue/components', `${filename}.vue`) } diff --git a/src/plugins/nuxt-environment.ts b/src/plugins/nuxt-environment.ts index 048830f1..0ad46981 100644 --- a/src/plugins/nuxt-environment.ts +++ b/src/plugins/nuxt-environment.ts @@ -3,13 +3,13 @@ import { normalize } from 'pathe' import { resolvePathSync } from 'mlly' import MagicString from 'magic-string' -import { runtimeDir } from '../unplugin' +import { runtimeDir, type NuxtUIOptions } from '../unplugin' /** * This plugin normalises Nuxt environment (#imports) and `import.meta.client` within the Nuxt UI components. */ -export default function NuxtEnvironmentPlugin() { - const stubPath = resolvePathSync('../runtime/vue/stubs', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }) +export default function NuxtEnvironmentPlugin(options: NuxtUIOptions) { + const stubPath = resolvePathSync(options.inertia ? '../runtime/inertia/stubs' : '../runtime/vue/stubs', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }) return { name: 'nuxt:ui', diff --git a/src/runtime/inertia/components/Link.vue b/src/runtime/inertia/components/Link.vue new file mode 100644 index 00000000..566d2e87 --- /dev/null +++ b/src/runtime/inertia/components/Link.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/src/runtime/inertia/stubs.ts b/src/runtime/inertia/stubs.ts new file mode 100644 index 00000000..d474959b --- /dev/null +++ b/src/runtime/inertia/stubs.ts @@ -0,0 +1,98 @@ +import { ref, onScopeDispose } from 'vue' +import type { Ref, Plugin as VuePlugin } from 'vue' +import { createHooks } from 'hookable' + +import appConfig from '#build/app.config' +import type { NuxtApp } from '#app' +import { useColorMode as useColorModeVueUse } from '@vueuse/core' +import { usePage } from '@inertiajs/vue3' + +export { useHead } from '@unhead/vue' + +export { defineShortcuts } from '../composables/defineShortcuts' +export { defineLocale } from '../composables/defineLocale' +export { useLocale } from '../composables/useLocale' + +export const useRoute = () => { + const page = usePage() + return { + fullPath: page.url + } +} + +export const useRouter = () => { + +} + +export const useColorMode = () => { + if (!appConfig.colorMode) { + return { + forced: true + } + } + + const { store, system } = useColorModeVueUse() + + return { + get preference() { return store.value === 'auto' ? 'system' : store.value }, + set preference(value) { store.value = value === 'system' ? 'auto' : value }, + get value() { return store.value === 'auto' ? system.value : store.value }, + forced: false + } +} + +export const useAppConfig = () => appConfig + +export const useCookie = ( + _name: string, + _options: Record = {} +) => { + const value = ref(null) as Ref + + return { + value, + get: () => value.value, + set: () => {}, + update: () => {}, + refresh: () => Promise.resolve(value.value), + remove: () => {} + } +} + +const state: Record = {} + +export const useState = (key: string, init: () => T): Ref => { + if (state[key]) { + return state[key] as Ref + } + const value = ref(init()) + state[key] = value + return value as Ref +} + +const hooks = createHooks() + +export function useNuxtApp() { + return { + isHydrating: true, + payload: { serverRendered: false }, + hooks, + hook: hooks.hook + } +} + +export function useRuntimeHook(name: string, fn: (...args: any[]) => void): void { + const nuxtApp = useNuxtApp() + + const unregister = nuxtApp.hook(name, fn) + + onScopeDispose(unregister) +} + +export function defineNuxtPlugin(plugin: (nuxtApp: NuxtApp) => void) { + return { + install(app) { + app.runWithContext(() => plugin({ vueApp: app } as NuxtApp)) + } + } satisfies VuePlugin +} diff --git a/src/runtime/vue/components/Link.vue b/src/runtime/vue/components/Link.vue index ff82c430..73aec38a 100644 --- a/src/runtime/vue/components/Link.vue +++ b/src/runtime/vue/components/Link.vue @@ -93,8 +93,8 @@ import { isEqual, diff } from 'ohash/utils' import { useForwardProps } from 'reka-ui' import { reactiveOmit } from '@vueuse/core' import { hasProtocol } from 'ufo' -import { useRoute, useAppConfig } from '#imports' -import { RouterLink } from 'vue-router' +import { useRoute, RouterLink } from 'vue-router' +import { useAppConfig } from '#imports' import { tv } from '../../utils/tv' defineOptions({ inheritAttrs: false }) diff --git a/src/unplugin.ts b/src/unplugin.ts index 138f3404..783d84b4 100644 --- a/src/unplugin.ts +++ b/src/unplugin.ts @@ -50,6 +50,10 @@ export interface NuxtUIOptions extends Omit + /** + * Enables compatibility layer for InertiaJS + */ + inertia?: boolean } export const runtimeDir = normalize(fileURLToPath(new URL('./runtime', import.meta.url))) @@ -63,7 +67,7 @@ export const NuxtUIPlugin = createUnplugin((_options const appConfig = defu({ ui: options.ui, colorMode: options.colorMode }, { ui: getDefaultUiConfig(options.theme.colors) }) return [ - NuxtEnvironmentPlugin(), + NuxtEnvironmentPlugin(options), ComponentImportPlugin(options, meta), AutoImportPlugin(options, meta), tailwind(),