diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 16ebaaec..1a190001 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -11,14 +11,37 @@ on: - dev paths: - 'apps/www/**' + # Triggers the workflow on pull request event, but only for pull request opened or pull request labeled with "๐Ÿš€request-deploy" (from forked repo) + # pull_request is not allowed to use secrets, so we use pull_request_target instead (in forked repos) + pull_request_target: + types: + # When a created pull request from forked repo, it will be comment 'Should deploy to add label' + - opened + # When a labeled '๐Ÿš€request-deploy' pull request from forked repo, it will be deploy to Cloudflare Pages + - labeled + +permissions: + # default contents: read & write (in forked repos, only read) + contents: write + # default deployments: read & write (in forked repos, only read) + deployments: write + # default pull-requests: read & write (in forked repos, only read) + pull-requests: write jobs: publish: runs-on: ubuntu-latest - permissions: - contents: read - deployments: write name: Publish to Cloudflare Pages + if: ${{ + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'pull_request' || + (github.event_name == 'pull_request_target' && + github.event.action == 'labeled' && + github.event.pull_request.head.repo.fork == true && + contains(github.event.label.name, '๐Ÿš€request-deploy')) + }} + steps: - name: Checkout uses: actions/checkout@v3 @@ -70,3 +93,16 @@ jobs: # Optional: Change the working directory workingDirectory: apps/www wranglerVersion: '3' + + - name: Remove label + if: ${{ github.event_name == 'pull_request_target' && contains(github.event.label.name, '๐Ÿš€request-deploy') }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: ['๐Ÿš€request-deploy'] + }) diff --git a/apps/www/.vitepress/theme/components/CodeSandbox.vue b/apps/www/.vitepress/theme/components/CodeSandbox.vue new file mode 100644 index 00000000..8b55d399 --- /dev/null +++ b/apps/www/.vitepress/theme/components/CodeSandbox.vue @@ -0,0 +1,35 @@ + + + diff --git a/apps/www/.vitepress/theme/components/ComponentPreview.vue b/apps/www/.vitepress/theme/components/ComponentPreview.vue index 403cb932..8653daa9 100644 --- a/apps/www/.vitepress/theme/components/ComponentPreview.vue +++ b/apps/www/.vitepress/theme/components/ComponentPreview.vue @@ -1,11 +1,17 @@ + + diff --git a/apps/www/.vitepress/theme/components/Tooltip.vue b/apps/www/.vitepress/theme/components/Tooltip.vue new file mode 100644 index 00000000..a910e4a3 --- /dev/null +++ b/apps/www/.vitepress/theme/components/Tooltip.vue @@ -0,0 +1,26 @@ + + + diff --git a/apps/www/.vitepress/theme/config/docs.ts b/apps/www/.vitepress/theme/config/docs.ts index c96098f8..46c76ba9 100644 --- a/apps/www/.vitepress/theme/config/docs.ts +++ b/apps/www/.vitepress/theme/config/docs.ts @@ -108,11 +108,11 @@ export const docsConfig: DocsConfig = { href: '/docs/installation/nuxt', items: [], }, - // { - // title: 'Astro', - // href: '/docs/installation/astro', - // items: [], - // }, + { + title: 'Astro', + href: '/docs/installation/astro', + items: [], + }, { title: 'Laravel', href: '/docs/installation/laravel', diff --git a/apps/www/.vitepress/theme/layout/ExamplesLayout.vue b/apps/www/.vitepress/theme/layout/ExamplesLayout.vue index 21159737..dbdd458e 100644 --- a/apps/www/.vitepress/theme/layout/ExamplesLayout.vue +++ b/apps/www/.vitepress/theme/layout/ExamplesLayout.vue @@ -14,13 +14,13 @@ import { cn } from '@/lib/utils'
๐ŸŽ‰ - Style, a new CLI and more. + New form & pagination component diff --git a/apps/www/.vitepress/theme/layout/MainLayout.vue b/apps/www/.vitepress/theme/layout/MainLayout.vue index 8b19bfb2..9a0b7a0c 100644 --- a/apps/www/.vitepress/theme/layout/MainLayout.vue +++ b/apps/www/.vitepress/theme/layout/MainLayout.vue @@ -120,26 +120,29 @@ watch(() => $route.path, (n) => {
-
- - - -
+
+ - + +
diff --git a/apps/www/.vitepress/theme/utils/codeeditor.ts b/apps/www/.vitepress/theme/utils/codeeditor.ts new file mode 100644 index 00000000..fd3ffe11 --- /dev/null +++ b/apps/www/.vitepress/theme/utils/codeeditor.ts @@ -0,0 +1,212 @@ +import { getParameters } from 'codesandbox/lib/api/define' +import sdk from '@stackblitz/sdk' +import { dependencies as deps } from '../../../package.json' +import { Index as demoIndex } from '../../../../www/__registry__' +import tailwindConfigRaw from '../../../tailwind.config?raw' +import cssRaw from '../../../../../packages/cli/test/fixtures/nuxt/assets/css/tailwind.css?raw' +import { type Style } from '@/lib/registry/styles' + +export function makeCodeSandboxParams(componentName: string, style: Style, sources: Record) { + let files = {} + files = constructFiles(componentName, style, sources) + return getParameters({ files, template: 'node' }) +} + +export function makeStackblitzParams(componentName: string, style: Style, sources: Record) { + const files: Record = {} + Object.entries(constructFiles(componentName, style, sources)).forEach(([k, v]) => (files[`${k}`] = typeof v.content === 'object' ? JSON.stringify(v.content, null, 2) : v.content)) + return sdk.openProject({ + title: `${componentName} - Radix Vue`, + files, + template: 'node', + }, { + newWindow: true, + openFile: ['src/App.vue'], + }) +} + +const viteConfig = { + 'vite.config.js': { + content: `import path from "path" +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, +})`, + isBinary: false, + }, + 'index.html': { + content: ` + + + + + + Vite + Vue + TS + + +
+ + + + `, + isBinary: false, + }, +} + +function constructFiles(componentName: string, style: Style, sources: Record) { + const componentsJson = { + style, + tailwind: { + config: 'tailwind.config.js', + css: 'src/assets/index.css', + baseColor: 'zinc', + cssVariables: true, + }, + aliases: { + utils: '@/utils', + components: '@/components', + }, + } + + const iconPackage = style === 'default' ? 'lucide-vue-next' : '@radix-icons/vue' + const dependencies = { + 'vue': 'latest', + 'radix-vue': deps['radix-vue'], + '@radix-ui/colors': 'latest', + 'clsx': 'latest', + 'class-variance-authority': 'latest', + 'tailwind-merge': 'latest', + 'tailwindcss-animate': 'latest', + [iconPackage]: 'latest', + 'shadcn-vue': 'latest', + 'typescript': 'latest', + } + + const devDependencies = { + 'vite': 'latest', + '@vitejs/plugin-vue': 'latest', + 'vue-tsc': 'latest', + 'tailwindcss': 'latest', + 'postcss': 'latest', + 'autoprefixer': 'latest', + } + + const transformImportPath = (code: string) => { + let parsed = code + parsed = parsed.replaceAll(`@/lib/registry/${style}`, '@/components') + parsed = parsed.replaceAll('@/lib/utils', '@/utils') + return parsed + } + + const componentFiles = Object.keys(sources).filter(key => key.endsWith('.vue') && key !== 'index.vue') + const components: Record = {} + componentFiles.forEach((i) => { + components[`src/${i}`] = { + isBinary: false, + content: transformImportPath(sources[i]), + } + }) + + // @ts-expect-error componentName migth not exist in Index + const registryDependencies = demoIndex[style][componentName as any]?.registryDependencies?.filter(i => i !== 'utils') + + const files = { + 'package.json': { + content: { + name: `shadcn-vue-${componentName.toLowerCase().replace(/ /g, '-')}`, + scripts: { start: `shadcn-vue add ${registryDependencies.join(' ')} -y && vite` }, + dependencies, + devDependencies, + }, + isBinary: false, + }, + 'components.json': { + content: componentsJson, + isBinary: false, + }, + ...viteConfig, + 'tailwind.config.js': { + content: tailwindConfigRaw, + isBinary: false, + }, + 'postcss.config.js': { + content: `module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + } +}`, + isBinary: false, + }, + 'tsconfig.json': { + content: `{ +"$schema": "https://json.schemastore.org/tsconfig", +"compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } +} +}`, + isBinary: false, + }, + 'src/utils.ts': { + isBinary: false, + content: `import { type ClassValue, clsx } from 'clsx' +import { twMerge } from 'tailwind-merge' +import { camelize, getCurrentInstance, toHandlerKey } from 'vue' + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +}`, + }, + 'src/assets/index.css': { + content: cssRaw, + isBinary: false, + }, + 'src/main.ts': { + content: `import { createApp } from 'vue'; +import App from './App.vue'; +import './assets/global.css'; +import './assets/index.css'; + +createApp(App).mount('#app')`, + isBinary: false, + }, + 'src/App.vue': { + isBinary: false, + content: sources['index.vue'], + }, + ...components, + 'src/assets/global.css': { + content: `body { + display: flex; + align-items: flex-start; + justify-content: center; + padding-top: 120px; + width: 100vw; + height: 100vh; + background-color: hsl(var(--background)); + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + color: hsl(var(--foreground)); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-feature-settings: "rlig" 1, "calt" 1; +} + +#app { + @apply w-full flex items-center justify-center px-12; +}`, + isBinary: false, + }, + } + + return files +} diff --git a/apps/www/__registry__/index.ts b/apps/www/__registry__/index.ts index 5438904e..0251b406 100644 --- a/apps/www/__registry__/index.ts +++ b/apps/www/__registry__/index.ts @@ -580,21 +580,21 @@ export const Index = { name: 'ActivityGoal', type: 'components:example', registryDependencies: ['button', 'card', 'themes', 'config'], - component: () => import('../src/lib/registry/default/example/ActivityGoal.vue').then(m => m.default), + component: () => import('../src/lib/registry/default/example/Cards/ActivityGoal.vue').then(m => m.default), files: ['../src/lib/registry/default/example/ActivityGoal.vue'], }, DataTable: { name: 'DataTable', type: 'components:example', registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'card', 'utils'], - component: () => import('../src/lib/registry/default/example/DataTable.vue').then(m => m.default), + component: () => import('../src/lib/registry/default/example/Cards/DataTable.vue').then(m => m.default), files: ['../src/lib/registry/default/example/DataTable.vue'], }, Metric: { name: 'Metric', type: 'components:example', registryDependencies: ['card', 'config'], - component: () => import('../src/lib/registry/default/example/Metric.vue').then(m => m.default), + component: () => import('../src/lib/registry/default/example/Cards/Metric.vue').then(m => m.default), files: ['../src/lib/registry/default/example/Metric.vue'], }, }, @@ -1177,21 +1177,21 @@ export const Index = { name: 'ActivityGoal', type: 'components:example', registryDependencies: ['button', 'card', 'themes', 'config'], - component: () => import('../src/lib/registry/new-york/example/ActivityGoal.vue').then(m => m.default), + component: () => import('../src/lib/registry/new-york/example/Cards/ActivityGoal.vue').then(m => m.default), files: ['../src/lib/registry/new-york/example/ActivityGoal.vue'], }, DataTable: { name: 'DataTable', type: 'components:example', registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'card', 'utils'], - component: () => import('../src/lib/registry/new-york/example/DataTable.vue').then(m => m.default), + component: () => import('../src/lib/registry/new-york/example/Cards/DataTable.vue').then(m => m.default), files: ['../src/lib/registry/new-york/example/DataTable.vue'], }, Metric: { name: 'Metric', type: 'components:example', registryDependencies: ['card', 'config'], - component: () => import('../src/lib/registry/new-york/example/Metric.vue').then(m => m.default), + component: () => import('../src/lib/registry/new-york/example/Cards/Metric.vue').then(m => m.default), files: ['../src/lib/registry/new-york/example/Metric.vue'], }, }, diff --git a/apps/www/package.json b/apps/www/package.json index 9a00623b..ec17fa5b 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -15,19 +15,22 @@ "@formkit/auto-animate": "^0.8.0", "@morev/vue-transitions": "^2.3.6", "@radix-icons/vue": "^1.0.0", - "@tanstack/vue-table": "^8.10.3", - "@unovis/ts": "^1.2.1", - "@unovis/vue": "1.3.0-alpha.3", - "@vee-validate/zod": "^4.11.7", - "@vueuse/core": "^10.4.1", + "@stackblitz/sdk": "^1.9.0", + "@tanstack/vue-table": "^8.10.7", + "@unovis/ts": "^1.2.2", + "@unovis/vue": "1.3.0-beta.3", + "@vee-validate/zod": "^4.11.8", + "@vueuse/core": "^10.5.0", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", + "codesandbox": "^2.2.3", "date-fns": "^2.30.0", "lucide-vue-next": "^0.276.0", + "radix-vue": "^1.0.0", "tailwindcss-animate": "^1.0.7", - "v-calendar": "^3.1.0", - "vee-validate": "4.11.7", - "vue": "^3.3.4", + "v-calendar": "^3.1.2", + "vee-validate": "4.11.8", + "vue": "^3.3.6", "vue-wrap-balancer": "^1.1.3", "zod": "^3.22.4" }, @@ -36,23 +39,23 @@ "@iconify-json/tabler": "^1.1.89", "@iconify/json": "^2.2.108", "@iconify/vue": "^4.1.1", - "@types/lodash.template": "^4.5.1", - "@types/node": "^20.6.0", + "@types/lodash.template": "^4.5.2", + "@types/node": "^20.8.7", "@vitejs/plugin-vue": "^4.4.0", "@vitejs/plugin-vue-jsx": "^3.0.2", - "@vue/compiler-core": "^3.3.4", - "@vue/compiler-dom": "^3.3.4", + "@vue/compiler-core": "^3.3.6", + "@vue/compiler-dom": "^3.3.6", "autoprefixer": "^10.4.16", "lodash.template": "^4.5.0", - "radix-vue": "^0.4.1", - "rimraf": "^5.0.1", + "radix-vue": "^1.0.0", + "rimraf": "^5.0.5", "tailwind-merge": "^1.14.0", "tailwindcss": "^3.3.3", - "tsx": "^3.13.0", + "tsx": "^3.14.0", "typescript": "^5.2.2", - "unplugin-icons": "^0.17.0", - "vite": "^4.4.11", - "vitepress": "^1.0.0-rc.20", - "vue-tsc": "^1.8.15" + "unplugin-icons": "^0.17.1", + "vite": "^4.5.0", + "vitepress": "^1.0.0-rc.23", + "vue-tsc": "^1.8.20" } } diff --git a/apps/www/src/content/docs/components/accordion.md b/apps/www/src/content/docs/components/accordion.md index a2f6b862..451ab1d9 100644 --- a/apps/www/src/content/docs/components/accordion.md +++ b/apps/www/src/content/docs/components/accordion.md @@ -6,7 +6,7 @@ primitive: https://www.radix-vue.com/components/accordion.html --- - + ## Installation diff --git a/apps/www/src/content/docs/components/combobox.md b/apps/www/src/content/docs/components/combobox.md index 122c9ca1..8f909099 100644 --- a/apps/www/src/content/docs/components/combobox.md +++ b/apps/www/src/content/docs/components/combobox.md @@ -96,9 +96,9 @@ const value = ref({}) - + ### Form diff --git a/apps/www/src/content/docs/components/data-table.md b/apps/www/src/content/docs/components/data-table.md index 9e50d6fa..cec3a907 100644 --- a/apps/www/src/content/docs/components/data-table.md +++ b/apps/www/src/content/docs/components/data-table.md @@ -20,4 +20,1139 @@ We'll start with the basic `` component and build a complex data table **Tip:** If you find yourself using the same table in multiple places in your app, you can always extract it into a reusable component. - \ No newline at end of file + + +## Table of Contents + +This guide will show you how to use [TanStack Table](https://tanstack.com/table/v8) and the
component to build your own custom data table. We'll cover the following topics: + +- [Basic Table](#basic-table) +- [Row Actions](#row-actions) +- [Pagination](#pagination) +- [Sorting](#sorting) +- [Filtering](#filtering) +- [Visibility](#visibility) +- [Row Selection](#row-selection) +- [Reusable Components](#reusable-components) + +## Installation + +1. Add the `
` component to your project: + +```bash +npx shadcn-vue@latest add table +``` + +2. Add `tanstack/vue-table` dependency: + +```bash +npm install @tanstack/vue-table +``` + +## Prerequisites + +We are going to build a table to show recent payments. Here's what our data looks like: + +```ts:line-numbers +interface Payment { + id: string + amount: number + status: 'pending' | 'processing' | 'success' | 'failed' + email: string +} + +export const payments: Payment[] = [ + { + id: '728ed52f', + amount: 100, + status: 'pending', + email: 'm@example.com', + }, + { + id: '489e1d42', + amount: 125, + status: 'processing', + email: 'example@gmail.com', + }, + // ... +] +``` + +## Project Structure + +Start by creating the following file structure: + +```txt + components + โ””โ”€โ”€ payments + โ”œโ”€โ”€ columns.ts + โ”œโ”€โ”€ data-table.vue + โ”œโ”€โ”€ data-table-dropdown.vue +โ””โ”€โ”€ app.vue +``` + +I'm using a Nuxt.js example here but this works for any other Vue framework. + +- `columns.ts` It will contain our column definitions. +- `data-table.vue` It will contain our `` component. +- `data-table-dropdown.vue` It will contain our `` component. +- `app.vue` This is where we'll fetch data and render our table. + +## Basic Table + +Let's start by building a basic table. + + + +### Column Definitions + +First, we'll define our columns in the `columns.ts` file. + +```ts:line-numbers title="components/payments/columns.ts" {1,12-27} +import type { ColumnDef } from '@tanstack/vue-table' + +// This type is used to define the shape of our data. +// You can use a Zod schema here if you want. +export interface Payment { + id: string + amount: number + status: 'pending' | 'processing' | 'success' | 'failed' + email: string +} + +export const columns: ColumnDef[] = [ + { + accessorKey: 'status', + header: 'Status', + }, + { + accessorKey: 'email', + header: 'Email', + }, + { + accessorKey: 'amount', + header: 'Amount', + }, +] +``` + + + +**Note:** Columns are where you define the core of what your table +will look like. They define the data that will be displayed, how it will be +formatted, sorted and filtered. + + + +### `` component + +Next, we'll create a `` component to render our table. + +```ts:line-numbers + + + +``` + + + +**Tip**: If you find yourself using `` in multiple places, this is the component you could make reusable by extracting it to `components/ui/data-table.vue`. + +`` + + + + +### Render the table + +Finally, we'll render our table in our index component. + +```ts:line-numbers showLineNumbers{28} + + + +``` + + + +## Cell Formatting + +Let's format the amount cell to display the dollar amount. We'll also align the cell to the right. + + + +### Update columns definition + +Update the `header` and `cell` definitions for amount as follows: + + +```ts:line-numbers showLineNumbers title="components/payments/columns.ts" {5-17} +import { h } from 'vue' + +export const columns: ColumnDef[] = [ + { + accessorKey: "amount", + header: () => h('div', { class: 'text-right' }, 'Amount'), + cell: ({ row }) => { + const amount = parseFloat(row.getValue("amount")) + const formatted = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(amount) + + return h('div', { class: 'text-right font-medium' }, formatted) + }, + } +] +``` +You can use the same approach to format other cells and headers. + + +## Row Actions + +Let's add row actions to our table. We'll use a `` component for this. + + + +### Add the following into your `DataTableDropDown.vue` component: + +```ts:line-numbers +// DataTableDropDown.vue + + + + +``` + +### Update columns definition + +Update our columns definition to add a new `actions` column. The `actions` cell returns a `` component. + + +```ts:line-numbers showLineNumber{2,6-16} +import { ColumnDef } from "@tanstack/vue-table" +import DropdownAction from '@/components/DataTableDropDown.vue' + +export const columns: ColumnDef[] = [ + // ... + { + id: 'actions', + enableHiding: false, + cell: ({ row }) => { + const payment = row.original + + return h('div', { class: 'relative' }, h(DropdownAction, { + payment, + })) + }, + }, +] + +``` + +You can access the row data using `row.original` in the `cell` function. Use this to handle actions for your row eg. use the `id` to make a DELETE call to your API. + + + +## Pagination + +Next, we'll add pagination to our table. + + + +### Update `` + +```ts:line-numbers showLineNumbers{4,12} +import { + FlexRender, + getCoreRowModel, + getPaginationRowModel, + useVueTable, +} from "@tanstack/vue-table" + +const table = useVueTable({ + data: props.data, + columns: props.columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), +}) +``` + +This will automatically paginate your rows into pages of 10. See the [pagination docs](https://tanstack.com/table/v8/docs/api/features/pagination) for more information on customizing page size and implementing manual pagination. + +### Add pagination controls + +We can add pagination controls to our table using the ` - + No framework found. @@ -53,7 +53,10 @@ const filterFunction = (list: typeof frameworks, search: string) => list.filter( v-for="framework in frameworks" :key="framework.value" :value="framework" - @select="open = false" + @select="(ev) => { + value = ev.detail.value as typeof framework + open = false + }" > Create a new project

- + - + Edit profile diff --git a/apps/www/src/lib/registry/default/ui/accordion/Accordion.vue b/apps/www/src/lib/registry/default/ui/accordion/Accordion.vue index 563e01a8..1bfac8de 100644 --- a/apps/www/src/lib/registry/default/ui/accordion/Accordion.vue +++ b/apps/www/src/lib/registry/default/ui/accordion/Accordion.vue @@ -11,7 +11,7 @@ const emits = defineEmits() diff --git a/apps/www/src/lib/registry/default/ui/alert-dialog/AlertDialog.vue b/apps/www/src/lib/registry/default/ui/alert-dialog/AlertDialog.vue index f0c5e07a..8fb30de8 100644 --- a/apps/www/src/lib/registry/default/ui/alert-dialog/AlertDialog.vue +++ b/apps/www/src/lib/registry/default/ui/alert-dialog/AlertDialog.vue @@ -1,14 +1,14 @@ diff --git a/apps/www/src/lib/registry/default/ui/calendar/Calendar.vue b/apps/www/src/lib/registry/default/ui/calendar/Calendar.vue index 78f15c80..e90acfb6 100644 --- a/apps/www/src/lib/registry/default/ui/calendar/Calendar.vue +++ b/apps/www/src/lib/registry/default/ui/calendar/Calendar.vue @@ -7,7 +7,11 @@ import { computed, nextTick, onMounted, ref } from 'vue' import { buttonVariants } from '../button' import { cn } from '@/lib/utils' -const props = withDefaults(defineProps< { +defineOptions({ + inheritAttrs: false, +}) + +const props = withDefaults(defineProps<{ modelValue?: string | number | Date | Partial<{ start: Date end: Date @@ -41,7 +45,6 @@ function handleNav(direction: 'prev' | 'next') { } onMounted(async () => { - await nextTick() await nextTick() if (modelValue.value instanceof Date && calendarRef.value) calendarRef.value.focusDate(modelValue.value) @@ -59,7 +62,16 @@ onMounted(async () => { - + diff --git a/apps/www/src/lib/registry/default/ui/checkbox/Checkbox.vue b/apps/www/src/lib/registry/default/ui/checkbox/Checkbox.vue index 4b94feea..338abf7b 100644 --- a/apps/www/src/lib/registry/default/ui/checkbox/Checkbox.vue +++ b/apps/www/src/lib/registry/default/ui/checkbox/Checkbox.vue @@ -1,18 +1,18 @@