chore(deps): migrate to eslint 9 (#2443)

This commit is contained in:
Benjamin Canac
2024-10-24 10:30:37 +02:00
committed by GitHub
parent b29fcd2650
commit cae4f0c4a8
177 changed files with 2034 additions and 1289 deletions

View File

@@ -1,14 +0,0 @@
node_modules
dist
.nuxt
coverage
*.log*
.DS_Store
.code
*.iml
package-lock.json
templates/*
sw.js
# Templates
src/templates

View File

@@ -1,46 +0,0 @@
module.exports = {
root: true,
extends: ['@nuxt/eslint-config'],
rules: {
// General
semi: ['error', 'never'],
quotes: ['error', 'single'],
'comma-dangle': ['error', 'never'],
'comma-spacing': ['error', { before: false, after: true }],
'keyword-spacing': ['error', { before: true, after: true }],
'space-before-function-paren': ['error', 'always'],
'object-curly-spacing': ['error', 'always'],
'arrow-spacing': ['error', { before: true, after: true }],
'key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
'space-before-blocks': ['error', 'always'],
'space-infix-ops': ['error', { int32Hint: false }],
'no-multi-spaces': ['error', { ignoreEOLComments: true }],
'no-trailing-spaces': ['error'],
// Typescript
'@typescript-eslint/type-annotation-spacing': 'error',
// Vuejs
'vue/multi-word-component-names': 0,
'vue/html-indent': ['error', 2],
'vue/comma-spacing': ['error', { before: false, after: true }],
'vue/script-indent': ['error', 2, { baseIndent: 0 }],
'vue/keyword-spacing': ['error', { before: true, after: true }],
'vue/object-curly-spacing': ['error', 'always'],
'vue/key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
'vue/arrow-spacing': ['error', { before: true, after: true }],
'vue/array-bracket-spacing': ['error', 'never'],
'vue/block-spacing': ['error', 'always'],
'vue/brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
'vue/space-infix-ops': ['error', { int32Hint: false }],
'vue/max-attributes-per-line': [
'error',
{
singleline: {
max: 5
}
}
],
'vue/padding-line-between-blocks': ['error', 'always']
}
}

View File

@@ -50,20 +50,22 @@ const links = computed(() => {
icon: 'i-heroicons-book-open', icon: 'i-heroicons-book-open',
to: '/getting-started', to: '/getting-started',
active: route.path.startsWith('/getting-started') || route.path.startsWith('/components') active: route.path.startsWith('/getting-started') || route.path.startsWith('/components')
}, ...(navigation.value.find(item => item._path === '/pro') ? [{ }, ...(navigation.value.find(item => item._path === '/pro')
label: 'Pro', ? [{
icon: 'i-heroicons-square-3-stack-3d', label: 'Pro',
to: '/pro', icon: 'i-heroicons-square-3-stack-3d',
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose') to: '/pro',
}, { active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
label: 'Pricing', }, {
icon: 'i-heroicons-ticket', label: 'Pricing',
to: '/pro/pricing' icon: 'i-heroicons-ticket',
}, { to: '/pro/pricing'
label: 'Templates', }, {
icon: 'i-heroicons-computer-desktop', label: 'Templates',
to: '/pro/templates' icon: 'i-heroicons-computer-desktop',
}] : []), { to: '/pro/templates'
}]
: []), {
label: 'Releases', label: 'Releases',
icon: 'i-heroicons-rocket-launch', icon: 'i-heroicons-rocket-launch',
to: '/releases' to: '/releases'

View File

@@ -48,8 +48,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { NavItem } from '@nuxt/content' import type { NavItem } from '@nuxt/content'
import type { HeaderLink } from '#ui-pro/types'
import pkg from '@nuxt/ui-pro/package.json' import pkg from '@nuxt/ui-pro/package.json'
import type { HeaderLink } from '#ui-pro/types'
defineProps<{ defineProps<{
links: HeaderLink[] links: HeaderLink[]

View File

@@ -32,10 +32,10 @@ const colorMode = useColorMode()
const primaryColors = computed(() => appConfig.ui.colors.filter(color => color !== 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] }))) const primaryColors = computed(() => appConfig.ui.colors.filter(color => color !== 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
const primary = computed({ const primary = computed({
get () { get() {
return primaryColors.value.find(option => option.value === appConfig.ui.primary) return primaryColors.value.find(option => option.value === appConfig.ui.primary)
}, },
set (option) { set(option) {
appConfig.ui.primary = option.value appConfig.ui.primary = option.value
window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.primary) window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.primary)
@@ -44,10 +44,10 @@ const primary = computed({
const grayColors = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] }))) const grayColors = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
const gray = computed({ const gray = computed({
get () { get() {
return grayColors.value.find(option => option.value === appConfig.ui.gray) return grayColors.value.find(option => option.value === appConfig.ui.gray)
}, },
set (option) { set(option) {
appConfig.ui.gray = option.value appConfig.ui.gray = option.value
window.localStorage.setItem('nuxt-ui-gray', appConfig.ui.gray) window.localStorage.setItem('nuxt-ui-gray', appConfig.ui.gray)

View File

@@ -20,6 +20,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
defineProps<{ color: { value: string, hex: string }, selected: { value: string} }>() defineProps<{ color: { value: string, hex: string }, selected: { value: string } }>()
defineEmits(['select']) defineEmits(['select'])
</script> </script>

View File

@@ -18,10 +18,10 @@
const colorMode = useColorMode() const colorMode = useColorMode()
const isDark = computed({ const isDark = computed({
get () { get() {
return colorMode.value === 'dark' return colorMode.value === 'dark'
}, },
set () { set() {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark' colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
} }
}) })

View File

@@ -54,7 +54,6 @@
import { upperFirst, camelCase, kebabCase } from 'scule' import { upperFirst, camelCase, kebabCase } from 'scule'
import { useShikiHighlighter } from '~/composables/useShikiHighlighter' import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
// eslint-disable-next-line vue/no-dupe-keys
const props = defineProps({ const props = defineProps({
slug: { slug: {
type: String, type: String,
@@ -89,7 +88,7 @@ const props = defineProps({
default: () => [] default: () => []
}, },
options: { options: {
type: Array as PropType<{ name: string; values: string[]; restriction: 'expected' | 'included' | 'excluded' | 'only' }[]>, type: Array as PropType<{ name: string, values: string[], restriction: 'expected' | 'included' | 'excluded' | 'only' }[]>,
default: () => [] default: () => []
}, },
backgroundClass: { backgroundClass: {
@@ -114,7 +113,6 @@ const props = defineProps({
} }
}) })
// eslint-disable-next-line vue/no-dupe-keys
const baseProps = reactive({ ...props.baseProps }) const baseProps = reactive({ ...props.baseProps })
const componentProps = reactive({ ...props.props }) const componentProps = reactive({ ...props.props })
@@ -158,13 +156,13 @@ const generateOptions = (key: string, schema: { kind: string, schema: [], type:
const schemaOptions = Object.values(schema?.schema || {}) const schemaOptions = Object.values(schema?.schema || {})
if (key.toLowerCase() === 'size' && schemaOptions?.length > 0) { if (key.toLowerCase() === 'size' && schemaOptions?.length > 0) {
const baseSizeOrder = { 'xs': 1, 'sm': 2, 'md': 3, 'lg': 4, 'xl': 5 } const baseSizeOrder = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }
schemaOptions.sort((a: string, b: string) => { schemaOptions.sort((a: string, b: string) => {
const aBase = a.match(/[a-zA-Z]+/)[0].toLowerCase() const aBase = a.match(/[a-z]+/i)[0].toLowerCase()
const bBase = b.match(/[a-zA-Z]+/)[0].toLowerCase() const bBase = b.match(/[a-z]+/i)[0].toLowerCase()
const aNum = parseInt(a.match(/\d+/)?.[0]) || 1 const aNum = Number.parseInt(a.match(/\d+/)?.[0]) || 1
const bNum = parseInt(b.match(/\d+/)?.[0]) || 1 const bNum = Number.parseInt(b.match(/\d+/)?.[0]) || 1
if (aBase === bBase) { if (aBase === bBase) {
return aBase === 'xs' ? bNum - aNum : aNum - bNum return aBase === 'xs' ? bNum - aNum : aNum - bNum
@@ -214,7 +212,6 @@ const propsToSelect = computed(() => Object.keys(componentProps).map((key) => {
} }
}).filter(Boolean)) }).filter(Boolean))
// eslint-disable-next-line vue/no-dupe-keys
const code = computed(() => { const code = computed(() => {
let code = `\`\`\`html let code = `\`\`\`html
<template> <template>
@@ -253,7 +250,7 @@ const code = computed(() => {
return code return code
}) })
function renderObject (obj: any) { function renderObject(obj: any) {
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
return `[${obj.map(renderObject).join(', ')}]` return `[${obj.map(renderObject).join(', ')}]`
} }
@@ -272,6 +269,7 @@ function renderObject (obj: any) {
const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`, async () => { const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`, async () => {
let formatted = '' let formatted = ''
try { try {
// @ts-ignore
formatted = await $prettier.format(code.value, { formatted = await $prettier.format(code.value, {
trailingComma: 'none', trailingComma: 'none',
semi: false, semi: false,

View File

@@ -18,7 +18,6 @@ const props = defineProps({
const route = useRoute() const route = useRoute()
const highlighter = useShikiHighlighter() const highlighter = useShikiHighlighter()
// eslint-disable-next-line vue/no-dupe-keys
const slug = props.slug || route.params.slug[route.params.slug.length - 1] const slug = props.slug || route.params.slug[route.params.slug.length - 1]
const camelName = camelCase(slug) const camelName = camelCase(slug)
const name = `U${upperFirst(camelName)}` const name = `U${upperFirst(camelName)}`

View File

@@ -36,7 +36,7 @@ defineProps({
} }
}) })
function startsWithCapital (word) { function startsWithCapital(word) {
if (word.charAt(0).startsWith('"')) { if (word.charAt(0).startsWith('"')) {
return false return false
} }

View File

@@ -13,7 +13,7 @@ const links = [{
<UBreadcrumb :links="links" :divider="null" :ui="{ ol: 'gap-x-3' }"> <UBreadcrumb :links="links" :divider="null" :ui="{ ol: 'gap-x-3' }">
<template #icon="{ link, index, isActive }"> <template #icon="{ link, index, isActive }">
<UAvatar <UAvatar
:alt="(index + 1 ).toString()" :alt="(index + 1).toString()"
:ui="{ :ui="{
background: isActive ? 'bg-primary-500 dark:bg-primary-400' : undefined, background: isActive ? 'bg-primary-500 dark:bg-primary-400' : undefined,
placeholder: isActive ? 'text-white dark:text-gray-900' : !!link.to ? 'group-hover:text-gray-700 dark:group-hover:text-gray-200' : '' placeholder: isActive ? 'text-white dark:text-gray-900' : !!link.to ? 'group-hover:text-gray-700 dark:group-hover:text-gray-200' : ''

View File

@@ -18,19 +18,21 @@ const actions = [
] ]
const groups = computed(() => const groups = computed(() =>
[commandPaletteRef.value?.query ? { [commandPaletteRef.value?.query
key: 'users', ? {
commands: users key: 'users',
} : { commands: users
key: 'recent', }
label: 'Recent searches', : {
commands: users.slice(0, 1) key: 'recent',
}, { label: 'Recent searches',
commands: users.slice(0, 1)
}, {
key: 'actions', key: 'actions',
commands: actions commands: actions
}].filter(Boolean)) }].filter(Boolean))
function onSelect (option) { function onSelect(option) {
if (option.click) { if (option.click) {
option.click() option.click()
} else if (option.to) { } else if (option.to) {

View File

@@ -71,7 +71,7 @@ const ui = {
:autoselect="false" :autoselect="false"
command-attribute="title" command-attribute="title"
:fuse="{ :fuse="{
fuseOptions: { keys: ['title', 'category'] }, fuseOptions: { keys: ['title', 'category'] }
}" }"
placeholder="Search docs" placeholder="Search docs"
/> />

View File

@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
const isOpen = ref(false) const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) }) const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () { function onContextMenu() {
const top = unref(y) - unref(windowY) const top = unref(y) - unref(windowY)
const left = unref(x) const left = unref(x)

View File

@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
const isOpen = ref(false) const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) }) const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () { function onContextMenu() {
const top = unref(y) - unref(windowY) const top = unref(y) - unref(windowY)
const left = unref(x) const left = unref(x)

View File

@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
const isOpen = ref(false) const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) }) const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () { function onContextMenu() {
const top = unref(y) - unref(windowY) const top = unref(y) - unref(windowY)
const left = unref(x) const left = unref(x)

View File

@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
const isOpen = ref(false) const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) }) const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () { function onContextMenu() {
const top = unref(y) - unref(windowY) const top = unref(y) - unref(windowY)
const left = unref(x) const left = unref(x)

View File

@@ -11,11 +11,11 @@ const ranges = [
] ]
const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() }) const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() })
function isRangeSelected (duration: Duration) { function isRangeSelected(duration: Duration) {
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date()) return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
} }
function selectRange (duration: Duration) { function selectRange(duration: Duration) {
selected.value = { start: sub(new Date(), duration), end: new Date() } selected.value = { start: sub(new Date(), duration), end: new Date() }
} }
</script> </script>

View File

@@ -13,7 +13,7 @@ const validate = (state: any): FormError[] => {
return errors return errors
} }
async function onSubmit (event: FormSubmitEvent<any>) { async function onSubmit(event: FormSubmitEvent<any>) {
// Do something with data // Do something with data
console.log(event.data) console.log(event.data)
} }

View File

@@ -53,7 +53,7 @@ type Schema = z.infer<typeof schema>
const form = ref() const form = ref()
async function onSubmit (event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with event.data // Do something with event.data
console.log(event.data) console.log(event.data)
} }

View File

@@ -14,7 +14,7 @@ const state = reactive({
password: undefined password: undefined
}) })
async function onSubmit (event: FormSubmitEvent<any>) { async function onSubmit(event: FormSubmitEvent<any>) {
// Do something with event.data // Do something with event.data
console.log(event.data) console.log(event.data)
} }

View File

@@ -13,12 +13,12 @@ const validate = (state: any): FormError[] => {
return errors return errors
} }
async function onSubmit (event: FormSubmitEvent<any>) { async function onSubmit(event: FormSubmitEvent<any>) {
// Do something with data // Do something with data
console.log(event.data) console.log(event.data)
} }
async function onError (event: FormErrorEvent) { async function onError(event: FormErrorEvent) {
const element = document.getElementById(event.errors[0].id) const element = document.getElementById(event.errors[0].id)
element?.focus() element?.focus()
element?.scrollIntoView({ behavior: 'smooth', block: 'center' }) element?.scrollIntoView({ behavior: 'smooth', block: 'center' })

View File

@@ -14,7 +14,7 @@ const state = reactive({
type Schema = Infer<typeof schema> type Schema = Infer<typeof schema>
async function onSubmit (event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
console.log(event.data) console.log(event.data)
} }
</script> </script>

View File

@@ -14,7 +14,7 @@ const state = reactive({
password: '' password: ''
}) })
async function onSubmit (event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with event.data // Do something with event.data
console.log(event.data) console.log(event.data)
} }

View File

@@ -16,7 +16,7 @@ const state = reactive({
password: undefined password: undefined
}) })
async function onSubmit (event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with event.data // Do something with event.data
console.log(event.data) console.log(event.data)
} }

View File

@@ -14,7 +14,7 @@ const state = reactive({
password: undefined password: undefined
}) })
async function onSubmit (event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
// Do something with data // Do something with data
console.log(event.data) console.log(event.data)
} }

View File

@@ -2,7 +2,7 @@
const loading = ref(false) const loading = ref(false)
const selected = ref() const selected = ref()
async function search (q: string) { async function search(q: string) {
loading.value = true loading.value = true
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } }) const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })

View File

@@ -8,7 +8,7 @@ defineProps({
const emit = defineEmits(['success']) const emit = defineEmits(['success'])
function onSuccess () { function onSuccess() {
emit('success') emit('success')
} }
</script> </script>

View File

@@ -5,11 +5,11 @@ const toast = useToast()
const modal = useModal() const modal = useModal()
const count = ref(0) const count = ref(0)
function openModal () { function openModal() {
count.value += 1 count.value += 1
modal.open(ModalExampleComponent, { modal.open(ModalExampleComponent, {
count: count.value, count: count.value,
onSuccess () { onSuccess() {
toast.add({ toast.add({
title: 'Success !', title: 'Success !',
id: 'modal-success' id: 'modal-success'

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
const toast = useToast() const toast = useToast()
function onCallback () { function onCallback() {
alert('Notification expired!') alert('Notification expired!')
} }
</script> </script>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
const toast = useToast() const toast = useToast()
function onClick () { function onClick() {
alert('Clicked!') alert('Clicked!')
} }
</script> </script>

View File

@@ -11,7 +11,7 @@ const items = ref(Array(50))
:to="(page: number) => ({ :to="(page: number) => ({
query: { page }, query: { page },
// Hash is specified here to prevent the page from scrolling to the top // Hash is specified here to prevent the page from scrolling to the top
hash: '#links', hash: '#links'
})" })"
/> />
</template> </template>

View File

@@ -3,10 +3,10 @@ const temp = ref(35)
const color = computed(() => { const color = computed(() => {
switch (true) { switch (true) {
case temp.value < 10: return 'blue' case temp.value < 10: return 'blue'
case temp.value < 20: return 'amber' case temp.value < 20: return 'amber'
case temp.value < 30: return 'orange' case temp.value < 30: return 'orange'
default: return 'red' default: return 'red'
} }
}) })
</script> </script>

View File

@@ -37,7 +37,7 @@ const labels = computed({
} }
}) })
function hashCode (str) { function hashCode(str) {
let hash = 0 let hash = 0
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash) hash = str.charCodeAt(i) + ((hash << 5) - hash)
@@ -45,7 +45,7 @@ function hashCode (str) {
return hash return hash
} }
function intToRGB (i) { function intToRGB(i) {
const c = (i & 0x00FFFFFF) const c = (i & 0x00FFFFFF)
.toString(16) .toString(16)
.toUpperCase() .toUpperCase()
@@ -53,7 +53,7 @@ function intToRGB (i) {
return '00000'.substring(0, 6 - c.length) + c return '00000'.substring(0, 6 - c.length) + c
} }
function generateColorFromString (str) { function generateColorFromString(str) {
return intToRGB(hashCode(str)) return intToRGB(hashCode(str))
} }
</script> </script>

View File

@@ -38,7 +38,7 @@ const labels = computed({
const showCreateOption = (query, results) => { const showCreateOption = (query, results) => {
const lowercaseQuery = String.prototype.toLowerCase.apply(query || '') const lowercaseQuery = String.prototype.toLowerCase.apply(query || '')
return lowercaseQuery.length >= 3 && !results.find(option => { return lowercaseQuery.length >= 3 && !results.find((option) => {
return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery
}) })
} }

View File

@@ -2,7 +2,7 @@
const loading = ref(false) const loading = ref(false)
const selected = ref([]) const selected = ref([])
async function search (q: string) { async function search(q: string) {
loading.value = true loading.value = true
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } }) const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })

View File

@@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
const props = defineProps({ const props = defineProps({
count: { count: {
type: Number, type: Number,
@@ -8,7 +7,7 @@ const props = defineProps({
}) })
const emits = defineEmits<{ const emits = defineEmits<{
close: []; close: []
}>() }>()
</script> </script>
@@ -27,4 +26,4 @@ const emits = defineEmits<{
<Placeholder class="h-full" /> <Placeholder class="h-full" />
</UCard> </UCard>
</USlideover> </USlideover>
</template> </template>

View File

@@ -3,7 +3,7 @@ import { SlideoverExampleComponent } from '#components'
const slideover = useSlideover() const slideover = useSlideover()
const count = ref(0) const count = ref(0)
function openSlideover () { function openSlideover() {
count.value += 1 count.value += 1
slideover.open(SlideoverExampleComponent, { slideover.open(SlideoverExampleComponent, {
count: count.value, count: count.value,

View File

@@ -19,13 +19,13 @@ const columns = [{
}] }]
const selectedColumns = ref(columns) const selectedColumns = ref(columns)
const columnsTable = computed(() => columns.filter((column) => selectedColumns.value.includes(column))) const columnsTable = computed(() => columns.filter(column => selectedColumns.value.includes(column)))
// Selected Rows // Selected Rows
const selectedRows = ref([]) const selectedRows = ref([])
function select (row) { function select(row) {
const index = selectedRows.value.findIndex((item) => item.id === row.id) const index = selectedRows.value.findIndex(item => item.id === row.id)
if (index === -1) { if (index === -1) {
selectedRows.value.push(row) selectedRows.value.push(row)
} else { } else {
@@ -92,10 +92,10 @@ const { data: todos, status } = await useLazyAsyncData<{
}[]>('todos', () => ($fetch as any)(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, { }[]>('todos', () => ($fetch as any)(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
query: { query: {
q: search.value, q: search.value,
'_page': page.value, _page: page.value,
'_limit': pageCount.value, _limit: pageCount.value,
'_sort': sort.value.column, _sort: sort.value.column,
'_order': sort.value.direction _order: sort.value.direction
} }
}), { }), {
default: () => [], default: () => [],

View File

@@ -31,8 +31,8 @@ const people = [{
role: 'Owner' role: 'Owner'
}] }]
function select (row) { function select(row) {
const index = selected.value.findIndex((item) => item.id === row.id) const index = selected.value.findIndex(item => item.id === row.id)
if (index === -1) { if (index === -1) {
selected.value.push(row) selected.value.push(row)
} else { } else {

View File

@@ -34,53 +34,55 @@ const pending = ref(true)
/* https://codepen.io/jenning/pen/YzNmzaV */ /* https://codepen.io/jenning/pen/YzNmzaV */
.loader { .loader {
--color: rgb(var(--color-primary-400)); --color: rgb(var(--color-primary-400));
--size-mid: 6vmin; --size-mid: 6vmin;
--size-dot: 1.5vmin; --size-dot: 1.5vmin;
--size-bar: 0.4vmin; --size-bar: 0.4vmin;
--size-square: 3vmin; --size-square: 3vmin;
display: block; display: block;
position: relative; position: relative;
width: 50%; width: 50%;
display: grid; display: grid;
place-items: center; place-items: center;
} }
.loader::before, .loader::before,
.loader::after { .loader::after {
content: ''; content: '';
box-sizing: border-box; box-sizing: border-box;
position: absolute; position: absolute;
} }
/** /**
loader --6 loader --6
**/ **/
.loader.--6::before { .loader.--6::before {
width: var(--size-square); width: var(--size-square);
height: var(--size-square); height: var(--size-square);
background-color: var(--color); background-color: var(--color);
top: calc(50% - var(--size-square)); top: calc(50% - var(--size-square));
left: calc(50% - var(--size-square)); left: calc(50% - var(--size-square));
animation: loader-6 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite; animation: loader-6 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite;
} }
@keyframes loader-6 { @keyframes loader-6 {
0%, 100% {
transform: none;
}
25% { 0%,
transform: translateX(100%); 100% {
} transform: none;
}
50% { 25% {
transform: translateX(100%) translateY(100%); transform: translateX(100%);
} }
75% { 50% {
transform: translateY(100%); transform: translateX(100%) translateY(100%);
} }
75% {
transform: translateY(100%);
}
} }
</style> </style>

View File

@@ -53,7 +53,7 @@ const people = [{
role: 'Member' role: 'Member'
}] }]
const items = (row) => [ const items = row => [
[{ [{
label: 'Edit', label: 'Edit',
icon: 'i-heroicons-pencil-square-20-solid', icon: 'i-heroicons-pencil-square-20-solid',

View File

@@ -13,7 +13,7 @@ const items = [{
content: 'Finally, this is the content for Tab3' content: 'Finally, this is the content for Tab3'
}] }]
function onChange (index) { function onChange(index) {
const item = items[index] const item = items[index]
alert(`${item.label} was clicked!`) alert(`${item.label} was clicked!`)

View File

@@ -10,11 +10,11 @@ const items = [{
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' }) const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
const passwordForm = reactive({ currentPassword: '', newPassword: '' }) const passwordForm = reactive({ currentPassword: '', newPassword: '' })
function onSubmitAccount () { function onSubmitAccount() {
console.log('Submitted form:', accountForm) console.log('Submitted form:', accountForm)
} }
function onSubmitPassword () { function onSubmitPassword() {
console.log('Submitted form:', passwordForm) console.log('Submitted form:', passwordForm)
} }
</script> </script>

View File

@@ -12,7 +12,7 @@ const items = [{
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' }) const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
const passwordForm = reactive({ currentPassword: '', newPassword: '' }) const passwordForm = reactive({ currentPassword: '', newPassword: '' })
function onSubmit (form) { function onSubmit(form) {
console.log('Submitted form:', form) console.log('Submitted form:', form)
} }
</script> </script>

View File

@@ -17,15 +17,15 @@ const route = useRoute()
const router = useRouter() const router = useRouter()
const selected = computed({ const selected = computed({
get () { get() {
const index = items.findIndex((item) => item.label === route.query.tab) const index = items.findIndex(item => item.label === route.query.tab)
if (index === -1) { if (index === -1) {
return 0 return 0
} }
return index return index
}, },
set (value) { set(value) {
// Hash is specified here to prevent the page from scrolling to the top // Hash is specified here to prevent the page from scrolling to the top
router.replace({ query: { tab: items[value].label }, hash: '#control-the-selected-index' }) router.replace({ query: { tab: items[value].label }, hash: '#control-the-selected-index' })
} }

View File

@@ -31,9 +31,9 @@ const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanSm = breakpoints.smaller('sm') const smallerThanSm = breakpoints.smaller('sm')
const attrs = { const attrs = {
transparent: true, 'transparent': true,
borderless: true, 'borderless': true,
color: 'primary', 'color': 'primary',
'is-dark': { selector: 'html', darkClass: 'dark' }, 'is-dark': { selector: 'html', darkClass: 'dark' },
'first-day-of-week': 2 'first-day-of-week': 2
} }

View File

@@ -29,7 +29,7 @@
v-else v-else
class="font-semibold flex flex-col gap-1 text-center" class="font-semibold flex flex-col gap-1 text-center"
:class="[ :class="[
!block.slot && (block.inactive || block.inactive === undefined ? 'text-gray-900 dark:text-white' : 'text-white dark:text-gray-900'), !block.slot && (block.inactive || block.inactive === undefined ? 'text-gray-900 dark:text-white' : 'text-white dark:text-gray-900')
]" ]"
> >
{{ block.name }} {{ block.name }}

View File

@@ -36,21 +36,22 @@ const cols = ref(0)
const { width, height } = useElementSize(el) const { width, height } = useElementSize(el)
function createGrid () { function createGrid() {
grid.value = [] grid.value = []
for (let i = 0; i <= rows.value; i++) { for (let i = 0; i <= rows.value; i++) {
// eslint-disable-next-line unicorn/no-new-array
grid.value.push(new Array(cols.value).fill(null)) grid.value.push(new Array(cols.value).fill(null))
} }
} }
function createNewCell () { function createNewCell() {
const x = Math.floor(Math.random() * cols.value) const x = Math.floor(Math.random() * cols.value)
grid.value[0][x] = true grid.value[0][x] = true
} }
function moveCellsDown () { function moveCellsDown() {
for (let row = rows.value - 1; row >= 0; row--) { for (let row = rows.value - 1; row >= 0; row--) {
for (let col = 0; col < cols.value; col++) { for (let col = 0; col < cols.value; col++) {
if (grid.value[row][col] !== null && grid.value[row + 1][col] === null) { if (grid.value[row][col] !== null && grid.value[row + 1][col] === null) {
@@ -69,11 +70,11 @@ function moveCellsDown () {
}, 500) }, 500)
} }
function removeCell (row, col) { function removeCell(row, col) {
grid.value[row][col] = null grid.value[row][col] = null
} }
function calcGrid () { function calcGrid() {
const base = Math.ceil(width.value / 60) const base = Math.ceil(width.value / 60)
const cell = width.value / base const cell = width.value / base

View File

@@ -1,13 +1,15 @@
const useComponentsMetaState = () => useState('components-meta', () => ({})) const useComponentsMetaState = () => useState('components-meta', () => ({}))
export async function fetchComponentMeta (name: string) { export async function fetchComponentMeta(name: string) {
const state = useComponentsMetaState() const state = useComponentsMetaState()
if (state.value[name]?.then) { if (state.value[name]?.then) {
await state.value[name] await state.value[name]
return state.value[name] return state.value[name]
} }
if (state.value[name]) { return state.value[name] } if (state.value[name]) {
return state.value[name]
}
// Store promise to avoid multiple calls // Store promise to avoid multiple calls

View File

@@ -1,6 +1,6 @@
const useContentExamplesCodeState = () => useState('content-examples-code', () => ({})) const useContentExamplesCodeState = () => useState('content-examples-code', () => ({}))
export async function fetchContentExampleCode (name?: string) { export async function fetchContentExampleCode(name?: string) {
if (!name) return if (!name) return
const state = useContentExamplesCodeState() const state = useContentExamplesCodeState()
@@ -8,7 +8,9 @@ export async function fetchContentExampleCode (name?: string) {
await state.value[name] await state.value[name]
return state.value[name] return state.value[name]
} }
if (state.value[name]) { return state.value[name] } if (state.value[name]) {
return state.value[name]
}
// add to nitro prerender // add to nitro prerender
if (import.meta.server) { if (import.meta.server) {

View File

@@ -29,8 +29,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { NuxtError } from '#app'
import type { ParsedContent } from '@nuxt/content' import type { ParsedContent } from '@nuxt/content'
import type { NuxtError } from '#app'
useSeoMeta({ useSeoMeta({
title: 'Page not found', title: 'Page not found',
@@ -57,20 +57,22 @@ const links = computed(() => {
icon: 'i-heroicons-book-open', icon: 'i-heroicons-book-open',
to: '/getting-started', to: '/getting-started',
active: route.path.startsWith('/getting-started') || route.path.startsWith('/components') active: route.path.startsWith('/getting-started') || route.path.startsWith('/components')
}, ...(navigation.value.find(item => item._path === '/pro') ? [{ }, ...(navigation.value.find(item => item._path === '/pro')
label: 'Pro', ? [{
icon: 'i-heroicons-square-3-stack-3d', label: 'Pro',
to: '/pro', icon: 'i-heroicons-square-3-stack-3d',
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose') to: '/pro',
}, { active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
label: 'Pricing', }, {
icon: 'i-heroicons-ticket', label: 'Pricing',
to: '/pro/pricing' icon: 'i-heroicons-ticket',
}, { to: '/pro/pricing'
label: 'Templates', }, {
icon: 'i-heroicons-computer-desktop', label: 'Templates',
to: '/pro/templates' icon: 'i-heroicons-computer-desktop',
}] : []), { to: '/pro/templates'
}]
: []), {
label: 'Releases', label: 'Releases',
icon: 'i-heroicons-rocket-launch', icon: 'i-heroicons-rocket-launch',
to: '/releases' to: '/releases'

View File

@@ -1,3 +1,6 @@
import { existsSync, readFileSync } from 'node:fs'
import fsp from 'node:fs/promises'
import { dirname, join } from 'pathe'
import { import {
defineNuxtModule, defineNuxtModule,
addTemplate, addTemplate,
@@ -5,28 +8,24 @@ import {
createResolver createResolver
} from '@nuxt/kit' } from '@nuxt/kit'
import { existsSync, readFileSync } from 'fs'
import { dirname, join } from 'pathe'
import fsp from 'fs/promises'
export default defineNuxtModule({ export default defineNuxtModule({
meta: { meta: {
name: 'content-examples-code' name: 'content-examples-code'
}, },
async setup (_options, nuxt) { async setup(_options, nuxt) {
const resolver = createResolver(import.meta.url) const resolver = createResolver(import.meta.url)
let _configResolved: any let _configResolved: any
let components: Record<string, any> let components: Record<string, any>
const outputPath = join(nuxt.options.buildDir, 'content-examples-code') const outputPath = join(nuxt.options.buildDir, 'content-examples-code')
async function stubOutput () { async function stubOutput() {
if (existsSync(outputPath + '.mjs')) { if (existsSync(outputPath + '.mjs')) {
return return
} }
await updateOutput('export default {}') await updateOutput('export default {}')
} }
async function fetchComponent (component: string | any) { async function fetchComponent(component: string | any) {
if (typeof component === 'string') { if (typeof component === 'string') {
if (components[component]) { if (components[component]) {
component = components[component] component = components[component]
@@ -57,7 +56,7 @@ export default defineNuxtModule({
const getVirtualModuleContent = () => const getVirtualModuleContent = () =>
`export default ${getStringifiedComponents()}` `export default ${getStringifiedComponents()}`
async function updateOutput (content?: string) { async function updateOutput(content?: string) {
const path = outputPath + '.mjs' const path = outputPath + '.mjs'
if (!existsSync(dirname(path))) { if (!existsSync(dirname(path))) {
await fsp.mkdir(dirname(path), { recursive: true }) await fsp.mkdir(dirname(path), { recursive: true })
@@ -68,13 +67,13 @@ export default defineNuxtModule({
await fsp.writeFile(path, content || getVirtualModuleContent(), 'utf-8') await fsp.writeFile(path, content || getVirtualModuleContent(), 'utf-8')
} }
async function fetchComponents () { async function fetchComponents() {
await Promise.all(Object.keys(components).map(fetchComponent)) await Promise.all(Object.keys(components).map(fetchComponent))
} }
nuxt.hook('components:extend', async (_components) => { nuxt.hook('components:extend', async (_components) => {
components = _components components = _components
.filter((v) => v.shortPath.includes('components/content/examples/')) .filter(v => v.shortPath.includes('components/content/examples/'))
.reduce((acc, component) => { .reduce((acc, component) => {
acc[component.pascalName] = component acc[component.pascalName] = component
return acc return acc
@@ -93,17 +92,17 @@ export default defineNuxtModule({
vite.config.plugins.push({ vite.config.plugins.push({
name: 'content-examples-code', name: 'content-examples-code',
enforce: 'post', enforce: 'post',
async buildStart () { async buildStart() {
if (_configResolved?.build.ssr) { if (_configResolved?.build.ssr) {
return return
} }
await fetchComponents() await fetchComponents()
await updateOutput() await updateOutput()
}, },
configResolved (config) { configResolved(config) {
_configResolved = config _configResolved = config
}, },
async handleHotUpdate ({ file }) { async handleHotUpdate({ file }) {
if ( if (
Object.entries(components).some( Object.entries(components).some(
([, comp]: any) => comp.filePath === file ([, comp]: any) => comp.filePath === file

View File

@@ -8,13 +8,15 @@ const { resolve } = createResolver(import.meta.url)
export default defineNuxtConfig({ export default defineNuxtConfig({
// @ts-ignore // @ts-ignore
extends: process.env.NUXT_UI_PRO_PATH ? [ extends: process.env.NUXT_UI_PRO_PATH
process.env.NUXT_UI_PRO_PATH, ? [
resolve(process.env.NUXT_UI_PRO_PATH, '.docs') process.env.NUXT_UI_PRO_PATH,
] : [ resolve(process.env.NUXT_UI_PRO_PATH, '.docs')
'@nuxt/ui-pro', ]
process.env.NUXT_GITHUB_TOKEN && ['github:nuxt/ui-pro/.docs#dev', { giget: { auth: process.env.NUXT_GITHUB_TOKEN } }] : [
].filter(Boolean), '@nuxt/ui-pro',
process.env.NUXT_GITHUB_TOKEN && ['github:nuxt/ui-pro/.docs#dev', { giget: { auth: process.env.NUXT_GITHUB_TOKEN } }]
].filter(Boolean),
modules: [ modules: [
'@nuxt/content', '@nuxt/content',
@@ -29,15 +31,8 @@ export default defineNuxtConfig({
'modules/content-examples-code' 'modules/content-examples-code'
], ],
runtimeConfig: { site: {
public: { url: 'https://ui.nuxt.com'
version: pkg.version
}
},
ui: {
global: true,
safelistColors: excludeColors(colors)
}, },
content: { content: {
@@ -48,31 +43,42 @@ export default defineNuxtConfig({
] ]
}, },
sources: { sources: {
pro: process.env.NUXT_UI_PRO_PATH ? { pro: process.env.NUXT_UI_PRO_PATH
prefix: '/pro', ? {
driver: 'fs', prefix: '/pro',
base: resolve(process.env.NUXT_UI_PRO_PATH, '.docs/content/pro') driver: 'fs',
} : process.env.NUXT_GITHUB_TOKEN ? { base: resolve(process.env.NUXT_UI_PRO_PATH, '.docs/content/pro')
prefix: '/pro', }
driver: 'github', : process.env.NUXT_GITHUB_TOKEN
repo: 'nuxt/ui-pro', ? {
branch: 'dev', prefix: '/pro',
dir: '.docs/content/pro', driver: 'github',
token: process.env.NUXT_GITHUB_TOKEN || '' repo: 'nuxt/ui-pro',
} : undefined branch: 'dev',
dir: '.docs/content/pro',
token: process.env.NUXT_GITHUB_TOKEN || ''
}
: undefined
} }
}, },
image: { ui: {
provider: 'ipx' global: true,
safelistColors: excludeColors(colors)
}, },
icon: { runtimeConfig: {
clientBundle: { public: {
scan: true version: pkg.version
} }
}, },
routeRules: {
'/components': { redirect: '/components/accordion', prerender: false }
},
compatibilityDate: '2024-07-23',
nitro: { nitro: {
prerender: { prerender: {
routes: [ routes: [
@@ -86,8 +92,32 @@ export default defineNuxtConfig({
} }
}, },
routeRules: { vite: {
'/components': { redirect: '/components/accordion', prerender: false } optimizeDeps: {
include: ['date-fns']
}
},
typescript: {
strict: false
},
hooks: {
// Related to https://github.com/nuxt/nuxt/pull/22558
'components:extend': (components) => {
components.forEach((component) => {
if (component.shortPath.includes(process.env.NUXT_UI_PRO_PATH || '@nuxt/ui-pro')) {
component.global = true
} else if (component.global) {
component.global = 'sync'
}
})
}
},
cloudflareAnalytics: {
token: '1e2b0c5e9a214f0390b9b94e043d8d4c',
scriptPath: false
}, },
componentMeta: { componentMeta: {
@@ -111,37 +141,13 @@ export default defineNuxtConfig({
} }
}, },
cloudflareAnalytics: { icon: {
token: '1e2b0c5e9a214f0390b9b94e043d8d4c', clientBundle: {
scriptPath: false scan: true
},
hooks: {
// Related to https://github.com/nuxt/nuxt/pull/22558
'components:extend': (components) => {
components.forEach((component) => {
if (component.shortPath.includes(process.env.NUXT_UI_PRO_PATH || '@nuxt/ui-pro')) {
component.global = true
} else if (component.global) {
component.global = 'sync'
}
})
} }
}, },
typescript: { image: {
strict: false provider: 'ipx'
}, }
site: {
url: 'https://ui.nuxt.com'
},
vite: {
optimizeDeps: {
include: ['date-fns']
}
},
compatibilityDate: '2024-07-23'
}) })

View File

@@ -295,7 +295,7 @@
wrapper: 'px-4 py-2.5 border-gray-800/10 dark:border-gray-200/10 cursor-pointer', wrapper: 'px-4 py-2.5 border-gray-800/10 dark:border-gray-200/10 cursor-pointer',
icon: { icon: {
wrapper: 'mb-2 p-1', wrapper: 'mb-2 p-1',
base: 'h-4 w-4', base: 'h-4 w-4'
}, },
title: 'text-sm', title: 'text-sm',
description: 'text-xs' description: 'text-xs'
@@ -466,188 +466,212 @@ const steps = {
const inc = computed(() => (height.value - 32 - 64 - 32 - 32) / 4) const inc = computed(() => (height.value - 32 - 64 - 32 - 32) / 4)
const landingBlocks = computed(() => isAfterStep(steps.landing) && isBeforeStep(steps.docs) ? [{ const landingBlocks = computed(() => isAfterStep(steps.landing) && isBeforeStep(steps.docs)
class: 'inset-x-0 top-20 bottom-20 overflow-hidden', ? [{
inactive: true, class: 'inset-x-0 top-20 bottom-20 overflow-hidden',
children: [{ inactive: true,
name: 'ULandingHero',
to: '/pro/components/landing-hero',
class: [
'inset-4',
isAfterStep(steps.landing + 2) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--step-y': `${getStepY(steps.landing + 2)}px`
},
inactive: isAfterStep(steps.landing + 1),
children: [{
slot: 'landing-hero',
class: 'inset-4'
}]
}, isAfterStep(steps.landing + 2) && {
name: 'ULandingSection',
to: '/pro/components/landing-section',
class: [
'inset-4',
isBeforeStep(steps.landing + 6) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]',
isAfterStep(steps.landing + 10) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--height': (inc.value * 4) + 'px',
'--step-y': `${getStepY(steps.landing + 10)}px`,
'--prev-step-y': `${getStepY(steps.landing + 2)}px`
},
inactive: isAfterStep(steps.landing + 7),
children: [{
slot: 'landing-section',
class: 'inset-x-4 top-16'
}, {
name: 'ULandingGrid',
to: '/pro/components/landing-grid',
class: ['inset-x-4 bottom-4 top-48', isAfterStep(steps.landing + 8) && 'grid grid-cols-4 gap-4 p-4'].filter(Boolean).join(' '),
inactive: isAfterStep(steps.landing + 8),
children: [isAfterStep(steps.landing + 9) ? {
slot: 'landing-card-1',
class: '!relative'
} : {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9) ? {
slot: 'landing-card-2',
class: '!relative h-full'
} : {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9) ? {
slot: 'landing-card-3',
class: '!relative h-full'
} : {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9) ? {
slot: 'landing-card-4',
class: '!relative h-full'
} : {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}]
}]
}, isAfterStep(steps.landing + 10) && {
name: 'ULandingSection',
to: '/pro/components/landing-section',
class: [
'inset-4',
isBeforeStep(steps.landing + 14) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--height': (inc.value * 4) + 'px',
'--step-y': `${getStepY(steps.landing + 18)}px`,
'--prev-step-y': `${getStepY(steps.landing + 10)}px`
},
inactive: isAfterStep(steps.landing + 15),
children: [{
name: 'ULandingCTA',
class: 'inset-4',
inactive: isAfterStep(steps.landing + 16),
children: [{ children: [{
slot: 'landing-cta', name: 'ULandingHero',
class: 'inset-0' to: '/pro/components/landing-hero',
}] class: [
'inset-4',
isAfterStep(steps.landing + 2) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--step-y': `${getStepY(steps.landing + 2)}px`
},
inactive: isAfterStep(steps.landing + 1),
children: [{
slot: 'landing-hero',
class: 'inset-4'
}]
}, isAfterStep(steps.landing + 2) && {
name: 'ULandingSection',
to: '/pro/components/landing-section',
class: [
'inset-4',
isBeforeStep(steps.landing + 6) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]',
isAfterStep(steps.landing + 10) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--height': (inc.value * 4) + 'px',
'--step-y': `${getStepY(steps.landing + 10)}px`,
'--prev-step-y': `${getStepY(steps.landing + 2)}px`
},
inactive: isAfterStep(steps.landing + 7),
children: [{
slot: 'landing-section',
class: 'inset-x-4 top-16'
}, {
name: 'ULandingGrid',
to: '/pro/components/landing-grid',
class: ['inset-x-4 bottom-4 top-48', isAfterStep(steps.landing + 8) && 'grid grid-cols-4 gap-4 p-4'].filter(Boolean).join(' '),
inactive: isAfterStep(steps.landing + 8),
children: [isAfterStep(steps.landing + 9)
? {
slot: 'landing-card-1',
class: '!relative'
}
: {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9)
? {
slot: 'landing-card-2',
class: '!relative h-full'
}
: {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9)
? {
slot: 'landing-card-3',
class: '!relative h-full'
}
: {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}, isAfterStep(steps.landing + 9)
? {
slot: 'landing-card-4',
class: '!relative h-full'
}
: {
name: 'ULandingCard',
to: '/pro/components/landing-card',
class: '!relative h-full',
inactive: false
}]
}]
}, isAfterStep(steps.landing + 10) && {
name: 'ULandingSection',
to: '/pro/components/landing-section',
class: [
'inset-4',
isBeforeStep(steps.landing + 14) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]'
].filter(Boolean).join(' '),
style: {
'--height': (inc.value * 4) + 'px',
'--step-y': `${getStepY(steps.landing + 18)}px`,
'--prev-step-y': `${getStepY(steps.landing + 10)}px`
},
inactive: isAfterStep(steps.landing + 15),
children: [{
name: 'ULandingCTA',
class: 'inset-4',
inactive: isAfterStep(steps.landing + 16),
children: [{
slot: 'landing-cta',
class: 'inset-0'
}]
}]
}].filter(Boolean)
}] }]
}].filter(Boolean) : [])
}] : [])
const docsBlocks = computed(() => [isAfterStep(steps.docs) && { const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
name: 'UPage', name: 'UPage',
to: '/pro/components/page', to: '/pro/components/page',
class: 'inset-x-0 top-20 bottom-20', class: 'inset-x-0 top-20 bottom-20',
inactive: isAfterStep(steps.docs + 1), inactive: isAfterStep(steps.docs + 1),
children: [isAfterStep(steps.docs + 2) ? { children: [isAfterStep(steps.docs + 2)
name: 'UAside', ? {
to: '/pro/components/aside', name: 'UAside',
class: 'left-4 inset-y-4 w-64', to: '/pro/components/aside',
inactive: isAfterStep(steps.docs + 3), class: 'left-4 inset-y-4 w-64',
children: [isAfterStep(steps.docs + 4) ? { inactive: isAfterStep(steps.docs + 3),
slot: 'aside-top', children: [isAfterStep(steps.docs + 4)
class: 'inset-x-4 top-4' ? {
} : { slot: 'aside-top',
name: '#top', class: 'inset-x-4 top-4'
class: 'inset-x-4 top-4 h-9' }
}, isAfterStep(steps.docs + 5) ? { : {
name: 'UNavigationTree', name: '#top',
to: '/pro/components/navigation-tree', class: 'inset-x-4 top-4 h-9'
class: ['inset-x-4 top-[4.25rem] bottom-4', isAfterStep(steps.docs + 6) && '!bg-transparent !border-0'].join(' '), }, isAfterStep(steps.docs + 5)
inactive: isAfterStep(steps.docs + 6), ? {
children: [{ name: 'UNavigationTree',
slot: 'aside-default', to: '/pro/components/navigation-tree',
class: 'inset-0' class: ['inset-x-4 top-[4.25rem] bottom-4', isAfterStep(steps.docs + 6) && '!bg-transparent !border-0'].join(' '),
inactive: isAfterStep(steps.docs + 6),
children: [{
slot: 'aside-default',
class: 'inset-0'
}]
}
: {
name: '#default',
class: 'inset-x-4 top-[4.25rem] bottom-4'
}]
}
: {
name: '#left',
class: 'left-4 inset-y-4 w-64'
}, isAfterStep(steps.docs + 7)
? {
name: 'UPage',
to: '/pro/components/page',
class: 'left-72 right-4 inset-y-4',
inactive: isAfterStep(steps.docs + 8),
children: [...(isAfterStep(steps.docs + 9)
? [{
name: 'UPageHeader',
to: '/pro/components/page-header',
class: 'top-4 left-4 right-72 h-32',
inactive: isAfterStep(steps.docs + 10),
children: [{
slot: 'page-header',
class: 'inset-4 justify-start'
}]
}, {
name: 'UPageBody',
to: '/pro/components/page-body',
class: 'top-40 left-4 right-72 bottom-4 overflow-y-auto',
inactive: isAfterStep(steps.docs + 11),
children: [{
slot: 'page-body',
class: 'inset-x-4 top-4 justify-start'
}, isAfterStep(steps.docs + 12)
? {
slot: 'content-surround',
class: 'bottom-4 inset-x-4 h-28'
}
: {
name: 'UContentSurround',
to: '/pro/components/content-surround',
class: 'bottom-4 inset-x-4 h-28',
inactive: false
}]
}]
: [{
name: '#default',
class: 'left-4 right-72 inset-y-4'
}]), isAfterStep(steps.docs + 13)
? {
name: 'UContentToc',
to: '/pro/components/content-toc',
class: 'right-4 inset-y-4 w-64',
inactive: isAfterStep(steps.docs + 14),
children: [{
slot: 'content-toc',
class: 'inset-4 overflow-y-auto'
}]
}
: {
name: '#right',
class: 'right-4 inset-y-4 w-64'
}]
}
: {
name: '#default',
class: 'left-72 right-4 inset-y-4'
}] }]
} : {
name: '#default',
class: 'inset-x-4 top-[4.25rem] bottom-4'
}]
} : {
name: '#left',
class: 'left-4 inset-y-4 w-64'
}, isAfterStep(steps.docs + 7) ? {
name: 'UPage',
to: '/pro/components/page',
class: 'left-72 right-4 inset-y-4',
inactive: isAfterStep(steps.docs + 8),
children: [...(isAfterStep(steps.docs + 9) ? [{
name: 'UPageHeader',
to: '/pro/components/page-header',
class: 'top-4 left-4 right-72 h-32',
inactive: isAfterStep(steps.docs + 10),
children: [{
slot: 'page-header',
class: 'inset-4 justify-start'
}]
}, {
name: 'UPageBody',
to: '/pro/components/page-body',
class: 'top-40 left-4 right-72 bottom-4 overflow-y-auto',
inactive: isAfterStep(steps.docs + 11),
children: [{
slot: 'page-body',
class: 'inset-x-4 top-4 justify-start'
}, isAfterStep(steps.docs + 12) ? {
slot: 'content-surround',
class: 'bottom-4 inset-x-4 h-28'
} : {
name: 'UContentSurround',
to: '/pro/components/content-surround',
class: 'bottom-4 inset-x-4 h-28',
inactive: false
}]
}] : [{
name: '#default',
class: 'left-4 right-72 inset-y-4'
}]), isAfterStep(steps.docs + 13) ? {
name: 'UContentToc',
to: '/pro/components/content-toc',
class: 'right-4 inset-y-4 w-64',
inactive: isAfterStep(steps.docs + 14),
children: [{
slot: 'content-toc',
class: 'inset-4 overflow-y-auto'
}]
} : {
name: '#right',
class: 'right-4 inset-y-4 w-64'
}]
} : {
name: '#default',
class: 'left-72 right-4 inset-y-4'
}]
}].filter(Boolean)) }].filter(Boolean))
const blocks = computed(() => [isAfterStep(steps.header) && { const blocks = computed(() => [isAfterStep(steps.header) && {
@@ -655,62 +679,74 @@ const blocks = computed(() => [isAfterStep(steps.header) && {
to: '/pro/components/header', to: '/pro/components/header',
class: 'h-16 inset-x-0 top-0', class: 'h-16 inset-x-0 top-0',
inactive: isAfterStep(steps.header + 1), inactive: isAfterStep(steps.header + 1),
children: [isAfterStep(steps.header + 2) ? { children: [isAfterStep(steps.header + 2)
slot: 'header-left', ? {
class: 'left-4 top-4' slot: 'header-left',
} : { class: 'left-4 top-4'
name: '#left', }
class: 'left-4 inset-y-4 w-64' : {
}, isAfterStep(steps.header + 3) ? { name: '#left',
slot: 'header-center', class: 'left-4 inset-y-4 w-64'
class: 'inset-x-72 top-5' }, isAfterStep(steps.header + 3)
} : { ? {
name: '#center', slot: 'header-center',
class: 'inset-x-72 inset-y-4' class: 'inset-x-72 top-5'
}, isAfterStep(steps.header + 4) ? { }
slot: 'header-right', : {
class: 'right-4 top-4' name: '#center',
} : { class: 'inset-x-72 inset-y-4'
name: '#right', }, isAfterStep(steps.header + 4)
class: 'right-4 inset-y-4 w-64' ? {
}] slot: 'header-right',
class: 'right-4 top-4'
}
: {
name: '#right',
class: 'right-4 inset-y-4 w-64'
}]
}, isAfterStep(steps.footer) && { }, isAfterStep(steps.footer) && {
name: 'UFooter', name: 'UFooter',
to: '/pro/components/footer', to: '/pro/components/footer',
class: 'h-16 inset-x-0 bottom-0', class: 'h-16 inset-x-0 bottom-0',
inactive: isAfterStep(steps.footer + 1), inactive: isAfterStep(steps.footer + 1),
children: [isAfterStep(steps.footer + 2) ? { children: [isAfterStep(steps.footer + 2)
slot: 'footer-left', ? {
class: 'left-4 bottom-5' slot: 'footer-left',
} : { class: 'left-4 bottom-5'
name: '#left', }
class: 'left-4 inset-y-4 w-64' : {
}, isAfterStep(steps.footer + 3) ? { name: '#left',
slot: 'footer-center', class: 'left-4 inset-y-4 w-64'
class: 'inset-x-72 bottom-5' }, isAfterStep(steps.footer + 3)
} : { ? {
name: '#center', slot: 'footer-center',
class: 'inset-x-72 inset-y-4' class: 'inset-x-72 bottom-5'
}, isAfterStep(steps.footer + 4) ? { }
slot: 'footer-right', : {
class: 'right-4 bottom-4' name: '#center',
} : { class: 'inset-x-72 inset-y-4'
name: '#right', }, isAfterStep(steps.footer + 4)
class: 'right-4 inset-y-4 w-64' ? {
}] slot: 'footer-right',
class: 'right-4 bottom-4'
}
: {
name: '#right',
class: 'right-4 inset-y-4 w-64'
}]
}, ...landingBlocks.value, ...docsBlocks.value].filter(Boolean)) }, ...landingBlocks.value, ...docsBlocks.value].filter(Boolean))
// Methods // Methods
function isBeforeStep (i = 0) { function isBeforeStep(i = 0) {
return y.value < (start.value + (i * inc.value)) return y.value < (start.value + (i * inc.value))
} }
function isAfterStep (i = 0) { function isAfterStep(i = 0) {
return y.value >= (start.value + (i * inc.value)) return y.value >= (start.value + (i * inc.value))
} }
function getStepY (step: number) { function getStepY(step: number) {
return start.value + (step * inc.value) return start.value + (step * inc.value)
} }

View File

@@ -50,7 +50,7 @@ const dates = computed(() => {
const days = eachDayOfInterval({ start: new Date(first.published_at), end: new Date() }) const days = eachDayOfInterval({ start: new Date(first.published_at), end: new Date() })
return days.reverse().map(day => { return days.reverse().map((day) => {
return { return {
day, day,
release: releases.value.find(release => isSameDay(new Date(release.published_at), day)), release: releases.value.find(release => isSameDay(new Date(release.published_at), day)),

View File

@@ -6,7 +6,7 @@ export interface SimplePrettier {
format: (source: string, options?: Options) => Promise<string> format: (source: string, options?: Options) => Promise<string>
} }
function createPrettierWorkerApi (worker: Worker): SimplePrettier { function createPrettierWorkerApi(worker: Worker): SimplePrettier {
let counter = 0 let counter = 0
const handlers: any = {} const handlers: any = {}
@@ -18,6 +18,7 @@ function createPrettierWorkerApi (worker: Worker): SimplePrettier {
} }
const [resolve, reject] = handlers[uid] const [resolve, reject] = handlers[uid]
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete handlers[uid] delete handlers[uid]
if (error) { if (error) {
@@ -27,7 +28,7 @@ function createPrettierWorkerApi (worker: Worker): SimplePrettier {
} }
}) })
function postMessage<T> (message: any) { function postMessage<T>(message: any) {
const uid = ++counter const uid = ++counter
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
handlers[uid] = [resolve, reject] handlers[uid] = [resolve, reject]
@@ -36,7 +37,7 @@ function createPrettierWorkerApi (worker: Worker): SimplePrettier {
} }
return { return {
format (source: string, options?: Options) { format(source: string, options?: Options) {
return postMessage({ type: 'format', source, options }) return postMessage({ type: 'format', source, options })
} }
} }
@@ -47,7 +48,7 @@ export default defineNuxtPlugin(async () => {
if (import.meta.server) { if (import.meta.server) {
const prettierModule = await import('prettier') const prettierModule = await import('prettier')
prettier = { prettier = {
format (source, options = {}) { format(source, options = {}) {
return prettierModule.format(source, defu(options, { return prettierModule.format(source, defu(options, {
parser: 'markdown' parser: 'markdown'
})) }))

View File

@@ -3,7 +3,7 @@ import colors from '#tailwind-config/theme/colors'
export default defineNuxtPlugin({ export default defineNuxtPlugin({
enforce: 'post', enforce: 'post',
setup () { setup() {
const appConfig = useAppConfig() const appConfig = useAppConfig()
const root = computed(() => { const root = computed(() => {

View File

@@ -1,6 +1,6 @@
import { Octokit } from '@octokit/rest' import { Octokit } from '@octokit/rest'
function isUserABot (user) { function isUserABot(user) {
return user?.login?.endsWith('-bot') || user?.login?.endsWith('[bot]') return user?.login?.endsWith('-bot') || user?.login?.endsWith('[bot]')
} }

View File

@@ -6,14 +6,14 @@ self.onmessage = async function (event) {
}) })
} }
function handleMessage (message) { function handleMessage(message) {
switch (message.type) { switch (message.type) {
case 'format': case 'format':
return handleFormatMessage(message) return handleFormatMessage(message)
} }
} }
async function handleFormatMessage (message) { async function handleFormatMessage(message) {
if (!globalThis.prettier) { if (!globalThis.prettier) {
await Promise.all([ await Promise.all([
import('https://unpkg.com/prettier@3.3.3/standalone.js'), import('https://unpkg.com/prettier@3.3.3/standalone.js'),

19
eslint.config.mjs Normal file
View File

@@ -0,0 +1,19 @@
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
export default createConfigForNuxt({
features: {
tooling: true,
stylistic: {
commaDangle: 'never',
braceStyle: '1tbs'
}
}
}).overrideRules({
'vue/multi-word-component-names': 'off',
'vue/max-attributes-per-line': ['error', { singleline: 5 }],
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unsafe-function-type': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-explicit-any': 'off'
})

View File

@@ -56,12 +56,12 @@
"tailwindcss": "^3.4.14" "tailwindcss": "^3.4.14"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint-config": "^0.4.0", "@nuxt/eslint-config": "^0.6.0",
"@nuxt/module-builder": "^0.8.4", "@nuxt/module-builder": "^0.8.4",
"@nuxt/test-utils": "^3.14.4", "@nuxt/test-utils": "^3.14.4",
"@release-it/conventional-changelog": "^9.0.1", "@release-it/conventional-changelog": "^9.0.1",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"eslint": "^8.57.0", "eslint": "^9.13.0",
"happy-dom": "^14.12.3", "happy-dom": "^14.12.3",
"joi": "^17.13.3", "joi": "^17.13.3",
"nuxt": "^3.13.2", "nuxt": "^3.13.2",

View File

@@ -4,4 +4,4 @@ export default defineNuxtConfig({
], ],
compatibilityDate: '2024-07-23' compatibilityDate: '2024-07-23'
}) })

847
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,6 @@
"enabled": true "enabled": true
}, },
"ignoreDeps": [ "ignoreDeps": [
"@nuxt/eslint-config",
"eslint",
"happy-dom", "happy-dom",
"valibot30", "valibot30",
"valibot31" "valibot31"

View File

@@ -1,8 +1,8 @@
import { promises as fsp } from 'fs' import { promises as fsp } from 'node:fs'
import { resolve } from 'path' import { resolve } from 'node:path'
import { execSync } from 'child_process' import { execSync } from 'node:child_process'
async function loadPackage (dir: string) { async function loadPackage(dir: string) {
const pkgPath = resolve(dir, 'package.json') const pkgPath = resolve(dir, 'package.json')
const data = JSON.parse(await fsp.readFile(pkgPath, 'utf-8').catch(() => '{}')) const data = JSON.parse(await fsp.readFile(pkgPath, 'utf-8').catch(() => '{}'))
@@ -16,7 +16,7 @@ async function loadPackage (dir: string) {
} }
} }
async function main () { async function main() {
const pkg = await loadPackage(process.cwd()) const pkg = await loadPackage(process.cwd())
const commit = execSync('git rev-parse --short HEAD').toString('utf-8').trim() const commit = execSync('git rev-parse --short HEAD').toString('utf-8').trim()
@@ -31,7 +31,6 @@ async function main () {
} }
main().catch((err) => { main().catch((err) => {
// eslint-disable-next-line no-console
console.error(err) console.error(err)
process.exit(1) process.exit(1)
}) })

View File

@@ -2,7 +2,7 @@ import { createRequire } from 'node:module'
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit' import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit'
import { name, version } from '../package.json' import { name, version } from '../package.json'
import createTemplates from './templates' import createTemplates from './templates'
import * as config from './runtime/ui.config' import type * as config from './runtime/ui.config'
import type { DeepPartial, Strategy } from './runtime/types' import type { DeepPartial, Strategy } from './runtime/types'
import installTailwind from './tailwind' import installTailwind from './tailwind'
@@ -62,7 +62,7 @@ export default defineNuxtModule<ModuleOptions>({
safelistColors: ['primary'], safelistColors: ['primary'],
disableGlobalStyles: false disableGlobalStyles: false
}, },
async setup (options, nuxt) { async setup(options, nuxt) {
const { resolve } = createResolver(import.meta.url) const { resolve } = createResolver(import.meta.url)
// Transpile runtime // Transpile runtime

View File

@@ -140,11 +140,11 @@ import { table } from '#ui/ui.config'
const config = mergeConfig<typeof table>(appConfig.ui.strategy, appConfig.ui.table, table) const config = mergeConfig<typeof table>(appConfig.ui.strategy, appConfig.ui.table, table)
function defaultComparator<T> (a: T, z: T): boolean { function defaultComparator<T>(a: T, z: T): boolean {
return JSON.stringify(a) === JSON.stringify(z) return JSON.stringify(a) === JSON.stringify(z)
} }
function defaultSort (a: any, b: any, direction: 'asc' | 'desc') { function defaultSort(a: any, b: any, direction: 'asc' | 'desc') {
if (a === b) { if (a === b) {
return 0 return 0
} }
@@ -239,10 +239,10 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'update:sort'], emits: ['update:modelValue', 'update:sort'],
setup (props, { emit, attrs: $attrs }) { setup(props, { emit, attrs: $attrs }) {
const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))
const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map((key) => ({ key, label: upperFirst(key), sortable: false, class: undefined, sort: defaultSort }) as TableColumn)) const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map(key => ({ key, label: upperFirst(key), sortable: false, class: undefined, sort: defaultSort }) as TableColumn))
const sort = useVModel(props, 'sort', emit, { passive: true, defaultValue: defu({}, props.sort, { column: null, direction: 'asc' }) }) const sort = useVModel(props, 'sort', emit, { passive: true, defaultValue: defu({}, props.sort, { column: null, direction: 'asc' }) })
@@ -261,17 +261,17 @@ export default defineComponent({
const aValue = get(a, column) const aValue = get(a, column)
const bValue = get(b, column) const bValue = get(b, column)
const sort = columns.value.find((col) => col.key === column)?.sort ?? defaultSort const sort = columns.value.find(col => col.key === column)?.sort ?? defaultSort
return sort(aValue, bValue, direction) return sort(aValue, bValue, direction)
}) })
}) })
const selected = computed({ const selected = computed({
get () { get() {
return props.modelValue return props.modelValue
}, },
set (value) { set(value) {
emit('update:modelValue', value) emit('update:modelValue', value)
} }
}) })
@@ -288,7 +288,7 @@ export default defineComponent({
return { ...ui.value.default.loadingState, ...props.loadingState } return { ...ui.value.default.loadingState, ...props.loadingState }
}) })
function compare (a: any, z: any) { function compare(a: any, z: any) {
if (typeof props.by === 'string') { if (typeof props.by === 'string') {
const accesorFn = accessor(props.by) const accesorFn = accessor(props.by)
return accesorFn(a) === accesorFn(z) return accesorFn(a) === accesorFn(z)
@@ -296,19 +296,19 @@ export default defineComponent({
return props.by(a, z) return props.by(a, z)
} }
function accessor <T extends Record<string, any>> (key: string) { function accessor<T extends Record<string, any>>(key: string) {
return (obj: T) => get(obj, key) return (obj: T) => get(obj, key)
} }
function isSelected (row: TableRow) { function isSelected(row: TableRow) {
if (!props.modelValue) { if (!props.modelValue) {
return false return false
} }
return selected.value.some((item) => compare(toRaw(item), toRaw(row))) return selected.value.some(item => compare(toRaw(item), toRaw(row)))
} }
function onSort (column: { key: string, direction?: 'asc' | 'desc' }) { function onSort(column: { key: string, direction?: 'asc' | 'desc' }) {
if (sort.value.column === column.key) { if (sort.value.column === column.key) {
const direction = !column.direction || column.direction === 'asc' ? 'desc' : 'asc' const direction = !column.direction || column.direction === 'asc' ? 'desc' : 'asc'
@@ -322,7 +322,7 @@ export default defineComponent({
} }
} }
function onSelect (row: TableRow) { function onSelect(row: TableRow) {
if (!$attrs.onSelect) { if (!$attrs.onSelect) {
return return
} }
@@ -331,7 +331,7 @@ export default defineComponent({
$attrs.onSelect(row) $attrs.onSelect(row)
} }
function selectAllRows () { function selectAllRows() {
// Create a new array to ensure reactivity // Create a new array to ensure reactivity
const newSelected = [...selected.value] const newSelected = [...selected.value]
@@ -346,7 +346,7 @@ export default defineComponent({
selected.value = newSelected selected.value = newSelected
} }
function onChange (checked: boolean) { function onChange(checked: boolean) {
if (checked) { if (checked) {
selectAllRows() selectAllRows()
} else { } else {
@@ -354,28 +354,28 @@ export default defineComponent({
} }
} }
function onChangeCheckbox (checked: boolean, row: TableRow) { function onChangeCheckbox(checked: boolean, row: TableRow) {
if (checked) { if (checked) {
selected.value.push(row) selected.value.push(row)
} else { } else {
const index = selected.value.findIndex((item) => compare(item, row)) const index = selected.value.findIndex(item => compare(item, row))
selected.value.splice(index, 1) selected.value.splice(index, 1)
} }
} }
function getRowData (row: TableRow, rowKey: string | string[], defaultValue: any = '') { function getRowData(row: TableRow, rowKey: string | string[], defaultValue: any = '') {
return get(row, rowKey, defaultValue) return get(row, rowKey, defaultValue)
} }
function toggleOpened (index: number) { function toggleOpened(index: number) {
if (openedRows.value.includes(index)) { if (openedRows.value.includes(index)) {
openedRows.value = openedRows.value.filter((i) => i !== index) openedRows.value = openedRows.value.filter(i => i !== index)
} else { } else {
openedRows.value.push(index) openedRows.value.push(index)
} }
} }
function getAriaSort (column: TableColumn): AriaAttributes['aria-sort'] { function getAriaSort(column: TableColumn): AriaAttributes['aria-sort'] {
if (!column.sortable) { if (!column.sortable) {
return undefined return undefined
} }
@@ -423,4 +423,4 @@ export default defineComponent({
} }
} }
}) })
</script> </script>

View File

@@ -127,7 +127,7 @@ export default defineComponent({
} }
}, },
emits: ['open'], emits: ['open'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('accordion', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('accordion', toRef(props, 'ui'), config, toRef(props, 'class'))
const uiButton = computed<typeof configButton>(() => configButton) const uiButton = computed<typeof configButton>(() => configButton)
@@ -146,7 +146,7 @@ export default defineComponent({
} }
}, { immediate: true }) }, { immediate: true })
function closeOthers (currentIndex: number, e: Event) { function closeOthers(currentIndex: number, e: Event) {
if (!props.items[currentIndex].closeOthers && props.multiple) { if (!props.items[currentIndex].closeOthers && props.multiple) {
return return
} }
@@ -158,27 +158,29 @@ export default defineComponent({
}) })
} }
function onEnter (_el: Element, done: () => void) { function onEnter(_el: Element, done: () => void) {
const el = _el as HTMLElement const el = _el as HTMLElement
el.style.height = '0' el.style.height = '0'
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
el.offsetHeight // Trigger a reflow, flushing the CSS changes el.offsetHeight // Trigger a reflow, flushing the CSS changes
el.style.height = el.scrollHeight + 'px' el.style.height = el.scrollHeight + 'px'
el.addEventListener('transitionend', done, { once: true }) el.addEventListener('transitionend', done, { once: true })
} }
function onBeforeLeave (_el: Element) { function onBeforeLeave(_el: Element) {
const el = _el as HTMLElement const el = _el as HTMLElement
el.style.height = el.scrollHeight + 'px' el.style.height = el.scrollHeight + 'px'
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
el.offsetHeight // Trigger a reflow, flushing the CSS changes el.offsetHeight // Trigger a reflow, flushing the CSS changes
} }
function onAfterEnter (_el: Element) { function onAfterEnter(_el: Element) {
const el = _el as HTMLElement const el = _el as HTMLElement
el.style.height = 'auto' el.style.height = 'auto'
} }
function onLeave (_el: Element, done: () => void) { function onLeave(_el: Element, done: () => void) {
const el = _el as HTMLElement const el = _el as HTMLElement
el.style.height = '0' el.style.height = '0'

View File

@@ -90,14 +90,14 @@ export default defineComponent({
color: { color: {
type: String as PropType<AlertColor>, type: String as PropType<AlertColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<AlertVariant>, type: String as PropType<AlertVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -114,7 +114,7 @@ export default defineComponent({
} }
}, },
emits: ['close'], emits: ['close'],
setup (props) { setup(props) {
const { ui, attrs } = useUI('alert', toRef(props, 'ui'), config) const { ui, attrs } = useUI('alert', toRef(props, 'ui'), config)
const alertClass = computed(() => { const alertClass = computed(() => {
@@ -129,7 +129,7 @@ export default defineComponent({
), props.class) ), props.class)
}) })
function onAction (action: AlertAction) { function onAction(action: AlertAction) {
if (action.click) { if (action.click) {
action.click() action.click()
} }

View File

@@ -63,21 +63,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<AvatarSize>, type: String as PropType<AvatarSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
chipColor: { chipColor: {
type: String as PropType<AvatarChipColor>, type: String as PropType<AvatarChipColor>,
default: () => config.default.chipColor, default: () => config.default.chipColor,
validator (value: string) { validator(value: string) {
return ['gray', ...appConfig.ui.colors].includes(value) return ['gray', ...appConfig.ui.colors].includes(value)
} }
}, },
chipPosition: { chipPosition: {
type: String as PropType<AvatarChipPosition>, type: String as PropType<AvatarChipPosition>,
default: () => config.default.chipPosition, default: () => config.default.chipPosition,
validator (value: string) { validator(value: string) {
return Object.keys(config.chip.position).includes(value) return Object.keys(config.chip.position).includes(value)
} }
}, },
@@ -98,7 +98,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('avatar', toRef(props, 'ui'), config) const { ui, attrs } = useUI('avatar', toRef(props, 'ui'), config)
const url = computed(() => { const url = computed(() => {
@@ -152,7 +152,7 @@ export default defineComponent({
} }
}) })
function onError () { function onError() {
error.value = true error.value = true
} }

View File

@@ -1,10 +1,10 @@
import { h, cloneVNode, computed, toRef, defineComponent } from 'vue' import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge' import { twMerge, twJoin } from 'tailwind-merge'
import UAvatar from './Avatar.vue'
import { useUI } from '../../composables/useUI' import { useUI } from '../../composables/useUI'
import { mergeConfig, getSlotsChildren } from '../../utils' import { mergeConfig, getSlotsChildren } from '../../utils'
import type { AvatarSize, Strategy } from '../../types/index' import type { AvatarSize, Strategy } from '../../types/index'
import UAvatar from './Avatar.vue'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { avatar, avatarGroup } from '#ui/ui.config' import { avatar, avatarGroup } from '#ui/ui.config'
@@ -19,7 +19,7 @@ export default defineComponent({
size: { size: {
type: String as PropType<AvatarSize>, type: String as PropType<AvatarSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(avatarConfig.size).includes(value) return Object.keys(avatarConfig.size).includes(value)
} }
}, },
@@ -36,12 +36,12 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props, { slots }) { setup(props, { slots }) {
const { ui, attrs } = useUI('avatarGroup', toRef(props, 'ui'), avatarGroupConfig, toRef(props, 'class')) const { ui, attrs } = useUI('avatarGroup', toRef(props, 'ui'), avatarGroupConfig, toRef(props, 'class'))
const children = computed(() => getSlotsChildren(slots)) const children = computed(() => getSlotsChildren(slots))
const max = computed(() => typeof props.max === 'string' ? parseInt(props.max, 10) : props.max) const max = computed(() => typeof props.max === 'string' ? Number.parseInt(props.max, 10) : props.max)
const clones = computed(() => children.value.map((node, index) => { const clones = computed(() => children.value.map((node, index) => {
const vProps: any = {} const vProps: any = {}

View File

@@ -24,21 +24,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<BadgeSize>, type: String as PropType<BadgeSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<BadgeColor>, type: String as PropType<BadgeColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<BadgeVariant>, type: String as PropType<BadgeVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -58,7 +58,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('badge', toRef(props, 'ui'), config) const { ui, attrs } = useUI('badge', toRef(props, 'ui'), config)
const { size, rounded } = useInjectButtonGroup({ ui, props }) const { size, rounded } = useInjectButtonGroup({ ui, props })

View File

@@ -67,21 +67,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<ButtonSize>, type: String as PropType<ButtonSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<ButtonColor>, type: String as PropType<ButtonColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<ButtonVariant>, type: String as PropType<ButtonVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -129,7 +129,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props, { slots }) { setup(props, { slots }) {
const { ui, attrs } = useUI('button', toRef(props, 'ui'), config) const { ui, attrs } = useUI('button', toRef(props, 'ui'), config)
const { size, rounded } = useInjectButtonGroup({ ui, props }) const { size, rounded } = useInjectButtonGroup({ ui, props })

View File

@@ -19,14 +19,14 @@ export default defineComponent({
size: { size: {
type: String as PropType<ButtonSize>, type: String as PropType<ButtonSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(buttonConfig.size).includes(value) return Object.keys(buttonConfig.size).includes(value)
} }
}, },
orientation: { orientation: {
type: String as PropType<'horizontal' | 'vertical'>, type: String as PropType<'horizontal' | 'vertical'>,
default: 'horizontal', default: 'horizontal',
validator (value: string) { validator(value: string) {
return ['horizontal', 'vertical'].includes(value) return ['horizontal', 'vertical'].includes(value)
} }
}, },
@@ -39,7 +39,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props, { slots }) { setup(props, { slots }) {
const { ui, attrs } = useUI('buttonGroup', toRef(props, 'ui'), buttonGroupConfig) const { ui, attrs } = useUI('buttonGroup', toRef(props, 'ui'), buttonGroupConfig)
const children = computed(() => getSlotsChildren(slots)) const children = computed(() => getSlotsChildren(slots))

View File

@@ -59,12 +59,12 @@
import { ref, toRef, computed, defineComponent } from 'vue' import { ref, toRef, computed, defineComponent } from 'vue'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { useScroll, useResizeObserver, useElementSize } from '@vueuse/core'
import { mergeConfig } from '../../utils' import { mergeConfig } from '../../utils'
import UButton from '../elements/Button.vue' import UButton from '../elements/Button.vue'
import type { Strategy, Button, DeepPartial } from '../../types/index' import type { Strategy, Button, DeepPartial } from '../../types/index'
import { useUI } from '../../composables/useUI' import { useUI } from '../../composables/useUI'
import { useCarouselScroll } from '../../composables/useCarouselScroll' import { useCarouselScroll } from '../../composables/useCarouselScroll'
import { useScroll, useResizeObserver, useElementSize } from '@vueuse/core'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { carousel } from '#ui/ui.config' import { carousel } from '#ui/ui.config'
@@ -110,7 +110,7 @@ export default defineComponent({
default: undefined default: undefined
} }
}, },
setup (props, { expose }) { setup(props, { expose }) {
const { ui, attrs } = useUI('carousel', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('carousel', toRef(props, 'ui'), config, toRef(props, 'class'))
const carouselRef = ref<HTMLElement>() const carouselRef = ref<HTMLElement>()
@@ -157,15 +157,15 @@ export default defineComponent({
const isFirst = computed(() => currentPage.value <= 1) const isFirst = computed(() => currentPage.value <= 1)
const isLast = computed(() => currentPage.value === pages.value) const isLast = computed(() => currentPage.value === pages.value)
function onClickNext () { function onClickNext() {
x.value += isRtl.value ? -itemWidth.value : itemWidth.value x.value += isRtl.value ? -itemWidth.value : itemWidth.value
} }
function onClickPrev () { function onClickPrev() {
x.value -= isRtl.value ? -itemWidth.value : itemWidth.value x.value -= isRtl.value ? -itemWidth.value : itemWidth.value
} }
function onClick (page: number) { function onClick(page: number) {
x.value = (page - 1) * itemWidth.value * (isRtl.value ? -1 : 1) x.value = (page - 1) * itemWidth.value * (isRtl.value ? -1 : 1)
} }

View File

@@ -29,21 +29,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<ChipSize>, type: String as PropType<ChipSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<ChipColor>, type: String as PropType<ChipColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return ['gray', ...appConfig.ui.colors].includes(value) return ['gray', ...appConfig.ui.colors].includes(value)
} }
}, },
position: { position: {
type: String as PropType<ChipPosition>, type: String as PropType<ChipPosition>,
default: () => config.default.position, default: () => config.default.position,
validator (value: string) { validator(value: string) {
return Object.keys(config.position).includes(value) return Object.keys(config.position).includes(value)
} }
}, },
@@ -68,7 +68,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('chip', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('chip', toRef(props, 'ui'), config, toRef(props, 'class'))
const chipClass = computed(() => { const chipClass = computed(() => {

View File

@@ -126,7 +126,7 @@ export default defineComponent({
} }
}, },
emits: ['update:open'], emits: ['update:open'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('dropdown', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('dropdown', toRef(props, 'ui'), config, toRef(props, 'class'))
const popper = computed<PopperOptions>(() => defu(props.mode === 'hover' ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper as PopperOptions)) const popper = computed<PopperOptions>(() => defu(props.mode === 'hover' ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper as PopperOptions))
@@ -182,7 +182,7 @@ export default defineComponent({
} }
}) })
function onTouchStart (event: TouchEvent) { function onTouchStart(event: TouchEvent) {
if (!event.cancelable || !menuApi.value || props.mode === 'click') { if (!event.cancelable || !menuApi.value || props.mode === 'click') {
return return
} }
@@ -194,7 +194,7 @@ export default defineComponent({
} }
} }
function onMouseEnter () { function onMouseEnter() {
if (props.mode !== 'hover' || !menuApi.value) { if (props.mode !== 'hover' || !menuApi.value) {
return return
} }
@@ -209,12 +209,14 @@ export default defineComponent({
return return
} }
openTimeout = openTimeout || setTimeout(() => { openTimeout = openTimeout || setTimeout(() => {
menuApi.value.openMenu && menuApi.value.openMenu() if (menuApi.value.openMenu) {
menuApi.value.openMenu()
}
openTimeout = null openTimeout = null
}, props.openDelay) }, props.openDelay)
} }
function onMouseLeave () { function onMouseLeave() {
if (props.mode !== 'hover' || !menuApi.value) { if (props.mode !== 'hover' || !menuApi.value) {
return return
} }
@@ -229,12 +231,14 @@ export default defineComponent({
return return
} }
closeTimeout = closeTimeout || setTimeout(() => { closeTimeout = closeTimeout || setTimeout(() => {
menuApi.value.closeMenu && menuApi.value.closeMenu() if (menuApi.value.closeMenu) {
menuApi.value.closeMenu()
}
closeTimeout = null closeTimeout = null
}, props.closeDelay) }, props.closeDelay)
} }
function onClick (e, item, { href, navigate, close, isExternal }) { function onClick(e, item, { href, navigate, close, isExternal }) {
if (item.click) { if (item.click) {
item.click(e) item.click(e)
} }

View File

@@ -27,7 +27,7 @@ export default defineComponent({
size: { size: {
type: String as PropType<KbdSize>, type: String as PropType<KbdSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
@@ -40,7 +40,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('kbd', toRef(props, 'ui'), config) const { ui, attrs } = useUI('kbd', toRef(props, 'ui'), config)
const kbdClass = computed(() => { const kbdClass = computed(() => {

View File

@@ -73,8 +73,8 @@ export default defineComponent({
default: undefined default: undefined
} }
}, },
setup (props) { setup(props) {
function resolveLinkClass (route, $route, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }) { function resolveLinkClass(route, $route, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }) {
if (props.exactQuery && !isEqual(route.query, $route.query)) { if (props.exactQuery && !isEqual(route.query, $route.query)) {
return props.inactiveClass return props.inactiveClass
} }

View File

@@ -47,8 +47,8 @@ export default defineComponent({
}, },
inheritAttrs: false, inheritAttrs: false,
slots: Object as SlotsType<{ slots: Object as SlotsType<{
indicator?: { percent: number, value: number }, indicator?: { percent: number, value: number }
label?: { percent: number, value: number }, label?: { percent: number, value: number }
}>, }>,
props: { props: {
value: { value: {
@@ -74,14 +74,14 @@ export default defineComponent({
size: { size: {
type: String as PropType<MeterSize>, type: String as PropType<MeterSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.meter.size).includes(value) return Object.keys(config.meter.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<MeterColor>, type: String as PropType<MeterColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
@@ -98,10 +98,10 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('meter', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('meter', toRef(props, 'ui'), config, toRef(props, 'class'))
function clampPercent (value: number, min: number, max: number): number { function clampPercent(value: number, min: number, max: number): number {
if (min == max) { if (min == max) {
return value < min ? 0 : 100 return value < min ? 0 : 100
} }

View File

@@ -2,10 +2,10 @@ import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
import type { ComputedRef, VNode, SlotsType, PropType } from 'vue' import type { ComputedRef, VNode, SlotsType, PropType } from 'vue'
import { twJoin } from 'tailwind-merge' import { twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue' import UIcon from '../elements/Icon.vue'
import Meter from './Meter.vue'
import { useUI } from '../../composables/useUI' import { useUI } from '../../composables/useUI'
import { mergeConfig, getSlotsChildren } from '../../utils' import { mergeConfig, getSlotsChildren } from '../../utils'
import type { Strategy, MeterSize } from '../../types/index' import type { Strategy, MeterSize } from '../../types/index'
import type Meter from './Meter.vue'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { meter, meterGroup } from '#ui/ui.config' import { meter, meterGroup } from '#ui/ui.config'
@@ -19,8 +19,8 @@ export default defineComponent({
}, },
inheritAttrs: false, inheritAttrs: false,
slots: Object as SlotsType<{ slots: Object as SlotsType<{
default?: typeof Meter[], default?: typeof Meter[]
indicator?: { percent: number }, indicator?: { percent: number }
}>, }>,
props: { props: {
min: { min: {
@@ -34,7 +34,7 @@ export default defineComponent({
size: { size: {
type: String as PropType<MeterSize>, type: String as PropType<MeterSize>,
default: () => meterConfig.default.size, default: () => meterConfig.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(meterConfig.meter.bar.size).includes(value) return Object.keys(meterConfig.meter.bar.size).includes(value)
} }
}, },
@@ -55,7 +55,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props, { slots }) { setup(props, { slots }) {
const { ui, attrs } = useUI('meterGroup', toRef(props, 'ui'), meterGroupConfig) const { ui, attrs } = useUI('meterGroup', toRef(props, 'ui'), meterGroupConfig)
const { ui: uiMeter } = useUI('meter', undefined, meterConfig) const { ui: uiMeter } = useUI('meter', undefined, meterConfig)
@@ -72,7 +72,7 @@ export default defineComponent({
const rounded = computed(() => ui.value.orientation[ui.value.rounded]) const rounded = computed(() => ui.value.orientation[ui.value.rounded])
function clampPercent (value: number, min: number, max: number): number { function clampPercent(value: number, min: number, max: number): number {
if (min == max) { if (min == max) {
return value < min ? 0 : 100 return value < min ? 0 : 100
} }
@@ -138,9 +138,9 @@ export default defineComponent({
const clone = cloneVNode(node, vProps) const clone = cloneVNode(node, vProps)
// @ts-expect-error // @ts-expect-error
delete(clone.children?.label) delete (clone.children?.label)
delete(clone.props?.indicator) delete (clone.props?.indicator)
delete(clone.props?.label) delete (clone.props?.label)
return clone return clone
})) }))
@@ -196,7 +196,7 @@ export default defineComponent({
return h('li', { class: labelClass.value }, [ return h('li', { class: labelClass.value }, [
h(UIcon, { name: clones.value[key]?.props.icon ?? props.icon }), h(UIcon, { name: clones.value[key]?.props.icon ?? props.icon }),
`${label} (${ Math.round(percents.value[key]) }%)` `${label} (${Math.round(percents.value[key])}%)`
]) ])
})) }))

View File

@@ -58,21 +58,21 @@ export default defineComponent({
animation: { animation: {
type: String as PropType<ProgressAnimation>, type: String as PropType<ProgressAnimation>,
default: () => config.default.animation, default: () => config.default.animation,
validator (value: string) { validator(value: string) {
return Object.keys(config.animation).includes(value) return Object.keys(config.animation).includes(value)
} }
}, },
size: { size: {
type: String as PropType<ProgressSize>, type: String as PropType<ProgressSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.progress.size).includes(value) return Object.keys(config.progress.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<ProgressColor>, type: String as PropType<ProgressColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
@@ -85,7 +85,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('progress', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('progress', toRef(props, 'ui'), config, toRef(props, 'class'))
const indicatorContainerClass = computed(() => { const indicatorContainerClass = computed(() => {
@@ -154,15 +154,15 @@ export default defineComponent({
) )
}) })
function isActive (index: number) { function isActive(index: number) {
return index === Number(props.value) return index === Number(props.value)
} }
function isFirst (index: number) { function isFirst(index: number) {
return index === 0 return index === 0
} }
function stepClasses (index: string | number) { function stepClasses(index: string | number) {
index = Number(index) index = Number(index)
const classes = [stepClass.value] const classes = [stepClass.value]
@@ -199,9 +199,9 @@ export default defineComponent({
} }
switch (true) { switch (true) {
case props.value < 0: return 0 case props.value < 0: return 0
case props.value > (realMax.value as number): return 100 case props.value > (realMax.value as number): return 100
default: return (props.value / (realMax.value as number)) * 100 default: return (props.value / (realMax.value as number)) * 100
} }
}) })
@@ -421,4 +421,5 @@ progress:indeterminate {
width: 90%; width: 90%;
margin-left: 5% margin-left: 5%
} }
}</style> }
</style>

View File

@@ -40,7 +40,7 @@ import type { DeepPartial, Strategy } from '../../types/index'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { checkbox } from '#ui/ui.config' import { checkbox } from '#ui/ui.config'
import colors from '#ui-colors' import type colors from '#ui-colors'
import { useId } from '#app' import { useId } from '#app'
const config = mergeConfig<typeof checkbox>(appConfig.ui.strategy, appConfig.ui.checkbox, checkbox) const config = mergeConfig<typeof checkbox>(appConfig.ui.strategy, appConfig.ui.checkbox, checkbox)
@@ -87,7 +87,7 @@ export default defineComponent({
color: { color: {
type: String as PropType<typeof colors[number]>, type: String as PropType<typeof colors[number]>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
@@ -105,17 +105,17 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormChange, color, name, inputId: _inputId } = useFormGroup(props) const { emitFormChange, color, name, inputId: _inputId } = useFormGroup(props)
const inputId = _inputId.value ?? useId() const inputId = _inputId.value ?? useId()
const toggle = computed({ const toggle = computed({
get () { get() {
return props.modelValue return props.modelValue
}, },
set (value) { set(value) {
emit('update:modelValue', value) emit('update:modelValue', value)
} }
}) })

View File

@@ -18,7 +18,7 @@ import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEve
import { useId } from '#imports' import { useId } from '#imports'
class FormException extends Error { class FormException extends Error {
constructor (message: string) { constructor(message: string) {
super(message) super(message)
this.message = message this.message = message
Object.setPrototypeOf(this, FormException.prototype) Object.setPrototypeOf(this, FormException.prototype)
@@ -29,14 +29,14 @@ export default defineComponent({
props: { props: {
schema: { schema: {
type: [Object, Function] as type: [Object, Function] as
| PropType<ZodSchema> | PropType<ZodSchema>
| PropType<YupObjectSchema<any>> | PropType<YupObjectSchema<any>>
| PropType<JoiSchema> | PropType<JoiSchema>
| PropType<ValibotSchema30 | ValibotSchemaAsync30> | PropType<ValibotSchema30 | ValibotSchemaAsync30>
| PropType<ValibotSchema31 | ValibotSchemaAsync31> | PropType<ValibotSchema31 | ValibotSchemaAsync31>
| PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>> | PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>>
| PropType<ValibotSchema | ValibotSchemaAsync> | PropType<ValibotSchema | ValibotSchemaAsync>
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>, | PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>,
default: undefined default: undefined
}, },
state: { state: {
@@ -45,8 +45,8 @@ export default defineComponent({
}, },
validate: { validate: {
type: Function as type: Function as
| PropType<(state: any) => Promise<FormError[]>> | PropType<(state: any) => Promise<FormError[]>>
| PropType<(state: any) => FormError[]>, | PropType<(state: any) => FormError[]>,
default: () => [] default: () => []
}, },
validateOn: { validateOn: {
@@ -55,7 +55,7 @@ export default defineComponent({
} }
}, },
emits: ['submit', 'error'], emits: ['submit', 'error'],
setup (props, { expose, emit }) { setup(props, { expose, emit }) {
const formId = useId() const formId = useId()
const bus = useEventBus<FormEvent>(`form-${formId}`) const bus = useEventBus<FormEvent>(`form-${formId}`)
@@ -77,7 +77,7 @@ export default defineComponent({
const inputs = ref({}) const inputs = ref({})
provide('form-inputs', inputs) provide('form-inputs', inputs)
async function getErrors (): Promise<FormError[]> { async function getErrors(): Promise<FormError[]> {
let errs = await props.validate(props.state) let errs = await props.validate(props.state)
if (props.schema) { if (props.schema) {
@@ -99,7 +99,7 @@ export default defineComponent({
return errs return errs
} }
async function validate (path?: string | string[], opts: { silent?: boolean } = { silent: false }) { async function validate(path?: string | string[], opts: { silent?: boolean } = { silent: false }) {
let paths = path let paths = path
if (path && !Array.isArray(path)) { if (path && !Array.isArray(path)) {
@@ -108,10 +108,10 @@ export default defineComponent({
if (paths) { if (paths) {
const otherErrors = errors.value.filter( const otherErrors = errors.value.filter(
(error) => !paths.includes(error.path) error => !paths.includes(error.path)
) )
const pathErrors = (await getErrors()).filter( const pathErrors = (await getErrors()).filter(
(error) => paths.includes(error.path) error => paths.includes(error.path)
) )
errors.value = otherErrors.concat(pathErrors) errors.value = otherErrors.concat(pathErrors)
} else { } else {
@@ -129,7 +129,7 @@ export default defineComponent({
return props.state return props.state
} }
async function onSubmit (payload: Event) { async function onSubmit(payload: Event) {
const event = payload as FormSubmitEvent<any> const event = payload as FormSubmitEvent<any>
try { try {
if (props.validateOn?.includes('submit')) { if (props.validateOn?.includes('submit')) {
@@ -144,7 +144,7 @@ export default defineComponent({
const errorEvent: FormErrorEvent = { const errorEvent: FormErrorEvent = {
...event, ...event,
errors: errors.value.map((err) => ({ errors: errors.value.map(err => ({
...err, ...err,
id: inputs.value[err.path] id: inputs.value[err.path]
})) }))
@@ -156,27 +156,27 @@ export default defineComponent({
expose({ expose({
validate, validate,
errors, errors,
setErrors (errs: FormError[], path?: string) { setErrors(errs: FormError[], path?: string) {
if (path) { if (path) {
errors.value = errors.value.filter( errors.value = errors.value.filter(
(error) => error.path !== path error => error.path !== path
).concat(errs) ).concat(errs)
} else { } else {
errors.value = errs errors.value = errs
} }
}, },
async submit () { async submit() {
await onSubmit(new Event('submit')) await onSubmit(new Event('submit'))
}, },
getErrors (path?: string) { getErrors(path?: string) {
if (path) { if (path) {
return errors.value.filter((err) => err.path === path) return errors.value.filter(err => err.path === path)
} }
return errors.value return errors.value
}, },
clear (path?: string) { clear(path?: string) {
if (path) { if (path) {
errors.value = errors.value.filter((err) => err.path !== path) errors.value = errors.value.filter(err => err.path !== path)
} else { } else {
errors.value = [] errors.value = []
} }
@@ -190,24 +190,24 @@ export default defineComponent({
} }
}) })
function isYupSchema (schema: any): schema is YupObjectSchema<any> { function isYupSchema(schema: any): schema is YupObjectSchema<any> {
return schema.validate && schema.__isYupSchema__ return schema.validate && schema.__isYupSchema__
} }
function isYupError (error: any): error is YupError { function isYupError(error: any): error is YupError {
return error.inner !== undefined return error.inner !== undefined
} }
function isSuperStructSchema (schema: any): schema is Struct<any, any> { function isSuperStructSchema(schema: any): schema is Struct<any, any> {
return ( return (
'schema' in schema && 'schema' in schema
typeof schema.coercer === 'function' && && typeof schema.coercer === 'function'
typeof schema.validator === 'function' && && typeof schema.validator === 'function'
typeof schema.refiner === 'function' && typeof schema.refiner === 'function'
) )
} }
async function getYupErrors ( async function getYupErrors(
state: any, state: any,
schema: YupObjectSchema<any> schema: YupObjectSchema<any>
): Promise<FormError[]> { ): Promise<FormError[]> {
@@ -216,7 +216,7 @@ async function getYupErrors (
return [] return []
} catch (error) { } catch (error) {
if (isYupError(error)) { if (isYupError(error)) {
return error.inner.map((issue) => ({ return error.inner.map(issue => ({
path: issue.path ?? '', path: issue.path ?? '',
message: issue.message message: issue.message
})) }))
@@ -226,15 +226,15 @@ async function getYupErrors (
} }
} }
function isZodSchema (schema: any): schema is ZodSchema { function isZodSchema(schema: any): schema is ZodSchema {
return schema.parse !== undefined return schema.parse !== undefined
} }
async function getSuperStructErrors (state: any, schema: Struct<any, any>): Promise<FormError[]> { async function getSuperStructErrors(state: any, schema: Struct<any, any>): Promise<FormError[]> {
const [err] = schema.validate(state) const [err] = schema.validate(state)
if (err) { if (err) {
const errors = err.failures() const errors = err.failures()
return errors.map((error) => ({ return errors.map(error => ({
message: error.message, message: error.message,
path: error.path.join('.') path: error.path.join('.')
})) }))
@@ -242,13 +242,13 @@ async function getSuperStructErrors (state: any, schema: Struct<any, any>): Prom
return [] return []
} }
async function getZodErrors ( async function getZodErrors(
state: any, state: any,
schema: ZodSchema schema: ZodSchema
): Promise<FormError[]> { ): Promise<FormError[]> {
const result = await schema.safeParseAsync(state) const result = await schema.safeParseAsync(state)
if (result.success === false) { if (result.success === false) {
return result.error.issues.map((issue) => ({ return result.error.issues.map(issue => ({
path: issue.path.join('.'), path: issue.path.join('.'),
message: issue.message message: issue.message
})) }))
@@ -256,15 +256,15 @@ async function getZodErrors (
return [] return []
} }
function isJoiSchema (schema: any): schema is JoiSchema { function isJoiSchema(schema: any): schema is JoiSchema {
return schema.validateAsync !== undefined && schema.id !== undefined return schema.validateAsync !== undefined && schema.id !== undefined
} }
function isJoiError (error: any): error is JoiError { function isJoiError(error: any): error is JoiError {
return error.isJoi === true return error.isJoi === true
} }
async function getJoiErrors ( async function getJoiErrors(
state: any, state: any,
schema: JoiSchema schema: JoiSchema
): Promise<FormError[]> { ): Promise<FormError[]> {
@@ -273,7 +273,7 @@ async function getJoiErrors (
return [] return []
} catch (error) { } catch (error) {
if (isJoiError(error)) { if (isJoiError(error)) {
return error.details.map((detail) => ({ return error.details.map(detail => ({
path: detail.path.join('.'), path: detail.path.join('.'),
message: detail.message message: detail.message
})) }))
@@ -283,19 +283,18 @@ async function getJoiErrors (
} }
} }
function isValibotSchema(schema: any): schema is ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
function isValibotSchema (schema: any): schema is ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
return '_parse' in schema || '_run' in schema || (typeof schema === 'function' && 'schema' in schema) return '_parse' in schema || '_run' in schema || (typeof schema === 'function' && 'schema' in schema)
} }
async function getValibotError ( async function getValibotError(
state: any, state: any,
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
): Promise<FormError[]> { ): Promise<FormError[]> {
const result = await ('_parse' in schema ? schema._parse(state) : '_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state)) const result = await ('_parse' in schema ? schema._parse(state) : '_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state))
return result.issues?.map((issue) => ({ return result.issues?.map(issue => ({
// We know that the key for a form schema is always a string or a number // We know that the key for a form schema is always a string or a number
path: issue.path?.map((item) => item.key).join('.') || '', path: issue.path?.map(item => item.key).join('.') || '',
message: issue.message message: issue.message
})) || [] })) || []
} }

View File

@@ -62,7 +62,7 @@ export default defineComponent({
size: { size: {
type: String as PropType<FormGroupSize>, type: String as PropType<FormGroupSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
@@ -103,7 +103,7 @@ export default defineComponent({
default: false default: false
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('formGroup', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('formGroup', toRef(props, 'ui'), config, toRef(props, 'class'))
const formErrors = inject<Ref<FormError[]> | null>('form-errors', null) const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)
@@ -111,7 +111,7 @@ export default defineComponent({
const error = computed(() => { const error = computed(() => {
return (props.error && typeof props.error === 'string') || typeof props.error === 'boolean' return (props.error && typeof props.error === 'string') || typeof props.error === 'boolean'
? props.error ? props.error
: formErrors?.value?.find((error) => error.path === props.name)?.message : formErrors?.value?.find(error => error.path === props.name)?.message
}) })
const size = computed(() => ui.value.size[props.size ?? config.default.size]) const size = computed(() => ui.value.size[props.size ?? config.default.size])

View File

@@ -34,8 +34,8 @@
import { ref, computed, toRef, onMounted, defineComponent } from 'vue' import { ref, computed, toRef, onMounted, defineComponent } from 'vue'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge' import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
import { defu } from 'defu' import { defu } from 'defu'
import UIcon from '../elements/Icon.vue'
import { useUI } from '../../composables/useUI' import { useUI } from '../../composables/useUI'
import { useFormGroup } from '../../composables/useFormGroup' import { useFormGroup } from '../../composables/useFormGroup'
import { mergeConfig, looseToNumber } from '../../utils' import { mergeConfig, looseToNumber } from '../../utils'
@@ -124,21 +124,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<InputSize>, type: String as PropType<InputSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<InputColor>, type: String as PropType<InputColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<InputVariant>, type: String as PropType<InputVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -163,7 +163,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'blur', 'change'], emits: ['update:modelValue', 'blur', 'change'],
setup (props, { emit, slots }) { setup(props, { emit, slots }) {
const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class'))
const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props }) const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props })
@@ -184,7 +184,6 @@ export default defineComponent({
// Custom function to handle the v-model properties // Custom function to handle the v-model properties
const updateInput = (value: string) => { const updateInput = (value: string) => {
if (modelModifiers.value.trim) { if (modelModifiers.value.trim) {
value = value.trim() value = value.trim()
} }

View File

@@ -212,21 +212,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<InputSize>, type: String as PropType<InputSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<InputColor>, type: String as PropType<InputColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<InputVariant>, type: String as PropType<InputVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -279,7 +279,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'], emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],
setup (props, { emit, slots }) { setup(props, { emit, slots }) {
const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class'))
const { ui: uiMenu } = useUI('inputMenu', toRef(props, 'uiMenu'), configMenu) const { ui: uiMenu } = useUI('inputMenu', toRef(props, 'uiMenu'), configMenu)
@@ -294,10 +294,10 @@ export default defineComponent({
const internalQuery = ref('') const internalQuery = ref('')
const query = computed({ const query = computed({
get () { get() {
return props.query ?? internalQuery.value return props.query ?? internalQuery.value
}, },
set (value) { set(value) {
internalQuery.value = value internalQuery.value = value
emit('update:query', value) emit('update:query', value)
} }
@@ -401,7 +401,7 @@ export default defineComponent({
lazy: props.searchLazy lazy: props.searchLazy
}) })
function escapeRegExp (string: string) { function escapeRegExp(string: string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
} }
@@ -434,7 +434,7 @@ export default defineComponent({
} }
}) })
function onUpdate (value: any) { function onUpdate(value: any) {
query.value = '' query.value = ''
emit('update:modelValue', value) emit('update:modelValue', value)
emit('change', value) emit('change', value)
@@ -442,7 +442,7 @@ export default defineComponent({
emitFormChange() emitFormChange()
} }
function onQueryChange (event: any) { function onQueryChange(event: any) {
query.value = event.target.value query.value = event.target.value
} }

View File

@@ -39,7 +39,7 @@ import type { DeepPartial, Strategy } from '../../types/index'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { radio } from '#ui/ui.config' import { radio } from '#ui/ui.config'
import colors from '#ui-colors' import type colors from '#ui-colors'
import { useId } from '#imports' import { useId } from '#imports'
const config = mergeConfig<typeof radio>(appConfig.ui.strategy, appConfig.ui.radio, radio) const config = mergeConfig<typeof radio>(appConfig.ui.strategy, appConfig.ui.radio, radio)
@@ -82,7 +82,7 @@ export default defineComponent({
color: { color: {
type: String as PropType<typeof colors[number]>, type: String as PropType<typeof colors[number]>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
@@ -100,7 +100,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('radio', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('radio', toRef(props, 'ui'), config, toRef(props, 'class'))
const inputId = props.id ?? useId() const inputId = props.id ?? useId()
@@ -109,10 +109,10 @@ export default defineComponent({
const { emitFormChange, color, name } = radioGroup ?? useFormGroup(props, config) const { emitFormChange, color, name } = radioGroup ?? useFormGroup(props, config)
const pick = computed({ const pick = computed({
get () { get() {
return props.modelValue return props.modelValue
}, },
set (value) { set(value) {
emit('update:modelValue', value) emit('update:modelValue', value)
if (!radioGroup) { if (!radioGroup) {
emitFormChange() emitFormChange()
@@ -120,7 +120,7 @@ export default defineComponent({
} }
}) })
function onChange (event: Event) { function onChange(event: Event) {
emit('change', (event.target as HTMLInputElement).value) emit('change', (event.target as HTMLInputElement).value)
} }

View File

@@ -30,17 +30,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import URadio from './Radio.vue'
import { computed, defineComponent, provide, toRef } from 'vue' import { computed, defineComponent, provide, toRef } from 'vue'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { useUI } from '../../composables/useUI' import { useUI } from '../../composables/useUI'
import { useFormGroup } from '../../composables/useFormGroup' import { useFormGroup } from '../../composables/useFormGroup'
import { mergeConfig, get } from '../../utils' import { mergeConfig, get } from '../../utils'
import type { DeepPartial, Strategy } from '../../types/index' import type { DeepPartial, Strategy } from '../../types/index'
import URadio from './Radio.vue'
// @ts-expect-error // @ts-expect-error
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { radioGroup, radio } from '#ui/ui.config' import { radioGroup, radio } from '#ui/ui.config'
import colors from '#ui-colors' import type colors from '#ui-colors'
const config = mergeConfig<typeof radioGroup>(appConfig.ui.strategy, appConfig.ui.radioGroup, radioGroup) const config = mergeConfig<typeof radioGroup>(appConfig.ui.strategy, appConfig.ui.radioGroup, radioGroup)
const configRadio = mergeConfig<typeof radio>(appConfig.ui.strategy, appConfig.ui.radio, radio) const configRadio = mergeConfig<typeof radio>(appConfig.ui.strategy, appConfig.ui.radio, radio)
@@ -82,7 +82,7 @@ export default defineComponent({
color: { color: {
type: String as PropType<typeof colors[number]>, type: String as PropType<typeof colors[number]>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
@@ -100,7 +100,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('radioGroup', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('radioGroup', toRef(props, 'ui'), config, toRef(props, 'class'))
const { ui: uiRadio } = useUI('radio', toRef(props, 'uiRadio'), configRadio) const { ui: uiRadio } = useUI('radio', toRef(props, 'uiRadio'), configRadio)
@@ -152,7 +152,7 @@ export default defineComponent({
uiRadio, uiRadio,
attrs, attrs,
normalizedOptions, normalizedOptions,
// eslint-disable-next-line vue/no-dupe-keys
onUpdate onUpdate
} }
} }

View File

@@ -67,14 +67,14 @@ export default defineComponent({
size: { size: {
type: String as PropType<RangeSize>, type: String as PropType<RangeSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<RangeColor>, type: String as PropType<RangeColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
@@ -92,16 +92,16 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('range', toRef(props, 'ui'), config) const { ui, attrs } = useUI('range', toRef(props, 'ui'), config)
const { emitFormChange, inputId, color, size, name } = useFormGroup(props, config) const { emitFormChange, inputId, color, size, name } = useFormGroup(props, config)
const value = computed({ const value = computed({
get () { get() {
return props.modelValue return props.modelValue
}, },
set (value) { set(value) {
emit('update:modelValue', value) emit('update:modelValue', value)
} }
}) })

View File

@@ -137,21 +137,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<SelectSize>, type: String as PropType<SelectSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<SelectColor>, type: String as PropType<SelectColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<SelectVariant>, type: String as PropType<SelectVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -180,7 +180,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit, slots }) { setup(props, { emit, slots }) {
const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class'))
const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props }) const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props })

View File

@@ -280,21 +280,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<SelectSize>, type: String as PropType<SelectSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<SelectColor>, type: String as PropType<SelectColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<SelectVariant>, type: String as PropType<SelectVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -335,7 +335,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'], emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],
setup (props, { emit, slots }) { setup(props, { emit, slots }) {
if (import.meta.dev && props.multiple && !Array.isArray(props.modelValue)) { if (import.meta.dev && props.multiple && !Array.isArray(props.modelValue)) {
console.warn(`[@nuxt/ui] The USelectMenu components needs to have a modelValue of type Array when using the multiple prop. Got '${typeof props.modelValue}' instead.`, props.modelValue) console.warn(`[@nuxt/ui] The USelectMenu components needs to have a modelValue of type Array when using the multiple prop. Got '${typeof props.modelValue}' instead.`, props.modelValue)
} }
@@ -354,10 +354,10 @@ export default defineComponent({
const internalQuery = ref('') const internalQuery = ref('')
const query = computed({ const query = computed({
get () { get() {
return props.query ?? internalQuery.value return props.query ?? internalQuery.value
}, },
set (value) { set(value) {
internalQuery.value = value internalQuery.value = value
emit('update:query', value) emit('update:query', value)
} }
@@ -485,7 +485,7 @@ export default defineComponent({
lazy: props.searchableLazy lazy: props.searchableLazy
}) })
function escapeRegExp (string: string) { function escapeRegExp(string: string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
} }
@@ -530,7 +530,7 @@ export default defineComponent({
return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value } return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value }
}) })
function clearOnClose () { function clearOnClose() {
if (props.clearSearchOnClose) { if (props.clearSearchOnClose) {
query.value = '' query.value = ''
} }
@@ -546,13 +546,13 @@ export default defineComponent({
} }
}) })
function onUpdate (value: any) { function onUpdate(value: any) {
emit('update:modelValue', value) emit('update:modelValue', value)
emit('change', value) emit('change', value)
emitFormChange() emitFormChange()
} }
function onQueryChange (event: any) { function onQueryChange(event: any) {
query.value = event.target.value query.value = event.target.value
} }

View File

@@ -93,21 +93,21 @@ export default defineComponent({
size: { size: {
type: String as PropType<TextareaSize>, type: String as PropType<TextareaSize>,
default: null, default: null,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
color: { color: {
type: String as PropType<TextareaColor>, type: String as PropType<TextareaColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value) return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
} }
}, },
variant: { variant: {
type: String as PropType<TextareaVariant>, type: String as PropType<TextareaVariant>,
default: () => config.default.variant, default: () => config.default.variant,
validator (value: string) { validator(value: string) {
return [ return [
...Object.keys(config.variant), ...Object.keys(config.variant),
...Object.values(config.color).flatMap(value => Object.keys(value)) ...Object.values(config.color).flatMap(value => Object.keys(value))
@@ -132,7 +132,7 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'blur', 'change'], emits: ['update:modelValue', 'blur', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('textarea', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('textarea', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormBlur, emitFormInput, inputId, color, size, name } = useFormGroup(props, config) const { emitFormBlur, emitFormInput, inputId, color, size, name } = useFormGroup(props, config)
@@ -158,10 +158,10 @@ export default defineComponent({
textarea.value.style.overflow = 'hidden' textarea.value.style.overflow = 'hidden'
const styles = window.getComputedStyle(textarea.value) const styles = window.getComputedStyle(textarea.value)
const paddingTop = parseInt(styles.paddingTop) const paddingTop = Number.parseInt(styles.paddingTop)
const paddingBottom = parseInt(styles.paddingBottom) const paddingBottom = Number.parseInt(styles.paddingBottom)
const padding = paddingTop + paddingBottom const padding = paddingTop + paddingBottom
const lineHeight = parseInt(styles.lineHeight) const lineHeight = Number.parseInt(styles.lineHeight)
const { scrollHeight } = textarea.value const { scrollHeight } = textarea.value
const newRows = (scrollHeight - padding) / lineHeight const newRows = (scrollHeight - padding) / lineHeight

View File

@@ -88,14 +88,14 @@ export default defineComponent({
color: { color: {
type: String as PropType<ToggleColor>, type: String as PropType<ToggleColor>,
default: () => config.default.color, default: () => config.default.color,
validator (value: string) { validator(value: string) {
return appConfig.ui.colors.includes(value) return appConfig.ui.colors.includes(value)
} }
}, },
size: { size: {
type: String as PropType<ToggleSize>, type: String as PropType<ToggleSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.size).includes(value) return Object.keys(config.size).includes(value)
} }
}, },
@@ -109,16 +109,16 @@ export default defineComponent({
} }
}, },
emits: ['update:modelValue', 'change'], emits: ['update:modelValue', 'change'],
setup (props, { emit }) { setup(props, { emit }) {
const { ui, attrs } = useUI('toggle', toRef(props, 'ui'), config) const { ui, attrs } = useUI('toggle', toRef(props, 'ui'), config)
const { emitFormChange, color, inputId, name } = useFormGroup(props) const { emitFormChange, color, inputId, name } = useFormGroup(props)
const active = computed({ const active = computed({
get () { get() {
return props.modelValue return props.modelValue
}, },
set (value) { set(value) {
emit('update:modelValue', value) emit('update:modelValue', value)
emit('change', value) emit('change', value)

View File

@@ -45,7 +45,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('card', toRef(props, 'ui'), config) const { ui, attrs } = useUI('card', toRef(props, 'ui'), config)
const cardClass = computed(() => { const cardClass = computed(() => {

View File

@@ -33,7 +33,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('container', toRef(props, 'ui'), config) const { ui, attrs } = useUI('container', toRef(props, 'ui'), config)
const containerClass = computed(() => { const containerClass = computed(() => {

View File

@@ -55,7 +55,7 @@ export default defineComponent({
size: { size: {
type: String as PropType<DividerSize>, type: String as PropType<DividerSize>,
default: () => config.default.size, default: () => config.default.size,
validator (value: string) { validator(value: string) {
return Object.keys(config.border.size.horizontal).includes(value) || Object.keys(config.border.size.vertical).includes(value) return Object.keys(config.border.size.horizontal).includes(value) || Object.keys(config.border.size.vertical).includes(value)
} }
}, },
@@ -78,7 +78,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('divider', toRef(props, 'ui'), config) const { ui, attrs } = useUI('divider', toRef(props, 'ui'), config)
const wrapperClass = computed(() => { const wrapperClass = computed(() => {

View File

@@ -31,7 +31,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('skeleton', toRef(props, 'ui'), config) const { ui, attrs } = useUI('skeleton', toRef(props, 'ui'), config)
const skeletonClass = computed(() => { const skeletonClass = computed(() => {

View File

@@ -72,7 +72,7 @@ export default defineComponent({
default: () => ({}) default: () => ({})
} }
}, },
setup (props) { setup(props) {
const { ui, attrs } = useUI('breadcrumb', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('breadcrumb', toRef(props, 'ui'), config, toRef(props, 'class'))
return { return {

Some files were not shown because too many files have changed in this diff Show More