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 sdk from '@stackblitz/sdk'
|
||||
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__'
|
||||
// @ts-expect-error ?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>) {
|
||||
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
|
||||
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 = {
|
||||
'package.json': {
|
||||
|
|
|
|||
|
|
@ -632,6 +632,57 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "command",
|
||||
description: "",
|
||||
|
|
@ -2985,7 +3036,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxDemo",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","popover"],
|
||||
registryDependencies: ["utils","combobox"],
|
||||
files: [{
|
||||
path: "registry/new-york/example/ComboboxDemo.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -3015,7 +3066,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxForm",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||
files: [{
|
||||
path: "registry/new-york/example/ComboboxForm.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -3056,6 +3107,21 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
description: "",
|
||||
|
|
@ -3086,6 +3152,66 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "ContextMenuDemo",
|
||||
description: "",
|
||||
|
|
@ -6352,6 +6478,57 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "command",
|
||||
description: "",
|
||||
|
|
@ -8705,7 +8882,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxDemo",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","popover"],
|
||||
registryDependencies: ["utils","combobox"],
|
||||
files: [{
|
||||
path: "registry/new-york/example/ComboboxDemo.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -8735,7 +8912,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxForm",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||
files: [{
|
||||
path: "registry/new-york/example/ComboboxForm.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -8776,6 +8953,21 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
description: "",
|
||||
|
|
@ -8806,6 +8998,66 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "ContextMenuDemo",
|
||||
description: "",
|
||||
|
|
@ -12088,6 +12340,57 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "command",
|
||||
description: "",
|
||||
|
|
@ -14441,7 +14744,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxDemo",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","popover"],
|
||||
registryDependencies: ["utils","combobox"],
|
||||
files: [{
|
||||
path: "registry/default/example/ComboboxDemo.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -14471,7 +14774,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxForm",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||
files: [{
|
||||
path: "registry/default/example/ComboboxForm.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -14512,6 +14815,21 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
description: "",
|
||||
|
|
@ -14542,6 +14860,66 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "ContextMenuDemo",
|
||||
description: "",
|
||||
|
|
@ -17808,6 +18186,57 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "command",
|
||||
description: "",
|
||||
|
|
@ -20161,7 +20590,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxDemo",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","popover"],
|
||||
registryDependencies: ["utils","combobox"],
|
||||
files: [{
|
||||
path: "registry/default/example/ComboboxDemo.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -20191,7 +20620,7 @@ export const Index: Record<string, any> = {
|
|||
name: "ComboboxForm",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["utils","button","command","form","popover","toast"],
|
||||
registryDependencies: ["utils","button","combobox","form","toast"],
|
||||
files: [{
|
||||
path: "registry/default/example/ComboboxForm.vue",
|
||||
type: "registry:example",
|
||||
|
|
@ -20232,6 +20661,21 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
description: "",
|
||||
|
|
@ -20262,6 +20706,66 @@ export const Index: Record<string, any> = {
|
|||
category: "",
|
||||
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": {
|
||||
name: "ContextMenuDemo",
|
||||
description: "",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
---
|
||||
title: Combobox
|
||||
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" />
|
||||
|
|
@ -9,9 +11,9 @@ description: Autocomplete input and command palette with a list of suggestions.
|
|||
|
||||
## Installation
|
||||
|
||||
The Combobox is built using a composition of the `<Popover />` and the `<Command />` components.
|
||||
|
||||
See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
|
||||
```bash
|
||||
npx shadcn-vue@latest add combobox
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
@ -92,11 +94,11 @@ const value = ref('')
|
|||
|
||||
## Examples
|
||||
|
||||
### Combobox
|
||||
### Combobox Trigger
|
||||
|
||||
<ComponentPreview name="ComboboxDemo" />
|
||||
<ComponentPreview name="ComboboxTrigger" />
|
||||
|
||||
### Popover
|
||||
<!-- ### Popover
|
||||
|
||||
<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.
|
||||
|
||||
<ComponentPreview name="ComboboxResponsive" />
|
||||
<ComponentPreview name="ComboboxResponsive" /> -->
|
||||
|
||||
### Form
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: Command
|
||||
description: Fast, composable, unstyled command menu.
|
||||
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" />
|
||||
|
|
@ -134,6 +134,28 @@ watch(CmdJ, (v) => {
|
|||
</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",
|
||||
"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",
|
||||
"type": "registry:ui",
|
||||
|
|
|
|||
|
|
@ -4,14 +4,12 @@
|
|||
"dependencies": [],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"popover"
|
||||
"combobox"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"target": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,14 @@
|
|||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"combobox",
|
||||
"form",
|
||||
"popover",
|
||||
"toast"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"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": [],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"popover"
|
||||
"combobox"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"target": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,14 @@
|
|||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"combobox",
|
||||
"form",
|
||||
"popover",
|
||||
"toast"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"type": "registry:ui",
|
||||
|
|
@ -4108,14 +4180,12 @@
|
|||
"dependencies": [],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"popover"
|
||||
"combobox"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"target": ""
|
||||
}
|
||||
|
|
@ -4150,15 +4220,14 @@
|
|||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"combobox",
|
||||
"form",
|
||||
"popover",
|
||||
"toast"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"type": "registry:ui",
|
||||
|
|
@ -11401,14 +11642,12 @@
|
|||
"dependencies": [],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"popover"
|
||||
"combobox"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"target": ""
|
||||
}
|
||||
|
|
@ -11443,15 +11682,14 @@
|
|||
"registryDependencies": [
|
||||
"utils",
|
||||
"button",
|
||||
"command",
|
||||
"combobox",
|
||||
"form",
|
||||
"popover",
|
||||
"toast"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"type": "registry:example",
|
||||
|
|
|
|||
|
|
@ -1,22 +1,7 @@
|
|||
<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 {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/registry/default/ui/popover'
|
||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/default/ui/combobox'
|
||||
import { Check, Search } from 'lucide-vue-next'
|
||||
|
||||
const frameworks = [
|
||||
{ value: 'next.js', label: 'Next.js' },
|
||||
|
|
@ -25,54 +10,37 @@ const frameworks = [
|
|||
{ value: 'remix', label: 'Remix' },
|
||||
{ value: 'astro', label: 'Astro' },
|
||||
]
|
||||
|
||||
const open = ref(false)
|
||||
const value = ref('')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Popover v-model:open="open">
|
||||
<PopoverTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
:aria-expanded="open"
|
||||
class="w-[200px] justify-between"
|
||||
>
|
||||
{{ value
|
||||
? frameworks.find((framework) => framework.value === value)?.label
|
||||
: "Select framework..." }}
|
||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
||||
<CommandEmpty>No framework found.</CommandEmpty>
|
||||
<CommandList>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
<Combobox by="label">
|
||||
<ComboboxAnchor>
|
||||
<div class="relative w-full max-w-sm items-center">
|
||||
<ComboboxInput class="pl-9" :display-value="(val) => val?.label ?? ''" 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>
|
||||
</ComboboxAnchor>
|
||||
|
||||
<ComboboxList>
|
||||
<ComboboxEmpty>
|
||||
No framework found.
|
||||
</ComboboxEmpty>
|
||||
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem
|
||||
v-for="framework in frameworks"
|
||||
:key="framework.value"
|
||||
:value="framework.value"
|
||||
@select="(ev) => {
|
||||
if (typeof ev.detail.value === 'string') {
|
||||
value = ev.detail.value
|
||||
}
|
||||
open = false
|
||||
}"
|
||||
:value="framework"
|
||||
>
|
||||
{{ framework.label }}
|
||||
<Check
|
||||
:class="cn(
|
||||
'ml-auto h-4 w-4',
|
||||
value === framework.value ? 'opacity-100' : 'opacity-0',
|
||||
)"
|
||||
/>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
<ComboboxItemIndicator>
|
||||
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||
</ComboboxItemIndicator>
|
||||
</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</Combobox>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
<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 { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/default/ui/combobox'
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
|
|
@ -18,11 +12,6 @@ import {
|
|||
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'
|
||||
|
|
@ -40,7 +29,7 @@ const languages = [
|
|||
{ label: 'Japanese', value: 'ja' },
|
||||
{ label: 'Korean', value: 'ko' },
|
||||
{ label: 'Chinese', value: 'zh' },
|
||||
]
|
||||
] as const
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
language: z.string({
|
||||
|
|
@ -48,8 +37,11 @@ const formSchema = toTypedSchema(z.object({
|
|||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit, setFieldValue, values } = useForm({
|
||||
const { handleSubmit, setFieldValue } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
language: '',
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
|
|
@ -65,45 +57,43 @@ const onSubmit = handleSubmit((values) => {
|
|||
<FormField name="language">
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Language</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
|
||||
<Combobox by="label">
|
||||
<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>
|
||||
<ComboboxAnchor>
|
||||
<div class="relative w-full max-w-sm items-center">
|
||||
<ComboboxInput :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||
<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>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search language..." />
|
||||
<CommandEmpty>Nothing found.</CommandEmpty>
|
||||
<CommandList>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
|
||||
<ComboboxList>
|
||||
<ComboboxEmpty>
|
||||
Nothing found.
|
||||
</ComboboxEmpty>
|
||||
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem
|
||||
v-for="language in languages"
|
||||
:key="language.value"
|
||||
:value="language.label"
|
||||
:value="language"
|
||||
@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>
|
||||
|
||||
<ComboboxItemIndicator>
|
||||
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||
</ComboboxItemIndicator>
|
||||
</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</Combobox>
|
||||
|
||||
<FormDescription>
|
||||
This is the language that will be used in the dashboard.
|
||||
</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">
|
||||
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 {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/registry/new-york/ui/popover'
|
||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from '@/registry/new-york/ui/combobox'
|
||||
import { Check, Search } from 'lucide-vue-next'
|
||||
|
||||
const frameworks = [
|
||||
{ value: 'next.js', label: 'Next.js' },
|
||||
|
|
@ -25,54 +10,37 @@ const frameworks = [
|
|||
{ value: 'remix', label: 'Remix' },
|
||||
{ value: 'astro', label: 'Astro' },
|
||||
]
|
||||
|
||||
const open = ref(false)
|
||||
const value = ref('')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Popover v-model:open="open">
|
||||
<PopoverTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
:aria-expanded="open"
|
||||
class="w-[200px] justify-between"
|
||||
>
|
||||
{{ value
|
||||
? frameworks.find((framework) => framework.value === value)?.label
|
||||
: "Select framework..." }}
|
||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
||||
<CommandEmpty>No framework found.</CommandEmpty>
|
||||
<CommandList>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
<Combobox by="label">
|
||||
<ComboboxAnchor>
|
||||
<div class="relative w-full max-w-sm items-center">
|
||||
<ComboboxInput class="pl-9" :display-value="(val) => val?.label ?? ''" 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>
|
||||
</ComboboxAnchor>
|
||||
|
||||
<ComboboxList>
|
||||
<ComboboxEmpty>
|
||||
No framework found.
|
||||
</ComboboxEmpty>
|
||||
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem
|
||||
v-for="framework in frameworks"
|
||||
:key="framework.value"
|
||||
:value="framework.value"
|
||||
@select="(ev) => {
|
||||
if (typeof ev.detail.value === 'string') {
|
||||
value = ev.detail.value
|
||||
}
|
||||
open = false
|
||||
}"
|
||||
:value="framework"
|
||||
>
|
||||
{{ framework.label }}
|
||||
<Check
|
||||
:class="cn(
|
||||
'ml-auto h-4 w-4',
|
||||
value === framework.value ? 'opacity-100' : 'opacity-0',
|
||||
)"
|
||||
/>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
<ComboboxItemIndicator>
|
||||
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||
</ComboboxItemIndicator>
|
||||
</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</Combobox>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
<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 { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxTrigger } from '@/registry/new-york/ui/combobox'
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
|
|
@ -18,11 +12,6 @@ import {
|
|||
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'
|
||||
|
|
@ -48,7 +37,7 @@ const formSchema = toTypedSchema(z.object({
|
|||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit, setFieldValue, values } = useForm({
|
||||
const { handleSubmit, setFieldValue } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
language: '',
|
||||
|
|
@ -68,45 +57,43 @@ const onSubmit = handleSubmit((values) => {
|
|||
<FormField name="language">
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Language</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
|
||||
<Combobox by="label">
|
||||
<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>
|
||||
<ComboboxAnchor>
|
||||
<div class="relative w-full max-w-sm items-center">
|
||||
<ComboboxInput :display-value="(val) => val?.label ?? ''" placeholder="Select framework..." />
|
||||
<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>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search language..." />
|
||||
<CommandEmpty>Nothing found.</CommandEmpty>
|
||||
<CommandList>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
|
||||
<ComboboxList>
|
||||
<ComboboxEmpty>
|
||||
Nothing found.
|
||||
</ComboboxEmpty>
|
||||
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem
|
||||
v-for="language in languages"
|
||||
:key="language.value"
|
||||
:value="language.label"
|
||||
:value="language"
|
||||
@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>
|
||||
|
||||
<ComboboxItemIndicator>
|
||||
<Check :class="cn('ml-auto h-4 w-4')" />
|
||||
</ComboboxItemIndicator>
|
||||
</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</Combobox>
|
||||
|
||||
<FormDescription>
|
||||
This is the language that will be used in the dashboard.
|
||||
</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