From 5012094a5b8261531a58b32f7fe3bf125553acac Mon Sep 17 00:00:00 2001 From: Zach <86675944+zwgnr@users.noreply.github.com> Date: Sun, 5 Oct 2025 23:19:45 -0400 Subject: [PATCH] fixes --- packages/components/registry.json | 26 + .../components/scripts/gen-registry-json.ts | 1 + web/app/llms.txt/route.ts | 4 +- web/app/r/[...segments]/route.ts | 45 - web/app/r/[[...segments]]/route.ts | 2 +- web/components/component-metadata.tsx | 2 +- web/lib/component-data.ts | 2 +- web/public/r/accordion.json | 3 +- web/public/r/badge.json | 3 +- web/public/r/breadcrumbs.json | 3 +- web/public/r/button.json | 3 +- web/public/r/calendar.json | 3 +- web/public/r/card.json | 3 +- web/public/r/checkbox.json | 3 +- web/public/r/combobox.json | 3 +- web/public/r/command.json | 3 +- web/public/r/date-field.json | 3 +- web/public/r/date-picker.json | 3 +- web/public/r/index.json | 1044 ----------------- web/public/r/input.json | 3 +- web/public/r/menu.json | 3 +- web/public/r/meter.json | 3 +- web/public/r/modal.json | 3 +- web/public/r/popover.json | 3 +- web/public/r/radio-group.json | 5 +- web/public/r/registry.json | 26 + web/public/r/select.json | 3 +- web/public/r/slider.json | 3 +- web/public/r/switch.json | 3 +- web/public/r/table.json | 3 +- web/public/r/tabs.json | 3 +- web/public/r/tag-group.json | 3 +- web/public/r/time-field.json | 3 +- web/public/r/toggle.json | 3 +- web/public/r/tooltip.json | 3 +- 35 files changed, 111 insertions(+), 1121 deletions(-) delete mode 100644 web/app/r/[...segments]/route.ts delete mode 100644 web/public/r/index.json diff --git a/packages/components/registry.json b/packages/components/registry.json index 5a78a29..b2ba251 100644 --- a/packages/components/registry.json +++ b/packages/components/registry.json @@ -15,6 +15,7 @@ "files": [ { "path": "src/core/accordion/accordion.tsx", + "target": "components/ui/accordion.tsx", "type": "registry:component" } ], @@ -109,6 +110,7 @@ "files": [ { "path": "src/core/badge/badge.tsx", + "target": "components/ui/badge.tsx", "type": "registry:component" } ], @@ -200,6 +202,7 @@ "files": [ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", + "target": "components/ui/breadcrumbs.tsx", "type": "registry:component" } ], @@ -291,6 +294,7 @@ "files": [ { "path": "src/core/button/button.tsx", + "target": "components/ui/button.tsx", "type": "registry:component" } ], @@ -383,6 +387,7 @@ "files": [ { "path": "src/core/calendar/calendar.tsx", + "target": "components/ui/calendar.tsx", "type": "registry:component" } ], @@ -476,6 +481,7 @@ "files": [ { "path": "src/core/card/card.tsx", + "target": "components/ui/card.tsx", "type": "registry:component" } ], @@ -569,6 +575,7 @@ "files": [ { "path": "src/core/checkbox/checkbox.tsx", + "target": "components/ui/checkbox.tsx", "type": "registry:component" } ], @@ -661,6 +668,7 @@ "files": [ { "path": "src/core/combobox/combobox.tsx", + "target": "components/ui/combobox.tsx", "type": "registry:component" } ], @@ -754,6 +762,7 @@ "files": [ { "path": "src/core/command/command.tsx", + "target": "components/ui/command.tsx", "type": "registry:component" } ], @@ -848,6 +857,7 @@ "files": [ { "path": "src/core/date-field/date-field.tsx", + "target": "components/ui/date-field.tsx", "type": "registry:component" } ], @@ -941,6 +951,7 @@ "files": [ { "path": "src/core/date-picker/date-picker.tsx", + "target": "components/ui/date-picker.tsx", "type": "registry:component" } ], @@ -1037,6 +1048,7 @@ "files": [ { "path": "src/core/input/input.tsx", + "target": "components/ui/input.tsx", "type": "registry:component" } ], @@ -1129,6 +1141,7 @@ "files": [ { "path": "src/core/menu/menu.tsx", + "target": "components/ui/menu.tsx", "type": "registry:component" } ], @@ -1221,6 +1234,7 @@ "files": [ { "path": "src/core/meter/meter.tsx", + "target": "components/ui/meter.tsx", "type": "registry:component" } ], @@ -1313,6 +1327,7 @@ "files": [ { "path": "src/core/modal/modal.tsx", + "target": "components/ui/modal.tsx", "type": "registry:component" } ], @@ -1404,6 +1419,7 @@ "files": [ { "path": "src/core/popover/popover.tsx", + "target": "components/ui/popover.tsx", "type": "registry:component" } ], @@ -1496,6 +1512,7 @@ "files": [ { "path": "src/core/radio-group/radio-group.tsx", + "target": "components/ui/radio-group.tsx", "type": "registry:component" } ], @@ -1589,6 +1606,7 @@ "files": [ { "path": "src/core/select/select.tsx", + "target": "components/ui/select.tsx", "type": "registry:component" } ], @@ -1682,6 +1700,7 @@ "files": [ { "path": "src/core/slider/slider.tsx", + "target": "components/ui/slider.tsx", "type": "registry:component" } ], @@ -1775,6 +1794,7 @@ "files": [ { "path": "src/core/switch/switch.tsx", + "target": "components/ui/switch.tsx", "type": "registry:component" } ], @@ -1868,6 +1888,7 @@ "files": [ { "path": "src/core/table/table.tsx", + "target": "components/ui/table.tsx", "type": "registry:component" } ], @@ -1964,6 +1985,7 @@ "files": [ { "path": "src/core/tabs/tabs.tsx", + "target": "components/ui/tabs.tsx", "type": "registry:component" } ], @@ -2057,6 +2079,7 @@ "files": [ { "path": "src/core/tag-group/tag-group.tsx", + "target": "components/ui/tag-group.tsx", "type": "registry:component" } ], @@ -2151,6 +2174,7 @@ "files": [ { "path": "src/core/time-field/time-field.tsx", + "target": "components/ui/time-field.tsx", "type": "registry:component" } ], @@ -2244,6 +2268,7 @@ "files": [ { "path": "src/core/toggle/toggle.tsx", + "target": "components/ui/toggle.tsx", "type": "registry:component" } ], @@ -2337,6 +2362,7 @@ "files": [ { "path": "src/core/tooltip/tooltip.tsx", + "target": "components/ui/tooltip.tsx", "type": "registry:component" } ], diff --git a/packages/components/scripts/gen-registry-json.ts b/packages/components/scripts/gen-registry-json.ts index f730b73..40f3fa7 100644 --- a/packages/components/scripts/gen-registry-json.ts +++ b/packages/components/scripts/gen-registry-json.ts @@ -100,6 +100,7 @@ async function processComponent( files: [ { path: `src/core/${componentId}/${componentId}.tsx`, + target: `components/ui/${componentId}.tsx`, type: "registry:component", }, ], diff --git a/web/app/llms.txt/route.ts b/web/app/llms.txt/route.ts index cf1a07d..186c45d 100644 --- a/web/app/llms.txt/route.ts +++ b/web/app/llms.txt/route.ts @@ -10,7 +10,7 @@ interface RegistryItem { export async function GET() { // Read the shadcn registry - const registryPath = join(process.cwd(), "public/r/index.json"); + const registryPath = join(process.cwd(), "public/r/registry.json"); const registry = JSON.parse(readFileSync(registryPath, "utf8")); const components = registry.items; @@ -138,7 +138,7 @@ This returns the complete component definition with source code in the \`files[] ## Registry Endpoints -- \`GET /r/index.json\` - List all components with metadata +- \`GET /r/registry.json\` - List all components with metadata - \`GET /r/{component}.json\` - Get specific component with full source code ## Additional Resources diff --git a/web/app/r/[...segments]/route.ts b/web/app/r/[...segments]/route.ts deleted file mode 100644 index c59ecaf..0000000 --- a/web/app/r/[...segments]/route.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { NextResponse } from "next/server"; - -import { existsSync, readFileSync } from "node:fs"; -import { join } from "node:path"; - -export async function GET( - _request: Request, - { params }: { params: Promise<{ segments?: string[] }> }, -) { - try { - const { segments } = await params; - - // If no segments, return the registry index - if (!segments || segments.length === 0) { - const registryPath = join(process.cwd(), "public/r/index.json"); - const registryContent = readFileSync(registryPath, "utf8"); - return new NextResponse(registryContent, { - headers: { - "Content-Type": "application/json", - "Cache-Control": "public, max-age=3600", - }, - }); - } - - // Handle specific registry item requests - // Support both /r/button and /r/button.json - const itemName = segments[0].replace(/\.json$/, ""); - const itemPath = join(process.cwd(), `public/r/${itemName}.json`); - - if (!existsSync(itemPath)) { - return new NextResponse("Registry item not found", { status: 404 }); - } - - const itemContent = readFileSync(itemPath, "utf8"); - return new NextResponse(itemContent, { - headers: { - "Content-Type": "application/json", - "Cache-Control": "public, max-age=3600", - }, - }); - } catch (error) { - console.error("Error in registry API route:", error); - return new NextResponse("Internal Server Error", { status: 500 }); - } -} diff --git a/web/app/r/[[...segments]]/route.ts b/web/app/r/[[...segments]]/route.ts index c59ecaf..f172a3d 100644 --- a/web/app/r/[[...segments]]/route.ts +++ b/web/app/r/[[...segments]]/route.ts @@ -12,7 +12,7 @@ export async function GET( // If no segments, return the registry index if (!segments || segments.length === 0) { - const registryPath = join(process.cwd(), "public/r/index.json"); + const registryPath = join(process.cwd(), "public/r/registry.json"); const registryContent = readFileSync(registryPath, "utf8"); return new NextResponse(registryContent, { headers: { diff --git a/web/components/component-metadata.tsx b/web/components/component-metadata.tsx index c82ff4f..860c502 100644 --- a/web/components/component-metadata.tsx +++ b/web/components/component-metadata.tsx @@ -32,7 +32,7 @@ export async function ComponentMetadata({ showTags = false, }: ComponentMetadataProps) { // Read from shadcn registry for metadata - const shadcnRegistryPath = join(process.cwd(), "public/r/index.json"); + const shadcnRegistryPath = join(process.cwd(), "public/r/registry.json"); const shadcnRegistryContent = readFileSync(shadcnRegistryPath, "utf8"); const shadcnRegistry = JSON.parse(shadcnRegistryContent); diff --git a/web/lib/component-data.ts b/web/lib/component-data.ts index 38995a0..2fc2d83 100644 --- a/web/lib/component-data.ts +++ b/web/lib/component-data.ts @@ -8,7 +8,7 @@ const examplesDir = join(process.cwd(), "../packages/components/src/examples"); export async function getComponentSource(name: string): Promise { try { // Read the shadcn registry - const shadcnRegistryPath = join(process.cwd(), "public/r/index.json"); + const shadcnRegistryPath = join(process.cwd(), "public/r/registry.json"); const shadcnRegistryContent = readFileSync(shadcnRegistryPath, "utf8"); const shadcnRegistry = JSON.parse(shadcnRegistryContent); diff --git a/web/public/r/accordion.json b/web/public/r/accordion.json index a7c8f2c..05fde01 100644 --- a/web/public/r/accordion.json +++ b/web/public/r/accordion.json @@ -15,7 +15,8 @@ { "path": "src/core/accordion/accordion.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tButton,\n\tDisclosure,\n\tDisclosureGroup,\n\ttype DisclosureGroupProps,\n\tDisclosurePanel,\n\ttype DisclosureProps,\n\tHeading,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { Minus, Plus } from \"lucide-react\";\n\nconst accordion = tv({\n\tslots: {\n\t\troot: \"group w-full\",\n\t\tgroup: \"flex flex-col gap-3\",\n\t\tbutton:\n\t\t\t\"flex w-full items-center justify-between gap-6 rounded-2xl border border-border bg-surface-2 p-4 data-[focus-visible]:outline-none data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 data-[focus-visible]:ring-offset-surface group-data-[expanded]:rounded-b-none group-data-[expanded]:border-b-0\",\n\t\ticon: \"size-4 shrink-0 fill-none transition-transform duration-200\",\n\t\tpanel:\n\t\t\t\"rounded-b-2xl border-border bg-surface-2 px-4 text-muted-foreground text-sm group-data-[expanded]:border-x group-data-[expanded]:border-b group-data-[expanded]:pb-4\",\n\t},\n});\n\nconst styles = accordion();\n\ntype AccordionVariantProps = VariantProps;\n\ninterface AccordionProps\n\textends AccordionVariantProps,\n\t\tOmit {\n\tclassName?: string;\n\ttitle?: string;\n\tchildren?: ReactNode;\n}\n\nconst Accordion = ({\n\tclassName,\n\ttitle,\n\tchildren,\n\t...props\n}: AccordionProps) => {\n\treturn (\n\t\t\n\t\t\t{({ isExpanded }) => (\n\t\t\t\t<>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{children}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t);\n};\n\ninterface AccordionGroupProps extends DisclosureGroupProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst AccordionGroup = ({\n\tclassName,\n\tchildren,\n\t...props\n}: AccordionGroupProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Accordion, AccordionGroup };\nexport type { AccordionProps, AccordionGroupProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/accordion.tsx" } ], "tailwind": { diff --git a/web/public/r/badge.json b/web/public/r/badge.json index 7735934..afa1e75 100644 --- a/web/public/r/badge.json +++ b/web/public/r/badge.json @@ -15,7 +15,8 @@ { "path": "src/core/badge/badge.tsx", "content": "import type { HTMLAttributes } from \"react\";\n\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const badge = tv({\n\tbase: \"flex items-center justify-center rounded-4xl px-3 py-2 font-semibold text-xs\",\n\tvariants: {\n\t\tvariant: {\n\t\t\tattention: \"bg-gradient-to-r from-pink-500 to-purple-500 text-white\",\n\t\t\tneutral: \"bg-secondary text-secondary-fg\",\n\t\t\tdanger: \"bg-danger text-danger-fg\",\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"attention\",\n\t},\n});\n\ntype BadgeProps = VariantProps & HTMLAttributes;\n\nconst Badge = ({ className, variant, ...props }: BadgeProps) => (\n\t\n);\n\nexport { Badge };\nexport type { BadgeProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/badge.tsx" } ], "tailwind": { diff --git a/web/public/r/breadcrumbs.json b/web/public/r/breadcrumbs.json index 3155025..b68ade7 100644 --- a/web/public/r/breadcrumbs.json +++ b/web/public/r/breadcrumbs.json @@ -15,7 +15,8 @@ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", "content": "\"use client\";\n\nimport {\n\tBreadcrumbs as AriaBreadcrumbs,\n\ttype BreadcrumbsProps as AriaBreadcrumbsProps,\n\tBreadcrumb,\n\ttype BreadcrumbProps,\n\tLink,\n\ttype LinkProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst breadcrumbs = tv({\n\tslots: {\n\t\troot: \"m-0 flex list-none items-center gap-2 p-0 font-md\",\n\t\tlink: \"relative cursor-pointer rounded-md text-fg outline-none ring-focus data-[hovered]:underline data-[focus-visible]:ring-2 [&[aria-current]]:font-extrabold [&[aria-current]]:text-fg\",\n\t\titem: \"flex items-center gap-2\",\n\t},\n});\n\nconst styles = breadcrumbs();\n\nconst Breadcrumbs = ({\n\tchildren,\n\tclassName,\n\t...props\n}: AriaBreadcrumbsProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst BreadcrumbsLink = ({\n\tchildren,\n\tclassName,\n\t...props\n}: LinkProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst BreadcrumbsItem = ({\n\tchildren,\n\tclassName,\n\t...props\n}: BreadcrumbProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { BreadcrumbsItem, BreadcrumbsLink, Breadcrumbs };", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/breadcrumbs.tsx" } ], "tailwind": { diff --git a/web/public/r/button.json b/web/public/r/button.json index 8c3cea1..cdb6b88 100644 --- a/web/public/r/button.json +++ b/web/public/r/button.json @@ -15,7 +15,8 @@ { "path": "src/core/button/button.tsx", "content": "\"use client\";\n\nimport {\n\tButton as AriaButton,\n\ttype ButtonProps as AriaButtonProps,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nconst button = tv({\n\tbase: \"inline-flex appearance-none items-center justify-center rounded-full font-semibold outline-none ring-focus ring-offset-3 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[focus-visible]:ring-2\",\n\tvariants: {\n\t\tvariant: {\n\t\t\tprimary:\n\t\t\t\t\"bg-primary text-primary-fg data-[hovered]:bg-primary/80\",\n\t\t\tsecondary:\n\t\t\t\t\"border border-border text-fg data-[hovered]:border-secondary data-[hovered]:bg-secondary\",\n\t\t\tghost:\n\t\t\t\t\"bg-transparent text-fg data-[hovered]:bg-secondary data-[hovered]:text-secondary-fg\",\n\t\t\tdanger:\n\t\t\t\t\"border border-transparent bg-danger text-danger-fg data-[hovered]:bg-danger/80\",\n\t\t},\n\t\tsize: {\n\t\t\tsm: \"px-2 py-1.5 text-sm\",\n\t\t\tmd: \"px-4 py-2.5 text-base\",\n\t\t\tlg: \"px-6 py-3.5 font-bold text-lg\",\n\t\t\ticon: \"size-9\",\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"primary\",\n\t\tsize: \"md\",\n\t},\n});\n\ntype ButtonVariantProps = VariantProps;\n\ninterface ButtonProps\n\textends Omit,\n\t\tButtonVariantProps {\n\tclassName?: string;\n}\n\nconst Button = ({\n\tclassName,\n\tsize,\n\tvariant,\n\tchildren,\n\t...props\n}: ButtonProps) => (\n\t\n\t\t{children}\n\t\n);\n\nButton.displayName = \"Button\";\n\nexport { Button };\nexport type { ButtonProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/button.tsx" } ], "tailwind": { diff --git a/web/public/r/calendar.json b/web/public/r/calendar.json index e9a465e..4681d64 100644 --- a/web/public/r/calendar.json +++ b/web/public/r/calendar.json @@ -15,7 +15,8 @@ { "path": "src/core/calendar/calendar.tsx", "content": "\"use client\";\n\nimport {\n\tCalendar as AriaCalendar,\n\ttype CalendarProps as AriaCalendarProps,\n\tRangeCalendar as AriaRangeCalendar,\n\ttype RangeCalendarProps as AriaRangeCalendarProps,\n\tButton,\n\tCalendarCell,\n\tCalendarGrid,\n\tCalendarGridBody,\n\tCalendarGridHeader,\n\tCalendarHeaderCell,\n\ttype DateValue,\n\tHeading,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\nconst baseStyles = tv({\n\tslots: {\n\t\troot: \"w-fit max-w-full rounded-2xl border border-border bg-surface p-4 text-fg\",\n\t\theader: \"flex w-full items-center gap-1 pb-4\",\n\t\theading: \"flex-1 text-center font-bold\",\n\t\theaderCell: \"pb-2 text-fg-muted text-sm\",\n\t\tmonthButton:\n\t\t\t\"flex appearance-none items-center justify-center rounded-full p-2 text-center outline-none ring-focus data-[hovered]:bg-secondary data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst calendar = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tcell: \"flex size-9 cursor-default items-center justify-center rounded-full border-border text-center text-sm outline-focus outline-offset-2 data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:outline-2 data-[focus-visible]:outline-focus [&[data-outside-month]]:hidden\",\n\t},\n});\n\nconst rangeCalendar = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tcell: \"flex size-9 cursor-default items-center justify-center rounded-full text-center text-sm outline-none outline-offset-2 data-[selected]:rounded-none data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 [&[data-outside-month]]:hidden [&[data-selection-end]]:rounded-r-full [&[data-selection-start]]:rounded-l-full\",\n\t},\n});\n\nconst styles = calendar();\nconst rangeStyles = rangeCalendar();\n\ninterface CalendarProps\n\textends Omit, \"className\"> {\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst Calendar = ({\n\tclassName,\n\terrorMessage,\n\t...props\n}: CalendarProps) => (\n\t\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\n\t\t\t\n\t\t\t\t{(day) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{day}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{(date) => }\n\t\t\t\n\t\t\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t
\n);\n\ninterface RangeCalendarProps\n\textends Omit, \"className\"> {\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst RangeCalendar = ({\n\tclassName,\n\terrorMessage,\n\t...props\n}: RangeCalendarProps) => (\n\t\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\n\t\t\t\n\t\t\t\t{(day) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{day}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{(date) => }\n\t\t\t\n\t\t\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t
\n);\n\nexport { Calendar, RangeCalendar };\nexport type { CalendarProps, RangeCalendarProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/calendar.tsx" } ], "tailwind": { diff --git a/web/public/r/card.json b/web/public/r/card.json index 5e1477a..27215a9 100644 --- a/web/public/r/card.json +++ b/web/public/r/card.json @@ -15,7 +15,8 @@ { "path": "src/core/card/card.tsx", "content": "\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\n\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nconst card = tv({\n\tslots: {\n\t\troot: \"rounded-2xl border-2 bg-surface text-fg\",\n\t\theader: \"flex flex-col space-y-1.5 p-6\",\n\t\ttitle: \"font-semibold text-2xl leading-none tracking-tight\",\n\t\tdescription: \"text-fg-muted text-sm\",\n\t\tcontent: \"p-6 pt-0\",\n\t\tfooter: \"flex items-center p-6 pt-0\",\n\t},\n\tvariants: {\n\t\tvariant: {\n\t\t\toutlined: {\n\t\t\t\troot: \"border border-border/50\",\n\t\t\t},\n\t\t\tfilled: {\n\t\t\t\troot: \"border-surface-2 bg-surface-2\",\n\t\t\t},\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"outlined\",\n\t},\n});\n\nconst styles = card();\n\ntype CardVariantProps = VariantProps;\n\ninterface CardProps extends HTMLAttributes, CardVariantProps {\n\tclassName?: string;\n\ttitle?: string;\n\tdescription?: string;\n}\n\ninterface CardHeaderProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\ninterface CardContentProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\ninterface CardFooterProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\nconst Card = ({\n\tclassName,\n\tvariant,\n\ttitle,\n\tdescription,\n\tchildren,\n\t...props\n}: CardProps) => (\n\t
\n\t\t{(title || description) && (\n\t\t\t
\n\t\t\t\t{title &&

{title}

}\n\t\t\t\t{description &&

{description}

}\n\t\t\t
\n\t\t)}\n\t\t{children}\n\t
\n);\n\nconst CardHeader = ({ className, ...props }: CardHeaderProps) => (\n\t
\n);\n\nconst CardContent = ({ className, ...props }: CardContentProps) => (\n\t
\n);\n\nconst CardFooter = ({ className, ...props }: CardFooterProps) => (\n\t
\n);\n\nexport { Card, CardHeader, CardContent, CardFooter };\nexport type { CardProps, CardHeaderProps, CardContentProps, CardFooterProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/card.tsx" } ], "tailwind": { diff --git a/web/public/r/checkbox.json b/web/public/r/checkbox.json index 1464c4d..1f8ad58 100644 --- a/web/public/r/checkbox.json +++ b/web/public/r/checkbox.json @@ -15,7 +15,8 @@ { "path": "src/core/checkbox/checkbox.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\ttype CheckboxProps as AriaCheckBoxProps,\n\tCheckbox as AriaCheckbox,\n\tCheckboxGroup as AriaCheckboxGroup,\n\ttype CheckboxGroupProps as AriaCheckboxGroupProps,\n\tFieldError,\n\tText,\n\ttype ValidationResult,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { Check } from \"lucide-react\";\n\nconst checkbox = tv({\n\tbase: \"group flex items-center justify-center gap-2 py-1 text-fg\",\n});\n\nconst checkboxGroup = tv({\n\tbase: \"flex flex-col gap-2\",\n});\n\ntype CheckboxVariantProps = VariantProps;\n\ninterface CheckboxProps extends CheckboxVariantProps, AriaCheckBoxProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst Checkbox = ({\n\tclassName,\n\terrorMessage,\n\tchildren,\n\tdescription,\n\t...props\n}: CheckboxProps) => {\n\treturn (\n\t\t\n\t\t\t{({ isSelected }) => (\n\t\t\t\t<>\n\t\t\t\t\t
\n\t\t\t\t\t\t{isSelected && }\n\t\t\t\t\t
\n\t\t\t\t\t{children}\n\t\t\t\t\t{description && (\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\n\t\t\t\t\t)}\n\t\t\t\t\t\n\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t
\n\t);\n};\n\ninterface CheckboxGroupProps extends AriaCheckboxGroupProps {\n\tclassName?: string;\n\tlabel?: string;\n\tchildren: ReactNode;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst CheckboxGroup = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: CheckboxGroupProps) => (\n\t\n\t\t{label && (\n\t\t\t\n\t\t\t\t{label}\n\t\t\t\n\t\t)}\n\t\t{children}\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { Checkbox, CheckboxGroup };\nexport type { CheckboxProps, CheckboxGroupProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/checkbox.tsx" } ], "tailwind": { diff --git a/web/public/r/combobox.json b/web/public/r/combobox.json index b77e314..3a883a1 100644 --- a/web/public/r/combobox.json +++ b/web/public/r/combobox.json @@ -15,7 +15,8 @@ { "path": "src/core/combobox/combobox.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tComboBox as AriaComboBox,\n\ttype ComboBoxProps as AriaComboBoxProps,\n\tButton,\n\tFieldError,\n\tInput,\n\tLabel,\n\tListBox,\n\tListBoxItem,\n\ttype ListBoxItemProps,\n\tPopover,\n\tText,\n\ttype ValidationResult,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CheckIcon, ChevronsUpDown } from \"lucide-react\";\n\nconst combobox = tv({\n\tslots: {\n\t\troot: \"group max-h-inherit w-full overflow-auto p-1 outline-none\",\n\t\tinput:\n\t\t\t\"w-full rounded-lg border border-border bg-surface px-4 py-1.5 align-middle font-semibold text-fg outline-none ring-fg transition-all group-data-[focused]:border-transparent group-data-[focused]:bg-surface group-data-[focused]:ring-2\",\n\t\tbutton:\n\t\t\t\"absolute right-2 flex appearance-none items-center justify-center rounded-full border-0 outline-none ring-focus ring-offset-2 ring-offset-surface data-[focus-visible]:ring-2\",\n\t\tpopover:\n\t\t\t\"w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none\",\n\t\titem: \"relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t},\n});\n\nconst styles = combobox();\n\ninterface ComboBoxProps\n\textends Omit, \"className\"> {\n\tclassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst ComboBox = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: ComboBoxProps) => (\n\t\n\t\t{label && }\n\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\ninterface ComboBoxItemProps\n\textends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst ComboBoxItem = ({ className, ...props }: ComboBoxItemProps) => (\n\t\n\t\t{({ isSelected }) => (\n\t\t\t
\n\t\t\t\t{props.children}\n\t\t\t\t{isSelected && }\n\t\t\t
\n\t\t)}\n\t
\n);\n\nexport { ComboBox, ComboBoxItem };\nexport type { ComboBoxProps, ListBoxItemProps as ComboBoxItemProps };", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/combobox.tsx" } ], "tailwind": { diff --git a/web/public/r/command.json b/web/public/r/command.json index f1217ed..6abf631 100644 --- a/web/public/r/command.json +++ b/web/public/r/command.json @@ -15,7 +15,8 @@ { "path": "src/core/command/command.tsx", "content": "\"use client\";\n\nimport type { ComponentType, ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\n\nimport {\n\tButton as AriaButton,\n\tDialog as AriaDialog,\n\tDialogTrigger as AriaDialogTrigger,\n\tModal as AriaModal,\n\tAutocomplete,\n\tInput,\n\tMenu,\n\tMenuItem,\n\ttype MenuItemProps,\n\tModalOverlay,\n\ttype ModalOverlayProps,\n\tTextField,\n\tuseFilter,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Search } from \"lucide-react\";\n\nconst command = tv({\n\tslots: {\n\t\ttrigger:\n\t\t\t\"flex w-full items-center justify-between rounded-full bg-secondary px-4 py-2 font-semibold text-fg outline-none ring-primary ring-offset-2 ring-offset-surface transition-colors data-[hovered]:bg-secondary/75 data-[focus-visible]:ring-2\",\n\t\toverlay:\n\t\t\t\"data-[entering]:fade-in data-[exiting]:fade-out fixed inset-0 z-50 flex min-h-full items-start justify-center bg-zinc-500/25 p-4 text-center data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200 sm:items-center\",\n\t\tmodal:\n\t\t\t\"data-[entering]:zoom-in-95 data-[exiting]:zoom-out-95 data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200\",\n\t\tdialog:\n\t\t\t\"flex min-h-96 min-w-80 max-w-full flex-col gap-1 rounded-2xl bg-surface p-2 shadow-lg outline-none md:w-lg\",\n\t\tinput:\n\t\t\t\"rounded-lg border-b-2 border-none bg-transparent px-3 py-2 text-base text-fg leading-5 outline-none placeholder:text-fg-muted\",\n\t\tmenu: \"mt-2 h-80 overflow-auto\",\n\t\titem: \"group flex min-h-12 w-full cursor-default items-center rounded-lg px-3 py-2 text-fg outline-none data-[focused]:bg-secondary data-[pressed]:bg-surface-3 data-[focused]:text-focus-fg\",\n\t\tkbd: \"ml-auto rounded border border-border bg-surface-2 px-2 py-1 font-semibold text-fg-muted text-xs\",\n\t},\n});\n\nconst styles = command();\n\ninterface CommandItem {\n\tid: string;\n\tlabel: string;\n\tshortcut?: string;\n\ticon?: ComponentType<{ className?: string }>;\n\tonSelect?: () => void;\n}\n\ninterface CommandProps extends Omit {\n\tclassName?: string;\n\ttrigger?: ReactNode;\n\tcommands: CommandItem[];\n\tplaceholder?: string;\n\ttriggerKey?: string;\n\tonCommandSelect?: (command: CommandItem) => void;\n\tonSearchChange?: (search: string) => void;\n}\n\nconst Command = ({\n\tclassName,\n\ttrigger,\n\tcommands,\n\tplaceholder = \"Search commands…\",\n\ttriggerKey = \"k\",\n\tonCommandSelect,\n\tonSearchChange,\n\t...props\n}: CommandProps) => {\n\tconst [isOpen, setOpen] = useState(false);\n\tconst [isMac, setIsMac] = useState(true);\n\tconst { contains } = useFilter({ sensitivity: \"base\" });\n\n\tuseEffect(() => {\n\t\tsetIsMac(/Mac/.test(navigator?.platform || \"\"));\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (\n\t\t\t\te.key.toLowerCase() === triggerKey.toLowerCase() &&\n\t\t\t\t(isMac ? e.metaKey : e.ctrlKey)\n\t\t\t) {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetOpen((prev) => !prev);\n\t\t\t} else if (e.key === \"Escape\") {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => document.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [isMac, triggerKey]);\n\n\tconst handleCommandSelect = (command: CommandItem) => {\n\t\tcommand.onSelect?.();\n\t\tonCommandSelect?.(command);\n\t\tsetOpen(false);\n\t};\n\n\treturn (\n\t\t\n\t\t\t{trigger || (\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\tSearch\n\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t{isMac ? \"⌘\" : \"Ctrl\"} {triggerKey.toUpperCase()}\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t)}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t true : contains}>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{({ label, shortcut, icon: Icon, ...command }) => (\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\thandleCommandSelect({\n\t\t\t\t\t\t\t\t\t\t\t\tlabel,\n\t\t\t\t\t\t\t\t\t\t\t\tshortcut,\n\t\t\t\t\t\t\t\t\t\t\t\ticon: Icon,\n\t\t\t\t\t\t\t\t\t\t\t\t...command,\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{Icon && (\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t{shortcut && (\n\t\t\t\t\t\t\t\t\t\t\t{shortcut}\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t);\n};\n\ninterface CommandMenuItemProps extends Omit {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst CommandMenuItem = ({\n\tclassName,\n\tchildren,\n\t...props\n}: CommandMenuItemProps) => (\n\t\n\t\t{children}\n\t\n);\n\nconst CommandTrigger = AriaDialogTrigger;\n\nexport { Command, CommandMenuItem, CommandTrigger };\nexport type { CommandProps, CommandMenuItemProps, CommandItem };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/command.tsx" } ], "tailwind": { diff --git a/web/public/r/date-field.json b/web/public/r/date-field.json index 9c1b0d1..ecbd126 100644 --- a/web/public/r/date-field.json +++ b/web/public/r/date-field.json @@ -15,7 +15,8 @@ { "path": "src/core/date-field/date-field.tsx", "content": "\"use client\";\n\nimport type {\n\tDateFieldProps as AriaDateFieldProps,\n\tDateValue,\n} from \"react-aria-components\";\nimport {\n\tDateField as AriaDateField,\n\tDateInput,\n\tDateSegment,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst dateField = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"flex min-h-11 min-w-48 appearance-none items-center rounded-lg border border-border bg-surface px-3 py-0.5 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:border-none data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm\",\n\t\tsegmentStyles:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:text-primary-fg data-[focused]:bg-primary data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t},\n});\n\nconst styles = dateField();\n\ninterface DateFieldProps extends AriaDateFieldProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst DateField = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\t...props\n}: DateFieldProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{(segment) => (\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t\t{description && {description}}\n\t\t{errorMessage}\n\t\n);\n\nexport { DateField };\nexport type { DateFieldProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/date-field.tsx" } ], "tailwind": { diff --git a/web/public/r/date-picker.json b/web/public/r/date-picker.json index 79c199f..2858489 100644 --- a/web/public/r/date-picker.json +++ b/web/public/r/date-picker.json @@ -18,7 +18,8 @@ { "path": "src/core/date-picker/date-picker.tsx", "content": "\"use client\";\n\nimport type {\n\tDatePickerProps as AriaDatePickerProps,\n\tDateRangePickerProps as AriaDateRangePickerProps,\n} from \"react-aria-components\";\nimport {\n\tDatePicker as AriaDatePicker,\n\tDateRangePicker as AriaDateRangePicker,\n\tButton,\n\tDateInput,\n\tDateSegment,\n\ttype DateValue,\n\tDialog,\n\tFieldError,\n\tGroup,\n\tLabel,\n\tPopover,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronDown } from \"lucide-react\";\n\nimport { Calendar, RangeCalendar } from \"@/components/ui/calendar/calendar\";\n\nconst baseStyles = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"appearance-none rounded-lg px-3 py-1.5 outline-none ring-primary transition-all\",\n\t\tpopover:\n\t\t\t\"overflow-auto rounded-2xl data-[entering]:animate-fade data-[exiting]:animate-fadeOut\",\n\t},\n});\n\nconst datePicker = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tgroup:\n\t\t\t\"relative flex min-h-11 w-auto min-w-48 items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface\",\n\t\tdateSegment:\n\t\t\t\"min-w-16 rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t},\n});\n\nconst dateRangePicker = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tgroup:\n\t\t\t\"relative flex min-h-11 w-full flex-wrap items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface\",\n\t\tdateSegment:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t\tseparator: \"px-2 text-fg-muted\",\n\t},\n});\n\nconst styles = datePicker();\nconst rangeStyles = dateRangePicker();\n\ninterface DatePickerProps extends AriaDatePickerProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst DatePicker = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: DatePickerProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n);\n\ninterface DateRangePickerProps\n\textends AriaDateRangePickerProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst DateRangePicker = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: DateRangePickerProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t–\n\t\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n);\n\nexport { DatePicker, DateRangePicker };\nexport type { DatePickerProps, DateRangePickerProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/date-picker.tsx" } ], "tailwind": { diff --git a/web/public/r/index.json b/web/public/r/index.json deleted file mode 100644 index 76ea874..0000000 --- a/web/public/r/index.json +++ /dev/null @@ -1,1044 +0,0 @@ -{ - "name": "baselayer", - "$schema": "https://ui.shadcn.com/schema/registry.json", - "homepage": "https://baselayer.dev", - "items": [ - { - "name": "accordion", - "type": "registry:ui", - "title": "accordion", - "description": "An accordion allows users to toggle the display of sections of content. Each accordion consists of a header with a title and content area.", - "author": "BaseLayer", - "categories": [ - "layout" - ], - "files": [ - { - "path": "components/base/accordion.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tButton,\n\tDisclosure,\n\tDisclosureGroup,\n\ttype DisclosureGroupProps,\n\tDisclosurePanel,\n\ttype DisclosureProps,\n\tHeading,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { Minus, Plus } from \"lucide-react\";\n\nconst accordion = tv({\n\tslots: {\n\t\troot: \"group w-full\",\n\t\tgroup: \"flex flex-col gap-3\",\n\t\tbutton:\n\t\t\t\"flex w-full items-center justify-between gap-6 rounded-2xl border border-border bg-surface-2 p-4 data-[focus-visible]:outline-none data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 data-[focus-visible]:ring-offset-surface group-data-[expanded]:rounded-b-none group-data-[expanded]:border-b-0\",\n\t\ticon: \"size-4 shrink-0 fill-none transition-transform duration-200\",\n\t\tpanel:\n\t\t\t\"rounded-b-2xl border-border bg-surface-2 px-4 text-muted-foreground text-sm group-data-[expanded]:border-x group-data-[expanded]:border-b group-data-[expanded]:pb-4\",\n\t},\n});\n\nconst styles = accordion();\n\ntype AccordionVariantProps = VariantProps;\n\ninterface AccordionProps\n\textends AccordionVariantProps,\n\t\tOmit {\n\tclassName?: string;\n\ttitle?: string;\n\tchildren?: ReactNode;\n}\n\nconst Accordion = ({\n\tclassName,\n\ttitle,\n\tchildren,\n\t...props\n}: AccordionProps) => {\n\treturn (\n\t\t\n\t\t\t{({ isExpanded }) => (\n\t\t\t\t<>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{children}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t);\n};\n\ninterface AccordionGroupProps extends DisclosureGroupProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst AccordionGroup = ({\n\tclassName,\n\tchildren,\n\t...props\n}: AccordionGroupProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Accordion, AccordionGroup };\nexport type { AccordionProps, AccordionGroupProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "disclosure", - "collapsible", - "expandable", - "content" - ] - } - }, - { - "name": "badge", - "type": "registry:ui", - "title": "badge", - "description": "A badge is a small label that can be used to display information or status.", - "author": "BaseLayer", - "categories": [ - "display" - ], - "files": [ - { - "path": "components/base/badge.tsx", - "content": "import type { HTMLAttributes } from \"react\";\n\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const badge = tv({\n\tbase: \"flex items-center justify-center rounded-4xl px-3 py-2 font-semibold text-xs\",\n\tvariants: {\n\t\tvariant: {\n\t\t\tattention: \"bg-gradient-to-r from-pink-500 to-purple-500 text-white\",\n\t\t\tneutral: \"bg-secondary text-secondary-fg\",\n\t\t\tdanger: \"bg-danger text-danger-fg\",\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"attention\",\n\t},\n});\n\ntype BadgeProps = VariantProps & HTMLAttributes;\n\nconst Badge = ({ className, variant, ...props }: BadgeProps) => (\n\t\n);\n\nexport { Badge };\nexport type { BadgeProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "status" - ] - } - }, - { - "name": "breadcrumbs", - "type": "registry:ui", - "title": "breadcrumbs", - "description": "Breadcrumbs display a heirarchy of links to the current page or resource in an application.", - "author": "BaseLayer", - "categories": [ - "navigation" - ], - "files": [ - { - "path": "components/base/breadcrumbs.tsx", - "content": "\"use client\";\n\nimport {\n\tBreadcrumbs as AriaBreadcrumbs,\n\ttype BreadcrumbsProps as AriaBreadcrumbsProps,\n\tBreadcrumb,\n\ttype BreadcrumbProps,\n\tLink,\n\ttype LinkProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst breadcrumbs = tv({\n\tslots: {\n\t\troot: \"m-0 flex list-none items-center gap-2 p-0 font-md\",\n\t\tlink: \"relative cursor-pointer rounded-md text-fg outline-none ring-focus data-[hovered]:underline data-[focus-visible]:ring-2 [&[aria-current]]:font-extrabold [&[aria-current]]:text-fg\",\n\t\titem: \"flex items-center gap-2\",\n\t},\n});\n\nconst styles = breadcrumbs();\n\nconst Breadcrumbs = ({\n\tchildren,\n\tclassName,\n\t...props\n}: AriaBreadcrumbsProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst BreadcrumbsLink = ({\n\tchildren,\n\tclassName,\n\t...props\n}: LinkProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst BreadcrumbsItem = ({\n\tchildren,\n\tclassName,\n\t...props\n}: BreadcrumbProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { BreadcrumbsItem, BreadcrumbsLink, Breadcrumbs };", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "navigation" - ] - } - }, - { - "name": "button", - "type": "registry:ui", - "title": "button", - "description": "A button allows a user to perform an action, with mouse, touch, and keyboard interactions.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/button.tsx", - "content": "\"use client\";\n\nimport {\n\tButton as AriaButton,\n\ttype ButtonProps as AriaButtonProps,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nconst button = tv({\n\tbase: \"inline-flex appearance-none items-center justify-center rounded-full font-semibold outline-none ring-focus ring-offset-3 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[focus-visible]:ring-2\",\n\tvariants: {\n\t\tvariant: {\n\t\t\tprimary:\n\t\t\t\t\"bg-primary text-primary-fg data-[hovered]:bg-primary/80\",\n\t\t\tsecondary:\n\t\t\t\t\"border border-border text-fg data-[hovered]:border-secondary data-[hovered]:bg-secondary\",\n\t\t\tghost:\n\t\t\t\t\"bg-transparent text-fg data-[hovered]:bg-secondary data-[hovered]:text-secondary-fg\",\n\t\t\tdanger:\n\t\t\t\t\"border border-transparent bg-danger text-danger-fg data-[hovered]:bg-danger/80\",\n\t\t},\n\t\tsize: {\n\t\t\tsm: \"px-2 py-1.5 text-sm\",\n\t\t\tmd: \"px-4 py-2.5 text-base\",\n\t\t\tlg: \"px-6 py-3.5 font-bold text-lg\",\n\t\t\ticon: \"size-9\",\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"primary\",\n\t\tsize: \"md\",\n\t},\n});\n\ntype ButtonVariantProps = VariantProps;\n\ninterface ButtonProps\n\textends Omit,\n\t\tButtonVariantProps {\n\tclassName?: string;\n}\n\nconst Button = ({\n\tclassName,\n\tsize,\n\tvariant,\n\tchildren,\n\t...props\n}: ButtonProps) => (\n\t\n\t\t{children}\n\t\n);\n\nButton.displayName = \"Button\";\n\nexport { Button };\nexport type { ButtonProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive" - ] - } - }, - { - "name": "calendar", - "type": "registry:ui", - "title": "calendar", - "description": "A calendar displays one or more date grids and allows users to select either a single date or a contiguous range of dates.", - "author": "BaseLayer", - "categories": [ - "data-entry" - ], - "files": [ - { - "path": "components/base/calendar.tsx", - "content": "\"use client\";\n\nimport {\n\tCalendar as AriaCalendar,\n\ttype CalendarProps as AriaCalendarProps,\n\tRangeCalendar as AriaRangeCalendar,\n\ttype RangeCalendarProps as AriaRangeCalendarProps,\n\tButton,\n\tCalendarCell,\n\tCalendarGrid,\n\tCalendarGridBody,\n\tCalendarGridHeader,\n\tCalendarHeaderCell,\n\ttype DateValue,\n\tHeading,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\nconst baseStyles = tv({\n\tslots: {\n\t\troot: \"w-fit max-w-full rounded-2xl border border-border bg-surface p-4 text-fg\",\n\t\theader: \"flex w-full items-center gap-1 pb-4\",\n\t\theading: \"flex-1 text-center font-bold\",\n\t\theaderCell: \"pb-2 text-fg-muted text-sm\",\n\t\tmonthButton:\n\t\t\t\"flex appearance-none items-center justify-center rounded-full p-2 text-center outline-none ring-focus data-[hovered]:bg-secondary data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst calendar = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tcell: \"flex size-9 cursor-default items-center justify-center rounded-full border-border text-center text-sm outline-focus outline-offset-2 data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:outline-2 data-[focus-visible]:outline-focus [&[data-outside-month]]:hidden\",\n\t},\n});\n\nconst rangeCalendar = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tcell: \"flex size-9 cursor-default items-center justify-center rounded-full text-center text-sm outline-none outline-offset-2 data-[selected]:rounded-none data-[hovered]:bg-secondary data-[pressed]:bg-secondary data-[selected]:bg-primary data-[selected]:text-primary-fg data-[unavailable]:text-fg-muted data-[unavailable]:line-through data-[focus-visible]:ring-2 data-[focus-visible]:ring-focus data-[focus-visible]:ring-offset-2 [&[data-outside-month]]:hidden [&[data-selection-end]]:rounded-r-full [&[data-selection-start]]:rounded-l-full\",\n\t},\n});\n\nconst styles = calendar();\nconst rangeStyles = rangeCalendar();\n\ninterface CalendarProps\n\textends Omit, \"className\"> {\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst Calendar = ({\n\tclassName,\n\terrorMessage,\n\t...props\n}: CalendarProps) => (\n\t\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\n\t\t\t\n\t\t\t\t{(day) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{day}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{(date) => }\n\t\t\t\n\t\t\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t
\n);\n\ninterface RangeCalendarProps\n\textends Omit, \"className\"> {\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst RangeCalendar = ({\n\tclassName,\n\terrorMessage,\n\t...props\n}: RangeCalendarProps) => (\n\t\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t
\n\t\t\n\t\t\t\n\t\t\t\t{(day) => (\n\t\t\t\t\t\n\t\t\t\t\t\t{day}\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{(date) => }\n\t\t\t\n\t\t\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t
\n);\n\nexport { Calendar, RangeCalendar };\nexport type { CalendarProps, RangeCalendarProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "date-time" - ] - } - }, - { - "name": "card", - "type": "registry:ui", - "title": "card", - "description": "Displays a card with header, content, and footer.", - "author": "BaseLayer", - "categories": [ - "layout" - ], - "files": [ - { - "path": "components/base/card.tsx", - "content": "\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\n\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nconst card = tv({\n\tslots: {\n\t\troot: \"rounded-2xl border-2 bg-surface text-fg\",\n\t\theader: \"flex flex-col space-y-1.5 p-6\",\n\t\ttitle: \"font-semibold text-2xl leading-none tracking-tight\",\n\t\tdescription: \"text-fg-muted text-sm\",\n\t\tcontent: \"p-6 pt-0\",\n\t\tfooter: \"flex items-center p-6 pt-0\",\n\t},\n\tvariants: {\n\t\tvariant: {\n\t\t\toutlined: {\n\t\t\t\troot: \"border border-border/50\",\n\t\t\t},\n\t\t\tfilled: {\n\t\t\t\troot: \"border-surface-2 bg-surface-2\",\n\t\t\t},\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tvariant: \"outlined\",\n\t},\n});\n\nconst styles = card();\n\ntype CardVariantProps = VariantProps;\n\ninterface CardProps extends HTMLAttributes, CardVariantProps {\n\tclassName?: string;\n\ttitle?: string;\n\tdescription?: string;\n}\n\ninterface CardHeaderProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\ninterface CardContentProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\ninterface CardFooterProps extends HTMLAttributes {\n\tclassName?: string;\n}\n\nconst Card = ({\n\tclassName,\n\tvariant,\n\ttitle,\n\tdescription,\n\tchildren,\n\t...props\n}: CardProps) => (\n\t
\n\t\t{(title || description) && (\n\t\t\t
\n\t\t\t\t{title &&

{title}

}\n\t\t\t\t{description &&

{description}

}\n\t\t\t
\n\t\t)}\n\t\t{children}\n\t
\n);\n\nconst CardHeader = ({ className, ...props }: CardHeaderProps) => (\n\t
\n);\n\nconst CardContent = ({ className, ...props }: CardContentProps) => (\n\t
\n);\n\nconst CardFooter = ({ className, ...props }: CardFooterProps) => (\n\t
\n);\n\nexport { Card, CardHeader, CardContent, CardFooter };\nexport type { CardProps, CardHeaderProps, CardContentProps, CardFooterProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "layout", - "container", - "display" - ] - } - }, - { - "name": "checkbox", - "type": "registry:ui", - "title": "checkbox", - "description": "A checkbox allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/checkbox.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\ttype CheckboxProps as AriaCheckBoxProps,\n\tCheckbox as AriaCheckbox,\n\tCheckboxGroup as AriaCheckboxGroup,\n\ttype CheckboxGroupProps as AriaCheckboxGroupProps,\n\tFieldError,\n\tText,\n\ttype ValidationResult,\n} from \"react-aria-components\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { Check } from \"lucide-react\";\n\nconst checkbox = tv({\n\tbase: \"group flex items-center justify-center gap-2 py-1 text-fg\",\n});\n\nconst checkboxGroup = tv({\n\tbase: \"flex flex-col gap-2\",\n});\n\ntype CheckboxVariantProps = VariantProps;\n\ninterface CheckboxProps extends CheckboxVariantProps, AriaCheckBoxProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst Checkbox = ({\n\tclassName,\n\terrorMessage,\n\tchildren,\n\tdescription,\n\t...props\n}: CheckboxProps) => {\n\treturn (\n\t\t\n\t\t\t{({ isSelected }) => (\n\t\t\t\t<>\n\t\t\t\t\t
\n\t\t\t\t\t\t{isSelected && }\n\t\t\t\t\t
\n\t\t\t\t\t{children}\n\t\t\t\t\t{description && (\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\n\t\t\t\t\t)}\n\t\t\t\t\t\n\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t
\n\t);\n};\n\ninterface CheckboxGroupProps extends AriaCheckboxGroupProps {\n\tclassName?: string;\n\tlabel?: string;\n\tchildren: ReactNode;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst CheckboxGroup = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: CheckboxGroupProps) => (\n\t\n\t\t{label && (\n\t\t\t\n\t\t\t\t{label}\n\t\t\t\n\t\t)}\n\t\t{children}\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { Checkbox, CheckboxGroup };\nexport type { CheckboxProps, CheckboxGroupProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive" - ] - } - }, - { - "name": "combobox", - "type": "registry:ui", - "title": "combobox", - "description": "A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/combobox.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tComboBox as AriaComboBox,\n\ttype ComboBoxProps as AriaComboBoxProps,\n\tButton,\n\tFieldError,\n\tInput,\n\tLabel,\n\tListBox,\n\tListBoxItem,\n\ttype ListBoxItemProps,\n\tPopover,\n\tText,\n\ttype ValidationResult,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CheckIcon, ChevronsUpDown } from \"lucide-react\";\n\nconst combobox = tv({\n\tslots: {\n\t\troot: \"group max-h-inherit w-full overflow-auto p-1 outline-none\",\n\t\tinput:\n\t\t\t\"w-full rounded-lg border border-border bg-surface px-4 py-1.5 align-middle font-semibold text-fg outline-none ring-fg transition-all group-data-[focused]:border-transparent group-data-[focused]:bg-surface group-data-[focused]:ring-2\",\n\t\tbutton:\n\t\t\t\"absolute right-2 flex appearance-none items-center justify-center rounded-full border-0 outline-none ring-focus ring-offset-2 ring-offset-surface data-[focus-visible]:ring-2\",\n\t\tpopover:\n\t\t\t\"w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none\",\n\t\titem: \"relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t},\n});\n\nconst styles = combobox();\n\ninterface ComboBoxProps\n\textends Omit, \"className\"> {\n\tclassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst ComboBox = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: ComboBoxProps) => (\n\t\n\t\t{label && }\n\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\ninterface ComboBoxItemProps\n\textends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst ComboBoxItem = ({ className, ...props }: ComboBoxItemProps) => (\n\t\n\t\t{({ isSelected }) => (\n\t\t\t
\n\t\t\t\t{props.children}\n\t\t\t\t{isSelected && }\n\t\t\t
\n\t\t)}\n\t
\n);\n\nexport { ComboBox, ComboBoxItem };\nexport type { ComboBoxProps, ListBoxItemProps as ComboBoxItemProps };", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "picker" - ] - } - }, - { - "name": "command", - "type": "registry:ui", - "title": "command", - "description": "A command palette that allows users to quickly search and execute commands using keyboard shortcuts.", - "author": "BaseLayer", - "categories": [ - "navigation" - ], - "files": [ - { - "path": "components/base/command.tsx", - "content": "\"use client\";\n\nimport type { ComponentType, ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\n\nimport {\n\tButton as AriaButton,\n\tDialog as AriaDialog,\n\tDialogTrigger as AriaDialogTrigger,\n\tModal as AriaModal,\n\tAutocomplete,\n\tInput,\n\tMenu,\n\tMenuItem,\n\ttype MenuItemProps,\n\tModalOverlay,\n\ttype ModalOverlayProps,\n\tTextField,\n\tuseFilter,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Search } from \"lucide-react\";\n\nconst command = tv({\n\tslots: {\n\t\ttrigger:\n\t\t\t\"flex w-full items-center justify-between rounded-full bg-secondary px-4 py-2 font-semibold text-fg outline-none ring-primary ring-offset-2 ring-offset-surface transition-colors data-[hovered]:bg-secondary/75 data-[focus-visible]:ring-2\",\n\t\toverlay:\n\t\t\t\"data-[entering]:fade-in data-[exiting]:fade-out fixed inset-0 z-50 flex min-h-full items-start justify-center bg-zinc-500/25 p-4 text-center data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200 sm:items-center\",\n\t\tmodal:\n\t\t\t\"data-[entering]:zoom-in-95 data-[exiting]:zoom-out-95 data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:duration-300 data-[exiting]:duration-200\",\n\t\tdialog:\n\t\t\t\"flex min-h-96 min-w-80 max-w-full flex-col gap-1 rounded-2xl bg-surface p-2 shadow-lg outline-none md:w-lg\",\n\t\tinput:\n\t\t\t\"rounded-lg border-b-2 border-none bg-transparent px-3 py-2 text-base text-fg leading-5 outline-none placeholder:text-fg-muted\",\n\t\tmenu: \"mt-2 h-80 overflow-auto\",\n\t\titem: \"group flex min-h-12 w-full cursor-default items-center rounded-lg px-3 py-2 text-fg outline-none data-[focused]:bg-secondary data-[pressed]:bg-surface-3 data-[focused]:text-focus-fg\",\n\t\tkbd: \"ml-auto rounded border border-border bg-surface-2 px-2 py-1 font-semibold text-fg-muted text-xs\",\n\t},\n});\n\nconst styles = command();\n\ninterface CommandItem {\n\tid: string;\n\tlabel: string;\n\tshortcut?: string;\n\ticon?: ComponentType<{ className?: string }>;\n\tonSelect?: () => void;\n}\n\ninterface CommandProps extends Omit {\n\tclassName?: string;\n\ttrigger?: ReactNode;\n\tcommands: CommandItem[];\n\tplaceholder?: string;\n\ttriggerKey?: string;\n\tonCommandSelect?: (command: CommandItem) => void;\n\tonSearchChange?: (search: string) => void;\n}\n\nconst Command = ({\n\tclassName,\n\ttrigger,\n\tcommands,\n\tplaceholder = \"Search commands…\",\n\ttriggerKey = \"k\",\n\tonCommandSelect,\n\tonSearchChange,\n\t...props\n}: CommandProps) => {\n\tconst [isOpen, setOpen] = useState(false);\n\tconst [isMac, setIsMac] = useState(true);\n\tconst { contains } = useFilter({ sensitivity: \"base\" });\n\n\tuseEffect(() => {\n\t\tsetIsMac(/Mac/.test(navigator?.platform || \"\"));\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (\n\t\t\t\te.key.toLowerCase() === triggerKey.toLowerCase() &&\n\t\t\t\t(isMac ? e.metaKey : e.ctrlKey)\n\t\t\t) {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetOpen((prev) => !prev);\n\t\t\t} else if (e.key === \"Escape\") {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => document.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [isMac, triggerKey]);\n\n\tconst handleCommandSelect = (command: CommandItem) => {\n\t\tcommand.onSelect?.();\n\t\tonCommandSelect?.(command);\n\t\tsetOpen(false);\n\t};\n\n\treturn (\n\t\t\n\t\t\t{trigger || (\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\tSearch\n\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t{isMac ? \"⌘\" : \"Ctrl\"} {triggerKey.toUpperCase()}\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t)}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t true : contains}>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{({ label, shortcut, icon: Icon, ...command }) => (\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\thandleCommandSelect({\n\t\t\t\t\t\t\t\t\t\t\t\tlabel,\n\t\t\t\t\t\t\t\t\t\t\t\tshortcut,\n\t\t\t\t\t\t\t\t\t\t\t\ticon: Icon,\n\t\t\t\t\t\t\t\t\t\t\t\t...command,\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{Icon && (\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t{shortcut && (\n\t\t\t\t\t\t\t\t\t\t\t{shortcut}\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t);\n};\n\ninterface CommandMenuItemProps extends Omit {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst CommandMenuItem = ({\n\tclassName,\n\tchildren,\n\t...props\n}: CommandMenuItemProps) => (\n\t\n\t\t{children}\n\t\n);\n\nconst CommandTrigger = AriaDialogTrigger;\n\nexport { Command, CommandMenuItem, CommandTrigger };\nexport type { CommandProps, CommandMenuItemProps, CommandItem };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "beta", - "tags": [ - "search", - "navigation", - "keyboard", - "palette" - ] - } - }, - { - "name": "date-field", - "type": "registry:ui", - "title": "date-field", - "description": "A date field allows users to enter and edit date and time values using a keyboard. Each part of a date value is displayed in an individually editable segment.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/date-field.tsx", - "content": "\"use client\";\n\nimport type {\n\tDateFieldProps as AriaDateFieldProps,\n\tDateValue,\n} from \"react-aria-components\";\nimport {\n\tDateField as AriaDateField,\n\tDateInput,\n\tDateSegment,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst dateField = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"flex min-h-11 min-w-48 appearance-none items-center rounded-lg border border-border bg-surface px-3 py-0.5 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:border-none data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm\",\n\t\tsegmentStyles:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:text-primary-fg data-[focused]:bg-primary data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t},\n});\n\nconst styles = dateField();\n\ninterface DateFieldProps extends AriaDateFieldProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst DateField = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\t...props\n}: DateFieldProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{(segment) => (\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t\t{description && {description}}\n\t\t{errorMessage}\n\t\n);\n\nexport { DateField };\nexport type { DateFieldProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "date" - ] - } - }, - { - "name": "date-picker", - "type": "registry:ui", - "title": "date-picker", - "description": "A date picker combines one or more DateFields with a calendar popover, allowing users to enter or select a single date/time or a range.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/date-picker.tsx", - "content": "\"use client\";\n\nimport type {\n\tDatePickerProps as AriaDatePickerProps,\n\tDateRangePickerProps as AriaDateRangePickerProps,\n} from \"react-aria-components\";\nimport {\n\tDatePicker as AriaDatePicker,\n\tDateRangePicker as AriaDateRangePicker,\n\tButton,\n\tDateInput,\n\tDateSegment,\n\ttype DateValue,\n\tDialog,\n\tFieldError,\n\tGroup,\n\tLabel,\n\tPopover,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronDown } from \"lucide-react\";\n\nimport { Calendar, RangeCalendar } from \"../calendar/calendar\";\n\nconst baseStyles = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"appearance-none rounded-lg px-3 py-1.5 outline-none ring-primary transition-all\",\n\t\tpopover:\n\t\t\t\"overflow-auto rounded-2xl data-[entering]:animate-fade data-[exiting]:animate-fadeOut\",\n\t},\n});\n\nconst datePicker = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tgroup:\n\t\t\t\"relative flex min-h-11 w-auto min-w-48 items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface\",\n\t\tdateSegment:\n\t\t\t\"min-w-16 rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t},\n});\n\nconst dateRangePicker = tv({\n\textend: baseStyles,\n\tslots: {\n\t\tgroup:\n\t\t\t\"relative flex min-h-11 w-full flex-wrap items-center rounded-lg border border-border bg-surface transition-all data-[focus-within]:border-transparent data-[focus-within]:bg-surface data-[focus-within]:ring-2 data-[focus-within]:ring-primary data-[focus-within]:ring-offset-surface\",\n\t\tdateSegment:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted data-[placeholder]:focus:text-primary-fg\",\n\t\tseparator: \"px-2 text-fg-muted\",\n\t},\n});\n\nconst styles = datePicker();\nconst rangeStyles = dateRangePicker();\n\ninterface DatePickerProps extends AriaDatePickerProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst DatePicker = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: DatePickerProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n);\n\ninterface DateRangePickerProps\n\textends AriaDateRangePickerProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n\tclassName?: string;\n}\n\nconst DateRangePicker = ({\n\tclassName,\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tchildren,\n\t...props\n}: DateRangePickerProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t–\n\t\t\t\n\t\t\t\n\t\t\t\t{(segment) => (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\n);\n\nexport { DatePicker, DateRangePicker };\nexport type { DatePickerProps, DateRangePickerProps };\n", - "type": "registry:component" - } - ], - "registryDependencies": [ - "calendar" - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "date-time" - ] - } - }, - { - "name": "input", - "type": "registry:ui", - "title": "input", - "description": "Allows a user to enter a plain text value with a keyboard.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/input.tsx", - "content": "\"use client\";\n\nimport type {\n\tTextFieldProps as AriaTextFieldProps,\n\tValidationResult,\n} from \"react-aria-components\";\nimport {\n\tInput as AriaInput,\n\tTextField as AriaTextField,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst input = tv({\n\tbase: \"min-h-11 appearance-none rounded-lg border border-border bg-surface px-3 py-1 text-fg outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focused]:border-transparent data-[disabled]:bg-primary/10 data-[disabled]:text-fg-disabled data-[focused]:ring-2 [&::placeholder]:text-fg-muted [&::placeholder]:text-sm\",\n});\n\ninterface InputProps extends Omit {\n\tclassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n\tplaceholder?: string;\n}\n\nconst Input = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tplaceholder,\n\tclassName,\n\t...props\n}: InputProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { Input };\nexport type { InputProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive" - ] - } - }, - { - "name": "menu", - "type": "registry:ui", - "title": "menu", - "description": "A menu displays a list of actions or options that a user can choose.", - "author": "BaseLayer", - "categories": [ - "pickers" - ], - "files": [ - { - "path": "components/base/menu.tsx", - "content": "\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\n\nimport {\n\tHeader as AriaHeader,\n\tMenu as AriaMenu,\n\tMenuItem as AriaMenuItem,\n\tMenuSection as AriaMenuSection,\n\tMenuTrigger as AriaMenuTrigger,\n\ttype MenuItemProps,\n\ttype MenuProps,\n\tPopover,\n\tSeparator,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const menu = tv({\n\tslots: {\n\t\tmenuPopover:\n\t\t\t\"data-[entering]:fade-in data-[exiting]:fade-out overflow-auto rounded-2xl border border-border/25 bg-surface shadow-xl data-[entering]:animate-in data-[exiting]:animate-out\",\n\t\theader: \"p-2 font-semibold\",\n\t\tcontent: \"flex h-fit min-w-56 flex-col gap-2 p-3 outline-none\",\n\t\titem: \"relative flex cursor-default justify-between rounded-lg p-3 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t\tseparator: \"h-[1px] bg-border\",\n\t},\n});\n\nconst { menuPopover, content, header, item, separator } = menu();\n\nconst MenuTrigger = AriaMenuTrigger;\nconst MenuSection = AriaMenuSection;\n\nconst MenuContent = ({\n\tchildren,\n\tclassName,\n\t...props\n}: MenuProps & { className?: string }) => (\n\t\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\nconst MenuItem = ({\n\tchildren,\n\tclassName,\n\t...props\n}: MenuItemProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst MenuHeader = ({\n\tchildren,\n\tclassName,\n\t...props\n}: HTMLAttributes & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst MenuSeperator = ({\n\tclassName,\n\t...props\n}: HTMLAttributes & { className?: string }) => (\n\t\n);\n\nexport {\n\tMenuContent,\n\tMenuHeader,\n\tMenuItem,\n\tMenuSeperator,\n\tMenuTrigger,\n\tMenuSection,\n};\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "interactive", - "navigation" - ] - } - }, - { - "name": "meter", - "type": "registry:ui", - "title": "meter", - "description": "A meter represents a quantity within a known range, or a fractional value.", - "author": "BaseLayer", - "categories": [ - "data-display" - ], - "files": [ - { - "path": "components/base/meter.tsx", - "content": "\"use client\";\n\nimport {\n\tMeter as AriaMeter,\n\ttype MeterProps as AriaMeterProps,\n\tLabel,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst bar = tv({\n\tbase: \"h-4 overflow-hidden rounded-2xl bg-surface-2\",\n});\n\ninterface MeterProps extends Omit {\n\tlabel?: string;\n\tclassName?: string;\n}\n\nconst Meter = ({ label, className, ...props }: MeterProps) => (\n\t\n\t\t{({ percentage, valueText }) => (\n\t\t\t<>\n\t\t\t\t
\n\t\t\t\t\t{label && }\n\t\t\t\t\t{valueText}\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t)}\n\t
\n);\n\nexport { Meter };\nexport type { MeterProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "data-display", - "progress" - ] - } - }, - { - "name": "modal", - "type": "registry:ui", - "title": "modal", - "description": "A modal is an overlay element which blocks interaction with elements outside it.", - "author": "BaseLayer", - "categories": [ - "overlays" - ], - "files": [ - { - "path": "components/base/modal.tsx", - "content": "\"use client\";\n\nimport {\n\tDialog as AriaDialog,\n\tDialogTrigger as AriaDialogTrigger,\n\tModal as AriaModal,\n\ttype DialogProps,\n\tModalOverlay,\n\ttype ModalOverlayProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const modal = tv({\n\tslots: {\n\t\tdialog: \"flex w-full flex-col gap-6 outline-none\",\n\t\tmodalStyles:\n\t\t\t\"fade-in w-full rounded-2xl bg-surface p-6 text-fg outline-none data-[entering]:animate-in md:w-md\",\n\t},\n});\n\nconst styles = modal();\n\ninterface ModalProps extends Omit {\n\tclassName?: string;\n}\n\nconst Modal = ({ children, className, ...props }: ModalProps) => (\n\t\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\nconst Dialog = ({ children, className, ...props }: DialogProps) => (\n\t\n\t\t{children}\n\t\n);\n\nconst ModalTrigger = AriaDialogTrigger;\n\nexport { Modal, Dialog, ModalTrigger };\nexport type { ModalProps, DialogProps };", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "overlay" - ] - } - }, - { - "name": "popover", - "type": "registry:ui", - "title": "popover", - "description": "A popover is an overlay element positioned relative to a trigger.", - "author": "BaseLayer", - "categories": [ - "overlays" - ], - "files": [ - { - "path": "components/base/popover.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tDialogTrigger as AriaDialogTrigger,\n\tPopover as AriaPopover,\n\ttype PopoverProps as AriaPopoverProps,\n\tDialog,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const popover = tv({\n\tbase: \"data-[entering]:fade-in data-[exiting]:fade-out m-1 max-w-lg rounded-2xl border border-border/25 bg-surface p-2 text-fg shadow-lg outline-none data-[entering]:animate-in data-[exiting]:animate-out\",\n});\n\ninterface DialogProps extends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst PopoverTrigger = AriaDialogTrigger;\n\nconst Popover = ({ children, className, ...props }: DialogProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Popover, PopoverTrigger };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "overlay", - "interactive" - ] - } - }, - { - "name": "radio-group", - "type": "registry:ui", - "title": "radio-group", - "description": "A radio group allows a user to select a single option from a list of mutually exclusive options.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/radio-group.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport type {\n RadioGroupProps as AriaRadioGroupProps,\n RadioProps,\n ValidationResult,\n} from \"react-aria-components\";\nimport {\n Radio as AriaRadio,\n RadioGroup as AriaRadioGroup,\n FieldError,\n Text,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst radioGroup = tv({\n slots: {\n radio:\n \"flex items-center gap-4 text-fg before:block before:h-5 before:w-5 before:rounded-full before:border before:border-border before:ring-focus before:ring-offset-2 before:ring-offset-surface before:transition-all data-[selected]:before:border-4 data-[selected]:before:border-primary data-[focus-visible]:before:ring-2\",\n group: \"flex flex-col gap-4 text-fg\",\n },\n});\n\nconst { group, radio } = radioGroup();\n\ninterface RadioGroupProps extends Omit {\n className?: string;\n children?: ReactNode;\n label?: string;\n description?: string;\n errorMessage?: string | ((validation: ValidationResult) => string)\n}\n\nconst RadioGroup = ({\n className,\n label,\n description,\n errorMessage,\n children,\n ...props\n}: RadioGroupProps) => (\n \n {label}\n {children}\n {description && {description}}\n {errorMessage}\n \n);\n\nconst Radio = ({\n children,\n className,\n ...props\n}: RadioProps & {\n className?: string;\n}) => (\n \n {children}\n \n);\n\nexport { RadioGroup, Radio }; ", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "selection" - ] - } - }, - { - "name": "select", - "type": "registry:ui", - "title": "select", - "description": "A select displays a collapsible list of options and allows a user to select one of them.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/select.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport type {\n\tSelectProps as AriaSelectProps,\n\tListBoxItemProps,\n\tValidationResult,\n} from \"react-aria-components\";\nimport {\n\tSelect as AriaSelect,\n\tAutocomplete,\n\tButton,\n\tFieldError,\n\tInput,\n\tLabel,\n\tListBox,\n\tListBoxItem,\n\tPopover,\n\tSearchField,\n\tSelectValue,\n\tText,\n\tuseFilter,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CheckIcon, ChevronDown, Search } from \"lucide-react\";\n\nconst select = tv({\n\tslots: {\n\t\tgroup: \"group flex flex-col gap-1\",\n\t\tbutton:\n\t\t\t\"group flex w-fit items-center justify-between gap-4 rounded-full border border-border bg-surface px-4 py-2.75 align-middle font-semibold text-fg text-sm outline-none ring-fg transition-all data-[hovered]:bg-surface-2 group-data-[focus-visible]:border-transparent group-data-[open]:bg-surface-2 group-data-[focus-visible]:ring-2\",\n\t\titem: \"relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t\tsearchField:\n\t\t\t\"group m-1 flex items-center rounded-full border border-border bg-surface px-2 py-1.5\",\n\t\tsearchInput:\n\t\t\t\"flex-1 bg-transparent text-fg outline-none placeholder:text-fg-muted\",\n\t\tsearchIcon: \"mr-2 size-4 text-fg-muted\",\n\t\tclearButton:\n\t\t\t\"ml-2 rounded p-0.5 text-fg-muted transition-colors hover:bg-surface-2 hover:text-fg group-empty:invisible\",\n\t\tpopover:\n\t\t\t\"min-w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none\",\n\t},\n});\n\nconst styles = select();\n\ninterface SelectProps\n\textends Omit, \"className\"> {\n\tclassName?: string;\n\tpopoverClassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst Select = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tpopoverClassName,\n\tchildren,\n\t...props\n}: SelectProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\ninterface SelectItemProps\n\textends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst SelectItem = ({ className, ...props }: SelectItemProps) => (\n\t\n\t\t{({ isSelected }) => (\n\t\t\t
\n\t\t\t\t{props.children}\n\t\t\t\t{isSelected && }\n\t\t\t
\n\t\t)}\n\t
\n);\n\ninterface SearchableSelectProps\n\textends SelectProps {\n\tsearchPlaceholder?: string;\n}\n\nconst SearchableSelect = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tsearchPlaceholder = \"Search...\",\n\tchildren,\n\tpopoverClassName,\n\t...props\n}: SearchableSelectProps) => {\n\tconst { contains } = useFilter({ sensitivity: \"base\" });\n\n\treturn (\n\t\t\n\t\t\t{label && }\n\t\t\t\n\t\t\t{description && (\n\t\t\t\t\n\t\t\t\t\t{description}\n\t\t\t\t\n\t\t\t)}\n\t\t\t{errorMessage}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{children}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nexport { Select, SelectItem, SearchableSelect };\nexport type { SelectProps, SelectItemProps, SearchableSelectProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "picker" - ] - } - }, - { - "name": "slider", - "type": "registry:ui", - "title": "slider", - "description": "A slider allows a user to select one or more values within a range.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/slider.tsx", - "content": "\"use client\";\n\nimport {\n\tSlider as AriaSlider,\n\tSliderThumb as AriaSliderThumb,\n\tSliderTrack as AriaSliderTrack,\n\tLabel,\n\ttype LabelProps,\n\tSliderOutput,\n\ttype SliderProps,\n\ttype SliderThumbProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst slider = tv({\n\tslots: {\n\t\troot: \"grid w-64 auto-cols-fr grid-cols-1 text-fg-muted\",\n\t\tthumb:\n\t\t\t\"h-5 w-5 rounded-full bg-primary ring-focus ring-offset-2 ring-offset-surface data-[dragging]:outline-2 data-[focus-visible]:ring-2\",\n\t\ttrack:\n\t\t\t\"before:-translate-y-1/2 relative col-span-2 col-start-1 w-full before:absolute before:top-1/2 before:h-0.5 before:w-full before:transform before:bg-secondary\",\n\t},\n});\n\nconst { root, thumb, track } = slider();\n\nconst SliderRoot = ({\n\tchildren,\n\tclassName,\n\t...props\n}: SliderProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst SliderThumb = ({\n\tchildren,\n\tclassName,\n\t...props\n}: SliderThumbProps & { className?: string }) => (\n\t\n\t\t\n\t\n);\n\nconst SliderLabel = ({\n\tchildren,\n\tclassName,\n\t...props\n}: LabelProps & { className?: string }) => (\n\t
\n\t\t\n\t\t\n\t
\n);\n\nexport { SliderRoot, SliderThumb, SliderLabel };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "range" - ] - } - }, - { - "name": "switch", - "type": "registry:ui", - "title": "switch", - "description": "A switch allows a user to turn a setting on or off.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/switch.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tSwitch as AriaSwitch,\n\ttype SwitchProps as AriaSwitchProps,\n\tLabel,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst switchStyles = tv({\n\tslots: {\n\t\troot: \"group flex items-center gap-2 transition-none duration-200\",\n\t\tindicator:\n\t\t\t\"h-6 w-10 cursor-pointer rounded-xl bg-secondary duration-200 before:mx-[3px] before:mt-[3px] before:block before:size-4.5 before:rounded-2xl before:bg-surface before:transition-all data-[selected]:bg-primary group-data-[selected]:bg-primary group-data-[focus-visible]:ring-2 group-data-[focus-visible]:ring-focus group-data-[focus-visible]:ring-offset-2 group-data-[focus-visible]:ring-offset-surface group-data-[selected]:before:translate-x-4\",\n\t\tlabel: \"font-semibold text-fg text-sm\",\n\t},\t\n});\n\nconst styles = switchStyles();\n\ninterface SwitchProps extends AriaSwitchProps {\n\tchildren?: ReactNode;\n\tclassName?: string;\n}\n\n const Switch = ({ className, children, ...restProps }: SwitchProps) => (\n\t\n\t\t
\n\t\t\n\t\n);\n\nexport { Switch };\nexport type { SwitchProps };", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "toggle" - ] - } - }, - { - "name": "table", - "type": "registry:ui", - "title": "table", - "description": "A table displays data in rows and columns and enables a user to navigate its contents via directional navigation keys, and optionally supports row selection and sorting.", - "author": "BaseLayer", - "categories": [ - "data-display" - ], - "files": [ - { - "path": "components/base/table.tsx", - "content": "\"use client\";\n\nimport {\n\tColumn as AriaColumn,\n\tTable as AriaTable,\n\tTableBody as AriaTableBody,\n\tTableHeader as AriaTableheader,\n\tCell,\n\ttype CellProps,\n\tCollection,\n\ttype ColumnProps,\n\tRow,\n\ttype RowProps,\n\ttype TableHeaderProps,\n\ttype TableProps,\n\tuseTableOptions,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Menu } from \"lucide-react\";\n\nimport { Button } from \"../button/button\";\nimport { Checkbox } from \"../checkbox/checkbox\";\n\nconst table = tv({\n\tslots: {\n\t\troot: \"table min-h-[100px] border-separate border-spacing-0 rounded-xl border border-border p-4 outline-none\",\n\t\tcolumn: \"border-border border-b-2 px-4 py-1 text-left outline-none\",\n\t\theader: \"text-fg after:table-row after:h-[2px]\",\n\t\tlabel: \"text-fg-3\",\n\t\trow: \"relative cursor-default rounded-xl text-fg outline-none ring-focus data-[focus-visible]:ring-2\",\n\t\tcell: \"px-4 py-2 outline-none ring-focus data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = table();\n\nconst TableBody = AriaTableBody;\n\nconst Table = ({\n\tchildren,\n\tclassName,\n\t...props\n}: TableProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableCell = ({\n\tchildren,\n\tclassName,\n\t...props\n}: CellProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableColumn = ({\n\tchildren,\n\tclassName,\n\t...props\n}: ColumnProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableHeader = ({\n\tchildren,\n\tclassName,\n\tcolumns,\n\t...props\n}: TableHeaderProps & { className?: string }) => {\n\tconst { selectionBehavior, selectionMode, allowsDragging } =\n\t\tuseTableOptions();\n\treturn (\n\t\t\n\t\t\t{/* Add extra columns for drag and drop and selection. */}\n\t\t\t{allowsDragging && }\n\t\t\t{selectionBehavior === \"toggle\" && (\n\t\t\t\t\n\t\t\t\t\t{selectionMode === \"multiple\" && (\n\t\t\t\t\t\t \n\t\t\t\t\t)}\n\t\t\t\t\n\t\t\t)}\n\t\t\t{children}\n\t\t\n\t);\n};\n\nconst TableRow = ({\n\tchildren,\n\tclassName,\n\tcolumns,\n\tid,\n\t...props\n}: RowProps & { className?: string }) => {\n\tconst { selectionBehavior, allowsDragging } = useTableOptions();\n\treturn (\n\t\t\n\t\t\t{allowsDragging && (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t\t{selectionBehavior === \"toggle\" && (\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t\n\t\t\t)}\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport { TableColumn, Table, TableBody, TableCell, TableHeader, TableRow };\n", - "type": "registry:component" - } - ], - "registryDependencies": [ - "button", - "checkbox" - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "data-display", - "interactive" - ] - } - }, - { - "name": "tabs", - "type": "registry:ui", - "title": "tabs", - "description": "Tabs organize content into multiple sections and allow users to navigate between them.", - "author": "BaseLayer", - "categories": [ - "navigation" - ], - "files": [ - { - "path": "components/base/tabs.tsx", - "content": "\"use client\";\n\nimport {\n\tTab as AriaTab,\n\tTabList as AriaTabList,\n\ttype TabListProps as AriaTabListProps,\n\tTabPanel as AriaTabPanel,\n\ttype TabPanelProps as AriaTabPanelProps,\n\ttype TabProps as AriaTabProps,\n\ttype TabsProps as AriaTabsProps,\n\tTabs as AriaTabsRoot,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tabs = tv({\n\tslots: {\n\t\troot: \"flex w-full flex-col items-start\",\n\t\tlist: \"relative inline-flex items-center justify-between gap-6 rounded-md p-1\",\n\t\ttab: \"relative flex w-fit cursor-pointer justify-center rounded-2xl border-primary pb-0.5 font-semibold text-fg-muted outline-none ring-focus ring-offset-2 ring-offset-surface transition-colors duration-200 aria-selected:cursor-default aria-selected:rounded-none aria-selected:border-b-2 aria-selected:pb-0 aria-selected:text-primary aria-selected:hover:bg-transparent data-[hovered]:text-primary data-[focus-visible]:ring-2\",\n\t\tpanel:\n\t\t\t\"mt-4 w-96 rounded-xl p-4 outline-none ring-focus data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = tabs();\n\ninterface TabsProps extends Omit {\n\tclassName?: string;\n}\n\nconst TabsRoot = ({ children, className, ...props }: TabsProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabListProps extends Omit, \"className\"> {\n\tclassName?: string;\n}\n\nconst TabList = ({\n\tchildren,\n\tclassName,\n\t...props\n}: TabListProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabProps extends Omit {\n\tclassName?: string;\n}\n\nconst Tab = ({ children, className, ...props }: TabProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabPanelProps extends Omit {\n\tclassName?: string;\n}\n\nconst TabPanel = ({ children, className, ...props }: TabPanelProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Tab, TabList, TabPanel, TabsRoot };\nexport type { TabsProps, TabListProps, TabProps, TabPanelProps }; ", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "navigation", - "interactive", - "layout" - ] - } - }, - { - "name": "tag-group", - "type": "registry:ui", - "title": "tag-group", - "description": "A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/tag-group.tsx", - "content": "\"use client\";\n\nimport {\n\tTag as AriaTag,\n\tTagGroup as AriaTagGroup,\n\ttype TagGroupProps as AriaTagGroupProps,\n\ttype TagProps as AriaTagProps,\n\tLabel,\n\tTagList,\n\ttype TagListProps,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tagGroup = tv({\n\tslots: {\n\t\troot: \"flex flex-col gap-2 text-sm\",\n\t\tlist: \"flex flex-wrap gap-2\",\n\t\ttag: \"flex cursor-default items-center rounded-full border border-border px-2 py-1 outline-none ring-focus ring-offset-2 ring-offset-surface aria-selected:border-primary aria-selected:bg-primary aria-selected:text-primary-fg data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = tagGroup();\n\ninterface TagGroupProps\n\textends Omit,\n\t\tPick, \"items\" | \"children\" | \"renderEmptyState\"> {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst TagGroup = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\titems,\n\tchildren,\n\trenderEmptyState,\n\t...props\n}: TagGroupProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{children}\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t\n);\n\nconst Tag = ({\n\tchildren,\n\tclassName,\n\t...props\n}: AriaTagProps & { className?: string }) => {\n\tconst textValue = typeof children === \"string\" ? children : undefined;\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport { Tag, TagGroup };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "selection", - "filtering" - ] - } - }, - { - "name": "time-field", - "type": "registry:ui", - "title": "time-field", - "description": "A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/time-field.tsx", - "content": "\"use client\";\n\nimport type {\n\tTimeFieldProps as AriaTimeFieldProps,\n\tTimeValue,\n} from \"react-aria-components\";\nimport {\n\tTimeField as AriaTimeField,\n\tDateInput,\n\tDateSegment,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst timeField = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"appearance-none rounded-lg border border-border bg-surface px-3 py-1.75 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm [&::placeholder]:focus:text-primary-fg\",\n\t\tsegmentStyles:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted\",\n\t},\n});\n\nconst styles = timeField();\n\ninterface TimeFieldProps extends AriaTimeFieldProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst TimeField = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\t...props\n}: TimeFieldProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{(segment) => (\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { TimeField };\nexport type { TimeFieldProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "time" - ] - } - }, - { - "name": "toggle", - "type": "registry:ui", - "title": "toggle", - "description": "A toggle button allows a user to toggle a selection on or off, for example switching between two states or modes.", - "author": "BaseLayer", - "categories": [ - "forms" - ], - "files": [ - { - "path": "components/base/toggle.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tToggleButton,\n\tToggleButtonGroup,\n\ttype ToggleButtonGroupProps,\n\ttype ToggleButtonProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst toggle = tv({\n\tbase: \"inline-flex appearance-none items-center justify-center rounded-full bg-surface-2 px-4 py-1 font-medium outline-none ring-focus ring-offset-2 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[selected]:bg-primary data-[selected]:text-primary-fg data-[focus-visible]:ring-2\",\n});\n\nconst toggleGroup = tv({\n\tbase: \"flex min-h-11 gap-1 rounded-full border border-border bg-surface-2 p-1\",\n});\n\ninterface ToggleProps extends Omit {\n\tclassName?: string;\n}\n\nconst Toggle = ({ className, children, ...props }: ToggleProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface ToggleGroupProps extends ToggleButtonGroupProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst ToggleGroup = ({ className, children, ...props }: ToggleGroupProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Toggle, ToggleGroup };\nexport type { ToggleProps, ToggleGroupProps };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "form", - "interactive", - "toggle" - ] - } - }, - { - "name": "tooltip", - "type": "registry:ui", - "title": "tooltip", - "description": "A tooltip displays a description of an element on hover or focus.", - "author": "BaseLayer", - "categories": [ - "overlays" - ], - "files": [ - { - "path": "components/base/tooltip.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tTooltip as AriaTooltip,\n\ttype TooltipProps as AriaTooltipProps,\n\tTooltipTrigger as AriaTooltipTrigger,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tooltip = tv({\n\tbase: \"[&[data-entering]]:fade-in [&[data-exiting]]:fade-out m-1 max-w-sm rounded-full border border-border bg-surface px-4 py-2 text-fg shadow-xl outline-none [&[data-entering]]:animate-fade-in [&[data-exiting]]:animate-fade-out\",\n});\n\nconst TooltipTrigger = AriaTooltipTrigger;\n\ninterface TooltipProps extends Omit {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst Tooltip = ({ children, className, ...props }: TooltipProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Tooltip, TooltipTrigger };\n", - "type": "registry:component" - } - ], - "dependencies": [ - "react-aria-components", - "tailwind-variants", - "lucide-react" - ], - "tailwind": { - "config": { - "content": [ - "./components/**/*.{ts,tsx}" - ], - "theme": { - "extend": {} - } - } - }, - "meta": { - "status": "stable", - "tags": [ - "overlay", - "interactive", - "help" - ] - } - } - ] -} \ No newline at end of file diff --git a/web/public/r/input.json b/web/public/r/input.json index 32010f2..6ad89d5 100644 --- a/web/public/r/input.json +++ b/web/public/r/input.json @@ -15,7 +15,8 @@ { "path": "src/core/input/input.tsx", "content": "\"use client\";\n\nimport type {\n\tTextFieldProps as AriaTextFieldProps,\n\tValidationResult,\n} from \"react-aria-components\";\nimport {\n\tInput as AriaInput,\n\tTextField as AriaTextField,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst input = tv({\n\tbase: \"min-h-11 appearance-none rounded-lg border border-border bg-surface px-3 py-1 text-fg outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focused]:border-transparent data-[disabled]:bg-primary/10 data-[disabled]:text-fg-disabled data-[focused]:ring-2 [&::placeholder]:text-fg-muted [&::placeholder]:text-sm\",\n});\n\ninterface InputProps extends Omit {\n\tclassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n\tplaceholder?: string;\n}\n\nconst Input = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\tplaceholder,\n\tclassName,\n\t...props\n}: InputProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { Input };\nexport type { InputProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/input.tsx" } ], "tailwind": { diff --git a/web/public/r/menu.json b/web/public/r/menu.json index 87d2652..ef7117b 100644 --- a/web/public/r/menu.json +++ b/web/public/r/menu.json @@ -15,7 +15,8 @@ { "path": "src/core/menu/menu.tsx", "content": "\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\n\nimport {\n\tHeader as AriaHeader,\n\tMenu as AriaMenu,\n\tMenuItem as AriaMenuItem,\n\tMenuSection as AriaMenuSection,\n\tMenuTrigger as AriaMenuTrigger,\n\ttype MenuItemProps,\n\ttype MenuProps,\n\tPopover,\n\tSeparator,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const menu = tv({\n\tslots: {\n\t\tmenuPopover:\n\t\t\t\"data-[entering]:fade-in data-[exiting]:fade-out overflow-auto rounded-2xl border border-border/25 bg-surface shadow-xl data-[entering]:animate-in data-[exiting]:animate-out\",\n\t\theader: \"p-2 font-semibold\",\n\t\tcontent: \"flex h-fit min-w-56 flex-col gap-2 p-3 outline-none\",\n\t\titem: \"relative flex cursor-default justify-between rounded-lg p-3 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t\tseparator: \"h-[1px] bg-border\",\n\t},\n});\n\nconst { menuPopover, content, header, item, separator } = menu();\n\nconst MenuTrigger = AriaMenuTrigger;\nconst MenuSection = AriaMenuSection;\n\nconst MenuContent = ({\n\tchildren,\n\tclassName,\n\t...props\n}: MenuProps & { className?: string }) => (\n\t\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\nconst MenuItem = ({\n\tchildren,\n\tclassName,\n\t...props\n}: MenuItemProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst MenuHeader = ({\n\tchildren,\n\tclassName,\n\t...props\n}: HTMLAttributes & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst MenuSeperator = ({\n\tclassName,\n\t...props\n}: HTMLAttributes & { className?: string }) => (\n\t\n);\n\nexport {\n\tMenuContent,\n\tMenuHeader,\n\tMenuItem,\n\tMenuSeperator,\n\tMenuTrigger,\n\tMenuSection,\n};\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/menu.tsx" } ], "tailwind": { diff --git a/web/public/r/meter.json b/web/public/r/meter.json index 567b611..501b470 100644 --- a/web/public/r/meter.json +++ b/web/public/r/meter.json @@ -15,7 +15,8 @@ { "path": "src/core/meter/meter.tsx", "content": "\"use client\";\n\nimport {\n\tMeter as AriaMeter,\n\ttype MeterProps as AriaMeterProps,\n\tLabel,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst bar = tv({\n\tbase: \"h-4 overflow-hidden rounded-2xl bg-surface-2\",\n});\n\ninterface MeterProps extends Omit {\n\tlabel?: string;\n\tclassName?: string;\n}\n\nconst Meter = ({ label, className, ...props }: MeterProps) => (\n\t\n\t\t{({ percentage, valueText }) => (\n\t\t\t<>\n\t\t\t\t
\n\t\t\t\t\t{label && }\n\t\t\t\t\t{valueText}\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t)}\n\t
\n);\n\nexport { Meter };\nexport type { MeterProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/meter.tsx" } ], "tailwind": { diff --git a/web/public/r/modal.json b/web/public/r/modal.json index fd852bf..f641498 100644 --- a/web/public/r/modal.json +++ b/web/public/r/modal.json @@ -15,7 +15,8 @@ { "path": "src/core/modal/modal.tsx", "content": "\"use client\";\n\nimport {\n\tDialog as AriaDialog,\n\tDialogTrigger as AriaDialogTrigger,\n\tModal as AriaModal,\n\ttype DialogProps,\n\tModalOverlay,\n\ttype ModalOverlayProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const modal = tv({\n\tslots: {\n\t\tdialog: \"flex w-full flex-col gap-6 outline-none\",\n\t\tmodalStyles:\n\t\t\t\"fade-in w-full rounded-2xl bg-surface p-6 text-fg outline-none data-[entering]:animate-in md:w-md\",\n\t},\n});\n\nconst styles = modal();\n\ninterface ModalProps extends Omit {\n\tclassName?: string;\n}\n\nconst Modal = ({ children, className, ...props }: ModalProps) => (\n\t\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\nconst Dialog = ({ children, className, ...props }: DialogProps) => (\n\t\n\t\t{children}\n\t\n);\n\nconst ModalTrigger = AriaDialogTrigger;\n\nexport { Modal, Dialog, ModalTrigger };\nexport type { ModalProps, DialogProps };", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/modal.tsx" } ], "tailwind": { diff --git a/web/public/r/popover.json b/web/public/r/popover.json index 6b61a10..878bc24 100644 --- a/web/public/r/popover.json +++ b/web/public/r/popover.json @@ -15,7 +15,8 @@ { "path": "src/core/popover/popover.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tDialogTrigger as AriaDialogTrigger,\n\tPopover as AriaPopover,\n\ttype PopoverProps as AriaPopoverProps,\n\tDialog,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nexport const popover = tv({\n\tbase: \"data-[entering]:fade-in data-[exiting]:fade-out m-1 max-w-lg rounded-2xl border border-border/25 bg-surface p-2 text-fg shadow-lg outline-none data-[entering]:animate-in data-[exiting]:animate-out\",\n});\n\ninterface DialogProps extends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst PopoverTrigger = AriaDialogTrigger;\n\nconst Popover = ({ children, className, ...props }: DialogProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Popover, PopoverTrigger };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/popover.tsx" } ], "tailwind": { diff --git a/web/public/r/radio-group.json b/web/public/r/radio-group.json index f60c971..d25cebf 100644 --- a/web/public/r/radio-group.json +++ b/web/public/r/radio-group.json @@ -14,8 +14,9 @@ "files": [ { "path": "src/core/radio-group/radio-group.tsx", - "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport type {\n RadioGroupProps as AriaRadioGroupProps,\n RadioProps,\n ValidationResult,\n} from \"react-aria-components\";\nimport {\n Radio as AriaRadio,\n RadioGroup as AriaRadioGroup,\n FieldError,\n Text,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst radioGroup = tv({\n slots: {\n radio:\n \"flex items-center gap-4 text-fg before:block before:h-5 before:w-5 before:rounded-full before:border before:border-border before:ring-focus before:ring-offset-2 before:ring-offset-surface before:transition-all data-[selected]:before:border-4 data-[selected]:before:border-primary data-[focus-visible]:before:ring-2\",\n group: \"flex flex-col gap-4 text-fg\",\n },\n});\n\nconst { group, radio } = radioGroup();\n\ninterface RadioGroupProps extends Omit {\n className?: string;\n children?: ReactNode;\n label?: string;\n description?: string;\n errorMessage?: string | ((validation: ValidationResult) => string)\n}\n\nconst RadioGroup = ({\n className,\n label,\n description,\n errorMessage,\n children,\n ...props\n}: RadioGroupProps) => (\n \n {label}\n {children}\n {description && {description}}\n {errorMessage}\n \n);\n\nconst Radio = ({\n children,\n className,\n ...props\n}: RadioProps & {\n className?: string;\n}) => (\n \n {children}\n \n);\n\nexport { RadioGroup, Radio }; ", - "type": "registry:component" + "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport type {\n RadioGroupProps as AriaRadioGroupProps,\n RadioProps,\n ValidationResult,\n} from \"react-aria-components\";\nimport {\n Radio as AriaRadio,\n RadioGroup as AriaRadioGroup,\n FieldError,\n Text,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst radioGroup = tv({\n slots: {\n radio:\n \"flex items-center gap-4 text-fg before:block before:h-5 before:w-5 before:rounded-full before:border before:border-border before:ring-focus before:ring-offset-2 before:ring-offset-surface before:transition-all data-[selected]:before:border-4 data-[selected]:before:border-primary data-[focus-visible]:before:ring-2\",\n group: \"flex flex-col gap-4 text-fg\",\n },\n});\n\nconst { group, radio } = radioGroup();\n\ninterface RadioGroupProps extends Omit {\n className?: string;\n children?: ReactNode;\n label?: string;\n description?: string;\n errorMessage?: string | ((validation: ValidationResult) => string)\n}\n\nconst RadioGroup = ({\n className,\n label,\n description,\n errorMessage,\n children,\n ...props\n}: RadioGroupProps) => (\n \n {label}\n {children}\n {description && {description}}\n {errorMessage}\n \n);\n\nconst Radio = ({\n children,\n className,\n ...props\n}: RadioProps & {\n className?: string;\n}) => (\n \n {children}\n \n);\n\nexport { RadioGroup, Radio }; ", + "type": "registry:component", + "target": "components/ui/radio-group.tsx" } ], "tailwind": { diff --git a/web/public/r/registry.json b/web/public/r/registry.json index 5a78a29..b2ba251 100644 --- a/web/public/r/registry.json +++ b/web/public/r/registry.json @@ -15,6 +15,7 @@ "files": [ { "path": "src/core/accordion/accordion.tsx", + "target": "components/ui/accordion.tsx", "type": "registry:component" } ], @@ -109,6 +110,7 @@ "files": [ { "path": "src/core/badge/badge.tsx", + "target": "components/ui/badge.tsx", "type": "registry:component" } ], @@ -200,6 +202,7 @@ "files": [ { "path": "src/core/breadcrumbs/breadcrumbs.tsx", + "target": "components/ui/breadcrumbs.tsx", "type": "registry:component" } ], @@ -291,6 +294,7 @@ "files": [ { "path": "src/core/button/button.tsx", + "target": "components/ui/button.tsx", "type": "registry:component" } ], @@ -383,6 +387,7 @@ "files": [ { "path": "src/core/calendar/calendar.tsx", + "target": "components/ui/calendar.tsx", "type": "registry:component" } ], @@ -476,6 +481,7 @@ "files": [ { "path": "src/core/card/card.tsx", + "target": "components/ui/card.tsx", "type": "registry:component" } ], @@ -569,6 +575,7 @@ "files": [ { "path": "src/core/checkbox/checkbox.tsx", + "target": "components/ui/checkbox.tsx", "type": "registry:component" } ], @@ -661,6 +668,7 @@ "files": [ { "path": "src/core/combobox/combobox.tsx", + "target": "components/ui/combobox.tsx", "type": "registry:component" } ], @@ -754,6 +762,7 @@ "files": [ { "path": "src/core/command/command.tsx", + "target": "components/ui/command.tsx", "type": "registry:component" } ], @@ -848,6 +857,7 @@ "files": [ { "path": "src/core/date-field/date-field.tsx", + "target": "components/ui/date-field.tsx", "type": "registry:component" } ], @@ -941,6 +951,7 @@ "files": [ { "path": "src/core/date-picker/date-picker.tsx", + "target": "components/ui/date-picker.tsx", "type": "registry:component" } ], @@ -1037,6 +1048,7 @@ "files": [ { "path": "src/core/input/input.tsx", + "target": "components/ui/input.tsx", "type": "registry:component" } ], @@ -1129,6 +1141,7 @@ "files": [ { "path": "src/core/menu/menu.tsx", + "target": "components/ui/menu.tsx", "type": "registry:component" } ], @@ -1221,6 +1234,7 @@ "files": [ { "path": "src/core/meter/meter.tsx", + "target": "components/ui/meter.tsx", "type": "registry:component" } ], @@ -1313,6 +1327,7 @@ "files": [ { "path": "src/core/modal/modal.tsx", + "target": "components/ui/modal.tsx", "type": "registry:component" } ], @@ -1404,6 +1419,7 @@ "files": [ { "path": "src/core/popover/popover.tsx", + "target": "components/ui/popover.tsx", "type": "registry:component" } ], @@ -1496,6 +1512,7 @@ "files": [ { "path": "src/core/radio-group/radio-group.tsx", + "target": "components/ui/radio-group.tsx", "type": "registry:component" } ], @@ -1589,6 +1606,7 @@ "files": [ { "path": "src/core/select/select.tsx", + "target": "components/ui/select.tsx", "type": "registry:component" } ], @@ -1682,6 +1700,7 @@ "files": [ { "path": "src/core/slider/slider.tsx", + "target": "components/ui/slider.tsx", "type": "registry:component" } ], @@ -1775,6 +1794,7 @@ "files": [ { "path": "src/core/switch/switch.tsx", + "target": "components/ui/switch.tsx", "type": "registry:component" } ], @@ -1868,6 +1888,7 @@ "files": [ { "path": "src/core/table/table.tsx", + "target": "components/ui/table.tsx", "type": "registry:component" } ], @@ -1964,6 +1985,7 @@ "files": [ { "path": "src/core/tabs/tabs.tsx", + "target": "components/ui/tabs.tsx", "type": "registry:component" } ], @@ -2057,6 +2079,7 @@ "files": [ { "path": "src/core/tag-group/tag-group.tsx", + "target": "components/ui/tag-group.tsx", "type": "registry:component" } ], @@ -2151,6 +2174,7 @@ "files": [ { "path": "src/core/time-field/time-field.tsx", + "target": "components/ui/time-field.tsx", "type": "registry:component" } ], @@ -2244,6 +2268,7 @@ "files": [ { "path": "src/core/toggle/toggle.tsx", + "target": "components/ui/toggle.tsx", "type": "registry:component" } ], @@ -2337,6 +2362,7 @@ "files": [ { "path": "src/core/tooltip/tooltip.tsx", + "target": "components/ui/tooltip.tsx", "type": "registry:component" } ], diff --git a/web/public/r/select.json b/web/public/r/select.json index 1dfb0bd..757350f 100644 --- a/web/public/r/select.json +++ b/web/public/r/select.json @@ -15,7 +15,8 @@ { "path": "src/core/select/select.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport type {\n\tSelectProps as AriaSelectProps,\n\tListBoxItemProps,\n\tValidationResult,\n} from \"react-aria-components\";\nimport {\n\tSelect as AriaSelect,\n\tAutocomplete,\n\tButton,\n\tFieldError,\n\tInput,\n\tLabel,\n\tListBox,\n\tListBoxItem,\n\tPopover,\n\tSearchField,\n\tSelectValue,\n\tText,\n\tuseFilter,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CheckIcon, ChevronDown, Search } from \"lucide-react\";\n\nconst select = tv({\n\tslots: {\n\t\tgroup: \"group flex flex-col gap-1\",\n\t\tbutton:\n\t\t\t\"group flex w-fit items-center justify-between gap-4 rounded-full border border-border bg-surface px-4 py-2.75 align-middle font-semibold text-fg text-sm outline-none ring-fg transition-all data-[hovered]:bg-surface-2 group-data-[focus-visible]:border-transparent group-data-[open]:bg-surface-2 group-data-[focus-visible]:ring-2\",\n\t\titem: \"relative m-1 flex cursor-default flex-col rounded-lg p-2 font-semibold outline-none data-[disabled]:cursor-not-allowed data-[focused]:bg-secondary data-[disabled]:text-fg-disabled\",\n\t\tsearchField:\n\t\t\t\"group m-1 flex items-center rounded-full border border-border bg-surface px-2 py-1.5\",\n\t\tsearchInput:\n\t\t\t\"flex-1 bg-transparent text-fg outline-none placeholder:text-fg-muted\",\n\t\tsearchIcon: \"mr-2 size-4 text-fg-muted\",\n\t\tclearButton:\n\t\t\t\"ml-2 rounded p-0.5 text-fg-muted transition-colors hover:bg-surface-2 hover:text-fg group-empty:invisible\",\n\t\tpopover:\n\t\t\t\"min-w-[var(--trigger-width)] rounded-xl border border-border/25 bg-surface p-1 text-fg shadow-lg outline-none\",\n\t},\n});\n\nconst styles = select();\n\ninterface SelectProps\n\textends Omit, \"className\"> {\n\tclassName?: string;\n\tpopoverClassName?: string;\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string | ((validation: ValidationResult) => string);\n}\n\nconst Select = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tpopoverClassName,\n\tchildren,\n\t...props\n}: SelectProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\t\n\t\t\t{children}\n\t\t\n\t\n);\n\ninterface SelectItemProps\n\textends Omit {\n\tchildren: ReactNode;\n\tclassName?: string;\n}\n\nconst SelectItem = ({ className, ...props }: SelectItemProps) => (\n\t\n\t\t{({ isSelected }) => (\n\t\t\t
\n\t\t\t\t{props.children}\n\t\t\t\t{isSelected && }\n\t\t\t
\n\t\t)}\n\t
\n);\n\ninterface SearchableSelectProps\n\textends SelectProps {\n\tsearchPlaceholder?: string;\n}\n\nconst SearchableSelect = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\tsearchPlaceholder = \"Search...\",\n\tchildren,\n\tpopoverClassName,\n\t...props\n}: SearchableSelectProps) => {\n\tconst { contains } = useFilter({ sensitivity: \"base\" });\n\n\treturn (\n\t\t\n\t\t\t{label && }\n\t\t\t\n\t\t\t{description && (\n\t\t\t\t\n\t\t\t\t\t{description}\n\t\t\t\t\n\t\t\t)}\n\t\t\t{errorMessage}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{children}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nexport { Select, SelectItem, SearchableSelect };\nexport type { SelectProps, SelectItemProps, SearchableSelectProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/select.tsx" } ], "tailwind": { diff --git a/web/public/r/slider.json b/web/public/r/slider.json index 5438a64..23b4c11 100644 --- a/web/public/r/slider.json +++ b/web/public/r/slider.json @@ -15,7 +15,8 @@ { "path": "src/core/slider/slider.tsx", "content": "\"use client\";\n\nimport {\n\tSlider as AriaSlider,\n\tSliderThumb as AriaSliderThumb,\n\tSliderTrack as AriaSliderTrack,\n\tLabel,\n\ttype LabelProps,\n\tSliderOutput,\n\ttype SliderProps,\n\ttype SliderThumbProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst slider = tv({\n\tslots: {\n\t\troot: \"grid w-64 auto-cols-fr grid-cols-1 text-fg-muted\",\n\t\tthumb:\n\t\t\t\"h-5 w-5 rounded-full bg-primary ring-focus ring-offset-2 ring-offset-surface data-[dragging]:outline-2 data-[focus-visible]:ring-2\",\n\t\ttrack:\n\t\t\t\"before:-translate-y-1/2 relative col-span-2 col-start-1 w-full before:absolute before:top-1/2 before:h-0.5 before:w-full before:transform before:bg-secondary\",\n\t},\n});\n\nconst { root, thumb, track } = slider();\n\nconst SliderRoot = ({\n\tchildren,\n\tclassName,\n\t...props\n}: SliderProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst SliderThumb = ({\n\tchildren,\n\tclassName,\n\t...props\n}: SliderThumbProps & { className?: string }) => (\n\t\n\t\t\n\t\n);\n\nconst SliderLabel = ({\n\tchildren,\n\tclassName,\n\t...props\n}: LabelProps & { className?: string }) => (\n\t
\n\t\t\n\t\t\n\t
\n);\n\nexport { SliderRoot, SliderThumb, SliderLabel };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/slider.tsx" } ], "tailwind": { diff --git a/web/public/r/switch.json b/web/public/r/switch.json index 9e29c0c..f75434f 100644 --- a/web/public/r/switch.json +++ b/web/public/r/switch.json @@ -15,7 +15,8 @@ { "path": "src/core/switch/switch.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tSwitch as AriaSwitch,\n\ttype SwitchProps as AriaSwitchProps,\n\tLabel,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst switchStyles = tv({\n\tslots: {\n\t\troot: \"group flex items-center gap-2 transition-none duration-200\",\n\t\tindicator:\n\t\t\t\"h-6 w-10 cursor-pointer rounded-xl bg-secondary duration-200 before:mx-[3px] before:mt-[3px] before:block before:size-4.5 before:rounded-2xl before:bg-surface before:transition-all data-[selected]:bg-primary group-data-[selected]:bg-primary group-data-[focus-visible]:ring-2 group-data-[focus-visible]:ring-focus group-data-[focus-visible]:ring-offset-2 group-data-[focus-visible]:ring-offset-surface group-data-[selected]:before:translate-x-4\",\n\t\tlabel: \"font-semibold text-fg text-sm\",\n\t},\t\n});\n\nconst styles = switchStyles();\n\ninterface SwitchProps extends AriaSwitchProps {\n\tchildren?: ReactNode;\n\tclassName?: string;\n}\n\n const Switch = ({ className, children, ...restProps }: SwitchProps) => (\n\t\n\t\t
\n\t\t\n\t\n);\n\nexport { Switch };\nexport type { SwitchProps };", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/switch.tsx" } ], "tailwind": { diff --git a/web/public/r/table.json b/web/public/r/table.json index 674e3db..9b52e06 100644 --- a/web/public/r/table.json +++ b/web/public/r/table.json @@ -19,7 +19,8 @@ { "path": "src/core/table/table.tsx", "content": "\"use client\";\n\nimport {\n\tColumn as AriaColumn,\n\tTable as AriaTable,\n\tTableBody as AriaTableBody,\n\tTableHeader as AriaTableheader,\n\tCell,\n\ttype CellProps,\n\tCollection,\n\ttype ColumnProps,\n\tRow,\n\ttype RowProps,\n\ttype TableHeaderProps,\n\ttype TableProps,\n\tuseTableOptions,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Menu } from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button/button\";\nimport { Checkbox } from \"@/components/ui/checkbox/checkbox\";\n\nconst table = tv({\n\tslots: {\n\t\troot: \"table min-h-[100px] border-separate border-spacing-0 rounded-xl border border-border p-4 outline-none\",\n\t\tcolumn: \"border-border border-b-2 px-4 py-1 text-left outline-none\",\n\t\theader: \"text-fg after:table-row after:h-[2px]\",\n\t\tlabel: \"text-fg-3\",\n\t\trow: \"relative cursor-default rounded-xl text-fg outline-none ring-focus data-[focus-visible]:ring-2\",\n\t\tcell: \"px-4 py-2 outline-none ring-focus data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = table();\n\nconst TableBody = AriaTableBody;\n\nconst Table = ({\n\tchildren,\n\tclassName,\n\t...props\n}: TableProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableCell = ({\n\tchildren,\n\tclassName,\n\t...props\n}: CellProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableColumn = ({\n\tchildren,\n\tclassName,\n\t...props\n}: ColumnProps & { className?: string }) => (\n\t\n\t\t{children}\n\t\n);\n\nconst TableHeader = ({\n\tchildren,\n\tclassName,\n\tcolumns,\n\t...props\n}: TableHeaderProps & { className?: string }) => {\n\tconst { selectionBehavior, selectionMode, allowsDragging } =\n\t\tuseTableOptions();\n\treturn (\n\t\t\n\t\t\t{/* Add extra columns for drag and drop and selection. */}\n\t\t\t{allowsDragging && }\n\t\t\t{selectionBehavior === \"toggle\" && (\n\t\t\t\t\n\t\t\t\t\t{selectionMode === \"multiple\" && (\n\t\t\t\t\t\t \n\t\t\t\t\t)}\n\t\t\t\t\n\t\t\t)}\n\t\t\t{children}\n\t\t\n\t);\n};\n\nconst TableRow = ({\n\tchildren,\n\tclassName,\n\tcolumns,\n\tid,\n\t...props\n}: RowProps & { className?: string }) => {\n\tconst { selectionBehavior, allowsDragging } = useTableOptions();\n\treturn (\n\t\t\n\t\t\t{allowsDragging && (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t)}\n\t\t\t{selectionBehavior === \"toggle\" && (\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t\n\t\t\t)}\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport { TableColumn, Table, TableBody, TableCell, TableHeader, TableRow };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/table.tsx" } ], "tailwind": { diff --git a/web/public/r/tabs.json b/web/public/r/tabs.json index 4202aca..cdfd098 100644 --- a/web/public/r/tabs.json +++ b/web/public/r/tabs.json @@ -15,7 +15,8 @@ { "path": "src/core/tabs/tabs.tsx", "content": "\"use client\";\n\nimport {\n\tTab as AriaTab,\n\tTabList as AriaTabList,\n\ttype TabListProps as AriaTabListProps,\n\tTabPanel as AriaTabPanel,\n\ttype TabPanelProps as AriaTabPanelProps,\n\ttype TabProps as AriaTabProps,\n\ttype TabsProps as AriaTabsProps,\n\tTabs as AriaTabsRoot,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tabs = tv({\n\tslots: {\n\t\troot: \"flex w-full flex-col items-start\",\n\t\tlist: \"relative inline-flex items-center justify-between gap-6 rounded-md p-1\",\n\t\ttab: \"relative flex w-fit cursor-pointer justify-center rounded-2xl border-primary pb-0.5 font-semibold text-fg-muted outline-none ring-focus ring-offset-2 ring-offset-surface transition-colors duration-200 aria-selected:cursor-default aria-selected:rounded-none aria-selected:border-b-2 aria-selected:pb-0 aria-selected:text-primary aria-selected:hover:bg-transparent data-[hovered]:text-primary data-[focus-visible]:ring-2\",\n\t\tpanel:\n\t\t\t\"mt-4 w-96 rounded-xl p-4 outline-none ring-focus data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = tabs();\n\ninterface TabsProps extends Omit {\n\tclassName?: string;\n}\n\nconst TabsRoot = ({ children, className, ...props }: TabsProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabListProps extends Omit, \"className\"> {\n\tclassName?: string;\n}\n\nconst TabList = ({\n\tchildren,\n\tclassName,\n\t...props\n}: TabListProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabProps extends Omit {\n\tclassName?: string;\n}\n\nconst Tab = ({ children, className, ...props }: TabProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface TabPanelProps extends Omit {\n\tclassName?: string;\n}\n\nconst TabPanel = ({ children, className, ...props }: TabPanelProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Tab, TabList, TabPanel, TabsRoot };\nexport type { TabsProps, TabListProps, TabProps, TabPanelProps }; ", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/tabs.tsx" } ], "tailwind": { diff --git a/web/public/r/tag-group.json b/web/public/r/tag-group.json index afa29b9..6d7eada 100644 --- a/web/public/r/tag-group.json +++ b/web/public/r/tag-group.json @@ -15,7 +15,8 @@ { "path": "src/core/tag-group/tag-group.tsx", "content": "\"use client\";\n\nimport {\n\tTag as AriaTag,\n\tTagGroup as AriaTagGroup,\n\ttype TagGroupProps as AriaTagGroupProps,\n\ttype TagProps as AriaTagProps,\n\tLabel,\n\tTagList,\n\ttype TagListProps,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tagGroup = tv({\n\tslots: {\n\t\troot: \"flex flex-col gap-2 text-sm\",\n\t\tlist: \"flex flex-wrap gap-2\",\n\t\ttag: \"flex cursor-default items-center rounded-full border border-border px-2 py-1 outline-none ring-focus ring-offset-2 ring-offset-surface aria-selected:border-primary aria-selected:bg-primary aria-selected:text-primary-fg data-[focus-visible]:ring-2\",\n\t},\n});\n\nconst styles = tagGroup();\n\ninterface TagGroupProps\n\textends Omit,\n\t\tPick, \"items\" | \"children\" | \"renderEmptyState\"> {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst TagGroup = ({\n\tlabel,\n\tclassName,\n\tdescription,\n\terrorMessage,\n\titems,\n\tchildren,\n\trenderEmptyState,\n\t...props\n}: TagGroupProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{children}\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage && (\n\t\t\t\n\t\t\t\t{errorMessage}\n\t\t\t\n\t\t)}\n\t\n);\n\nconst Tag = ({\n\tchildren,\n\tclassName,\n\t...props\n}: AriaTagProps & { className?: string }) => {\n\tconst textValue = typeof children === \"string\" ? children : undefined;\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport { Tag, TagGroup };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/tag-group.tsx" } ], "tailwind": { diff --git a/web/public/r/time-field.json b/web/public/r/time-field.json index 9a81f1c..4bec1f4 100644 --- a/web/public/r/time-field.json +++ b/web/public/r/time-field.json @@ -15,7 +15,8 @@ { "path": "src/core/time-field/time-field.tsx", "content": "\"use client\";\n\nimport type {\n\tTimeFieldProps as AriaTimeFieldProps,\n\tTimeValue,\n} from \"react-aria-components\";\nimport {\n\tTimeField as AriaTimeField,\n\tDateInput,\n\tDateSegment,\n\tFieldError,\n\tLabel,\n\tText,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst timeField = tv({\n\tslots: {\n\t\tinput:\n\t\t\t\"appearance-none rounded-lg border border-border bg-surface px-3 py-1.75 outline-none ring-primary transition-all data-[disabled]:cursor-not-allowed data-[focus-within]:border-transparent data-[disabled]:bg-primary/10 data-[focus-within]:bg-surface data-[disabled]:text-fg-disabled data-[focus-within]:ring-2 [&::placeholder]:text-sm [&::placeholder]:focus:text-primary-fg\",\n\t\tsegmentStyles:\n\t\t\t\"rounded-md p-1 text-end outline-none focus:bg-primary focus:text-primary-fg data-[placeholder]:text-fg-muted data-[type='literal']:text-fg-muted\",\n\t},\n});\n\nconst styles = timeField();\n\ninterface TimeFieldProps extends AriaTimeFieldProps {\n\tlabel?: string;\n\tdescription?: string;\n\terrorMessage?: string;\n}\n\nconst TimeField = ({\n\tlabel,\n\tdescription,\n\terrorMessage,\n\t...props\n}: TimeFieldProps) => (\n\t\n\t\t{label && }\n\t\t\n\t\t\t{(segment) => (\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t\t{description && (\n\t\t\t\n\t\t\t\t{description}\n\t\t\t\n\t\t)}\n\t\t{errorMessage}\n\t\n);\n\nexport { TimeField };\nexport type { TimeFieldProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/time-field.tsx" } ], "tailwind": { diff --git a/web/public/r/toggle.json b/web/public/r/toggle.json index 5124ea2..7546fcf 100644 --- a/web/public/r/toggle.json +++ b/web/public/r/toggle.json @@ -15,7 +15,8 @@ { "path": "src/core/toggle/toggle.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tToggleButton,\n\tToggleButtonGroup,\n\ttype ToggleButtonGroupProps,\n\ttype ToggleButtonProps,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst toggle = tv({\n\tbase: \"inline-flex appearance-none items-center justify-center rounded-full bg-surface-2 px-4 py-1 font-medium outline-none ring-focus ring-offset-2 ring-offset-surface transition-transform duration-100 disabled:pointer-events-none disabled:opacity-50 data-[selected]:bg-primary data-[selected]:text-primary-fg data-[focus-visible]:ring-2\",\n});\n\nconst toggleGroup = tv({\n\tbase: \"flex min-h-11 gap-1 rounded-full border border-border bg-surface-2 p-1\",\n});\n\ninterface ToggleProps extends Omit {\n\tclassName?: string;\n}\n\nconst Toggle = ({ className, children, ...props }: ToggleProps) => (\n\t\n\t\t{children}\n\t\n);\n\ninterface ToggleGroupProps extends ToggleButtonGroupProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst ToggleGroup = ({ className, children, ...props }: ToggleGroupProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Toggle, ToggleGroup };\nexport type { ToggleProps, ToggleGroupProps };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/toggle.tsx" } ], "tailwind": { diff --git a/web/public/r/tooltip.json b/web/public/r/tooltip.json index b0792c3..67a1a45 100644 --- a/web/public/r/tooltip.json +++ b/web/public/r/tooltip.json @@ -15,7 +15,8 @@ { "path": "src/core/tooltip/tooltip.tsx", "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\n\nimport {\n\tTooltip as AriaTooltip,\n\ttype TooltipProps as AriaTooltipProps,\n\tTooltipTrigger as AriaTooltipTrigger,\n} from \"react-aria-components\";\nimport { tv } from \"tailwind-variants\";\n\nconst tooltip = tv({\n\tbase: \"[&[data-entering]]:fade-in [&[data-exiting]]:fade-out m-1 max-w-sm rounded-full border border-border bg-surface px-4 py-2 text-fg shadow-xl outline-none [&[data-entering]]:animate-fade-in [&[data-exiting]]:animate-fade-out\",\n});\n\nconst TooltipTrigger = AriaTooltipTrigger;\n\ninterface TooltipProps extends Omit {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nconst Tooltip = ({ children, className, ...props }: TooltipProps) => (\n\t\n\t\t{children}\n\t\n);\n\nexport { Tooltip, TooltipTrigger };\n", - "type": "registry:component" + "type": "registry:component", + "target": "components/ui/tooltip.tsx" } ], "tailwind": {