feat: add Base UI Tailwind component library

Add composable wrappers for 37 Base UI component families.

Expose primitive and convenience APIs with shared styling utilities.

Add the registry manifest, installer CLI, generation and export checks.

Include a smoke example covering primitive and shadcn-style imports.
This commit is contained in:
Maofeng
2026-07-25 06:03:12 +08:00
parent 312cb1fd59
commit b3a7a2a8f5
311 changed files with 10879 additions and 0 deletions
Executable
+308
View File
@@ -0,0 +1,308 @@
#!/usr/bin/env node
import { accessSync } from "node:fs"
import { access, copyFile, mkdir, readFile, writeFile } from "node:fs/promises"
import path from "node:path"
import process from "node:process"
import { fileURLToPath } from "node:url"
const command = process.argv[2]
const args = process.argv.slice(3)
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
const bundledManifestPath = path.join(packageRoot, "manifest.json")
const configFileName = "base-ui-tailwind.json"
main().catch((error) => {
console.error(error instanceof Error ? error.message : String(error))
process.exit(1)
})
async function main() {
if (!command || command === "-h" || command === "--help") {
printHelp()
return
}
if (command === "init") {
await initProject(parseOptions(args))
return
}
if (command === "add") {
await addItems(parseOptions(args))
return
}
throw new Error(`Unknown command: ${command}`)
}
async function initProject(options) {
const cwd = path.resolve(options.cwd ?? process.cwd())
const configPath = path.join(cwd, configFileName)
const localManifestPath = path.join(cwd, "manifest.json")
const config = {
manifest: options.manifest ?? ((await exists(localManifestPath)) ? "manifest.json" : bundledManifestPath),
aliases: {
ui: "components/ui",
lib: "lib",
},
}
if (!options.force && (await exists(configPath))) {
console.log(`${configFileName} already exists. Use --force to overwrite it.`)
return
}
await mkdir(path.join(cwd, config.aliases.ui), { recursive: true })
await mkdir(path.join(cwd, config.aliases.lib), { recursive: true })
await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`)
console.log(`Created ${path.relative(process.cwd(), configPath) || configFileName}.`)
}
async function addItems(options) {
const names = options._.filter((item) => !item.startsWith("-"))
if (names.length === 0) {
throw new Error("Usage: base-ui-tailwind add <name...>")
}
const cwd = path.resolve(options.cwd ?? process.cwd())
const config = await loadConfig(cwd)
const manifestRef = options.manifest ?? config.manifest ?? bundledManifestPath
const manifest = await loadManifest(manifestRef, cwd)
const selected = resolveItems(manifest, names)
const files = collectFiles(manifest, selected)
const written = []
const skipped = []
const packageDependencies = collectPackageDependencies(manifest, selected)
for (const file of files) {
const targetPath = path.join(cwd, resolveTargetPath(file.target, config.aliases))
if (!options.overwrite && (await exists(targetPath))) {
skipped.push(path.relative(cwd, targetPath))
continue
}
if (!options.dryRun) {
await mkdir(path.dirname(targetPath), { recursive: true })
const source = await readSourceFile(file.path, manifestRef, cwd)
if (source.kind === "local") {
await copyFile(source.path, targetPath)
} else {
await writeFile(targetPath, source.contents)
}
}
written.push(path.relative(cwd, targetPath))
}
if (written.length > 0) {
console.log(`${options.dryRun ? "Would add" : "Added"}:`)
for (const file of written) {
console.log(` ${file}`)
}
}
if (skipped.length > 0) {
console.log("Skipped existing files:")
for (const file of skipped) {
console.log(` ${file}`)
}
console.log("Use --overwrite to replace existing files.")
}
if (packageDependencies.length > 0) {
console.log("Required packages:")
console.log(` ${packageDependencies.join(" ")}`)
}
}
function resolveItems(manifest, names) {
const resolved = new Set()
const queue = [...names]
while (queue.length > 0) {
const name = queue.shift()
const item = manifest.items?.[name]
if (!item) {
throw new Error(`Manifest item not found: ${name}`)
}
if (resolved.has(name)) {
continue
}
resolved.add(name)
for (const dependency of item.localDependencies ?? []) {
queue.push(dependency)
}
}
return [...resolved]
}
function collectFiles(manifest, names) {
const files = []
const seen = new Set()
for (const name of names) {
for (const file of manifest.items[name].files ?? []) {
const key = file.target
if (!seen.has(key)) {
seen.add(key)
files.push(file)
}
}
}
return files
}
function collectPackageDependencies(manifest, names) {
const dependencies = new Set()
for (const name of names) {
for (const dependency of manifest.items[name].dependencies ?? []) {
dependencies.add(dependency)
}
}
return [...dependencies].sort((a, b) => a.localeCompare(b))
}
async function loadConfig(cwd) {
const configPath = path.join(cwd, configFileName)
if (!(await exists(configPath))) {
return {
manifest: undefined,
aliases: {
ui: "components/ui",
lib: "lib",
},
}
}
const config = JSON.parse(await readFile(configPath, "utf8"))
return {
manifest: config.manifest,
aliases: {
ui: config.aliases?.ui ?? "components/ui",
lib: config.aliases?.lib ?? "lib",
},
}
}
async function loadManifest(manifestRef, cwd) {
const contents = isUrl(manifestRef)
? await fetchText(manifestRef)
: await readFile(resolveLocalPath(manifestRef, cwd), "utf8")
const manifest = JSON.parse(contents)
if (!manifest.items || typeof manifest.items !== "object") {
throw new Error("Invalid manifest: missing items.")
}
return manifest
}
async function readSourceFile(filePath, manifestRef, cwd) {
if (isUrl(manifestRef)) {
return {
kind: "remote",
contents: await fetchText(new URL(filePath, manifestRef).toString()),
}
}
return {
kind: "local",
path: path.join(path.dirname(resolveLocalPath(manifestRef, cwd)), filePath),
}
}
function resolveTargetPath(target, aliases) {
if (target.startsWith("src/components/ui/")) {
return path.join(aliases.ui, target.slice("src/components/ui/".length))
}
if (target.startsWith("src/lib/")) {
return path.join(aliases.lib, target.slice("src/lib/".length))
}
if (target.startsWith("components/ui/")) {
return path.join(aliases.ui, target.slice("components/ui/".length))
}
if (target.startsWith("lib/")) {
return path.join(aliases.lib, target.slice("lib/".length))
}
return target
}
function resolveLocalPath(value, cwd) {
if (path.isAbsolute(value)) {
return value
}
const projectPath = path.resolve(cwd, value)
return value === "manifest.json" && !existsSync(projectPath) ? bundledManifestPath : projectPath
}
function parseOptions(values) {
const options = { _: [] }
for (let index = 0; index < values.length; index += 1) {
const value = values[index]
if (value === "--cwd") {
options.cwd = values[++index]
} else if (value === "--manifest") {
options.manifest = values[++index]
} else if (value === "--force") {
options.force = true
} else if (value === "--overwrite") {
options.overwrite = true
} else if (value === "--dry-run") {
options.dryRun = true
} else {
options._.push(value)
}
}
return options
}
async function fetchText(url) {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`)
}
return response.text()
}
function existsSync(filePath) {
try {
accessSync(filePath)
return true
} catch {
return false
}
}
async function exists(filePath) {
try {
await access(filePath)
return true
} catch {
return false
}
}
function isUrl(value) {
return /^https?:\/\//.test(value)
}
function printHelp() {
console.log(`base-ui-tailwind
Usage:
base-ui-tailwind init [--manifest <path-or-url>] [--cwd <dir>] [--force]
base-ui-tailwind add <name...> [--manifest <path-or-url>] [--cwd <dir>] [--overwrite] [--dry-run]
`)
}
+39
View File
@@ -0,0 +1,39 @@
import Dialog, {
Dialog as ShadcnDialog,
DialogClose,
DialogContent,
DialogDescription,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import Button, { Button as UIButton } from "@/components/ui/button"
export function Smoke() {
return (
<div>
<Button focusableWhenDisabled>Primitive-style button</Button>
<UIButton>Named button</UIButton>
<Dialog.Root>
<Dialog.Trigger>Primitive dialog</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Backdrop />
<Dialog.Popup>
<Dialog.Title>Primitive dialog</Dialog.Title>
<Dialog.Description>Default namespace API.</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>
<ShadcnDialog>
<DialogTrigger>Named dialog</DialogTrigger>
<DialogContent>
<DialogTitle>Named dialog</DialogTitle>
<DialogDescription>Named shadcn-style API.</DialogDescription>
<DialogClose>Close</DialogClose>
</DialogContent>
</ShadcnDialog>
</div>
)
}
+1777
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
import { readdir, readFile } from "node:fs/promises"
import path from "node:path"
const uiComponentsPath = path.join("src", "components", "ui")
const componentEntries = await readdir(uiComponentsPath, { withFileTypes: true })
const components = componentEntries
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name)
.sort((a, b) => a.localeCompare(b))
const failures = []
for (const component of components) {
const indexPath = path.join(uiComponentsPath, component, "index.ts")
try {
const source = await readFile(indexPath, "utf8")
if (!source.includes("export default")) {
failures.push(`${indexPath}: missing default export`)
}
} catch (error) {
if (error.code !== "ENOENT") {
throw error
}
failures.push(`${indexPath}: missing file`)
}
}
if (failures.length > 0) {
console.error(failures.join("\n"))
process.exit(1)
}
console.log(`Checked ${components.length} component exports.`)
+166
View File
@@ -0,0 +1,166 @@
import { readdir, readFile, writeFile } from "node:fs/promises"
import path from "node:path"
import process from "node:process"
const root = process.cwd()
const sourceDir = path.join(root, "src")
const componentsDir = path.join(sourceDir, "components", "ui")
const libDir = path.join(sourceDir, "lib")
const outputPath = path.join(root, "manifest.json")
const packageJson = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"))
const components = await listDirectories(componentsDir)
const utils = await listFiles(libDir)
const items = {}
for (const file of utils) {
const name = path.basename(file, path.extname(file))
const source = await readFile(path.join(root, file), "utf8")
const target = stripSourcePrefix(file)
items[`utils/${name}`] = {
name: `utils/${name}`,
type: "util",
description: `Utility source for ${name}.`,
dependencies: collectPackageDependencies(source),
files: [
{
path: file,
target,
},
],
}
}
for (const component of components) {
const componentFiles = await listFiles(path.join("src", "components", "ui", component))
const sources = await Promise.all(
componentFiles.map(async (file) => readFile(path.join(root, file), "utf8")),
)
const source = sources.join("\n")
items[component] = {
name: component,
type: "component",
description: `${toTitle(component)} component wrapper for Base UI and Tailwind CSS.`,
dependencies: collectPackageDependencies(source),
localDependencies: collectLocalDependencies(source, component, components, utils),
files: componentFiles.map((file) => ({
path: file,
target: stripSourcePrefix(file),
})),
}
}
const manifest = {
name: "base-ui-tailwind",
version: packageJson.version ?? "0.0.0",
generatedAt: new Date().toISOString(),
command: "base-ui-tailwind",
configFile: "base-ui-tailwind.json",
dependencies: {
"@base-ui/react": packageJson.dependencies?.["@base-ui/react"],
"clsx": packageJson.dependencies?.clsx,
"lucide-react": packageJson.dependencies?.["lucide-react"],
"tailwind-merge": packageJson.dependencies?.["tailwind-merge"],
},
items,
}
await writeFile(outputPath, `${JSON.stringify(manifest, null, 2)}\n`)
console.log(`Generated manifest.json with ${Object.keys(items).length} items.`)
async function listDirectories(directory) {
const entries = await readdir(directory, { withFileTypes: true })
return entries
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name)
.sort((a, b) => a.localeCompare(b))
}
async function listFiles(relativeOrAbsoluteDirectory) {
const absoluteDirectory = path.isAbsolute(relativeOrAbsoluteDirectory)
? relativeOrAbsoluteDirectory
: path.join(root, relativeOrAbsoluteDirectory)
const relativeDirectory = path.relative(root, absoluteDirectory)
const entries = await readdir(absoluteDirectory, { withFileTypes: true })
const files = []
for (const entry of entries) {
const relativePath = path.join(relativeDirectory, entry.name)
const absolutePath = path.join(absoluteDirectory, entry.name)
if (entry.isDirectory()) {
files.push(...(await listFiles(absolutePath)))
} else if (entry.isFile()) {
files.push(relativePath.split(path.sep).join("/"))
}
}
return files.sort((a, b) => a.localeCompare(b))
}
function collectPackageDependencies(source) {
const dependencies = new Set()
const importPattern = /from\s+["']([^"']+)["']|import\s+["']([^"']+)["']/g
for (const match of source.matchAll(importPattern)) {
const specifier = match[1] ?? match[2]
if (!specifier || specifier.startsWith(".") || specifier.startsWith("@/")) {
continue
}
dependencies.add(getPackageName(specifier))
}
return [...dependencies].sort((a, b) => a.localeCompare(b))
}
function collectLocalDependencies(source, component, components, utils) {
const dependencies = new Set()
const localPattern = /from\s+["']@\/([^"']+)["']|import\s+["']@\/([^"']+)["']/g
for (const match of source.matchAll(localPattern)) {
const specifier = match[1] ?? match[2]
if (!specifier) {
continue
}
const componentMatch = specifier.match(/^components\/ui\/([^/]+)/)
if (componentMatch && componentMatch[1] !== component && components.includes(componentMatch[1])) {
dependencies.add(componentMatch[1])
continue
}
const utilMatch = specifier.match(/^lib\/([^/]+)/)
if (utilMatch) {
const utilPath = utils.find(
(file) => file === `src/lib/${utilMatch[1]}.ts` || file === `src/lib/${utilMatch[1]}.tsx`,
)
if (utilPath) {
dependencies.add(`utils/${path.basename(utilPath, path.extname(utilPath))}`)
}
}
}
return [...dependencies].sort((a, b) => a.localeCompare(b))
}
function stripSourcePrefix(file) {
return file.startsWith("src/") ? file.slice("src/".length) : file
}
function getPackageName(specifier) {
if (specifier.startsWith("@")) {
const [scope, name] = specifier.split("/")
return `${scope}/${name}`
}
return specifier.split("/")[0]
}
function toTitle(value) {
return value
.split("-")
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ")
}
+338
View File
@@ -0,0 +1,338 @@
import fs from "node:fs"
import path from "node:path"
const root = process.cwd()
const contentDir = path.join(root, "site/src/content/components")
const uiDir = path.join(root, "src/components/ui")
const examplesDir = path.join(root, "site/src/examples/components")
const finished = new Set(["menu", "context-menu", "navigation-menu"])
const names = {
"alert-dialog": "AlertDialog",
"checkbox-group": "CheckboxGroup",
"context-menu": "ContextMenu",
"navigation-menu": "NavigationMenu",
"number-field": "NumberField",
"otp-field": "OtpField",
"preview-card": "PreviewCard",
"scroll-area": "ScrollArea",
"toggle-group": "ToggleGroup",
}
const officialSlugs = {
"otp-field": "otp-field",
}
for (const file of fs.readdirSync(contentDir).sort()) {
if (!file.endsWith(".mdx")) continue
const slug = file.replace(/\.mdx$/, "")
if (finished.has(slug)) continue
const filePath = path.join(contentDir, file)
const current = fs.readFileSync(filePath, "utf8")
const title = current.match(/^# (.+)$/m)?.[1] ?? titleCase(slug)
const component = names[slug] ?? title.replace(/[^A-Za-z0-9]/g, "")
const parts = readParts(slug)
const exampleSrc = `components/${slug}/${slug}.tsx`
const hasTopExample = fs.existsSync(path.join(examplesDir, slug, `${slug}.tsx`))
const intro = readIntro(current, title)
const baseStyle = readSectionCode(current, "Base UI Style") ?? makeBaseStyle(slug, component, parts)
const shadcnStyle =
readSectionCode(current, "Shadcn Style") ??
readSectionCode(current, "Named Import Style") ??
makeNamedStyle(slug, component, parts)
const examples = readExamples(current, title, slug, exampleSrc, hasTopExample)
const next = [
`# ${title}`,
"",
intro || `${title} wraps Base UI's ${title.toLowerCase()} primitive with the Tailwind classes from the official Base UI example.`,
"",
hasTopExample ? `::example{src="${exampleSrc}"}` : "",
"",
"## Anatomy",
"",
"### Base UI Style",
"",
fenced(baseStyle),
"",
"### Shadcn Style",
"",
fenced(shadcnStyle),
"",
"## Composition",
"",
`Use the following composition to build \`${component}\`:`,
"",
"```txt",
makeComposition(component, parts).join("\n"),
"```",
"",
"## Examples",
"",
examples.trim(),
"",
makeApi(slug, title, component, parts),
"",
]
.filter((line, index, array) => !(line === "" && array[index - 1] === ""))
.join("\n")
fs.writeFileSync(filePath, next)
}
function readParts(slug) {
const indexPath = path.join(uiDir, slug, "index.ts")
if (!fs.existsSync(indexPath)) return ["Root"]
const source = fs.readFileSync(indexPath, "utf8")
const objectMatch = source.match(/const\s+\w+\s*=\s*\{([\s\S]*?)\n\}/)
if (!objectMatch) return ["Root"]
const parts = []
for (const line of objectMatch[1].split("\n")) {
const match = line.match(/^\s*([A-Za-z][A-Za-z0-9]*):/)
if (!match) continue
const part = match[1]
if (part[0] === part[0].toLowerCase()) continue
if (!parts.includes(part)) parts.push(part)
}
return parts.length ? parts : ["Root"]
}
function readIntro(source, title) {
const start = source.indexOf(`# ${title}`)
if (start === -1) return ""
let rest = source.slice(start + title.length + 3)
const stops = ["\n<ComponentPreview", "\nexport ", "\n## ", "\n::example"]
let end = rest.length
for (const stop of stops) {
const index = rest.indexOf(stop)
if (index !== -1 && index < end) end = index
}
rest = rest.slice(0, end)
return rest
.replace(/^import .+$/gm, "")
.replace(/\n{3,}/g, "\n\n")
.trim()
}
function readSectionCode(source, heading) {
const start = source.indexOf(`## ${heading}`)
if (start === -1) return null
const fenceStart = source.indexOf("```", start)
if (fenceStart === -1) return null
const lineEnd = source.indexOf("\n", fenceStart)
const fenceEnd = source.indexOf("\n```", lineEnd)
if (fenceEnd === -1) return null
return source.slice(lineEnd + 1, fenceEnd).trim()
}
function readExamples(source, title, slug, exampleSrc, hasTopExample) {
const start = source.indexOf("## Examples")
if (start === -1) return ""
const nextHeading = source.slice(start + 1).search(/\n## /)
const end = nextHeading === -1 ? source.length : start + 1 + nextHeading
let content = source.slice(start + "## Examples".length, end).trim()
if (hasTopExample) {
const escapedTitle = escapeRegExp(title)
const escapedSrc = escapeRegExp(exampleSrc)
const duplicate = new RegExp(`^### ${escapedTitle}\\n\\n::example\\{src="${escapedSrc}"\\}\\n*`, "m")
content = content.replace(duplicate, "").trim()
}
return content || "No additional examples yet."
}
function makeBaseStyle(slug, component, parts) {
const lines = [`import ${component} from "@/components/ui/${slug}"`, "", `<${component}.Root>`]
for (const part of parts.filter((part) => part !== "Root").slice(0, 5)) {
lines.push(` <${component}.${part} />`)
}
lines.push(`</${component}.Root>`)
return lines.join("\n")
}
function makeNamedStyle(slug, component, parts) {
const named = parts.map((part) => (part === "Root" ? component : `${component}${part}`))
return [
"import {",
...named.slice(0, 8).map((name) => ` ${name},`),
`} from "@/components/ui/${slug}"`,
].join("\n")
}
function makeComposition(component, parts) {
const has = (part) => parts.includes(part)
const portalChildren = []
if (has("Backdrop")) portalChildren.push(`${component}Backdrop`)
if (has("Positioner")) {
const popupChildren = []
for (const part of ["Arrow", "Viewport", "List", "Collection", "Group", "Item", "Empty"]) {
if (has(part)) popupChildren.push(`${component}${part}`)
}
portalChildren.push({
label: `${component}Positioner`,
children: has("Popup") ? [{ label: `${component}Popup`, children: popupChildren }] : popupChildren,
})
} else if (has("Popup")) {
portalChildren.push(`${component}Popup`)
}
const children = []
const leading = ["Trigger", "Label", "Input", "Control", "Track", "Thumb", "Image", "Fallback", "Group"]
for (const part of leading) {
if (has(part)) children.push(`${component}${part}`)
}
if (has("Portal")) {
children.push({ label: `${component}Portal`, children: portalChildren })
}
for (const part of parts) {
if (part === "Root" || leading.includes(part) || part === "Portal" || part === "Backdrop" || part === "Positioner" || part === "Popup") {
continue
}
const label = part === "Separator" ? `${component}.Separator` : `${component}${part}`
if (!treeHas(children, label)) children.push(label)
}
return renderTree({ label: component, children })
}
function treeHas(children, label) {
for (const child of children) {
if (typeof child === "string" && child === label) return true
if (typeof child === "object") {
if (child.label === label) return true
if (treeHas(child.children ?? [], label)) return true
}
}
return false
}
function renderTree(node, prefix = "") {
const lines = [prefix ? `${prefix}${node.label}` : node.label]
const children = node.children ?? []
children.forEach((child, index) => {
const last = index === children.length - 1
const branch = last ? "└── " : "├── "
const nextPrefix = prefix + (last ? " " : "│ ")
if (typeof child === "string") {
lines.push(`${prefix}${branch}${child}`)
} else {
lines.push(`${prefix}${branch}${child.label}`)
lines.push(...renderChildren(child.children ?? [], nextPrefix))
}
})
return lines
}
function renderChildren(children, prefix) {
const lines = []
children.forEach((child, index) => {
const last = index === children.length - 1
const branch = last ? "└── " : "├── "
const nextPrefix = prefix + (last ? " " : "│ ")
if (typeof child === "string") {
lines.push(`${prefix}${branch}${child}`)
} else {
lines.push(`${prefix}${branch}${child.label}`)
lines.push(...renderChildren(child.children ?? [], nextPrefix))
}
})
return lines
}
function makeApi(slug, title, component, parts) {
const official = `https://base-ui.com/react/components/${officialSlugs[slug] ?? slug}#api-reference`
const sections = parts.map((part) => makeApiPart(component, part)).join("\n\n")
return [
"## API Reference",
"",
`Official API: [Base UI ${title} API](${official}).`,
"",
`This wrapper preserves the underlying Base UI ${title} API. Styled parts forward \`className\`, \`style\`, and \`render\` where Base UI supports them.`,
"",
sections,
].join("\n")
}
function makeApiPart(component, part) {
const heading = part === "Root" ? "Root" : part
const label = part === "Root" ? component : `${component}.${part}`
const rows = apiRows(part)
return [
`### ${heading}`,
"",
`\`${label}\` exposes the corresponding Base UI part with the wrapper's Tailwind styles.`,
"",
"| Prop | Type | Default | Description |",
"| --- | --- | --- | --- |",
...rows,
].join("\n")
}
function apiRows(part) {
if (part === "Root") {
return [
"| `defaultValue` / `defaultOpen` | `any` | - | Initial uncontrolled value or open state when supported. |",
"| `value` / `open` | `any` | - | Controlled value or open state when supported. |",
"| `onValueChange` / `onOpenChange` | `function` | - | Called when controlled state changes. |",
"| `children` | `React.ReactNode` | - | Child parts rendered inside the root. |",
]
}
if (part === "Portal") {
return [
"| `container` | `HTMLElement \\| RefObject<HTMLElement>` | `document.body` | Element that receives portal content. |",
"| `keepMounted` | `boolean` | `false` | Keeps children mounted when closed. |",
"| `children` | `React.ReactNode` | - | Floating content. |",
]
}
if (part === "Positioner") {
return [
"| `side` | `Side` | - | Preferred side for floating content. |",
"| `align` | `Align` | - | Alignment on the selected side. |",
"| `sideOffset` | `number \\| OffsetFunction` | `0` | Distance from the anchor. |",
"| `collisionAvoidance` | `CollisionAvoidance` | - | Controls flip and shift behavior. |",
"| `className` | `string \\| (state) => string` | - | Classes for placement state. |",
]
}
if (["Trigger", "Item", "LinkItem", "Link", "Button", "Close", "Action"].includes(part)) {
return [
"| `disabled` | `boolean` | `false` | Prevents user interaction when supported. |",
"| `onClick` | `function` | - | Called when the element is pressed. |",
"| `className` | `string \\| (state) => string` | - | Classes for interactive state. |",
"| `render` | `ReactElement \\| (props, state) => ReactElement` | - | Replaces the rendered element. |",
"| `children` | `React.ReactNode` | - | Visible content. |",
]
}
if (["CheckboxItem", "RadioGroup", "RadioItem"].includes(part)) {
return [
"| `checked` / `value` | `any` | - | Controlled checked or selected state when supported. |",
"| `defaultChecked` / `defaultValue` | `any` | - | Initial uncontrolled state when supported. |",
"| `onCheckedChange` / `onValueChange` | `function` | - | Called when selection changes. |",
"| `disabled` | `boolean` | `false` | Prevents user interaction. |",
"| `className` | `string \\| (state) => string` | - | Classes for checked, highlighted, and disabled state. |",
]
}
return [
"| `className` | `string \\| (state) => string` | - | Classes for the part state. |",
"| `style` | `React.CSSProperties \\| (state) => React.CSSProperties` | - | Inline style or state-based style. |",
"| `render` | `ReactElement \\| (props, state) => ReactElement` | - | Replaces the rendered element when supported. |",
"| `children` | `React.ReactNode` | - | Child content when the part accepts children. |",
]
}
function fenced(value) {
return ["```tsx", value.trim(), "```"].join("\n")
}
function titleCase(slug) {
return slug
.split("-")
.map((word) => word[0].toUpperCase() + word.slice(1))
.join(" ")
}
function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
}
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Accordion as BaseAccordion } from "@base-ui/react/accordion"
import { cn } from "@/lib/utils"
export type AccordionHeaderProps = React.ComponentPropsWithoutRef<typeof BaseAccordion.Header> & {
className?: string
}
const BaseAccordionHeader = BaseAccordion.Header as React.ElementType
export const AccordionHeader = React.forwardRef<HTMLElement, AccordionHeaderProps>(
({ className, ...props }, ref) => (
<BaseAccordionHeader
ref={ref}
className={cn(
"flex",
className,
)}
{...props}
/>
),
)
AccordionHeader.displayName = "AccordionHeader"
+30
View File
@@ -0,0 +1,30 @@
import { AccordionRoot } from "./root"
import { AccordionItem } from "./item"
import { AccordionHeader } from "./header"
import { AccordionTrigger } from "./trigger"
import { AccordionPanel } from "./panel"
const AccordionPrimitive = {
Root: AccordionRoot,
Item: AccordionItem,
Header: AccordionHeader,
Trigger: AccordionTrigger,
Panel: AccordionPanel,
}
export default AccordionPrimitive
export {
AccordionRoot as Accordion,
AccordionRoot,
AccordionItem,
AccordionHeader,
AccordionTrigger,
AccordionPanel,
}
export type { AccordionRootProps } from "./root"
export type { AccordionItemProps } from "./item"
export type { AccordionHeaderProps } from "./header"
export type { AccordionTriggerProps } from "./trigger"
export type { AccordionPanelProps } from "./panel"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Accordion as BaseAccordion } from "@base-ui/react/accordion"
import { cn } from "@/lib/utils"
export type AccordionItemProps = React.ComponentPropsWithoutRef<typeof BaseAccordion.Item> & {
className?: string
}
const BaseAccordionItem = BaseAccordion.Item as React.ElementType
export const AccordionItem = React.forwardRef<HTMLElement, AccordionItemProps>(
({ className, ...props }, ref) => (
<BaseAccordionItem
ref={ref}
className={cn(className)}
{...props}
/>
),
)
AccordionItem.displayName = "AccordionItem"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Accordion as BaseAccordion } from "@base-ui/react/accordion"
import { cn } from "@/lib/utils"
export type AccordionPanelProps = React.ComponentPropsWithoutRef<typeof BaseAccordion.Panel> & {
className?: string
}
const BaseAccordionPanel = BaseAccordion.Panel as React.ElementType
export const AccordionPanel = React.forwardRef<HTMLElement, AccordionPanelProps>(
({ className, ...props }, ref) => (
<BaseAccordionPanel
ref={ref}
className={cn(
"h-(--accordion-panel-height) overflow-hidden text-sm transition-[height] duration-150 ease-[ease-out] data-ending-style:h-0 data-starting-style:h-0",
className,
)}
{...props}
/>
),
)
AccordionPanel.displayName = "AccordionPanel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Accordion as BaseAccordion } from "@base-ui/react/accordion"
import { cn } from "@/lib/utils"
export type AccordionRootProps = React.ComponentPropsWithoutRef<typeof BaseAccordion.Root> & {
className?: string
}
const BaseAccordionRoot = BaseAccordion.Root as React.ElementType
export const AccordionRoot = React.forwardRef<HTMLElement, AccordionRootProps>(
({ className, ...props }, ref) => (
<BaseAccordionRoot
ref={ref}
className={cn(
"flex w-full max-w-80 flex-col border border-neutral-950 text-neutral-950 dark:border-white dark:text-white",
className,
)}
{...props}
/>
),
)
AccordionRoot.displayName = "AccordionRoot"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Accordion as BaseAccordion } from "@base-ui/react/accordion"
import { cn } from "@/lib/utils"
export type AccordionTriggerProps = React.ComponentPropsWithoutRef<typeof BaseAccordion.Trigger> & {
className?: string
}
const BaseAccordionTrigger = BaseAccordion.Trigger as React.ElementType
export const AccordionTrigger = React.forwardRef<HTMLElement, AccordionTriggerProps>(
({ className, ...props }, ref) => (
<BaseAccordionTrigger
ref={ref}
className={cn(
"group flex w-full items-center justify-between gap-4 bg-transparent px-3 py-2 text-left text-sm font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 focus-visible:relative focus-visible:z-1 focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-neutral-950 dark:focus-visible:outline-white dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800",
className,
)}
{...props}
/>
),
)
AccordionTrigger.displayName = "AccordionTrigger"
@@ -0,0 +1,27 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogBackdropProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Backdrop> & {
className?: string
}
const BaseAlertDialogBackdrop = BaseAlertDialog.Backdrop as React.ElementType
export const AlertDialogBackdrop = React.forwardRef<HTMLElement, AlertDialogBackdropProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogBackdrop
ref={ref}
className={cn(
"z-40",
"fixed inset-0 min-h-dvh bg-black opacity-20 transition-opacity duration-350 ease-out data-ending-style:duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:opacity-50 supports-[-webkit-touch-callout:none]:absolute",
className,
)}
{...props}
/>
),
)
AlertDialogBackdrop.displayName = "AlertDialogBackdrop"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogCloseProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Close> & {
className?: string
}
const BaseAlertDialogClose = BaseAlertDialog.Close as React.ElementType
export const AlertDialogClose = React.forwardRef<HTMLElement, AlertDialogCloseProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogClose
ref={ref}
className={cn(
"flex h-8 items-center justify-center gap-2 border border-neutral-950 bg-white px-3 text-sm leading-none whitespace-nowrap font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 [&:not([data-disabled]):active]:bg-neutral-200 data-disabled:border-neutral-500 data-disabled:text-neutral-500 disabled:border-neutral-500 disabled:text-neutral-500 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800 dark:[&:not([data-disabled]):active]:bg-neutral-700 dark:data-disabled:border-neutral-400 dark:data-disabled:text-neutral-400 dark:focus-visible:outline-white",
className,
)}
{...props}
/>
),
)
AlertDialogClose.displayName = "AlertDialogClose"
@@ -0,0 +1,20 @@
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
import { AlertDialogBackdrop } from "./backdrop"
import { AlertDialogPortal } from "./portal"
import { AlertDialogPopup, type AlertDialogPopupProps } from "./popup"
export type AlertDialogContentProps = AlertDialogPopupProps
export const AlertDialogContent = React.forwardRef<HTMLElement, AlertDialogContentProps>(
({ className, ...props }, ref) => (
<AlertDialogPortal>
<AlertDialogBackdrop />
<AlertDialogPopup ref={ref} className={cn(className)} {...props} />
</AlertDialogPortal>
),
)
AlertDialogContent.displayName = "AlertDialogContent"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogDescriptionProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Description> & {
className?: string
}
const BaseAlertDialogDescription = BaseAlertDialog.Description as React.ElementType
export const AlertDialogDescription = React.forwardRef<HTMLElement, AlertDialogDescriptionProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogDescription
ref={ref}
className={cn(
"text-sm text-neutral-600 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
AlertDialogDescription.displayName = "AlertDialogDescription"
+52
View File
@@ -0,0 +1,52 @@
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { AlertDialogRoot } from "./root"
import { AlertDialogBackdrop } from "./backdrop"
import { AlertDialogClose } from "./close"
import { AlertDialogDescription } from "./description"
import { AlertDialogPopup } from "./popup"
import { AlertDialogPortal } from "./portal"
import { AlertDialogTitle } from "./title"
import { AlertDialogTrigger } from "./trigger"
import { AlertDialogViewport } from "./viewport"
import { AlertDialogContent } from "./content"
const AlertDialogPrimitive = {
Root: AlertDialogRoot,
Backdrop: AlertDialogBackdrop,
Close: AlertDialogClose,
Description: AlertDialogDescription,
Popup: AlertDialogPopup,
Portal: AlertDialogPortal,
Title: AlertDialogTitle,
Trigger: AlertDialogTrigger,
Viewport: AlertDialogViewport,
createHandle: BaseAlertDialog.createHandle,
}
export default AlertDialogPrimitive
export {
AlertDialogRoot as AlertDialog,
AlertDialogRoot,
AlertDialogBackdrop,
AlertDialogClose,
AlertDialogDescription,
AlertDialogPopup,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogTrigger,
AlertDialogViewport,
AlertDialogContent,
BaseAlertDialog,
}
export type { AlertDialogRootProps } from "./root"
export type { AlertDialogBackdropProps } from "./backdrop"
export type { AlertDialogCloseProps } from "./close"
export type { AlertDialogDescriptionProps } from "./description"
export type { AlertDialogPopupProps } from "./popup"
export type { AlertDialogPortalProps } from "./portal"
export type { AlertDialogTitleProps } from "./title"
export type { AlertDialogTriggerProps } from "./trigger"
export type { AlertDialogViewportProps } from "./viewport"
export type { AlertDialogContentProps } from "./content"
+27
View File
@@ -0,0 +1,27 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogPopupProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Popup> & {
className?: string
}
const BaseAlertDialogPopup = BaseAlertDialog.Popup as React.ElementType
export const AlertDialogPopup = React.forwardRef<HTMLElement, AlertDialogPopupProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogPopup
ref={ref}
className={cn(
"z-50",
"fixed top-1/2 left-1/2 -mt-8 flex w-96 max-w-[calc(100vw-3rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 bg-white dark:bg-neutral-950 p-4 text-neutral-950 dark:text-white border border-neutral-950 dark:border-white shadow-[0.25rem_0.25rem_0_rgb(0_0_0/12%)] dark:shadow-none transition-[transform,opacity] duration-350 ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-ending-style:scale-[0.98] data-ending-style:opacity-0 data-starting-style:scale-[0.98] data-starting-style:opacity-0",
className,
)}
{...props}
/>
),
)
AlertDialogPopup.displayName = "AlertDialogPopup"
+29
View File
@@ -0,0 +1,29 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
import { usePortalContainer } from "@/lib/portal-container"
export type AlertDialogPortalProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Portal> & {
className?: string
}
const BaseAlertDialogPortal = BaseAlertDialog.Portal as React.ElementType
export const AlertDialogPortal = React.forwardRef<HTMLElement, AlertDialogPortalProps>(
({ className, container, ...props }, ref) => {
const portalContainer = usePortalContainer()
return (
<BaseAlertDialogPortal
ref={ref}
className={cn(className)}
container={container ?? portalContainer ?? undefined}
{...props}
/>
)
},
)
AlertDialogPortal.displayName = "AlertDialogPortal"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogRootProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Root> & {
className?: string
}
const BaseAlertDialogRoot = BaseAlertDialog.Root as React.ElementType
export const AlertDialogRoot = React.forwardRef<HTMLElement, AlertDialogRootProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogRoot
ref={ref}
className={cn(className)}
{...props}
/>
),
)
AlertDialogRoot.displayName = "AlertDialogRoot"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogTitleProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Title> & {
className?: string
}
const BaseAlertDialogTitle = BaseAlertDialog.Title as React.ElementType
export const AlertDialogTitle = React.forwardRef<HTMLElement, AlertDialogTitleProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogTitle
ref={ref}
className={cn(
"text-base font-bold",
className,
)}
{...props}
/>
),
)
AlertDialogTitle.displayName = "AlertDialogTitle"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogTriggerProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Trigger> & {
className?: string
}
const BaseAlertDialogTrigger = BaseAlertDialog.Trigger as React.ElementType
export const AlertDialogTrigger = React.forwardRef<HTMLElement, AlertDialogTriggerProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogTrigger
ref={ref}
className={cn(
"flex h-8 items-center justify-center gap-2 border border-neutral-950 bg-white px-3 text-sm leading-none whitespace-nowrap font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 [&:not([data-disabled]):active]:bg-neutral-200 data-disabled:border-neutral-500 data-disabled:text-neutral-500 disabled:border-neutral-500 disabled:text-neutral-500 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800 dark:[&:not([data-disabled]):active]:bg-neutral-700 dark:data-disabled:border-neutral-400 dark:data-disabled:text-neutral-400 dark:focus-visible:outline-white",
className,
)}
{...props}
/>
),
)
AlertDialogTrigger.displayName = "AlertDialogTrigger"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog"
import { cn } from "@/lib/utils"
export type AlertDialogViewportProps = React.ComponentPropsWithoutRef<typeof BaseAlertDialog.Viewport> & {
className?: string
}
const BaseAlertDialogViewport = BaseAlertDialog.Viewport as React.ElementType
export const AlertDialogViewport = React.forwardRef<HTMLElement, AlertDialogViewportProps>(
({ className, ...props }, ref) => (
<BaseAlertDialogViewport
ref={ref}
className={cn(
"z-50 outline-none",
className,
)}
{...props}
/>
),
)
AlertDialogViewport.displayName = "AlertDialogViewport"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteArrowProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Arrow> & {
className?: string
}
const BaseAutocompleteArrow = BaseAutocomplete.Arrow as React.ElementType
export const AutocompleteArrow = React.forwardRef<HTMLElement, AutocompleteArrowProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteArrow
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-neutral-500 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
AutocompleteArrow.displayName = "AutocompleteArrow"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteBackdropProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Backdrop> & {
className?: string
}
const BaseAutocompleteBackdrop = BaseAutocomplete.Backdrop as React.ElementType
export const AutocompleteBackdrop = React.forwardRef<HTMLElement, AutocompleteBackdropProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteBackdrop
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-black/20 backdrop-blur-[1px] transition-opacity data-ending-style:opacity-0 data-starting-style:opacity-0 dark:bg-black/50",
className,
)}
{...props}
/>
),
)
AutocompleteBackdrop.displayName = "AutocompleteBackdrop"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteClearProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Clear> & {
className?: string
}
const BaseAutocompleteClear = BaseAutocomplete.Clear as React.ElementType
export const AutocompleteClear = React.forwardRef<HTMLElement, AutocompleteClearProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteClear
ref={ref}
className={cn(
"combobox-clear flex h-full w-6 items-center justify-center border-0 bg-transparent p-0 text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
AutocompleteClear.displayName = "AutocompleteClear"
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteCollectionProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Collection> & {
className?: string
}
const BaseAutocompleteCollection = BaseAutocomplete.Collection as React.ElementType
export const AutocompleteCollection = React.forwardRef<HTMLElement, AutocompleteCollectionProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteCollection
ref={ref}
className={cn(className)}
{...props}
/>
),
)
AutocompleteCollection.displayName = "AutocompleteCollection"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteEmptyProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Empty> & {
className?: string
}
const BaseAutocompleteEmpty = BaseAutocomplete.Empty as React.ElementType
export const AutocompleteEmpty = React.forwardRef<HTMLElement, AutocompleteEmptyProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteEmpty
ref={ref}
className={cn(
"text-sm text-neutral-600 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
AutocompleteEmpty.displayName = "AutocompleteEmpty"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteGroupLabelProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.GroupLabel> & {
className?: string
}
const BaseAutocompleteGroupLabel = BaseAutocomplete.GroupLabel as React.ElementType
export const AutocompleteGroupLabel = React.forwardRef<HTMLElement, AutocompleteGroupLabelProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteGroupLabel
ref={ref}
className={cn(
"flex min-h-8 items-center pr-6 pl-3 text-sm leading-none font-normal text-neutral-500 select-none outline-none dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
AutocompleteGroupLabel.displayName = "AutocompleteGroupLabel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteGroupProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Group> & {
className?: string
}
const BaseAutocompleteGroup = BaseAutocomplete.Group as React.ElementType
export const AutocompleteGroup = React.forwardRef<HTMLElement, AutocompleteGroupProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteGroup
ref={ref}
className={cn(
"not-last:mb-1",
className,
)}
{...props}
/>
),
)
AutocompleteGroup.displayName = "AutocompleteGroup"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteIconProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Icon> & {
className?: string
}
const BaseAutocompleteIcon = BaseAutocomplete.Icon as React.ElementType
export const AutocompleteIcon = React.forwardRef<HTMLElement, AutocompleteIconProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteIcon
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-neutral-500 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
AutocompleteIcon.displayName = "AutocompleteIcon"
+92
View File
@@ -0,0 +1,92 @@
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { AutocompleteRoot } from "./root"
import { AutocompleteValue } from "./value"
import { AutocompleteTrigger } from "./trigger"
import { AutocompleteInput } from "./input"
import { AutocompleteInputGroup } from "./input-group"
import { AutocompleteIcon } from "./icon"
import { AutocompleteClear } from "./clear"
import { AutocompleteList } from "./list"
import { AutocompletePortal } from "./portal"
import { AutocompleteBackdrop } from "./backdrop"
import { AutocompletePositioner } from "./positioner"
import { AutocompletePopup } from "./popup"
import { AutocompleteArrow } from "./arrow"
import { AutocompleteGroup } from "./group"
import { AutocompleteGroupLabel } from "./group-label"
import { AutocompleteItem } from "./item"
import { AutocompleteRow } from "./row"
import { AutocompleteCollection } from "./collection"
import { AutocompleteEmpty } from "./empty"
const AutocompletePrimitive = {
Root: AutocompleteRoot,
Value: AutocompleteValue,
Trigger: AutocompleteTrigger,
Input: AutocompleteInput,
InputGroup: AutocompleteInputGroup,
Icon: AutocompleteIcon,
Clear: AutocompleteClear,
List: AutocompleteList,
Portal: AutocompletePortal,
Backdrop: AutocompleteBackdrop,
Positioner: AutocompletePositioner,
Popup: AutocompletePopup,
Arrow: AutocompleteArrow,
Group: AutocompleteGroup,
GroupLabel: AutocompleteGroupLabel,
Item: AutocompleteItem,
Row: AutocompleteRow,
Collection: AutocompleteCollection,
Empty: AutocompleteEmpty,
Separator: BaseAutocomplete.Separator,
Status: BaseAutocomplete.Status,
useFilter: BaseAutocomplete.useFilter,
useFilteredItems: BaseAutocomplete.useFilteredItems,
}
export default AutocompletePrimitive
export {
AutocompleteRoot as Autocomplete,
AutocompleteRoot,
AutocompleteValue,
AutocompleteTrigger,
AutocompleteInput,
AutocompleteInputGroup,
AutocompleteIcon,
AutocompleteClear,
AutocompleteList,
AutocompletePortal,
AutocompleteBackdrop,
AutocompletePositioner,
AutocompletePopup,
AutocompleteArrow,
AutocompleteGroup,
AutocompleteGroupLabel,
AutocompleteItem,
AutocompleteRow,
AutocompleteCollection,
AutocompleteEmpty,
BaseAutocomplete,
}
export type { AutocompleteRootProps } from "./root"
export type { AutocompleteValueProps } from "./value"
export type { AutocompleteTriggerProps } from "./trigger"
export type { AutocompleteInputProps } from "./input"
export type { AutocompleteInputGroupProps } from "./input-group"
export type { AutocompleteIconProps } from "./icon"
export type { AutocompleteClearProps } from "./clear"
export type { AutocompleteListProps } from "./list"
export type { AutocompletePortalProps } from "./portal"
export type { AutocompleteBackdropProps } from "./backdrop"
export type { AutocompletePositionerProps } from "./positioner"
export type { AutocompletePopupProps } from "./popup"
export type { AutocompleteArrowProps } from "./arrow"
export type { AutocompleteGroupProps } from "./group"
export type { AutocompleteGroupLabelProps } from "./group-label"
export type { AutocompleteItemProps } from "./item"
export type { AutocompleteRowProps } from "./row"
export type { AutocompleteCollectionProps } from "./collection"
export type { AutocompleteEmptyProps } from "./empty"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteInputGroupProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.InputGroup> & {
className?: string
}
const BaseAutocompleteInputGroup = BaseAutocomplete.InputGroup as React.ElementType
export const AutocompleteInputGroup = React.forwardRef<HTMLElement, AutocompleteInputGroupProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteInputGroup
ref={ref}
className={cn(
"flex items-center gap-2",
className,
)}
{...props}
/>
),
)
AutocompleteInputGroup.displayName = "AutocompleteInputGroup"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteInputProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Input> & {
className?: string
}
const BaseAutocompleteInput = BaseAutocomplete.Input as React.ElementType
export const AutocompleteInput = React.forwardRef<HTMLElement, AutocompleteInputProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteInput
ref={ref}
className={cn(
"h-8 w-[16rem] border border-neutral-950 bg-white dark:bg-neutral-950 px-2 text-sm any-pointer-coarse:text-base font-normal text-neutral-950 placeholder:opacity-100 placeholder:text-neutral-500 placeholder:[-webkit-text-fill-color:var(--color-neutral-500)] dark:placeholder:text-neutral-400 dark:placeholder:[-webkit-text-fill-color:var(--color-neutral-400)] focus:outline-2 focus:outline-solid focus:-outline-offset-1 focus:outline-neutral-950 dark:focus:outline-white dark:border-white dark:text-white",
className,
)}
{...props}
/>
),
)
AutocompleteInput.displayName = "AutocompleteInput"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteItemProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Item> & {
className?: string
}
const BaseAutocompleteItem = BaseAutocomplete.Item as React.ElementType
export const AutocompleteItem = React.forwardRef<HTMLElement, AutocompleteItemProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteItem
ref={ref}
className={cn(
"flex cursor-default items-center gap-2 py-2 pr-2 pl-2 text-sm leading-4 outline-none select-none data-highlighted:relative data-highlighted:z-0 data-highlighted:text-white data-highlighted:before:absolute data-highlighted:before:inset-x-0 data-highlighted:before:inset-y-0 data-highlighted:before:z-[-1] data-highlighted:before:bg-neutral-950 dark:data-highlighted:text-neutral-950 dark:data-highlighted:before:bg-white",
className,
)}
{...props}
/>
),
)
AutocompleteItem.displayName = "AutocompleteItem"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteListProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.List> & {
className?: string
}
const BaseAutocompleteList = BaseAutocomplete.List as React.ElementType
export const AutocompleteList = React.forwardRef<HTMLElement, AutocompleteListProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteList
ref={ref}
className={cn(
"outline-0 overflow-y-auto scroll-py-1 py-1 overscroll-contain max-h-[min(22.5rem,var(--available-height))] data-empty:p-0",
className,
)}
{...props}
/>
),
)
AutocompleteList.displayName = "AutocompleteList"
+25
View File
@@ -0,0 +1,25 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompletePopupProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Popup> & {
className?: string
}
const BaseAutocompletePopup = BaseAutocomplete.Popup as React.ElementType
const defaultAutocompletePopupClassName =
"w-[var(--anchor-width)] max-w-[var(--available-width)] border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none"
export const AutocompletePopup = React.forwardRef<HTMLElement, AutocompletePopupProps>(
({ className, ...props }, ref) => (
<BaseAutocompletePopup
ref={ref}
className={cn(className ?? defaultAutocompletePopupClassName)}
{...props}
/>
),
)
AutocompletePopup.displayName = "AutocompletePopup"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompletePortalProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Portal> & {
className?: string
}
const BaseAutocompletePortal = BaseAutocomplete.Portal as React.ElementType
export const AutocompletePortal = React.forwardRef<HTMLElement, AutocompletePortalProps>(
({ className, ...props }, ref) => (
<BaseAutocompletePortal
ref={ref}
className={cn(className)}
{...props}
/>
),
)
AutocompletePortal.displayName = "AutocompletePortal"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompletePositionerProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Positioner> & {
className?: string
}
const BaseAutocompletePositioner = BaseAutocomplete.Positioner as React.ElementType
export const AutocompletePositioner = React.forwardRef<HTMLElement, AutocompletePositionerProps>(
({ className, ...props }, ref) => (
<BaseAutocompletePositioner
ref={ref}
className={cn(
"outline-none",
className,
)}
{...props}
/>
),
)
AutocompletePositioner.displayName = "AutocompletePositioner"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteRootProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Root> & {
className?: string
}
const BaseAutocompleteRoot = BaseAutocomplete.Root as React.ElementType
export const AutocompleteRoot = React.forwardRef<HTMLElement, AutocompleteRootProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteRoot
ref={ref}
className={cn(className)}
{...props}
/>
),
)
AutocompleteRoot.displayName = "AutocompleteRoot"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteRowProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Row> & {
className?: string
}
const BaseAutocompleteRow = BaseAutocomplete.Row as React.ElementType
export const AutocompleteRow = React.forwardRef<HTMLElement, AutocompleteRowProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteRow
ref={ref}
className={cn(
"grid grid-cols-5",
className,
)}
{...props}
/>
),
)
AutocompleteRow.displayName = "AutocompleteRow"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteTriggerProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Trigger> & {
className?: string
}
const BaseAutocompleteTrigger = BaseAutocomplete.Trigger as React.ElementType
export const AutocompleteTrigger = React.forwardRef<HTMLElement, AutocompleteTriggerProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteTrigger
ref={ref}
className={cn(
"flex size-8 items-center justify-center border border-neutral-950 bg-transparent text-xl leading-none text-neutral-950 outline-none hover:bg-neutral-100 active:bg-neutral-200 focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white data-[popup-open]:bg-neutral-100 dark:border-white dark:text-white dark:hover:bg-neutral-800 dark:active:bg-neutral-700 dark:data-[popup-open]:bg-neutral-800",
className,
)}
{...props}
/>
),
)
AutocompleteTrigger.displayName = "AutocompleteTrigger"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete"
import { cn } from "@/lib/utils"
export type AutocompleteValueProps = React.ComponentPropsWithoutRef<typeof BaseAutocomplete.Value> & {
className?: string
}
const BaseAutocompleteValue = BaseAutocomplete.Value as React.ElementType
export const AutocompleteValue = React.forwardRef<HTMLElement, AutocompleteValueProps>(
({ className, ...props }, ref) => (
<BaseAutocompleteValue
ref={ref}
className={cn(
"text-sm text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
AutocompleteValue.displayName = "AutocompleteValue"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Avatar as BaseAvatar } from "@base-ui/react/avatar"
import { cn } from "@/lib/utils"
export type AvatarFallbackProps = React.ComponentPropsWithoutRef<typeof BaseAvatar.Fallback> & {
className?: string
}
const BaseAvatarFallback = BaseAvatar.Fallback as React.ElementType
export const AvatarFallback = React.forwardRef<HTMLElement, AvatarFallbackProps>(
({ className, ...props }, ref) => (
<BaseAvatarFallback
ref={ref}
className={cn(
"flex size-full items-center justify-center text-sm",
className,
)}
{...props}
/>
),
)
AvatarFallback.displayName = "AvatarFallback"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Avatar as BaseAvatar } from "@base-ui/react/avatar"
import { cn } from "@/lib/utils"
export type AvatarImageProps = React.ComponentPropsWithoutRef<typeof BaseAvatar.Image> & {
className?: string
}
const BaseAvatarImage = BaseAvatar.Image as React.ElementType
export const AvatarImage = React.forwardRef<HTMLElement, AvatarImageProps>(
({ className, ...props }, ref) => (
<BaseAvatarImage
ref={ref}
className={cn(
"size-full object-cover",
className,
)}
{...props}
/>
),
)
AvatarImage.displayName = "AvatarImage"
+22
View File
@@ -0,0 +1,22 @@
import { AvatarRoot } from "./root"
import { AvatarImage } from "./image"
import { AvatarFallback } from "./fallback"
const AvatarPrimitive = {
Root: AvatarRoot,
Image: AvatarImage,
Fallback: AvatarFallback,
}
export default AvatarPrimitive
export {
AvatarRoot as Avatar,
AvatarRoot,
AvatarImage,
AvatarFallback,
}
export type { AvatarRootProps } from "./root"
export type { AvatarImageProps } from "./image"
export type { AvatarFallbackProps } from "./fallback"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Avatar as BaseAvatar } from "@base-ui/react/avatar"
import { cn } from "@/lib/utils"
export type AvatarRootProps = React.ComponentPropsWithoutRef<typeof BaseAvatar.Root> & {
className?: string
}
const BaseAvatarRoot = BaseAvatar.Root as React.ElementType
export const AvatarRoot = React.forwardRef<HTMLElement, AvatarRootProps>(
({ className, ...props }, ref) => (
<BaseAvatarRoot
ref={ref}
className={cn(
"inline-flex size-8 items-center justify-center overflow-hidden rounded-full bg-neutral-200 align-middle text-sm leading-none font-normal text-neutral-950 select-none dark:bg-neutral-800 dark:text-white",
className,
)}
{...props}
/>
),
)
AvatarRoot.displayName = "AvatarRoot"
+4
View File
@@ -0,0 +1,4 @@
import { Button } from "./root"
export { Button, type ButtonProps } from "./root"
export default Button
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Button as BaseButton } from "@base-ui/react/button"
import { cn } from "@/lib/utils"
export type ButtonProps = React.ComponentPropsWithoutRef<typeof BaseButton> & {
className?: string
}
const BaseButtonElement = BaseButton as React.ElementType
export const Button = React.forwardRef<HTMLElement, ButtonProps>(
({ className, ...props }, ref) => (
<BaseButtonElement
ref={ref}
className={cn(
"flex h-8 items-center justify-center gap-2 rounded-none border border-neutral-950 bg-white px-3 text-sm leading-none whitespace-nowrap font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 [&:not([data-disabled]):active]:bg-neutral-200 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white data-disabled:cursor-default data-disabled:border-neutral-500 data-disabled:text-neutral-500 disabled:cursor-default disabled:border-neutral-500 disabled:text-neutral-500 dark:border-white dark:bg-neutral-950 dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800 dark:[&:not([data-disabled]):active]:bg-neutral-700 dark:data-disabled:border-neutral-400 dark:data-disabled:text-neutral-400",
className,
)}
{...props}
/>
),
)
Button.displayName = "Button"
@@ -0,0 +1,4 @@
import { CheckboxGroup } from "./root"
export { CheckboxGroup, type CheckboxGroupProps } from "./root"
export default CheckboxGroup
+21
View File
@@ -0,0 +1,21 @@
"use client"
import * as React from "react"
import { CheckboxGroup as BaseCheckboxGroup } from "@base-ui/react/checkbox-group"
import { cn } from "@/lib/utils"
export type CheckboxGroupProps = React.ComponentPropsWithoutRef<typeof BaseCheckboxGroup> & { className?: string }
const BaseCheckboxGroupElement = BaseCheckboxGroup as React.ElementType
export const CheckboxGroup = React.forwardRef<HTMLElement, CheckboxGroupProps>(
({ className, ...props }, ref) => (
<BaseCheckboxGroupElement
ref={ref}
className={cn("flex flex-col items-start gap-1 text-neutral-950 dark:text-white", className)}
{...props}
/>
),
)
CheckboxGroup.displayName = "CheckboxGroup"
+18
View File
@@ -0,0 +1,18 @@
import { CheckboxRoot } from "./root"
import { CheckboxIndicator } from "./indicator"
const CheckboxPrimitive = {
Root: CheckboxRoot,
Indicator: CheckboxIndicator,
}
export default CheckboxPrimitive
export {
CheckboxRoot as Checkbox,
CheckboxRoot,
CheckboxIndicator,
}
export type { CheckboxRootProps } from "./root"
export type { CheckboxIndicatorProps } from "./indicator"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox"
import { cn } from "@/lib/utils"
export type CheckboxIndicatorProps = React.ComponentPropsWithoutRef<typeof BaseCheckbox.Indicator> & {
className?: string
}
const BaseCheckboxIndicator = BaseCheckbox.Indicator as React.ElementType
export const CheckboxIndicator = React.forwardRef<HTMLElement, CheckboxIndicatorProps>(
({ className, ...props }, ref) => (
<BaseCheckboxIndicator
ref={ref}
className={cn(
"flex data-unchecked:hidden",
className,
)}
{...props}
/>
),
)
CheckboxIndicator.displayName = "CheckboxIndicator"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox"
import { cn } from "@/lib/utils"
export type CheckboxRootProps = React.ComponentPropsWithoutRef<typeof BaseCheckbox.Root> & {
className?: string
}
const BaseCheckboxRoot = BaseCheckbox.Root as React.ElementType
export const CheckboxRoot = React.forwardRef<HTMLElement, CheckboxRootProps>(
({ className, ...props }, ref) => (
<BaseCheckboxRoot
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center rounded-none border border-neutral-950 bg-white p-0 text-white data-checked:bg-neutral-950 data-checked:text-white focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:text-neutral-950 dark:data-checked:bg-white dark:data-checked:text-neutral-950 dark:focus-visible:outline-white",
className,
)}
{...props}
/>
),
)
CheckboxRoot.displayName = "CheckboxRoot"
+22
View File
@@ -0,0 +1,22 @@
import { CollapsibleRoot } from "./root"
import { CollapsibleTrigger } from "./trigger"
import { CollapsiblePanel } from "./panel"
const CollapsiblePrimitive = {
Root: CollapsibleRoot,
Trigger: CollapsibleTrigger,
Panel: CollapsiblePanel,
}
export default CollapsiblePrimitive
export {
CollapsibleRoot as Collapsible,
CollapsibleRoot,
CollapsibleTrigger,
CollapsiblePanel,
}
export type { CollapsibleRootProps } from "./root"
export type { CollapsibleTriggerProps } from "./trigger"
export type { CollapsiblePanelProps } from "./panel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible"
import { cn } from "@/lib/utils"
export type CollapsiblePanelProps = React.ComponentPropsWithoutRef<typeof BaseCollapsible.Panel> & {
className?: string
}
const BaseCollapsiblePanel = BaseCollapsible.Panel as React.ElementType
export const CollapsiblePanel = React.forwardRef<HTMLElement, CollapsiblePanelProps>(
({ className, ...props }, ref) => (
<BaseCollapsiblePanel
ref={ref}
className={cn(
"flex h-(--collapsible-panel-height) flex-col justify-end overflow-hidden text-sm transition-[height] duration-150 ease-[ease-out] [&[hidden]:not([hidden='until-found'])]:hidden data-ending-style:h-0 data-starting-style:h-0",
className,
)}
{...props}
/>
),
)
CollapsiblePanel.displayName = "CollapsiblePanel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible"
import { cn } from "@/lib/utils"
export type CollapsibleRootProps = React.ComponentPropsWithoutRef<typeof BaseCollapsible.Root> & {
className?: string
}
const BaseCollapsibleRoot = BaseCollapsible.Root as React.ElementType
export const CollapsibleRoot = React.forwardRef<HTMLElement, CollapsibleRootProps>(
({ className, ...props }, ref) => (
<BaseCollapsibleRoot
ref={ref}
className={cn(
"flex min-h-36 w-48 flex-col justify-center text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
CollapsibleRoot.displayName = "CollapsibleRoot"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Collapsible as BaseCollapsible } from "@base-ui/react/collapsible"
import { cn } from "@/lib/utils"
export type CollapsibleTriggerProps = React.ComponentPropsWithoutRef<typeof BaseCollapsible.Trigger> & {
className?: string
}
const BaseCollapsibleTrigger = BaseCollapsible.Trigger as React.ElementType
export const CollapsibleTrigger = React.forwardRef<HTMLElement, CollapsibleTriggerProps>(
({ className, ...props }, ref) => (
<BaseCollapsibleTrigger
ref={ref}
className={cn(
"group flex h-8 items-center justify-between gap-2 rounded-none border border-neutral-950 dark:border-white bg-white dark:bg-neutral-950 pl-3 pr-2 text-sm leading-none whitespace-nowrap font-normal text-neutral-950 dark:text-white select-none [&:not([data-disabled]):hover]:bg-neutral-100 dark:[&:not([data-disabled]):hover]:bg-neutral-800 [&:not([data-disabled]):active]:bg-neutral-200 dark:[&:not([data-disabled]):active]:bg-neutral-700 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white data-disabled:border-neutral-500 data-disabled:text-neutral-500 disabled:border-neutral-500 disabled:text-neutral-500 dark:data-disabled:border-neutral-400 dark:data-disabled:text-neutral-400",
className,
)}
{...props}
/>
),
)
CollapsibleTrigger.displayName = "CollapsibleTrigger"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxArrowProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Arrow> & {
className?: string
}
const BaseComboboxArrow = BaseCombobox.Arrow as React.ElementType
export const ComboboxArrow = React.forwardRef<HTMLElement, ComboboxArrowProps>(
({ className, ...props }, ref) => (
<BaseComboboxArrow
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-neutral-500 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
ComboboxArrow.displayName = "ComboboxArrow"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxBackdropProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Backdrop> & {
className?: string
}
const BaseComboboxBackdrop = BaseCombobox.Backdrop as React.ElementType
export const ComboboxBackdrop = React.forwardRef<HTMLElement, ComboboxBackdropProps>(
({ className, ...props }, ref) => (
<BaseComboboxBackdrop
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-black/20 backdrop-blur-[1px] transition-opacity data-ending-style:opacity-0 data-starting-style:opacity-0 dark:bg-black/50",
className,
)}
{...props}
/>
),
)
ComboboxBackdrop.displayName = "ComboboxBackdrop"
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxChipRemoveProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.ChipRemove> & {
className?: string
}
const BaseComboboxChipRemove = BaseCombobox.ChipRemove as React.ElementType
export const ComboboxChipRemove = React.forwardRef<HTMLElement, ComboboxChipRemoveProps>(
({ className, ...props }, ref) => (
<BaseComboboxChipRemove
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxChipRemove.displayName = "ComboboxChipRemove"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxChipProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Chip> & {
className?: string
}
const BaseComboboxChip = BaseCombobox.Chip as React.ElementType
export const ComboboxChip = React.forwardRef<HTMLElement, ComboboxChipProps>(
({ className, ...props }, ref) => (
<BaseComboboxChip
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxChip.displayName = "ComboboxChip"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxChipsProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Chips> & {
className?: string
}
const BaseComboboxChips = BaseCombobox.Chips as React.ElementType
export const ComboboxChips = React.forwardRef<HTMLElement, ComboboxChipsProps>(
({ className, ...props }, ref) => (
<BaseComboboxChips
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxChips.displayName = "ComboboxChips"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxClearProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Clear> & {
className?: string
}
const BaseComboboxClear = BaseCombobox.Clear as React.ElementType
export const ComboboxClear = React.forwardRef<HTMLElement, ComboboxClearProps>(
({ className, ...props }, ref) => (
<BaseComboboxClear
ref={ref}
className={cn(
"combobox-clear flex h-full w-6 items-center justify-center border-0 bg-transparent p-0 text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxClear.displayName = "ComboboxClear"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxCollectionProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Collection> & {
className?: string
}
const BaseComboboxCollection = BaseCombobox.Collection as React.ElementType
export const ComboboxCollection = React.forwardRef<HTMLElement, ComboboxCollectionProps>(
({ className, ...props }, ref) => (
<BaseComboboxCollection
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxCollection.displayName = "ComboboxCollection"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxEmptyProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Empty> & {
className?: string
}
const BaseComboboxEmpty = BaseCombobox.Empty as React.ElementType
export const ComboboxEmpty = React.forwardRef<HTMLElement, ComboboxEmptyProps>(
({ className, ...props }, ref) => (
<BaseComboboxEmpty
ref={ref}
className={cn(
"text-sm text-neutral-600 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
ComboboxEmpty.displayName = "ComboboxEmpty"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxGroupLabelProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.GroupLabel> & {
className?: string
}
const BaseComboboxGroupLabel = BaseCombobox.GroupLabel as React.ElementType
export const ComboboxGroupLabel = React.forwardRef<HTMLElement, ComboboxGroupLabelProps>(
({ className, ...props }, ref) => (
<BaseComboboxGroupLabel
ref={ref}
className={cn(
"py-2 pr-2 pl-8 text-sm leading-4 text-neutral-500 select-none dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
ComboboxGroupLabel.displayName = "ComboboxGroupLabel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxGroupProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Group> & {
className?: string
}
const BaseComboboxGroup = BaseCombobox.Group as React.ElementType
export const ComboboxGroup = React.forwardRef<HTMLElement, ComboboxGroupProps>(
({ className, ...props }, ref) => (
<BaseComboboxGroup
ref={ref}
className={cn(
"block pb-2 last:pb-0",
className,
)}
{...props}
/>
),
)
ComboboxGroup.displayName = "ComboboxGroup"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxIconProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Icon> & {
className?: string
}
const BaseComboboxIcon = BaseCombobox.Icon as React.ElementType
export const ComboboxIcon = React.forwardRef<HTMLElement, ComboboxIconProps>(
({ className, ...props }, ref) => (
<BaseComboboxIcon
ref={ref}
className={cn(
"text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxIcon.displayName = "ComboboxIcon"
+112
View File
@@ -0,0 +1,112 @@
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { ComboboxRoot } from "./root"
import { ComboboxLabel } from "./label"
import { ComboboxValue } from "./value"
import { ComboboxInput } from "./input"
import { ComboboxInputGroup } from "./input-group"
import { ComboboxTrigger } from "./trigger"
import { ComboboxList } from "./list"
import { ComboboxPortal } from "./portal"
import { ComboboxBackdrop } from "./backdrop"
import { ComboboxPositioner } from "./positioner"
import { ComboboxPopup } from "./popup"
import { ComboboxArrow } from "./arrow"
import { ComboboxIcon } from "./icon"
import { ComboboxGroup } from "./group"
import { ComboboxGroupLabel } from "./group-label"
import { ComboboxItem } from "./item"
import { ComboboxItemIndicator } from "./item-indicator"
import { ComboboxChips } from "./chips"
import { ComboboxChip } from "./chip"
import { ComboboxChipRemove } from "./chip-remove"
import { ComboboxRow } from "./row"
import { ComboboxCollection } from "./collection"
import { ComboboxEmpty } from "./empty"
import { ComboboxClear } from "./clear"
const ComboboxPrimitive = {
Root: ComboboxRoot,
Label: ComboboxLabel,
Value: ComboboxValue,
Input: ComboboxInput,
InputGroup: ComboboxInputGroup,
Trigger: ComboboxTrigger,
List: ComboboxList,
Portal: ComboboxPortal,
Backdrop: ComboboxBackdrop,
Positioner: ComboboxPositioner,
Popup: ComboboxPopup,
Arrow: ComboboxArrow,
Icon: ComboboxIcon,
Group: ComboboxGroup,
GroupLabel: ComboboxGroupLabel,
Item: ComboboxItem,
ItemIndicator: ComboboxItemIndicator,
Chips: ComboboxChips,
Chip: ComboboxChip,
ChipRemove: ComboboxChipRemove,
Row: ComboboxRow,
Collection: ComboboxCollection,
Empty: ComboboxEmpty,
Clear: ComboboxClear,
Separator: BaseCombobox.Separator,
Status: BaseCombobox.Status,
useFilter: BaseCombobox.useFilter,
useFilteredItems: BaseCombobox.useFilteredItems,
}
export default ComboboxPrimitive
export {
ComboboxRoot as Combobox,
ComboboxRoot,
ComboboxLabel,
ComboboxValue,
ComboboxInput,
ComboboxInputGroup,
ComboboxTrigger,
ComboboxList,
ComboboxPortal,
ComboboxBackdrop,
ComboboxPositioner,
ComboboxPopup,
ComboboxArrow,
ComboboxIcon,
ComboboxGroup,
ComboboxGroupLabel,
ComboboxItem,
ComboboxItemIndicator,
ComboboxChips,
ComboboxChip,
ComboboxChipRemove,
ComboboxRow,
ComboboxCollection,
ComboboxEmpty,
ComboboxClear,
BaseCombobox,
}
export type { ComboboxRootProps } from "./root"
export type { ComboboxLabelProps } from "./label"
export type { ComboboxValueProps } from "./value"
export type { ComboboxInputProps } from "./input"
export type { ComboboxInputGroupProps } from "./input-group"
export type { ComboboxTriggerProps } from "./trigger"
export type { ComboboxListProps } from "./list"
export type { ComboboxPortalProps } from "./portal"
export type { ComboboxBackdropProps } from "./backdrop"
export type { ComboboxPositionerProps } from "./positioner"
export type { ComboboxPopupProps } from "./popup"
export type { ComboboxArrowProps } from "./arrow"
export type { ComboboxIconProps } from "./icon"
export type { ComboboxGroupProps } from "./group"
export type { ComboboxGroupLabelProps } from "./group-label"
export type { ComboboxItemProps } from "./item"
export type { ComboboxItemIndicatorProps } from "./item-indicator"
export type { ComboboxChipsProps } from "./chips"
export type { ComboboxChipProps } from "./chip"
export type { ComboboxChipRemoveProps } from "./chip-remove"
export type { ComboboxRowProps } from "./row"
export type { ComboboxCollectionProps } from "./collection"
export type { ComboboxEmptyProps } from "./empty"
export type { ComboboxClearProps } from "./clear"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxInputGroupProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.InputGroup> & {
className?: string
}
const BaseComboboxInputGroup = BaseCombobox.InputGroup as React.ElementType
export const ComboboxInputGroup = React.forwardRef<HTMLElement, ComboboxInputGroupProps>(
({ className, ...props }, ref) => (
<BaseComboboxInputGroup
ref={ref}
className={cn(
"relative h-8 w-56 border border-neutral-950 bg-white dark:bg-neutral-950 focus-within:outline-2 focus-within:outline-solid focus-within:-outline-offset-1 focus-within:outline-neutral-950 dark:focus-within:outline-white dark:border-white [&>input]:pr-10 has-[.combobox-clear]:[&>input]:pr-18",
className,
)}
{...props}
/>
),
)
ComboboxInputGroup.displayName = "ComboboxInputGroup"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxInputProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Input> & {
className?: string
}
const BaseComboboxInput = BaseCombobox.Input as React.ElementType
export const ComboboxInput = React.forwardRef<HTMLElement, ComboboxInputProps>(
({ className, ...props }, ref) => (
<BaseComboboxInput
ref={ref}
className={cn(
"h-full w-full border-0 bg-white pl-2 dark:bg-neutral-950 text-sm any-pointer-coarse:text-base font-normal text-neutral-950 outline-none placeholder:text-neutral-500 dark:placeholder:text-neutral-400 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxInput.displayName = "ComboboxInput"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxItemIndicatorProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.ItemIndicator> & {
className?: string
}
const BaseComboboxItemIndicator = BaseCombobox.ItemIndicator as React.ElementType
export const ComboboxItemIndicator = React.forwardRef<HTMLElement, ComboboxItemIndicatorProps>(
({ className, ...props }, ref) => (
<BaseComboboxItemIndicator
ref={ref}
className={cn(
"col-start-1",
className,
)}
{...props}
/>
),
)
ComboboxItemIndicator.displayName = "ComboboxItemIndicator"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxItemProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Item> & {
className?: string
}
const BaseComboboxItem = BaseCombobox.Item as React.ElementType
export const ComboboxItem = React.forwardRef<HTMLElement, ComboboxItemProps>(
({ className, ...props }, ref) => (
<BaseComboboxItem
ref={ref}
className={cn(
"grid cursor-default grid-cols-[1rem_1fr] items-center gap-2 p-2 text-sm leading-4 outline-none select-none data-highlighted:relative data-highlighted:z-0 data-highlighted:text-white data-highlighted:before:absolute data-highlighted:before:inset-0 data-highlighted:before:z-[-1] data-highlighted:before:bg-neutral-950 dark:data-highlighted:text-neutral-950 dark:data-highlighted:before:bg-white",
className,
)}
{...props}
/>
),
)
ComboboxItem.displayName = "ComboboxItem"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxLabelProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Label> & {
className?: string
}
const BaseComboboxLabel = BaseCombobox.Label as React.ElementType
export const ComboboxLabel = React.forwardRef<HTMLElement, ComboboxLabelProps>(
({ className, ...props }, ref) => (
<BaseComboboxLabel
ref={ref}
className={cn(
"cursor-default text-sm leading-5 font-bold text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxLabel.displayName = "ComboboxLabel"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxListProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.List> & {
className?: string
}
const BaseComboboxList = BaseCombobox.List as React.ElementType
export const ComboboxList = React.forwardRef<HTMLElement, ComboboxListProps>(
({ className, ...props }, ref) => (
<BaseComboboxList
ref={ref}
className={cn(
"max-h-[min(22.5rem,var(--available-height))] overflow-y-auto overscroll-contain py-1 scroll-py-1 outline-0 data-empty:p-0",
className,
)}
{...props}
/>
),
)
ComboboxList.displayName = "ComboboxList"
+25
View File
@@ -0,0 +1,25 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxPopupProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Popup> & {
className?: string
}
const BaseComboboxPopup = BaseCombobox.Popup as React.ElementType
const defaultComboboxPopupClassName =
"w-[var(--anchor-width)] max-w-[var(--available-width)] origin-[var(--transform-origin)] border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none"
export const ComboboxPopup = React.forwardRef<HTMLElement, ComboboxPopupProps>(
({ className, ...props }, ref) => (
<BaseComboboxPopup
ref={ref}
className={cn(className ?? defaultComboboxPopupClassName)}
{...props}
/>
),
)
ComboboxPopup.displayName = "ComboboxPopup"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxPortalProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Portal> & {
className?: string
}
const BaseComboboxPortal = BaseCombobox.Portal as React.ElementType
export const ComboboxPortal = React.forwardRef<HTMLElement, ComboboxPortalProps>(
({ className, ...props }, ref) => (
<BaseComboboxPortal
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxPortal.displayName = "ComboboxPortal"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxPositionerProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Positioner> & {
className?: string
}
const BaseComboboxPositioner = BaseCombobox.Positioner as React.ElementType
export const ComboboxPositioner = React.forwardRef<HTMLElement, ComboboxPositionerProps>(
({ className, ...props }, ref) => (
<BaseComboboxPositioner
ref={ref}
className={cn(
"outline-none",
className,
)}
{...props}
/>
),
)
ComboboxPositioner.displayName = "ComboboxPositioner"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxRootProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Root> & {
className?: string
}
const BaseComboboxRoot = BaseCombobox.Root as React.ElementType
export const ComboboxRoot = React.forwardRef<HTMLElement, ComboboxRootProps>(
({ className, ...props }, ref) => (
<BaseComboboxRoot
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ComboboxRoot.displayName = "ComboboxRoot"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxRowProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Row> & {
className?: string
}
const BaseComboboxRow = BaseCombobox.Row as React.ElementType
export const ComboboxRow = React.forwardRef<HTMLElement, ComboboxRowProps>(
({ className, ...props }, ref) => (
<BaseComboboxRow
ref={ref}
className={cn(
"grid grid-cols-5",
className,
)}
{...props}
/>
),
)
ComboboxRow.displayName = "ComboboxRow"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxTriggerProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Trigger> & {
className?: string
}
const BaseComboboxTrigger = BaseCombobox.Trigger as React.ElementType
export const ComboboxTrigger = React.forwardRef<HTMLElement, ComboboxTriggerProps>(
({ className, ...props }, ref) => (
<BaseComboboxTrigger
ref={ref}
className={cn(
"flex h-full w-6 items-center justify-center border-0 bg-transparent p-0 text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxTrigger.displayName = "ComboboxTrigger"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { Combobox as BaseCombobox } from "@base-ui/react/combobox"
import { cn } from "@/lib/utils"
export type ComboboxValueProps = React.ComponentPropsWithoutRef<typeof BaseCombobox.Value> & {
className?: string
}
const BaseComboboxValue = BaseCombobox.Value as React.ElementType
export const ComboboxValue = React.forwardRef<HTMLElement, ComboboxValueProps>(
({ className, ...props }, ref) => (
<BaseComboboxValue
ref={ref}
className={cn(
"text-sm text-neutral-950 dark:text-white",
className,
)}
{...props}
/>
),
)
ComboboxValue.displayName = "ComboboxValue"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuArrowProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Arrow> & {
className?: string
}
const BaseContextMenuArrow = BaseContextMenu.Arrow as React.ElementType
export const ContextMenuArrow = React.forwardRef<HTMLElement, ContextMenuArrowProps>(
({ className, ...props }, ref) => (
<BaseContextMenuArrow
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-neutral-500 dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuArrow.displayName = "ContextMenuArrow"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuBackdropProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Backdrop> & {
className?: string
}
const BaseContextMenuBackdrop = BaseContextMenu.Backdrop as React.ElementType
export const ContextMenuBackdrop = React.forwardRef<HTMLElement, ContextMenuBackdropProps>(
({ className, ...props }, ref) => (
<BaseContextMenuBackdrop
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-black/20 backdrop-blur-[1px] transition-opacity data-ending-style:opacity-0 data-starting-style:opacity-0 dark:bg-black/50",
className,
)}
{...props}
/>
),
)
ContextMenuBackdrop.displayName = "ContextMenuBackdrop"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuCheckboxItemIndicatorProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItemIndicator> & {
className?: string
}
const BaseContextMenuCheckboxItemIndicator = BaseContextMenu.CheckboxItemIndicator as React.ElementType
export const ContextMenuCheckboxItemIndicator = React.forwardRef<HTMLElement, ContextMenuCheckboxItemIndicatorProps>(
({ className, ...props }, ref) => (
<BaseContextMenuCheckboxItemIndicator
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-current",
className,
)}
{...props}
/>
),
)
ContextMenuCheckboxItemIndicator.displayName = "ContextMenuCheckboxItemIndicator"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuCheckboxItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItem> & {
className?: string
}
const BaseContextMenuCheckboxItem = BaseContextMenu.CheckboxItem as React.ElementType
export const ContextMenuCheckboxItem = React.forwardRef<HTMLElement, ContextMenuCheckboxItemProps>(
({ className, ...props }, ref) => (
<BaseContextMenuCheckboxItem
ref={ref}
className={cn(
"flex cursor-default items-center gap-2 py-2 pr-8 pl-4 text-sm leading-4 outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-white data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:bg-neutral-950 data-[highlighted]:before:content-[''] data-[disabled]:text-neutral-500 dark:data-[highlighted]:text-neutral-950 dark:data-[highlighted]:before:bg-white dark:data-[disabled]:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuCheckboxItem.displayName = "ContextMenuCheckboxItem"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuGroupLabelProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.GroupLabel> & {
className?: string
}
const BaseContextMenuGroupLabel = BaseContextMenu.GroupLabel as React.ElementType
export const ContextMenuGroupLabel = React.forwardRef<HTMLElement, ContextMenuGroupLabelProps>(
({ className, ...props }, ref) => (
<BaseContextMenuGroupLabel
ref={ref}
className={cn(
"flex min-h-8 items-center pr-6 pl-3 text-sm leading-none font-normal text-neutral-500 select-none outline-none dark:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuGroupLabel.displayName = "ContextMenuGroupLabel"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuGroupProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Group> & {
className?: string
}
const BaseContextMenuGroup = BaseContextMenu.Group as React.ElementType
export const ContextMenuGroup = React.forwardRef<HTMLElement, ContextMenuGroupProps>(
({ className, ...props }, ref) => (
<BaseContextMenuGroup
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ContextMenuGroup.displayName = "ContextMenuGroup"
+85
View File
@@ -0,0 +1,85 @@
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { ContextMenuRoot } from "./root"
import { ContextMenuTrigger } from "./trigger"
import { ContextMenuBackdrop } from "./backdrop"
import { ContextMenuPortal } from "./portal"
import { ContextMenuPositioner } from "./positioner"
import { ContextMenuPopup } from "./popup"
import { ContextMenuArrow } from "./arrow"
import { ContextMenuGroup } from "./group"
import { ContextMenuGroupLabel } from "./group-label"
import { ContextMenuItem } from "./item"
import { ContextMenuCheckboxItem } from "./checkbox-item"
import { ContextMenuCheckboxItemIndicator } from "./checkbox-item-indicator"
import { ContextMenuLinkItem } from "./link-item"
import { ContextMenuRadioGroup } from "./radio-group"
import { ContextMenuRadioItem } from "./radio-item"
import { ContextMenuRadioItemIndicator } from "./radio-item-indicator"
import { ContextMenuSubmenuRoot } from "./submenu-root"
import { ContextMenuSubmenuTrigger } from "./submenu-trigger"
const ContextMenuPrimitive = {
Root: ContextMenuRoot,
Trigger: ContextMenuTrigger,
Backdrop: ContextMenuBackdrop,
Portal: ContextMenuPortal,
Positioner: ContextMenuPositioner,
Popup: ContextMenuPopup,
Arrow: ContextMenuArrow,
Group: ContextMenuGroup,
GroupLabel: ContextMenuGroupLabel,
Item: ContextMenuItem,
CheckboxItem: ContextMenuCheckboxItem,
CheckboxItemIndicator: ContextMenuCheckboxItemIndicator,
LinkItem: ContextMenuLinkItem,
RadioGroup: ContextMenuRadioGroup,
RadioItem: ContextMenuRadioItem,
RadioItemIndicator: ContextMenuRadioItemIndicator,
SubmenuRoot: ContextMenuSubmenuRoot,
SubmenuTrigger: ContextMenuSubmenuTrigger,
Separator: BaseContextMenu.Separator,
}
export default ContextMenuPrimitive
export {
ContextMenuRoot as ContextMenu,
ContextMenuRoot,
ContextMenuTrigger,
ContextMenuBackdrop,
ContextMenuPortal,
ContextMenuPositioner,
ContextMenuPopup,
ContextMenuArrow,
ContextMenuGroup,
ContextMenuGroupLabel,
ContextMenuItem,
ContextMenuCheckboxItem,
ContextMenuCheckboxItemIndicator,
ContextMenuLinkItem,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuRadioItemIndicator,
ContextMenuSubmenuRoot,
ContextMenuSubmenuTrigger,
BaseContextMenu,
}
export type { ContextMenuRootProps } from "./root"
export type { ContextMenuTriggerProps } from "./trigger"
export type { ContextMenuBackdropProps } from "./backdrop"
export type { ContextMenuPortalProps } from "./portal"
export type { ContextMenuPositionerProps } from "./positioner"
export type { ContextMenuPopupProps } from "./popup"
export type { ContextMenuArrowProps } from "./arrow"
export type { ContextMenuGroupProps } from "./group"
export type { ContextMenuGroupLabelProps } from "./group-label"
export type { ContextMenuItemProps } from "./item"
export type { ContextMenuCheckboxItemProps } from "./checkbox-item"
export type { ContextMenuCheckboxItemIndicatorProps } from "./checkbox-item-indicator"
export type { ContextMenuLinkItemProps } from "./link-item"
export type { ContextMenuRadioGroupProps } from "./radio-group"
export type { ContextMenuRadioItemProps } from "./radio-item"
export type { ContextMenuRadioItemIndicatorProps } from "./radio-item-indicator"
export type { ContextMenuSubmenuRootProps } from "./submenu-root"
export type { ContextMenuSubmenuTriggerProps } from "./submenu-trigger"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Item> & {
className?: string
}
const BaseContextMenuItem = BaseContextMenu.Item as React.ElementType
export const ContextMenuItem = React.forwardRef<HTMLElement, ContextMenuItemProps>(
({ className, ...props }, ref) => (
<BaseContextMenuItem
ref={ref}
className={cn(
"flex cursor-default py-2 pr-8 pl-4 text-sm leading-4 outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-white data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:bg-neutral-950 data-[highlighted]:before:content-[''] data-[disabled]:text-neutral-500 dark:data-[highlighted]:text-neutral-950 dark:data-[highlighted]:before:bg-white dark:data-[disabled]:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuItem.displayName = "ContextMenuItem"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuLinkItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.LinkItem> & {
className?: string
}
const BaseContextMenuLinkItem = BaseContextMenu.LinkItem as React.ElementType
export const ContextMenuLinkItem = React.forwardRef<HTMLElement, ContextMenuLinkItemProps>(
({ className, ...props }, ref) => (
<BaseContextMenuLinkItem
ref={ref}
className={cn(
"flex cursor-default py-2 pr-8 pl-4 text-sm leading-4 text-inherit no-underline outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-white data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:bg-neutral-950 data-[highlighted]:before:content-[''] data-[disabled]:text-neutral-500 dark:data-[highlighted]:text-neutral-950 dark:data-[highlighted]:before:bg-white dark:data-[disabled]:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuLinkItem.displayName = "ContextMenuLinkItem"
+26
View File
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuPopupProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Popup> & {
className?: string
}
const BaseContextMenuPopup = BaseContextMenu.Popup as React.ElementType
export const ContextMenuPopup = React.forwardRef<HTMLElement, ContextMenuPopupProps>(
({ className, ...props }, ref) => (
<BaseContextMenuPopup
ref={ref}
className={cn(
"origin-[var(--transform-origin)] border border-neutral-950 bg-white py-1 text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] outline-none transition-[transform,opacity] duration-[350ms] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:duration-150 data-ending-style:ease-out data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none",
className,
)}
{...props}
/>
),
)
ContextMenuPopup.displayName = "ContextMenuPopup"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuPortalProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Portal> & {
className?: string
}
const BaseContextMenuPortal = BaseContextMenu.Portal as React.ElementType
export const ContextMenuPortal = React.forwardRef<HTMLElement, ContextMenuPortalProps>(
({ className, ...props }, ref) => (
<BaseContextMenuPortal
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ContextMenuPortal.displayName = "ContextMenuPortal"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuPositionerProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Positioner> & {
className?: string
}
const BaseContextMenuPositioner = BaseContextMenu.Positioner as React.ElementType
export const ContextMenuPositioner = React.forwardRef<HTMLElement, ContextMenuPositionerProps>(
({ className, ...props }, ref) => (
<BaseContextMenuPositioner
ref={ref}
className={cn(
"outline-none",
className,
)}
{...props}
/>
),
)
ContextMenuPositioner.displayName = "ContextMenuPositioner"
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuRadioGroupProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioGroup> & {
className?: string
}
const BaseContextMenuRadioGroup = BaseContextMenu.RadioGroup as React.ElementType
export const ContextMenuRadioGroup = React.forwardRef<HTMLElement, ContextMenuRadioGroupProps>(
({ className, ...props }, ref) => (
<BaseContextMenuRadioGroup
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ContextMenuRadioGroup.displayName = "ContextMenuRadioGroup"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuRadioItemIndicatorProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItemIndicator> & {
className?: string
}
const BaseContextMenuRadioItemIndicator = BaseContextMenu.RadioItemIndicator as React.ElementType
export const ContextMenuRadioItemIndicator = React.forwardRef<HTMLElement, ContextMenuRadioItemIndicatorProps>(
({ className, ...props }, ref) => (
<BaseContextMenuRadioItemIndicator
ref={ref}
className={cn(
"flex size-4 shrink-0 items-center justify-center text-current",
className,
)}
{...props}
/>
),
)
ContextMenuRadioItemIndicator.displayName = "ContextMenuRadioItemIndicator"
@@ -0,0 +1,26 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuRadioItemProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItem> & {
className?: string
}
const BaseContextMenuRadioItem = BaseContextMenu.RadioItem as React.ElementType
export const ContextMenuRadioItem = React.forwardRef<HTMLElement, ContextMenuRadioItemProps>(
({ className, ...props }, ref) => (
<BaseContextMenuRadioItem
ref={ref}
className={cn(
"flex cursor-default items-center gap-2 py-2 pr-8 pl-4 text-sm leading-4 outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-white data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:bg-neutral-950 data-[highlighted]:before:content-[''] data-[disabled]:text-neutral-500 dark:data-[highlighted]:text-neutral-950 dark:data-[highlighted]:before:bg-white dark:data-[disabled]:text-neutral-400",
className,
)}
{...props}
/>
),
)
ContextMenuRadioItem.displayName = "ContextMenuRadioItem"
+23
View File
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuRootProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.Root> & {
className?: string
}
const BaseContextMenuRoot = BaseContextMenu.Root as React.ElementType
export const ContextMenuRoot = React.forwardRef<HTMLElement, ContextMenuRootProps>(
({ className, ...props }, ref) => (
<BaseContextMenuRoot
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ContextMenuRoot.displayName = "ContextMenuRoot"
@@ -0,0 +1,23 @@
"use client"
import * as React from "react"
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu"
import { cn } from "@/lib/utils"
export type ContextMenuSubmenuRootProps = React.ComponentPropsWithoutRef<typeof BaseContextMenu.SubmenuRoot> & {
className?: string
}
const BaseContextMenuSubmenuRoot = BaseContextMenu.SubmenuRoot as React.ElementType
export const ContextMenuSubmenuRoot = React.forwardRef<HTMLElement, ContextMenuSubmenuRootProps>(
({ className, ...props }, ref) => (
<BaseContextMenuSubmenuRoot
ref={ref}
className={cn(className)}
{...props}
/>
),
)
ContextMenuSubmenuRoot.displayName = "ContextMenuSubmenuRoot"

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