Add global modules via unplugin-vue-components

This commit is contained in:
philipp lang 2025-06-11 21:26:44 +02:00
parent ea2eb08052
commit 4698c808f8
7 changed files with 337 additions and 24 deletions

235
package-lock.json generated
View File

@ -40,6 +40,7 @@
"dayjs": "^1.11.10",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"unplugin-vue-components": "^28.7.0",
"vue-axios": "^3.5.2"
}
},
@ -1985,6 +1986,12 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/confbox": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
"dev": true
},
"node_modules/constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
@ -2520,6 +2527,12 @@
"node": ">=0.10.0"
}
},
"node_modules/exsolve": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz",
"integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==",
"dev": true
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -3137,6 +3150,23 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/local-pkg": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
"integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
"dev": true,
"dependencies": {
"mlly": "^1.7.4",
"pkg-types": "^2.0.1",
"quansync": "^0.2.8"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -3308,6 +3338,35 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mlly": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"pathe": "^2.0.1",
"pkg-types": "^1.3.0",
"ufo": "^1.5.4"
}
},
"node_modules/mlly/node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"dev": true
},
"node_modules/mlly/node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"dev": true,
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -3575,6 +3634,12 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -3628,6 +3693,17 @@
"node": ">= 6"
}
},
"node_modules/pkg-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",
"integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
"dev": true,
"dependencies": {
"confbox": "^0.2.1",
"exsolve": "^1.0.1",
"pathe": "^2.0.3"
}
},
"node_modules/postcss": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
@ -3829,6 +3905,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/quansync": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
"integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/antfu"
},
{
"type": "individual",
"url": "https://github.com/sponsors/sxzz"
}
]
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -4458,6 +4550,48 @@
"node": ">=0.8"
}
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"dev": true,
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"dev": true,
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -4548,6 +4682,101 @@
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/ufo": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
"dev": true
},
"node_modules/unplugin": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz",
"integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
"dev": true,
"dependencies": {
"acorn": "^8.14.1",
"picomatch": "^4.0.2",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=18.12.0"
}
},
"node_modules/unplugin-utils": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
"integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
"dev": true,
"dependencies": {
"pathe": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=18.12.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/unplugin-utils/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/unplugin-vue-components": {
"version": "28.7.0",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.7.0.tgz",
"integrity": "sha512-3SuWAHlTjOiZckqRBGXRdN/k6IMmKyt2Ch5/+DKwYaT321H0ItdZDvW4r8/YkEKQpN9TN3F/SZ0W342gQROC3Q==",
"dev": true,
"dependencies": {
"chokidar": "^3.6.0",
"debug": "^4.4.1",
"local-pkg": "^1.1.1",
"magic-string": "^0.30.17",
"mlly": "^1.7.4",
"tinyglobby": "^0.2.14",
"unplugin": "^2.3.4",
"unplugin-utils": "^0.2.4"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",
"vue": "2 || 3"
},
"peerDependenciesMeta": {
"@babel/parser": {
"optional": true
},
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/unplugin/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
@ -4792,6 +5021,12 @@
"vue": "^3.0.1"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -18,6 +18,7 @@
"dayjs": "^1.11.10",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"unplugin-vue-components": "^28.7.0",
"vue-axios": "^3.5.2"
},
"dependencies": {

18
resources/js/app.js vendored
View File

@ -1,16 +1,15 @@
import {createApp, h, defineAsyncComponent} from 'vue';
import {Head, createInertiaApp, Link as ILink} from '@inertiajs/vue3';
import { createApp, h, defineAsyncComponent } from 'vue';
import { Head, createInertiaApp, Link as ILink } from '@inertiajs/vue3';
import axios from 'axios';
import VueAxios from 'vue-axios';
import {Plugin as FloatingVue, options as FloatingVueOptions} from './lib/floatingVue.js';
import {createPinia, PiniaVuePlugin} from 'pinia';
import { Plugin as FloatingVue, options as FloatingVueOptions } from './lib/floatingVue.js';
import { createPinia, PiniaVuePlugin } from 'pinia';
import Echo from './lib/echo.js';
import requireModules from './lib/requireModules.js';
import AppLayout from './layouts/AppLayout.vue';
import hasModule from './mixins/hasModule.js';
import hasFlash from './mixins/hasFlash.js';
import {Toast, options as toastOptions, interceptor as toastInterceptor} from './lib/toast.js';
import { Toast, options as toastOptions, interceptor as toastInterceptor } from './lib/toast.js';
// ---------------------------------- Assets -----------------------------------
import '../css/app.css';
@ -35,8 +34,8 @@ createInertiaApp({
return page;
},
setup({el, App, props, plugin}) {
var app = createApp({pinia, render: () => h(App, props)})
setup({ el, App, props, plugin }) {
var app = createApp({ pinia, render: () => h(App, props) })
.use(plugin)
.use(FloatingVue, FloatingVueOptions)
.use(Toast, toastOptions)
@ -47,9 +46,6 @@ createInertiaApp({
.mixin(hasModule)
.mixin(hasFlash);
requireModules(import.meta.glob('./components/form/*.vue'), app, 'f');
requireModules(import.meta.glob('./components/ui/*.vue'), app, 'ui');
requireModules(import.meta.glob('./components/page/*.vue', {eager: true}), app, 'page');
app.component(
'FSinglefile',
defineAsyncComponent(() => import('!/medialibrary-helper/assets/components/SingleFile.vue'))

57
resources/js/components/components.d.ts vendored Normal file
View File

@ -0,0 +1,57 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
FCheckboxesLabel: typeof import('@/components/form/CheckboxesLabel.vue')['default']
FEditor: typeof import('@/components/form/Editor.vue')['default']
FHint: typeof import('@/components/form/Hint.vue')['default']
FLabel: typeof import('@/components/form/Label.vue')['default']
FMemberFilter: typeof import('@/components/form/MemberFilter.vue')['default']
FMultipleselect: typeof import('@/components/form/Multipleselect.vue')['default']
FSaveButton: typeof import('@/components/form/SaveButton.vue')['default']
FSelect: typeof import('@/components/form/Select.vue')['default']
FSwitch: typeof import('@/components/form/Switch.vue')['default']
FText: typeof import('@/components/form/Text.vue')['default']
FTextarea: typeof import('@/components/form/Textarea.vue')['default']
PageFilter: typeof import('@/components/page/Filter.vue')['default']
PageFullHeading: typeof import('@/components/page/FullHeading.vue')['default']
PageFullHeadingBanner: typeof import('@/components/page/FullHeadingBanner.vue')['default']
PageFullLayout: typeof import('@/components/page/FullLayout.vue')['default']
PageHeader: typeof import('@/components/page/Header.vue')['default']
PageLayout: typeof import('@/components/page/Layout.vue')['default']
PageSearchModal: typeof import('@/components/page/SearchModal.vue')['default']
PageTitle: typeof import('@/components/page/Title.vue')['default']
PageToolbarButton: typeof import('@/components/page/ToolbarButton.vue')['default']
UiActionButton: typeof import('@/components/ui/ActionButton.vue')['default']
UiAgeGroups: typeof import('@/components/ui/AgeGroups.vue')['default']
UiBool: typeof import('@/components/ui/Bool.vue')['default']
UiBooleanDisplay: typeof import('@/components/ui/BooleanDisplay.vue')['default']
UiBox: typeof import('@/components/ui/Box.vue')['default']
UiButton: typeof import('@/components/ui/Button.vue')['default']
UiFilterSidebar: typeof import('@/components/ui/FilterSidebar.vue')['default']
UiIconButton: typeof import('@/components/ui/IconButton.vue')['default']
UiLabel: typeof import('@/components/ui/Label.vue')['default']
UiLoading: typeof import('@/components/ui/Loading.vue')['default']
UiMenulist: typeof import('@/components/ui/Menulist.vue')['default']
UiNote: typeof import('@/components/ui/Note.vue')['default']
UiPagination: typeof import('@/components/ui/Pagination.vue')['default']
UiPopup: typeof import('@/components/ui/Popup.vue')['default']
UiRemoteResource: typeof import('@/components/ui/RemoteResource.vue')['default']
UiRemoteSelector: typeof import('@/components/ui/RemoteSelector.vue')['default']
UiSearchPagination: typeof import('@/components/ui/SearchPagination.vue')['default']
UiSearchResult: typeof import('@/components/ui/SearchResult.vue')['default']
UiSidebar: typeof import('@/components/ui/Sidebar.vue')['default']
UiSpinner: typeof import('@/components/ui/Spinner.vue')['default']
UiSprite: typeof import('@/components/ui/Sprite.vue')['default']
UiTableToggleButton: typeof import('@/components/ui/TableToggleButton.vue')['default']
UiTabs: typeof import('@/components/ui/Tabs.vue')['default']
UiTextDisplay: typeof import('@/components/ui/TextDisplay.vue')['default']
UiTh: typeof import('@/components/ui/Th.vue')['default']
}
}

View File

@ -1,10 +0,0 @@
import {paramCase} from 'change-case';
import {defineAsyncComponent} from 'vue';
export default function (context, app, prefix) {
for (const file in context) {
let componentName = paramCase(`${prefix}${file.replace(/^.*\/(.*?)\.vue$/g, '$1')}`);
app.component(componentName, typeof context[file] === 'function' ? defineAsyncComponent(context[file]) : context[file].default);
}
}

View File

@ -54,6 +54,10 @@
"forceConsistentCasingInFileNames": true,
// See <https://github.com/vuejs/vue-cli/pull/5688>
"skipLibCheck": true,
"types": ["vite/client"]
}
"types": ["vite/client"],
"paths": {
"@/*": ["./resources/js/*"]
}
},
"include": ["**/*", "resources/js/components/components.d.ts"]
}

32
vite.config.js vendored
View File

@ -1,10 +1,40 @@
import {defineConfig} from 'vite';
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
Components({
globs: [],
directives: false,
directoryAsNamespace: false,
types: [],
dts: 'resources/js/components/components.d.ts',
resolvers: [
(componentName) => {
if (componentName === 'FMultiplefiles') {
return;
}
if (componentName === 'FSinglefile') {
return;
}
if (componentName.startsWith('Ui')) {
let singleComponentName = componentName.replace(/^Ui/, '');
return { name: 'default', from: `@/components/ui/${singleComponentName}.vue` };
}
if (componentName.startsWith('F')) {
let singleComponentName = componentName.replace(/^F/, '');
return { name: 'default', from: `@/components/form/${singleComponentName}.vue` };
}
if (componentName.startsWith('Page')) {
let singleComponentName = componentName.replace(/^Page/, '');
return { name: 'default', from: `@/components/page/${singleComponentName}.vue` };
}
},
]
}),
laravel(['resources/js/app.js']),
vue({
template: {