mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
feat(module): add support for vue using unplugin (#2416)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
12
playground-vue/index.html
Normal file
12
playground-vue/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Nuxt UI ❤️ Vue</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="isolate"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
playground-vue/package.json
Normal file
24
playground-vue/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "playground-vue",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "latest",
|
||||
"vue": "^3.5.10",
|
||||
"vue-router": "^4.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"typescript": "^5.5.3",
|
||||
"unplugin-auto-import": "^0.18.3",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite": "^5.4.8",
|
||||
"vue-tsc": "^2.1.6"
|
||||
}
|
||||
}
|
||||
120
playground-vue/src/app.vue
Normal file
120
playground-vue/src/app.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<script setup lang="ts">
|
||||
import { splitByCase, upperFirst } from 'scule'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore included for compatibility with Nuxt playground
|
||||
import { useAppConfig } from '#imports'
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
appConfig.toaster = reactive({
|
||||
position: 'bottom-right' as const,
|
||||
expand: true,
|
||||
duration: 5000
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const components = [
|
||||
'accordion',
|
||||
'alert',
|
||||
'avatar',
|
||||
'badge',
|
||||
'breadcrumb',
|
||||
'button',
|
||||
'button-group',
|
||||
'card',
|
||||
'carousel',
|
||||
'checkbox',
|
||||
'chip',
|
||||
'collapsible',
|
||||
'context-menu',
|
||||
'command-palette',
|
||||
'drawer',
|
||||
'dropdown-menu',
|
||||
'form',
|
||||
'form-field',
|
||||
'input',
|
||||
'input-menu',
|
||||
'kbd',
|
||||
'link',
|
||||
'modal',
|
||||
'navigation-menu',
|
||||
'pagination',
|
||||
'popover',
|
||||
'progress',
|
||||
'radio-group',
|
||||
'select',
|
||||
'select-menu',
|
||||
'separator',
|
||||
'shortcuts',
|
||||
'skeleton',
|
||||
'slideover',
|
||||
'slider',
|
||||
'switch',
|
||||
'tabs',
|
||||
'textarea',
|
||||
'toast',
|
||||
'tooltip'
|
||||
]
|
||||
|
||||
const items = components.map(component => ({ label: upperName(component), to: `/components/${component}` }))
|
||||
|
||||
function upperName(name: string) {
|
||||
return splitByCase(name).map(p => upperFirst(p)).join('')
|
||||
}
|
||||
|
||||
const isCommandPaletteOpen = ref(false)
|
||||
|
||||
function onSelect(item: any) {
|
||||
router.push(item.to)
|
||||
}
|
||||
|
||||
defineShortcuts({
|
||||
meta_k: () => isCommandPaletteOpen.value = true
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UApp :toaster="(appConfig.toaster as any)">
|
||||
<div class="h-screen w-screen overflow-hidden flex min-h-0 bg-[var(--ui-bg)]" vaul-drawer-wrapper>
|
||||
<UNavigationMenu :items="items" orientation="vertical" class="hidden lg:flex border-r border-[var(--ui-border)] overflow-y-auto w-48 p-4" />
|
||||
<UNavigationMenu :items="items" orientation="horizontal" class="lg:hidden border-b border-[var(--ui-border)] overflow-x-auto" />
|
||||
|
||||
<div class="flex-1 flex flex-col items-center justify-around overflow-y-auto w-full py-12 px-4">
|
||||
<Suspense>
|
||||
<RouterView />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UModal v-model:open="isCommandPaletteOpen" class="sm:h-96">
|
||||
<template #content>
|
||||
<UCommandPalette placeholder="Search a component..." :groups="[{ id: 'items', items }]" :fuse="{ resultLimit: 100 }" @update:model-value="onSelect" @update:open="value => isCommandPaletteOpen = value" />
|
||||
</template>
|
||||
</UModal>
|
||||
</UApp>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme {
|
||||
--font-family-sans: 'Public Sans', sans-serif;
|
||||
|
||||
--color-green-50: #EFFDF5;
|
||||
--color-green-100: #D9FBE8;
|
||||
--color-green-200: #B3F5D1;
|
||||
--color-green-300: #75EDAE;
|
||||
--color-green-400: #00DC82;
|
||||
--color-green-500: #00C16A;
|
||||
--color-green-600: #00A155;
|
||||
--color-green-700: #007F45;
|
||||
--color-green-800: #016538;
|
||||
--color-green-900: #0A5331;
|
||||
--color-green-950: #052E16;
|
||||
}
|
||||
</style>
|
||||
54
playground-vue/src/main.ts
Normal file
54
playground-vue/src/main.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { createApp, ref } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import uiPlugin from '@nuxt/ui/vue-plugin'
|
||||
|
||||
import App from './app.vue'
|
||||
|
||||
const pages = import.meta.glob('../../playground/app/pages/**/*.vue')
|
||||
const components = import.meta.glob('../../playground/app/components/**/*.vue')
|
||||
|
||||
const routes = Object.keys(pages).map((path) => {
|
||||
const name = path.match(/\.\.\/\.\.\/playground\/app\/pages(.*)\.vue$/)![1].toLowerCase()
|
||||
return {
|
||||
path: name === '/index' ? '/' : name,
|
||||
component: pages[path]
|
||||
}
|
||||
})
|
||||
|
||||
const router = createRouter({
|
||||
routes,
|
||||
history: createWebHistory()
|
||||
})
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
Object.entries(components).forEach(([path, component]) => {
|
||||
const name = path.split('/').pop()!.replace('.vue', '')
|
||||
app.component(name, defineAsyncComponent(component as any))
|
||||
})
|
||||
|
||||
app.use(router)
|
||||
app.use(uiPlugin)
|
||||
|
||||
// @ts-expect-error unknown global property
|
||||
globalThis.useFetch = async (url: string, options: RequestInit & { transform?: (data) => any } = {}) => {
|
||||
const data = ref()
|
||||
const status = ref('idle')
|
||||
async function _fetch() {
|
||||
status.value = 'loading'
|
||||
try {
|
||||
data.value = await fetch(url, options).then(r => r.json()).then(r => options.transform ? options.transform(r) : r)
|
||||
status.value = 'success'
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
status.value = 'error'
|
||||
}
|
||||
}
|
||||
_fetch()
|
||||
return Promise.resolve({
|
||||
data,
|
||||
status
|
||||
})
|
||||
}
|
||||
|
||||
app.mount('#app')
|
||||
1
playground-vue/src/vite-env.d.ts
vendored
Normal file
1
playground-vue/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
33
playground-vue/tsconfig.app.json
Normal file
33
playground-vue/tsconfig.app.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"auto-imports.d.ts",
|
||||
"components.d.ts",
|
||||
"app.config.ts"
|
||||
]
|
||||
}
|
||||
7
playground-vue/tsconfig.json
Normal file
7
playground-vue/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
22
playground-vue/tsconfig.node.json
Normal file
22
playground-vue/tsconfig.node.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
35
playground-vue/vite.config.ts
Normal file
35
playground-vue/vite.config.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import AutoImports from 'unplugin-auto-import/vite'
|
||||
import VueComponents from 'unplugin-vue-components'
|
||||
|
||||
import ui from '../src/vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
server: {
|
||||
fs: {
|
||||
allow: ['..']
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
ui({
|
||||
ui: {
|
||||
colors: {
|
||||
primary: 'green',
|
||||
neutral: 'slate'
|
||||
}
|
||||
}
|
||||
}),
|
||||
// these are required as we share the component pages with the Nuxt playground
|
||||
AutoImports({ imports: ['vue'] }),
|
||||
VueComponents.vite({
|
||||
dirs: ['../playground/app/components']
|
||||
})
|
||||
],
|
||||
optimizeDeps: {
|
||||
// prevents reloading page when navigating between components
|
||||
include: ['radix-vue/namespaced', 'vaul-vue', 'fast-deep-equal', 'embla-carousel-vue', 'embla-carousel-autoplay', 'embla-carousel-auto-scroll', 'embla-carousel-auto-height', 'embla-carousel-class-names', 'embla-carousel-fade', 'embla-carousel-wheel-gestures']
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user