├── CODEOWNERS ├── .eslintignore ├── packages └── nuxt-ui-vue │ ├── env.d.ts │ ├── src │ ├── tailwind-merge.d.ts │ ├── App.vue │ ├── components │ │ ├── data │ │ │ └── index.ts │ │ ├── elements │ │ │ ├── Kbd │ │ │ │ ├── index.ts │ │ │ │ └── UKbd.vue │ │ │ ├── Icon │ │ │ │ ├── index.ts │ │ │ │ └── UIcon.vue │ │ │ ├── Link │ │ │ │ ├── index.ts │ │ │ │ └── ULink.vue │ │ │ ├── Alert │ │ │ │ ├── index.ts │ │ │ │ └── UAlert.vue │ │ │ ├── Badge │ │ │ │ ├── index.ts │ │ │ │ └── UBadge.vue │ │ │ ├── Dropdown │ │ │ │ ├── index.ts │ │ │ │ └── UDropdown.vue │ │ │ ├── Accordion │ │ │ │ ├── index.ts │ │ │ │ └── UAccordion.vue │ │ │ ├── Avatar │ │ │ │ ├── index.ts │ │ │ │ ├── Types │ │ │ │ │ └── index.ts │ │ │ │ ├── UAvatarGroup.vue │ │ │ │ └── UAvatar.vue │ │ │ └── Button │ │ │ │ ├── index.ts │ │ │ │ ├── UButtonGroup.vue │ │ │ │ └── UButton.vue │ │ ├── forms │ │ │ ├── Input │ │ │ │ ├── index.ts │ │ │ │ └── UInput.vue │ │ │ ├── Radio │ │ │ │ ├── index.ts │ │ │ │ └── URadio.vue │ │ │ ├── Range │ │ │ │ ├── index.ts │ │ │ │ └── URange.vue │ │ │ ├── Select │ │ │ │ ├── index.ts │ │ │ │ └── USelect.vue │ │ │ ├── Toggle │ │ │ │ ├── index.ts │ │ │ │ └── UToggle.vue │ │ │ ├── Checkbox │ │ │ │ ├── index.ts │ │ │ │ └── UCheckbox.vue │ │ │ ├── Textarea │ │ │ │ ├── index.ts │ │ │ │ └── UTextarea.vue │ │ │ ├── FormGroup │ │ │ │ ├── index.ts │ │ │ │ └── UFormGroup.vue │ │ │ └── SelectMenu │ │ │ │ └── index.ts │ │ ├── layouts │ │ │ ├── Card │ │ │ │ ├── index.ts │ │ │ │ └── UCard.vue │ │ │ ├── Skeleton │ │ │ │ ├── index.ts │ │ │ │ └── USkeleton.vue │ │ │ └── Container │ │ │ │ ├── index.ts │ │ │ │ └── UContainer.vue │ │ ├── navigation │ │ │ ├── Tabs │ │ │ │ ├── index.ts │ │ │ │ └── UTabs.vue │ │ │ ├── Pagination │ │ │ │ ├── index.ts │ │ │ │ └── UPagination.vue │ │ │ ├── index.ts │ │ │ ├── VerticalNavigation │ │ │ │ ├── index.ts │ │ │ │ └── UVerticalNavigation.vue │ │ │ └── Command-Palette │ │ │ │ ├── index.ts │ │ │ │ └── CommandPaletteGroup.vue │ │ ├── overlays │ │ │ ├── Modal │ │ │ │ ├── index.ts │ │ │ │ └── UModal.vue │ │ │ ├── Popover │ │ │ │ ├── index.ts │ │ │ │ └── UPopover.vue │ │ │ ├── Tooltip │ │ │ │ ├── index.ts │ │ │ │ └── UTooltip.vue │ │ │ ├── Slideover │ │ │ │ ├── index.ts │ │ │ │ └── USlideover.vue │ │ │ ├── ContextMenu │ │ │ │ ├── index.ts │ │ │ │ └── UContextMenu.vue │ │ │ └── Notification │ │ │ │ ├── index.ts │ │ │ │ ├── UNotifications.vue │ │ │ │ └── UNotification.vue │ │ └── index.ts │ ├── Types │ │ ├── components │ │ │ ├── tabs.ts │ │ │ ├── clipboard.ts │ │ │ ├── avatar.ts │ │ │ ├── link.ts │ │ │ ├── accordionItem.ts │ │ │ ├── form.ts │ │ │ ├── vertical-navigation.ts │ │ │ ├── dropdown.ts │ │ │ ├── popper.ts │ │ │ ├── button.ts │ │ │ ├── notification.ts │ │ │ └── command-palette.ts │ │ ├── enums │ │ │ ├── Sizes.ts │ │ │ ├── Variants.ts │ │ │ ├── Positions.ts │ │ │ └── Components.ts │ │ └── variant.ts │ ├── shim-vue.d.ts │ ├── install.ts │ ├── main.ts │ ├── assets │ │ └── css │ │ │ └── tailwind.css │ ├── componentResolver.ts │ ├── utils │ │ ├── stateEmitter.ts │ │ ├── lodash.ts │ │ ├── index.ts │ │ └── getVariantProps.ts │ ├── composables │ │ ├── useFormEvents.ts │ │ ├── useCopyToClipboard.ts │ │ ├── useShortcuts.ts │ │ ├── useToast.ts │ │ ├── useTimer.ts │ │ ├── useVariants.ts │ │ ├── usePopper.ts │ │ └── defineShortcuts.ts │ ├── index.ts │ └── plugin.ts │ ├── .vscode │ └── extensions.json │ ├── public │ └── favicon.ico │ ├── postcss.config.js │ ├── scripts │ └── theme.ts │ ├── index.html │ ├── tailwind.config.js │ ├── .gitignore │ ├── CHANGELOG.md │ ├── tsconfig.json │ ├── package.json │ ├── vite.config.ts │ └── components.d.ts ├── pnpm-workspace.yaml ├── .gitignore ├── .npmrc ├── .eslintrc ├── .github ├── workflows │ ├── update-readme.yml │ ├── ci.yml │ └── release.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── scripts │ └── update-readme-table.js ├── vitest.config.ts ├── tsconfig.json ├── LICENSE ├── package.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── CHANGELOG.md /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @selemondev -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | public 3 | es 4 | node_modules -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - example 4 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/tailwind-merge.d.ts: -------------------------------------------------------------------------------- 1 | declare module "tailwind-merge" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .output 4 | dist 5 | .DS_Store 6 | .history 7 | .env 8 | .netlify -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org 2 | ignore-workspace-root-check=true 3 | shamefully-hoist=true 4 | auto-install-peers=false -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/data/index.ts: -------------------------------------------------------------------------------- 1 | import Table from './UTable.vue' 2 | 3 | export default { 4 | Table, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Kbd/index.ts: -------------------------------------------------------------------------------- 1 | import Kbd from './UKbd.vue' 2 | 3 | export default { 4 | Kbd, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/nuxt-ui-vue/HEAD/packages/nuxt-ui-vue/public/favicon.ico -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Icon/index.ts: -------------------------------------------------------------------------------- 1 | import Icon from './UIcon.vue' 2 | 3 | export default { 4 | Icon, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Link/index.ts: -------------------------------------------------------------------------------- 1 | import Link from './ULink.vue' 2 | 3 | export default { 4 | Link, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Input/index.ts: -------------------------------------------------------------------------------- 1 | import Input from './UInput.vue' 2 | 3 | export default { 4 | Input, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Radio/index.ts: -------------------------------------------------------------------------------- 1 | import Radio from './URadio.vue' 2 | 3 | export default { 4 | Radio, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Range/index.ts: -------------------------------------------------------------------------------- 1 | import Range from './URange.vue' 2 | 3 | export default { 4 | Range, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Card/index.ts: -------------------------------------------------------------------------------- 1 | import Card from './UCard.vue' 2 | 3 | export default { 4 | Card, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Alert/index.ts: -------------------------------------------------------------------------------- 1 | import Alert from './UAlert.vue' 2 | 3 | export default { 4 | Alert, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Badge/index.ts: -------------------------------------------------------------------------------- 1 | import Badge from './UBadge.vue' 2 | 3 | export default { 4 | Badge, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Select/index.ts: -------------------------------------------------------------------------------- 1 | import Select from './USelect.vue' 2 | 3 | export default { 4 | Select, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Toggle/index.ts: -------------------------------------------------------------------------------- 1 | import Toggle from './UToggle.vue' 2 | 3 | export default { 4 | Toggle, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/Tabs/index.ts: -------------------------------------------------------------------------------- 1 | import Tabs from './UTabs.vue' 2 | 3 | export default { 4 | Tabs, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Modal/index.ts: -------------------------------------------------------------------------------- 1 | import Modal from './UModal.vue' 2 | 3 | export default { 4 | Modal, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Dropdown/index.ts: -------------------------------------------------------------------------------- 1 | import Dropdown from './UDropdown.vue' 2 | 3 | export default { 4 | Dropdown, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import Checkbox from './UCheckbox.vue' 2 | 3 | export default { 4 | Checkbox, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Textarea/index.ts: -------------------------------------------------------------------------------- 1 | import Textarea from './UTextarea.vue' 2 | 3 | export default { 4 | Textarea, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Skeleton/index.ts: -------------------------------------------------------------------------------- 1 | import Skeleton from './USkeleton.vue' 2 | 3 | export default { 4 | Skeleton, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Popover/index.ts: -------------------------------------------------------------------------------- 1 | import Popover from './UPopover.vue' 2 | 3 | export default { 4 | Popover, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Tooltip/index.ts: -------------------------------------------------------------------------------- 1 | import Tooltip from './UTooltip.vue' 2 | 3 | export default { 4 | Tooltip, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Accordion/index.ts: -------------------------------------------------------------------------------- 1 | import Accordion from './UAccordion.vue' 2 | 3 | export default { 4 | Accordion, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/FormGroup/index.ts: -------------------------------------------------------------------------------- 1 | import FormGroup from './UFormGroup.vue' 2 | 3 | export default { 4 | FormGroup, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/SelectMenu/index.ts: -------------------------------------------------------------------------------- 1 | import SelectMenu from './USelectMenu.vue' 2 | 3 | export default { 4 | SelectMenu, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Container/index.ts: -------------------------------------------------------------------------------- 1 | import Container from './UContainer.vue' 2 | 3 | export default { 4 | Container, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Slideover/index.ts: -------------------------------------------------------------------------------- 1 | import Slideover from './USlideover.vue' 2 | 3 | export default { 4 | Slideover, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/Pagination/index.ts: -------------------------------------------------------------------------------- 1 | import Pagination from './UPagination.vue' 2 | 3 | export default { 4 | Pagination, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/ContextMenu/index.ts: -------------------------------------------------------------------------------- 1 | import ContextMenu from './UContextMenu.vue' 2 | 3 | export default { 4 | ContextMenu, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Notification/index.ts: -------------------------------------------------------------------------------- 1 | import Notification from './UNotification.vue' 2 | 3 | export default { 4 | Notification, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/tabs.ts: -------------------------------------------------------------------------------- 1 | export interface TabItem { 2 | label: string 3 | slot?: string 4 | disabled?: boolean 5 | content?: string 6 | } 7 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/index.ts: -------------------------------------------------------------------------------- 1 | import VerticalNavigation from './VerticalNavigation.vue' 2 | 3 | export default { 4 | VerticalNavigation, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/VerticalNavigation/index.ts: -------------------------------------------------------------------------------- 1 | import VerticalNavigation from './UVerticalNavigation.vue' 2 | 3 | export default { 4 | VerticalNavigation, 5 | } 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/shim-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { defineComponent } from 'vue' 3 | const Component: ReturnType 4 | export default Component 5 | } -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/enums/Sizes.ts: -------------------------------------------------------------------------------- 1 | export enum Sizes { 2 | XS = 'xs', 3 | SM = 'sm', 4 | MD = 'md', 5 | LG = 'lg', 6 | XL = 'xl', 7 | '2XL' = '2xl', 8 | '3XL' = '3xl', 9 | } 10 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Avatar/index.ts: -------------------------------------------------------------------------------- 1 | import Avatar from './UAvatar.vue' 2 | import AvatarGroup from './UAvatarGroup.vue' 3 | 4 | export default { 5 | Avatar, 6 | AvatarGroup, 7 | } 8 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Button/index.ts: -------------------------------------------------------------------------------- 1 | import Button from './UButton.vue' 2 | import ButtonGroup from './UButtonGroup.vue' 3 | 4 | export default { 5 | Button, 6 | ButtonGroup, 7 | } 8 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/enums/Variants.ts: -------------------------------------------------------------------------------- 1 | export enum Variants { 2 | DEFAULT = 'default', 3 | PRIMARY = 'primary', 4 | SUCCESS = 'success', 5 | WARNING = 'warning', 6 | DANGER = 'danger', 7 | } 8 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/clipboard.ts: -------------------------------------------------------------------------------- 1 | export interface ClipboardPlugin { 2 | copy: (text: string, success?: { title?: string; description?: string }, failure?: { title?: string; description?: string }) => void 3 | } 4 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/install.ts: -------------------------------------------------------------------------------- 1 | import * as components from './components' 2 | import create from './plugin' 3 | 4 | export default create({ 5 | components: Object.keys(components).map( 6 | key => components[key as keyof object], 7 | ), 8 | }) 9 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/avatar.ts: -------------------------------------------------------------------------------- 1 | export interface Avatar { 2 | src?: string | boolean 3 | alt?: string 4 | text?: string 5 | size?: string 6 | chipColor?: string 7 | chipVariant?: string 8 | chipPosition?: string 9 | } 10 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/link.ts: -------------------------------------------------------------------------------- 1 | import type { RouterLinkProps } from 'vue-router' 2 | 3 | export interface Link extends RouterLinkProps { 4 | exact?: boolean 5 | exactQuery?: boolean 6 | exactMatch?: boolean 7 | inactiveClass?: string 8 | } 9 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/Command-Palette/index.ts: -------------------------------------------------------------------------------- 1 | import CommandPaletteGroup from './CommandPaletteGroup.vue' 2 | import CommandPalette from './CommandPalette.vue' 3 | 4 | export default { 5 | CommandPaletteGroup, 6 | CommandPalette, 7 | } 8 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/scripts/theme.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | 3 | fs.mkdirSync('./dist/theme', { recursive: true }) 4 | fs.copyFileSync('./src/theme/nuxtLabsTheme.ts', './dist/theme/nuxtLabsTheme.ts') 5 | fs.copyFileSync('./src/theme/nuxtLabsTheme.ts', './dist/theme/nuxtLabsTheme.js') 6 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/accordionItem.ts: -------------------------------------------------------------------------------- 1 | import type { Button } from './button' 2 | 3 | export interface AccordionItem extends Button { 4 | slot?: string 5 | disabled?: boolean 6 | content?: string 7 | defaultOpen?: boolean 8 | closeOthers?: boolean 9 | } 10 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import './assets/css/tailwind.css' 2 | import { createApp } from 'vue' 3 | import App from './App.vue' 4 | import config from './theme/nuxtLabsTheme' 5 | import install from './index' 6 | 7 | const app = createApp(App) 8 | app.use(install, config) 9 | app.mount('#app') 10 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/form.ts: -------------------------------------------------------------------------------- 1 | export interface FormError { 2 | path: string 3 | message: string 4 | } 5 | 6 | export interface Form { 7 | validate(): Promise 8 | } 9 | 10 | export interface FormEvent { 11 | type: 'blur' // | 'change' | 'focus' 12 | path: string 13 | } 14 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/enums/Positions.ts: -------------------------------------------------------------------------------- 1 | export enum Positions { 2 | B = 'bottom', 3 | BL = 'bottom-left', 4 | BR = 'bottom-right', 5 | L = 'left', 6 | LT = 'left-top', 7 | LB = 'left-bottom', 8 | R = 'right', 9 | RT = 'right-top', 10 | RB = 'right-bottom', 11 | T = 'top', 12 | TL = 'top-left', 13 | TR = 'top-right', 14 | } 15 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/assets/css/tailwind.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base{ 7 | body { 8 | @apply font-Roboto 9 | } 10 | 11 | select, option, input { 12 | @apply appearance-none 13 | } 14 | } -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/componentResolver.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentResolver } from 'unplugin-vue-components' 2 | 3 | export function NuxtUIVueComponentResolver(): ComponentResolver { 4 | return { 5 | type: 'component', 6 | resolve: (name: string) => { 7 | if (name.match(/^U[A-Z]/)) 8 | return { name, from: 'nuxt-ui-vue' } 9 | }, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@antfu" 4 | ], 5 | "rules": { 6 | "react/display-name": "off", 7 | "react-hooks/rules-of-hooks": "off", 8 | "no-sequences": "off", 9 | "no-alert": "off", 10 | "no-console": [ 11 | "error", 12 | { 13 | "allow": [ 14 | "error" 15 | ] 16 | } 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/vertical-navigation.ts: -------------------------------------------------------------------------------- 1 | import type { Link } from './link' 2 | import type { Avatar } from './avatar' 3 | 4 | export interface VerticalNavigationLink extends Link { 5 | label: string 6 | icon?: string 7 | iconClass?: string 8 | avatar?: Avatar 9 | // eslint-disable-next-line @typescript-eslint/ban-types 10 | click?: Function 11 | badge?: string | number 12 | } 13 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], 4 | darkMode: 'class', 5 | theme: { 6 | extend: { 7 | backgroundColor: ['disabled'], 8 | textColor: ['disabled'], 9 | fontFamily: { 10 | Roboto: 'Roboto', 11 | }, 12 | }, 13 | }, 14 | plugins: [], 15 | } 16 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/dropdown.ts: -------------------------------------------------------------------------------- 1 | import type { Link } from './link' 2 | import type { Avatar } from './avatar' 3 | 4 | export interface DropdownItem extends Link { 5 | label: string 6 | slot?: string 7 | icon?: string 8 | iconClass?: string 9 | avatar?: Avatar 10 | shortcuts?: string[] 11 | disabled?: boolean 12 | // eslint-disable-next-line @typescript-eslint/ban-types 13 | click?: Function 14 | } 15 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/popper.ts: -------------------------------------------------------------------------------- 1 | import type { Placement, PositioningStrategy } from '@popperjs/core' 2 | 3 | export interface PopperOptions { 4 | locked?: boolean 5 | overflowPadding?: number 6 | offsetDistance?: number 7 | offsetSkid?: number 8 | placement?: Placement 9 | strategy?: PositioningStrategy 10 | gpuAcceleration?: boolean 11 | adaptive?: boolean 12 | scroll?: boolean 13 | resize?: boolean 14 | } 15 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /.github/workflows/update-readme.yml: -------------------------------------------------------------------------------- 1 | name: Update Table in README on nuxt-ui-vue Version Change 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | update-readme-table: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout Repository 14 | uses: actions/checkout@v2 15 | 16 | - name: Update README Table 17 | run: node .github/scripts/update-readme-table.js 18 | env: 19 | README_PATH: README.md 20 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/utils/stateEmitter.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent, watch } from 'vue' 2 | 3 | export default defineComponent({ 4 | props: { 5 | open: { 6 | type: Boolean, 7 | default: false, 8 | }, 9 | }, 10 | emits: ['open', 'close'], 11 | setup(props, { emit }) { 12 | watch(() => props.open, (value) => { 13 | if (value) 14 | emit('open') 15 | 16 | else 17 | emit('close') 18 | }) 19 | 20 | return () => {} 21 | }, 22 | }) 23 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/button.ts: -------------------------------------------------------------------------------- 1 | export interface Button { 2 | type?: string 3 | block?: boolean 4 | label?: string 5 | loading?: boolean 6 | disabled?: boolean 7 | padded?: boolean 8 | size?: string 9 | color?: string 10 | variant?: string 11 | icon?: string 12 | loadingIcon?: string 13 | leadingIcon?: string 14 | trailingIcon?: string 15 | trailing?: boolean 16 | leading?: boolean 17 | to?: string | object 18 | target?: string 19 | square?: boolean 20 | truncate?: boolean 21 | } 22 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'node:path' 2 | import { defineConfig } from 'vitest/config' 3 | import Vue from '@vitejs/plugin-vue' 4 | 5 | const r = (p: string) => resolve(__dirname, p) 6 | export default defineConfig({ 7 | plugins: [Vue()], 8 | optimizeDeps: { 9 | disabled: true, 10 | }, 11 | test: { 12 | clearMocks: true, 13 | environment: 'jsdom', 14 | transformMode: { 15 | web: [/\.[jt]sx$/], 16 | }, 17 | }, 18 | resolve: { 19 | alias: { 20 | 'nuxt-ui-vue': r('./packages/nuxt-ui-vue'), 21 | }, 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/notification.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | import type { Avatar } from './avatar' 3 | import type { Button } from './button' 4 | 5 | export interface NotificationAction extends Button { 6 | click?: Function 7 | } 8 | 9 | export interface Notification { 10 | id: string 11 | title: string 12 | description?: string 13 | icon?: string 14 | avatar?: Avatar 15 | closeButton?: Button 16 | timeout: number 17 | actions?: NotificationAction[] 18 | click?: Function 19 | callback?: Function 20 | color?: string 21 | } 22 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useFormEvents.ts: -------------------------------------------------------------------------------- 1 | import { inject } from 'vue' 2 | import type { UseEventBusReturn } from '@vueuse/core' 3 | import type { FormEvent } from '@/Types/components/form' 4 | 5 | export function useFormEvents() { 6 | const formBus = inject | undefined>('form-events', undefined) 7 | const formPath = inject('form-path', undefined) 8 | 9 | const emitFormBlur = () => { 10 | if (formBus && formPath) 11 | formBus.emit({ type: 'blur', path: formPath }) 12 | } 13 | 14 | return { 15 | emitFormBlur, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components' 2 | 3 | export { default as createUI } from './plugin' 4 | 5 | export { defineShortcuts } from '@/composables/defineShortcuts' 6 | 7 | export { useCopyToClipboard } from '@/composables/useCopyToClipboard' 8 | 9 | export { useShortcuts } from '@/composables/useShortcuts' 10 | 11 | export { useToast, injectToast } from '@/composables/useToast' 12 | 13 | export { NuxtUIVueComponentResolver } from '@/componentResolver' 14 | 15 | export * as iconify from '@iconify/vue' 16 | 17 | export * as iconfiyOffline from '@iconify/vue/dist/offline' 18 | 19 | export { default } from './install' 20 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | ## v0.0.8 5 | 6 | [compare changes](https://github.com/selemondev/nuxtlabs-ui-vue/compare/v0.0.4...v0.0.8) 7 | 8 | ## v0.1.7 9 | 10 | [compare changes](https://github.com/selemondev/nuxtlabs-ui-vue/compare/v0.1.6...v0.1.7) 11 | 12 | ### 🩹 Fixes 13 | 14 | - **app:** #94 fix theme declaration types ([#94](https://github.com/selemondev/nuxtlabs-ui-vue/issues/94)) 15 | 16 | ### 🏡 Chore 17 | 18 | - **app:** #92 rename package name ([#92](https://github.com/selemondev/nuxtlabs-ui-vue/issues/92)) 19 | 20 | ### ❤️ Contributors 21 | 22 | - Selemondev 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Avatar/Types/index.ts: -------------------------------------------------------------------------------- 1 | import type { Slot, VNode } from 'vue' 2 | 3 | export function getSlotsFromChildren(slot: Slot | any): VNode[] { 4 | let children = slot?.default?.() 5 | if (children.length) { 6 | children = children.flatMap((c: { type: { name: string }; children: any; ctx: { slots: { default: () => any } } }) => { 7 | if (typeof c.type === 'symbol') { 8 | if (typeof c.children === 'string') 9 | return false 10 | 11 | return c.children 12 | } 13 | else if (c.type.name === 'ContentSlot') { 14 | return c.ctx.slots.default?.() 15 | } 16 | return c 17 | }).filter(Boolean) 18 | } 19 | return children 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "lib": ["esnext", "dom"], 6 | "moduleResolution": "node", 7 | "esModuleInterop": true, 8 | "strict": true, 9 | "noImplicitAny": false, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipDefaultLibCheck": true, 13 | "skipLibCheck": true, 14 | "jsx": "preserve", 15 | "types": ["node", "vite/client"], 16 | "paths": { 17 | "nuxt-ui-vue": ["./packages/nuxt-ui-vue/src/index.ts"] 18 | } 19 | }, 20 | "exclude": [ 21 | "**/dist/**", 22 | "**/node_modules/**", 23 | "**/test/dts/**", 24 | "**/example/**", 25 | "**/packages/nuxt-ui-vue/**" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "strict": true, 7 | "declaration": true, 8 | "composite": true, 9 | "jsx": "preserve", 10 | "importHelpers": true, 11 | "moduleResolution": "node", 12 | "experimentalDecorators": true, 13 | "isolatedModules": true, 14 | "esModuleInterop": true, 15 | "allowSyntheticDefaultImports": true, 16 | "sourceMap": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "@/*": ["src/*"] 20 | }, 21 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"] 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.vue", "components.d.ts", "auto-imports.d.ts"], 24 | "exclude": ["node_modules", "dist", "**/*.js"] 25 | } 26 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/components/command-palette.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | /* eslint-disable @typescript-eslint/prefer-ts-expect-error */ 3 | // @ts-ignore 4 | import type { FuseSortFunctionMatch, FuseSortFunctionMatchList } from 'fuse.js' 5 | import type { Avatar } from './avatar' 6 | 7 | export interface Command { 8 | id: string | number 9 | prefix?: string 10 | suffix?: string 11 | icon?: string 12 | iconClass?: string 13 | avatar?: Avatar 14 | chip?: string 15 | disabled?: boolean 16 | shortcuts?: string[] 17 | group?: string 18 | score?: number 19 | matches?: (FuseSortFunctionMatch | FuseSortFunctionMatchList)[] 20 | [key: string]: any 21 | } 22 | 23 | export interface Group { 24 | key: string 25 | active?: string 26 | inactive?: string 27 | commands: Command[] 28 | [key: string]: any 29 | } 30 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/utils/lodash.ts: -------------------------------------------------------------------------------- 1 | export function omit, K extends keyof T>( 2 | object: T, 3 | keysToOmit: K[] | any[], 4 | ): Pick> { 5 | const result = { ...object } 6 | 7 | for (const key of keysToOmit) 8 | delete result[key] 9 | 10 | return result 11 | } 12 | 13 | export function get(object: Record, path: (string | number)[] | string, defaultValue?: any): any { 14 | if (typeof path === 'string') { 15 | path = path.split('.').map((key) => { 16 | const numKey = Number(key) 17 | return Number.isNaN(numKey) ? key : numKey 18 | }) 19 | } 20 | 21 | let result: any = object 22 | 23 | for (const key of path) { 24 | if (result === undefined || result === null) 25 | return defaultValue 26 | 27 | result = result[key] 28 | } 29 | 30 | return result !== undefined ? result : defaultValue 31 | } 32 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Button/UButtonGroup.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 35 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { createDefu } from 'defu' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export const defuTwMerge = createDefu((obj, key, value) => { 5 | if (typeof obj[key] === 'string' && typeof value === 'string' && obj[key] && value) { 6 | obj[key] = twMerge(obj[key], value) 7 | return true 8 | } 9 | }) 10 | 11 | export function getSlotsChildren(slots: any) { 12 | let children = slots.default?.() 13 | if (children.length) { 14 | children = children.flatMap((c) => { 15 | if (typeof c.type === 'symbol') { 16 | if (typeof c.children === 'string') { 17 | // eslint-disable-next-line array-callback-return 18 | return 19 | } 20 | return c.children 21 | } 22 | else if (c.type.name === 'ContentSlot') { 23 | return c.ctx.slots.default?.() 24 | } 25 | return c 26 | }).filter(Boolean) 27 | } 28 | return children 29 | } 30 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useCopyToClipboard.ts: -------------------------------------------------------------------------------- 1 | import { useClipboard } from '@vueuse/core' 2 | import { injectToast } from './useToast' 3 | import type { Notification } from '@/Types/components/notification' 4 | 5 | export function useCopyToClipboard(options: Partial = {}) { 6 | const { copy: copyToClipboard, isSupported } = useClipboard() 7 | const toast = injectToast() 8 | 9 | function copy(text: string, success: { title?: string; description?: string } = {}, failure: { title?: string; description?: string } = {}) { 10 | if (!isSupported) 11 | return 12 | 13 | copyToClipboard(text).then(() => { 14 | if (!success.title && !success.description) 15 | return 16 | 17 | toast.add({ ...success, ...options }) 18 | }, (e) => { 19 | toast.add({ 20 | ...failure, 21 | description: failure.description || e.message, 22 | ...options, 23 | }) 24 | }) 25 | } 26 | 27 | return { 28 | copy, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref }} 5 | cancel-in-progress: true 6 | 7 | permissions: 8 | pull-requests: write 9 | contents: read 10 | 11 | on: 12 | push: 13 | branches: 14 | - main 15 | 16 | pull_request: 17 | branches: 18 | - main 19 | 20 | jobs: 21 | build-test: 22 | name: 📚 Main 23 | runs-on: ${{ matrix.os }} 24 | 25 | strategy: 26 | matrix: 27 | os: [ubuntu-latest] 28 | 29 | steps: 30 | - uses: actions/checkout@v3 31 | 32 | - run: corepack enable 33 | - uses: actions/setup-node@v3 34 | with: 35 | node-version: '18' 36 | cache: pnpm 37 | 38 | - name: 📦 Install dependencies 39 | run: pnpm install --frozen-lockfile 40 | 41 | - name: 👀 Lint 42 | run: pnpm lint 43 | 44 | - name: 🚀 Build 45 | run: pnpm build 46 | 47 | env: 48 | VITE_TEST_DB_URL: ${{ secrets.VITE_TEST_DB_URL }} 49 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useShortcuts.ts: -------------------------------------------------------------------------------- 1 | import { createSharedComposable, useActiveElement } from '@vueuse/core' 2 | import { computed, onMounted, ref } from 'vue' 3 | import type {} from '@vueuse/shared' 4 | 5 | export function _useShortcuts() { 6 | const macOS = computed(() => navigator && navigator.userAgent && navigator.userAgent.match(/Macintosh;/)) 7 | 8 | const metaSymbol = ref(' ') 9 | 10 | const activeElement = useActiveElement() 11 | const usingInput = computed(() => { 12 | const usingInput = !!(activeElement.value?.tagName === 'INPUT' || activeElement.value?.tagName === 'TEXTAREA' || activeElement.value?.contentEditable === 'true') 13 | 14 | if (usingInput) 15 | return ((activeElement.value as any)?.name as string) || true 16 | 17 | return false 18 | }) 19 | 20 | onMounted(() => { 21 | metaSymbol.value = macOS.value ? '⌘' : 'Ctrl' 22 | }) 23 | 24 | return { 25 | macOS, 26 | metaSymbol, 27 | activeElement, 28 | usingInput, 29 | } 30 | } 31 | 32 | export const useShortcuts = createSharedComposable(_useShortcuts) 33 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 0 15 | 16 | - name: Install pnpm 17 | uses: pnpm/action-setup@v2 18 | 19 | - name: Set node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: 16.x 23 | cache: pnpm 24 | 25 | - run: npx changelogithub 26 | continue-on-error: true 27 | env: 28 | GITHUB_TOKEN: ${{secrets.GH_TOKEN}} 29 | 30 | - name: Install 31 | run: pnpm install --no-frozen-lockfile 32 | 33 | - name: Build 34 | run: pnpm run build 35 | 36 | - name: Test 37 | run: pnpm run test 38 | 39 | - name: Config npm 40 | run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc 41 | env: 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | 44 | - name: Publish to npm 45 | run: pnpm -r publish --access public --no-git-checks 46 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Skeleton/USkeleton.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 NuxtLabs UI Vue, Selemondev, Nuxt, NuxtLabs & NuxtLabs Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/plugin.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import './assets/css/tailwind.css' 3 | import type { NuxtLabsUIConfiguration } from './Types/variant' 4 | 5 | const defaultOptions: NuxtLabsUIOptions = { 6 | prefix: 'U', 7 | registerComponents: true, 8 | } 9 | 10 | export interface NuxtLabsUIOptions { 11 | prefix?: string 12 | components?: any 13 | theme?: any 14 | registerComponents?: boolean 15 | } 16 | 17 | function create(createOptions: NuxtLabsUIOptions = {}) { 18 | const install = (app: App, installOptions: NuxtLabsUIConfiguration) => { 19 | const options = { 20 | ...defaultOptions, 21 | ...createOptions, 22 | ...installOptions, 23 | } 24 | if (options.registerComponents) { 25 | if (options.components) { 26 | options.components.forEach((component: any) => { 27 | const name = component._name?.startsWith('U') ? component.name.slice(1) : component.name 28 | app.component(`${options.prefix}${name}`, component) 29 | }) 30 | } 31 | } 32 | app.provide('config', installOptions) 33 | } 34 | 35 | return { 36 | install, 37 | } 38 | } 39 | 40 | export default create 41 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/enums/Components.ts: -------------------------------------------------------------------------------- 1 | export enum Components { 2 | UAlert = 'UAlert', 3 | UAccordion = 'UAccordion', 4 | UAvatar = 'UAvatar', 5 | UAvatarGroup = 'UAvatarGroup', 6 | UBadge = 'UBadge', 7 | UButton = 'UButton', 8 | UCard = 'UCard', 9 | UCommandPalette = 'UCommandPalette', 10 | UCommandPaletteGroup = 'UCommandPaletteGroup', 11 | UContainer = 'UContainer', 12 | UContextMenu = 'UContextMenu', 13 | UCheckbox = 'UCheckbox', 14 | ULink = 'ULink', 15 | UButtonGroup = 'UButtonGroup', 16 | UDropdown = 'UDropdown', 17 | UFormGroup = 'UFormGroup', 18 | UIcon = 'UIcon', 19 | UInput = 'UInput', 20 | UKbd = 'UKbd', 21 | UModal = 'UModal', 22 | UNotification = 'UNotification', 23 | UNotifications = 'UNotifications', 24 | UPagination = 'UPagination', 25 | UPopover = 'UPopover', 26 | URadio = 'URadio', 27 | URange = 'URange', 28 | USelect = 'USelect', 29 | USelectMenu = 'USelectMenu', 30 | USkeleton = 'USkeleton', 31 | USlideover = 'USlideover', 32 | UTable = 'UTable', 33 | UTabs = 'UTabs', 34 | UTextarea = 'UTextarea', 35 | UToggle = 'UToggle', 36 | UTooltip = 'UTooltip', 37 | UVerticalNavigation = 'UVerticalNavigation', 38 | } 39 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Kbd/UKbd.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 44 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Container/UContainer.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 48 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useToast.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable symbol-description */ 2 | import type { InjectionKey } from 'vue' 3 | import { inject, provide, ref } from 'vue' 4 | import type { Notification } from '@/Types/components/notification' 5 | 6 | interface ToastProvider { 7 | add: (notification: Partial) => void 8 | remove: (id: string) => void 9 | } 10 | 11 | const toastSymbol: InjectionKey = Symbol() 12 | 13 | export function injectToast() { 14 | const notifications = ref([]) 15 | 16 | function add(notification: Partial) { 17 | const body = { 18 | id: new Date().getTime().toString(), 19 | ...notification, 20 | } 21 | 22 | const index = notifications.value.findIndex((n: Notification) => n.id === body.id) 23 | if (index === -1) 24 | notifications.value.push(body as Notification) 25 | 26 | return body 27 | } 28 | 29 | function remove(id: string) { 30 | notifications.value = notifications.value.filter((n: Notification) => n.id !== id) 31 | } 32 | 33 | provide(toastSymbol, { 34 | notifications, 35 | add, 36 | remove, 37 | }) 38 | 39 | return { 40 | notifications, 41 | add, 42 | remove, 43 | } 44 | } 45 | 46 | export function useToast() { 47 | return inject(toastSymbol) 48 | } 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxt-ui/vue-monorepo", 3 | "version": "0.0.8", 4 | "private": false, 5 | "scripts": { 6 | "build": "rimraf packages/*/{dist,es,lib} && nr -r -F \"./packages/nuxt-ui-vue\" build", 7 | "lint": "eslint .", 8 | "lint:fix": "nr lint --fix", 9 | "clean": "rimraf packages/*/{dist,es,lib}", 10 | "test": "vitest", 11 | "test:update": "vitest -u", 12 | "test:coverage": "vitest --coverage", 13 | "nuxt-ui-vue": "pnpm --filter nuxt-ui-vue", 14 | "postinstall": "npx simple-git-hooks", 15 | "major": "taze minor -wIr" 16 | }, 17 | "dependencies": { 18 | "classnames": "^2.3.2" 19 | }, 20 | "devDependencies": { 21 | "@antfu/eslint-config": "^0.39.8", 22 | "@types/node": "^20.4.9", 23 | "@vitejs/plugin-vue": "^4.2.3", 24 | "@vue/test-utils": "^2.4.1", 25 | "bumpp": "^9.1.1", 26 | "eslint": "8.46.0", 27 | "jsdom": "^22.1.0", 28 | "lint-staged": "^13.2.3", 29 | "rimraf": "^5.0.1", 30 | "simple-git-hooks": "^2.9.0", 31 | "taze": "^0.11.2", 32 | "typescript": "^5.1.6", 33 | "unplugin-auto-import": "^0.16.6", 34 | "unplugin-vue-components": "^0.25.1", 35 | "vite": "^4.4.9", 36 | "vite-plugin-dts": "^3.5.1", 37 | "vitest": "^0.33.0" 38 | }, 39 | "simple-git-hooks": { 40 | "pre-commit": "pnpm lint-staged" 41 | }, 42 | "lint-staged": { 43 | "*.{ts,tsx,vue}": [ 44 | "pnpm lint:fix" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Icon/UIcon.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 56 | -------------------------------------------------------------------------------- /.github/scripts/update-readme-table.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable n/prefer-global/process */ 3 | const fs = require('node:fs') 4 | const path = require('node:path') 5 | 6 | const packageJsonPath = path.join(__dirname, '../../packages/nuxt-ui-vue/package.json') // Adjust the path based on your project structure 7 | const readmePath = path.join(__dirname, '../../README.md') 8 | 9 | // Read the package.json file 10 | fs.readFile(packageJsonPath, 'utf8', (err, packageJsonData) => { 11 | if (err) { 12 | console.error(err) 13 | process.exit(1) 14 | } 15 | 16 | const packageJson = JSON.parse(packageJsonData) 17 | const newNuxtUIVueVersion = packageJson.version 18 | 19 | // Read the README file 20 | fs.readFile(readmePath, 'utf8', (readmeErr, data) => { 21 | if (readmeErr) { 22 | console.error(readmeErr) 23 | process.exit(1) 24 | } 25 | const existingTableRegex = /\| nuxt-ui\s+\| nuxt-ui-vue\s+\|\s+\|[^]*?\|/m 26 | const updatedTableRow = `| nuxt-ui | nuxt-ui-vue |\n|------------------|------------------|\n| v2.7.0 | v${newNuxtUIVueVersion.padEnd(16)} |`.trim() // <-- Remove trailing whitespace 27 | 28 | const updatedData = data.replace(existingTableRegex, updatedTableRow) 29 | 30 | fs.writeFile(readmePath, updatedData, 'utf8', (writeErr) => { 31 | if (writeErr) { 32 | console.error('Error writing README:', writeErr) 33 | process.exit(1) 34 | } 35 | 36 | console.log('README table updated successfully.') 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useTimer.ts: -------------------------------------------------------------------------------- 1 | import { computed, ref } from 'vue-demi' 2 | import { useTimestamp } from '@vueuse/core' 3 | import type { UseTimestampOptions } from '@vueuse/core' 4 | 5 | export function useTimer(cb: (...args: unknown[]) => any, interval: number, options?: UseTimestampOptions) { 6 | let timer: number | null = null 7 | const { pause: tPause, resume: tResume, timestamp } = useTimestamp({ ...(options || {}), controls: true }) 8 | const startTime = ref(null) 9 | 10 | const remaining = computed(() => { 11 | if (!startTime.value) 12 | return 0 13 | 14 | return interval - (timestamp.value - startTime.value) 15 | }) 16 | 17 | function set(...args: unknown[]) { 18 | timer = setTimeout(() => { 19 | timer = null 20 | startTime.value = null 21 | cb(...args) 22 | }, remaining.value) as unknown as number 23 | } 24 | 25 | function clear() { 26 | if (timer) { 27 | clearTimeout(timer) 28 | timer = null 29 | } 30 | } 31 | 32 | function start() { 33 | startTime.value = Date.now() 34 | 35 | set() 36 | } 37 | 38 | function stop() { 39 | clear() 40 | tPause() 41 | } 42 | 43 | function pause() { 44 | clear() 45 | tPause() 46 | } 47 | 48 | function resume() { 49 | set() 50 | tResume() 51 | startTime.value = (startTime.value || 0) + (Date.now() - timestamp.value) 52 | } 53 | 54 | start() 55 | 56 | return { 57 | start, 58 | stop, 59 | pause, 60 | resume, 61 | remaining, 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/utils/getVariantProps.ts: -------------------------------------------------------------------------------- 1 | import type { PropType } from 'vue' 2 | import type { 3 | CSSClassesList, 4 | CSSRawClassesList, 5 | WithVariantProps, 6 | } from '../Types/variant' 7 | 8 | export interface VariantJSWithClassesListProps { 9 | classes?: { 10 | type: PropType> 11 | default: undefined 12 | } 13 | base?: { 14 | type: PropType> 15 | default: undefined 16 | } 17 | variants?: { 18 | type: PropType> 19 | default: undefined 20 | } 21 | variant?: { 22 | type: PropType 23 | default?: string 24 | } 25 | } 26 | 27 | declare interface ObjectWithClassesList { 28 | classesList?: CSSClassesList 29 | } 30 | 31 | export declare const parseVariantWithClassesList: < 32 | P extends ObjectWithClassesList, 33 | >() => P 34 | 35 | export function getVariantPropsWithClassesList< 36 | ClassesKeys extends Record, 37 | >(): VariantJSWithClassesListProps { 38 | return { 39 | classes: { 40 | type: Object as PropType>, 41 | default: undefined, 42 | }, 43 | base: { 44 | type: Object as PropType>, 45 | default: undefined, 46 | }, 47 | variants: { 48 | type: Object as PropType>, 49 | default: undefined, 50 | }, 51 | variant: { 52 | type: [String, Array] as PropType, 53 | default: undefined, 54 | }, 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/layouts/Card/UCard.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 63 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Badge/UBadge.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 68 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Avatar/UAvatarGroup.vue: -------------------------------------------------------------------------------- 1 | 62 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Notification/UNotifications.vue: -------------------------------------------------------------------------------- 1 | 2 | 47 | 48 | 66 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Link/ULink.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 75 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-ui-vue", 3 | "version": "1.0.2-beta.1", 4 | "private": false, 5 | "exports": { 6 | ".": { 7 | "types": "./dist/src/index.d.ts", 8 | "require": "./dist/nuxt-ui-vue.cjs", 9 | "import": "./dist/nuxt-ui-vue.mjs" 10 | }, 11 | "./dist/theme/nuxtlabsTheme": { 12 | "require": "./dist/theme/nuxtlabsTheme.ts", 13 | "import": "./dist/theme/nuxtlabsTheme.ts" 14 | } 15 | }, 16 | "main": "./dist/nuxt-ui-vue.cjs", 17 | "module": "./dist/nuxt-ui-vue.mjs", 18 | "types": "./dist/src/index.d.ts", 19 | "files": [ 20 | "dist", 21 | "src" 22 | ], 23 | "scripts": { 24 | "build": "vite build && pnpm run build:theme", 25 | "build:watch": "vite build --watch", 26 | "build:theme": "esno ./scripts/theme.ts", 27 | "dev": "vite", 28 | "play": "pnpm --filter playground dev", 29 | "prepublishOnly": "pnpm run build", 30 | "release": "pnpm build && bumpp --commit --push && pnpm publish", 31 | "lint": "eslint .", 32 | "lint:fix": "eslint . --fix" 33 | }, 34 | "peerDependencies": { 35 | "vue": "^3.3.4" 36 | }, 37 | "dependencies": { 38 | "@headlessui/vue": "^1.7.15", 39 | "@popperjs/core": "^2.11.8", 40 | "@vueuse/core": "^10.2.1", 41 | "@vueuse/integrations": "^10.2.1", 42 | "@vueuse/math": "^10.2.1", 43 | "defu": "^6.1.2", 44 | "esno": "^0.17.0", 45 | "fuse.js": "^6.6.2", 46 | "ohash": "^1.1.3", 47 | "scule": "^1.0.0", 48 | "tailwind-merge": "^1.14.0", 49 | "vue": "^3.3.4", 50 | "vue-router": "^4.2.4" 51 | }, 52 | "devDependencies": { 53 | "@iconify/vue": "^4.1.1", 54 | "@tailwindcss/forms": "^0.5.4", 55 | "@tsconfig/node18": "^18.2.0", 56 | "@types/node": "^18.17.4", 57 | "@vitejs/plugin-vue": "^4.2.3", 58 | "@vue/tsconfig": "^0.4.0", 59 | "autoprefixer": "^10.4.14", 60 | "bumpp": "^9.1.1", 61 | "npm-run-all": "^4.1.5", 62 | "postcss": "^8.4.27", 63 | "tailwindcss": "^3.3.3", 64 | "typescript": "~5.1.6", 65 | "vite": "^4.4.9", 66 | "vite-plugin-dts": "^3.3.1", 67 | "vue-tsc": "^1.8.8" 68 | }, 69 | "publishConfig": { 70 | "access": "public" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'node:path' 2 | import { URL, fileURLToPath } from 'node:url' 3 | import Vue from '@vitejs/plugin-vue' 4 | import { defineConfig } from 'vite' 5 | import Components from 'unplugin-vue-components/vite' 6 | import AutoImport from 'unplugin-auto-import/vite' 7 | import dtsPlugin from 'vite-plugin-dts' 8 | import * as pkg from './package.json' 9 | 10 | const externals = [ 11 | ...Object.keys(pkg.peerDependencies || {}), 12 | ] 13 | export default defineConfig({ 14 | plugins: [ 15 | Vue(), 16 | dtsPlugin({ 17 | insertTypesEntry: true, 18 | }), 19 | Components({ 20 | dts: true, 21 | resolvers: [ 22 | (componentName: string) => { 23 | if (componentName.startsWith('Icon')) { 24 | return { 25 | name: componentName, 26 | from: '@iconify/vue', 27 | } 28 | } 29 | }, 30 | ], 31 | 32 | types: [ 33 | { 34 | from: 'vue-router', 35 | names: ['RouterLink', 'RouterView', 'RouteLocationRaw'], 36 | }, 37 | ], 38 | }), 39 | 40 | AutoImport({ 41 | imports: [ 42 | 'vue', 43 | 'vue-router', 44 | '@vueuse/core', 45 | { 46 | 'classnames': [ 47 | ['default', 'classNames'], 48 | ], 49 | 'defu': [ 50 | 'defu', 51 | ], 52 | '@iconify/vue': [ 53 | 'loadIcon', 54 | ], 55 | 'ohash': [ 56 | 'isEqual', 57 | ], 58 | }, 59 | { 60 | from: 'vue-router', 61 | imports: ['RouteLocationRaw'], 62 | type: true, 63 | }, 64 | ], 65 | 66 | dirs: ['./src/utils', './src/Types/**', './src/theme', './src/composables', './src/components/Types'], 67 | }), 68 | ], 69 | resolve: { 70 | alias: { 71 | '@': fileURLToPath(new URL('./src', import.meta.url)), 72 | }, 73 | }, 74 | build: { 75 | lib: { 76 | entry: resolve(__dirname, './src/index.ts'), 77 | formats: ['es', 'cjs'], 78 | name: 'nuxt-ui-vue', 79 | fileName: format => format === 'cjs' ? 'nuxt-ui-vue.cjs' : 'nuxt-ui-vue.mjs', 80 | }, 81 | rollupOptions: { 82 | external: externals, 83 | output: { 84 | format: 'esm', 85 | globals: { 86 | vue: 'Vue', 87 | }, 88 | }, 89 | }, 90 | }, 91 | }) 92 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as UAccordion } from './elements/Accordion/UAccordion.vue' 2 | export { default as UAlert } from './elements/Alert/UAlert.vue' 3 | export { default as UAvatar } from './elements/Avatar/UAvatar.vue' 4 | export { default as UAvatarGroup } from './elements/Avatar/UAvatarGroup.vue' 5 | export { default as UBadge } from './elements/Badge/UBadge.vue' 6 | export { default as UButton } from './elements/Button/UButton.vue' 7 | export { default as UButtonGroup } from './elements/Button/UButtonGroup.vue' 8 | export { default as UCard } from './layouts/Card/UCard.vue' 9 | export { default as UCommandPalette } from './navigation/Command-Palette/CommandPalette.vue' 10 | export { default as UCommandPaletteGroup } from './navigation/Command-Palette/CommandPaletteGroup.vue' 11 | export { default as UContainer } from './layouts/Container/UContainer.vue' 12 | export { default as UContextMenu } from './overlays/ContextMenu/UContextMenu.vue' 13 | export { default as UCheckbox } from './forms/Checkbox/UCheckbox.vue' 14 | export { default as UDropdown } from './elements/Dropdown/UDropdown.vue' 15 | export { default as UFormGroup } from './forms/FormGroup/UFormGroup.vue' 16 | export { default as UIcon } from './elements/Icon/UIcon.vue' 17 | export { default as UKbd } from './elements/Kbd/UKbd.vue' 18 | export { default as UModal } from './overlays/Modal/UModal.vue' 19 | export { default as UNotification } from './overlays/Notification/UNotification.vue' 20 | export { default as UNotifications } from './overlays/Notification/UNotifications.vue' 21 | export { default as UInput } from './forms/Input/UInput.vue' 22 | export { default as ULink } from './elements/Link/ULink.vue' 23 | export { default as UPagination } from './navigation/Pagination/UPagination.vue' 24 | export { default as UPopover } from './overlays/Popover/UPopover.vue' 25 | export { default as URadio } from './forms/Radio/URadio.vue' 26 | export { default as URange } from './forms/Range/URange.vue' 27 | export { default as USelect } from './forms/Select/USelect.vue' 28 | export { default as USelectMenu } from './forms/SelectMenu/USelectMenu.vue' 29 | export { default as USkeleton } from './layouts/Skeleton/USkeleton.vue' 30 | export { default as USlideover } from './overlays/Slideover/USlideover.vue' 31 | export { default as UTable } from './data/Table/UTable.vue' 32 | export { default as UTabs } from './navigation/Tabs/UTabs.vue' 33 | export { default as UTextArea } from './forms/Textarea/UTextarea.vue' 34 | export { default as UToggle } from './forms/Toggle/UToggle.vue' 35 | export { default as UTooltip } from './overlays/Tooltip/UTooltip.vue' 36 | export { default as UVerticalNavigation } from './navigation/VerticalNavigation/UVerticalNavigation.vue' 37 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/useVariants.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | import { inject } from 'vue' 3 | import { twMerge } from 'tailwind-merge' 4 | import type { 5 | CSSClass, 6 | CSSClassKeyValuePair, 7 | CSSClasses, 8 | CSSRawClassesList, 9 | NuxtLabsUIConfiguration, 10 | } from '../Types/variant' 11 | import type { Components } from '../Types/enums/Components' 12 | import type { VariantJSWithClassesListProps } from '../utils/getVariantProps' 13 | 14 | export function selectClasses(classesObject: CSSClassKeyValuePair): CSSClasses { 15 | return Object.keys(classesObject).filter( 16 | (className: string) => !!classesObject[className], 17 | ) 18 | } 19 | 20 | function mergeClasses(...classes: CSSClasses): string { 21 | return classes 22 | .map((className: CSSClass): string => { 23 | if (typeof className === 'string' || className === undefined) 24 | return className || '' 25 | 26 | if (Array.isArray(className)) 27 | return mergeClasses(...className) 28 | 29 | return mergeClasses(...selectClasses(className)) 30 | }) 31 | .join(' ') 32 | .replace(/ +/g, ' ') 33 | .trim() 34 | } 35 | 36 | export function useVariants(name: Components, 37 | props: VariantJSWithClassesListProps = {}): { 38 | transitions?: Record> 39 | } & CSSRawClassesList { 40 | const config = inject( 41 | 'config', 42 | {} as NuxtLabsUIConfiguration, 43 | ) 44 | 45 | const globalVariant = config && config[name] 46 | 47 | const finalResult: { 48 | transitions?: Record> 49 | } & CSSRawClassesList = {} 50 | 51 | if (globalVariant) { 52 | for (const [key, value] of Object.entries(globalVariant.base || {})) { 53 | const result = props.base?.[key] 54 | ? [props.base[key]] 55 | : [value] 56 | 57 | const variant = props.variant || 'default' 58 | result.push( 59 | Array.isArray(variant) 60 | ? variant.map( 61 | el => 62 | 63 | props.variants?.[el]?.[key] 64 | || globalVariant?.variants?.[el]?.[key], 65 | ) 66 | // @ts-expect-error 67 | : props.variants?.[variant]?.[key] 68 | // @ts-expect-error 69 | || globalVariant?.variants?.[variant]?.[key], 70 | ) 71 | // @ts-expect-error 72 | finalResult[key as keyof T] = result.filter(el => !!el) 73 | } 74 | } 75 | 76 | for (const [key, value] of Object.entries(finalResult)) 77 | 78 | finalResult[key] = twMerge(mergeClasses(value)) 79 | 80 | finalResult.transitions = config?.transitions || {} 81 | 82 | return finalResult 83 | } 84 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/ContextMenu/UContextMenu.vue: -------------------------------------------------------------------------------- 1 | 81 | 82 | 92 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/navigation/VerticalNavigation/UVerticalNavigation.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 75 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/Types/variant.ts: -------------------------------------------------------------------------------- 1 | import type { Components } from './enums/Components' 2 | import type { UAccordionVariants, UAlertVariants, UAvatarVariants, UBadgeVariants, UButtonGroupVariants, UButtonVariants, UCardVariants, UCheckboxVariants, UCommandPaletteVariants, UContainerVariants, UContextMenuVariants, UDropdownVariants, UFormGroupVariants, UIconVariants, UInputVariants, UKbdVariants, UModalVariants, UNotificationVariants, UNotificationsVariants, UPaginationVariants, URadioVariants, URangeVariants, USelectMenuVariants, USelectVariants, USkeletonVariants, USlideoverVariants, UTabsVariants, UTextareaVariants, UToggleVariants, UTooltipVariants, UVerticalNavigationVariants } from './componentsTypes/components' 3 | 4 | export declare interface CSSClassKeyValuePair { 5 | [key: string]: any 6 | } 7 | export declare type CSSClasses = CSSClass[] 8 | export declare type CSSClass = 9 | | CSSClassKeyValuePair 10 | | string 11 | | CSSClasses 12 | | undefined 13 | 14 | export declare type CSSClassesList = { 15 | [key in ClassesKeys]?: CSSClass 16 | } 17 | 18 | export declare type CSSRawClassesList = { 19 | [T in keyof ClassesKeys]?: CSSClass 20 | } 21 | 22 | export type WithVariantProps

= { 23 | base?: CSSRawClassesList

24 | variants?: Variants

25 | } & P 26 | 27 | export interface Variants

{ 28 | [key: string]: CSSRawClassesList

| undefined 29 | } 30 | 31 | export interface NuxtLabsUIConfiguration { 32 | transitions: Record> 33 | [Components.UAlert]?: UAlertVariants 34 | [Components.UAccordion]?: UAccordionVariants 35 | [Components.UAvatar]?: UAvatarVariants 36 | [Components.UBadge]?: UBadgeVariants 37 | [Components.UButton]?: UButtonVariants 38 | [Components.UButtonGroup]?: UButtonGroupVariants 39 | [Components.UCard]?: UCardVariants 40 | [Components.UCommandPalette]?: UCommandPaletteVariants 41 | [Components.UContainer]?: UContainerVariants 42 | [Components.UContextMenu]?: UContextMenuVariants 43 | [Components.UCheckbox]?: UCheckboxVariants 44 | [Components.UDropdown]?: UDropdownVariants 45 | [Components.UFormGroup]?: UFormGroupVariants 46 | [Components.UIcon]?: UIconVariants 47 | [Components.UInput]?: UInputVariants 48 | [Components.UKbd]?: UKbdVariants 49 | [Components.UModal]?: UModalVariants 50 | [Components.UNotification]?: UNotificationVariants 51 | [Components.UNotifications]?: UNotificationsVariants 52 | [Components.UTextarea]?: UTextareaVariants 53 | [Components.UPagination]?: UPaginationVariants 54 | [Components.URadio]?: URadioVariants 55 | [Components.URange]?: URangeVariants 56 | [Components.USelect]?: USelectVariants 57 | [Components.USelectMenu]?: USelectMenuVariants 58 | [Components.USkeleton]?: USkeletonVariants 59 | [Components.USlideover]?: USlideoverVariants 60 | [Components.UTabs]?: UTabsVariants 61 | [Components.UToggle]?: UToggleVariants 62 | [Components.UTooltip]?: UTooltipVariants 63 | [Components.UVerticalNavigation]?: UVerticalNavigationVariants 64 | } 65 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Radio/URadio.vue: -------------------------------------------------------------------------------- 1 | 85 | 86 | 114 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Toggle/UToggle.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 105 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/composables/usePopper.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, ref, watchEffect } from 'vue' 2 | import type { Ref } from 'vue' 3 | import type { VirtualElement } from '@popperjs/core/lib/popper-lite' 4 | import { defaultModifiers, popperGenerator } from '@popperjs/core/lib/popper-lite' 5 | import type { Instance } from '@popperjs/core' 6 | import flip from '@popperjs/core/lib/modifiers/flip' 7 | import offset from '@popperjs/core/lib/modifiers/offset' 8 | import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow' 9 | import computeStyles from '@popperjs/core/lib/modifiers/computeStyles' 10 | import eventListeners from '@popperjs/core/lib/modifiers/eventListeners' 11 | import type { MaybeElement } from '@vueuse/core' 12 | import { unrefElement } from '@vueuse/core' 13 | import type { PopperOptions } from '@/Types/components/popper' 14 | 15 | export const createPopper = popperGenerator({ 16 | defaultModifiers: [...defaultModifiers, offset, flip, preventOverflow, computeStyles, eventListeners], 17 | }) 18 | 19 | export function usePopper({ 20 | locked = false, 21 | overflowPadding = 8, 22 | offsetDistance = 8, 23 | offsetSkid = 0, 24 | gpuAcceleration = true, 25 | adaptive = true, 26 | scroll = true, 27 | resize = true, 28 | placement, 29 | strategy, 30 | }: PopperOptions, virtualReference?: Ref) { 31 | const reference = ref(null) 32 | const popper = ref(null) 33 | const instance = ref(null) 34 | 35 | onMounted(() => { 36 | watchEffect((onInvalidate) => { 37 | if (!popper.value) 38 | return 39 | if (!reference.value && !virtualReference?.value) 40 | return 41 | 42 | const popperEl = unrefElement(popper) 43 | const referenceEl = virtualReference?.value || unrefElement(reference) 44 | 45 | // if (!(referenceEl instanceof HTMLElement)) { return } 46 | if (!(popperEl instanceof HTMLElement)) 47 | return 48 | if (!referenceEl) 49 | return 50 | 51 | const config: Record = { 52 | modifiers: [ 53 | { 54 | name: 'flip', 55 | enabled: !locked, 56 | }, 57 | { 58 | name: 'preventOverflow', 59 | options: { 60 | padding: overflowPadding, 61 | }, 62 | }, 63 | { 64 | name: 'offset', 65 | options: { 66 | offset: [offsetSkid, offsetDistance], 67 | }, 68 | }, 69 | { 70 | name: 'computeStyles', 71 | options: { 72 | adaptive, 73 | gpuAcceleration, 74 | }, 75 | }, 76 | { 77 | name: 'eventListeners', 78 | options: { 79 | scroll, 80 | resize, 81 | }, 82 | }, 83 | ], 84 | } 85 | 86 | if (placement) 87 | config.placement = placement 88 | 89 | if (strategy) 90 | config.strategy = strategy 91 | 92 | instance.value = createPopper(referenceEl, popperEl, config) 93 | 94 | onInvalidate(instance.value.destroy) 95 | }) 96 | }) 97 | 98 | return [reference, popper, instance] as const 99 | } 100 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Checkbox/UCheckbox.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 127 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, race, body size, disability, ethnicity, sex characteristics, and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, status, or sexual identity and orientation. 7 | 8 | ## Our Standards 9 | 10 | Examples of behavior that contributes to creating a positive environment include: 11 | 12 | - Using welcoming and inclusive language 13 | - Being respectful of differing viewpoints and experiences 14 | - Gracefully accepting constructive criticism 15 | - Focusing on what is best for the community 16 | - Showing empathy towards other community members 17 | 18 | Examples of unacceptable behavior by participants include: 19 | 20 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 21 | - Trolling, insulting/derogatory comments, and personal or political attacks 22 | - Public or private harassment 23 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 24 | - Other conduct which could reasonably be considered inappropriate in a professional setting 25 | 26 | ## Our Responsibilities 27 | 28 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 29 | 30 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 31 | 32 | ## Scope 33 | 34 | This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 35 | 36 | ## Enforcement 37 | 38 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at selemondev19@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 39 | 40 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 41 | 42 | ## Attribution 43 | 44 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 45 | 46 | For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/FormGroup/UFormGroup.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 115 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-vue-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | export {} 7 | 8 | declare module 'vue' { 9 | export interface GlobalComponents { 10 | CommandPalette: typeof import('./src/components/navigation/Command-Palette/CommandPalette.vue')['default'] 11 | CommandPaletteGroup: typeof import('./src/components/navigation/Command-Palette/CommandPaletteGroup.vue')['default'] 12 | Icon: typeof import('@iconify/vue')['Icon'] 13 | RouteLocationRaw: typeof import('vue-router')['RouteLocationRaw'] 14 | RouterLink: typeof import('vue-router')['RouterLink'] 15 | RouterView: typeof import('vue-router')['RouterView'] 16 | UAccordion: typeof import('./src/components/elements/Accordion/UAccordion.vue')['default'] 17 | UAlert: typeof import('./src/components/elements/Alert/UAlert.vue')['default'] 18 | UAvatar: typeof import('./src/components/elements/Avatar/UAvatar.vue')['default'] 19 | UAvatarGroup: typeof import('./src/components/elements/Avatar/UAvatarGroup.vue')['default'] 20 | UBadge: typeof import('./src/components/elements/Badge/UBadge.vue')['default'] 21 | UButton: typeof import('./src/components/elements/Button/UButton.vue')['default'] 22 | UButtonGroup: typeof import('./src/components/elements/Button/UButtonGroup.vue')['default'] 23 | UCard: typeof import('./src/components/layouts/Card/UCard.vue')['default'] 24 | UCheckbox: typeof import('./src/components/forms/Checkbox/UCheckbox.vue')['default'] 25 | UContainer: typeof import('./src/components/layouts/Container/UContainer.vue')['default'] 26 | UContextMenu: typeof import('./src/components/overlays/ContextMenu/UContextMenu.vue')['default'] 27 | UDropdown: typeof import('./src/components/elements/Dropdown/UDropdown.vue')['default'] 28 | UFormGroup: typeof import('./src/components/forms/FormGroup/UFormGroup.vue')['default'] 29 | UIcon: typeof import('./src/components/elements/Icon/UIcon.vue')['default'] 30 | UInput: typeof import('./src/components/forms/Input/UInput.vue')['default'] 31 | UKbd: typeof import('./src/components/elements/Kbd/UKbd.vue')['default'] 32 | ULink: typeof import('./src/components/elements/Link/ULink.vue')['default'] 33 | UModal: typeof import('./src/components/overlays/Modal/UModal.vue')['default'] 34 | UNotification: typeof import('./src/components/overlays/Notification/UNotification.vue')['default'] 35 | UNotifications: typeof import('./src/components/overlays/Notification/UNotifications.vue')['default'] 36 | UPagination: typeof import('./src/components/navigation/Pagination/UPagination.vue')['default'] 37 | UPopover: typeof import('./src/components/overlays/Popover/UPopover.vue')['default'] 38 | URadio: typeof import('./src/components/forms/Radio/URadio.vue')['default'] 39 | URange: typeof import('./src/components/forms/Range/URange.vue')['default'] 40 | USelect: typeof import('./src/components/forms/Select/USelect.vue')['default'] 41 | USelectMenu: typeof import('./src/components/forms/SelectMenu/USelectMenu.vue')['default'] 42 | USkeleton: typeof import('./src/components/layouts/Skeleton/USkeleton.vue')['default'] 43 | USlideover: typeof import('./src/components/overlays/Slideover/USlideover.vue')['default'] 44 | UTable: typeof import('./src/components/data/Table/UTable.vue')['default'] 45 | UTabs: typeof import('./src/components/navigation/Tabs/UTabs.vue')['default'] 46 | UTextarea: typeof import('./src/components/forms/Textarea/UTextarea.vue')['default'] 47 | UToggle: typeof import('./src/components/forms/Toggle/UToggle.vue')['default'] 48 | UTooltip: typeof import('./src/components/overlays/Tooltip/UTooltip.vue')['default'] 49 | UVerticalNavigation: typeof import('./src/components/navigation/VerticalNavigation/UVerticalNavigation.vue')['default'] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Slideover/USlideover.vue: -------------------------------------------------------------------------------- 1 | 108 | 109 | 128 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Modal/UModal.vue: -------------------------------------------------------------------------------- 1 | 101 | 102 | 132 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/overlays/Tooltip/UTooltip.vue: -------------------------------------------------------------------------------- 1 | 109 | 110 | 135 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Range/URange.vue: -------------------------------------------------------------------------------- 1 | 137 | 138 | 157 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Avatar/UAvatar.vue: -------------------------------------------------------------------------------- 1 | 146 | 147 | 159 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/elements/Alert/UAlert.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 138 | -------------------------------------------------------------------------------- /packages/nuxt-ui-vue/src/components/forms/Textarea/UTextarea.vue: -------------------------------------------------------------------------------- 1 | 160 | 161 |