refactor(Command, Combobox): adapt to respective component
This commit is contained in:
parent
d7c4f34bab
commit
18040192c8
|
|
@ -1,11 +1,11 @@
|
||||||
import type { RegistryStyle } from '@/registry/registry-styles'
|
import type { RegistryStyle } from '@/registry/registry-styles'
|
||||||
import sdk from '@stackblitz/sdk'
|
import sdk from '@stackblitz/sdk'
|
||||||
import { getParameters } from 'codesandbox/lib/api/define'
|
import { getParameters } from 'codesandbox/lib/api/define'
|
||||||
|
// @ts-expect-error ?raw
|
||||||
|
import cssRaw from '../../../../../packages/cli/test/fixtures/frameworks/nuxt/assets/css/tailwind.css?raw'
|
||||||
import { Index as demoIndex } from '../../../../www/__registry__'
|
import { Index as demoIndex } from '../../../../www/__registry__'
|
||||||
// @ts-expect-error ?raw
|
// @ts-expect-error ?raw
|
||||||
import tailwindConfigRaw from '../../../tailwind.config?raw'
|
import tailwindConfigRaw from '../../../tailwind.config?raw'
|
||||||
// @ts-expect-error ?raw
|
|
||||||
import cssRaw from '../../../../../packages/cli/test/fixtures/frameworks/nuxt/assets/css/tailwind.css?raw'
|
|
||||||
|
|
||||||
export function makeCodeSandboxParams(componentName: string, style: RegistryStyle, sources: Record<string, string>) {
|
export function makeCodeSandboxParams(componentName: string, style: RegistryStyle, sources: Record<string, string>) {
|
||||||
let files: Record<string, any> = {}
|
let files: Record<string, any> = {}
|
||||||
|
|
@ -132,7 +132,7 @@ function constructFiles(componentName: string, style: RegistryStyle, sources: Re
|
||||||
})
|
})
|
||||||
|
|
||||||
// @ts-expect-error componentName might not exist in Index
|
// @ts-expect-error componentName might not exist in Index
|
||||||
const registryDependencies = demoIndex[style][componentName as any]?.registryDependencies?.filter(i => i !== 'utils')
|
const registryDependencies = demoIndex[style][componentName as any]?.registryDependencies?.filter(i => i !== 'utils') ?? []
|
||||||
|
|
||||||
const files = {
|
const files = {
|
||||||
'package.json': {
|
'package.json': {
|
||||||
|
|
|
||||||
|
|
@ -632,6 +632,57 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"combobox": {
|
||||||
|
name: "combobox",
|
||||||
|
description: "",
|
||||||
|
type: "registry:ui",
|
||||||
|
registryDependencies: ["utils"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/ui/combobox/Combobox.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxAnchor.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxEmpty.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxGroup.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxInput.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxItem.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxList.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxSeparator.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxTrigger.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/index.ts",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/ui/combobox/Combobox.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"command": {
|
"command": {
|
||||||
name: "command",
|
name: "command",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -2985,7 +3036,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxDemo",
|
name: "ComboboxDemo",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","popover"],
|
registryDependencies: ["utils","combobox"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/new-york/example/ComboboxDemo.vue",
|
path: "registry/new-york/example/ComboboxDemo.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -3015,7 +3066,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxForm",
|
name: "ComboboxForm",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/new-york/example/ComboboxForm.vue",
|
path: "registry/new-york/example/ComboboxForm.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -3056,6 +3107,21 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"ComboboxTrigger": {
|
||||||
|
name: "ComboboxTrigger",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","combobox"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/ComboboxTrigger.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/ComboboxTrigger.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"CommandDemo": {
|
"CommandDemo": {
|
||||||
name: "CommandDemo",
|
name: "CommandDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -3086,6 +3152,66 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"CommandDropdownMenu": {
|
||||||
|
name: "CommandDropdownMenu",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","dropdown-menu"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandDropdownMenu.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandDropdownMenu.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandForm": {
|
||||||
|
name: "CommandForm",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandForm.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandForm.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandPopover": {
|
||||||
|
name: "CommandPopover",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandPopover.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandPopover.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandResponsive": {
|
||||||
|
name: "CommandResponsive",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","drawer","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandResponsive.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandResponsive.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"ContextMenuDemo": {
|
"ContextMenuDemo": {
|
||||||
name: "ContextMenuDemo",
|
name: "ContextMenuDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -6352,6 +6478,57 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"combobox": {
|
||||||
|
name: "combobox",
|
||||||
|
description: "",
|
||||||
|
type: "registry:ui",
|
||||||
|
registryDependencies: ["utils"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/ui/combobox/Combobox.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxAnchor.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxEmpty.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxGroup.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxInput.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxItem.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxList.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxSeparator.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/ComboboxTrigger.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/new-york/ui/combobox/index.ts",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/ui/combobox/Combobox.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"command": {
|
"command": {
|
||||||
name: "command",
|
name: "command",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -8705,7 +8882,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxDemo",
|
name: "ComboboxDemo",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","popover"],
|
registryDependencies: ["utils","combobox"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/new-york/example/ComboboxDemo.vue",
|
path: "registry/new-york/example/ComboboxDemo.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -8735,7 +8912,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxForm",
|
name: "ComboboxForm",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/new-york/example/ComboboxForm.vue",
|
path: "registry/new-york/example/ComboboxForm.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -8776,6 +8953,21 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"ComboboxTrigger": {
|
||||||
|
name: "ComboboxTrigger",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","combobox"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/ComboboxTrigger.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/ComboboxTrigger.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"CommandDemo": {
|
"CommandDemo": {
|
||||||
name: "CommandDemo",
|
name: "CommandDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -8806,6 +8998,66 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"CommandDropdownMenu": {
|
||||||
|
name: "CommandDropdownMenu",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","dropdown-menu"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandDropdownMenu.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandDropdownMenu.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandForm": {
|
||||||
|
name: "CommandForm",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandForm.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandForm.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandPopover": {
|
||||||
|
name: "CommandPopover",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandPopover.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandPopover.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandResponsive": {
|
||||||
|
name: "CommandResponsive",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","drawer","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/new-york/example/CommandResponsive.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/new-york/example/CommandResponsive.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"ContextMenuDemo": {
|
"ContextMenuDemo": {
|
||||||
name: "ContextMenuDemo",
|
name: "ContextMenuDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -12088,6 +12340,57 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"combobox": {
|
||||||
|
name: "combobox",
|
||||||
|
description: "",
|
||||||
|
type: "registry:ui",
|
||||||
|
registryDependencies: ["utils"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/ui/combobox/Combobox.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxAnchor.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxEmpty.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxGroup.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxInput.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxItem.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxList.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxSeparator.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxTrigger.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/index.ts",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/ui/combobox/Combobox.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"command": {
|
"command": {
|
||||||
name: "command",
|
name: "command",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -14441,7 +14744,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxDemo",
|
name: "ComboboxDemo",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","popover"],
|
registryDependencies: ["utils","combobox"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/default/example/ComboboxDemo.vue",
|
path: "registry/default/example/ComboboxDemo.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -14471,7 +14774,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxForm",
|
name: "ComboboxForm",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/default/example/ComboboxForm.vue",
|
path: "registry/default/example/ComboboxForm.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -14512,6 +14815,21 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"ComboboxTrigger": {
|
||||||
|
name: "ComboboxTrigger",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","combobox"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/ComboboxTrigger.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/ComboboxTrigger.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"CommandDemo": {
|
"CommandDemo": {
|
||||||
name: "CommandDemo",
|
name: "CommandDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -14542,6 +14860,66 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"CommandDropdownMenu": {
|
||||||
|
name: "CommandDropdownMenu",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","dropdown-menu"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandDropdownMenu.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandDropdownMenu.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandForm": {
|
||||||
|
name: "CommandForm",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandForm.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandForm.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandPopover": {
|
||||||
|
name: "CommandPopover",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandPopover.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandPopover.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandResponsive": {
|
||||||
|
name: "CommandResponsive",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","drawer","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandResponsive.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandResponsive.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"ContextMenuDemo": {
|
"ContextMenuDemo": {
|
||||||
name: "ContextMenuDemo",
|
name: "ContextMenuDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -17808,6 +18186,57 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"combobox": {
|
||||||
|
name: "combobox",
|
||||||
|
description: "",
|
||||||
|
type: "registry:ui",
|
||||||
|
registryDependencies: ["utils"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/ui/combobox/Combobox.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxAnchor.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxEmpty.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxGroup.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxInput.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxItem.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxList.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxSeparator.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/ComboboxTrigger.vue",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
},{
|
||||||
|
path: "registry/default/ui/combobox/index.ts",
|
||||||
|
type: "registry:ui",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/ui/combobox/Combobox.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"command": {
|
"command": {
|
||||||
name: "command",
|
name: "command",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -20161,7 +20590,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxDemo",
|
name: "ComboboxDemo",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","popover"],
|
registryDependencies: ["utils","combobox"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/default/example/ComboboxDemo.vue",
|
path: "registry/default/example/ComboboxDemo.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -20191,7 +20620,7 @@ export const Index: Record<string, any> = {
|
||||||
name: "ComboboxForm",
|
name: "ComboboxForm",
|
||||||
description: "",
|
description: "",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||||
files: [{
|
files: [{
|
||||||
path: "registry/default/example/ComboboxForm.vue",
|
path: "registry/default/example/ComboboxForm.vue",
|
||||||
type: "registry:example",
|
type: "registry:example",
|
||||||
|
|
@ -20232,6 +20661,21 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"ComboboxTrigger": {
|
||||||
|
name: "ComboboxTrigger",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","combobox"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/ComboboxTrigger.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/ComboboxTrigger.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"CommandDemo": {
|
"CommandDemo": {
|
||||||
name: "CommandDemo",
|
name: "CommandDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -20262,6 +20706,66 @@ export const Index: Record<string, any> = {
|
||||||
category: "",
|
category: "",
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
},
|
},
|
||||||
|
"CommandDropdownMenu": {
|
||||||
|
name: "CommandDropdownMenu",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","dropdown-menu"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandDropdownMenu.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandDropdownMenu.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandForm": {
|
||||||
|
name: "CommandForm",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandForm.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandForm.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandPopover": {
|
||||||
|
name: "CommandPopover",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandPopover.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandPopover.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
|
"CommandResponsive": {
|
||||||
|
name: "CommandResponsive",
|
||||||
|
description: "",
|
||||||
|
type: "registry:example",
|
||||||
|
registryDependencies: ["button","command","drawer","popover"],
|
||||||
|
files: [{
|
||||||
|
path: "registry/default/example/CommandResponsive.vue",
|
||||||
|
type: "registry:example",
|
||||||
|
target: ""
|
||||||
|
}],
|
||||||
|
component: () => import("@/registry/default/example/CommandResponsive.vue").then((m) => m.default),
|
||||||
|
source: "",
|
||||||
|
category: "",
|
||||||
|
subcategory: ""
|
||||||
|
},
|
||||||
"ContextMenuDemo": {
|
"ContextMenuDemo": {
|
||||||
name: "ContextMenuDemo",
|
name: "ContextMenuDemo",
|
||||||
description: "",
|
description: "",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
title: Combobox
|
title: Combobox
|
||||||
description: Autocomplete input and command palette with a list of suggestions.
|
description: Autocomplete input and command palette with a list of suggestions.
|
||||||
|
source: apps/www/registry/default/ui/combobox
|
||||||
|
primitive: https://www.reka-ui.com/docs/components/combobox.html
|
||||||
---
|
---
|
||||||
|
|
||||||
<ComponentPreview name="ComboboxDemo" />
|
<ComponentPreview name="ComboboxDemo" />
|
||||||
|
|
@ -9,9 +11,9 @@ description: Autocomplete input and command palette with a list of suggestions.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The Combobox is built using a composition of the `<Popover />` and the `<Command />` components.
|
```bash
|
||||||
|
npx shadcn-vue@latest add combobox
|
||||||
See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
@ -92,11 +94,11 @@ const value = ref('')
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Combobox
|
### Combobox Trigger
|
||||||
|
|
||||||
<ComponentPreview name="ComboboxDemo" />
|
<ComponentPreview name="ComboboxTrigger" />
|
||||||
|
|
||||||
### Popover
|
<!-- ### Popover
|
||||||
|
|
||||||
<ComponentPreview name="ComboboxPopover" />
|
<ComponentPreview name="ComboboxPopover" />
|
||||||
|
|
||||||
|
|
@ -108,7 +110,7 @@ const value = ref('')
|
||||||
|
|
||||||
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
|
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
|
||||||
|
|
||||||
<ComponentPreview name="ComboboxResponsive" />
|
<ComponentPreview name="ComboboxResponsive" /> -->
|
||||||
|
|
||||||
### Form
|
### Form
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: Command
|
title: Command
|
||||||
description: Fast, composable, unstyled command menu.
|
description: Fast, composable, unstyled command menu.
|
||||||
source: apps/www/registry/default/ui/command
|
source: apps/www/registry/default/ui/command
|
||||||
primitive: https://www.reka-ui.com/docs/components/combobox.html
|
primitive: https://www.reka-ui.com/docs/components/listbox.html
|
||||||
---
|
---
|
||||||
|
|
||||||
<ComponentPreview name="CommandDemo" />
|
<ComponentPreview name="CommandDemo" />
|
||||||
|
|
@ -134,6 +134,28 @@ watch(CmdJ, (v) => {
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Combobox
|
<br></br>
|
||||||
|
|
||||||
You can use the `<Command />` component as a combobox. See the [Combobox](/docs/components/combobox) page for more information.
|
<Callout>
|
||||||
|
|
||||||
|
You can use the `<Command />` component like a combobox.
|
||||||
|
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
### Popover
|
||||||
|
|
||||||
|
<ComponentPreview name="CommandPopover" />
|
||||||
|
|
||||||
|
### Dropdown menu
|
||||||
|
|
||||||
|
<ComponentPreview name="CommandDropdownMenu" />
|
||||||
|
|
||||||
|
### Responsive
|
||||||
|
|
||||||
|
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
|
||||||
|
|
||||||
|
<ComponentPreview name="CommandResponsive" />
|
||||||
|
|
||||||
|
### Form
|
||||||
|
|
||||||
|
<ComponentPreview name="CommandForm" />
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,58 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"type": "registry:ui"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "command",
|
"name": "command",
|
||||||
"type": "registry:ui",
|
"type": "registry:ui",
|
||||||
|
|
@ -2780,6 +2832,58 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"type": "registry:ui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"type": "registry:ui"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "command",
|
"name": "command",
|
||||||
"type": "registry:ui",
|
"type": "registry:ui",
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,12 @@
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"combobox"
|
||||||
"command",
|
|
||||||
"popover"
|
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxDemo.vue",
|
"path": "example/ComboboxDemo.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst open = ref(false)\nconst value = ref('')\n</script>\n\n<template>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n class=\"w-[200px] justify-between\"\n >\n {{ value\n ? frameworks.find((framework) => framework.value === value)?.label\n : \"Select framework...\" }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput class=\"h-9\" placeholder=\"Search framework...\" />\n <CommandEmpty>No framework found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework.value\"\n @select=\"(ev) => {\n if (typeof ev.detail.value === 'string') {\n value = ev.detail.value\n }\n open = false\n }\"\n >\n {{ framework.label }}\n <Check\n :class=\"cn(\n 'ml-auto h-4 w-4',\n value === framework.value ? 'opacity-100' : 'opacity-0',\n )\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/default/ui/combobox'\nimport { Check, Search } from 'lucide-vue-next'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n</script>\n\n<template>\n <Combobox by=\"label\">\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9\" :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n </ComboboxAnchor>\n\n <ComboboxList>\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,14 @@
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"button",
|
||||||
"command",
|
"combobox",
|
||||||
"form",
|
"form",
|
||||||
"popover",
|
|
||||||
"toast"
|
"toast"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxForm.vue",
|
"path": "example/ComboboxForm.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n]\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n <Check\n :class=\"cn('mr-2 h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n {{ language.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n\n <Combobox by=\"label\">\n <FormControl>\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <ComboboxTrigger class=\"absolute end-0 inset-y-0 flex items-center justify-center px-3\">\n <ChevronsUpDown class=\"size-4 text-muted-foreground\" />\n </ComboboxTrigger>\n </div>\n </ComboboxAnchor>\n </FormControl>\n\n <ComboboxList>\n <ComboboxEmpty>\n Nothing found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
apps/www/src/public/r/styles/default/ComboboxTrigger.json
Normal file
18
apps/www/src/public/r/styles/default/ComboboxTrigger.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "ComboboxTrigger",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"combobox"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst value = ref<typeof frameworks[0]>()\n</script>\n\n<template>\n <Combobox v-model=\"value\" by=\"label\">\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button variant=\"outline\" class=\"justify-between\">\n {{ value?.label ?? 'Select framework' }}\n\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "CommandDropdownMenu",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"dropdown-menu"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandDropdownMenu.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@/registry/default/ui/dropdown-menu'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst labels = [\n 'feature',\n 'bug',\n 'enhancement',\n 'documentation',\n 'design',\n 'question',\n 'maintenance',\n]\n\nconst labelRef = ref('feature')\nconst open = ref(false)\n</script>\n\n<template>\n <div class=\"flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center\">\n <p class=\"text-sm font-medium leading-none\">\n <span class=\"mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground\">\n {{ labelRef }}\n </span>\n <span class=\"text-muted-foreground\">Create a new project</span>\n </p>\n <DropdownMenu v-model:open=\"open\">\n <DropdownMenuTrigger as-child>\n <Button variant=\"ghost\" size=\"sm\">\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" class=\"w-[200px]\">\n <DropdownMenuLabel>Actions</DropdownMenuLabel>\n <DropdownMenuGroup>\n <DropdownMenuItem>\n Assign to...\n </DropdownMenuItem>\n <DropdownMenuItem>\n Set due date...\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n Apply label\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent class=\"p-0\">\n <Command>\n <CommandInput\n placeholder=\"Filter label...\"\n auto-focus\n />\n <CommandList>\n <CommandEmpty>No label found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"label in labels\"\n :key=\"label\"\n :value=\"label\"\n @select=\"(ev) => {\n labelRef = ev.detail.value as string\n open = false\n }\"\n >\n {{ label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n <DropdownMenuSeparator />\n <DropdownMenuItem class=\"text-red-600\">\n Delete\n <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
25
apps/www/src/public/r/styles/default/CommandForm.json
Normal file
25
apps/www/src/public/r/styles/default/CommandForm.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "CommandForm",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"vee-validate",
|
||||||
|
"@vee-validate/zod",
|
||||||
|
"zod"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"form",
|
||||||
|
"popover",
|
||||||
|
"toast"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandForm.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
18
apps/www/src/public/r/styles/default/CommandPopover.json
Normal file
18
apps/www/src/public/r/styles/default/CommandPopover.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "CommandPopover",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandPopover.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/default/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst open = ref(false)\nconst selectedStatus = ref<Status>()\n</script>\n\n<template>\n <div class=\"flex items-center space-x-4\">\n <p class=\"text-sm text-muted-foreground\">\n Status\n </p>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n size=\"sm\"\n class=\"w-[150px] justify-start\"\n >\n <template v-if=\"selectedStatus\">\n {{ selectedStatus?.label }}\n </template>\n <template v-else>\n + Set status\n </template>\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"p-0\" side=\"right\" align=\"start\">\n <Command>\n <CommandInput placeholder=\"Change status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status in statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"() => {\n selectedStatus = status\n open = false\n }\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
apps/www/src/public/r/styles/default/CommandResponsive.json
Normal file
21
apps/www/src/public/r/styles/default/CommandResponsive.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "CommandResponsive",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"@vueuse/core"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"drawer",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandResponsive.vue",
|
||||||
|
"content": "<script lang=\"ts\" setup>\nimport { Button } from '@/registry/default/ui/button'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/default/ui/command'\nimport { Drawer, DrawerContent, DrawerTrigger } from '@/registry/default/ui/drawer'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/registry/default/ui/popover'\nimport { createReusableTemplate, useMediaQuery } from '@vueuse/core'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst [UseTemplate, StatusList] = createReusableTemplate()\nconst isDesktop = useMediaQuery('(min-width: 768px)')\n\nconst isOpen = ref(false)\nconst selectedStatus = ref<Status | null>(null)\n\nfunction onStatusSelect(status: Status) {\n selectedStatus.value = status\n isOpen.value = false\n}\n</script>\n\n<template>\n <div>\n <UseTemplate>\n <Command>\n <CommandInput placeholder=\"Filter status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status of statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"onStatusSelect(status)\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </UseTemplate>\n\n <Popover v-if=\"isDesktop\" v-model:open=\"isOpen\">\n <PopoverTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\" align=\"start\">\n <StatusList />\n </PopoverContent>\n </Popover>\n\n <Drawer v-else :open=\"isOpen\" @update:open=\"(newOpenValue) => isOpen = newOpenValue\">\n <DrawerTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </DrawerTrigger>\n <DrawerContent>\n <div class=\"mt-4 border-t\">\n <StatusList />\n </div>\n </DrawerContent>\n </Drawer>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
72
apps/www/src/public/r/styles/default/combobox.json
Normal file
72
apps/www/src/public/r/styles/default/combobox.json
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'\n\nconst props = defineProps<ComboboxRootProps>()\nconst emits = defineEmits<ComboboxRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <ComboboxRoot v-bind=\"forwarded\">\n <slot />\n </ComboboxRoot>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxAnchorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxAnchor, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxAnchor\n v-bind=\"forwarded\"\n :class=\"cn('w-[200px]', props.class)\"\n >\n <slot />\n </ComboboxAnchor>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxEmptyProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxEmpty } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxEmpty v-bind=\"delegatedProps\" :class=\"cn('py-6 text-center text-sm', props.class)\">\n <slot />\n </ComboboxEmpty>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxGroupProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxGroup, ComboboxLabel } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxGroupProps & {\n class?: HTMLAttributes['class']\n heading?: string\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxGroup\n v-bind=\"delegatedProps\"\n :class=\"cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)\"\n >\n <ComboboxLabel v-if=\"heading\" class=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {{ heading }}\n </ComboboxLabel>\n <slot />\n </ComboboxGroup>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxInputProps & {\n class?: HTMLAttributes['class']\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxInput\n v-bind=\"forwardedProps\"\n :class=\"cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)\"\n >\n <slot />\n </ComboboxInput>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxItem, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()\nconst emits = defineEmits<ComboboxItemEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxItem\n v-bind=\"forwarded\"\n :class=\"cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)\"\n >\n <slot />\n </ComboboxItem>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {\n position: 'popper',\n align: 'center',\n sideOffset: 4,\n})\nconst emits = defineEmits<ComboboxContentEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxPortal>\n <ComboboxContent\n v-bind=\"forwarded\"\n :class=\"cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)\"\n >\n <ComboboxViewport>\n <slot />\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxSeparatorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxSeparator } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxSeparator\n v-bind=\"delegatedProps\"\n :class=\"cn('-mx-1 h-px bg-border', props.class)\"\n >\n <slot />\n </ComboboxSeparator>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxTriggerProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxTrigger, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxTrigger\n v-bind=\"forwarded\"\n :class=\"cn('', props.class)\"\n tabindex=\"0\"\n >\n <slot />\n </ComboboxTrigger>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"content": "export { default as Combobox } from './Combobox.vue'\nexport { default as ComboboxAnchor } from './ComboboxAnchor.vue'\nexport { default as ComboboxEmpty } from './ComboboxEmpty.vue'\nexport { default as ComboboxGroup } from './ComboboxGroup.vue'\nexport { default as ComboboxInput } from './ComboboxInput.vue'\nexport { default as ComboboxItem } from './ComboboxItem.vue'\nexport { default as ComboboxList } from './ComboboxList.vue'\nexport { default as ComboboxSeparator } from './ComboboxSeparator.vue'\n\nexport { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -4,14 +4,12 @@
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"combobox"
|
||||||
"command",
|
|
||||||
"popover"
|
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxDemo.vue",
|
"path": "example/ComboboxDemo.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst open = ref(false)\nconst value = ref('')\n</script>\n\n<template>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n class=\"w-[200px] justify-between\"\n >\n {{ value\n ? frameworks.find((framework) => framework.value === value)?.label\n : \"Select framework...\" }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput class=\"h-9\" placeholder=\"Search framework...\" />\n <CommandEmpty>No framework found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework.value\"\n @select=\"(ev) => {\n if (typeof ev.detail.value === 'string') {\n value = ev.detail.value\n }\n open = false\n }\"\n >\n {{ framework.label }}\n <Check\n :class=\"cn(\n 'ml-auto h-4 w-4',\n value === framework.value ? 'opacity-100' : 'opacity-0',\n )\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/new-york/ui/combobox'\nimport { Check, Search } from 'lucide-vue-next'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n</script>\n\n<template>\n <Combobox by=\"label\">\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9\" :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n </ComboboxAnchor>\n\n <ComboboxList>\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,14 @@
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"button",
|
||||||
"command",
|
"combobox",
|
||||||
"form",
|
"form",
|
||||||
"popover",
|
|
||||||
"toast"
|
"toast"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxForm.vue",
|
"path": "example/ComboboxForm.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n\n <Combobox by=\"label\">\n <FormControl>\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <ComboboxTrigger class=\"absolute end-0 inset-y-0 flex items-center justify-center px-3\">\n <ChevronsUpDown class=\"size-4 text-muted-foreground\" />\n </ComboboxTrigger>\n </div>\n </ComboboxAnchor>\n </FormControl>\n\n <ComboboxList>\n <ComboboxEmpty>\n Nothing found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
apps/www/src/public/r/styles/new-york/ComboboxTrigger.json
Normal file
18
apps/www/src/public/r/styles/new-york/ComboboxTrigger.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "ComboboxTrigger",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"combobox"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst value = ref<typeof frameworks[0]>()\n</script>\n\n<template>\n <Combobox v-model=\"value\" by=\"label\">\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button variant=\"outline\" class=\"justify-between\">\n {{ value?.label ?? 'Select framework' }}\n\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "CommandDropdownMenu",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"dropdown-menu"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandDropdownMenu.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@/registry/new-york/ui/dropdown-menu'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst labels = [\n 'feature',\n 'bug',\n 'enhancement',\n 'documentation',\n 'design',\n 'question',\n 'maintenance',\n]\n\nconst labelRef = ref('feature')\nconst open = ref(false)\n</script>\n\n<template>\n <div class=\"flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center\">\n <p class=\"text-sm font-medium leading-none\">\n <span class=\"mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground\">\n {{ labelRef }}\n </span>\n <span class=\"text-muted-foreground\">Create a new project</span>\n </p>\n <DropdownMenu v-model:open=\"open\">\n <DropdownMenuTrigger as-child>\n <Button variant=\"ghost\" size=\"sm\">\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" class=\"w-[200px]\">\n <DropdownMenuLabel>Actions</DropdownMenuLabel>\n <DropdownMenuGroup>\n <DropdownMenuItem>\n Assign to...\n </DropdownMenuItem>\n <DropdownMenuItem>\n Set due date...\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n Apply label\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent class=\"p-0\">\n <Command>\n <CommandInput\n placeholder=\"Filter label...\"\n auto-focus\n />\n <CommandList>\n <CommandEmpty>No label found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"label in labels\"\n :key=\"label\"\n :value=\"label\"\n @select=\"(ev) => {\n labelRef = ev.detail.value as string\n open = false\n }\"\n >\n {{ label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n <DropdownMenuSeparator />\n <DropdownMenuItem class=\"text-red-600\">\n Delete\n <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
25
apps/www/src/public/r/styles/new-york/CommandForm.json
Normal file
25
apps/www/src/public/r/styles/new-york/CommandForm.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "CommandForm",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"vee-validate",
|
||||||
|
"@vee-validate/zod",
|
||||||
|
"zod"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"form",
|
||||||
|
"popover",
|
||||||
|
"toast"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandForm.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
18
apps/www/src/public/r/styles/new-york/CommandPopover.json
Normal file
18
apps/www/src/public/r/styles/new-york/CommandPopover.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "CommandPopover",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandPopover.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/new-york/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst open = ref(false)\nconst selectedStatus = ref<Status>()\n</script>\n\n<template>\n <div class=\"flex items-center space-x-4\">\n <p class=\"text-sm text-muted-foreground\">\n Status\n </p>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n size=\"sm\"\n class=\"w-[150px] justify-start\"\n >\n <template v-if=\"selectedStatus\">\n {{ selectedStatus?.label }}\n </template>\n <template v-else>\n + Set status\n </template>\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"p-0\" side=\"right\" align=\"start\">\n <Command>\n <CommandInput placeholder=\"Change status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status in statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"() => {\n selectedStatus = status\n open = false\n }\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
apps/www/src/public/r/styles/new-york/CommandResponsive.json
Normal file
21
apps/www/src/public/r/styles/new-york/CommandResponsive.json
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "CommandResponsive",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"@vueuse/core"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"drawer",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandResponsive.vue",
|
||||||
|
"content": "<script lang=\"ts\" setup>\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/new-york/ui/command'\nimport { Drawer, DrawerContent, DrawerTrigger } from '@/registry/new-york/ui/drawer'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/registry/new-york/ui/popover'\nimport { createReusableTemplate, useMediaQuery } from '@vueuse/core'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst [UseTemplate, StatusList] = createReusableTemplate()\nconst isDesktop = useMediaQuery('(min-width: 768px)')\n\nconst isOpen = ref(false)\nconst selectedStatus = ref<Status | null>(null)\n\nfunction onStatusSelect(status: Status) {\n selectedStatus.value = status\n isOpen.value = false\n}\n</script>\n\n<template>\n <div>\n <UseTemplate>\n <Command>\n <CommandInput placeholder=\"Filter status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status of statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"onStatusSelect(status)\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </UseTemplate>\n\n <Popover v-if=\"isDesktop\" v-model:open=\"isOpen\">\n <PopoverTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\" align=\"start\">\n <StatusList />\n </PopoverContent>\n </Popover>\n\n <Drawer v-else v-model:open=\"isOpen\">\n <DrawerTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </DrawerTrigger>\n <DrawerContent>\n <div class=\"mt-4 border-t\">\n <StatusList />\n </div>\n </DrawerContent>\n </Drawer>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
72
apps/www/src/public/r/styles/new-york/combobox.json
Normal file
72
apps/www/src/public/r/styles/new-york/combobox.json
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'\n\nconst props = defineProps<ComboboxRootProps>()\nconst emits = defineEmits<ComboboxRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <ComboboxRoot v-bind=\"forwarded\">\n <slot />\n </ComboboxRoot>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxAnchorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxAnchor, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxAnchor\n v-bind=\"forwarded\"\n :class=\"cn('w-[200px]', props.class)\"\n >\n <slot />\n </ComboboxAnchor>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxEmptyProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxEmpty } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxEmpty v-bind=\"delegatedProps\" :class=\"cn('py-6 text-center text-sm', props.class)\">\n <slot />\n </ComboboxEmpty>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxGroupProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxGroup, ComboboxLabel } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxGroupProps & {\n class?: HTMLAttributes['class']\n heading?: string\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxGroup\n v-bind=\"delegatedProps\"\n :class=\"cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)\"\n >\n <ComboboxLabel v-if=\"heading\" class=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {{ heading }}\n </ComboboxLabel>\n <slot />\n </ComboboxGroup>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxInputProps & {\n class?: HTMLAttributes['class']\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxInput\n v-bind=\"forwardedProps\"\n :class=\"cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)\"\n >\n <slot />\n </ComboboxInput>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxItem, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()\nconst emits = defineEmits<ComboboxItemEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxItem\n v-bind=\"forwarded\"\n :class=\"cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)\"\n >\n <slot />\n </ComboboxItem>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {\n position: 'popper',\n align: 'center',\n sideOffset: 4,\n})\nconst emits = defineEmits<ComboboxContentEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxPortal>\n <ComboboxContent\n v-bind=\"forwarded\"\n :class=\"cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)\"\n >\n <ComboboxViewport>\n <slot />\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxSeparatorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxSeparator } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxSeparator\n v-bind=\"delegatedProps\"\n :class=\"cn('-mx-1 h-px bg-border', props.class)\"\n >\n <slot />\n </ComboboxSeparator>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxTriggerProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxTrigger, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxTrigger\n v-bind=\"forwarded\"\n :class=\"cn('', props.class)\"\n tabindex=\"0\"\n >\n <slot />\n </ComboboxTrigger>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"content": "export { default as Combobox } from './Combobox.vue'\nexport { default as ComboboxAnchor } from './ComboboxAnchor.vue'\nexport { default as ComboboxEmpty } from './ComboboxEmpty.vue'\nexport { default as ComboboxGroup } from './ComboboxGroup.vue'\nexport { default as ComboboxInput } from './ComboboxInput.vue'\nexport { default as ComboboxItem } from './ComboboxItem.vue'\nexport { default as ComboboxList } from './ComboboxList.vue'\nexport { default as ComboboxSeparator } from './ComboboxSeparator.vue'\n\nexport { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1046,6 +1046,78 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'\n\nconst props = defineProps<ComboboxRootProps>()\nconst emits = defineEmits<ComboboxRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <ComboboxRoot v-bind=\"forwarded\">\n <slot />\n </ComboboxRoot>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxAnchorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxAnchor, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxAnchor\n v-bind=\"forwarded\"\n :class=\"cn('w-[200px]', props.class)\"\n >\n <slot />\n </ComboboxAnchor>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxEmptyProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxEmpty } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxEmpty v-bind=\"delegatedProps\" :class=\"cn('py-6 text-center text-sm', props.class)\">\n <slot />\n </ComboboxEmpty>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxGroupProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxGroup, ComboboxLabel } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxGroupProps & {\n class?: HTMLAttributes['class']\n heading?: string\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxGroup\n v-bind=\"delegatedProps\"\n :class=\"cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)\"\n >\n <ComboboxLabel v-if=\"heading\" class=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {{ heading }}\n </ComboboxLabel>\n <slot />\n </ComboboxGroup>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxInputProps & {\n class?: HTMLAttributes['class']\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxInput\n v-bind=\"forwardedProps\"\n :class=\"cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)\"\n >\n <slot />\n </ComboboxInput>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxItem, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()\nconst emits = defineEmits<ComboboxItemEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxItem\n v-bind=\"forwarded\"\n :class=\"cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)\"\n >\n <slot />\n </ComboboxItem>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {\n position: 'popper',\n align: 'center',\n sideOffset: 4,\n})\nconst emits = defineEmits<ComboboxContentEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxPortal>\n <ComboboxContent\n v-bind=\"forwarded\"\n :class=\"cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)\"\n >\n <ComboboxViewport>\n <slot />\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxSeparatorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxSeparator } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxSeparator\n v-bind=\"delegatedProps\"\n :class=\"cn('-mx-1 h-px bg-border', props.class)\"\n >\n <slot />\n </ComboboxSeparator>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxTriggerProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxTrigger, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxTrigger\n v-bind=\"forwarded\"\n :class=\"cn('', props.class)\"\n tabindex=\"0\"\n >\n <slot />\n </ComboboxTrigger>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"content": "export { default as Combobox } from './Combobox.vue'\nexport { default as ComboboxAnchor } from './ComboboxAnchor.vue'\nexport { default as ComboboxEmpty } from './ComboboxEmpty.vue'\nexport { default as ComboboxGroup } from './ComboboxGroup.vue'\nexport { default as ComboboxInput } from './ComboboxInput.vue'\nexport { default as ComboboxItem } from './ComboboxItem.vue'\nexport { default as ComboboxList } from './ComboboxList.vue'\nexport { default as ComboboxSeparator } from './ComboboxSeparator.vue'\n\nexport { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "command",
|
"name": "command",
|
||||||
"type": "registry:ui",
|
"type": "registry:ui",
|
||||||
|
|
@ -4108,14 +4180,12 @@
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"combobox"
|
||||||
"command",
|
|
||||||
"popover"
|
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxDemo.vue",
|
"path": "example/ComboboxDemo.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst open = ref(false)\nconst value = ref('')\n</script>\n\n<template>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n class=\"w-[200px] justify-between\"\n >\n {{ value\n ? frameworks.find((framework) => framework.value === value)?.label\n : \"Select framework...\" }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput class=\"h-9\" placeholder=\"Search framework...\" />\n <CommandEmpty>No framework found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework.value\"\n @select=\"(ev) => {\n if (typeof ev.detail.value === 'string') {\n value = ev.detail.value\n }\n open = false\n }\"\n >\n {{ framework.label }}\n <Check\n :class=\"cn(\n 'ml-auto h-4 w-4',\n value === framework.value ? 'opacity-100' : 'opacity-0',\n )\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/new-york/ui/combobox'\nimport { Check, Search } from 'lucide-vue-next'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n</script>\n\n<template>\n <Combobox by=\"label\">\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9\" :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n </ComboboxAnchor>\n\n <ComboboxList>\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
@ -4150,15 +4220,14 @@
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"button",
|
||||||
"command",
|
"combobox",
|
||||||
"form",
|
"form",
|
||||||
"popover",
|
|
||||||
"toast"
|
"toast"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxForm.vue",
|
"path": "example/ComboboxForm.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n\n <Combobox by=\"label\">\n <FormControl>\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <ComboboxTrigger class=\"absolute end-0 inset-y-0 flex items-center justify-center px-3\">\n <ChevronsUpDown class=\"size-4 text-muted-foreground\" />\n </ComboboxTrigger>\n </div>\n </ComboboxAnchor>\n </FormControl>\n\n <ComboboxList>\n <ComboboxEmpty>\n Nothing found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
@ -4203,6 +4272,24 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ComboboxTrigger",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"combobox"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst value = ref<typeof frameworks[0]>()\n</script>\n\n<template>\n <Combobox v-model=\"value\" by=\"label\">\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button variant=\"outline\" class=\"justify-between\">\n {{ value?.label ?? 'Select framework' }}\n\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "CommandDemo",
|
"name": "CommandDemo",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
|
|
@ -4237,6 +4324,88 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandDropdownMenu",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"dropdown-menu"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandDropdownMenu.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@/registry/new-york/ui/dropdown-menu'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst labels = [\n 'feature',\n 'bug',\n 'enhancement',\n 'documentation',\n 'design',\n 'question',\n 'maintenance',\n]\n\nconst labelRef = ref('feature')\nconst open = ref(false)\n</script>\n\n<template>\n <div class=\"flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center\">\n <p class=\"text-sm font-medium leading-none\">\n <span class=\"mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground\">\n {{ labelRef }}\n </span>\n <span class=\"text-muted-foreground\">Create a new project</span>\n </p>\n <DropdownMenu v-model:open=\"open\">\n <DropdownMenuTrigger as-child>\n <Button variant=\"ghost\" size=\"sm\">\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" class=\"w-[200px]\">\n <DropdownMenuLabel>Actions</DropdownMenuLabel>\n <DropdownMenuGroup>\n <DropdownMenuItem>\n Assign to...\n </DropdownMenuItem>\n <DropdownMenuItem>\n Set due date...\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n Apply label\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent class=\"p-0\">\n <Command>\n <CommandInput\n placeholder=\"Filter label...\"\n auto-focus\n />\n <CommandList>\n <CommandEmpty>No label found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"label in labels\"\n :key=\"label\"\n :value=\"label\"\n @select=\"(ev) => {\n labelRef = ev.detail.value as string\n open = false\n }\"\n >\n {{ label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n <DropdownMenuSeparator />\n <DropdownMenuItem class=\"text-red-600\">\n Delete\n <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandForm",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"vee-validate",
|
||||||
|
"@vee-validate/zod",
|
||||||
|
"zod"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"form",
|
||||||
|
"popover",
|
||||||
|
"toast"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandForm.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/new-york/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { toast } from '@/registry/new-york/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandPopover",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandPopover.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/new-york/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/new-york/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/new-york/ui/popover'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst open = ref(false)\nconst selectedStatus = ref<Status>()\n</script>\n\n<template>\n <div class=\"flex items-center space-x-4\">\n <p class=\"text-sm text-muted-foreground\">\n Status\n </p>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n size=\"sm\"\n class=\"w-[150px] justify-start\"\n >\n <template v-if=\"selectedStatus\">\n {{ selectedStatus?.label }}\n </template>\n <template v-else>\n + Set status\n </template>\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"p-0\" side=\"right\" align=\"start\">\n <Command>\n <CommandInput placeholder=\"Change status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status in statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"() => {\n selectedStatus = status\n open = false\n }\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandResponsive",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"@vueuse/core"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"drawer",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandResponsive.vue",
|
||||||
|
"content": "<script lang=\"ts\" setup>\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/new-york/ui/command'\nimport { Drawer, DrawerContent, DrawerTrigger } from '@/registry/new-york/ui/drawer'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/registry/new-york/ui/popover'\nimport { createReusableTemplate, useMediaQuery } from '@vueuse/core'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst [UseTemplate, StatusList] = createReusableTemplate()\nconst isDesktop = useMediaQuery('(min-width: 768px)')\n\nconst isOpen = ref(false)\nconst selectedStatus = ref<Status | null>(null)\n\nfunction onStatusSelect(status: Status) {\n selectedStatus.value = status\n isOpen.value = false\n}\n</script>\n\n<template>\n <div>\n <UseTemplate>\n <Command>\n <CommandInput placeholder=\"Filter status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status of statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"onStatusSelect(status)\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </UseTemplate>\n\n <Popover v-if=\"isDesktop\" v-model:open=\"isOpen\">\n <PopoverTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\" align=\"start\">\n <StatusList />\n </PopoverContent>\n </Popover>\n\n <Drawer v-else v-model:open=\"isOpen\">\n <DrawerTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </DrawerTrigger>\n <DrawerContent>\n <div class=\"mt-4 border-t\">\n <StatusList />\n </div>\n </DrawerContent>\n </Drawer>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ContextMenuDemo",
|
"name": "ContextMenuDemo",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
|
|
@ -8339,6 +8508,78 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "combobox",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"dependencies": [
|
||||||
|
"reka-ui"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/Combobox.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'\n\nconst props = defineProps<ComboboxRootProps>()\nconst emits = defineEmits<ComboboxRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <ComboboxRoot v-bind=\"forwarded\">\n <slot />\n </ComboboxRoot>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxAnchor.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxAnchorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxAnchor, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxAnchor\n v-bind=\"forwarded\"\n :class=\"cn('w-[200px]', props.class)\"\n >\n <slot />\n </ComboboxAnchor>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxEmpty.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxEmptyProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxEmpty } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxEmpty v-bind=\"delegatedProps\" :class=\"cn('py-6 text-center text-sm', props.class)\">\n <slot />\n </ComboboxEmpty>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxGroup.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxGroupProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxGroup, ComboboxLabel } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxGroupProps & {\n class?: HTMLAttributes['class']\n heading?: string\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxGroup\n v-bind=\"delegatedProps\"\n :class=\"cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)\"\n >\n <ComboboxLabel v-if=\"heading\" class=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {{ heading }}\n </ComboboxLabel>\n <slot />\n </ComboboxGroup>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxInput.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxInputProps & {\n class?: HTMLAttributes['class']\n}>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxInput\n v-bind=\"forwardedProps\"\n :class=\"cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)\"\n >\n <slot />\n </ComboboxInput>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxItem.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxItem, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()\nconst emits = defineEmits<ComboboxItemEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxItem\n v-bind=\"forwarded\"\n :class=\"cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)\"\n >\n <slot />\n </ComboboxItem>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxList.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {\n position: 'popper',\n align: 'center',\n sideOffset: 4,\n})\nconst emits = defineEmits<ComboboxContentEmits>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <ComboboxPortal>\n <ComboboxContent\n v-bind=\"forwarded\"\n :class=\"cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)\"\n >\n <ComboboxViewport>\n <slot />\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxSeparator.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxSeparatorProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxSeparator } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <ComboboxSeparator\n v-bind=\"delegatedProps\"\n :class=\"cn('-mx-1 h-px bg-border', props.class)\"\n >\n <slot />\n </ComboboxSeparator>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport type { ComboboxTriggerProps } from 'reka-ui'\nimport { cn } from '@/lib/utils'\nimport { ComboboxTrigger, useForwardProps } from 'reka-ui'\nimport { computed, type HTMLAttributes } from 'vue'\n\nconst props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwarded = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <ComboboxTrigger\n v-bind=\"forwarded\"\n :class=\"cn('', props.class)\"\n tabindex=\"0\"\n >\n <slot />\n </ComboboxTrigger>\n</template>\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "ui/combobox/index.ts",
|
||||||
|
"content": "export { default as Combobox } from './Combobox.vue'\nexport { default as ComboboxAnchor } from './ComboboxAnchor.vue'\nexport { default as ComboboxEmpty } from './ComboboxEmpty.vue'\nexport { default as ComboboxGroup } from './ComboboxGroup.vue'\nexport { default as ComboboxInput } from './ComboboxInput.vue'\nexport { default as ComboboxItem } from './ComboboxItem.vue'\nexport { default as ComboboxList } from './ComboboxList.vue'\nexport { default as ComboboxSeparator } from './ComboboxSeparator.vue'\n\nexport { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'\n",
|
||||||
|
"type": "registry:ui",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "command",
|
"name": "command",
|
||||||
"type": "registry:ui",
|
"type": "registry:ui",
|
||||||
|
|
@ -11401,14 +11642,12 @@
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"combobox"
|
||||||
"command",
|
|
||||||
"popover"
|
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxDemo.vue",
|
"path": "example/ComboboxDemo.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst open = ref(false)\nconst value = ref('')\n</script>\n\n<template>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n class=\"w-[200px] justify-between\"\n >\n {{ value\n ? frameworks.find((framework) => framework.value === value)?.label\n : \"Select framework...\" }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput class=\"h-9\" placeholder=\"Search framework...\" />\n <CommandEmpty>No framework found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework.value\"\n @select=\"(ev) => {\n if (typeof ev.detail.value === 'string') {\n value = ev.detail.value\n }\n open = false\n }\"\n >\n {{ framework.label }}\n <Check\n :class=\"cn(\n 'ml-auto h-4 w-4',\n value === framework.value ? 'opacity-100' : 'opacity-0',\n )\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/default/ui/combobox'\nimport { Check, Search } from 'lucide-vue-next'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n</script>\n\n<template>\n <Combobox by=\"label\">\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9\" :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n </ComboboxAnchor>\n\n <ComboboxList>\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
@ -11443,15 +11682,14 @@
|
||||||
"registryDependencies": [
|
"registryDependencies": [
|
||||||
"utils",
|
"utils",
|
||||||
"button",
|
"button",
|
||||||
"command",
|
"combobox",
|
||||||
"form",
|
"form",
|
||||||
"popover",
|
|
||||||
"toast"
|
"toast"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": "example/ComboboxForm.vue",
|
"path": "example/ComboboxForm.vue",
|
||||||
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n]\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n <Check\n :class=\"cn('mr-2 h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n {{ language.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'\n\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n\n <Combobox by=\"label\">\n <FormControl>\n <ComboboxAnchor>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :display-value=\"(val) => val?.label ?? ''\" placeholder=\"Select framework...\" />\n <ComboboxTrigger class=\"absolute end-0 inset-y-0 flex items-center justify-center px-3\">\n <ChevronsUpDown class=\"size-4 text-muted-foreground\" />\n </ComboboxTrigger>\n </div>\n </ComboboxAnchor>\n </FormControl>\n\n <ComboboxList>\n <ComboboxEmpty>\n Nothing found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
"target": ""
|
"target": ""
|
||||||
}
|
}
|
||||||
|
|
@ -11497,6 +11735,24 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ComboboxTrigger",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"combobox"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/ComboboxTrigger.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst frameworks = [\n { value: 'next.js', label: 'Next.js' },\n { value: 'sveltekit', label: 'SvelteKit' },\n { value: 'nuxt', label: 'Nuxt' },\n { value: 'remix', label: 'Remix' },\n { value: 'astro', label: 'Astro' },\n]\n\nconst value = ref<typeof frameworks[0]>()\n</script>\n\n<template>\n <Combobox v-model=\"value\" by=\"label\">\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button variant=\"outline\" class=\"justify-between\">\n {{ value?.label ?? 'Select framework' }}\n\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput class=\"pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10\" placeholder=\"Select framework...\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-3\">\n <Search class=\"size-4 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n No framework found.\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"framework in frameworks\"\n :key=\"framework.value\"\n :value=\"framework\"\n >\n {{ framework.label }}\n\n <ComboboxItemIndicator>\n <Check :class=\"cn('ml-auto h-4 w-4')\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "CommandDemo",
|
"name": "CommandDemo",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
|
|
@ -11531,6 +11787,88 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandDropdownMenu",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"dropdown-menu"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandDropdownMenu.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@/registry/default/ui/dropdown-menu'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { ref } from 'vue'\n\nconst labels = [\n 'feature',\n 'bug',\n 'enhancement',\n 'documentation',\n 'design',\n 'question',\n 'maintenance',\n]\n\nconst labelRef = ref('feature')\nconst open = ref(false)\n</script>\n\n<template>\n <div class=\"flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center\">\n <p class=\"text-sm font-medium leading-none\">\n <span class=\"mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground\">\n {{ labelRef }}\n </span>\n <span class=\"text-muted-foreground\">Create a new project</span>\n </p>\n <DropdownMenu v-model:open=\"open\">\n <DropdownMenuTrigger as-child>\n <Button variant=\"ghost\" size=\"sm\">\n <MoreHorizontal />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" class=\"w-[200px]\">\n <DropdownMenuLabel>Actions</DropdownMenuLabel>\n <DropdownMenuGroup>\n <DropdownMenuItem>\n Assign to...\n </DropdownMenuItem>\n <DropdownMenuItem>\n Set due date...\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n Apply label\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent class=\"p-0\">\n <Command>\n <CommandInput\n placeholder=\"Filter label...\"\n auto-focus\n />\n <CommandList>\n <CommandEmpty>No label found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"label in labels\"\n :key=\"label\"\n :value=\"label\"\n @select=\"(ev) => {\n labelRef = ev.detail.value as string\n open = false\n }\"\n >\n {{ label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n <DropdownMenuSeparator />\n <DropdownMenuItem class=\"text-red-600\">\n Delete\n <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandForm",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"vee-validate",
|
||||||
|
"@vee-validate/zod",
|
||||||
|
"zod"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"utils",
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"form",
|
||||||
|
"popover",
|
||||||
|
"toast"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandForm.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/registry/default/ui/button'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@/registry/default/ui/form'\n\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, ChevronsUpDown } from 'lucide-vue-next'\nimport { useForm } from 'vee-validate'\nimport { h } from 'vue'\nimport * as z from 'zod'\n\nconst languages = [\n { label: 'English', value: 'en' },\n { label: 'French', value: 'fr' },\n { label: 'German', value: 'de' },\n { label: 'Spanish', value: 'es' },\n { label: 'Portuguese', value: 'pt' },\n { label: 'Russian', value: 'ru' },\n { label: 'Japanese', value: 'ja' },\n { label: 'Korean', value: 'ko' },\n { label: 'Chinese', value: 'zh' },\n] as const\n\nconst formSchema = toTypedSchema(z.object({\n language: z.string({\n required_error: 'Please select a language.',\n }),\n}))\n\nconst { handleSubmit, setFieldValue, values } = useForm({\n validationSchema: formSchema,\n initialValues: {\n language: '',\n },\n})\n\nconst onSubmit = handleSubmit((values) => {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n})\n</script>\n\n<template>\n <form class=\"space-y-6\" @submit=\"onSubmit\">\n <FormField name=\"language\">\n <FormItem class=\"flex flex-col\">\n <FormLabel>Language</FormLabel>\n <Popover>\n <PopoverTrigger as-child>\n <FormControl>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n :class=\"cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')\"\n >\n {{ values.language ? languages.find(\n (language) => language.value === values.language,\n )?.label : 'Select language...' }}\n <ChevronsUpDown class=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </FormControl>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\">\n <Command>\n <CommandInput placeholder=\"Search language...\" />\n <CommandEmpty>Nothing found.</CommandEmpty>\n <CommandList>\n <CommandGroup>\n <CommandItem\n v-for=\"language in languages\"\n :key=\"language.value\"\n :value=\"language.label\"\n @select=\"() => {\n setFieldValue('language', language.value)\n }\"\n >\n {{ language.label }}\n <Check\n :class=\"cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')\"\n />\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n <FormDescription>\n This is the language that will be used in the dashboard.\n </FormDescription>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <Button type=\"submit\">\n Submit\n </Button>\n </form>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandPopover",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandPopover.vue",
|
||||||
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/default/ui/button'\n\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/registry/default/ui/command'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@/registry/default/ui/popover'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst open = ref(false)\nconst selectedStatus = ref<Status>()\n</script>\n\n<template>\n <div class=\"flex items-center space-x-4\">\n <p class=\"text-sm text-muted-foreground\">\n Status\n </p>\n <Popover v-model:open=\"open\">\n <PopoverTrigger as-child>\n <Button\n variant=\"outline\"\n size=\"sm\"\n class=\"w-[150px] justify-start\"\n >\n <template v-if=\"selectedStatus\">\n {{ selectedStatus?.label }}\n </template>\n <template v-else>\n + Set status\n </template>\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"p-0\" side=\"right\" align=\"start\">\n <Command>\n <CommandInput placeholder=\"Change status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status in statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"() => {\n selectedStatus = status\n open = false\n }\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CommandResponsive",
|
||||||
|
"type": "registry:example",
|
||||||
|
"dependencies": [
|
||||||
|
"@vueuse/core"
|
||||||
|
],
|
||||||
|
"registryDependencies": [
|
||||||
|
"button",
|
||||||
|
"command",
|
||||||
|
"drawer",
|
||||||
|
"popover"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "example/CommandResponsive.vue",
|
||||||
|
"content": "<script lang=\"ts\" setup>\nimport { Button } from '@/registry/default/ui/button'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/default/ui/command'\nimport { Drawer, DrawerContent, DrawerTrigger } from '@/registry/default/ui/drawer'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/registry/default/ui/popover'\nimport { createReusableTemplate, useMediaQuery } from '@vueuse/core'\nimport { ref } from 'vue'\n\ninterface Status {\n value: string\n label: string\n}\n\nconst statuses: Status[] = [\n {\n value: 'backlog',\n label: 'Backlog',\n },\n {\n value: 'todo',\n label: 'Todo',\n },\n {\n value: 'in progress',\n label: 'In Progress',\n },\n {\n value: 'done',\n label: 'Done',\n },\n {\n value: 'canceled',\n label: 'Canceled',\n },\n]\n\nconst [UseTemplate, StatusList] = createReusableTemplate()\nconst isDesktop = useMediaQuery('(min-width: 768px)')\n\nconst isOpen = ref(false)\nconst selectedStatus = ref<Status | null>(null)\n\nfunction onStatusSelect(status: Status) {\n selectedStatus.value = status\n isOpen.value = false\n}\n</script>\n\n<template>\n <div>\n <UseTemplate>\n <Command>\n <CommandInput placeholder=\"Filter status...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup>\n <CommandItem\n v-for=\"status of statuses\"\n :key=\"status.value\"\n :value=\"status.value\"\n @select=\"onStatusSelect(status)\"\n >\n {{ status.label }}\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </UseTemplate>\n\n <Popover v-if=\"isDesktop\" v-model:open=\"isOpen\">\n <PopoverTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </PopoverTrigger>\n <PopoverContent class=\"w-[200px] p-0\" align=\"start\">\n <StatusList />\n </PopoverContent>\n </Popover>\n\n <Drawer v-else :open=\"isOpen\" @update:open=\"(newOpenValue) => isOpen = newOpenValue\">\n <DrawerTrigger as-child>\n <Button variant=\"outline\" class=\"w-[150px] justify-start\">\n {{ selectedStatus ? selectedStatus.label : \"+ Set status\" }}\n </Button>\n </DrawerTrigger>\n <DrawerContent>\n <div class=\"mt-4 border-t\">\n <StatusList />\n </div>\n </DrawerContent>\n </Drawer>\n </div>\n</template>\n",
|
||||||
|
"type": "registry:example",
|
||||||
|
"target": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ContextMenuDemo",
|
"name": "ContextMenuDemo",
|
||||||
"type": "registry:example",
|
"type": "registry:example",
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { Button } from '@/registry/default/ui/button'
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/default/ui/combobox'
|
||||||
|
import { Check, Search } from 'lucide-vue-next'
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/registry/default/ui/command'
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/registry/default/ui/popover'
|
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const frameworks = [
|
const frameworks = [
|
||||||
{ value: 'next.js', label: 'Next.js' },
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
|
@ -25,54 +10,37 @@ const frameworks = [
|
||||||
{ value: 'remix', label: 'Remix' },
|
{ value: 'remix', label: 'Remix' },
|
||||||
{ value: 'astro', label: 'Astro' },
|
{ value: 'astro', label: 'Astro' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const open = ref(false)
|
|
||||||
const value = ref('')
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="open">
|
<Combobox by="label">
|
||||||
<PopoverTrigger as-child>
|
<ComboboxAnchor>
|
||||||
<Button
|
<div class="relative w-full max-w-sm items-center">
|
||||||
variant="outline"
|
<ComboboxInput class="pl-9" :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||||
role="combobox"
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
:aria-expanded="open"
|
<Search class="size-4 text-muted-foreground" />
|
||||||
class="w-[200px] justify-between"
|
</span>
|
||||||
>
|
</div>
|
||||||
{{ value
|
</ComboboxAnchor>
|
||||||
? frameworks.find((framework) => framework.value === value)?.label
|
|
||||||
: "Select framework..." }}
|
<ComboboxList>
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<ComboboxEmpty>
|
||||||
</Button>
|
No framework found.
|
||||||
</PopoverTrigger>
|
</ComboboxEmpty>
|
||||||
<PopoverContent class="w-[200px] p-0">
|
|
||||||
<Command>
|
<ComboboxGroup>
|
||||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
<ComboboxItem
|
||||||
<CommandEmpty>No framework found.</CommandEmpty>
|
v-for="framework in frameworks"
|
||||||
<CommandList>
|
:key="framework.value"
|
||||||
<CommandGroup>
|
:value="framework"
|
||||||
<CommandItem
|
>
|
||||||
v-for="framework in frameworks"
|
{{ framework.label }}
|
||||||
:key="framework.value"
|
|
||||||
:value="framework.value"
|
<ComboboxItemIndicator>
|
||||||
@select="(ev) => {
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
if (typeof ev.detail.value === 'string') {
|
</ComboboxItemIndicator>
|
||||||
value = ev.detail.value
|
</ComboboxItem>
|
||||||
}
|
</ComboboxGroup>
|
||||||
open = false
|
</ComboboxList>
|
||||||
}"
|
</Combobox>
|
||||||
>
|
|
||||||
{{ framework.label }}
|
|
||||||
<Check
|
|
||||||
:class="cn(
|
|
||||||
'ml-auto h-4 w-4',
|
|
||||||
value === framework.value ? 'opacity-100' : 'opacity-0',
|
|
||||||
)"
|
|
||||||
/>
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { Button } from '@/registry/default/ui/button'
|
import { Button } from '@/registry/default/ui/button'
|
||||||
import {
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/registry/default/ui/command'
|
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormDescription,
|
FormDescription,
|
||||||
|
|
@ -18,11 +12,6 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/registry/default/ui/form'
|
} from '@/registry/default/ui/form'
|
||||||
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/registry/default/ui/popover'
|
|
||||||
import { toast } from '@/registry/default/ui/toast'
|
import { toast } from '@/registry/default/ui/toast'
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||||
|
|
@ -40,7 +29,7 @@ const languages = [
|
||||||
{ label: 'Japanese', value: 'ja' },
|
{ label: 'Japanese', value: 'ja' },
|
||||||
{ label: 'Korean', value: 'ko' },
|
{ label: 'Korean', value: 'ko' },
|
||||||
{ label: 'Chinese', value: 'zh' },
|
{ label: 'Chinese', value: 'zh' },
|
||||||
]
|
] as const
|
||||||
|
|
||||||
const formSchema = toTypedSchema(z.object({
|
const formSchema = toTypedSchema(z.object({
|
||||||
language: z.string({
|
language: z.string({
|
||||||
|
|
@ -48,8 +37,11 @@ const formSchema = toTypedSchema(z.object({
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const { handleSubmit, setFieldValue, values } = useForm({
|
const { handleSubmit, setFieldValue } = useForm({
|
||||||
validationSchema: formSchema,
|
validationSchema: formSchema,
|
||||||
|
initialValues: {
|
||||||
|
language: '',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSubmit = handleSubmit((values) => {
|
const onSubmit = handleSubmit((values) => {
|
||||||
|
|
@ -65,45 +57,43 @@ const onSubmit = handleSubmit((values) => {
|
||||||
<FormField name="language">
|
<FormField name="language">
|
||||||
<FormItem class="flex flex-col">
|
<FormItem class="flex flex-col">
|
||||||
<FormLabel>Language</FormLabel>
|
<FormLabel>Language</FormLabel>
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger as-child>
|
<Combobox by="label">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Button
|
<ComboboxAnchor>
|
||||||
variant="outline"
|
<div class="relative w-full max-w-sm items-center">
|
||||||
role="combobox"
|
<ComboboxInput :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||||
:class="cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')"
|
<ComboboxTrigger class="absolute end-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
|
<ChevronsUpDown class="size-4 text-muted-foreground" />
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</div>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<ComboboxList>
|
||||||
|
<ComboboxEmpty>
|
||||||
|
Nothing found.
|
||||||
|
</ComboboxEmpty>
|
||||||
|
|
||||||
|
<ComboboxGroup>
|
||||||
|
<ComboboxItem
|
||||||
|
v-for="language in languages"
|
||||||
|
:key="language.value"
|
||||||
|
:value="language"
|
||||||
|
@select="() => {
|
||||||
|
setFieldValue('language', language.value)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
{{ values.language ? languages.find(
|
{{ language.label }}
|
||||||
(language) => language.value === values.language,
|
|
||||||
)?.label : 'Select language...' }}
|
<ComboboxItemIndicator>
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
</Button>
|
</ComboboxItemIndicator>
|
||||||
</FormControl>
|
</ComboboxItem>
|
||||||
</PopoverTrigger>
|
</ComboboxGroup>
|
||||||
<PopoverContent class="w-[200px] p-0">
|
</ComboboxList>
|
||||||
<Command>
|
</Combobox>
|
||||||
<CommandInput placeholder="Search language..." />
|
|
||||||
<CommandEmpty>Nothing found.</CommandEmpty>
|
|
||||||
<CommandList>
|
|
||||||
<CommandGroup>
|
|
||||||
<CommandItem
|
|
||||||
v-for="language in languages"
|
|
||||||
:key="language.value"
|
|
||||||
:value="language.label"
|
|
||||||
@select="() => {
|
|
||||||
setFieldValue('language', language.value)
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<Check
|
|
||||||
:class="cn('mr-2 h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')"
|
|
||||||
/>
|
|
||||||
{{ language.label }}
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
This is the language that will be used in the dashboard.
|
This is the language that will be used in the dashboard.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
|
|
|
||||||
58
apps/www/src/registry/default/example/ComboboxTrigger.vue
Normal file
58
apps/www/src/registry/default/example/ComboboxTrigger.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/registry/default/ui/button'
|
||||||
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'
|
||||||
|
import { Check, ChevronsUpDown, Search } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const frameworks = [
|
||||||
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
{ value: 'sveltekit', label: 'SvelteKit' },
|
||||||
|
{ value: 'nuxt', label: 'Nuxt' },
|
||||||
|
{ value: 'remix', label: 'Remix' },
|
||||||
|
{ value: 'astro', label: 'Astro' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const value = ref<typeof frameworks[0]>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Combobox v-model="value" by="label">
|
||||||
|
<ComboboxAnchor as-child>
|
||||||
|
<ComboboxTrigger as-child>
|
||||||
|
<Button variant="outline" class="justify-between">
|
||||||
|
{{ value?.label ?? 'Select framework' }}
|
||||||
|
|
||||||
|
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
|
||||||
|
<ComboboxList>
|
||||||
|
<div class="relative w-full max-w-sm items-center">
|
||||||
|
<ComboboxInput class="pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10" placeholder="Select framework..." />
|
||||||
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
|
<Search class="size-4 text-muted-foreground" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ComboboxEmpty>
|
||||||
|
No framework found.
|
||||||
|
</ComboboxEmpty>
|
||||||
|
|
||||||
|
<ComboboxGroup>
|
||||||
|
<ComboboxItem
|
||||||
|
v-for="framework in frameworks"
|
||||||
|
:key="framework.value"
|
||||||
|
:value="framework"
|
||||||
|
>
|
||||||
|
{{ framework.label }}
|
||||||
|
|
||||||
|
<ComboboxItemIndicator>
|
||||||
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
|
</ComboboxItemIndicator>
|
||||||
|
</ComboboxItem>
|
||||||
|
</ComboboxGroup>
|
||||||
|
</ComboboxList>
|
||||||
|
</Combobox>
|
||||||
|
</template>
|
||||||
104
apps/www/src/registry/default/example/CommandDropdownMenu.vue
Normal file
104
apps/www/src/registry/default/example/CommandDropdownMenu.vue
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/registry/default/ui/button'
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/default/ui/command'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuShortcut,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/registry/default/ui/dropdown-menu'
|
||||||
|
import { MoreHorizontal } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const labels = [
|
||||||
|
'feature',
|
||||||
|
'bug',
|
||||||
|
'enhancement',
|
||||||
|
'documentation',
|
||||||
|
'design',
|
||||||
|
'question',
|
||||||
|
'maintenance',
|
||||||
|
]
|
||||||
|
|
||||||
|
const labelRef = ref('feature')
|
||||||
|
const open = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
|
||||||
|
<p class="text-sm font-medium leading-none">
|
||||||
|
<span class="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||||
|
{{ labelRef }}
|
||||||
|
</span>
|
||||||
|
<span class="text-muted-foreground">Create a new project</span>
|
||||||
|
</p>
|
||||||
|
<DropdownMenu v-model:open="open">
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<Button variant="ghost" size="sm">
|
||||||
|
<MoreHorizontal />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" class="w-[200px]">
|
||||||
|
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
Assign to...
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
Set due date...
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuSub>
|
||||||
|
<DropdownMenuSubTrigger>
|
||||||
|
Apply label
|
||||||
|
</DropdownMenuSubTrigger>
|
||||||
|
<DropdownMenuSubContent class="p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput
|
||||||
|
placeholder="Filter label..."
|
||||||
|
auto-focus
|
||||||
|
/>
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No label found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="label in labels"
|
||||||
|
:key="label"
|
||||||
|
:value="label"
|
||||||
|
@select="(ev) => {
|
||||||
|
labelRef = ev.detail.value as string
|
||||||
|
open = false
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuSub>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem class="text-red-600">
|
||||||
|
Delete
|
||||||
|
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
121
apps/www/src/registry/default/example/CommandForm.vue
Normal file
121
apps/www/src/registry/default/example/CommandForm.vue
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/registry/default/ui/button'
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/default/ui/command'
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from '@/registry/default/ui/form'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/registry/default/ui/popover'
|
||||||
|
import { toast } from '@/registry/default/ui/toast'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import { h } from 'vue'
|
||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
const languages = [
|
||||||
|
{ label: 'English', value: 'en' },
|
||||||
|
{ label: 'French', value: 'fr' },
|
||||||
|
{ label: 'German', value: 'de' },
|
||||||
|
{ label: 'Spanish', value: 'es' },
|
||||||
|
{ label: 'Portuguese', value: 'pt' },
|
||||||
|
{ label: 'Russian', value: 'ru' },
|
||||||
|
{ label: 'Japanese', value: 'ja' },
|
||||||
|
{ label: 'Korean', value: 'ko' },
|
||||||
|
{ label: 'Chinese', value: 'zh' },
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(z.object({
|
||||||
|
language: z.string({
|
||||||
|
required_error: 'Please select a language.',
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { handleSubmit, setFieldValue, values } = useForm({
|
||||||
|
validationSchema: formSchema,
|
||||||
|
initialValues: {
|
||||||
|
language: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit((values) => {
|
||||||
|
toast({
|
||||||
|
title: 'You submitted the following values:',
|
||||||
|
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<form class="space-y-6" @submit="onSubmit">
|
||||||
|
<FormField name="language">
|
||||||
|
<FormItem class="flex flex-col">
|
||||||
|
<FormLabel>Language</FormLabel>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<FormControl>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
:class="cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')"
|
||||||
|
>
|
||||||
|
{{ values.language ? languages.find(
|
||||||
|
(language) => language.value === values.language,
|
||||||
|
)?.label : 'Select language...' }}
|
||||||
|
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</FormControl>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[200px] p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Search language..." />
|
||||||
|
<CommandEmpty>Nothing found.</CommandEmpty>
|
||||||
|
<CommandList>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="language in languages"
|
||||||
|
:key="language.value"
|
||||||
|
:value="language.label"
|
||||||
|
@select="() => {
|
||||||
|
setFieldValue('language', language.value)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ language.label }}
|
||||||
|
<Check
|
||||||
|
:class="cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')"
|
||||||
|
/>
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<FormDescription>
|
||||||
|
This is the language that will be used in the dashboard.
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<Button type="submit">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
94
apps/www/src/registry/default/example/CommandPopover.vue
Normal file
94
apps/www/src/registry/default/example/CommandPopover.vue
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/registry/default/ui/button'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/default/ui/command'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/registry/default/ui/popover'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Status {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const statuses: Status[] = [
|
||||||
|
{
|
||||||
|
value: 'backlog',
|
||||||
|
label: 'Backlog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'todo',
|
||||||
|
label: 'Todo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'in progress',
|
||||||
|
label: 'In Progress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'done',
|
||||||
|
label: 'Done',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'canceled',
|
||||||
|
label: 'Canceled',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
const selectedStatus = ref<Status>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
<p class="text-sm text-muted-foreground">
|
||||||
|
Status
|
||||||
|
</p>
|
||||||
|
<Popover v-model:open="open">
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
class="w-[150px] justify-start"
|
||||||
|
>
|
||||||
|
<template v-if="selectedStatus">
|
||||||
|
{{ selectedStatus?.label }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
+ Set status
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="p-0" side="right" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Change status..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="status in statuses"
|
||||||
|
:key="status.value"
|
||||||
|
:value="status.value"
|
||||||
|
@select="() => {
|
||||||
|
selectedStatus = status
|
||||||
|
open = false
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ status.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
94
apps/www/src/registry/default/example/CommandResponsive.vue
Normal file
94
apps/www/src/registry/default/example/CommandResponsive.vue
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Button } from '@/registry/default/ui/button'
|
||||||
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/default/ui/command'
|
||||||
|
import { Drawer, DrawerContent, DrawerTrigger } from '@/registry/default/ui/drawer'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/registry/default/ui/popover'
|
||||||
|
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Status {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const statuses: Status[] = [
|
||||||
|
{
|
||||||
|
value: 'backlog',
|
||||||
|
label: 'Backlog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'todo',
|
||||||
|
label: 'Todo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'in progress',
|
||||||
|
label: 'In Progress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'done',
|
||||||
|
label: 'Done',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'canceled',
|
||||||
|
label: 'Canceled',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const [UseTemplate, StatusList] = createReusableTemplate()
|
||||||
|
const isDesktop = useMediaQuery('(min-width: 768px)')
|
||||||
|
|
||||||
|
const isOpen = ref(false)
|
||||||
|
const selectedStatus = ref<Status | null>(null)
|
||||||
|
|
||||||
|
function onStatusSelect(status: Status) {
|
||||||
|
selectedStatus.value = status
|
||||||
|
isOpen.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<UseTemplate>
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Filter status..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="status of statuses"
|
||||||
|
:key="status.value"
|
||||||
|
:value="status.value"
|
||||||
|
@select="onStatusSelect(status)"
|
||||||
|
>
|
||||||
|
{{ status.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</UseTemplate>
|
||||||
|
|
||||||
|
<Popover v-if="isDesktop" v-model:open="isOpen">
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button variant="outline" class="w-[150px] justify-start">
|
||||||
|
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[200px] p-0" align="start">
|
||||||
|
<StatusList />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<Drawer v-else :open="isOpen" @update:open="(newOpenValue) => isOpen = newOpenValue">
|
||||||
|
<DrawerTrigger as-child>
|
||||||
|
<Button variant="outline" class="w-[150px] justify-start">
|
||||||
|
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
|
||||||
|
</Button>
|
||||||
|
</DrawerTrigger>
|
||||||
|
<DrawerContent>
|
||||||
|
<div class="mt-4 border-t">
|
||||||
|
<StatusList />
|
||||||
|
</div>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
14
apps/www/src/registry/default/ui/combobox/Combobox.vue
Normal file
14
apps/www/src/registry/default/ui/combobox/Combobox.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxRootProps>()
|
||||||
|
const emits = defineEmits<ComboboxRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxRoot v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</ComboboxRoot>
|
||||||
|
</template>
|
||||||
25
apps/www/src/registry/default/ui/combobox/ComboboxAnchor.vue
Normal file
25
apps/www/src/registry/default/ui/combobox/ComboboxAnchor.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxAnchorProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxAnchor, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxAnchor
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('w-[200px]', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxAnchor>
|
||||||
|
</template>
|
||||||
20
apps/www/src/registry/default/ui/combobox/ComboboxEmpty.vue
Normal file
20
apps/www/src/registry/default/ui/combobox/ComboboxEmpty.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxEmptyProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxEmpty } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxEmpty v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)">
|
||||||
|
<slot />
|
||||||
|
</ComboboxEmpty>
|
||||||
|
</template>
|
||||||
29
apps/www/src/registry/default/ui/combobox/ComboboxGroup.vue
Normal file
29
apps/www/src/registry/default/ui/combobox/ComboboxGroup.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxGroupProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxGroup, ComboboxLabel } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxGroupProps & {
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
heading?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxGroup
|
||||||
|
v-bind="delegatedProps"
|
||||||
|
:class="cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)"
|
||||||
|
>
|
||||||
|
<ComboboxLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
|
||||||
|
{{ heading }}
|
||||||
|
</ComboboxLabel>
|
||||||
|
<slot />
|
||||||
|
</ComboboxGroup>
|
||||||
|
</template>
|
||||||
26
apps/www/src/registry/default/ui/combobox/ComboboxInput.vue
Normal file
26
apps/www/src/registry/default/ui/combobox/ComboboxInput.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxInputProps & {
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxInput
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxInput>
|
||||||
|
</template>
|
||||||
26
apps/www/src/registry/default/ui/combobox/ComboboxItem.vue
Normal file
26
apps/www/src/registry/default/ui/combobox/ComboboxItem.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxItem, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
const emits = defineEmits<ComboboxItemEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxItem>
|
||||||
|
</template>
|
||||||
34
apps/www/src/registry/default/ui/combobox/ComboboxList.vue
Normal file
34
apps/www/src/registry/default/ui/combobox/ComboboxList.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {
|
||||||
|
position: 'popper',
|
||||||
|
align: 'center',
|
||||||
|
sideOffset: 4,
|
||||||
|
})
|
||||||
|
const emits = defineEmits<ComboboxContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxPortal>
|
||||||
|
<ComboboxContent
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)"
|
||||||
|
>
|
||||||
|
<ComboboxViewport>
|
||||||
|
<slot />
|
||||||
|
</ComboboxViewport>
|
||||||
|
</ComboboxContent>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxSeparatorProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxSeparator } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxSeparator
|
||||||
|
v-bind="delegatedProps"
|
||||||
|
:class="cn('-mx-1 h-px bg-border', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxSeparator>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxTriggerProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxTrigger, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxTrigger
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('', props.class)"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</template>
|
||||||
10
apps/www/src/registry/default/ui/combobox/index.ts
Normal file
10
apps/www/src/registry/default/ui/combobox/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export { default as Combobox } from './Combobox.vue'
|
||||||
|
export { default as ComboboxAnchor } from './ComboboxAnchor.vue'
|
||||||
|
export { default as ComboboxEmpty } from './ComboboxEmpty.vue'
|
||||||
|
export { default as ComboboxGroup } from './ComboboxGroup.vue'
|
||||||
|
export { default as ComboboxInput } from './ComboboxInput.vue'
|
||||||
|
export { default as ComboboxItem } from './ComboboxItem.vue'
|
||||||
|
export { default as ComboboxList } from './ComboboxList.vue'
|
||||||
|
export { default as ComboboxSeparator } from './ComboboxSeparator.vue'
|
||||||
|
|
||||||
|
export { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'
|
||||||
|
|
@ -1,22 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { Button } from '@/registry/new-york/ui/button'
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/new-york/ui/combobox'
|
||||||
|
import { Check, Search } from 'lucide-vue-next'
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/registry/new-york/ui/command'
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/registry/new-york/ui/popover'
|
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const frameworks = [
|
const frameworks = [
|
||||||
{ value: 'next.js', label: 'Next.js' },
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
|
@ -25,54 +10,37 @@ const frameworks = [
|
||||||
{ value: 'remix', label: 'Remix' },
|
{ value: 'remix', label: 'Remix' },
|
||||||
{ value: 'astro', label: 'Astro' },
|
{ value: 'astro', label: 'Astro' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const open = ref(false)
|
|
||||||
const value = ref('')
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="open">
|
<Combobox by="label">
|
||||||
<PopoverTrigger as-child>
|
<ComboboxAnchor>
|
||||||
<Button
|
<div class="relative w-full max-w-sm items-center">
|
||||||
variant="outline"
|
<ComboboxInput class="pl-9" :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||||
role="combobox"
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
:aria-expanded="open"
|
<Search class="size-4 text-muted-foreground" />
|
||||||
class="w-[200px] justify-between"
|
</span>
|
||||||
>
|
</div>
|
||||||
{{ value
|
</ComboboxAnchor>
|
||||||
? frameworks.find((framework) => framework.value === value)?.label
|
|
||||||
: "Select framework..." }}
|
<ComboboxList>
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<ComboboxEmpty>
|
||||||
</Button>
|
No framework found.
|
||||||
</PopoverTrigger>
|
</ComboboxEmpty>
|
||||||
<PopoverContent class="w-[200px] p-0">
|
|
||||||
<Command>
|
<ComboboxGroup>
|
||||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
<ComboboxItem
|
||||||
<CommandEmpty>No framework found.</CommandEmpty>
|
v-for="framework in frameworks"
|
||||||
<CommandList>
|
:key="framework.value"
|
||||||
<CommandGroup>
|
:value="framework"
|
||||||
<CommandItem
|
>
|
||||||
v-for="framework in frameworks"
|
{{ framework.label }}
|
||||||
:key="framework.value"
|
|
||||||
:value="framework.value"
|
<ComboboxItemIndicator>
|
||||||
@select="(ev) => {
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
if (typeof ev.detail.value === 'string') {
|
</ComboboxItemIndicator>
|
||||||
value = ev.detail.value
|
</ComboboxItem>
|
||||||
}
|
</ComboboxGroup>
|
||||||
open = false
|
</ComboboxList>
|
||||||
}"
|
</Combobox>
|
||||||
>
|
|
||||||
{{ framework.label }}
|
|
||||||
<Check
|
|
||||||
:class="cn(
|
|
||||||
'ml-auto h-4 w-4',
|
|
||||||
value === framework.value ? 'opacity-100' : 'opacity-0',
|
|
||||||
)"
|
|
||||||
/>
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { Button } from '@/registry/new-york/ui/button'
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
import {
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/registry/new-york/ui/command'
|
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormDescription,
|
FormDescription,
|
||||||
|
|
@ -18,11 +12,6 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/registry/new-york/ui/form'
|
} from '@/registry/new-york/ui/form'
|
||||||
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/registry/new-york/ui/popover'
|
|
||||||
import { toast } from '@/registry/new-york/ui/toast'
|
import { toast } from '@/registry/new-york/ui/toast'
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||||
|
|
@ -48,7 +37,7 @@ const formSchema = toTypedSchema(z.object({
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const { handleSubmit, setFieldValue, values } = useForm({
|
const { handleSubmit, setFieldValue } = useForm({
|
||||||
validationSchema: formSchema,
|
validationSchema: formSchema,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
language: '',
|
language: '',
|
||||||
|
|
@ -68,45 +57,43 @@ const onSubmit = handleSubmit((values) => {
|
||||||
<FormField name="language">
|
<FormField name="language">
|
||||||
<FormItem class="flex flex-col">
|
<FormItem class="flex flex-col">
|
||||||
<FormLabel>Language</FormLabel>
|
<FormLabel>Language</FormLabel>
|
||||||
<Popover>
|
|
||||||
<PopoverTrigger as-child>
|
<Combobox by="label">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Button
|
<ComboboxAnchor>
|
||||||
variant="outline"
|
<div class="relative w-full max-w-sm items-center">
|
||||||
role="combobox"
|
<ComboboxInput :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||||
:class="cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')"
|
<ComboboxTrigger class="absolute end-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
|
<ChevronsUpDown class="size-4 text-muted-foreground" />
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</div>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<ComboboxList>
|
||||||
|
<ComboboxEmpty>
|
||||||
|
Nothing found.
|
||||||
|
</ComboboxEmpty>
|
||||||
|
|
||||||
|
<ComboboxGroup>
|
||||||
|
<ComboboxItem
|
||||||
|
v-for="language in languages"
|
||||||
|
:key="language.value"
|
||||||
|
:value="language"
|
||||||
|
@select="() => {
|
||||||
|
setFieldValue('language', language.value)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
{{ values.language ? languages.find(
|
{{ language.label }}
|
||||||
(language) => language.value === values.language,
|
|
||||||
)?.label : 'Select language...' }}
|
<ComboboxItemIndicator>
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
</Button>
|
</ComboboxItemIndicator>
|
||||||
</FormControl>
|
</ComboboxItem>
|
||||||
</PopoverTrigger>
|
</ComboboxGroup>
|
||||||
<PopoverContent class="w-[200px] p-0">
|
</ComboboxList>
|
||||||
<Command>
|
</Combobox>
|
||||||
<CommandInput placeholder="Search language..." />
|
|
||||||
<CommandEmpty>Nothing found.</CommandEmpty>
|
|
||||||
<CommandList>
|
|
||||||
<CommandGroup>
|
|
||||||
<CommandItem
|
|
||||||
v-for="language in languages"
|
|
||||||
:key="language.value"
|
|
||||||
:value="language.label"
|
|
||||||
@select="() => {
|
|
||||||
setFieldValue('language', language.value)
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ language.label }}
|
|
||||||
<Check
|
|
||||||
:class="cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')"
|
|
||||||
/>
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
This is the language that will be used in the dashboard.
|
This is the language that will be used in the dashboard.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
|
|
|
||||||
58
apps/www/src/registry/new-york/example/ComboboxTrigger.vue
Normal file
58
apps/www/src/registry/new-york/example/ComboboxTrigger.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
|
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'
|
||||||
|
import { Check, ChevronsUpDown, Search } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const frameworks = [
|
||||||
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
{ value: 'sveltekit', label: 'SvelteKit' },
|
||||||
|
{ value: 'nuxt', label: 'Nuxt' },
|
||||||
|
{ value: 'remix', label: 'Remix' },
|
||||||
|
{ value: 'astro', label: 'Astro' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const value = ref<typeof frameworks[0]>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Combobox v-model="value" by="label">
|
||||||
|
<ComboboxAnchor as-child>
|
||||||
|
<ComboboxTrigger as-child>
|
||||||
|
<Button variant="outline" class="justify-between">
|
||||||
|
{{ value?.label ?? 'Select framework' }}
|
||||||
|
|
||||||
|
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
|
||||||
|
<ComboboxList>
|
||||||
|
<div class="relative w-full max-w-sm items-center">
|
||||||
|
<ComboboxInput class="pl-9 focus-visible:ring-0 border-0 border-b rounded-none h-10" placeholder="Select framework..." />
|
||||||
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-3">
|
||||||
|
<Search class="size-4 text-muted-foreground" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ComboboxEmpty>
|
||||||
|
No framework found.
|
||||||
|
</ComboboxEmpty>
|
||||||
|
|
||||||
|
<ComboboxGroup>
|
||||||
|
<ComboboxItem
|
||||||
|
v-for="framework in frameworks"
|
||||||
|
:key="framework.value"
|
||||||
|
:value="framework"
|
||||||
|
>
|
||||||
|
{{ framework.label }}
|
||||||
|
|
||||||
|
<ComboboxItemIndicator>
|
||||||
|
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||||
|
</ComboboxItemIndicator>
|
||||||
|
</ComboboxItem>
|
||||||
|
</ComboboxGroup>
|
||||||
|
</ComboboxList>
|
||||||
|
</Combobox>
|
||||||
|
</template>
|
||||||
104
apps/www/src/registry/new-york/example/CommandDropdownMenu.vue
Normal file
104
apps/www/src/registry/new-york/example/CommandDropdownMenu.vue
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/new-york/ui/command'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuGroup,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuShortcut,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/registry/new-york/ui/dropdown-menu'
|
||||||
|
import { MoreHorizontal } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const labels = [
|
||||||
|
'feature',
|
||||||
|
'bug',
|
||||||
|
'enhancement',
|
||||||
|
'documentation',
|
||||||
|
'design',
|
||||||
|
'question',
|
||||||
|
'maintenance',
|
||||||
|
]
|
||||||
|
|
||||||
|
const labelRef = ref('feature')
|
||||||
|
const open = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
|
||||||
|
<p class="text-sm font-medium leading-none">
|
||||||
|
<span class="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||||
|
{{ labelRef }}
|
||||||
|
</span>
|
||||||
|
<span class="text-muted-foreground">Create a new project</span>
|
||||||
|
</p>
|
||||||
|
<DropdownMenu v-model:open="open">
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<Button variant="ghost" size="sm">
|
||||||
|
<MoreHorizontal />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end" class="w-[200px]">
|
||||||
|
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||||
|
<DropdownMenuGroup>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
Assign to...
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
Set due date...
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuSub>
|
||||||
|
<DropdownMenuSubTrigger>
|
||||||
|
Apply label
|
||||||
|
</DropdownMenuSubTrigger>
|
||||||
|
<DropdownMenuSubContent class="p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput
|
||||||
|
placeholder="Filter label..."
|
||||||
|
auto-focus
|
||||||
|
/>
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No label found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="label in labels"
|
||||||
|
:key="label"
|
||||||
|
:value="label"
|
||||||
|
@select="(ev) => {
|
||||||
|
labelRef = ev.detail.value as string
|
||||||
|
open = false
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuSub>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem class="text-red-600">
|
||||||
|
Delete
|
||||||
|
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
121
apps/www/src/registry/new-york/example/CommandForm.vue
Normal file
121
apps/www/src/registry/new-york/example/CommandForm.vue
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/new-york/ui/command'
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from '@/registry/new-york/ui/form'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/registry/new-york/ui/popover'
|
||||||
|
import { toast } from '@/registry/new-york/ui/toast'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import { h } from 'vue'
|
||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
|
const languages = [
|
||||||
|
{ label: 'English', value: 'en' },
|
||||||
|
{ label: 'French', value: 'fr' },
|
||||||
|
{ label: 'German', value: 'de' },
|
||||||
|
{ label: 'Spanish', value: 'es' },
|
||||||
|
{ label: 'Portuguese', value: 'pt' },
|
||||||
|
{ label: 'Russian', value: 'ru' },
|
||||||
|
{ label: 'Japanese', value: 'ja' },
|
||||||
|
{ label: 'Korean', value: 'ko' },
|
||||||
|
{ label: 'Chinese', value: 'zh' },
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(z.object({
|
||||||
|
language: z.string({
|
||||||
|
required_error: 'Please select a language.',
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { handleSubmit, setFieldValue, values } = useForm({
|
||||||
|
validationSchema: formSchema,
|
||||||
|
initialValues: {
|
||||||
|
language: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit((values) => {
|
||||||
|
toast({
|
||||||
|
title: 'You submitted the following values:',
|
||||||
|
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<form class="space-y-6" @submit="onSubmit">
|
||||||
|
<FormField name="language">
|
||||||
|
<FormItem class="flex flex-col">
|
||||||
|
<FormLabel>Language</FormLabel>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<FormControl>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
role="combobox"
|
||||||
|
:class="cn('w-[200px] justify-between', !values.language && 'text-muted-foreground')"
|
||||||
|
>
|
||||||
|
{{ values.language ? languages.find(
|
||||||
|
(language) => language.value === values.language,
|
||||||
|
)?.label : 'Select language...' }}
|
||||||
|
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</FormControl>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[200px] p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Search language..." />
|
||||||
|
<CommandEmpty>Nothing found.</CommandEmpty>
|
||||||
|
<CommandList>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="language in languages"
|
||||||
|
:key="language.value"
|
||||||
|
:value="language.label"
|
||||||
|
@select="() => {
|
||||||
|
setFieldValue('language', language.value)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ language.label }}
|
||||||
|
<Check
|
||||||
|
:class="cn('ml-auto h-4 w-4', language.value === values.language ? 'opacity-100' : 'opacity-0')"
|
||||||
|
/>
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<FormDescription>
|
||||||
|
This is the language that will be used in the dashboard.
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<Button type="submit">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
94
apps/www/src/registry/new-york/example/CommandPopover.vue
Normal file
94
apps/www/src/registry/new-york/example/CommandPopover.vue
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
} from '@/registry/new-york/ui/command'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/registry/new-york/ui/popover'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Status {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const statuses: Status[] = [
|
||||||
|
{
|
||||||
|
value: 'backlog',
|
||||||
|
label: 'Backlog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'todo',
|
||||||
|
label: 'Todo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'in progress',
|
||||||
|
label: 'In Progress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'done',
|
||||||
|
label: 'Done',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'canceled',
|
||||||
|
label: 'Canceled',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
const selectedStatus = ref<Status>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
<p class="text-sm text-muted-foreground">
|
||||||
|
Status
|
||||||
|
</p>
|
||||||
|
<Popover v-model:open="open">
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
class="w-[150px] justify-start"
|
||||||
|
>
|
||||||
|
<template v-if="selectedStatus">
|
||||||
|
{{ selectedStatus?.label }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
+ Set status
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="p-0" side="right" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Change status..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="status in statuses"
|
||||||
|
:key="status.value"
|
||||||
|
:value="status.value"
|
||||||
|
@select="() => {
|
||||||
|
selectedStatus = status
|
||||||
|
open = false
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ status.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
94
apps/www/src/registry/new-york/example/CommandResponsive.vue
Normal file
94
apps/www/src/registry/new-york/example/CommandResponsive.vue
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Button } from '@/registry/new-york/ui/button'
|
||||||
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/registry/new-york/ui/command'
|
||||||
|
import { Drawer, DrawerContent, DrawerTrigger } from '@/registry/new-york/ui/drawer'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/registry/new-york/ui/popover'
|
||||||
|
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Status {
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const statuses: Status[] = [
|
||||||
|
{
|
||||||
|
value: 'backlog',
|
||||||
|
label: 'Backlog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'todo',
|
||||||
|
label: 'Todo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'in progress',
|
||||||
|
label: 'In Progress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'done',
|
||||||
|
label: 'Done',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'canceled',
|
||||||
|
label: 'Canceled',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const [UseTemplate, StatusList] = createReusableTemplate()
|
||||||
|
const isDesktop = useMediaQuery('(min-width: 768px)')
|
||||||
|
|
||||||
|
const isOpen = ref(false)
|
||||||
|
const selectedStatus = ref<Status | null>(null)
|
||||||
|
|
||||||
|
function onStatusSelect(status: Status) {
|
||||||
|
selectedStatus.value = status
|
||||||
|
isOpen.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<UseTemplate>
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Filter status..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="status of statuses"
|
||||||
|
:key="status.value"
|
||||||
|
:value="status.value"
|
||||||
|
@select="onStatusSelect(status)"
|
||||||
|
>
|
||||||
|
{{ status.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</UseTemplate>
|
||||||
|
|
||||||
|
<Popover v-if="isDesktop" v-model:open="isOpen">
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button variant="outline" class="w-[150px] justify-start">
|
||||||
|
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[200px] p-0" align="start">
|
||||||
|
<StatusList />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<Drawer v-else v-model:open="isOpen">
|
||||||
|
<DrawerTrigger as-child>
|
||||||
|
<Button variant="outline" class="w-[150px] justify-start">
|
||||||
|
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
|
||||||
|
</Button>
|
||||||
|
</DrawerTrigger>
|
||||||
|
<DrawerContent>
|
||||||
|
<div class="mt-4 border-t">
|
||||||
|
<StatusList />
|
||||||
|
</div>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
14
apps/www/src/registry/new-york/ui/combobox/Combobox.vue
Normal file
14
apps/www/src/registry/new-york/ui/combobox/Combobox.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ComboboxRoot, type ComboboxRootEmits, type ComboboxRootProps, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxRootProps>()
|
||||||
|
const emits = defineEmits<ComboboxRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxRoot v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</ComboboxRoot>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxAnchorProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxAnchor, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxAnchor
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('w-[200px]', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxAnchor>
|
||||||
|
</template>
|
||||||
20
apps/www/src/registry/new-york/ui/combobox/ComboboxEmpty.vue
Normal file
20
apps/www/src/registry/new-york/ui/combobox/ComboboxEmpty.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxEmptyProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxEmpty } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxEmpty v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)">
|
||||||
|
<slot />
|
||||||
|
</ComboboxEmpty>
|
||||||
|
</template>
|
||||||
29
apps/www/src/registry/new-york/ui/combobox/ComboboxGroup.vue
Normal file
29
apps/www/src/registry/new-york/ui/combobox/ComboboxGroup.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxGroupProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxGroup, ComboboxLabel } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxGroupProps & {
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
heading?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxGroup
|
||||||
|
v-bind="delegatedProps"
|
||||||
|
:class="cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)"
|
||||||
|
>
|
||||||
|
<ComboboxLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
|
||||||
|
{{ heading }}
|
||||||
|
</ComboboxLabel>
|
||||||
|
<slot />
|
||||||
|
</ComboboxGroup>
|
||||||
|
</template>
|
||||||
26
apps/www/src/registry/new-york/ui/combobox/ComboboxInput.vue
Normal file
26
apps/www/src/registry/new-york/ui/combobox/ComboboxInput.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxInputProps & {
|
||||||
|
class?: HTMLAttributes['class']
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxInput
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxInput>
|
||||||
|
</template>
|
||||||
26
apps/www/src/registry/new-york/ui/combobox/ComboboxItem.vue
Normal file
26
apps/www/src/registry/new-york/ui/combobox/ComboboxItem.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxItem, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
const emits = defineEmits<ComboboxItemEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('relative flex cursor-default gap-2 select-none justify-between items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxItem>
|
||||||
|
</template>
|
||||||
34
apps/www/src/registry/new-york/ui/combobox/ComboboxList.vue
Normal file
34
apps/www/src/registry/new-york/ui/combobox/ComboboxList.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {
|
||||||
|
position: 'popper',
|
||||||
|
align: 'center',
|
||||||
|
sideOffset: 4,
|
||||||
|
})
|
||||||
|
const emits = defineEmits<ComboboxContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxPortal>
|
||||||
|
<ComboboxContent
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)"
|
||||||
|
>
|
||||||
|
<ComboboxViewport>
|
||||||
|
<slot />
|
||||||
|
</ComboboxViewport>
|
||||||
|
</ComboboxContent>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxSeparatorProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxSeparator } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxSeparator
|
||||||
|
v-bind="delegatedProps"
|
||||||
|
:class="cn('-mx-1 h-px bg-border', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxSeparator>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ComboboxTriggerProps } from 'reka-ui'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { ComboboxTrigger, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ComboboxTrigger
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn('', props.class)"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</ComboboxTrigger>
|
||||||
|
</template>
|
||||||
10
apps/www/src/registry/new-york/ui/combobox/index.ts
Normal file
10
apps/www/src/registry/new-york/ui/combobox/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export { default as Combobox } from './Combobox.vue'
|
||||||
|
export { default as ComboboxAnchor } from './ComboboxAnchor.vue'
|
||||||
|
export { default as ComboboxEmpty } from './ComboboxEmpty.vue'
|
||||||
|
export { default as ComboboxGroup } from './ComboboxGroup.vue'
|
||||||
|
export { default as ComboboxInput } from './ComboboxInput.vue'
|
||||||
|
export { default as ComboboxItem } from './ComboboxItem.vue'
|
||||||
|
export { default as ComboboxList } from './ComboboxList.vue'
|
||||||
|
export { default as ComboboxSeparator } from './ComboboxSeparator.vue'
|
||||||
|
|
||||||
|
export { ComboboxCancel, ComboboxItemIndicator, ComboboxTrigger } from 'reka-ui'
|
||||||
Loading…
Reference in New Issue
Block a user