@weaverclub/render 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entrypoint +0 -0
- package/package.json +6 -2
- package/.github/workflows/publish.yml +0 -44
- package/biome.json +0 -42
- package/build.ts +0 -62
- package/bun.lock +0 -733
- package/bunfig.toml +0 -3
- package/ideas.md +0 -11
- package/publish.ts +0 -62
- package/src/cli/command/renderCommand.ts +0 -112
- package/src/cli/entrypoint.ts +0 -25
- package/src/core/bundler.ts +0 -180
- package/src/core/control/arrayControl.ts +0 -15
- package/src/core/control/booleanControl.ts +0 -15
- package/src/core/control/control.ts +0 -7
- package/src/core/control/controlBuilder.ts +0 -87
- package/src/core/control/numberControl.ts +0 -15
- package/src/core/control/stringControl.ts +0 -15
- package/src/core/control/variantControl.ts +0 -18
- package/src/core/css/css.ts +0 -50
- package/src/core/css/tailwind.ts +0 -172
- package/src/core/html.ts +0 -63
- package/src/core/pkg.ts +0 -92
- package/src/core/story.ts +0 -52
- package/src/core/tsconfig.ts +0 -46
- package/src/react/react.ts +0 -2
- package/src/react/reactControlBuilder.ts +0 -130
- package/src/react/reactStory.ts +0 -36
- package/src/server/api/getStories.ts +0 -44
- package/src/server/api/renderIframe.ts +0 -66
- package/src/server/backend.ts +0 -104
- package/src/server/streaming.ts +0 -16
- package/src/ui/api.ts +0 -16
- package/src/ui/app.tsx +0 -23
- package/src/ui/cn.ts +0 -6
- package/src/ui/components/appSidebar.tsx +0 -76
- package/src/ui/components/button.stories.tsx +0 -32
- package/src/ui/components/button.tsx +0 -55
- package/src/ui/components/command.tsx +0 -187
- package/src/ui/components/contextMenu.tsx +0 -261
- package/src/ui/components/dialog.tsx +0 -153
- package/src/ui/components/input.tsx +0 -23
- package/src/ui/components/inputGroup.tsx +0 -157
- package/src/ui/components/kdb.tsx +0 -26
- package/src/ui/components/searchCommand.tsx +0 -5
- package/src/ui/components/separator.tsx +0 -22
- package/src/ui/components/sheet.tsx +0 -131
- package/src/ui/components/sidebar.tsx +0 -725
- package/src/ui/components/skeleton.tsx +0 -13
- package/src/ui/components/spinner.tsx +0 -15
- package/src/ui/components/tabButton.tsx +0 -80
- package/src/ui/components/tabContent.tsx +0 -20
- package/src/ui/components/tabList.tsx +0 -53
- package/src/ui/components/textarea.tsx +0 -17
- package/src/ui/components/tooltip.tsx +0 -67
- package/src/ui/frontend.tsx +0 -68
- package/src/ui/hooks/useMobile.ts +0 -23
- package/src/ui/index.html +0 -12
- package/src/ui/routeTree.gen.ts +0 -35
- package/src/ui/routes/__root.tsx +0 -9
- package/src/ui/styles.css +0 -123
- package/src/ui/tabs.tsx +0 -89
- package/tsconfig.json +0 -25
- package/tsr.config.json +0 -6
package/src/server/backend.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { BunContext } from '@effect/platform-bun'
|
|
2
|
-
import { Console, Effect } from 'effect'
|
|
3
|
-
import type { CSS } from '#core/css/css'
|
|
4
|
-
import type { ReactStory } from '#react/reactStory'
|
|
5
|
-
import index from '../ui/index.html'
|
|
6
|
-
import { getStories } from './api/getStories'
|
|
7
|
-
import { renderIframe } from './api/renderIframe'
|
|
8
|
-
|
|
9
|
-
// Track connected WebSocket clients for HMR
|
|
10
|
-
const hmrClients = new Set<{ send: (msg: string) => void }>()
|
|
11
|
-
|
|
12
|
-
export const notifyHmrClients = () => {
|
|
13
|
-
for (const client of hmrClients) {
|
|
14
|
-
try {
|
|
15
|
-
client.send(JSON.stringify({ type: 'reload' }))
|
|
16
|
-
} catch {
|
|
17
|
-
hmrClients.delete(client)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Mutable state for HMR updates
|
|
23
|
-
// biome-ignore lint/suspicious/noExplicitAny: Required for story typing
|
|
24
|
-
let currentStories: ReactStory<any>[] = []
|
|
25
|
-
let currentCss: CSS[] = []
|
|
26
|
-
let currentProjectRoot = ''
|
|
27
|
-
|
|
28
|
-
export const updateBackendState = ({
|
|
29
|
-
stories,
|
|
30
|
-
css,
|
|
31
|
-
projectRoot
|
|
32
|
-
}: StartBackendArgs) => {
|
|
33
|
-
currentStories = stories
|
|
34
|
-
currentCss = css
|
|
35
|
-
currentProjectRoot = projectRoot
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const startBackend = ({ stories, css, projectRoot }: StartBackendArgs) =>
|
|
39
|
-
Effect.sync(() => {
|
|
40
|
-
// Initialize mutable state
|
|
41
|
-
currentStories = stories
|
|
42
|
-
currentCss = css
|
|
43
|
-
currentProjectRoot = projectRoot
|
|
44
|
-
|
|
45
|
-
return Bun.serve({
|
|
46
|
-
port: 3210,
|
|
47
|
-
routes: {
|
|
48
|
-
'/iframe/*': {
|
|
49
|
-
GET: (request) =>
|
|
50
|
-
Effect.runPromise(
|
|
51
|
-
renderIframe({
|
|
52
|
-
request,
|
|
53
|
-
stories: currentStories,
|
|
54
|
-
css: currentCss,
|
|
55
|
-
projectRoot: currentProjectRoot
|
|
56
|
-
}).pipe(Effect.provide(BunContext.layer))
|
|
57
|
-
)
|
|
58
|
-
},
|
|
59
|
-
'/api/stories': {
|
|
60
|
-
GET: (request) =>
|
|
61
|
-
Effect.runSync(getStories({ request, stories: currentStories }))
|
|
62
|
-
},
|
|
63
|
-
// Explicit routes for UI paths
|
|
64
|
-
'/': index,
|
|
65
|
-
'/index.html': index
|
|
66
|
-
},
|
|
67
|
-
// @ts-expect-error
|
|
68
|
-
fetch(req, server) {
|
|
69
|
-
const url = new URL(req.url)
|
|
70
|
-
|
|
71
|
-
// Handle WebSocket upgrade for HMR
|
|
72
|
-
if (url.pathname === '/__hmr') {
|
|
73
|
-
const upgraded = server.upgrade(req)
|
|
74
|
-
if (upgraded) return undefined
|
|
75
|
-
return new Response('WebSocket upgrade failed', { status: 500 })
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Fall back to index for any other paths (SPA routing)
|
|
79
|
-
return index
|
|
80
|
-
},
|
|
81
|
-
websocket: {
|
|
82
|
-
open(ws) {
|
|
83
|
-
hmrClients.add(ws)
|
|
84
|
-
console.log('🔌 HMR client connected')
|
|
85
|
-
},
|
|
86
|
-
close(ws) {
|
|
87
|
-
hmrClients.delete(ws)
|
|
88
|
-
console.log('🔌 HMR client disconnected')
|
|
89
|
-
},
|
|
90
|
-
message(_ws, _message) {
|
|
91
|
-
// No client messages expected
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
}).pipe(
|
|
96
|
-
Effect.tap(() => Console.log('Backend started on http://localhost:3210'))
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
type StartBackendArgs = {
|
|
100
|
-
// biome-ignore lint/suspicious/noExplicitAny: Required for story typing
|
|
101
|
-
stories: ReactStory<any>[]
|
|
102
|
-
css: CSS[]
|
|
103
|
-
projectRoot: string
|
|
104
|
-
}
|
package/src/server/streaming.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Effect } from 'effect'
|
|
2
|
-
|
|
3
|
-
export const streamToString = Effect.fn(function* (stream: ReadableStream) {
|
|
4
|
-
const reader = stream.getReader()
|
|
5
|
-
const chunks: Uint8Array[] = []
|
|
6
|
-
|
|
7
|
-
while (true) {
|
|
8
|
-
const { done, value } = yield* Effect.tryPromise(() => reader.read())
|
|
9
|
-
|
|
10
|
-
if (done) break
|
|
11
|
-
|
|
12
|
-
chunks.push(value)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return new TextDecoder().decode(Buffer.concat(chunks))
|
|
16
|
-
})
|
package/src/ui/api.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
-
|
|
3
|
-
export const queryClient = new QueryClient()
|
|
4
|
-
|
|
5
|
-
export async function getStories(): Promise<GetStoriesResponse> {
|
|
6
|
-
return fetch('/api/stories').then((res) => res.json())
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export type GetStoriesResponse = {
|
|
10
|
-
[category: string]: Story[]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type Story = {
|
|
14
|
-
name: string
|
|
15
|
-
path: string
|
|
16
|
-
}
|
package/src/ui/app.tsx
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Tabs } from '@base-ui/react'
|
|
2
|
-
import { QueryClientProvider } from '@tanstack/react-query'
|
|
3
|
-
import { queryClient } from './api'
|
|
4
|
-
import { AppSidebar } from './components/appSidebar'
|
|
5
|
-
import { SidebarProvider } from './components/sidebar'
|
|
6
|
-
import { TabContent } from './components/tabContent'
|
|
7
|
-
import { TabList } from './components/tabList'
|
|
8
|
-
|
|
9
|
-
export function App() {
|
|
10
|
-
return (
|
|
11
|
-
<QueryClientProvider client={queryClient}>
|
|
12
|
-
<SidebarProvider>
|
|
13
|
-
<AppSidebar />
|
|
14
|
-
<main className="flex flex-col w-full">
|
|
15
|
-
<Tabs.Root>
|
|
16
|
-
<TabList />
|
|
17
|
-
<TabContent />
|
|
18
|
-
</Tabs.Root>
|
|
19
|
-
</main>
|
|
20
|
-
</SidebarProvider>
|
|
21
|
-
</QueryClientProvider>
|
|
22
|
-
)
|
|
23
|
-
}
|
package/src/ui/cn.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query'
|
|
2
|
-
import { getStories } from '#ui/api'
|
|
3
|
-
import { Button } from './button'
|
|
4
|
-
import { Kbd } from './kdb'
|
|
5
|
-
import {
|
|
6
|
-
Sidebar,
|
|
7
|
-
SidebarContent,
|
|
8
|
-
SidebarGroup,
|
|
9
|
-
SidebarGroupContent,
|
|
10
|
-
SidebarGroupLabel,
|
|
11
|
-
SidebarHeader,
|
|
12
|
-
SidebarMenu
|
|
13
|
-
} from './sidebar'
|
|
14
|
-
import { Spinner } from './spinner'
|
|
15
|
-
import { TabButton } from './tabButton'
|
|
16
|
-
|
|
17
|
-
export function AppSidebar() {
|
|
18
|
-
const { data, isLoading, error } = useQuery({
|
|
19
|
-
queryKey: ['stories'],
|
|
20
|
-
queryFn: getStories
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<Sidebar>
|
|
25
|
-
<SidebarHeader>
|
|
26
|
-
<Button
|
|
27
|
-
variant="outline"
|
|
28
|
-
size="lg"
|
|
29
|
-
className="flex justify-between gap-1 w-full text-zinc-500 font-normal"
|
|
30
|
-
>
|
|
31
|
-
<span>Search...</span>
|
|
32
|
-
<Kbd>⌘ K</Kbd>
|
|
33
|
-
</Button>
|
|
34
|
-
</SidebarHeader>
|
|
35
|
-
|
|
36
|
-
<SidebarContent>
|
|
37
|
-
{isLoading && (
|
|
38
|
-
<div className="w-full py-8 flex items-center justify-center">
|
|
39
|
-
<Spinner />
|
|
40
|
-
</div>
|
|
41
|
-
)}
|
|
42
|
-
{error && (
|
|
43
|
-
<div className="w-full py-8 flex flex-col items-center justify-center text-center gap-2">
|
|
44
|
-
<p className="text-xs text-destructive font-medium">
|
|
45
|
-
Failed to load stories.
|
|
46
|
-
</p>
|
|
47
|
-
<p className="text-xs text-muted-foreground">
|
|
48
|
-
Check if your server is running and accessible.
|
|
49
|
-
</p>
|
|
50
|
-
</div>
|
|
51
|
-
)}
|
|
52
|
-
{data &&
|
|
53
|
-
Object.keys(data).map((storyGroup) => (
|
|
54
|
-
<SidebarGroup key={storyGroup}>
|
|
55
|
-
<SidebarGroupLabel>{storyGroup}</SidebarGroupLabel>
|
|
56
|
-
<SidebarGroupContent>
|
|
57
|
-
<SidebarMenu>
|
|
58
|
-
{data[storyGroup]?.map((story) => (
|
|
59
|
-
<TabButton
|
|
60
|
-
key={story.path}
|
|
61
|
-
story={{
|
|
62
|
-
id: story.path,
|
|
63
|
-
name: story.name
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
<span>{story.name}</span>
|
|
67
|
-
</TabButton>
|
|
68
|
-
))}
|
|
69
|
-
</SidebarMenu>
|
|
70
|
-
</SidebarGroupContent>
|
|
71
|
-
</SidebarGroup>
|
|
72
|
-
))}
|
|
73
|
-
</SidebarContent>
|
|
74
|
-
</Sidebar>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { controls } from '#react/reactControlBuilder'
|
|
2
|
-
import { story } from '#react/reactStory'
|
|
3
|
-
import { Button } from './button'
|
|
4
|
-
|
|
5
|
-
const buttonControls = controls<typeof Button>()
|
|
6
|
-
.variant('variant', {
|
|
7
|
-
defaultValue: 'default',
|
|
8
|
-
options: ['default', 'destructive', 'ghost', 'outline', 'secondary', 'link']
|
|
9
|
-
})
|
|
10
|
-
.variant('size', {
|
|
11
|
-
defaultValue: 'default',
|
|
12
|
-
options: [
|
|
13
|
-
'default',
|
|
14
|
-
'xs',
|
|
15
|
-
'sm',
|
|
16
|
-
'lg',
|
|
17
|
-
'icon',
|
|
18
|
-
'icon-xs',
|
|
19
|
-
'icon-sm',
|
|
20
|
-
'icon-lg'
|
|
21
|
-
]
|
|
22
|
-
})
|
|
23
|
-
.bool('disabled', {
|
|
24
|
-
defaultValue: false
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const Story = story({
|
|
28
|
-
name: 'UI/Button',
|
|
29
|
-
component: Button,
|
|
30
|
-
controls: buttonControls,
|
|
31
|
-
render: (props) => <Button {...props}>Click me</Button>
|
|
32
|
-
})
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Button as ButtonPrimitive } from '@base-ui/react/button'
|
|
2
|
-
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
-
import { cn } from '../cn'
|
|
4
|
-
|
|
5
|
-
const buttonVariants = cva(
|
|
6
|
-
"focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium focus-visible:ring-2 aria-invalid:ring-2 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
|
7
|
-
{
|
|
8
|
-
variants: {
|
|
9
|
-
variant: {
|
|
10
|
-
default: 'bg-primary text-primary-foreground hover:bg-primary/80',
|
|
11
|
-
outline:
|
|
12
|
-
'border-border dark:bg-input/20 dark:bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground',
|
|
13
|
-
secondary:
|
|
14
|
-
'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',
|
|
15
|
-
ghost:
|
|
16
|
-
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
|
|
17
|
-
destructive:
|
|
18
|
-
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
|
|
19
|
-
link: 'text-primary underline-offset-4 hover:underline'
|
|
20
|
-
},
|
|
21
|
-
size: {
|
|
22
|
-
default:
|
|
23
|
-
"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
24
|
-
xs: "h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5",
|
|
25
|
-
sm: "h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
26
|
-
lg: "h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4",
|
|
27
|
-
icon: "size-7 [&_svg:not([class*='size-'])]:size-3.5",
|
|
28
|
-
'icon-xs': "size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5",
|
|
29
|
-
'icon-sm': "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
30
|
-
'icon-lg': "size-8 [&_svg:not([class*='size-'])]:size-4"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
defaultVariants: {
|
|
34
|
-
variant: 'default',
|
|
35
|
-
size: 'default'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
function Button({
|
|
41
|
-
className,
|
|
42
|
-
variant = 'default',
|
|
43
|
-
size = 'default',
|
|
44
|
-
...props
|
|
45
|
-
}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
|
|
46
|
-
return (
|
|
47
|
-
<ButtonPrimitive
|
|
48
|
-
data-slot="button"
|
|
49
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
50
|
-
{...props}
|
|
51
|
-
/>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export { Button, buttonVariants }
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { Command as CommandPrimitive } from 'cmdk'
|
|
2
|
-
import { CheckIcon, SearchIcon } from 'lucide-react'
|
|
3
|
-
import type * as React from 'react'
|
|
4
|
-
import { cn } from '../cn'
|
|
5
|
-
import {
|
|
6
|
-
Dialog,
|
|
7
|
-
DialogContent,
|
|
8
|
-
DialogDescription,
|
|
9
|
-
DialogHeader,
|
|
10
|
-
DialogTitle
|
|
11
|
-
} from './dialog'
|
|
12
|
-
import { InputGroup, InputGroupAddon } from './inputGroup'
|
|
13
|
-
|
|
14
|
-
function Command({
|
|
15
|
-
className,
|
|
16
|
-
...props
|
|
17
|
-
}: React.ComponentProps<typeof CommandPrimitive>) {
|
|
18
|
-
return (
|
|
19
|
-
<CommandPrimitive
|
|
20
|
-
data-slot="command"
|
|
21
|
-
className={cn(
|
|
22
|
-
'bg-popover text-popover-foreground rounded-xl p-1 flex size-full flex-col overflow-hidden',
|
|
23
|
-
className
|
|
24
|
-
)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function CommandDialog({
|
|
31
|
-
title = 'Command Palette',
|
|
32
|
-
description = 'Search for a command to run...',
|
|
33
|
-
children,
|
|
34
|
-
className,
|
|
35
|
-
showCloseButton = false,
|
|
36
|
-
...props
|
|
37
|
-
}: Omit<React.ComponentProps<typeof Dialog>, 'children'> & {
|
|
38
|
-
title?: string
|
|
39
|
-
description?: string
|
|
40
|
-
className?: string
|
|
41
|
-
showCloseButton?: boolean
|
|
42
|
-
children: React.ReactNode
|
|
43
|
-
}) {
|
|
44
|
-
return (
|
|
45
|
-
<Dialog {...props}>
|
|
46
|
-
<DialogHeader className="sr-only">
|
|
47
|
-
<DialogTitle>{title}</DialogTitle>
|
|
48
|
-
<DialogDescription>{description}</DialogDescription>
|
|
49
|
-
</DialogHeader>
|
|
50
|
-
<DialogContent
|
|
51
|
-
className={cn('rounded-xl! p-0 overflow-hidden p-0', className)}
|
|
52
|
-
showCloseButton={showCloseButton}
|
|
53
|
-
>
|
|
54
|
-
{children}
|
|
55
|
-
</DialogContent>
|
|
56
|
-
</Dialog>
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function CommandInput({
|
|
61
|
-
className,
|
|
62
|
-
...props
|
|
63
|
-
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
|
|
64
|
-
return (
|
|
65
|
-
<div data-slot="command-input-wrapper" className="p-1 pb-0">
|
|
66
|
-
<InputGroup className="bg-input/20 dark:bg-input/30 h-8!">
|
|
67
|
-
<CommandPrimitive.Input
|
|
68
|
-
data-slot="command-input"
|
|
69
|
-
className={cn(
|
|
70
|
-
'w-full text-xs/relaxed outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
|
71
|
-
className
|
|
72
|
-
)}
|
|
73
|
-
{...props}
|
|
74
|
-
/>
|
|
75
|
-
<InputGroupAddon>
|
|
76
|
-
<SearchIcon className="size-3.5 shrink-0 opacity-50" />
|
|
77
|
-
</InputGroupAddon>
|
|
78
|
-
</InputGroup>
|
|
79
|
-
</div>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function CommandList({
|
|
84
|
-
className,
|
|
85
|
-
...props
|
|
86
|
-
}: React.ComponentProps<typeof CommandPrimitive.List>) {
|
|
87
|
-
return (
|
|
88
|
-
<CommandPrimitive.List
|
|
89
|
-
data-slot="command-list"
|
|
90
|
-
className={cn(
|
|
91
|
-
'no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto',
|
|
92
|
-
className
|
|
93
|
-
)}
|
|
94
|
-
{...props}
|
|
95
|
-
/>
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function CommandEmpty({
|
|
100
|
-
className,
|
|
101
|
-
...props
|
|
102
|
-
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
|
103
|
-
return (
|
|
104
|
-
<CommandPrimitive.Empty
|
|
105
|
-
data-slot="command-empty"
|
|
106
|
-
className={cn('py-6 text-center text-xs/relaxed', className)}
|
|
107
|
-
{...props}
|
|
108
|
-
/>
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function CommandGroup({
|
|
113
|
-
className,
|
|
114
|
-
...props
|
|
115
|
-
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
|
|
116
|
-
return (
|
|
117
|
-
<CommandPrimitive.Group
|
|
118
|
-
data-slot="command-group"
|
|
119
|
-
className={cn(
|
|
120
|
-
'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
|
|
121
|
-
className
|
|
122
|
-
)}
|
|
123
|
-
{...props}
|
|
124
|
-
/>
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function CommandSeparator({
|
|
129
|
-
className,
|
|
130
|
-
...props
|
|
131
|
-
}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
|
|
132
|
-
return (
|
|
133
|
-
<CommandPrimitive.Separator
|
|
134
|
-
data-slot="command-separator"
|
|
135
|
-
className={cn('bg-border/50 -mx-1 my-1 h-px', className)}
|
|
136
|
-
{...props}
|
|
137
|
-
/>
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function CommandItem({
|
|
142
|
-
className,
|
|
143
|
-
children,
|
|
144
|
-
...props
|
|
145
|
-
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
|
|
146
|
-
return (
|
|
147
|
-
<CommandPrimitive.Item
|
|
148
|
-
data-slot="command-item"
|
|
149
|
-
className={cn(
|
|
150
|
-
"data-selected:bg-muted data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex min-h-7 cursor-default items-center gap-2 rounded-md px-2.5 py-1.5 text-xs/relaxed outline-hidden select-none [&_svg:not([class*='size-'])]:size-3.5 [[data-slot=dialog-content]_&]:rounded-md group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
151
|
-
className
|
|
152
|
-
)}
|
|
153
|
-
{...props}
|
|
154
|
-
>
|
|
155
|
-
{children}
|
|
156
|
-
<CheckIcon className="ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
|
|
157
|
-
</CommandPrimitive.Item>
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function CommandShortcut({
|
|
162
|
-
className,
|
|
163
|
-
...props
|
|
164
|
-
}: React.ComponentProps<'span'>) {
|
|
165
|
-
return (
|
|
166
|
-
<span
|
|
167
|
-
data-slot="command-shortcut"
|
|
168
|
-
className={cn(
|
|
169
|
-
'text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-[0.625rem] tracking-widest',
|
|
170
|
-
className
|
|
171
|
-
)}
|
|
172
|
-
{...props}
|
|
173
|
-
/>
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export {
|
|
178
|
-
Command,
|
|
179
|
-
CommandDialog,
|
|
180
|
-
CommandInput,
|
|
181
|
-
CommandList,
|
|
182
|
-
CommandEmpty,
|
|
183
|
-
CommandGroup,
|
|
184
|
-
CommandItem,
|
|
185
|
-
CommandShortcut,
|
|
186
|
-
CommandSeparator
|
|
187
|
-
}
|