diff --git a/cli/index.mjs b/cli/index.mjs new file mode 100755 index 0000000..1d4938b --- /dev/null +++ b/cli/index.mjs @@ -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 ") + } + + 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 ] [--cwd ] [--force] + base-ui-tailwind add [--manifest ] [--cwd ] [--overwrite] [--dry-run] +`) +} diff --git a/examples/smoke.tsx b/examples/smoke.tsx new file mode 100644 index 0000000..bc619ef --- /dev/null +++ b/examples/smoke.tsx @@ -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 ( +
+ + Named button + + + Primitive dialog + + + + Primitive dialog + Default namespace API. + Close + + + + + + Named dialog + + Named dialog + Named shadcn-style API. + Close + + +
+ ) +} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..06ceffb --- /dev/null +++ b/manifest.json @@ -0,0 +1,1777 @@ +{ + "name": "base-ui-tailwind", + "version": "0.0.0", + "generatedAt": "2026-07-24T21:53:13.965Z", + "command": "base-ui-tailwind", + "configFile": "base-ui-tailwind.json", + "dependencies": { + "@base-ui/react": "^1.6.0", + "clsx": "^2.1.1", + "lucide-react": "^1.23.0", + "tailwind-merge": "^3.6.0" + }, + "items": { + "utils/portal-container": { + "name": "utils/portal-container", + "type": "util", + "description": "Utility source for portal-container.", + "dependencies": [ + "react" + ], + "files": [ + { + "path": "src/lib/portal-container.tsx", + "target": "lib/portal-container.tsx" + } + ] + }, + "utils/utils": { + "name": "utils/utils", + "type": "util", + "description": "Utility source for utils.", + "dependencies": [ + "clsx", + "tailwind-merge" + ], + "files": [ + { + "path": "src/lib/utils.ts", + "target": "lib/utils.ts" + } + ] + }, + "accordion": { + "name": "accordion", + "type": "component", + "description": "Accordion component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/accordion/header.tsx", + "target": "components/ui/accordion/header.tsx" + }, + { + "path": "src/components/ui/accordion/index.ts", + "target": "components/ui/accordion/index.ts" + }, + { + "path": "src/components/ui/accordion/item.tsx", + "target": "components/ui/accordion/item.tsx" + }, + { + "path": "src/components/ui/accordion/panel.tsx", + "target": "components/ui/accordion/panel.tsx" + }, + { + "path": "src/components/ui/accordion/root.tsx", + "target": "components/ui/accordion/root.tsx" + }, + { + "path": "src/components/ui/accordion/trigger.tsx", + "target": "components/ui/accordion/trigger.tsx" + } + ] + }, + "alert-dialog": { + "name": "alert-dialog", + "type": "component", + "description": "Alert Dialog component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/alert-dialog/backdrop.tsx", + "target": "components/ui/alert-dialog/backdrop.tsx" + }, + { + "path": "src/components/ui/alert-dialog/close.tsx", + "target": "components/ui/alert-dialog/close.tsx" + }, + { + "path": "src/components/ui/alert-dialog/content.tsx", + "target": "components/ui/alert-dialog/content.tsx" + }, + { + "path": "src/components/ui/alert-dialog/description.tsx", + "target": "components/ui/alert-dialog/description.tsx" + }, + { + "path": "src/components/ui/alert-dialog/index.ts", + "target": "components/ui/alert-dialog/index.ts" + }, + { + "path": "src/components/ui/alert-dialog/popup.tsx", + "target": "components/ui/alert-dialog/popup.tsx" + }, + { + "path": "src/components/ui/alert-dialog/portal.tsx", + "target": "components/ui/alert-dialog/portal.tsx" + }, + { + "path": "src/components/ui/alert-dialog/root.tsx", + "target": "components/ui/alert-dialog/root.tsx" + }, + { + "path": "src/components/ui/alert-dialog/title.tsx", + "target": "components/ui/alert-dialog/title.tsx" + }, + { + "path": "src/components/ui/alert-dialog/trigger.tsx", + "target": "components/ui/alert-dialog/trigger.tsx" + }, + { + "path": "src/components/ui/alert-dialog/viewport.tsx", + "target": "components/ui/alert-dialog/viewport.tsx" + } + ] + }, + "autocomplete": { + "name": "autocomplete", + "type": "component", + "description": "Autocomplete component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/autocomplete/arrow.tsx", + "target": "components/ui/autocomplete/arrow.tsx" + }, + { + "path": "src/components/ui/autocomplete/backdrop.tsx", + "target": "components/ui/autocomplete/backdrop.tsx" + }, + { + "path": "src/components/ui/autocomplete/clear.tsx", + "target": "components/ui/autocomplete/clear.tsx" + }, + { + "path": "src/components/ui/autocomplete/collection.tsx", + "target": "components/ui/autocomplete/collection.tsx" + }, + { + "path": "src/components/ui/autocomplete/empty.tsx", + "target": "components/ui/autocomplete/empty.tsx" + }, + { + "path": "src/components/ui/autocomplete/group-label.tsx", + "target": "components/ui/autocomplete/group-label.tsx" + }, + { + "path": "src/components/ui/autocomplete/group.tsx", + "target": "components/ui/autocomplete/group.tsx" + }, + { + "path": "src/components/ui/autocomplete/icon.tsx", + "target": "components/ui/autocomplete/icon.tsx" + }, + { + "path": "src/components/ui/autocomplete/index.ts", + "target": "components/ui/autocomplete/index.ts" + }, + { + "path": "src/components/ui/autocomplete/input-group.tsx", + "target": "components/ui/autocomplete/input-group.tsx" + }, + { + "path": "src/components/ui/autocomplete/input.tsx", + "target": "components/ui/autocomplete/input.tsx" + }, + { + "path": "src/components/ui/autocomplete/item.tsx", + "target": "components/ui/autocomplete/item.tsx" + }, + { + "path": "src/components/ui/autocomplete/list.tsx", + "target": "components/ui/autocomplete/list.tsx" + }, + { + "path": "src/components/ui/autocomplete/popup.tsx", + "target": "components/ui/autocomplete/popup.tsx" + }, + { + "path": "src/components/ui/autocomplete/portal.tsx", + "target": "components/ui/autocomplete/portal.tsx" + }, + { + "path": "src/components/ui/autocomplete/positioner.tsx", + "target": "components/ui/autocomplete/positioner.tsx" + }, + { + "path": "src/components/ui/autocomplete/root.tsx", + "target": "components/ui/autocomplete/root.tsx" + }, + { + "path": "src/components/ui/autocomplete/row.tsx", + "target": "components/ui/autocomplete/row.tsx" + }, + { + "path": "src/components/ui/autocomplete/trigger.tsx", + "target": "components/ui/autocomplete/trigger.tsx" + }, + { + "path": "src/components/ui/autocomplete/value.tsx", + "target": "components/ui/autocomplete/value.tsx" + } + ] + }, + "avatar": { + "name": "avatar", + "type": "component", + "description": "Avatar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/avatar/fallback.tsx", + "target": "components/ui/avatar/fallback.tsx" + }, + { + "path": "src/components/ui/avatar/image.tsx", + "target": "components/ui/avatar/image.tsx" + }, + { + "path": "src/components/ui/avatar/index.ts", + "target": "components/ui/avatar/index.ts" + }, + { + "path": "src/components/ui/avatar/root.tsx", + "target": "components/ui/avatar/root.tsx" + } + ] + }, + "button": { + "name": "button", + "type": "component", + "description": "Button component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/button/index.ts", + "target": "components/ui/button/index.ts" + }, + { + "path": "src/components/ui/button/root.tsx", + "target": "components/ui/button/root.tsx" + } + ] + }, + "checkbox": { + "name": "checkbox", + "type": "component", + "description": "Checkbox component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/checkbox/index.ts", + "target": "components/ui/checkbox/index.ts" + }, + { + "path": "src/components/ui/checkbox/indicator.tsx", + "target": "components/ui/checkbox/indicator.tsx" + }, + { + "path": "src/components/ui/checkbox/root.tsx", + "target": "components/ui/checkbox/root.tsx" + } + ] + }, + "checkbox-group": { + "name": "checkbox-group", + "type": "component", + "description": "Checkbox Group component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/checkbox-group/index.ts", + "target": "components/ui/checkbox-group/index.ts" + }, + { + "path": "src/components/ui/checkbox-group/root.tsx", + "target": "components/ui/checkbox-group/root.tsx" + } + ] + }, + "collapsible": { + "name": "collapsible", + "type": "component", + "description": "Collapsible component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/collapsible/index.ts", + "target": "components/ui/collapsible/index.ts" + }, + { + "path": "src/components/ui/collapsible/panel.tsx", + "target": "components/ui/collapsible/panel.tsx" + }, + { + "path": "src/components/ui/collapsible/root.tsx", + "target": "components/ui/collapsible/root.tsx" + }, + { + "path": "src/components/ui/collapsible/trigger.tsx", + "target": "components/ui/collapsible/trigger.tsx" + } + ] + }, + "combobox": { + "name": "combobox", + "type": "component", + "description": "Combobox component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/combobox/arrow.tsx", + "target": "components/ui/combobox/arrow.tsx" + }, + { + "path": "src/components/ui/combobox/backdrop.tsx", + "target": "components/ui/combobox/backdrop.tsx" + }, + { + "path": "src/components/ui/combobox/chip-remove.tsx", + "target": "components/ui/combobox/chip-remove.tsx" + }, + { + "path": "src/components/ui/combobox/chip.tsx", + "target": "components/ui/combobox/chip.tsx" + }, + { + "path": "src/components/ui/combobox/chips.tsx", + "target": "components/ui/combobox/chips.tsx" + }, + { + "path": "src/components/ui/combobox/clear.tsx", + "target": "components/ui/combobox/clear.tsx" + }, + { + "path": "src/components/ui/combobox/collection.tsx", + "target": "components/ui/combobox/collection.tsx" + }, + { + "path": "src/components/ui/combobox/empty.tsx", + "target": "components/ui/combobox/empty.tsx" + }, + { + "path": "src/components/ui/combobox/group-label.tsx", + "target": "components/ui/combobox/group-label.tsx" + }, + { + "path": "src/components/ui/combobox/group.tsx", + "target": "components/ui/combobox/group.tsx" + }, + { + "path": "src/components/ui/combobox/icon.tsx", + "target": "components/ui/combobox/icon.tsx" + }, + { + "path": "src/components/ui/combobox/index.ts", + "target": "components/ui/combobox/index.ts" + }, + { + "path": "src/components/ui/combobox/input-group.tsx", + "target": "components/ui/combobox/input-group.tsx" + }, + { + "path": "src/components/ui/combobox/input.tsx", + "target": "components/ui/combobox/input.tsx" + }, + { + "path": "src/components/ui/combobox/item-indicator.tsx", + "target": "components/ui/combobox/item-indicator.tsx" + }, + { + "path": "src/components/ui/combobox/item.tsx", + "target": "components/ui/combobox/item.tsx" + }, + { + "path": "src/components/ui/combobox/label.tsx", + "target": "components/ui/combobox/label.tsx" + }, + { + "path": "src/components/ui/combobox/list.tsx", + "target": "components/ui/combobox/list.tsx" + }, + { + "path": "src/components/ui/combobox/popup.tsx", + "target": "components/ui/combobox/popup.tsx" + }, + { + "path": "src/components/ui/combobox/portal.tsx", + "target": "components/ui/combobox/portal.tsx" + }, + { + "path": "src/components/ui/combobox/positioner.tsx", + "target": "components/ui/combobox/positioner.tsx" + }, + { + "path": "src/components/ui/combobox/root.tsx", + "target": "components/ui/combobox/root.tsx" + }, + { + "path": "src/components/ui/combobox/row.tsx", + "target": "components/ui/combobox/row.tsx" + }, + { + "path": "src/components/ui/combobox/trigger.tsx", + "target": "components/ui/combobox/trigger.tsx" + }, + { + "path": "src/components/ui/combobox/value.tsx", + "target": "components/ui/combobox/value.tsx" + } + ] + }, + "context-menu": { + "name": "context-menu", + "type": "component", + "description": "Context Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/context-menu/arrow.tsx", + "target": "components/ui/context-menu/arrow.tsx" + }, + { + "path": "src/components/ui/context-menu/backdrop.tsx", + "target": "components/ui/context-menu/backdrop.tsx" + }, + { + "path": "src/components/ui/context-menu/checkbox-item-indicator.tsx", + "target": "components/ui/context-menu/checkbox-item-indicator.tsx" + }, + { + "path": "src/components/ui/context-menu/checkbox-item.tsx", + "target": "components/ui/context-menu/checkbox-item.tsx" + }, + { + "path": "src/components/ui/context-menu/group-label.tsx", + "target": "components/ui/context-menu/group-label.tsx" + }, + { + "path": "src/components/ui/context-menu/group.tsx", + "target": "components/ui/context-menu/group.tsx" + }, + { + "path": "src/components/ui/context-menu/index.ts", + "target": "components/ui/context-menu/index.ts" + }, + { + "path": "src/components/ui/context-menu/item.tsx", + "target": "components/ui/context-menu/item.tsx" + }, + { + "path": "src/components/ui/context-menu/link-item.tsx", + "target": "components/ui/context-menu/link-item.tsx" + }, + { + "path": "src/components/ui/context-menu/popup.tsx", + "target": "components/ui/context-menu/popup.tsx" + }, + { + "path": "src/components/ui/context-menu/portal.tsx", + "target": "components/ui/context-menu/portal.tsx" + }, + { + "path": "src/components/ui/context-menu/positioner.tsx", + "target": "components/ui/context-menu/positioner.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-group.tsx", + "target": "components/ui/context-menu/radio-group.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-item-indicator.tsx", + "target": "components/ui/context-menu/radio-item-indicator.tsx" + }, + { + "path": "src/components/ui/context-menu/radio-item.tsx", + "target": "components/ui/context-menu/radio-item.tsx" + }, + { + "path": "src/components/ui/context-menu/root.tsx", + "target": "components/ui/context-menu/root.tsx" + }, + { + "path": "src/components/ui/context-menu/submenu-root.tsx", + "target": "components/ui/context-menu/submenu-root.tsx" + }, + { + "path": "src/components/ui/context-menu/submenu-trigger.tsx", + "target": "components/ui/context-menu/submenu-trigger.tsx" + }, + { + "path": "src/components/ui/context-menu/trigger.tsx", + "target": "components/ui/context-menu/trigger.tsx" + } + ] + }, + "dialog": { + "name": "dialog", + "type": "component", + "description": "Dialog component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/dialog/backdrop.tsx", + "target": "components/ui/dialog/backdrop.tsx" + }, + { + "path": "src/components/ui/dialog/close.tsx", + "target": "components/ui/dialog/close.tsx" + }, + { + "path": "src/components/ui/dialog/content.tsx", + "target": "components/ui/dialog/content.tsx" + }, + { + "path": "src/components/ui/dialog/description.tsx", + "target": "components/ui/dialog/description.tsx" + }, + { + "path": "src/components/ui/dialog/index.ts", + "target": "components/ui/dialog/index.ts" + }, + { + "path": "src/components/ui/dialog/popup.tsx", + "target": "components/ui/dialog/popup.tsx" + }, + { + "path": "src/components/ui/dialog/portal.tsx", + "target": "components/ui/dialog/portal.tsx" + }, + { + "path": "src/components/ui/dialog/root.tsx", + "target": "components/ui/dialog/root.tsx" + }, + { + "path": "src/components/ui/dialog/title.tsx", + "target": "components/ui/dialog/title.tsx" + }, + { + "path": "src/components/ui/dialog/trigger.tsx", + "target": "components/ui/dialog/trigger.tsx" + }, + { + "path": "src/components/ui/dialog/viewport.tsx", + "target": "components/ui/dialog/viewport.tsx" + } + ] + }, + "drawer": { + "name": "drawer", + "type": "component", + "description": "Drawer component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/drawer/backdrop.tsx", + "target": "components/ui/drawer/backdrop.tsx" + }, + { + "path": "src/components/ui/drawer/close.tsx", + "target": "components/ui/drawer/close.tsx" + }, + { + "path": "src/components/ui/drawer/content.tsx", + "target": "components/ui/drawer/content.tsx" + }, + { + "path": "src/components/ui/drawer/description.tsx", + "target": "components/ui/drawer/description.tsx" + }, + { + "path": "src/components/ui/drawer/indent-background.tsx", + "target": "components/ui/drawer/indent-background.tsx" + }, + { + "path": "src/components/ui/drawer/indent.tsx", + "target": "components/ui/drawer/indent.tsx" + }, + { + "path": "src/components/ui/drawer/index.ts", + "target": "components/ui/drawer/index.ts" + }, + { + "path": "src/components/ui/drawer/popup.tsx", + "target": "components/ui/drawer/popup.tsx" + }, + { + "path": "src/components/ui/drawer/portal.tsx", + "target": "components/ui/drawer/portal.tsx" + }, + { + "path": "src/components/ui/drawer/provider.tsx", + "target": "components/ui/drawer/provider.tsx" + }, + { + "path": "src/components/ui/drawer/root.tsx", + "target": "components/ui/drawer/root.tsx" + }, + { + "path": "src/components/ui/drawer/swipe-area.tsx", + "target": "components/ui/drawer/swipe-area.tsx" + }, + { + "path": "src/components/ui/drawer/title.tsx", + "target": "components/ui/drawer/title.tsx" + }, + { + "path": "src/components/ui/drawer/trigger.tsx", + "target": "components/ui/drawer/trigger.tsx" + }, + { + "path": "src/components/ui/drawer/viewport.tsx", + "target": "components/ui/drawer/viewport.tsx" + }, + { + "path": "src/components/ui/drawer/virtual-keyboard-provider.tsx", + "target": "components/ui/drawer/virtual-keyboard-provider.tsx" + } + ] + }, + "field": { + "name": "field", + "type": "component", + "description": "Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/field/control.tsx", + "target": "components/ui/field/control.tsx" + }, + { + "path": "src/components/ui/field/description.tsx", + "target": "components/ui/field/description.tsx" + }, + { + "path": "src/components/ui/field/error.tsx", + "target": "components/ui/field/error.tsx" + }, + { + "path": "src/components/ui/field/index.ts", + "target": "components/ui/field/index.ts" + }, + { + "path": "src/components/ui/field/item.tsx", + "target": "components/ui/field/item.tsx" + }, + { + "path": "src/components/ui/field/label.tsx", + "target": "components/ui/field/label.tsx" + }, + { + "path": "src/components/ui/field/root.tsx", + "target": "components/ui/field/root.tsx" + }, + { + "path": "src/components/ui/field/validity.tsx", + "target": "components/ui/field/validity.tsx" + } + ] + }, + "fieldset": { + "name": "fieldset", + "type": "component", + "description": "Fieldset component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/fieldset/index.ts", + "target": "components/ui/fieldset/index.ts" + }, + { + "path": "src/components/ui/fieldset/legend.tsx", + "target": "components/ui/fieldset/legend.tsx" + }, + { + "path": "src/components/ui/fieldset/root.tsx", + "target": "components/ui/fieldset/root.tsx" + } + ] + }, + "form": { + "name": "form", + "type": "component", + "description": "Form component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/form/index.ts", + "target": "components/ui/form/index.ts" + }, + { + "path": "src/components/ui/form/root.tsx", + "target": "components/ui/form/root.tsx" + } + ] + }, + "input": { + "name": "input", + "type": "component", + "description": "Input component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/input/index.ts", + "target": "components/ui/input/index.ts" + }, + { + "path": "src/components/ui/input/root.tsx", + "target": "components/ui/input/root.tsx" + } + ] + }, + "menu": { + "name": "menu", + "type": "component", + "description": "Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/menu/arrow.tsx", + "target": "components/ui/menu/arrow.tsx" + }, + { + "path": "src/components/ui/menu/backdrop.tsx", + "target": "components/ui/menu/backdrop.tsx" + }, + { + "path": "src/components/ui/menu/checkbox-item-indicator.tsx", + "target": "components/ui/menu/checkbox-item-indicator.tsx" + }, + { + "path": "src/components/ui/menu/checkbox-item.tsx", + "target": "components/ui/menu/checkbox-item.tsx" + }, + { + "path": "src/components/ui/menu/group-label.tsx", + "target": "components/ui/menu/group-label.tsx" + }, + { + "path": "src/components/ui/menu/group.tsx", + "target": "components/ui/menu/group.tsx" + }, + { + "path": "src/components/ui/menu/index.ts", + "target": "components/ui/menu/index.ts" + }, + { + "path": "src/components/ui/menu/item.tsx", + "target": "components/ui/menu/item.tsx" + }, + { + "path": "src/components/ui/menu/link-item.tsx", + "target": "components/ui/menu/link-item.tsx" + }, + { + "path": "src/components/ui/menu/popup.tsx", + "target": "components/ui/menu/popup.tsx" + }, + { + "path": "src/components/ui/menu/portal.tsx", + "target": "components/ui/menu/portal.tsx" + }, + { + "path": "src/components/ui/menu/positioner.tsx", + "target": "components/ui/menu/positioner.tsx" + }, + { + "path": "src/components/ui/menu/radio-group.tsx", + "target": "components/ui/menu/radio-group.tsx" + }, + { + "path": "src/components/ui/menu/radio-item-indicator.tsx", + "target": "components/ui/menu/radio-item-indicator.tsx" + }, + { + "path": "src/components/ui/menu/radio-item.tsx", + "target": "components/ui/menu/radio-item.tsx" + }, + { + "path": "src/components/ui/menu/root.tsx", + "target": "components/ui/menu/root.tsx" + }, + { + "path": "src/components/ui/menu/submenu-root.tsx", + "target": "components/ui/menu/submenu-root.tsx" + }, + { + "path": "src/components/ui/menu/submenu-trigger.tsx", + "target": "components/ui/menu/submenu-trigger.tsx" + }, + { + "path": "src/components/ui/menu/trigger.tsx", + "target": "components/ui/menu/trigger.tsx" + }, + { + "path": "src/components/ui/menu/viewport.tsx", + "target": "components/ui/menu/viewport.tsx" + } + ] + }, + "menubar": { + "name": "menubar", + "type": "component", + "description": "Menubar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/menubar/index.ts", + "target": "components/ui/menubar/index.ts" + }, + { + "path": "src/components/ui/menubar/root.tsx", + "target": "components/ui/menubar/root.tsx" + } + ] + }, + "meter": { + "name": "meter", + "type": "component", + "description": "Meter component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/meter/index.ts", + "target": "components/ui/meter/index.ts" + }, + { + "path": "src/components/ui/meter/indicator.tsx", + "target": "components/ui/meter/indicator.tsx" + }, + { + "path": "src/components/ui/meter/label.tsx", + "target": "components/ui/meter/label.tsx" + }, + { + "path": "src/components/ui/meter/root.tsx", + "target": "components/ui/meter/root.tsx" + }, + { + "path": "src/components/ui/meter/track.tsx", + "target": "components/ui/meter/track.tsx" + }, + { + "path": "src/components/ui/meter/value.tsx", + "target": "components/ui/meter/value.tsx" + } + ] + }, + "navigation-menu": { + "name": "navigation-menu", + "type": "component", + "description": "Navigation Menu component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/navigation-menu/arrow.tsx", + "target": "components/ui/navigation-menu/arrow.tsx" + }, + { + "path": "src/components/ui/navigation-menu/backdrop.tsx", + "target": "components/ui/navigation-menu/backdrop.tsx" + }, + { + "path": "src/components/ui/navigation-menu/content.tsx", + "target": "components/ui/navigation-menu/content.tsx" + }, + { + "path": "src/components/ui/navigation-menu/icon.tsx", + "target": "components/ui/navigation-menu/icon.tsx" + }, + { + "path": "src/components/ui/navigation-menu/index.ts", + "target": "components/ui/navigation-menu/index.ts" + }, + { + "path": "src/components/ui/navigation-menu/item.tsx", + "target": "components/ui/navigation-menu/item.tsx" + }, + { + "path": "src/components/ui/navigation-menu/link.tsx", + "target": "components/ui/navigation-menu/link.tsx" + }, + { + "path": "src/components/ui/navigation-menu/list.tsx", + "target": "components/ui/navigation-menu/list.tsx" + }, + { + "path": "src/components/ui/navigation-menu/popup.tsx", + "target": "components/ui/navigation-menu/popup.tsx" + }, + { + "path": "src/components/ui/navigation-menu/portal.tsx", + "target": "components/ui/navigation-menu/portal.tsx" + }, + { + "path": "src/components/ui/navigation-menu/positioner.tsx", + "target": "components/ui/navigation-menu/positioner.tsx" + }, + { + "path": "src/components/ui/navigation-menu/root.tsx", + "target": "components/ui/navigation-menu/root.tsx" + }, + { + "path": "src/components/ui/navigation-menu/trigger.tsx", + "target": "components/ui/navigation-menu/trigger.tsx" + }, + { + "path": "src/components/ui/navigation-menu/viewport.tsx", + "target": "components/ui/navigation-menu/viewport.tsx" + } + ] + }, + "number-field": { + "name": "number-field", + "type": "component", + "description": "Number Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/number-field/decrement.tsx", + "target": "components/ui/number-field/decrement.tsx" + }, + { + "path": "src/components/ui/number-field/group.tsx", + "target": "components/ui/number-field/group.tsx" + }, + { + "path": "src/components/ui/number-field/increment.tsx", + "target": "components/ui/number-field/increment.tsx" + }, + { + "path": "src/components/ui/number-field/index.ts", + "target": "components/ui/number-field/index.ts" + }, + { + "path": "src/components/ui/number-field/input.tsx", + "target": "components/ui/number-field/input.tsx" + }, + { + "path": "src/components/ui/number-field/root.tsx", + "target": "components/ui/number-field/root.tsx" + }, + { + "path": "src/components/ui/number-field/scrub-area-cursor.tsx", + "target": "components/ui/number-field/scrub-area-cursor.tsx" + }, + { + "path": "src/components/ui/number-field/scrub-area.tsx", + "target": "components/ui/number-field/scrub-area.tsx" + } + ] + }, + "otp-field": { + "name": "otp-field", + "type": "component", + "description": "Otp Field component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/otp-field/index.ts", + "target": "components/ui/otp-field/index.ts" + }, + { + "path": "src/components/ui/otp-field/input.tsx", + "target": "components/ui/otp-field/input.tsx" + }, + { + "path": "src/components/ui/otp-field/root.tsx", + "target": "components/ui/otp-field/root.tsx" + } + ] + }, + "popover": { + "name": "popover", + "type": "component", + "description": "Popover component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/popover/arrow.tsx", + "target": "components/ui/popover/arrow.tsx" + }, + { + "path": "src/components/ui/popover/backdrop.tsx", + "target": "components/ui/popover/backdrop.tsx" + }, + { + "path": "src/components/ui/popover/close.tsx", + "target": "components/ui/popover/close.tsx" + }, + { + "path": "src/components/ui/popover/content.tsx", + "target": "components/ui/popover/content.tsx" + }, + { + "path": "src/components/ui/popover/description.tsx", + "target": "components/ui/popover/description.tsx" + }, + { + "path": "src/components/ui/popover/index.ts", + "target": "components/ui/popover/index.ts" + }, + { + "path": "src/components/ui/popover/popup.tsx", + "target": "components/ui/popover/popup.tsx" + }, + { + "path": "src/components/ui/popover/portal.tsx", + "target": "components/ui/popover/portal.tsx" + }, + { + "path": "src/components/ui/popover/positioner.tsx", + "target": "components/ui/popover/positioner.tsx" + }, + { + "path": "src/components/ui/popover/root.tsx", + "target": "components/ui/popover/root.tsx" + }, + { + "path": "src/components/ui/popover/title.tsx", + "target": "components/ui/popover/title.tsx" + }, + { + "path": "src/components/ui/popover/trigger.tsx", + "target": "components/ui/popover/trigger.tsx" + }, + { + "path": "src/components/ui/popover/viewport.tsx", + "target": "components/ui/popover/viewport.tsx" + } + ] + }, + "preview-card": { + "name": "preview-card", + "type": "component", + "description": "Preview Card component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/preview-card/arrow.tsx", + "target": "components/ui/preview-card/arrow.tsx" + }, + { + "path": "src/components/ui/preview-card/backdrop.tsx", + "target": "components/ui/preview-card/backdrop.tsx" + }, + { + "path": "src/components/ui/preview-card/content.tsx", + "target": "components/ui/preview-card/content.tsx" + }, + { + "path": "src/components/ui/preview-card/index.ts", + "target": "components/ui/preview-card/index.ts" + }, + { + "path": "src/components/ui/preview-card/popup.tsx", + "target": "components/ui/preview-card/popup.tsx" + }, + { + "path": "src/components/ui/preview-card/portal.tsx", + "target": "components/ui/preview-card/portal.tsx" + }, + { + "path": "src/components/ui/preview-card/positioner.tsx", + "target": "components/ui/preview-card/positioner.tsx" + }, + { + "path": "src/components/ui/preview-card/root.tsx", + "target": "components/ui/preview-card/root.tsx" + }, + { + "path": "src/components/ui/preview-card/trigger.tsx", + "target": "components/ui/preview-card/trigger.tsx" + }, + { + "path": "src/components/ui/preview-card/viewport.tsx", + "target": "components/ui/preview-card/viewport.tsx" + } + ] + }, + "progress": { + "name": "progress", + "type": "component", + "description": "Progress component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/progress/index.ts", + "target": "components/ui/progress/index.ts" + }, + { + "path": "src/components/ui/progress/indicator.tsx", + "target": "components/ui/progress/indicator.tsx" + }, + { + "path": "src/components/ui/progress/label.tsx", + "target": "components/ui/progress/label.tsx" + }, + { + "path": "src/components/ui/progress/root.tsx", + "target": "components/ui/progress/root.tsx" + }, + { + "path": "src/components/ui/progress/track.tsx", + "target": "components/ui/progress/track.tsx" + }, + { + "path": "src/components/ui/progress/value.tsx", + "target": "components/ui/progress/value.tsx" + } + ] + }, + "radio": { + "name": "radio", + "type": "component", + "description": "Radio component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/radio/index.ts", + "target": "components/ui/radio/index.ts" + }, + { + "path": "src/components/ui/radio/indicator.tsx", + "target": "components/ui/radio/indicator.tsx" + }, + { + "path": "src/components/ui/radio/root.tsx", + "target": "components/ui/radio/root.tsx" + } + ] + }, + "scroll-area": { + "name": "scroll-area", + "type": "component", + "description": "Scroll Area component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/scroll-area/content.tsx", + "target": "components/ui/scroll-area/content.tsx" + }, + { + "path": "src/components/ui/scroll-area/corner.tsx", + "target": "components/ui/scroll-area/corner.tsx" + }, + { + "path": "src/components/ui/scroll-area/index.ts", + "target": "components/ui/scroll-area/index.ts" + }, + { + "path": "src/components/ui/scroll-area/root.tsx", + "target": "components/ui/scroll-area/root.tsx" + }, + { + "path": "src/components/ui/scroll-area/scrollbar.tsx", + "target": "components/ui/scroll-area/scrollbar.tsx" + }, + { + "path": "src/components/ui/scroll-area/thumb.tsx", + "target": "components/ui/scroll-area/thumb.tsx" + }, + { + "path": "src/components/ui/scroll-area/viewport.tsx", + "target": "components/ui/scroll-area/viewport.tsx" + } + ] + }, + "select": { + "name": "select", + "type": "component", + "description": "Select component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/select/arrow.tsx", + "target": "components/ui/select/arrow.tsx" + }, + { + "path": "src/components/ui/select/backdrop.tsx", + "target": "components/ui/select/backdrop.tsx" + }, + { + "path": "src/components/ui/select/group-label.tsx", + "target": "components/ui/select/group-label.tsx" + }, + { + "path": "src/components/ui/select/group.tsx", + "target": "components/ui/select/group.tsx" + }, + { + "path": "src/components/ui/select/icon.tsx", + "target": "components/ui/select/icon.tsx" + }, + { + "path": "src/components/ui/select/index.ts", + "target": "components/ui/select/index.ts" + }, + { + "path": "src/components/ui/select/item-indicator.tsx", + "target": "components/ui/select/item-indicator.tsx" + }, + { + "path": "src/components/ui/select/item-text.tsx", + "target": "components/ui/select/item-text.tsx" + }, + { + "path": "src/components/ui/select/item.tsx", + "target": "components/ui/select/item.tsx" + }, + { + "path": "src/components/ui/select/label.tsx", + "target": "components/ui/select/label.tsx" + }, + { + "path": "src/components/ui/select/list.tsx", + "target": "components/ui/select/list.tsx" + }, + { + "path": "src/components/ui/select/popup.tsx", + "target": "components/ui/select/popup.tsx" + }, + { + "path": "src/components/ui/select/portal.tsx", + "target": "components/ui/select/portal.tsx" + }, + { + "path": "src/components/ui/select/positioner.tsx", + "target": "components/ui/select/positioner.tsx" + }, + { + "path": "src/components/ui/select/root.tsx", + "target": "components/ui/select/root.tsx" + }, + { + "path": "src/components/ui/select/scroll-down-arrow.tsx", + "target": "components/ui/select/scroll-down-arrow.tsx" + }, + { + "path": "src/components/ui/select/scroll-up-arrow.tsx", + "target": "components/ui/select/scroll-up-arrow.tsx" + }, + { + "path": "src/components/ui/select/separator.tsx", + "target": "components/ui/select/separator.tsx" + }, + { + "path": "src/components/ui/select/trigger.tsx", + "target": "components/ui/select/trigger.tsx" + }, + { + "path": "src/components/ui/select/value.tsx", + "target": "components/ui/select/value.tsx" + } + ] + }, + "separator": { + "name": "separator", + "type": "component", + "description": "Separator component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/separator/index.ts", + "target": "components/ui/separator/index.ts" + }, + { + "path": "src/components/ui/separator/root.tsx", + "target": "components/ui/separator/root.tsx" + } + ] + }, + "slider": { + "name": "slider", + "type": "component", + "description": "Slider component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/slider/control.tsx", + "target": "components/ui/slider/control.tsx" + }, + { + "path": "src/components/ui/slider/index.ts", + "target": "components/ui/slider/index.ts" + }, + { + "path": "src/components/ui/slider/indicator.tsx", + "target": "components/ui/slider/indicator.tsx" + }, + { + "path": "src/components/ui/slider/label.tsx", + "target": "components/ui/slider/label.tsx" + }, + { + "path": "src/components/ui/slider/root.tsx", + "target": "components/ui/slider/root.tsx" + }, + { + "path": "src/components/ui/slider/thumb.tsx", + "target": "components/ui/slider/thumb.tsx" + }, + { + "path": "src/components/ui/slider/track.tsx", + "target": "components/ui/slider/track.tsx" + }, + { + "path": "src/components/ui/slider/value.tsx", + "target": "components/ui/slider/value.tsx" + } + ] + }, + "switch": { + "name": "switch", + "type": "component", + "description": "Switch component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/switch/index.ts", + "target": "components/ui/switch/index.ts" + }, + { + "path": "src/components/ui/switch/root.tsx", + "target": "components/ui/switch/root.tsx" + }, + { + "path": "src/components/ui/switch/thumb.tsx", + "target": "components/ui/switch/thumb.tsx" + } + ] + }, + "tabs": { + "name": "tabs", + "type": "component", + "description": "Tabs component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/tabs/index.ts", + "target": "components/ui/tabs/index.ts" + }, + { + "path": "src/components/ui/tabs/indicator.tsx", + "target": "components/ui/tabs/indicator.tsx" + }, + { + "path": "src/components/ui/tabs/list.tsx", + "target": "components/ui/tabs/list.tsx" + }, + { + "path": "src/components/ui/tabs/panel.tsx", + "target": "components/ui/tabs/panel.tsx" + }, + { + "path": "src/components/ui/tabs/root.tsx", + "target": "components/ui/tabs/root.tsx" + }, + { + "path": "src/components/ui/tabs/tab.tsx", + "target": "components/ui/tabs/tab.tsx" + } + ] + }, + "toast": { + "name": "toast", + "type": "component", + "description": "Toast component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/portal-container", + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toast/action.tsx", + "target": "components/ui/toast/action.tsx" + }, + { + "path": "src/components/ui/toast/arrow.tsx", + "target": "components/ui/toast/arrow.tsx" + }, + { + "path": "src/components/ui/toast/close.tsx", + "target": "components/ui/toast/close.tsx" + }, + { + "path": "src/components/ui/toast/content.tsx", + "target": "components/ui/toast/content.tsx" + }, + { + "path": "src/components/ui/toast/description.tsx", + "target": "components/ui/toast/description.tsx" + }, + { + "path": "src/components/ui/toast/index.ts", + "target": "components/ui/toast/index.ts" + }, + { + "path": "src/components/ui/toast/portal.tsx", + "target": "components/ui/toast/portal.tsx" + }, + { + "path": "src/components/ui/toast/positioner.tsx", + "target": "components/ui/toast/positioner.tsx" + }, + { + "path": "src/components/ui/toast/provider.tsx", + "target": "components/ui/toast/provider.tsx" + }, + { + "path": "src/components/ui/toast/root.tsx", + "target": "components/ui/toast/root.tsx" + }, + { + "path": "src/components/ui/toast/title.tsx", + "target": "components/ui/toast/title.tsx" + }, + { + "path": "src/components/ui/toast/viewport.tsx", + "target": "components/ui/toast/viewport.tsx" + } + ] + }, + "toggle": { + "name": "toggle", + "type": "component", + "description": "Toggle component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toggle/index.ts", + "target": "components/ui/toggle/index.ts" + }, + { + "path": "src/components/ui/toggle/root.tsx", + "target": "components/ui/toggle/root.tsx" + } + ] + }, + "toggle-group": { + "name": "toggle-group", + "type": "component", + "description": "Toggle Group component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toggle-group/index.ts", + "target": "components/ui/toggle-group/index.ts" + }, + { + "path": "src/components/ui/toggle-group/root.tsx", + "target": "components/ui/toggle-group/root.tsx" + } + ] + }, + "toolbar": { + "name": "toolbar", + "type": "component", + "description": "Toolbar component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/toolbar/button.tsx", + "target": "components/ui/toolbar/button.tsx" + }, + { + "path": "src/components/ui/toolbar/group.tsx", + "target": "components/ui/toolbar/group.tsx" + }, + { + "path": "src/components/ui/toolbar/index.ts", + "target": "components/ui/toolbar/index.ts" + }, + { + "path": "src/components/ui/toolbar/input.tsx", + "target": "components/ui/toolbar/input.tsx" + }, + { + "path": "src/components/ui/toolbar/link.tsx", + "target": "components/ui/toolbar/link.tsx" + }, + { + "path": "src/components/ui/toolbar/root.tsx", + "target": "components/ui/toolbar/root.tsx" + }, + { + "path": "src/components/ui/toolbar/separator.tsx", + "target": "components/ui/toolbar/separator.tsx" + } + ] + }, + "tooltip": { + "name": "tooltip", + "type": "component", + "description": "Tooltip component wrapper for Base UI and Tailwind CSS.", + "dependencies": [ + "@base-ui/react", + "react" + ], + "localDependencies": [ + "utils/utils" + ], + "files": [ + { + "path": "src/components/ui/tooltip/arrow.tsx", + "target": "components/ui/tooltip/arrow.tsx" + }, + { + "path": "src/components/ui/tooltip/content.tsx", + "target": "components/ui/tooltip/content.tsx" + }, + { + "path": "src/components/ui/tooltip/index.ts", + "target": "components/ui/tooltip/index.ts" + }, + { + "path": "src/components/ui/tooltip/popup.tsx", + "target": "components/ui/tooltip/popup.tsx" + }, + { + "path": "src/components/ui/tooltip/portal.tsx", + "target": "components/ui/tooltip/portal.tsx" + }, + { + "path": "src/components/ui/tooltip/positioner.tsx", + "target": "components/ui/tooltip/positioner.tsx" + }, + { + "path": "src/components/ui/tooltip/provider.tsx", + "target": "components/ui/tooltip/provider.tsx" + }, + { + "path": "src/components/ui/tooltip/root.tsx", + "target": "components/ui/tooltip/root.tsx" + }, + { + "path": "src/components/ui/tooltip/trigger.tsx", + "target": "components/ui/tooltip/trigger.tsx" + }, + { + "path": "src/components/ui/tooltip/viewport.tsx", + "target": "components/ui/tooltip/viewport.tsx" + } + ] + } + } +} diff --git a/scripts/check-ui-exports.mjs b/scripts/check-ui-exports.mjs new file mode 100644 index 0000000..0eee965 --- /dev/null +++ b/scripts/check-ui-exports.mjs @@ -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.`) diff --git a/scripts/generate-manifest.mjs b/scripts/generate-manifest.mjs new file mode 100644 index 0000000..1e958ef --- /dev/null +++ b/scripts/generate-manifest.mjs @@ -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(" ") +} diff --git a/scripts/normalize-component-docs.mjs b/scripts/normalize-component-docs.mjs new file mode 100644 index 0000000..a4b0665 --- /dev/null +++ b/scripts/normalize-component-docs.mjs @@ -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`] + for (const part of parts.filter((part) => part !== "Root").slice(0, 5)) { + lines.push(` <${component}.${part} />`) + } + lines.push(``) + 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` | `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, "\\$&") +} diff --git a/src/components/ui/accordion/header.tsx b/src/components/ui/accordion/header.tsx new file mode 100644 index 0000000..60e6474 --- /dev/null +++ b/src/components/ui/accordion/header.tsx @@ -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 & { + className?: string +} + +const BaseAccordionHeader = BaseAccordion.Header as React.ElementType + +export const AccordionHeader = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionHeader.displayName = "AccordionHeader" diff --git a/src/components/ui/accordion/index.ts b/src/components/ui/accordion/index.ts new file mode 100644 index 0000000..175aa55 --- /dev/null +++ b/src/components/ui/accordion/index.ts @@ -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" diff --git a/src/components/ui/accordion/item.tsx b/src/components/ui/accordion/item.tsx new file mode 100644 index 0000000..8457890 --- /dev/null +++ b/src/components/ui/accordion/item.tsx @@ -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 & { + className?: string +} + +const BaseAccordionItem = BaseAccordion.Item as React.ElementType + +export const AccordionItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionItem.displayName = "AccordionItem" diff --git a/src/components/ui/accordion/panel.tsx b/src/components/ui/accordion/panel.tsx new file mode 100644 index 0000000..3b03f58 --- /dev/null +++ b/src/components/ui/accordion/panel.tsx @@ -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 & { + className?: string +} + +const BaseAccordionPanel = BaseAccordion.Panel as React.ElementType + +export const AccordionPanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionPanel.displayName = "AccordionPanel" diff --git a/src/components/ui/accordion/root.tsx b/src/components/ui/accordion/root.tsx new file mode 100644 index 0000000..3d0b294 --- /dev/null +++ b/src/components/ui/accordion/root.tsx @@ -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 & { + className?: string +} + +const BaseAccordionRoot = BaseAccordion.Root as React.ElementType + +export const AccordionRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionRoot.displayName = "AccordionRoot" diff --git a/src/components/ui/accordion/trigger.tsx b/src/components/ui/accordion/trigger.tsx new file mode 100644 index 0000000..008b00d --- /dev/null +++ b/src/components/ui/accordion/trigger.tsx @@ -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 & { + className?: string +} + +const BaseAccordionTrigger = BaseAccordion.Trigger as React.ElementType + +export const AccordionTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AccordionTrigger.displayName = "AccordionTrigger" diff --git a/src/components/ui/alert-dialog/backdrop.tsx b/src/components/ui/alert-dialog/backdrop.tsx new file mode 100644 index 0000000..b1207b6 --- /dev/null +++ b/src/components/ui/alert-dialog/backdrop.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogBackdrop = BaseAlertDialog.Backdrop as React.ElementType + +export const AlertDialogBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogBackdrop.displayName = "AlertDialogBackdrop" diff --git a/src/components/ui/alert-dialog/close.tsx b/src/components/ui/alert-dialog/close.tsx new file mode 100644 index 0000000..b49e0f0 --- /dev/null +++ b/src/components/ui/alert-dialog/close.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogClose = BaseAlertDialog.Close as React.ElementType + +export const AlertDialogClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogClose.displayName = "AlertDialogClose" diff --git a/src/components/ui/alert-dialog/content.tsx b/src/components/ui/alert-dialog/content.tsx new file mode 100644 index 0000000..57b9c29 --- /dev/null +++ b/src/components/ui/alert-dialog/content.tsx @@ -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( + ({ className, ...props }, ref) => ( + + + + + ), +) + +AlertDialogContent.displayName = "AlertDialogContent" diff --git a/src/components/ui/alert-dialog/description.tsx b/src/components/ui/alert-dialog/description.tsx new file mode 100644 index 0000000..6a003ae --- /dev/null +++ b/src/components/ui/alert-dialog/description.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogDescription = BaseAlertDialog.Description as React.ElementType + +export const AlertDialogDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogDescription.displayName = "AlertDialogDescription" diff --git a/src/components/ui/alert-dialog/index.ts b/src/components/ui/alert-dialog/index.ts new file mode 100644 index 0000000..ae22916 --- /dev/null +++ b/src/components/ui/alert-dialog/index.ts @@ -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" diff --git a/src/components/ui/alert-dialog/popup.tsx b/src/components/ui/alert-dialog/popup.tsx new file mode 100644 index 0000000..2030d70 --- /dev/null +++ b/src/components/ui/alert-dialog/popup.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogPopup = BaseAlertDialog.Popup as React.ElementType + +export const AlertDialogPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogPopup.displayName = "AlertDialogPopup" diff --git a/src/components/ui/alert-dialog/portal.tsx b/src/components/ui/alert-dialog/portal.tsx new file mode 100644 index 0000000..fff4f4a --- /dev/null +++ b/src/components/ui/alert-dialog/portal.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogPortal = BaseAlertDialog.Portal as React.ElementType + +export const AlertDialogPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +AlertDialogPortal.displayName = "AlertDialogPortal" diff --git a/src/components/ui/alert-dialog/root.tsx b/src/components/ui/alert-dialog/root.tsx new file mode 100644 index 0000000..72c333a --- /dev/null +++ b/src/components/ui/alert-dialog/root.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogRoot = BaseAlertDialog.Root as React.ElementType + +export const AlertDialogRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogRoot.displayName = "AlertDialogRoot" diff --git a/src/components/ui/alert-dialog/title.tsx b/src/components/ui/alert-dialog/title.tsx new file mode 100644 index 0000000..b885b87 --- /dev/null +++ b/src/components/ui/alert-dialog/title.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogTitle = BaseAlertDialog.Title as React.ElementType + +export const AlertDialogTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogTitle.displayName = "AlertDialogTitle" diff --git a/src/components/ui/alert-dialog/trigger.tsx b/src/components/ui/alert-dialog/trigger.tsx new file mode 100644 index 0000000..adddb00 --- /dev/null +++ b/src/components/ui/alert-dialog/trigger.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogTrigger = BaseAlertDialog.Trigger as React.ElementType + +export const AlertDialogTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogTrigger.displayName = "AlertDialogTrigger" diff --git a/src/components/ui/alert-dialog/viewport.tsx b/src/components/ui/alert-dialog/viewport.tsx new file mode 100644 index 0000000..9dc9ef3 --- /dev/null +++ b/src/components/ui/alert-dialog/viewport.tsx @@ -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 & { + className?: string +} + +const BaseAlertDialogViewport = BaseAlertDialog.Viewport as React.ElementType + +export const AlertDialogViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AlertDialogViewport.displayName = "AlertDialogViewport" diff --git a/src/components/ui/autocomplete/arrow.tsx b/src/components/ui/autocomplete/arrow.tsx new file mode 100644 index 0000000..169c9e9 --- /dev/null +++ b/src/components/ui/autocomplete/arrow.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteArrow = BaseAutocomplete.Arrow as React.ElementType + +export const AutocompleteArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteArrow.displayName = "AutocompleteArrow" diff --git a/src/components/ui/autocomplete/backdrop.tsx b/src/components/ui/autocomplete/backdrop.tsx new file mode 100644 index 0000000..9d77373 --- /dev/null +++ b/src/components/ui/autocomplete/backdrop.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteBackdrop = BaseAutocomplete.Backdrop as React.ElementType + +export const AutocompleteBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteBackdrop.displayName = "AutocompleteBackdrop" diff --git a/src/components/ui/autocomplete/clear.tsx b/src/components/ui/autocomplete/clear.tsx new file mode 100644 index 0000000..23339e1 --- /dev/null +++ b/src/components/ui/autocomplete/clear.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteClear = BaseAutocomplete.Clear as React.ElementType + +export const AutocompleteClear = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteClear.displayName = "AutocompleteClear" diff --git a/src/components/ui/autocomplete/collection.tsx b/src/components/ui/autocomplete/collection.tsx new file mode 100644 index 0000000..515b75a --- /dev/null +++ b/src/components/ui/autocomplete/collection.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteCollection = BaseAutocomplete.Collection as React.ElementType + +export const AutocompleteCollection = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteCollection.displayName = "AutocompleteCollection" diff --git a/src/components/ui/autocomplete/empty.tsx b/src/components/ui/autocomplete/empty.tsx new file mode 100644 index 0000000..ddacea3 --- /dev/null +++ b/src/components/ui/autocomplete/empty.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteEmpty = BaseAutocomplete.Empty as React.ElementType + +export const AutocompleteEmpty = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteEmpty.displayName = "AutocompleteEmpty" diff --git a/src/components/ui/autocomplete/group-label.tsx b/src/components/ui/autocomplete/group-label.tsx new file mode 100644 index 0000000..759aaf7 --- /dev/null +++ b/src/components/ui/autocomplete/group-label.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteGroupLabel = BaseAutocomplete.GroupLabel as React.ElementType + +export const AutocompleteGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteGroupLabel.displayName = "AutocompleteGroupLabel" diff --git a/src/components/ui/autocomplete/group.tsx b/src/components/ui/autocomplete/group.tsx new file mode 100644 index 0000000..4553de7 --- /dev/null +++ b/src/components/ui/autocomplete/group.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteGroup = BaseAutocomplete.Group as React.ElementType + +export const AutocompleteGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteGroup.displayName = "AutocompleteGroup" diff --git a/src/components/ui/autocomplete/icon.tsx b/src/components/ui/autocomplete/icon.tsx new file mode 100644 index 0000000..7cd0acb --- /dev/null +++ b/src/components/ui/autocomplete/icon.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteIcon = BaseAutocomplete.Icon as React.ElementType + +export const AutocompleteIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteIcon.displayName = "AutocompleteIcon" diff --git a/src/components/ui/autocomplete/index.ts b/src/components/ui/autocomplete/index.ts new file mode 100644 index 0000000..9747a78 --- /dev/null +++ b/src/components/ui/autocomplete/index.ts @@ -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" diff --git a/src/components/ui/autocomplete/input-group.tsx b/src/components/ui/autocomplete/input-group.tsx new file mode 100644 index 0000000..4f074d7 --- /dev/null +++ b/src/components/ui/autocomplete/input-group.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteInputGroup = BaseAutocomplete.InputGroup as React.ElementType + +export const AutocompleteInputGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteInputGroup.displayName = "AutocompleteInputGroup" diff --git a/src/components/ui/autocomplete/input.tsx b/src/components/ui/autocomplete/input.tsx new file mode 100644 index 0000000..12473c7 --- /dev/null +++ b/src/components/ui/autocomplete/input.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteInput = BaseAutocomplete.Input as React.ElementType + +export const AutocompleteInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteInput.displayName = "AutocompleteInput" diff --git a/src/components/ui/autocomplete/item.tsx b/src/components/ui/autocomplete/item.tsx new file mode 100644 index 0000000..eeb4cdc --- /dev/null +++ b/src/components/ui/autocomplete/item.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteItem = BaseAutocomplete.Item as React.ElementType + +export const AutocompleteItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteItem.displayName = "AutocompleteItem" diff --git a/src/components/ui/autocomplete/list.tsx b/src/components/ui/autocomplete/list.tsx new file mode 100644 index 0000000..443e75c --- /dev/null +++ b/src/components/ui/autocomplete/list.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteList = BaseAutocomplete.List as React.ElementType + +export const AutocompleteList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteList.displayName = "AutocompleteList" diff --git a/src/components/ui/autocomplete/popup.tsx b/src/components/ui/autocomplete/popup.tsx new file mode 100644 index 0000000..e00e31d --- /dev/null +++ b/src/components/ui/autocomplete/popup.tsx @@ -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 & { + 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( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePopup.displayName = "AutocompletePopup" diff --git a/src/components/ui/autocomplete/portal.tsx b/src/components/ui/autocomplete/portal.tsx new file mode 100644 index 0000000..82a6806 --- /dev/null +++ b/src/components/ui/autocomplete/portal.tsx @@ -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 & { + className?: string +} + +const BaseAutocompletePortal = BaseAutocomplete.Portal as React.ElementType + +export const AutocompletePortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePortal.displayName = "AutocompletePortal" diff --git a/src/components/ui/autocomplete/positioner.tsx b/src/components/ui/autocomplete/positioner.tsx new file mode 100644 index 0000000..7bcd037 --- /dev/null +++ b/src/components/ui/autocomplete/positioner.tsx @@ -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 & { + className?: string +} + +const BaseAutocompletePositioner = BaseAutocomplete.Positioner as React.ElementType + +export const AutocompletePositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompletePositioner.displayName = "AutocompletePositioner" diff --git a/src/components/ui/autocomplete/root.tsx b/src/components/ui/autocomplete/root.tsx new file mode 100644 index 0000000..b6a6cb1 --- /dev/null +++ b/src/components/ui/autocomplete/root.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteRoot = BaseAutocomplete.Root as React.ElementType + +export const AutocompleteRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteRoot.displayName = "AutocompleteRoot" diff --git a/src/components/ui/autocomplete/row.tsx b/src/components/ui/autocomplete/row.tsx new file mode 100644 index 0000000..53c52af --- /dev/null +++ b/src/components/ui/autocomplete/row.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteRow = BaseAutocomplete.Row as React.ElementType + +export const AutocompleteRow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteRow.displayName = "AutocompleteRow" diff --git a/src/components/ui/autocomplete/trigger.tsx b/src/components/ui/autocomplete/trigger.tsx new file mode 100644 index 0000000..b931608 --- /dev/null +++ b/src/components/ui/autocomplete/trigger.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteTrigger = BaseAutocomplete.Trigger as React.ElementType + +export const AutocompleteTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteTrigger.displayName = "AutocompleteTrigger" diff --git a/src/components/ui/autocomplete/value.tsx b/src/components/ui/autocomplete/value.tsx new file mode 100644 index 0000000..e6abe76 --- /dev/null +++ b/src/components/ui/autocomplete/value.tsx @@ -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 & { + className?: string +} + +const BaseAutocompleteValue = BaseAutocomplete.Value as React.ElementType + +export const AutocompleteValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AutocompleteValue.displayName = "AutocompleteValue" diff --git a/src/components/ui/avatar/fallback.tsx b/src/components/ui/avatar/fallback.tsx new file mode 100644 index 0000000..3dc783f --- /dev/null +++ b/src/components/ui/avatar/fallback.tsx @@ -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 & { + className?: string +} + +const BaseAvatarFallback = BaseAvatar.Fallback as React.ElementType + +export const AvatarFallback = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarFallback.displayName = "AvatarFallback" diff --git a/src/components/ui/avatar/image.tsx b/src/components/ui/avatar/image.tsx new file mode 100644 index 0000000..450a933 --- /dev/null +++ b/src/components/ui/avatar/image.tsx @@ -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 & { + className?: string +} + +const BaseAvatarImage = BaseAvatar.Image as React.ElementType + +export const AvatarImage = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarImage.displayName = "AvatarImage" diff --git a/src/components/ui/avatar/index.ts b/src/components/ui/avatar/index.ts new file mode 100644 index 0000000..7c19bef --- /dev/null +++ b/src/components/ui/avatar/index.ts @@ -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" diff --git a/src/components/ui/avatar/root.tsx b/src/components/ui/avatar/root.tsx new file mode 100644 index 0000000..42ea2aa --- /dev/null +++ b/src/components/ui/avatar/root.tsx @@ -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 & { + className?: string +} + +const BaseAvatarRoot = BaseAvatar.Root as React.ElementType + +export const AvatarRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +AvatarRoot.displayName = "AvatarRoot" diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts new file mode 100644 index 0000000..2b5c37f --- /dev/null +++ b/src/components/ui/button/index.ts @@ -0,0 +1,4 @@ +import { Button } from "./root" + +export { Button, type ButtonProps } from "./root" +export default Button diff --git a/src/components/ui/button/root.tsx b/src/components/ui/button/root.tsx new file mode 100644 index 0000000..649e619 --- /dev/null +++ b/src/components/ui/button/root.tsx @@ -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 & { + className?: string +} + +const BaseButtonElement = BaseButton as React.ElementType + +export const Button = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Button.displayName = "Button" diff --git a/src/components/ui/checkbox-group/index.ts b/src/components/ui/checkbox-group/index.ts new file mode 100644 index 0000000..3dd6db8 --- /dev/null +++ b/src/components/ui/checkbox-group/index.ts @@ -0,0 +1,4 @@ +import { CheckboxGroup } from "./root" + +export { CheckboxGroup, type CheckboxGroupProps } from "./root" +export default CheckboxGroup diff --git a/src/components/ui/checkbox-group/root.tsx b/src/components/ui/checkbox-group/root.tsx new file mode 100644 index 0000000..d202579 --- /dev/null +++ b/src/components/ui/checkbox-group/root.tsx @@ -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 & { className?: string } + +const BaseCheckboxGroupElement = BaseCheckboxGroup as React.ElementType + +export const CheckboxGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxGroup.displayName = "CheckboxGroup" diff --git a/src/components/ui/checkbox/index.ts b/src/components/ui/checkbox/index.ts new file mode 100644 index 0000000..2f1bc73 --- /dev/null +++ b/src/components/ui/checkbox/index.ts @@ -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" diff --git a/src/components/ui/checkbox/indicator.tsx b/src/components/ui/checkbox/indicator.tsx new file mode 100644 index 0000000..395fcee --- /dev/null +++ b/src/components/ui/checkbox/indicator.tsx @@ -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 & { + className?: string +} + +const BaseCheckboxIndicator = BaseCheckbox.Indicator as React.ElementType + +export const CheckboxIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxIndicator.displayName = "CheckboxIndicator" diff --git a/src/components/ui/checkbox/root.tsx b/src/components/ui/checkbox/root.tsx new file mode 100644 index 0000000..4697673 --- /dev/null +++ b/src/components/ui/checkbox/root.tsx @@ -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 & { + className?: string +} + +const BaseCheckboxRoot = BaseCheckbox.Root as React.ElementType + +export const CheckboxRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CheckboxRoot.displayName = "CheckboxRoot" diff --git a/src/components/ui/collapsible/index.ts b/src/components/ui/collapsible/index.ts new file mode 100644 index 0000000..38b96dd --- /dev/null +++ b/src/components/ui/collapsible/index.ts @@ -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" diff --git a/src/components/ui/collapsible/panel.tsx b/src/components/ui/collapsible/panel.tsx new file mode 100644 index 0000000..2cae774 --- /dev/null +++ b/src/components/ui/collapsible/panel.tsx @@ -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 & { + className?: string +} + +const BaseCollapsiblePanel = BaseCollapsible.Panel as React.ElementType + +export const CollapsiblePanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsiblePanel.displayName = "CollapsiblePanel" diff --git a/src/components/ui/collapsible/root.tsx b/src/components/ui/collapsible/root.tsx new file mode 100644 index 0000000..aa2d54f --- /dev/null +++ b/src/components/ui/collapsible/root.tsx @@ -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 & { + className?: string +} + +const BaseCollapsibleRoot = BaseCollapsible.Root as React.ElementType + +export const CollapsibleRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsibleRoot.displayName = "CollapsibleRoot" diff --git a/src/components/ui/collapsible/trigger.tsx b/src/components/ui/collapsible/trigger.tsx new file mode 100644 index 0000000..58bdea0 --- /dev/null +++ b/src/components/ui/collapsible/trigger.tsx @@ -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 & { + className?: string +} + +const BaseCollapsibleTrigger = BaseCollapsible.Trigger as React.ElementType + +export const CollapsibleTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +CollapsibleTrigger.displayName = "CollapsibleTrigger" diff --git a/src/components/ui/combobox/arrow.tsx b/src/components/ui/combobox/arrow.tsx new file mode 100644 index 0000000..6146148 --- /dev/null +++ b/src/components/ui/combobox/arrow.tsx @@ -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 & { + className?: string +} + +const BaseComboboxArrow = BaseCombobox.Arrow as React.ElementType + +export const ComboboxArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxArrow.displayName = "ComboboxArrow" diff --git a/src/components/ui/combobox/backdrop.tsx b/src/components/ui/combobox/backdrop.tsx new file mode 100644 index 0000000..ae50fb7 --- /dev/null +++ b/src/components/ui/combobox/backdrop.tsx @@ -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 & { + className?: string +} + +const BaseComboboxBackdrop = BaseCombobox.Backdrop as React.ElementType + +export const ComboboxBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxBackdrop.displayName = "ComboboxBackdrop" diff --git a/src/components/ui/combobox/chip-remove.tsx b/src/components/ui/combobox/chip-remove.tsx new file mode 100644 index 0000000..9898131 --- /dev/null +++ b/src/components/ui/combobox/chip-remove.tsx @@ -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 & { + className?: string +} + +const BaseComboboxChipRemove = BaseCombobox.ChipRemove as React.ElementType + +export const ComboboxChipRemove = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChipRemove.displayName = "ComboboxChipRemove" diff --git a/src/components/ui/combobox/chip.tsx b/src/components/ui/combobox/chip.tsx new file mode 100644 index 0000000..bae7c42 --- /dev/null +++ b/src/components/ui/combobox/chip.tsx @@ -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 & { + className?: string +} + +const BaseComboboxChip = BaseCombobox.Chip as React.ElementType + +export const ComboboxChip = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChip.displayName = "ComboboxChip" diff --git a/src/components/ui/combobox/chips.tsx b/src/components/ui/combobox/chips.tsx new file mode 100644 index 0000000..8e9f3f2 --- /dev/null +++ b/src/components/ui/combobox/chips.tsx @@ -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 & { + className?: string +} + +const BaseComboboxChips = BaseCombobox.Chips as React.ElementType + +export const ComboboxChips = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxChips.displayName = "ComboboxChips" diff --git a/src/components/ui/combobox/clear.tsx b/src/components/ui/combobox/clear.tsx new file mode 100644 index 0000000..51026ee --- /dev/null +++ b/src/components/ui/combobox/clear.tsx @@ -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 & { + className?: string +} + +const BaseComboboxClear = BaseCombobox.Clear as React.ElementType + +export const ComboboxClear = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxClear.displayName = "ComboboxClear" diff --git a/src/components/ui/combobox/collection.tsx b/src/components/ui/combobox/collection.tsx new file mode 100644 index 0000000..bd59b65 --- /dev/null +++ b/src/components/ui/combobox/collection.tsx @@ -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 & { + className?: string +} + +const BaseComboboxCollection = BaseCombobox.Collection as React.ElementType + +export const ComboboxCollection = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxCollection.displayName = "ComboboxCollection" diff --git a/src/components/ui/combobox/empty.tsx b/src/components/ui/combobox/empty.tsx new file mode 100644 index 0000000..66c57ac --- /dev/null +++ b/src/components/ui/combobox/empty.tsx @@ -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 & { + className?: string +} + +const BaseComboboxEmpty = BaseCombobox.Empty as React.ElementType + +export const ComboboxEmpty = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxEmpty.displayName = "ComboboxEmpty" diff --git a/src/components/ui/combobox/group-label.tsx b/src/components/ui/combobox/group-label.tsx new file mode 100644 index 0000000..e954c81 --- /dev/null +++ b/src/components/ui/combobox/group-label.tsx @@ -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 & { + className?: string +} + +const BaseComboboxGroupLabel = BaseCombobox.GroupLabel as React.ElementType + +export const ComboboxGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxGroupLabel.displayName = "ComboboxGroupLabel" diff --git a/src/components/ui/combobox/group.tsx b/src/components/ui/combobox/group.tsx new file mode 100644 index 0000000..08b0535 --- /dev/null +++ b/src/components/ui/combobox/group.tsx @@ -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 & { + className?: string +} + +const BaseComboboxGroup = BaseCombobox.Group as React.ElementType + +export const ComboboxGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxGroup.displayName = "ComboboxGroup" diff --git a/src/components/ui/combobox/icon.tsx b/src/components/ui/combobox/icon.tsx new file mode 100644 index 0000000..16cf06d --- /dev/null +++ b/src/components/ui/combobox/icon.tsx @@ -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 & { + className?: string +} + +const BaseComboboxIcon = BaseCombobox.Icon as React.ElementType + +export const ComboboxIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxIcon.displayName = "ComboboxIcon" diff --git a/src/components/ui/combobox/index.ts b/src/components/ui/combobox/index.ts new file mode 100644 index 0000000..6e577fb --- /dev/null +++ b/src/components/ui/combobox/index.ts @@ -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" diff --git a/src/components/ui/combobox/input-group.tsx b/src/components/ui/combobox/input-group.tsx new file mode 100644 index 0000000..0454ef5 --- /dev/null +++ b/src/components/ui/combobox/input-group.tsx @@ -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 & { + className?: string +} + +const BaseComboboxInputGroup = BaseCombobox.InputGroup as React.ElementType + +export const ComboboxInputGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + input]:pr-10 has-[.combobox-clear]:[&>input]:pr-18", + className, + )} + {...props} + /> + ), +) + +ComboboxInputGroup.displayName = "ComboboxInputGroup" diff --git a/src/components/ui/combobox/input.tsx b/src/components/ui/combobox/input.tsx new file mode 100644 index 0000000..47fef59 --- /dev/null +++ b/src/components/ui/combobox/input.tsx @@ -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 & { + className?: string +} + +const BaseComboboxInput = BaseCombobox.Input as React.ElementType + +export const ComboboxInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxInput.displayName = "ComboboxInput" diff --git a/src/components/ui/combobox/item-indicator.tsx b/src/components/ui/combobox/item-indicator.tsx new file mode 100644 index 0000000..6a03412 --- /dev/null +++ b/src/components/ui/combobox/item-indicator.tsx @@ -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 & { + className?: string +} + +const BaseComboboxItemIndicator = BaseCombobox.ItemIndicator as React.ElementType + +export const ComboboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxItemIndicator.displayName = "ComboboxItemIndicator" diff --git a/src/components/ui/combobox/item.tsx b/src/components/ui/combobox/item.tsx new file mode 100644 index 0000000..c096a96 --- /dev/null +++ b/src/components/ui/combobox/item.tsx @@ -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 & { + className?: string +} + +const BaseComboboxItem = BaseCombobox.Item as React.ElementType + +export const ComboboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxItem.displayName = "ComboboxItem" diff --git a/src/components/ui/combobox/label.tsx b/src/components/ui/combobox/label.tsx new file mode 100644 index 0000000..f5e3830 --- /dev/null +++ b/src/components/ui/combobox/label.tsx @@ -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 & { + className?: string +} + +const BaseComboboxLabel = BaseCombobox.Label as React.ElementType + +export const ComboboxLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxLabel.displayName = "ComboboxLabel" diff --git a/src/components/ui/combobox/list.tsx b/src/components/ui/combobox/list.tsx new file mode 100644 index 0000000..4c21d2a --- /dev/null +++ b/src/components/ui/combobox/list.tsx @@ -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 & { + className?: string +} + +const BaseComboboxList = BaseCombobox.List as React.ElementType + +export const ComboboxList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxList.displayName = "ComboboxList" diff --git a/src/components/ui/combobox/popup.tsx b/src/components/ui/combobox/popup.tsx new file mode 100644 index 0000000..544d729 --- /dev/null +++ b/src/components/ui/combobox/popup.tsx @@ -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 & { + 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( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPopup.displayName = "ComboboxPopup" diff --git a/src/components/ui/combobox/portal.tsx b/src/components/ui/combobox/portal.tsx new file mode 100644 index 0000000..3c2be7c --- /dev/null +++ b/src/components/ui/combobox/portal.tsx @@ -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 & { + className?: string +} + +const BaseComboboxPortal = BaseCombobox.Portal as React.ElementType + +export const ComboboxPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPortal.displayName = "ComboboxPortal" diff --git a/src/components/ui/combobox/positioner.tsx b/src/components/ui/combobox/positioner.tsx new file mode 100644 index 0000000..e873002 --- /dev/null +++ b/src/components/ui/combobox/positioner.tsx @@ -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 & { + className?: string +} + +const BaseComboboxPositioner = BaseCombobox.Positioner as React.ElementType + +export const ComboboxPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxPositioner.displayName = "ComboboxPositioner" diff --git a/src/components/ui/combobox/root.tsx b/src/components/ui/combobox/root.tsx new file mode 100644 index 0000000..ed2bde2 --- /dev/null +++ b/src/components/ui/combobox/root.tsx @@ -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 & { + className?: string +} + +const BaseComboboxRoot = BaseCombobox.Root as React.ElementType + +export const ComboboxRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxRoot.displayName = "ComboboxRoot" diff --git a/src/components/ui/combobox/row.tsx b/src/components/ui/combobox/row.tsx new file mode 100644 index 0000000..dfcce0b --- /dev/null +++ b/src/components/ui/combobox/row.tsx @@ -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 & { + className?: string +} + +const BaseComboboxRow = BaseCombobox.Row as React.ElementType + +export const ComboboxRow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxRow.displayName = "ComboboxRow" diff --git a/src/components/ui/combobox/trigger.tsx b/src/components/ui/combobox/trigger.tsx new file mode 100644 index 0000000..3a68cee --- /dev/null +++ b/src/components/ui/combobox/trigger.tsx @@ -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 & { + className?: string +} + +const BaseComboboxTrigger = BaseCombobox.Trigger as React.ElementType + +export const ComboboxTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxTrigger.displayName = "ComboboxTrigger" diff --git a/src/components/ui/combobox/value.tsx b/src/components/ui/combobox/value.tsx new file mode 100644 index 0000000..d8366e2 --- /dev/null +++ b/src/components/ui/combobox/value.tsx @@ -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 & { + className?: string +} + +const BaseComboboxValue = BaseCombobox.Value as React.ElementType + +export const ComboboxValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ComboboxValue.displayName = "ComboboxValue" diff --git a/src/components/ui/context-menu/arrow.tsx b/src/components/ui/context-menu/arrow.tsx new file mode 100644 index 0000000..90ae4c6 --- /dev/null +++ b/src/components/ui/context-menu/arrow.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuArrow = BaseContextMenu.Arrow as React.ElementType + +export const ContextMenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuArrow.displayName = "ContextMenuArrow" diff --git a/src/components/ui/context-menu/backdrop.tsx b/src/components/ui/context-menu/backdrop.tsx new file mode 100644 index 0000000..1a0e138 --- /dev/null +++ b/src/components/ui/context-menu/backdrop.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuBackdrop = BaseContextMenu.Backdrop as React.ElementType + +export const ContextMenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuBackdrop.displayName = "ContextMenuBackdrop" diff --git a/src/components/ui/context-menu/checkbox-item-indicator.tsx b/src/components/ui/context-menu/checkbox-item-indicator.tsx new file mode 100644 index 0000000..dcf8f20 --- /dev/null +++ b/src/components/ui/context-menu/checkbox-item-indicator.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuCheckboxItemIndicator = BaseContextMenu.CheckboxItemIndicator as React.ElementType + +export const ContextMenuCheckboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuCheckboxItemIndicator.displayName = "ContextMenuCheckboxItemIndicator" diff --git a/src/components/ui/context-menu/checkbox-item.tsx b/src/components/ui/context-menu/checkbox-item.tsx new file mode 100644 index 0000000..7e37aa5 --- /dev/null +++ b/src/components/ui/context-menu/checkbox-item.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuCheckboxItem = BaseContextMenu.CheckboxItem as React.ElementType + +export const ContextMenuCheckboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuCheckboxItem.displayName = "ContextMenuCheckboxItem" diff --git a/src/components/ui/context-menu/group-label.tsx b/src/components/ui/context-menu/group-label.tsx new file mode 100644 index 0000000..46ef892 --- /dev/null +++ b/src/components/ui/context-menu/group-label.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuGroupLabel = BaseContextMenu.GroupLabel as React.ElementType + +export const ContextMenuGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuGroupLabel.displayName = "ContextMenuGroupLabel" diff --git a/src/components/ui/context-menu/group.tsx b/src/components/ui/context-menu/group.tsx new file mode 100644 index 0000000..06eeabf --- /dev/null +++ b/src/components/ui/context-menu/group.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuGroup = BaseContextMenu.Group as React.ElementType + +export const ContextMenuGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuGroup.displayName = "ContextMenuGroup" diff --git a/src/components/ui/context-menu/index.ts b/src/components/ui/context-menu/index.ts new file mode 100644 index 0000000..921f562 --- /dev/null +++ b/src/components/ui/context-menu/index.ts @@ -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" diff --git a/src/components/ui/context-menu/item.tsx b/src/components/ui/context-menu/item.tsx new file mode 100644 index 0000000..4ab899b --- /dev/null +++ b/src/components/ui/context-menu/item.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuItem = BaseContextMenu.Item as React.ElementType + +export const ContextMenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuItem.displayName = "ContextMenuItem" diff --git a/src/components/ui/context-menu/link-item.tsx b/src/components/ui/context-menu/link-item.tsx new file mode 100644 index 0000000..efc98a0 --- /dev/null +++ b/src/components/ui/context-menu/link-item.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuLinkItem = BaseContextMenu.LinkItem as React.ElementType + +export const ContextMenuLinkItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuLinkItem.displayName = "ContextMenuLinkItem" diff --git a/src/components/ui/context-menu/popup.tsx b/src/components/ui/context-menu/popup.tsx new file mode 100644 index 0000000..542fb0a --- /dev/null +++ b/src/components/ui/context-menu/popup.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuPopup = BaseContextMenu.Popup as React.ElementType + +export const ContextMenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPopup.displayName = "ContextMenuPopup" diff --git a/src/components/ui/context-menu/portal.tsx b/src/components/ui/context-menu/portal.tsx new file mode 100644 index 0000000..dd8890b --- /dev/null +++ b/src/components/ui/context-menu/portal.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuPortal = BaseContextMenu.Portal as React.ElementType + +export const ContextMenuPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPortal.displayName = "ContextMenuPortal" diff --git a/src/components/ui/context-menu/positioner.tsx b/src/components/ui/context-menu/positioner.tsx new file mode 100644 index 0000000..248eee8 --- /dev/null +++ b/src/components/ui/context-menu/positioner.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuPositioner = BaseContextMenu.Positioner as React.ElementType + +export const ContextMenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuPositioner.displayName = "ContextMenuPositioner" diff --git a/src/components/ui/context-menu/radio-group.tsx b/src/components/ui/context-menu/radio-group.tsx new file mode 100644 index 0000000..0506bda --- /dev/null +++ b/src/components/ui/context-menu/radio-group.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuRadioGroup = BaseContextMenu.RadioGroup as React.ElementType + +export const ContextMenuRadioGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioGroup.displayName = "ContextMenuRadioGroup" diff --git a/src/components/ui/context-menu/radio-item-indicator.tsx b/src/components/ui/context-menu/radio-item-indicator.tsx new file mode 100644 index 0000000..5054013 --- /dev/null +++ b/src/components/ui/context-menu/radio-item-indicator.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuRadioItemIndicator = BaseContextMenu.RadioItemIndicator as React.ElementType + +export const ContextMenuRadioItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioItemIndicator.displayName = "ContextMenuRadioItemIndicator" diff --git a/src/components/ui/context-menu/radio-item.tsx b/src/components/ui/context-menu/radio-item.tsx new file mode 100644 index 0000000..bf587ae --- /dev/null +++ b/src/components/ui/context-menu/radio-item.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuRadioItem = BaseContextMenu.RadioItem as React.ElementType + +export const ContextMenuRadioItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRadioItem.displayName = "ContextMenuRadioItem" diff --git a/src/components/ui/context-menu/root.tsx b/src/components/ui/context-menu/root.tsx new file mode 100644 index 0000000..9d9b584 --- /dev/null +++ b/src/components/ui/context-menu/root.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuRoot = BaseContextMenu.Root as React.ElementType + +export const ContextMenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuRoot.displayName = "ContextMenuRoot" diff --git a/src/components/ui/context-menu/submenu-root.tsx b/src/components/ui/context-menu/submenu-root.tsx new file mode 100644 index 0000000..1ac3bfc --- /dev/null +++ b/src/components/ui/context-menu/submenu-root.tsx @@ -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 & { + className?: string +} + +const BaseContextMenuSubmenuRoot = BaseContextMenu.SubmenuRoot as React.ElementType + +export const ContextMenuSubmenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuSubmenuRoot.displayName = "ContextMenuSubmenuRoot" diff --git a/src/components/ui/context-menu/submenu-trigger.tsx b/src/components/ui/context-menu/submenu-trigger.tsx new file mode 100644 index 0000000..13f7dc4 --- /dev/null +++ b/src/components/ui/context-menu/submenu-trigger.tsx @@ -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 ContextMenuSubmenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuSubmenuTrigger = BaseContextMenu.SubmenuTrigger as React.ElementType + +export const ContextMenuSubmenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuSubmenuTrigger.displayName = "ContextMenuSubmenuTrigger" diff --git a/src/components/ui/context-menu/trigger.tsx b/src/components/ui/context-menu/trigger.tsx new file mode 100644 index 0000000..f3b5af9 --- /dev/null +++ b/src/components/ui/context-menu/trigger.tsx @@ -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 ContextMenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseContextMenuTrigger = BaseContextMenu.Trigger as React.ElementType + +export const ContextMenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ContextMenuTrigger.displayName = "ContextMenuTrigger" diff --git a/src/components/ui/dialog/backdrop.tsx b/src/components/ui/dialog/backdrop.tsx new file mode 100644 index 0000000..a7eddaa --- /dev/null +++ b/src/components/ui/dialog/backdrop.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogBackdrop = BaseDialog.Backdrop as React.ElementType +const defaultDialogBackdropClassName = + "fixed inset-0 min-h-dvh bg-black opacity-20 transition-opacity duration-[350ms] 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" + +export const DialogBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogBackdrop.displayName = "DialogBackdrop" diff --git a/src/components/ui/dialog/close.tsx b/src/components/ui/dialog/close.tsx new file mode 100644 index 0000000..d39f221 --- /dev/null +++ b/src/components/ui/dialog/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogClose = BaseDialog.Close as React.ElementType + +export const DialogClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogClose.displayName = "DialogClose" diff --git a/src/components/ui/dialog/content.tsx b/src/components/ui/dialog/content.tsx new file mode 100644 index 0000000..cb144d2 --- /dev/null +++ b/src/components/ui/dialog/content.tsx @@ -0,0 +1,20 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { DialogBackdrop } from "./backdrop" +import { DialogPortal } from "./portal" +import { DialogPopup, type DialogPopupProps } from "./popup" + +export type DialogContentProps = DialogPopupProps + +export const DialogContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + ), +) + +DialogContent.displayName = "DialogContent" diff --git a/src/components/ui/dialog/description.tsx b/src/components/ui/dialog/description.tsx new file mode 100644 index 0000000..505c77a --- /dev/null +++ b/src/components/ui/dialog/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogDescription = BaseDialog.Description as React.ElementType + +export const DialogDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogDescription.displayName = "DialogDescription" diff --git a/src/components/ui/dialog/index.ts b/src/components/ui/dialog/index.ts new file mode 100644 index 0000000..f93c2fe --- /dev/null +++ b/src/components/ui/dialog/index.ts @@ -0,0 +1,52 @@ +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { DialogBackdrop } from "./backdrop" +import { DialogClose } from "./close" +import { DialogDescription } from "./description" +import { DialogPopup } from "./popup" +import { DialogPortal } from "./portal" +import { DialogRoot } from "./root" +import { DialogViewport } from "./viewport" +import { DialogTitle } from "./title" +import { DialogTrigger } from "./trigger" +import { DialogContent } from "./content" + +const DialogPrimitive = { + Backdrop: DialogBackdrop, + Close: DialogClose, + Description: DialogDescription, + Popup: DialogPopup, + Portal: DialogPortal, + Root: DialogRoot, + Viewport: DialogViewport, + Title: DialogTitle, + Trigger: DialogTrigger, + createHandle: BaseDialog.createHandle, +} + +export default DialogPrimitive + +export { + DialogRoot as Dialog, + DialogBackdrop, + DialogClose, + DialogDescription, + DialogPopup, + DialogPortal, + DialogRoot, + DialogViewport, + DialogTitle, + DialogTrigger, + DialogContent, + BaseDialog, +} + +export type { DialogBackdropProps } from "./backdrop" +export type { DialogCloseProps } from "./close" +export type { DialogDescriptionProps } from "./description" +export type { DialogPopupProps } from "./popup" +export type { DialogPortalProps } from "./portal" +export type { DialogRootProps } from "./root" +export type { DialogViewportProps } from "./viewport" +export type { DialogTitleProps } from "./title" +export type { DialogTriggerProps } from "./trigger" +export type { DialogContentProps } from "./content" diff --git a/src/components/ui/dialog/popup.tsx b/src/components/ui/dialog/popup.tsx new file mode 100644 index 0000000..d46005a --- /dev/null +++ b/src/components/ui/dialog/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogPopup = BaseDialog.Popup as React.ElementType +const defaultDialogPopupClassName = + "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-[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" + +export const DialogPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogPopup.displayName = "DialogPopup" diff --git a/src/components/ui/dialog/portal.tsx b/src/components/ui/dialog/portal.tsx new file mode 100644 index 0000000..685e6c3 --- /dev/null +++ b/src/components/ui/dialog/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type DialogPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogPortal = BaseDialog.Portal as React.ElementType + +export const DialogPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +DialogPortal.displayName = "DialogPortal" diff --git a/src/components/ui/dialog/root.tsx b/src/components/ui/dialog/root.tsx new file mode 100644 index 0000000..d32d6b6 --- /dev/null +++ b/src/components/ui/dialog/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogRoot = BaseDialog.Root as React.ElementType + +export const DialogRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogRoot.displayName = "DialogRoot" diff --git a/src/components/ui/dialog/title.tsx b/src/components/ui/dialog/title.tsx new file mode 100644 index 0000000..1b2a70a --- /dev/null +++ b/src/components/ui/dialog/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogTitle = BaseDialog.Title as React.ElementType + +export const DialogTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogTitle.displayName = "DialogTitle" diff --git a/src/components/ui/dialog/trigger.tsx b/src/components/ui/dialog/trigger.tsx new file mode 100644 index 0000000..d9c092e --- /dev/null +++ b/src/components/ui/dialog/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogTrigger = BaseDialog.Trigger as React.ElementType + +export const DialogTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogTrigger.displayName = "DialogTrigger" diff --git a/src/components/ui/dialog/viewport.tsx b/src/components/ui/dialog/viewport.tsx new file mode 100644 index 0000000..8cda9cb --- /dev/null +++ b/src/components/ui/dialog/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Dialog as BaseDialog } from "@base-ui/react/dialog" +import { cn } from "@/lib/utils" + +export type DialogViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDialogViewport = BaseDialog.Viewport as React.ElementType +const defaultDialogViewportClassName = + "fixed inset-0 flex items-center justify-center overflow-hidden py-6 [@media(min-height:600px)]:pb-12 [@media(min-height:600px)]:pt-8" + +export const DialogViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DialogViewport.displayName = "DialogViewport" diff --git a/src/components/ui/drawer/backdrop.tsx b/src/components/ui/drawer/backdrop.tsx new file mode 100644 index 0000000..6380865 --- /dev/null +++ b/src/components/ui/drawer/backdrop.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerBackdrop = BaseDrawer.Backdrop as React.ElementType +const defaultDrawerBackdropClassName = + "[--backdrop-opacity:0.2] [--bleed:3rem] dark:[--backdrop-opacity:0.7] fixed inset-0 min-h-dvh bg-black opacity-[calc(var(--backdrop-opacity)*(1-var(--drawer-swipe-progress)))] transition-opacity duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:duration-0 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0 data-[ending-style]:duration-[calc(var(--drawer-swipe-strength)*400ms)] supports-[-webkit-touch-callout:none]:absolute" + +export const DrawerBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerBackdrop.displayName = "DrawerBackdrop" diff --git a/src/components/ui/drawer/close.tsx b/src/components/ui/drawer/close.tsx new file mode 100644 index 0000000..83563b6 --- /dev/null +++ b/src/components/ui/drawer/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerClose = BaseDrawer.Close as React.ElementType + +export const DrawerClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerClose.displayName = "DrawerClose" diff --git a/src/components/ui/drawer/content.tsx b/src/components/ui/drawer/content.tsx new file mode 100644 index 0000000..8754ad2 --- /dev/null +++ b/src/components/ui/drawer/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerContent = BaseDrawer.Content as React.ElementType + +export const DrawerContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerContent.displayName = "DrawerContent" diff --git a/src/components/ui/drawer/description.tsx b/src/components/ui/drawer/description.tsx new file mode 100644 index 0000000..df642ed --- /dev/null +++ b/src/components/ui/drawer/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerDescription = BaseDrawer.Description as React.ElementType + +export const DrawerDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerDescription.displayName = "DrawerDescription" diff --git a/src/components/ui/drawer/indent-background.tsx b/src/components/ui/drawer/indent-background.tsx new file mode 100644 index 0000000..2ca9ee5 --- /dev/null +++ b/src/components/ui/drawer/indent-background.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerIndentBackgroundProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerIndentBackground = BaseDrawer.IndentBackground as React.ElementType + +export const DrawerIndentBackground = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerIndentBackground.displayName = "DrawerIndentBackground" diff --git a/src/components/ui/drawer/indent.tsx b/src/components/ui/drawer/indent.tsx new file mode 100644 index 0000000..56f3e7f --- /dev/null +++ b/src/components/ui/drawer/indent.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerIndentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerIndent = BaseDrawer.Indent as React.ElementType + +export const DrawerIndent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerIndent.displayName = "DrawerIndent" diff --git a/src/components/ui/drawer/index.ts b/src/components/ui/drawer/index.ts new file mode 100644 index 0000000..9934c4e --- /dev/null +++ b/src/components/ui/drawer/index.ts @@ -0,0 +1,70 @@ +import { DrawerBackdrop } from "./backdrop" +import { DrawerClose } from "./close" +import { DrawerContent } from "./content" +import { DrawerDescription } from "./description" +import { DrawerIndent } from "./indent" +import { DrawerIndentBackground } from "./indent-background" +import { DrawerPopup } from "./popup" +import { DrawerPortal } from "./portal" +import { DrawerProvider } from "./provider" +import { DrawerRoot } from "./root" +import { DrawerSwipeArea } from "./swipe-area" +import { DrawerTitle } from "./title" +import { DrawerTrigger } from "./trigger" +import { DrawerViewport } from "./viewport" +import { DrawerVirtualKeyboardProvider } from "./virtual-keyboard-provider" + +const DrawerPrimitive = { + Backdrop: DrawerBackdrop, + Close: DrawerClose, + Content: DrawerContent, + Description: DrawerDescription, + Indent: DrawerIndent, + IndentBackground: DrawerIndentBackground, + Popup: DrawerPopup, + Portal: DrawerPortal, + Provider: DrawerProvider, + Root: DrawerRoot, + SwipeArea: DrawerSwipeArea, + Title: DrawerTitle, + Trigger: DrawerTrigger, + Viewport: DrawerViewport, + VirtualKeyboardProvider: DrawerVirtualKeyboardProvider, +} + +export default DrawerPrimitive + +export { + DrawerRoot as Drawer, + DrawerBackdrop, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerIndent, + DrawerIndentBackground, + DrawerPopup, + DrawerPortal, + DrawerProvider, + DrawerRoot, + DrawerSwipeArea, + DrawerTitle, + DrawerTrigger, + DrawerViewport, + DrawerVirtualKeyboardProvider, +} + +export type { DrawerBackdropProps } from "./backdrop" +export type { DrawerCloseProps } from "./close" +export type { DrawerContentProps } from "./content" +export type { DrawerDescriptionProps } from "./description" +export type { DrawerIndentProps } from "./indent" +export type { DrawerIndentBackgroundProps } from "./indent-background" +export type { DrawerPopupProps } from "./popup" +export type { DrawerPortalProps } from "./portal" +export type { DrawerProviderProps } from "./provider" +export type { DrawerRootProps } from "./root" +export type { DrawerSwipeAreaProps } from "./swipe-area" +export type { DrawerTitleProps } from "./title" +export type { DrawerTriggerProps } from "./trigger" +export type { DrawerViewportProps } from "./viewport" +export type { DrawerVirtualKeyboardProviderProps } from "./virtual-keyboard-provider" diff --git a/src/components/ui/drawer/popup.tsx b/src/components/ui/drawer/popup.tsx new file mode 100644 index 0000000..b833a79 --- /dev/null +++ b/src/components/ui/drawer/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerPopup = BaseDrawer.Popup as React.ElementType +const defaultDrawerPopupClassName = + "[--bleed:3rem] supports-[-webkit-touch-callout:none]:[--bleed:0px] h-full w-[calc(20rem+3rem)] max-w-[calc(100vw-3rem+3rem)] -mr-[3rem] border-l border-neutral-950 bg-white p-6 pr-[calc(1.5rem+3rem)] text-neutral-950 outline-none shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] overflow-y-auto overscroll-contain touch-auto [transform:translateX(var(--drawer-swipe-movement-x))] transition-transform duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:select-none data-[ending-style]:[transform:translateX(calc(100%-var(--bleed)+var(--viewport-padding)+2px))] data-[starting-style]:[transform:translateX(calc(100%-var(--bleed)+var(--viewport-padding)+2px))] data-[ending-style]:duration-[calc(var(--drawer-swipe-strength)*400ms)] supports-[-webkit-touch-callout:none]:mr-0 supports-[-webkit-touch-callout:none]:w-[20rem] supports-[-webkit-touch-callout:none]:max-w-[calc(100vw-3rem)] supports-[-webkit-touch-callout:none]:border supports-[-webkit-touch-callout:none]:pr-6 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const DrawerPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerPopup.displayName = "DrawerPopup" diff --git a/src/components/ui/drawer/portal.tsx b/src/components/ui/drawer/portal.tsx new file mode 100644 index 0000000..c028900 --- /dev/null +++ b/src/components/ui/drawer/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type DrawerPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerPortal = BaseDrawer.Portal as React.ElementType + +export const DrawerPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +DrawerPortal.displayName = "DrawerPortal" diff --git a/src/components/ui/drawer/provider.tsx b/src/components/ui/drawer/provider.tsx new file mode 100644 index 0000000..764b496 --- /dev/null +++ b/src/components/ui/drawer/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerProvider = BaseDrawer.Provider as React.ElementType + +export const DrawerProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerProvider.displayName = "DrawerProvider" diff --git a/src/components/ui/drawer/root.tsx b/src/components/ui/drawer/root.tsx new file mode 100644 index 0000000..c6ee019 --- /dev/null +++ b/src/components/ui/drawer/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerRoot = BaseDrawer.Root as React.ElementType + +export const DrawerRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerRoot.displayName = "DrawerRoot" diff --git a/src/components/ui/drawer/swipe-area.tsx b/src/components/ui/drawer/swipe-area.tsx new file mode 100644 index 0000000..2f49967 --- /dev/null +++ b/src/components/ui/drawer/swipe-area.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerSwipeAreaProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerSwipeArea = BaseDrawer.SwipeArea as React.ElementType + +export const DrawerSwipeArea = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerSwipeArea.displayName = "DrawerSwipeArea" diff --git a/src/components/ui/drawer/title.tsx b/src/components/ui/drawer/title.tsx new file mode 100644 index 0000000..ffdd9af --- /dev/null +++ b/src/components/ui/drawer/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerTitle = BaseDrawer.Title as React.ElementType + +export const DrawerTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerTitle.displayName = "DrawerTitle" diff --git a/src/components/ui/drawer/trigger.tsx b/src/components/ui/drawer/trigger.tsx new file mode 100644 index 0000000..70ae68f --- /dev/null +++ b/src/components/ui/drawer/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerTrigger = BaseDrawer.Trigger as React.ElementType + +export const DrawerTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerTrigger.displayName = "DrawerTrigger" diff --git a/src/components/ui/drawer/viewport.tsx b/src/components/ui/drawer/viewport.tsx new file mode 100644 index 0000000..2519e08 --- /dev/null +++ b/src/components/ui/drawer/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerViewport = BaseDrawer.Viewport as React.ElementType +const defaultDrawerViewportClassName = + "[--viewport-padding:0px] supports-[-webkit-touch-callout:none]:[--viewport-padding:0.625rem] fixed inset-0 flex items-stretch justify-end p-(--viewport-padding)" + +export const DrawerViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerViewport.displayName = "DrawerViewport" diff --git a/src/components/ui/drawer/virtual-keyboard-provider.tsx b/src/components/ui/drawer/virtual-keyboard-provider.tsx new file mode 100644 index 0000000..fa2dffc --- /dev/null +++ b/src/components/ui/drawer/virtual-keyboard-provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Drawer as BaseDrawer } from "@base-ui/react/drawer" +import { cn } from "@/lib/utils" + +export type DrawerVirtualKeyboardProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseDrawerVirtualKeyboardProvider = BaseDrawer.VirtualKeyboardProvider as React.ElementType + +export const DrawerVirtualKeyboardProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +DrawerVirtualKeyboardProvider.displayName = "DrawerVirtualKeyboardProvider" diff --git a/src/components/ui/field/control.tsx b/src/components/ui/field/control.tsx new file mode 100644 index 0000000..ed6a284 --- /dev/null +++ b/src/components/ui/field/control.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldControlProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldControl = BaseField.Control as React.ElementType + +export const FieldControl = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldControl.displayName = "FieldControl" diff --git a/src/components/ui/field/description.tsx b/src/components/ui/field/description.tsx new file mode 100644 index 0000000..0f626ad --- /dev/null +++ b/src/components/ui/field/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldDescription = BaseField.Description as React.ElementType + +export const FieldDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldDescription.displayName = "FieldDescription" diff --git a/src/components/ui/field/error.tsx b/src/components/ui/field/error.tsx new file mode 100644 index 0000000..7aefc48 --- /dev/null +++ b/src/components/ui/field/error.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldErrorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldError = BaseField.Error as React.ElementType + +export const FieldError = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldError.displayName = "FieldError" diff --git a/src/components/ui/field/index.ts b/src/components/ui/field/index.ts new file mode 100644 index 0000000..a116b3c --- /dev/null +++ b/src/components/ui/field/index.ts @@ -0,0 +1,38 @@ +import { FieldRoot } from "./root" +import { FieldLabel } from "./label" +import { FieldError } from "./error" +import { FieldDescription } from "./description" +import { FieldControl } from "./control" +import { FieldValidity } from "./validity" +import { FieldItem } from "./item" + +const FieldPrimitive = { + Root: FieldRoot, + Label: FieldLabel, + Error: FieldError, + Description: FieldDescription, + Control: FieldControl, + Validity: FieldValidity, + Item: FieldItem, +} + +export default FieldPrimitive + +export { + FieldRoot as Field, + FieldRoot, + FieldLabel, + FieldError, + FieldDescription, + FieldControl, + FieldValidity, + FieldItem, +} + +export type { FieldRootProps } from "./root" +export type { FieldLabelProps } from "./label" +export type { FieldErrorProps } from "./error" +export type { FieldDescriptionProps } from "./description" +export type { FieldControlProps } from "./control" +export type { FieldValidityProps } from "./validity" +export type { FieldItemProps } from "./item" diff --git a/src/components/ui/field/item.tsx b/src/components/ui/field/item.tsx new file mode 100644 index 0000000..1cef4b5 --- /dev/null +++ b/src/components/ui/field/item.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldItem = BaseField.Item as React.ElementType + +export const FieldItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldItem.displayName = "FieldItem" diff --git a/src/components/ui/field/label.tsx b/src/components/ui/field/label.tsx new file mode 100644 index 0000000..d9897bd --- /dev/null +++ b/src/components/ui/field/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldLabel = BaseField.Label as React.ElementType + +export const FieldLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldLabel.displayName = "FieldLabel" diff --git a/src/components/ui/field/root.tsx b/src/components/ui/field/root.tsx new file mode 100644 index 0000000..a8210f8 --- /dev/null +++ b/src/components/ui/field/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldRoot = BaseField.Root as React.ElementType + +export const FieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldRoot.displayName = "FieldRoot" diff --git a/src/components/ui/field/validity.tsx b/src/components/ui/field/validity.tsx new file mode 100644 index 0000000..8f0b4ab --- /dev/null +++ b/src/components/ui/field/validity.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Field as BaseField } from "@base-ui/react/field" +import { cn } from "@/lib/utils" + +export type FieldValidityProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldValidity = BaseField.Validity as React.ElementType + +export const FieldValidity = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldValidity.displayName = "FieldValidity" diff --git a/src/components/ui/fieldset/index.ts b/src/components/ui/fieldset/index.ts new file mode 100644 index 0000000..2a1ede7 --- /dev/null +++ b/src/components/ui/fieldset/index.ts @@ -0,0 +1,18 @@ +import { FieldsetRoot } from "./root" +import { FieldsetLegend } from "./legend" + +const FieldsetPrimitive = { + Root: FieldsetRoot, + Legend: FieldsetLegend, +} + +export default FieldsetPrimitive + +export { + FieldsetRoot as Fieldset, + FieldsetRoot, + FieldsetLegend, +} + +export type { FieldsetRootProps } from "./root" +export type { FieldsetLegendProps } from "./legend" diff --git a/src/components/ui/fieldset/legend.tsx b/src/components/ui/fieldset/legend.tsx new file mode 100644 index 0000000..5b11855 --- /dev/null +++ b/src/components/ui/fieldset/legend.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Fieldset as BaseFieldset } from "@base-ui/react/fieldset" +import { cn } from "@/lib/utils" + +export type FieldsetLegendProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldsetLegend = BaseFieldset.Legend as React.ElementType + +export const FieldsetLegend = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldsetLegend.displayName = "FieldsetLegend" diff --git a/src/components/ui/fieldset/root.tsx b/src/components/ui/fieldset/root.tsx new file mode 100644 index 0000000..8011aa0 --- /dev/null +++ b/src/components/ui/fieldset/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Fieldset as BaseFieldset } from "@base-ui/react/fieldset" +import { cn } from "@/lib/utils" + +export type FieldsetRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseFieldsetRoot = BaseFieldset.Root as React.ElementType + +export const FieldsetRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +FieldsetRoot.displayName = "FieldsetRoot" diff --git a/src/components/ui/form/index.ts b/src/components/ui/form/index.ts new file mode 100644 index 0000000..fa5ece3 --- /dev/null +++ b/src/components/ui/form/index.ts @@ -0,0 +1,4 @@ +import { Form } from "./root" + +export { Form, type FormProps } from "./root" +export default Form diff --git a/src/components/ui/form/root.tsx b/src/components/ui/form/root.tsx new file mode 100644 index 0000000..c18f298 --- /dev/null +++ b/src/components/ui/form/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Form as BaseForm } from "@base-ui/react/form" +import { cn } from "@/lib/utils" + +export type FormProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseFormElement = BaseForm as React.ElementType + +export const Form = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Form.displayName = "Form" diff --git a/src/components/ui/input/index.ts b/src/components/ui/input/index.ts new file mode 100644 index 0000000..1161ce5 --- /dev/null +++ b/src/components/ui/input/index.ts @@ -0,0 +1,4 @@ +import { Input } from "./root" + +export { Input, type InputProps } from "./root" +export default Input diff --git a/src/components/ui/input/root.tsx b/src/components/ui/input/root.tsx new file mode 100644 index 0000000..ab996d0 --- /dev/null +++ b/src/components/ui/input/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Input as BaseInput } from "@base-ui/react/input" +import { cn } from "@/lib/utils" + +export type InputProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseInputElement = BaseInput as React.ElementType + +export const Input = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Input.displayName = "Input" diff --git a/src/components/ui/menu/arrow.tsx b/src/components/ui/menu/arrow.tsx new file mode 100644 index 0000000..356a66b --- /dev/null +++ b/src/components/ui/menu/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuArrow = BaseMenu.Arrow as React.ElementType + +export const MenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuArrow.displayName = "MenuArrow" diff --git a/src/components/ui/menu/backdrop.tsx b/src/components/ui/menu/backdrop.tsx new file mode 100644 index 0000000..12ced99 --- /dev/null +++ b/src/components/ui/menu/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuBackdrop = BaseMenu.Backdrop as React.ElementType + +export const MenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuBackdrop.displayName = "MenuBackdrop" diff --git a/src/components/ui/menu/checkbox-item-indicator.tsx b/src/components/ui/menu/checkbox-item-indicator.tsx new file mode 100644 index 0000000..5cb1b23 --- /dev/null +++ b/src/components/ui/menu/checkbox-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuCheckboxItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuCheckboxItemIndicator = BaseMenu.CheckboxItemIndicator as React.ElementType + +export const MenuCheckboxItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuCheckboxItemIndicator.displayName = "MenuCheckboxItemIndicator" diff --git a/src/components/ui/menu/checkbox-item.tsx b/src/components/ui/menu/checkbox-item.tsx new file mode 100644 index 0000000..bc0cdc9 --- /dev/null +++ b/src/components/ui/menu/checkbox-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuCheckboxItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuCheckboxItem = BaseMenu.CheckboxItem as React.ElementType + +export const MenuCheckboxItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuCheckboxItem.displayName = "MenuCheckboxItem" diff --git a/src/components/ui/menu/group-label.tsx b/src/components/ui/menu/group-label.tsx new file mode 100644 index 0000000..45ea521 --- /dev/null +++ b/src/components/ui/menu/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuGroupLabel = BaseMenu.GroupLabel as React.ElementType + +export const MenuGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuGroupLabel.displayName = "MenuGroupLabel" diff --git a/src/components/ui/menu/group.tsx b/src/components/ui/menu/group.tsx new file mode 100644 index 0000000..4516fb2 --- /dev/null +++ b/src/components/ui/menu/group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuGroup = BaseMenu.Group as React.ElementType + +export const MenuGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuGroup.displayName = "MenuGroup" diff --git a/src/components/ui/menu/index.ts b/src/components/ui/menu/index.ts new file mode 100644 index 0000000..fa5ecde --- /dev/null +++ b/src/components/ui/menu/index.ts @@ -0,0 +1,90 @@ +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { MenuArrow } from "./arrow" +import { MenuBackdrop } from "./backdrop" +import { MenuCheckboxItem } from "./checkbox-item" +import { MenuCheckboxItemIndicator } from "./checkbox-item-indicator" +import { MenuGroup } from "./group" +import { MenuGroupLabel } from "./group-label" +import { MenuItem } from "./item" +import { MenuLinkItem } from "./link-item" +import { MenuPopup } from "./popup" +import { MenuPortal } from "./portal" +import { MenuPositioner } from "./positioner" +import { MenuRadioGroup } from "./radio-group" +import { MenuRadioItem } from "./radio-item" +import { MenuRadioItemIndicator } from "./radio-item-indicator" +import { MenuRoot } from "./root" +import { MenuSubmenuRoot } from "./submenu-root" +import { MenuTrigger } from "./trigger" +import { MenuViewport } from "./viewport" +import { MenuSubmenuTrigger } from "./submenu-trigger" + +const MenuPrimitive = { + Arrow: MenuArrow, + Backdrop: MenuBackdrop, + CheckboxItem: MenuCheckboxItem, + CheckboxItemIndicator: MenuCheckboxItemIndicator, + Group: MenuGroup, + GroupLabel: MenuGroupLabel, + Item: MenuItem, + LinkItem: MenuLinkItem, + Popup: MenuPopup, + Portal: MenuPortal, + Positioner: MenuPositioner, + RadioGroup: MenuRadioGroup, + RadioItem: MenuRadioItem, + RadioItemIndicator: MenuRadioItemIndicator, + Root: MenuRoot, + SubmenuRoot: MenuSubmenuRoot, + Trigger: MenuTrigger, + Viewport: MenuViewport, + SubmenuTrigger: MenuSubmenuTrigger, + Separator: BaseMenu.Separator, + createHandle: BaseMenu.createHandle, +} + +export default MenuPrimitive + +export { + MenuRoot as Menu, + MenuArrow, + MenuBackdrop, + MenuCheckboxItem, + MenuCheckboxItemIndicator, + MenuGroup, + MenuGroupLabel, + MenuItem, + MenuLinkItem, + MenuPopup, + MenuPortal, + MenuPositioner, + MenuRadioGroup, + MenuRadioItem, + MenuRadioItemIndicator, + MenuRoot, + MenuSubmenuRoot, + MenuTrigger, + MenuViewport, + MenuSubmenuTrigger, + BaseMenu, +} + +export type { MenuArrowProps } from "./arrow" +export type { MenuBackdropProps } from "./backdrop" +export type { MenuCheckboxItemProps } from "./checkbox-item" +export type { MenuCheckboxItemIndicatorProps } from "./checkbox-item-indicator" +export type { MenuGroupProps } from "./group" +export type { MenuGroupLabelProps } from "./group-label" +export type { MenuItemProps } from "./item" +export type { MenuLinkItemProps } from "./link-item" +export type { MenuPopupProps } from "./popup" +export type { MenuPortalProps } from "./portal" +export type { MenuPositionerProps } from "./positioner" +export type { MenuRadioGroupProps } from "./radio-group" +export type { MenuRadioItemProps } from "./radio-item" +export type { MenuRadioItemIndicatorProps } from "./radio-item-indicator" +export type { MenuRootProps } from "./root" +export type { MenuSubmenuRootProps } from "./submenu-root" +export type { MenuTriggerProps } from "./trigger" +export type { MenuViewportProps } from "./viewport" +export type { MenuSubmenuTriggerProps } from "./submenu-trigger" diff --git a/src/components/ui/menu/item.tsx b/src/components/ui/menu/item.tsx new file mode 100644 index 0000000..9b01969 --- /dev/null +++ b/src/components/ui/menu/item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuItem = BaseMenu.Item as React.ElementType + +export const MenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuItem.displayName = "MenuItem" diff --git a/src/components/ui/menu/link-item.tsx b/src/components/ui/menu/link-item.tsx new file mode 100644 index 0000000..2dc83ed --- /dev/null +++ b/src/components/ui/menu/link-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuLinkItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuLinkItem = BaseMenu.LinkItem as React.ElementType + +export const MenuLinkItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuLinkItem.displayName = "MenuLinkItem" diff --git a/src/components/ui/menu/popup.tsx b/src/components/ui/menu/popup.tsx new file mode 100644 index 0000000..275a288 --- /dev/null +++ b/src/components/ui/menu/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuPopup = BaseMenu.Popup as React.ElementType +const defaultMenuPopupClassName = + "relative 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" + +export const MenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuPopup.displayName = "MenuPopup" diff --git a/src/components/ui/menu/portal.tsx b/src/components/ui/menu/portal.tsx new file mode 100644 index 0000000..2591405 --- /dev/null +++ b/src/components/ui/menu/portal.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type MenuPortalProps = React.ComponentPropsWithoutRef & { + className?: string + container?: HTMLElement | ShadowRoot | React.RefObject | null +} + +const BaseMenuPortal = BaseMenu.Portal as React.ElementType + +export const MenuPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +MenuPortal.displayName = "MenuPortal" diff --git a/src/components/ui/menu/positioner.tsx b/src/components/ui/menu/positioner.tsx new file mode 100644 index 0000000..e9db49f --- /dev/null +++ b/src/components/ui/menu/positioner.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuPositioner = BaseMenu.Positioner as React.ElementType +const defaultMenuPositionerClassName = "outline-none" + +export const MenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuPositioner.displayName = "MenuPositioner" diff --git a/src/components/ui/menu/radio-group.tsx b/src/components/ui/menu/radio-group.tsx new file mode 100644 index 0000000..f21c244 --- /dev/null +++ b/src/components/ui/menu/radio-group.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioGroup = BaseMenu.RadioGroup as React.ElementType + +export const MenuRadioGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioGroup.displayName = "MenuRadioGroup" diff --git a/src/components/ui/menu/radio-item-indicator.tsx b/src/components/ui/menu/radio-item-indicator.tsx new file mode 100644 index 0000000..5b03bee --- /dev/null +++ b/src/components/ui/menu/radio-item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioItemIndicator = BaseMenu.RadioItemIndicator as React.ElementType + +export const MenuRadioItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioItemIndicator.displayName = "MenuRadioItemIndicator" diff --git a/src/components/ui/menu/radio-item.tsx b/src/components/ui/menu/radio-item.tsx new file mode 100644 index 0000000..ac6eda1 --- /dev/null +++ b/src/components/ui/menu/radio-item.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRadioItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRadioItem = BaseMenu.RadioItem as React.ElementType + +export const MenuRadioItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRadioItem.displayName = "MenuRadioItem" diff --git a/src/components/ui/menu/root.tsx b/src/components/ui/menu/root.tsx new file mode 100644 index 0000000..47f6666 --- /dev/null +++ b/src/components/ui/menu/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuRoot = BaseMenu.Root as React.ElementType + +export const MenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuRoot.displayName = "MenuRoot" diff --git a/src/components/ui/menu/submenu-root.tsx b/src/components/ui/menu/submenu-root.tsx new file mode 100644 index 0000000..d3cb2c0 --- /dev/null +++ b/src/components/ui/menu/submenu-root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuSubmenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuSubmenuRoot = BaseMenu.SubmenuRoot as React.ElementType + +export const MenuSubmenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuSubmenuRoot.displayName = "MenuSubmenuRoot" diff --git a/src/components/ui/menu/submenu-trigger.tsx b/src/components/ui/menu/submenu-trigger.tsx new file mode 100644 index 0000000..812e9fc --- /dev/null +++ b/src/components/ui/menu/submenu-trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuSubmenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuSubmenuTrigger = BaseMenu.SubmenuTrigger as React.ElementType + +export const MenuSubmenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuSubmenuTrigger.displayName = "MenuSubmenuTrigger" diff --git a/src/components/ui/menu/trigger.tsx b/src/components/ui/menu/trigger.tsx new file mode 100644 index 0000000..5ad8586 --- /dev/null +++ b/src/components/ui/menu/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuTrigger = BaseMenu.Trigger as React.ElementType + +export const MenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuTrigger.displayName = "MenuTrigger" diff --git a/src/components/ui/menu/viewport.tsx b/src/components/ui/menu/viewport.tsx new file mode 100644 index 0000000..870ffc9 --- /dev/null +++ b/src/components/ui/menu/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Menu as BaseMenu } from "@base-ui/react/menu" +import { cn } from "@/lib/utils" + +export type MenuViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMenuViewport = BaseMenu.Viewport as React.ElementType + +export const MenuViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MenuViewport.displayName = "MenuViewport" diff --git a/src/components/ui/menubar/index.ts b/src/components/ui/menubar/index.ts new file mode 100644 index 0000000..c2efebc --- /dev/null +++ b/src/components/ui/menubar/index.ts @@ -0,0 +1,4 @@ +import { Menubar } from "./root" + +export { Menubar, type MenubarProps } from "./root" +export default Menubar diff --git a/src/components/ui/menubar/root.tsx b/src/components/ui/menubar/root.tsx new file mode 100644 index 0000000..ad5a303 --- /dev/null +++ b/src/components/ui/menubar/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Menubar as BaseMenubar } from "@base-ui/react/menubar" +import { cn } from "@/lib/utils" + +export type MenubarProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseMenubarElement = BaseMenubar as React.ElementType + +export const Menubar = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Menubar.displayName = "Menubar" diff --git a/src/components/ui/meter/index.ts b/src/components/ui/meter/index.ts new file mode 100644 index 0000000..18e398c --- /dev/null +++ b/src/components/ui/meter/index.ts @@ -0,0 +1,30 @@ +import { MeterRoot } from "./root" +import { MeterTrack } from "./track" +import { MeterIndicator } from "./indicator" +import { MeterValue } from "./value" +import { MeterLabel } from "./label" + +const MeterPrimitive = { + Root: MeterRoot, + Track: MeterTrack, + Indicator: MeterIndicator, + Value: MeterValue, + Label: MeterLabel, +} + +export default MeterPrimitive + +export { + MeterRoot as Meter, + MeterRoot, + MeterTrack, + MeterIndicator, + MeterValue, + MeterLabel, +} + +export type { MeterRootProps } from "./root" +export type { MeterTrackProps } from "./track" +export type { MeterIndicatorProps } from "./indicator" +export type { MeterValueProps } from "./value" +export type { MeterLabelProps } from "./label" diff --git a/src/components/ui/meter/indicator.tsx b/src/components/ui/meter/indicator.tsx new file mode 100644 index 0000000..4087380 --- /dev/null +++ b/src/components/ui/meter/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterIndicator = BaseMeter.Indicator as React.ElementType + +export const MeterIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterIndicator.displayName = "MeterIndicator" diff --git a/src/components/ui/meter/label.tsx b/src/components/ui/meter/label.tsx new file mode 100644 index 0000000..fc01c6b --- /dev/null +++ b/src/components/ui/meter/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterLabel = BaseMeter.Label as React.ElementType + +export const MeterLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterLabel.displayName = "MeterLabel" diff --git a/src/components/ui/meter/root.tsx b/src/components/ui/meter/root.tsx new file mode 100644 index 0000000..10e53d3 --- /dev/null +++ b/src/components/ui/meter/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterRoot = BaseMeter.Root as React.ElementType + +export const MeterRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterRoot.displayName = "MeterRoot" diff --git a/src/components/ui/meter/track.tsx b/src/components/ui/meter/track.tsx new file mode 100644 index 0000000..a520288 --- /dev/null +++ b/src/components/ui/meter/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterTrack = BaseMeter.Track as React.ElementType + +export const MeterTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterTrack.displayName = "MeterTrack" diff --git a/src/components/ui/meter/value.tsx b/src/components/ui/meter/value.tsx new file mode 100644 index 0000000..3b2b6b3 --- /dev/null +++ b/src/components/ui/meter/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Meter as BaseMeter } from "@base-ui/react/meter" +import { cn } from "@/lib/utils" + +export type MeterValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseMeterValue = BaseMeter.Value as React.ElementType + +export const MeterValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +MeterValue.displayName = "MeterValue" diff --git a/src/components/ui/navigation-menu/arrow.tsx b/src/components/ui/navigation-menu/arrow.tsx new file mode 100644 index 0000000..37576bd --- /dev/null +++ b/src/components/ui/navigation-menu/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuArrow = BaseNavigationMenu.Arrow as React.ElementType + +export const NavigationMenuArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuArrow.displayName = "NavigationMenuArrow" diff --git a/src/components/ui/navigation-menu/backdrop.tsx b/src/components/ui/navigation-menu/backdrop.tsx new file mode 100644 index 0000000..09c6665 --- /dev/null +++ b/src/components/ui/navigation-menu/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuBackdrop = BaseNavigationMenu.Backdrop as React.ElementType + +export const NavigationMenuBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuBackdrop.displayName = "NavigationMenuBackdrop" diff --git a/src/components/ui/navigation-menu/content.tsx b/src/components/ui/navigation-menu/content.tsx new file mode 100644 index 0000000..3cd30ba --- /dev/null +++ b/src/components/ui/navigation-menu/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuContent = BaseNavigationMenu.Content as React.ElementType + +export const NavigationMenuContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuContent.displayName = "NavigationMenuContent" diff --git a/src/components/ui/navigation-menu/icon.tsx b/src/components/ui/navigation-menu/icon.tsx new file mode 100644 index 0000000..2701a9c --- /dev/null +++ b/src/components/ui/navigation-menu/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuIcon = BaseNavigationMenu.Icon as React.ElementType + +export const NavigationMenuIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuIcon.displayName = "NavigationMenuIcon" diff --git a/src/components/ui/navigation-menu/index.ts b/src/components/ui/navigation-menu/index.ts new file mode 100644 index 0000000..61e6ac6 --- /dev/null +++ b/src/components/ui/navigation-menu/index.ts @@ -0,0 +1,62 @@ +import { NavigationMenuRoot } from "./root" +import { NavigationMenuList } from "./list" +import { NavigationMenuItem } from "./item" +import { NavigationMenuContent } from "./content" +import { NavigationMenuTrigger } from "./trigger" +import { NavigationMenuPortal } from "./portal" +import { NavigationMenuPositioner } from "./positioner" +import { NavigationMenuViewport } from "./viewport" +import { NavigationMenuBackdrop } from "./backdrop" +import { NavigationMenuPopup } from "./popup" +import { NavigationMenuArrow } from "./arrow" +import { NavigationMenuLink } from "./link" +import { NavigationMenuIcon } from "./icon" + +const NavigationMenuPrimitive = { + Root: NavigationMenuRoot, + List: NavigationMenuList, + Item: NavigationMenuItem, + Content: NavigationMenuContent, + Trigger: NavigationMenuTrigger, + Portal: NavigationMenuPortal, + Positioner: NavigationMenuPositioner, + Viewport: NavigationMenuViewport, + Backdrop: NavigationMenuBackdrop, + Popup: NavigationMenuPopup, + Arrow: NavigationMenuArrow, + Link: NavigationMenuLink, + Icon: NavigationMenuIcon, +} + +export default NavigationMenuPrimitive + +export { + NavigationMenuRoot as NavigationMenu, + NavigationMenuRoot, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuPortal, + NavigationMenuPositioner, + NavigationMenuViewport, + NavigationMenuBackdrop, + NavigationMenuPopup, + NavigationMenuArrow, + NavigationMenuLink, + NavigationMenuIcon, +} + +export type { NavigationMenuRootProps } from "./root" +export type { NavigationMenuListProps } from "./list" +export type { NavigationMenuItemProps } from "./item" +export type { NavigationMenuContentProps } from "./content" +export type { NavigationMenuTriggerProps } from "./trigger" +export type { NavigationMenuPortalProps } from "./portal" +export type { NavigationMenuPositionerProps } from "./positioner" +export type { NavigationMenuViewportProps } from "./viewport" +export type { NavigationMenuBackdropProps } from "./backdrop" +export type { NavigationMenuPopupProps } from "./popup" +export type { NavigationMenuArrowProps } from "./arrow" +export type { NavigationMenuLinkProps } from "./link" +export type { NavigationMenuIconProps } from "./icon" diff --git a/src/components/ui/navigation-menu/item.tsx b/src/components/ui/navigation-menu/item.tsx new file mode 100644 index 0000000..51fa2bf --- /dev/null +++ b/src/components/ui/navigation-menu/item.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuItem = BaseNavigationMenu.Item as React.ElementType + +export const NavigationMenuItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuItem.displayName = "NavigationMenuItem" diff --git a/src/components/ui/navigation-menu/link.tsx b/src/components/ui/navigation-menu/link.tsx new file mode 100644 index 0000000..ca4b674 --- /dev/null +++ b/src/components/ui/navigation-menu/link.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuLinkProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuLink = BaseNavigationMenu.Link as React.ElementType + +export const NavigationMenuLink = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuLink.displayName = "NavigationMenuLink" diff --git a/src/components/ui/navigation-menu/list.tsx b/src/components/ui/navigation-menu/list.tsx new file mode 100644 index 0000000..d7c119c --- /dev/null +++ b/src/components/ui/navigation-menu/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuList = BaseNavigationMenu.List as React.ElementType + +export const NavigationMenuList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuList.displayName = "NavigationMenuList" diff --git a/src/components/ui/navigation-menu/popup.tsx b/src/components/ui/navigation-menu/popup.tsx new file mode 100644 index 0000000..77d4a2d --- /dev/null +++ b/src/components/ui/navigation-menu/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPopup = BaseNavigationMenu.Popup as React.ElementType +const defaultNavigationMenuPopupClassName = + "relative h-[var(--popup-height)] w-[var(--popup-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%)] outline-none transition-[opacity,transform,width,height,scale] duration-[var(--duration)] ease-[var(--easing)] data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[ending-style]:ease-[ease] data-[starting-style]:scale-90 data-[starting-style]:opacity-0 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const NavigationMenuPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuPopup.displayName = "NavigationMenuPopup" diff --git a/src/components/ui/navigation-menu/portal.tsx b/src/components/ui/navigation-menu/portal.tsx new file mode 100644 index 0000000..fcdb017 --- /dev/null +++ b/src/components/ui/navigation-menu/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type NavigationMenuPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPortal = BaseNavigationMenu.Portal as React.ElementType + +export const NavigationMenuPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +NavigationMenuPortal.displayName = "NavigationMenuPortal" diff --git a/src/components/ui/navigation-menu/positioner.tsx b/src/components/ui/navigation-menu/positioner.tsx new file mode 100644 index 0000000..1e5a182 --- /dev/null +++ b/src/components/ui/navigation-menu/positioner.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuPositioner = BaseNavigationMenu.Positioner as React.ElementType +const defaultNavigationMenuPositionerClassName = + "h-[var(--positioner-height)] w-[var(--positioner-width)] max-w-[var(--available-width)] transition-[top,left,right,bottom] duration-[var(--duration)] ease-[var(--easing)] before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=left]:before:top-0 data-[side=left]:before:right-[-10px] data-[side=left]:before:bottom-0 data-[side=left]:before:w-2.5 data-[side=right]:before:top-0 data-[side=right]:before:bottom-0 data-[side=right]:before:left-[-10px] data-[side=right]:before:w-2.5 data-[side=top]:before:right-0 data-[side=top]:before:bottom-[-10px] data-[side=top]:before:left-0 data-[side=top]:before:h-2.5" + +export const NavigationMenuPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuPositioner.displayName = "NavigationMenuPositioner" diff --git a/src/components/ui/navigation-menu/root.tsx b/src/components/ui/navigation-menu/root.tsx new file mode 100644 index 0000000..b8abb55 --- /dev/null +++ b/src/components/ui/navigation-menu/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuRoot = BaseNavigationMenu.Root as React.ElementType + +export const NavigationMenuRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuRoot.displayName = "NavigationMenuRoot" diff --git a/src/components/ui/navigation-menu/trigger.tsx b/src/components/ui/navigation-menu/trigger.tsx new file mode 100644 index 0000000..bd2e0c0 --- /dev/null +++ b/src/components/ui/navigation-menu/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuTrigger = BaseNavigationMenu.Trigger as React.ElementType + +export const NavigationMenuTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuTrigger.displayName = "NavigationMenuTrigger" diff --git a/src/components/ui/navigation-menu/viewport.tsx b/src/components/ui/navigation-menu/viewport.tsx new file mode 100644 index 0000000..0afd15f --- /dev/null +++ b/src/components/ui/navigation-menu/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NavigationMenu as BaseNavigationMenu } from "@base-ui/react/navigation-menu" +import { cn } from "@/lib/utils" + +export type NavigationMenuViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNavigationMenuViewport = BaseNavigationMenu.Viewport as React.ElementType + +export const NavigationMenuViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NavigationMenuViewport.displayName = "NavigationMenuViewport" diff --git a/src/components/ui/number-field/decrement.tsx b/src/components/ui/number-field/decrement.tsx new file mode 100644 index 0000000..3a171aa --- /dev/null +++ b/src/components/ui/number-field/decrement.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldDecrementProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldDecrement = BaseNumberField.Decrement as React.ElementType + +export const NumberFieldDecrement = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldDecrement.displayName = "NumberFieldDecrement" diff --git a/src/components/ui/number-field/group.tsx b/src/components/ui/number-field/group.tsx new file mode 100644 index 0000000..5347851 --- /dev/null +++ b/src/components/ui/number-field/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldGroup = BaseNumberField.Group as React.ElementType + +export const NumberFieldGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldGroup.displayName = "NumberFieldGroup" diff --git a/src/components/ui/number-field/increment.tsx b/src/components/ui/number-field/increment.tsx new file mode 100644 index 0000000..eacd6c8 --- /dev/null +++ b/src/components/ui/number-field/increment.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldIncrementProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldIncrement = BaseNumberField.Increment as React.ElementType + +export const NumberFieldIncrement = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldIncrement.displayName = "NumberFieldIncrement" diff --git a/src/components/ui/number-field/index.ts b/src/components/ui/number-field/index.ts new file mode 100644 index 0000000..d517351 --- /dev/null +++ b/src/components/ui/number-field/index.ts @@ -0,0 +1,38 @@ +import { NumberFieldRoot } from "./root" +import { NumberFieldGroup } from "./group" +import { NumberFieldIncrement } from "./increment" +import { NumberFieldDecrement } from "./decrement" +import { NumberFieldInput } from "./input" +import { NumberFieldScrubArea } from "./scrub-area" +import { NumberFieldScrubAreaCursor } from "./scrub-area-cursor" + +const NumberFieldPrimitive = { + Root: NumberFieldRoot, + Group: NumberFieldGroup, + Increment: NumberFieldIncrement, + Decrement: NumberFieldDecrement, + Input: NumberFieldInput, + ScrubArea: NumberFieldScrubArea, + ScrubAreaCursor: NumberFieldScrubAreaCursor, +} + +export default NumberFieldPrimitive + +export { + NumberFieldRoot as NumberField, + NumberFieldRoot, + NumberFieldGroup, + NumberFieldIncrement, + NumberFieldDecrement, + NumberFieldInput, + NumberFieldScrubArea, + NumberFieldScrubAreaCursor, +} + +export type { NumberFieldRootProps } from "./root" +export type { NumberFieldGroupProps } from "./group" +export type { NumberFieldIncrementProps } from "./increment" +export type { NumberFieldDecrementProps } from "./decrement" +export type { NumberFieldInputProps } from "./input" +export type { NumberFieldScrubAreaProps } from "./scrub-area" +export type { NumberFieldScrubAreaCursorProps } from "./scrub-area-cursor" diff --git a/src/components/ui/number-field/input.tsx b/src/components/ui/number-field/input.tsx new file mode 100644 index 0000000..5f8efaa --- /dev/null +++ b/src/components/ui/number-field/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldInput = BaseNumberField.Input as React.ElementType + +export const NumberFieldInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldInput.displayName = "NumberFieldInput" diff --git a/src/components/ui/number-field/root.tsx b/src/components/ui/number-field/root.tsx new file mode 100644 index 0000000..8d9b989 --- /dev/null +++ b/src/components/ui/number-field/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldRoot = BaseNumberField.Root as React.ElementType + +export const NumberFieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldRoot.displayName = "NumberFieldRoot" diff --git a/src/components/ui/number-field/scrub-area-cursor.tsx b/src/components/ui/number-field/scrub-area-cursor.tsx new file mode 100644 index 0000000..235bb98 --- /dev/null +++ b/src/components/ui/number-field/scrub-area-cursor.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldScrubAreaCursorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldScrubAreaCursor = BaseNumberField.ScrubAreaCursor as React.ElementType + +export const NumberFieldScrubAreaCursor = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldScrubAreaCursor.displayName = "NumberFieldScrubAreaCursor" diff --git a/src/components/ui/number-field/scrub-area.tsx b/src/components/ui/number-field/scrub-area.tsx new file mode 100644 index 0000000..945badb --- /dev/null +++ b/src/components/ui/number-field/scrub-area.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { NumberField as BaseNumberField } from "@base-ui/react/number-field" +import { cn } from "@/lib/utils" + +export type NumberFieldScrubAreaProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseNumberFieldScrubArea = BaseNumberField.ScrubArea as React.ElementType + +export const NumberFieldScrubArea = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +NumberFieldScrubArea.displayName = "NumberFieldScrubArea" diff --git a/src/components/ui/otp-field/index.ts b/src/components/ui/otp-field/index.ts new file mode 100644 index 0000000..7e4882b --- /dev/null +++ b/src/components/ui/otp-field/index.ts @@ -0,0 +1,21 @@ +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { OTPFieldRoot } from "./root" +import { OTPFieldInput } from "./input" + +const OTPFieldPrimitive = { + Root: OTPFieldRoot, + Input: OTPFieldInput, + Separator: BaseOTPField.Separator, +} + +export default OTPFieldPrimitive + +export { + OTPFieldRoot as OTPField, + OTPFieldRoot, + OTPFieldInput, + BaseOTPField, +} + +export type { OTPFieldRootProps } from "./root" +export type { OTPFieldInputProps } from "./input" diff --git a/src/components/ui/otp-field/input.tsx b/src/components/ui/otp-field/input.tsx new file mode 100644 index 0000000..504bf2e --- /dev/null +++ b/src/components/ui/otp-field/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { cn } from "@/lib/utils" + +export type OTPFieldInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseOTPFieldInput = BaseOTPField.Input as React.ElementType + +export const OTPFieldInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +OTPFieldInput.displayName = "OTPFieldInput" diff --git a/src/components/ui/otp-field/root.tsx b/src/components/ui/otp-field/root.tsx new file mode 100644 index 0000000..27836cf --- /dev/null +++ b/src/components/ui/otp-field/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { OTPField as BaseOTPField } from "@base-ui/react/otp-field" +import { cn } from "@/lib/utils" + +export type OTPFieldRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseOTPFieldRoot = BaseOTPField.Root as React.ElementType + +export const OTPFieldRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +OTPFieldRoot.displayName = "OTPFieldRoot" diff --git a/src/components/ui/popover/arrow.tsx b/src/components/ui/popover/arrow.tsx new file mode 100644 index 0000000..5ed2a80 --- /dev/null +++ b/src/components/ui/popover/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverArrow = BasePopover.Arrow as React.ElementType + +export const PopoverArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverArrow.displayName = "PopoverArrow" diff --git a/src/components/ui/popover/backdrop.tsx b/src/components/ui/popover/backdrop.tsx new file mode 100644 index 0000000..12de54e --- /dev/null +++ b/src/components/ui/popover/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverBackdrop = BasePopover.Backdrop as React.ElementType + +export const PopoverBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverBackdrop.displayName = "PopoverBackdrop" diff --git a/src/components/ui/popover/close.tsx b/src/components/ui/popover/close.tsx new file mode 100644 index 0000000..4c96758 --- /dev/null +++ b/src/components/ui/popover/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverClose = BasePopover.Close as React.ElementType + +export const PopoverClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverClose.displayName = "PopoverClose" diff --git a/src/components/ui/popover/content.tsx b/src/components/ui/popover/content.tsx new file mode 100644 index 0000000..9e8e224 --- /dev/null +++ b/src/components/ui/popover/content.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { PopoverBackdrop } from "./backdrop" +import { PopoverPortal } from "./portal" +import { PopoverPositioner } from "./positioner" +import { PopoverPopup, type PopoverPopupProps } from "./popup" + +export type PopoverContentProps = PopoverPopupProps + +export const PopoverContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + + ), +) + +PopoverContent.displayName = "PopoverContent" diff --git a/src/components/ui/popover/description.tsx b/src/components/ui/popover/description.tsx new file mode 100644 index 0000000..e88c3db --- /dev/null +++ b/src/components/ui/popover/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverDescription = BasePopover.Description as React.ElementType + +export const PopoverDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverDescription.displayName = "PopoverDescription" diff --git a/src/components/ui/popover/index.ts b/src/components/ui/popover/index.ts new file mode 100644 index 0000000..c6766ce --- /dev/null +++ b/src/components/ui/popover/index.ts @@ -0,0 +1,60 @@ +import { Popover as BasePopover } from "@base-ui/react/popover" +import { PopoverRoot } from "./root" +import { PopoverTrigger } from "./trigger" +import { PopoverPortal } from "./portal" +import { PopoverPositioner } from "./positioner" +import { PopoverPopup } from "./popup" +import { PopoverArrow } from "./arrow" +import { PopoverBackdrop } from "./backdrop" +import { PopoverTitle } from "./title" +import { PopoverDescription } from "./description" +import { PopoverClose } from "./close" +import { PopoverViewport } from "./viewport" +import { PopoverContent } from "./content" + +const PopoverPrimitive = { + Root: PopoverRoot, + Trigger: PopoverTrigger, + Portal: PopoverPortal, + Positioner: PopoverPositioner, + Popup: PopoverPopup, + Arrow: PopoverArrow, + Backdrop: PopoverBackdrop, + Title: PopoverTitle, + Description: PopoverDescription, + Close: PopoverClose, + Viewport: PopoverViewport, + createHandle: BasePopover.createHandle, +} + +export default PopoverPrimitive + +export { + PopoverRoot as Popover, + PopoverRoot, + PopoverTrigger, + PopoverPortal, + PopoverPositioner, + PopoverPopup, + PopoverArrow, + PopoverBackdrop, + PopoverTitle, + PopoverDescription, + PopoverClose, + PopoverViewport, + PopoverContent, + BasePopover, +} + +export type { PopoverRootProps } from "./root" +export type { PopoverTriggerProps } from "./trigger" +export type { PopoverPortalProps } from "./portal" +export type { PopoverPositionerProps } from "./positioner" +export type { PopoverPopupProps } from "./popup" +export type { PopoverArrowProps } from "./arrow" +export type { PopoverBackdropProps } from "./backdrop" +export type { PopoverTitleProps } from "./title" +export type { PopoverDescriptionProps } from "./description" +export type { PopoverCloseProps } from "./close" +export type { PopoverViewportProps } from "./viewport" +export type { PopoverContentProps } from "./content" diff --git a/src/components/ui/popover/popup.tsx b/src/components/ui/popover/popup.tsx new file mode 100644 index 0000000..75be69d --- /dev/null +++ b/src/components/ui/popover/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPopup = BasePopover.Popup as React.ElementType + +export const PopoverPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPopup.displayName = "PopoverPopup" diff --git a/src/components/ui/popover/portal.tsx b/src/components/ui/popover/portal.tsx new file mode 100644 index 0000000..b7047d8 --- /dev/null +++ b/src/components/ui/popover/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPortal = BasePopover.Portal as React.ElementType + +export const PopoverPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPortal.displayName = "PopoverPortal" diff --git a/src/components/ui/popover/positioner.tsx b/src/components/ui/popover/positioner.tsx new file mode 100644 index 0000000..a49387a --- /dev/null +++ b/src/components/ui/popover/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverPositioner = BasePopover.Positioner as React.ElementType + +export const PopoverPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverPositioner.displayName = "PopoverPositioner" diff --git a/src/components/ui/popover/root.tsx b/src/components/ui/popover/root.tsx new file mode 100644 index 0000000..5497c35 --- /dev/null +++ b/src/components/ui/popover/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverRoot = BasePopover.Root as React.ElementType + +export const PopoverRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverRoot.displayName = "PopoverRoot" diff --git a/src/components/ui/popover/title.tsx b/src/components/ui/popover/title.tsx new file mode 100644 index 0000000..fcd4972 --- /dev/null +++ b/src/components/ui/popover/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverTitle = BasePopover.Title as React.ElementType + +export const PopoverTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverTitle.displayName = "PopoverTitle" diff --git a/src/components/ui/popover/trigger.tsx b/src/components/ui/popover/trigger.tsx new file mode 100644 index 0000000..e150581 --- /dev/null +++ b/src/components/ui/popover/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverTrigger = BasePopover.Trigger as React.ElementType + +export const PopoverTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverTrigger.displayName = "PopoverTrigger" diff --git a/src/components/ui/popover/viewport.tsx b/src/components/ui/popover/viewport.tsx new file mode 100644 index 0000000..0e0675a --- /dev/null +++ b/src/components/ui/popover/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Popover as BasePopover } from "@base-ui/react/popover" +import { cn } from "@/lib/utils" + +export type PopoverViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePopoverViewport = BasePopover.Viewport as React.ElementType + +export const PopoverViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PopoverViewport.displayName = "PopoverViewport" diff --git a/src/components/ui/preview-card/arrow.tsx b/src/components/ui/preview-card/arrow.tsx new file mode 100644 index 0000000..87b892c --- /dev/null +++ b/src/components/ui/preview-card/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardArrow = BasePreviewCard.Arrow as React.ElementType + +export const PreviewCardArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardArrow.displayName = "PreviewCardArrow" diff --git a/src/components/ui/preview-card/backdrop.tsx b/src/components/ui/preview-card/backdrop.tsx new file mode 100644 index 0000000..b528129 --- /dev/null +++ b/src/components/ui/preview-card/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardBackdrop = BasePreviewCard.Backdrop as React.ElementType + +export const PreviewCardBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardBackdrop.displayName = "PreviewCardBackdrop" diff --git a/src/components/ui/preview-card/content.tsx b/src/components/ui/preview-card/content.tsx new file mode 100644 index 0000000..e044ad5 --- /dev/null +++ b/src/components/ui/preview-card/content.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { PreviewCardBackdrop } from "./backdrop" +import { PreviewCardPortal } from "./portal" +import { PreviewCardPositioner } from "./positioner" +import { PreviewCardPopup, type PreviewCardPopupProps } from "./popup" + +export type PreviewCardContentProps = PreviewCardPopupProps + +export const PreviewCardContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + + ), +) + +PreviewCardContent.displayName = "PreviewCardContent" diff --git a/src/components/ui/preview-card/index.ts b/src/components/ui/preview-card/index.ts new file mode 100644 index 0000000..fb8b51d --- /dev/null +++ b/src/components/ui/preview-card/index.ts @@ -0,0 +1,48 @@ +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { PreviewCardRoot } from "./root" +import { PreviewCardPortal } from "./portal" +import { PreviewCardTrigger } from "./trigger" +import { PreviewCardPositioner } from "./positioner" +import { PreviewCardPopup } from "./popup" +import { PreviewCardArrow } from "./arrow" +import { PreviewCardBackdrop } from "./backdrop" +import { PreviewCardViewport } from "./viewport" +import { PreviewCardContent } from "./content" + +const PreviewCardPrimitive = { + Root: PreviewCardRoot, + Portal: PreviewCardPortal, + Trigger: PreviewCardTrigger, + Positioner: PreviewCardPositioner, + Popup: PreviewCardPopup, + Arrow: PreviewCardArrow, + Backdrop: PreviewCardBackdrop, + Viewport: PreviewCardViewport, + createHandle: BasePreviewCard.createHandle, +} + +export default PreviewCardPrimitive + +export { + PreviewCardRoot as PreviewCard, + PreviewCardRoot, + PreviewCardPortal, + PreviewCardTrigger, + PreviewCardPositioner, + PreviewCardPopup, + PreviewCardArrow, + PreviewCardBackdrop, + PreviewCardViewport, + PreviewCardContent, + BasePreviewCard, +} + +export type { PreviewCardRootProps } from "./root" +export type { PreviewCardPortalProps } from "./portal" +export type { PreviewCardTriggerProps } from "./trigger" +export type { PreviewCardPositionerProps } from "./positioner" +export type { PreviewCardPopupProps } from "./popup" +export type { PreviewCardArrowProps } from "./arrow" +export type { PreviewCardBackdropProps } from "./backdrop" +export type { PreviewCardViewportProps } from "./viewport" +export type { PreviewCardContentProps } from "./content" diff --git a/src/components/ui/preview-card/popup.tsx b/src/components/ui/preview-card/popup.tsx new file mode 100644 index 0000000..d8ae9db --- /dev/null +++ b/src/components/ui/preview-card/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPopup = BasePreviewCard.Popup as React.ElementType + +export const PreviewCardPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPopup.displayName = "PreviewCardPopup" diff --git a/src/components/ui/preview-card/portal.tsx b/src/components/ui/preview-card/portal.tsx new file mode 100644 index 0000000..7d0ebeb --- /dev/null +++ b/src/components/ui/preview-card/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPortal = BasePreviewCard.Portal as React.ElementType + +export const PreviewCardPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPortal.displayName = "PreviewCardPortal" diff --git a/src/components/ui/preview-card/positioner.tsx b/src/components/ui/preview-card/positioner.tsx new file mode 100644 index 0000000..aa9b075 --- /dev/null +++ b/src/components/ui/preview-card/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardPositioner = BasePreviewCard.Positioner as React.ElementType + +export const PreviewCardPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardPositioner.displayName = "PreviewCardPositioner" diff --git a/src/components/ui/preview-card/root.tsx b/src/components/ui/preview-card/root.tsx new file mode 100644 index 0000000..be9ac46 --- /dev/null +++ b/src/components/ui/preview-card/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardRoot = BasePreviewCard.Root as React.ElementType + +export const PreviewCardRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardRoot.displayName = "PreviewCardRoot" diff --git a/src/components/ui/preview-card/trigger.tsx b/src/components/ui/preview-card/trigger.tsx new file mode 100644 index 0000000..b7139c2 --- /dev/null +++ b/src/components/ui/preview-card/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardTrigger = BasePreviewCard.Trigger as React.ElementType + +export const PreviewCardTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardTrigger.displayName = "PreviewCardTrigger" diff --git a/src/components/ui/preview-card/viewport.tsx b/src/components/ui/preview-card/viewport.tsx new file mode 100644 index 0000000..47d63e4 --- /dev/null +++ b/src/components/ui/preview-card/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card" +import { cn } from "@/lib/utils" + +export type PreviewCardViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BasePreviewCardViewport = BasePreviewCard.Viewport as React.ElementType + +export const PreviewCardViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +PreviewCardViewport.displayName = "PreviewCardViewport" diff --git a/src/components/ui/progress/index.ts b/src/components/ui/progress/index.ts new file mode 100644 index 0000000..cd0662d --- /dev/null +++ b/src/components/ui/progress/index.ts @@ -0,0 +1,30 @@ +import { ProgressRoot } from "./root" +import { ProgressTrack } from "./track" +import { ProgressIndicator } from "./indicator" +import { ProgressValue } from "./value" +import { ProgressLabel } from "./label" + +const ProgressPrimitive = { + Root: ProgressRoot, + Track: ProgressTrack, + Indicator: ProgressIndicator, + Value: ProgressValue, + Label: ProgressLabel, +} + +export default ProgressPrimitive + +export { + ProgressRoot as Progress, + ProgressRoot, + ProgressTrack, + ProgressIndicator, + ProgressValue, + ProgressLabel, +} + +export type { ProgressRootProps } from "./root" +export type { ProgressTrackProps } from "./track" +export type { ProgressIndicatorProps } from "./indicator" +export type { ProgressValueProps } from "./value" +export type { ProgressLabelProps } from "./label" diff --git a/src/components/ui/progress/indicator.tsx b/src/components/ui/progress/indicator.tsx new file mode 100644 index 0000000..a044e92 --- /dev/null +++ b/src/components/ui/progress/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressIndicator = BaseProgress.Indicator as React.ElementType + +export const ProgressIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressIndicator.displayName = "ProgressIndicator" diff --git a/src/components/ui/progress/label.tsx b/src/components/ui/progress/label.tsx new file mode 100644 index 0000000..bc8befa --- /dev/null +++ b/src/components/ui/progress/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressLabel = BaseProgress.Label as React.ElementType + +export const ProgressLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressLabel.displayName = "ProgressLabel" diff --git a/src/components/ui/progress/root.tsx b/src/components/ui/progress/root.tsx new file mode 100644 index 0000000..eaf9991 --- /dev/null +++ b/src/components/ui/progress/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressRoot = BaseProgress.Root as React.ElementType + +export const ProgressRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressRoot.displayName = "ProgressRoot" diff --git a/src/components/ui/progress/track.tsx b/src/components/ui/progress/track.tsx new file mode 100644 index 0000000..2494a12 --- /dev/null +++ b/src/components/ui/progress/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressTrack = BaseProgress.Track as React.ElementType + +export const ProgressTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressTrack.displayName = "ProgressTrack" diff --git a/src/components/ui/progress/value.tsx b/src/components/ui/progress/value.tsx new file mode 100644 index 0000000..b8ee5a6 --- /dev/null +++ b/src/components/ui/progress/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Progress as BaseProgress } from "@base-ui/react/progress" +import { cn } from "@/lib/utils" + +export type ProgressValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseProgressValue = BaseProgress.Value as React.ElementType + +export const ProgressValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ProgressValue.displayName = "ProgressValue" diff --git a/src/components/ui/radio/index.ts b/src/components/ui/radio/index.ts new file mode 100644 index 0000000..974fb9d --- /dev/null +++ b/src/components/ui/radio/index.ts @@ -0,0 +1,18 @@ +import { RadioRoot } from "./root" +import { RadioIndicator } from "./indicator" + +const RadioPrimitive = { + Root: RadioRoot, + Indicator: RadioIndicator, +} + +export default RadioPrimitive + +export { + RadioRoot as Radio, + RadioRoot, + RadioIndicator, +} + +export type { RadioRootProps } from "./root" +export type { RadioIndicatorProps } from "./indicator" diff --git a/src/components/ui/radio/indicator.tsx b/src/components/ui/radio/indicator.tsx new file mode 100644 index 0000000..27c7ef0 --- /dev/null +++ b/src/components/ui/radio/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Radio as BaseRadio } from "@base-ui/react/radio" +import { cn } from "@/lib/utils" + +export type RadioIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseRadioIndicator = BaseRadio.Indicator as React.ElementType + +export const RadioIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +RadioIndicator.displayName = "RadioIndicator" diff --git a/src/components/ui/radio/root.tsx b/src/components/ui/radio/root.tsx new file mode 100644 index 0000000..88c6623 --- /dev/null +++ b/src/components/ui/radio/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Radio as BaseRadio } from "@base-ui/react/radio" +import { cn } from "@/lib/utils" + +export type RadioRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseRadioRoot = BaseRadio.Root as React.ElementType + +export const RadioRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +RadioRoot.displayName = "RadioRoot" diff --git a/src/components/ui/scroll-area/content.tsx b/src/components/ui/scroll-area/content.tsx new file mode 100644 index 0000000..1469bd4 --- /dev/null +++ b/src/components/ui/scroll-area/content.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaContent = BaseScrollArea.Content as React.ElementType +const defaultScrollAreaContentClassName = + "flex flex-col gap-4 py-2 pr-5 pl-3 text-sm leading-[1.375rem] text-neutral-950 dark:text-white" + +export const ScrollAreaContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaContent.displayName = "ScrollAreaContent" diff --git a/src/components/ui/scroll-area/corner.tsx b/src/components/ui/scroll-area/corner.tsx new file mode 100644 index 0000000..b05ff73 --- /dev/null +++ b/src/components/ui/scroll-area/corner.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaCornerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaCorner = BaseScrollArea.Corner as React.ElementType +const defaultScrollAreaCornerClassName = "bg-neutral-100 dark:bg-neutral-900" + +export const ScrollAreaCorner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaCorner.displayName = "ScrollAreaCorner" diff --git a/src/components/ui/scroll-area/index.ts b/src/components/ui/scroll-area/index.ts new file mode 100644 index 0000000..e79238d --- /dev/null +++ b/src/components/ui/scroll-area/index.ts @@ -0,0 +1,34 @@ +import { ScrollAreaRoot } from "./root" +import { ScrollAreaViewport } from "./viewport" +import { ScrollAreaScrollbar } from "./scrollbar" +import { ScrollAreaContent } from "./content" +import { ScrollAreaThumb } from "./thumb" +import { ScrollAreaCorner } from "./corner" + +const ScrollAreaPrimitive = { + Root: ScrollAreaRoot, + Viewport: ScrollAreaViewport, + Scrollbar: ScrollAreaScrollbar, + Content: ScrollAreaContent, + Thumb: ScrollAreaThumb, + Corner: ScrollAreaCorner, +} + +export default ScrollAreaPrimitive + +export { + ScrollAreaRoot as ScrollArea, + ScrollAreaRoot, + ScrollAreaViewport, + ScrollAreaScrollbar, + ScrollAreaContent, + ScrollAreaThumb, + ScrollAreaCorner, +} + +export type { ScrollAreaRootProps } from "./root" +export type { ScrollAreaViewportProps } from "./viewport" +export type { ScrollAreaScrollbarProps } from "./scrollbar" +export type { ScrollAreaContentProps } from "./content" +export type { ScrollAreaThumbProps } from "./thumb" +export type { ScrollAreaCornerProps } from "./corner" diff --git a/src/components/ui/scroll-area/root.tsx b/src/components/ui/scroll-area/root.tsx new file mode 100644 index 0000000..bcf9057 --- /dev/null +++ b/src/components/ui/scroll-area/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaRoot = BaseScrollArea.Root as React.ElementType +const defaultScrollAreaRootClassName = + "group/scroll-area h-[8.5rem] w-96 max-w-[calc(100vw-8rem)] bg-white dark:bg-neutral-950" + +export const ScrollAreaRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaRoot.displayName = "ScrollAreaRoot" diff --git a/src/components/ui/scroll-area/scrollbar.tsx b/src/components/ui/scroll-area/scrollbar.tsx new file mode 100644 index 0000000..66c85a6 --- /dev/null +++ b/src/components/ui/scroll-area/scrollbar.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaScrollbarProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaScrollbar = BaseScrollArea.Scrollbar as React.ElementType +const defaultScrollAreaScrollbarClassName = + "m-px flex bg-black/[.12] opacity-0 transition-opacity pointer-events-none data-[orientation=vertical]:w-4 data-[orientation=horizontal]:h-4 data-hovering:opacity-100 data-hovering:pointer-events-auto data-scrolling:opacity-100 data-scrolling:duration-0 data-scrolling:pointer-events-auto group-hover/scroll-area:opacity-100 group-hover/scroll-area:pointer-events-auto dark:bg-white/[.12]" + +export const ScrollAreaScrollbar = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaScrollbar.displayName = "ScrollAreaScrollbar" diff --git a/src/components/ui/scroll-area/thumb.tsx b/src/components/ui/scroll-area/thumb.tsx new file mode 100644 index 0000000..d4e3f48 --- /dev/null +++ b/src/components/ui/scroll-area/thumb.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaThumb = BaseScrollArea.Thumb as React.ElementType + +export const ScrollAreaThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaThumb.displayName = "ScrollAreaThumb" diff --git a/src/components/ui/scroll-area/viewport.tsx b/src/components/ui/scroll-area/viewport.tsx new file mode 100644 index 0000000..b3b3355 --- /dev/null +++ b/src/components/ui/scroll-area/viewport.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area" +import { cn } from "@/lib/utils" + +export type ScrollAreaViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseScrollAreaViewport = BaseScrollArea.Viewport as React.ElementType +const defaultScrollAreaViewportClassName = + "h-full border border-neutral-950 dark:border-white focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ScrollAreaViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ScrollAreaViewport.displayName = "ScrollAreaViewport" diff --git a/src/components/ui/select/arrow.tsx b/src/components/ui/select/arrow.tsx new file mode 100644 index 0000000..ebc6c01 --- /dev/null +++ b/src/components/ui/select/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectArrow = BaseSelect.Arrow as React.ElementType + +export const SelectArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectArrow.displayName = "SelectArrow" diff --git a/src/components/ui/select/backdrop.tsx b/src/components/ui/select/backdrop.tsx new file mode 100644 index 0000000..d26f8ad --- /dev/null +++ b/src/components/ui/select/backdrop.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectBackdropProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectBackdrop = BaseSelect.Backdrop as React.ElementType + +export const SelectBackdrop = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectBackdrop.displayName = "SelectBackdrop" diff --git a/src/components/ui/select/group-label.tsx b/src/components/ui/select/group-label.tsx new file mode 100644 index 0000000..990495b --- /dev/null +++ b/src/components/ui/select/group-label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectGroupLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectGroupLabel = BaseSelect.GroupLabel as React.ElementType + +export const SelectGroupLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectGroupLabel.displayName = "SelectGroupLabel" diff --git a/src/components/ui/select/group.tsx b/src/components/ui/select/group.tsx new file mode 100644 index 0000000..3698e9b --- /dev/null +++ b/src/components/ui/select/group.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectGroup = BaseSelect.Group as React.ElementType + +export const SelectGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectGroup.displayName = "SelectGroup" diff --git a/src/components/ui/select/icon.tsx b/src/components/ui/select/icon.tsx new file mode 100644 index 0000000..45b90fa --- /dev/null +++ b/src/components/ui/select/icon.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectIconProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectIcon = BaseSelect.Icon as React.ElementType + +export const SelectIcon = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectIcon.displayName = "SelectIcon" diff --git a/src/components/ui/select/index.ts b/src/components/ui/select/index.ts new file mode 100644 index 0000000..88aa533 --- /dev/null +++ b/src/components/ui/select/index.ts @@ -0,0 +1,88 @@ +import { Select as BaseSelect } from "@base-ui/react/select" +import { SelectRoot } from "./root" +import { SelectLabel } from "./label" +import { SelectTrigger } from "./trigger" +import { SelectValue } from "./value" +import { SelectIcon } from "./icon" +import { SelectPortal } from "./portal" +import { SelectBackdrop } from "./backdrop" +import { SelectPositioner } from "./positioner" +import { SelectPopup } from "./popup" +import { SelectList } from "./list" +import { SelectItem } from "./item" +import { SelectItemIndicator } from "./item-indicator" +import { SelectItemText } from "./item-text" +import { SelectArrow } from "./arrow" +import { SelectScrollDownArrow } from "./scroll-down-arrow" +import { SelectScrollUpArrow } from "./scroll-up-arrow" +import { SelectGroup } from "./group" +import { SelectGroupLabel } from "./group-label" +import { SelectSeparator } from "./separator" + +const SelectPrimitive = { + Root: SelectRoot, + Label: SelectLabel, + Trigger: SelectTrigger, + Value: SelectValue, + Icon: SelectIcon, + Portal: SelectPortal, + Backdrop: SelectBackdrop, + Positioner: SelectPositioner, + Popup: SelectPopup, + List: SelectList, + Item: SelectItem, + ItemIndicator: SelectItemIndicator, + ItemText: SelectItemText, + Arrow: SelectArrow, + ScrollDownArrow: SelectScrollDownArrow, + ScrollUpArrow: SelectScrollUpArrow, + Group: SelectGroup, + GroupLabel: SelectGroupLabel, + Separator: SelectSeparator, +} + +export default SelectPrimitive + +export { + SelectRoot as Select, + SelectRoot, + SelectLabel, + SelectTrigger, + SelectValue, + SelectIcon, + SelectPortal, + SelectBackdrop, + SelectPositioner, + SelectPopup, + SelectList, + SelectItem, + SelectItemIndicator, + SelectItemText, + SelectArrow, + SelectScrollDownArrow, + SelectScrollUpArrow, + SelectGroup, + SelectGroupLabel, + SelectSeparator, + BaseSelect, +} + +export type { SelectRootProps } from "./root" +export type { SelectLabelProps } from "./label" +export type { SelectTriggerProps } from "./trigger" +export type { SelectValueProps } from "./value" +export type { SelectIconProps } from "./icon" +export type { SelectPortalProps } from "./portal" +export type { SelectBackdropProps } from "./backdrop" +export type { SelectPositionerProps } from "./positioner" +export type { SelectPopupProps } from "./popup" +export type { SelectListProps } from "./list" +export type { SelectItemProps } from "./item" +export type { SelectItemIndicatorProps } from "./item-indicator" +export type { SelectItemTextProps } from "./item-text" +export type { SelectArrowProps } from "./arrow" +export type { SelectScrollDownArrowProps } from "./scroll-down-arrow" +export type { SelectScrollUpArrowProps } from "./scroll-up-arrow" +export type { SelectGroupProps } from "./group" +export type { SelectGroupLabelProps } from "./group-label" +export type { SelectSeparatorProps } from "./separator" diff --git a/src/components/ui/select/item-indicator.tsx b/src/components/ui/select/item-indicator.tsx new file mode 100644 index 0000000..3592963 --- /dev/null +++ b/src/components/ui/select/item-indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItemIndicator = BaseSelect.ItemIndicator as React.ElementType + +export const SelectItemIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItemIndicator.displayName = "SelectItemIndicator" diff --git a/src/components/ui/select/item-text.tsx b/src/components/ui/select/item-text.tsx new file mode 100644 index 0000000..a076da8 --- /dev/null +++ b/src/components/ui/select/item-text.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemTextProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItemText = BaseSelect.ItemText as React.ElementType + +export const SelectItemText = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItemText.displayName = "SelectItemText" diff --git a/src/components/ui/select/item.tsx b/src/components/ui/select/item.tsx new file mode 100644 index 0000000..31dd089 --- /dev/null +++ b/src/components/ui/select/item.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectItemProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectItem = BaseSelect.Item as React.ElementType +const defaultSelectItemClassName = + "grid cursor-default grid-cols-[1rem_1fr] items-center gap-2 py-1.5 pr-4 pl-2.5 text-sm outline-none select-none data-[highlighted]:bg-neutral-950 data-[highlighted]:text-white pointer-coarse:py-2.5 dark:data-[highlighted]:bg-white dark:data-[highlighted]:text-neutral-950" + +export const SelectItem = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectItem.displayName = "SelectItem" diff --git a/src/components/ui/select/label.tsx b/src/components/ui/select/label.tsx new file mode 100644 index 0000000..0460002 --- /dev/null +++ b/src/components/ui/select/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectLabel = BaseSelect.Label as React.ElementType + +export const SelectLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectLabel.displayName = "SelectLabel" diff --git a/src/components/ui/select/list.tsx b/src/components/ui/select/list.tsx new file mode 100644 index 0000000..8702dad --- /dev/null +++ b/src/components/ui/select/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectList = BaseSelect.List as React.ElementType + +export const SelectList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectList.displayName = "SelectList" diff --git a/src/components/ui/select/popup.tsx b/src/components/ui/select/popup.tsx new file mode 100644 index 0000000..1dda4e8 --- /dev/null +++ b/src/components/ui/select/popup.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPopup = BaseSelect.Popup as React.ElementType +const defaultSelectPopupClassName = + "group min-w-[var(--anchor-width)] origin-[var(--transform-origin)] bg-clip-padding border border-neutral-950 bg-white text-neutral-950 outline-none 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-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[side=none]:translate-y-px data-[side=none]:min-w-[calc(var(--anchor-width)+1.75rem)] data-[side=none]:data-[ending-style]:transition-none data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0 data-[side=none]:data-[starting-style]:scale-100 data-[side=none]:data-[starting-style]:opacity-100 data-[side=none]:data-[starting-style]:transition-none dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const SelectPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectPopup.displayName = "SelectPopup" diff --git a/src/components/ui/select/portal.tsx b/src/components/ui/select/portal.tsx new file mode 100644 index 0000000..2fec9e7 --- /dev/null +++ b/src/components/ui/select/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type SelectPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPortal = BaseSelect.Portal as React.ElementType + +export const SelectPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +SelectPortal.displayName = "SelectPortal" diff --git a/src/components/ui/select/positioner.tsx b/src/components/ui/select/positioner.tsx new file mode 100644 index 0000000..32cd4cf --- /dev/null +++ b/src/components/ui/select/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectPositioner = BaseSelect.Positioner as React.ElementType + +export const SelectPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectPositioner.displayName = "SelectPositioner" diff --git a/src/components/ui/select/root.tsx b/src/components/ui/select/root.tsx new file mode 100644 index 0000000..a625eb3 --- /dev/null +++ b/src/components/ui/select/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectRoot = BaseSelect.Root as React.ElementType + +export const SelectRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectRoot.displayName = "SelectRoot" diff --git a/src/components/ui/select/scroll-down-arrow.tsx b/src/components/ui/select/scroll-down-arrow.tsx new file mode 100644 index 0000000..1411162 --- /dev/null +++ b/src/components/ui/select/scroll-down-arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectScrollDownArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectScrollDownArrow = BaseSelect.ScrollDownArrow as React.ElementType + +export const SelectScrollDownArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectScrollDownArrow.displayName = "SelectScrollDownArrow" diff --git a/src/components/ui/select/scroll-up-arrow.tsx b/src/components/ui/select/scroll-up-arrow.tsx new file mode 100644 index 0000000..1a721d5 --- /dev/null +++ b/src/components/ui/select/scroll-up-arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectScrollUpArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectScrollUpArrow = BaseSelect.ScrollUpArrow as React.ElementType + +export const SelectScrollUpArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectScrollUpArrow.displayName = "SelectScrollUpArrow" diff --git a/src/components/ui/select/separator.tsx b/src/components/ui/select/separator.tsx new file mode 100644 index 0000000..6cd35ae --- /dev/null +++ b/src/components/ui/select/separator.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectSeparatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectSeparator = BaseSelect.Separator as React.ElementType +const defaultSelectSeparatorClassName = "mx-4 my-1 h-px bg-neutral-950 dark:bg-white" + +export const SelectSeparator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectSeparator.displayName = "SelectSeparator" diff --git a/src/components/ui/select/trigger.tsx b/src/components/ui/select/trigger.tsx new file mode 100644 index 0000000..f646feb --- /dev/null +++ b/src/components/ui/select/trigger.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectTrigger = BaseSelect.Trigger as React.ElementType +const defaultSelectTriggerClassName = + "flex h-8 min-w-40 items-center justify-between gap-3 pl-2 pr-1 text-sm leading-none whitespace-nowrap border border-neutral-950 dark:border-white bg-white dark:bg-neutral-950 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 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 data-[popup-open]:bg-neutral-100 dark:data-[popup-open]:bg-neutral-800 font-normal focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const SelectTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectTrigger.displayName = "SelectTrigger" diff --git a/src/components/ui/select/value.tsx b/src/components/ui/select/value.tsx new file mode 100644 index 0000000..a1fdcfd --- /dev/null +++ b/src/components/ui/select/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Select as BaseSelect } from "@base-ui/react/select" +import { cn } from "@/lib/utils" + +export type SelectValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSelectValue = BaseSelect.Value as React.ElementType + +export const SelectValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SelectValue.displayName = "SelectValue" diff --git a/src/components/ui/separator/index.ts b/src/components/ui/separator/index.ts new file mode 100644 index 0000000..e273624 --- /dev/null +++ b/src/components/ui/separator/index.ts @@ -0,0 +1,4 @@ +import { Separator } from "./root" + +export { Separator, type SeparatorProps } from "./root" +export default Separator diff --git a/src/components/ui/separator/root.tsx b/src/components/ui/separator/root.tsx new file mode 100644 index 0000000..c71b287 --- /dev/null +++ b/src/components/ui/separator/root.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { Separator as BaseSeparator } from "@base-ui/react/separator" +import { cn } from "@/lib/utils" + +export type SeparatorProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseSeparatorElement = BaseSeparator as React.ElementType + +export const Separator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Separator.displayName = "Separator" diff --git a/src/components/ui/slider/control.tsx b/src/components/ui/slider/control.tsx new file mode 100644 index 0000000..2808b83 --- /dev/null +++ b/src/components/ui/slider/control.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderControlProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderControl = BaseSlider.Control as React.ElementType + +export const SliderControl = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderControl.displayName = "SliderControl" diff --git a/src/components/ui/slider/index.ts b/src/components/ui/slider/index.ts new file mode 100644 index 0000000..9a380fb --- /dev/null +++ b/src/components/ui/slider/index.ts @@ -0,0 +1,38 @@ +import { SliderRoot } from "./root" +import { SliderLabel } from "./label" +import { SliderValue } from "./value" +import { SliderControl } from "./control" +import { SliderTrack } from "./track" +import { SliderThumb } from "./thumb" +import { SliderIndicator } from "./indicator" + +const SliderPrimitive = { + Root: SliderRoot, + Label: SliderLabel, + Value: SliderValue, + Control: SliderControl, + Track: SliderTrack, + Thumb: SliderThumb, + Indicator: SliderIndicator, +} + +export default SliderPrimitive + +export { + SliderRoot as Slider, + SliderRoot, + SliderLabel, + SliderValue, + SliderControl, + SliderTrack, + SliderThumb, + SliderIndicator, +} + +export type { SliderRootProps } from "./root" +export type { SliderLabelProps } from "./label" +export type { SliderValueProps } from "./value" +export type { SliderControlProps } from "./control" +export type { SliderTrackProps } from "./track" +export type { SliderThumbProps } from "./thumb" +export type { SliderIndicatorProps } from "./indicator" diff --git a/src/components/ui/slider/indicator.tsx b/src/components/ui/slider/indicator.tsx new file mode 100644 index 0000000..0d64683 --- /dev/null +++ b/src/components/ui/slider/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderIndicator = BaseSlider.Indicator as React.ElementType + +export const SliderIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderIndicator.displayName = "SliderIndicator" diff --git a/src/components/ui/slider/label.tsx b/src/components/ui/slider/label.tsx new file mode 100644 index 0000000..d02f94d --- /dev/null +++ b/src/components/ui/slider/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderLabelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderLabel = BaseSlider.Label as React.ElementType + +export const SliderLabel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderLabel.displayName = "SliderLabel" diff --git a/src/components/ui/slider/root.tsx b/src/components/ui/slider/root.tsx new file mode 100644 index 0000000..d598e97 --- /dev/null +++ b/src/components/ui/slider/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderRoot = BaseSlider.Root as React.ElementType + +export const SliderRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderRoot.displayName = "SliderRoot" diff --git a/src/components/ui/slider/thumb.tsx b/src/components/ui/slider/thumb.tsx new file mode 100644 index 0000000..805643d --- /dev/null +++ b/src/components/ui/slider/thumb.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderThumb = BaseSlider.Thumb as React.ElementType + +export const SliderThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderThumb.displayName = "SliderThumb" diff --git a/src/components/ui/slider/track.tsx b/src/components/ui/slider/track.tsx new file mode 100644 index 0000000..c6fe448 --- /dev/null +++ b/src/components/ui/slider/track.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderTrackProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderTrack = BaseSlider.Track as React.ElementType + +export const SliderTrack = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderTrack.displayName = "SliderTrack" diff --git a/src/components/ui/slider/value.tsx b/src/components/ui/slider/value.tsx new file mode 100644 index 0000000..0daaebb --- /dev/null +++ b/src/components/ui/slider/value.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Slider as BaseSlider } from "@base-ui/react/slider" +import { cn } from "@/lib/utils" + +export type SliderValueProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSliderValue = BaseSlider.Value as React.ElementType + +export const SliderValue = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SliderValue.displayName = "SliderValue" diff --git a/src/components/ui/switch/index.ts b/src/components/ui/switch/index.ts new file mode 100644 index 0000000..56a8f1b --- /dev/null +++ b/src/components/ui/switch/index.ts @@ -0,0 +1,18 @@ +import { SwitchRoot } from "./root" +import { SwitchThumb } from "./thumb" + +const SwitchPrimitive = { + Root: SwitchRoot, + Thumb: SwitchThumb, +} + +export default SwitchPrimitive + +export { + SwitchRoot as Switch, + SwitchRoot, + SwitchThumb, +} + +export type { SwitchRootProps } from "./root" +export type { SwitchThumbProps } from "./thumb" diff --git a/src/components/ui/switch/root.tsx b/src/components/ui/switch/root.tsx new file mode 100644 index 0000000..b683827 --- /dev/null +++ b/src/components/ui/switch/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Switch as BaseSwitch } from "@base-ui/react/switch" +import { cn } from "@/lib/utils" + +export type SwitchRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSwitchRoot = BaseSwitch.Root as React.ElementType +const defaultSwitchRootClassName = + "flex h-5 w-9 shrink-0 border border-neutral-950 bg-white p-0.5 transition-colors duration-150 ease-[ease] data-[checked]:bg-neutral-950 focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-2 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:data-[checked]:bg-white dark:focus-visible:outline-white" + +export const SwitchRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SwitchRoot.displayName = "SwitchRoot" diff --git a/src/components/ui/switch/thumb.tsx b/src/components/ui/switch/thumb.tsx new file mode 100644 index 0000000..565963a --- /dev/null +++ b/src/components/ui/switch/thumb.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Switch as BaseSwitch } from "@base-ui/react/switch" +import { cn } from "@/lib/utils" + +export type SwitchThumbProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseSwitchThumb = BaseSwitch.Thumb as React.ElementType +const defaultSwitchThumbClassName = + "size-3.5 bg-neutral-950 transition-[translate,background-color] duration-150 ease-[ease] data-checked:translate-x-4 data-checked:bg-white dark:bg-white dark:data-checked:bg-neutral-950" + +export const SwitchThumb = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +SwitchThumb.displayName = "SwitchThumb" diff --git a/src/components/ui/tabs/index.ts b/src/components/ui/tabs/index.ts new file mode 100644 index 0000000..ca93104 --- /dev/null +++ b/src/components/ui/tabs/index.ts @@ -0,0 +1,30 @@ +import { TabsRoot } from "./root" +import { TabsTab } from "./tab" +import { TabsIndicator } from "./indicator" +import { TabsPanel } from "./panel" +import { TabsList } from "./list" + +const TabsPrimitive = { + Root: TabsRoot, + Tab: TabsTab, + Indicator: TabsIndicator, + Panel: TabsPanel, + List: TabsList, +} + +export default TabsPrimitive + +export { + TabsRoot as Tabs, + TabsRoot, + TabsTab, + TabsIndicator, + TabsPanel, + TabsList, +} + +export type { TabsRootProps } from "./root" +export type { TabsTabProps } from "./tab" +export type { TabsIndicatorProps } from "./indicator" +export type { TabsPanelProps } from "./panel" +export type { TabsListProps } from "./list" diff --git a/src/components/ui/tabs/indicator.tsx b/src/components/ui/tabs/indicator.tsx new file mode 100644 index 0000000..f9f10b9 --- /dev/null +++ b/src/components/ui/tabs/indicator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsIndicatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsIndicator = BaseTabs.Indicator as React.ElementType + +export const TabsIndicator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsIndicator.displayName = "TabsIndicator" diff --git a/src/components/ui/tabs/list.tsx b/src/components/ui/tabs/list.tsx new file mode 100644 index 0000000..ed2f537 --- /dev/null +++ b/src/components/ui/tabs/list.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsListProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsList = BaseTabs.List as React.ElementType + +export const TabsList = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsList.displayName = "TabsList" diff --git a/src/components/ui/tabs/panel.tsx b/src/components/ui/tabs/panel.tsx new file mode 100644 index 0000000..d0690f1 --- /dev/null +++ b/src/components/ui/tabs/panel.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsPanelProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsPanel = BaseTabs.Panel as React.ElementType + +export const TabsPanel = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsPanel.displayName = "TabsPanel" diff --git a/src/components/ui/tabs/root.tsx b/src/components/ui/tabs/root.tsx new file mode 100644 index 0000000..82eaee8 --- /dev/null +++ b/src/components/ui/tabs/root.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsRoot = BaseTabs.Root as React.ElementType + +export const TabsRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsRoot.displayName = "TabsRoot" diff --git a/src/components/ui/tabs/tab.tsx b/src/components/ui/tabs/tab.tsx new file mode 100644 index 0000000..53e68a1 --- /dev/null +++ b/src/components/ui/tabs/tab.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tabs as BaseTabs } from "@base-ui/react/tabs" +import { cn } from "@/lib/utils" + +export type TabsTabProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTabsTab = BaseTabs.Tab as React.ElementType + +export const TabsTab = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TabsTab.displayName = "TabsTab" diff --git a/src/components/ui/toast/action.tsx b/src/components/ui/toast/action.tsx new file mode 100644 index 0000000..f10e1a6 --- /dev/null +++ b/src/components/ui/toast/action.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastActionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastAction = BaseToast.Action as React.ElementType + +export const ToastAction = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastAction.displayName = "ToastAction" diff --git a/src/components/ui/toast/arrow.tsx b/src/components/ui/toast/arrow.tsx new file mode 100644 index 0000000..5e8830c --- /dev/null +++ b/src/components/ui/toast/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastArrow = BaseToast.Arrow as React.ElementType + +export const ToastArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastArrow.displayName = "ToastArrow" diff --git a/src/components/ui/toast/close.tsx b/src/components/ui/toast/close.tsx new file mode 100644 index 0000000..ac6549b --- /dev/null +++ b/src/components/ui/toast/close.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastCloseProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastClose = BaseToast.Close as React.ElementType + +export const ToastClose = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastClose.displayName = "ToastClose" diff --git a/src/components/ui/toast/content.tsx b/src/components/ui/toast/content.tsx new file mode 100644 index 0000000..dcbff13 --- /dev/null +++ b/src/components/ui/toast/content.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastContentProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastContent = BaseToast.Content as React.ElementType + +export const ToastContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastContent.displayName = "ToastContent" diff --git a/src/components/ui/toast/description.tsx b/src/components/ui/toast/description.tsx new file mode 100644 index 0000000..2532df1 --- /dev/null +++ b/src/components/ui/toast/description.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastDescriptionProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastDescription = BaseToast.Description as React.ElementType + +export const ToastDescription = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastDescription.displayName = "ToastDescription" diff --git a/src/components/ui/toast/index.ts b/src/components/ui/toast/index.ts new file mode 100644 index 0000000..f44784c --- /dev/null +++ b/src/components/ui/toast/index.ts @@ -0,0 +1,62 @@ +import { Toast as BaseToast } from "@base-ui/react/toast" +import { ToastProvider } from "./provider" +import { ToastViewport } from "./viewport" +import { ToastRoot } from "./root" +import { ToastContent } from "./content" +import { ToastDescription } from "./description" +import { ToastTitle } from "./title" +import { ToastClose } from "./close" +import { ToastAction } from "./action" +import { ToastPortal } from "./portal" +import { ToastPositioner } from "./positioner" +import { ToastArrow } from "./arrow" + +const useToastManager = BaseToast.useToastManager +const createToastManager = BaseToast.createToastManager + +const ToastPrimitive = { + Provider: ToastProvider, + Viewport: ToastViewport, + Root: ToastRoot, + Content: ToastContent, + Description: ToastDescription, + Title: ToastTitle, + Close: ToastClose, + Action: ToastAction, + Portal: ToastPortal, + Positioner: ToastPositioner, + Arrow: ToastArrow, + useToastManager: BaseToast.useToastManager, + createToastManager: BaseToast.createToastManager, +} + +export default ToastPrimitive + +export { + ToastRoot as Toast, + ToastProvider, + ToastViewport, + ToastRoot, + ToastContent, + ToastDescription, + ToastTitle, + ToastClose, + ToastAction, + ToastPortal, + ToastPositioner, + ToastArrow, + useToastManager, + createToastManager, +} + +export type { ToastProviderProps } from "./provider" +export type { ToastViewportProps } from "./viewport" +export type { ToastRootProps } from "./root" +export type { ToastContentProps } from "./content" +export type { ToastDescriptionProps } from "./description" +export type { ToastTitleProps } from "./title" +export type { ToastCloseProps } from "./close" +export type { ToastActionProps } from "./action" +export type { ToastPortalProps } from "./portal" +export type { ToastPositionerProps } from "./positioner" +export type { ToastArrowProps } from "./arrow" diff --git a/src/components/ui/toast/portal.tsx b/src/components/ui/toast/portal.tsx new file mode 100644 index 0000000..3f1c549 --- /dev/null +++ b/src/components/ui/toast/portal.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" +import { usePortalContainer } from "@/lib/portal-container" + +export type ToastPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastPortal = BaseToast.Portal as React.ElementType + +export const ToastPortal = React.forwardRef( + ({ className, container, ...props }, ref) => { + const portalContainer = usePortalContainer() + + return ( + + ) + }, +) + +ToastPortal.displayName = "ToastPortal" diff --git a/src/components/ui/toast/positioner.tsx b/src/components/ui/toast/positioner.tsx new file mode 100644 index 0000000..0d694ba --- /dev/null +++ b/src/components/ui/toast/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastPositioner = BaseToast.Positioner as React.ElementType + +export const ToastPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastPositioner.displayName = "ToastPositioner" diff --git a/src/components/ui/toast/provider.tsx b/src/components/ui/toast/provider.tsx new file mode 100644 index 0000000..f7faf36 --- /dev/null +++ b/src/components/ui/toast/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastProvider = BaseToast.Provider as React.ElementType + +export const ToastProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastProvider.displayName = "ToastProvider" diff --git a/src/components/ui/toast/root.tsx b/src/components/ui/toast/root.tsx new file mode 100644 index 0000000..5deb2f0 --- /dev/null +++ b/src/components/ui/toast/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastRoot = BaseToast.Root as React.ElementType +const defaultToastRootClassName = + "border border-neutral-950 bg-white text-neutral-950 shadow-[0.25rem_0.25rem_0_rgb(0_0_0_/_12%)] select-none focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:-outline-offset-1 focus-visible:outline-neutral-950 dark:border-white dark:bg-neutral-950 dark:text-white dark:shadow-none" + +export const ToastRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastRoot.displayName = "ToastRoot" diff --git a/src/components/ui/toast/title.tsx b/src/components/ui/toast/title.tsx new file mode 100644 index 0000000..2eca064 --- /dev/null +++ b/src/components/ui/toast/title.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastTitleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastTitle = BaseToast.Title as React.ElementType + +export const ToastTitle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastTitle.displayName = "ToastTitle" diff --git a/src/components/ui/toast/viewport.tsx b/src/components/ui/toast/viewport.tsx new file mode 100644 index 0000000..fc967c7 --- /dev/null +++ b/src/components/ui/toast/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toast as BaseToast } from "@base-ui/react/toast" +import { cn } from "@/lib/utils" + +export type ToastViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToastViewport = BaseToast.Viewport as React.ElementType + +export const ToastViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToastViewport.displayName = "ToastViewport" diff --git a/src/components/ui/toggle-group/index.ts b/src/components/ui/toggle-group/index.ts new file mode 100644 index 0000000..053002a --- /dev/null +++ b/src/components/ui/toggle-group/index.ts @@ -0,0 +1,4 @@ +import { ToggleGroup } from "./root" + +export { ToggleGroup, type ToggleGroupProps } from "./root" +export default ToggleGroup diff --git a/src/components/ui/toggle-group/root.tsx b/src/components/ui/toggle-group/root.tsx new file mode 100644 index 0000000..db285d5 --- /dev/null +++ b/src/components/ui/toggle-group/root.tsx @@ -0,0 +1,22 @@ +"use client" + +import * as React from "react" +import { ToggleGroup as BaseToggleGroup } from "@base-ui/react/toggle-group" +import { cn } from "@/lib/utils" + +export type ToggleGroupProps = React.ComponentPropsWithoutRef & { className?: string } + +const BaseToggleGroupElement = BaseToggleGroup as React.ElementType +const defaultToggleGroupClassName = "flex gap-px border border-neutral-950 p-px dark:border-white" + +export const ToggleGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToggleGroup.displayName = "ToggleGroup" diff --git a/src/components/ui/toggle/index.ts b/src/components/ui/toggle/index.ts new file mode 100644 index 0000000..de64e1d --- /dev/null +++ b/src/components/ui/toggle/index.ts @@ -0,0 +1,4 @@ +import { Toggle } from "./root" + +export { Toggle, type ToggleProps } from "./root" +export default Toggle diff --git a/src/components/ui/toggle/root.tsx b/src/components/ui/toggle/root.tsx new file mode 100644 index 0000000..b9a0a4f --- /dev/null +++ b/src/components/ui/toggle/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toggle as BaseToggle } from "@base-ui/react/toggle" +import { cn } from "@/lib/utils" + +export type ToggleProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToggleElement = BaseToggle as React.ElementType +const defaultToggleClassName = + "flex size-8 items-center justify-center border-none rounded-none bg-transparent 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]):not([data-pressed]):active]:bg-neutral-200 dark:[&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-700 data-[pressed]:bg-neutral-950 data-[pressed]:text-white dark:data-[pressed]:bg-white dark:data-[pressed]:text-neutral-950 data-[pressed]:hover:bg-neutral-950 data-[pressed]:hover:text-white dark:data-[pressed]:hover:bg-white dark:data-[pressed]:hover:text-neutral-950 focus-visible:relative focus-visible:z-1 focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const Toggle = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +Toggle.displayName = "Toggle" diff --git a/src/components/ui/toolbar/button.tsx b/src/components/ui/toolbar/button.tsx new file mode 100644 index 0000000..49555e9 --- /dev/null +++ b/src/components/ui/toolbar/button.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarButtonProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarButton = BaseToolbar.Button as React.ElementType +const defaultToolbarButtonClassName = + "flex h-8 min-w-8 items-center justify-center gap-2 border-0 bg-transparent font-[inherit] text-sm leading-none whitespace-nowrap font-normal text-neutral-950 select-none [&:not([data-disabled]):hover]:bg-neutral-100 [&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-200 data-[pressed]:bg-neutral-950 data-[pressed]:text-white data-[pressed]:[&:not([data-disabled]):hover]:bg-neutral-950 data-[pressed]:[&:not([data-disabled]):hover]:text-white data-[popup-open]:!bg-neutral-100 data-[popup-open]:!text-neutral-950 dark:text-white dark:[&:not([data-disabled]):hover]:bg-neutral-800 dark:[&:not([data-disabled]):not([data-pressed]):active]:bg-neutral-700 dark:data-[pressed]:bg-white dark:data-[pressed]:text-neutral-950 dark:data-[pressed]:[&:not([data-disabled]):hover]:bg-white dark:data-[pressed]:[&:not([data-disabled]):hover]:text-neutral-950 dark:data-[popup-open]:!bg-neutral-800 dark:data-[popup-open]:!text-white focus-visible:bg-transparent focus-visible:outline-2 focus-visible:[outline-style:solid] focus-visible:outline-offset-1 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ToolbarButton = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarButton.displayName = "ToolbarButton" diff --git a/src/components/ui/toolbar/group.tsx b/src/components/ui/toolbar/group.tsx new file mode 100644 index 0000000..c6f0993 --- /dev/null +++ b/src/components/ui/toolbar/group.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarGroupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarGroup = BaseToolbar.Group as React.ElementType +const defaultToolbarGroupClassName = "flex gap-px" + +export const ToolbarGroup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarGroup.displayName = "ToolbarGroup" diff --git a/src/components/ui/toolbar/index.ts b/src/components/ui/toolbar/index.ts new file mode 100644 index 0000000..3ec94f7 --- /dev/null +++ b/src/components/ui/toolbar/index.ts @@ -0,0 +1,34 @@ +import { ToolbarSeparator } from "./separator" +import { ToolbarRoot } from "./root" +import { ToolbarGroup } from "./group" +import { ToolbarButton } from "./button" +import { ToolbarLink } from "./link" +import { ToolbarInput } from "./input" + +const ToolbarPrimitive = { + Separator: ToolbarSeparator, + Root: ToolbarRoot, + Group: ToolbarGroup, + Button: ToolbarButton, + Link: ToolbarLink, + Input: ToolbarInput, +} + +export default ToolbarPrimitive + +export { + ToolbarRoot as Toolbar, + ToolbarSeparator, + ToolbarRoot, + ToolbarGroup, + ToolbarButton, + ToolbarLink, + ToolbarInput, +} + +export type { ToolbarSeparatorProps } from "./separator" +export type { ToolbarRootProps } from "./root" +export type { ToolbarGroupProps } from "./group" +export type { ToolbarButtonProps } from "./button" +export type { ToolbarLinkProps } from "./link" +export type { ToolbarInputProps } from "./input" diff --git a/src/components/ui/toolbar/input.tsx b/src/components/ui/toolbar/input.tsx new file mode 100644 index 0000000..bbfcb4c --- /dev/null +++ b/src/components/ui/toolbar/input.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarInputProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarInput = BaseToolbar.Input as React.ElementType + +export const ToolbarInput = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarInput.displayName = "ToolbarInput" diff --git a/src/components/ui/toolbar/link.tsx b/src/components/ui/toolbar/link.tsx new file mode 100644 index 0000000..a458854 --- /dev/null +++ b/src/components/ui/toolbar/link.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarLinkProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarLink = BaseToolbar.Link as React.ElementType +const defaultToolbarLinkClassName = + "mr-[0.875rem] ml-auto flex-none self-center font-[inherit] text-sm text-neutral-500 no-underline hover:text-blue-700 dark:text-neutral-400 dark:hover:text-blue-500 focus-visible:outline-2 focus-visible:outline-neutral-950 dark:focus-visible:outline-white" + +export const ToolbarLink = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarLink.displayName = "ToolbarLink" diff --git a/src/components/ui/toolbar/root.tsx b/src/components/ui/toolbar/root.tsx new file mode 100644 index 0000000..40ee4c0 --- /dev/null +++ b/src/components/ui/toolbar/root.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarRoot = BaseToolbar.Root as React.ElementType +const defaultToolbarRootClassName = + "flex w-[37.5rem] items-center gap-px border border-neutral-950 bg-white p-px dark:border-white dark:bg-neutral-950" + +export const ToolbarRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarRoot.displayName = "ToolbarRoot" diff --git a/src/components/ui/toolbar/separator.tsx b/src/components/ui/toolbar/separator.tsx new file mode 100644 index 0000000..76a5c61 --- /dev/null +++ b/src/components/ui/toolbar/separator.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar" +import { cn } from "@/lib/utils" + +export type ToolbarSeparatorProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseToolbarSeparator = BaseToolbar.Separator as React.ElementType + +export const ToolbarSeparator = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +ToolbarSeparator.displayName = "ToolbarSeparator" diff --git a/src/components/ui/tooltip/arrow.tsx b/src/components/ui/tooltip/arrow.tsx new file mode 100644 index 0000000..79e6cb0 --- /dev/null +++ b/src/components/ui/tooltip/arrow.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipArrowProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipArrow = BaseTooltip.Arrow as React.ElementType + +export const TooltipArrow = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipArrow.displayName = "TooltipArrow" diff --git a/src/components/ui/tooltip/content.tsx b/src/components/ui/tooltip/content.tsx new file mode 100644 index 0000000..1248cbc --- /dev/null +++ b/src/components/ui/tooltip/content.tsx @@ -0,0 +1,21 @@ +"use client" + +import * as React from "react" +import { cn } from "@/lib/utils" +import { TooltipPortal } from "./portal" +import { TooltipPositioner } from "./positioner" +import { TooltipPopup, type TooltipPopupProps } from "./popup" + +export type TooltipContentProps = TooltipPopupProps + +export const TooltipContent = React.forwardRef( + ({ className, ...props }, ref) => ( + + + + + + ), +) + +TooltipContent.displayName = "TooltipContent" diff --git a/src/components/ui/tooltip/index.ts b/src/components/ui/tooltip/index.ts new file mode 100644 index 0000000..5f94b79 --- /dev/null +++ b/src/components/ui/tooltip/index.ts @@ -0,0 +1,48 @@ +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { TooltipRoot } from "./root" +import { TooltipTrigger } from "./trigger" +import { TooltipPortal } from "./portal" +import { TooltipPositioner } from "./positioner" +import { TooltipPopup } from "./popup" +import { TooltipArrow } from "./arrow" +import { TooltipProvider } from "./provider" +import { TooltipViewport } from "./viewport" +import { TooltipContent } from "./content" + +const TooltipPrimitive = { + Root: TooltipRoot, + Trigger: TooltipTrigger, + Portal: TooltipPortal, + Positioner: TooltipPositioner, + Popup: TooltipPopup, + Arrow: TooltipArrow, + Provider: TooltipProvider, + Viewport: TooltipViewport, + createHandle: BaseTooltip.createHandle, +} + +export default TooltipPrimitive + +export { + TooltipRoot as Tooltip, + TooltipRoot, + TooltipTrigger, + TooltipPortal, + TooltipPositioner, + TooltipPopup, + TooltipArrow, + TooltipProvider, + TooltipViewport, + TooltipContent, + BaseTooltip, +} + +export type { TooltipRootProps } from "./root" +export type { TooltipTriggerProps } from "./trigger" +export type { TooltipPortalProps } from "./portal" +export type { TooltipPositionerProps } from "./positioner" +export type { TooltipPopupProps } from "./popup" +export type { TooltipArrowProps } from "./arrow" +export type { TooltipProviderProps } from "./provider" +export type { TooltipViewportProps } from "./viewport" +export type { TooltipContentProps } from "./content" diff --git a/src/components/ui/tooltip/popup.tsx b/src/components/ui/tooltip/popup.tsx new file mode 100644 index 0000000..75b58a0 --- /dev/null +++ b/src/components/ui/tooltip/popup.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPopupProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPopup = BaseTooltip.Popup as React.ElementType + +export const TooltipPopup = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPopup.displayName = "TooltipPopup" diff --git a/src/components/ui/tooltip/portal.tsx b/src/components/ui/tooltip/portal.tsx new file mode 100644 index 0000000..41f7e1e --- /dev/null +++ b/src/components/ui/tooltip/portal.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPortalProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPortal = BaseTooltip.Portal as React.ElementType + +export const TooltipPortal = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPortal.displayName = "TooltipPortal" diff --git a/src/components/ui/tooltip/positioner.tsx b/src/components/ui/tooltip/positioner.tsx new file mode 100644 index 0000000..4de534e --- /dev/null +++ b/src/components/ui/tooltip/positioner.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipPositionerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipPositioner = BaseTooltip.Positioner as React.ElementType + +export const TooltipPositioner = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipPositioner.displayName = "TooltipPositioner" diff --git a/src/components/ui/tooltip/provider.tsx b/src/components/ui/tooltip/provider.tsx new file mode 100644 index 0000000..3ff755b --- /dev/null +++ b/src/components/ui/tooltip/provider.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipProviderProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipProvider = BaseTooltip.Provider as React.ElementType + +export const TooltipProvider = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipProvider.displayName = "TooltipProvider" diff --git a/src/components/ui/tooltip/root.tsx b/src/components/ui/tooltip/root.tsx new file mode 100644 index 0000000..df9e528 --- /dev/null +++ b/src/components/ui/tooltip/root.tsx @@ -0,0 +1,23 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipRootProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipRoot = BaseTooltip.Root as React.ElementType + +export const TooltipRoot = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipRoot.displayName = "TooltipRoot" diff --git a/src/components/ui/tooltip/trigger.tsx b/src/components/ui/tooltip/trigger.tsx new file mode 100644 index 0000000..5b61d5b --- /dev/null +++ b/src/components/ui/tooltip/trigger.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipTriggerProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipTrigger = BaseTooltip.Trigger as React.ElementType + +export const TooltipTrigger = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipTrigger.displayName = "TooltipTrigger" diff --git a/src/components/ui/tooltip/viewport.tsx b/src/components/ui/tooltip/viewport.tsx new file mode 100644 index 0000000..2c89f63 --- /dev/null +++ b/src/components/ui/tooltip/viewport.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip" +import { cn } from "@/lib/utils" + +export type TooltipViewportProps = React.ComponentPropsWithoutRef & { + className?: string +} + +const BaseTooltipViewport = BaseTooltip.Viewport as React.ElementType + +export const TooltipViewport = React.forwardRef( + ({ className, ...props }, ref) => ( + + ), +) + +TooltipViewport.displayName = "TooltipViewport" diff --git a/src/lib/portal-container.tsx b/src/lib/portal-container.tsx new file mode 100644 index 0000000..6295e50 --- /dev/null +++ b/src/lib/portal-container.tsx @@ -0,0 +1,25 @@ +"use client" + +import * as React from "react" + +type PortalContainer = React.RefObject + +const PortalContainerContext = React.createContext(null) + +export function PortalContainerProvider({ + children, + container, +}: { + children: React.ReactNode + container: PortalContainer +}) { + return ( + + {children} + + ) +} + +export function usePortalContainer() { + return React.useContext(PortalContainerContext) +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/styles/globals.css b/src/styles/globals.css new file mode 100644 index 0000000..96865d3 --- /dev/null +++ b/src/styles/globals.css @@ -0,0 +1,98 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +@utility no-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; + + &::-webkit-scrollbar { + display: none; + } +} + +@custom-variant data-open { + &:where([data-state="open"]), + &:where([data-open]:not([data-open="false"])) { + @slot; + } +} + +@custom-variant data-closed { + &:where([data-state="closed"]), + &:where([data-closed]:not([data-closed="false"])) { + @slot; + } +} + +@custom-variant data-checked { + &:where([data-state="checked"]), + &:where([data-checked]:not([data-checked="false"])) { + @slot; + } +} + +@custom-variant data-unchecked { + &:where([data-state="unchecked"]), + &:where([data-unchecked]:not([data-unchecked="false"])) { + @slot; + } +} + +@custom-variant data-selected { + &:where([data-selected="true"]) { + @slot; + } +} + +@custom-variant data-disabled { + &:where([data-disabled="true"]), + &:where([data-disabled]:not([data-disabled="false"])) { + @slot; + } +} + +@custom-variant data-active { + &:where([data-state="active"]), + &:where([data-active]:not([data-active="false"])) { + @slot; + } +} + +@custom-variant data-horizontal { + &:where([data-orientation="horizontal"]) { + @slot; + } +} + +@custom-variant data-vertical { + &:where([data-orientation="vertical"]) { + @slot; + } +} + +@theme inline { + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +:root { + --radius: 0.625rem; +} + +.dark {} + +@layer base { + /** { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + }*/ +}