chore(ui): Full type documentation (#10)

* Adds typedoc for docs consolidation

* chore: add UI types

* fix: remove latent docs
This commit is contained in:
Ian Cameron Lyles 2025-02-27 17:07:33 -08:00 committed by GitHub
parent 52512beaa2
commit 71fac7ffa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
69 changed files with 4336 additions and 634 deletions

34
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Generate and Deploy Documentation
on:
push:
branches: [ main, master, develop, develop-qwrk ] # Trigger on push to these branches
workflow_dispatch: # Allow manual triggering
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for proper versioning
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Generate documentation
run: node scripts/generate-docs.js
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages # The branch the action should deploy to
folder: docs # The folder the action should deploy
clean: true # Automatically remove deleted files from the deploy branch

6
.gitignore vendored
View File

@ -3,6 +3,7 @@ yarn-error.log
.yarnrc.yml
.yarn/
.yarnrc
.cursor
packages/backend/environments/local.toml
packages/backend/dev/
@ -10,4 +11,7 @@ packages/frontend/dist/
# ignore all .DS_Store files
**/.DS_Store
.vscode
.vscode
# TypeDoc generated documentation
/docs

165
DOCUMENTATION.md Normal file
View File

@ -0,0 +1,165 @@
# Documentation Guide for Snowball Tools
This guide explains how to write and generate documentation for the Snowball Tools project.
## TSDoc and TypeDoc
We use [TSDoc](https://tsdoc.org/) for documenting our TypeScript code and [TypeDoc](https://typedoc.org/) for generating API documentation from those comments.
## Writing Documentation
### Basic Comment Structure
TSDoc comments start with `/**` and end with `*/`. Each line within the comment block typically starts with a `*`.
```typescript
/**
* This is a TSDoc comment.
*/
```
### Documenting Functions
```typescript
/**
* Calculates the sum of two numbers.
*
* @param a - The first number
* @param b - The second number
* @returns The sum of a and b
*
* @example
* ```ts
* const result = add(1, 2);
* console.log(result); // 3
* ```
*/
function add(a: number, b: number): number {
return a + b;
}
```
### Documenting Classes
```typescript
/**
* Represents a user in the system.
*
* @remarks
* This class is used throughout the application to represent user data.
*
* @example
* ```ts
* const user = new User('John', 'Doe');
* console.log(user.fullName); // "John Doe"
* ```
*/
class User {
/**
* Creates a new User instance.
*
* @param firstName - The user's first name
* @param lastName - The user's last name
*/
constructor(
/** The user's first name */
public firstName: string,
/** The user's last name */
public lastName: string
) {}
/**
* Gets the user's full name.
*/
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
```
### Documenting Interfaces
```typescript
/**
* Configuration options for the application.
*
* @public
*/
interface AppConfig {
/**
* The port number the server should listen on.
* @default 3000
*/
port: number;
/**
* The host the server should bind to.
* @default "localhost"
*/
host: string;
/**
* Whether to enable debug mode.
* @default false
*/
debug?: boolean;
}
```
## Common TSDoc Tags
| Tag | Description |
|-----|-------------|
| `@param` | Documents a function parameter |
| `@returns` | Documents the return value |
| `@throws` | Documents exceptions that might be thrown |
| `@example` | Provides an example of usage |
| `@remarks` | Adds additional information |
| `@deprecated` | Marks an item as deprecated |
| `@see` | Refers to related documentation |
| `@default` | Documents the default value |
| `@public`, `@protected`, `@private` | Visibility modifiers |
| `@internal` | Marks an item as internal (not part of the public API) |
| `@beta` | Marks an item as in beta stage |
| `@alpha` | Marks an item as in alpha stage |
| `@experimental` | Marks an item as experimental |
## Generating Documentation
To generate documentation for the project, run:
```bash
yarn docs
```
This will create a `docs` directory with the generated documentation.
To watch for changes and regenerate documentation automatically:
```bash
yarn docs:watch
```
## Best Practices
1. **Document Public APIs**: Always document public APIs thoroughly.
2. **Include Examples**: Provide examples for complex functions or classes.
3. **Be Concise**: Keep documentation clear and to the point.
4. **Use Proper Grammar**: Use proper grammar and punctuation.
5. **Update Documentation**: Keep documentation in sync with code changes.
6. **Document Parameters**: Document all parameters, including their types and purpose.
7. **Document Return Values**: Document what a function returns.
8. **Document Exceptions**: Document any exceptions that might be thrown.
## Example Files
For reference, check out these example files that demonstrate proper TSDoc usage:
- `packages/backend/src/utils/tsdoc-example.ts`
- `packages/frontend/src/utils/tsdoc-example.ts`
## Resources
- [TSDoc Official Documentation](https://tsdoc.org/)
- [TypeDoc Official Documentation](https://typedoc.org/)
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)

View File

@ -21,3 +21,19 @@ yarn build --ignore frontend
### Environment variables, running the development server, and deployment
Follow the instructions in the README.md files of the [backend](packages/backend/README.md) and [frontend](packages/frontend/README.md) packages.
## Documentation
This project uses TSDoc for code documentation and TypeDoc for generating API documentation.
### Generating Documentation
To generate the API documentation, run:
```zsh
yarn docs
```
This will create a `docs` directory with the generated documentation.
For more information about writing documentation, see [DOCUMENTATION.md](DOCUMENTATION.md).

114
docs-readme.md Normal file
View File

@ -0,0 +1,114 @@
# Snowball Tools API Documentation
This documentation is automatically generated using [TypeDoc](https://typedoc.org/) from TSDoc comments in the codebase.
## Packages
The monorepo contains the following packages:
- **frontend**: The frontend web application
- **backend**: The backend API server
- **gql-client**: GraphQL client library
- **deployer**: Deployment utilities
## How to Use This Documentation
The documentation is organized by packages and modules. You can navigate through the sidebar to explore the different parts of the codebase.
## Contributing to Documentation
To contribute to the documentation:
1. Add TSDoc comments to your code using the JSDoc syntax
2. Run `yarn docs` to generate the documentation
3. Preview the documentation in the `docs` directory
## TSDoc Comment Examples
### Function Documentation
```typescript
/**
* Calculates the sum of two numbers.
*
* @param a - The first number
* @param b - The second number
* @returns The sum of a and b
*
* @example
* ```ts
* const result = add(1, 2);
* console.log(result); // 3
* ```
*/
function add(a: number, b: number): number {
return a + b;
}
```
### Class Documentation
```typescript
/**
* Represents a user in the system.
*
* @remarks
* This class is used throughout the application to represent user data.
*
* @example
* ```ts
* const user = new User('John', 'Doe');
* console.log(user.fullName); // "John Doe"
* ```
*/
class User {
/**
* Creates a new User instance.
*
* @param firstName - The user's first name
* @param lastName - The user's last name
*/
constructor(
/** The user's first name */
public firstName: string,
/** The user's last name */
public lastName: string
) {}
/**
* Gets the user's full name.
*/
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
```
### Interface Documentation
```typescript
/**
* Configuration options for the application.
*
* @public
*/
interface AppConfig {
/**
* The port number the server should listen on.
* @default 3000
*/
port: number;
/**
* The host the server should bind to.
* @default "localhost"
*/
host: string;
/**
* Whether to enable debug mode.
* @default false
*/
debug?: boolean;
}
```

View File

@ -5,12 +5,15 @@
"packages/*"
],
"devDependencies": {
"chalk": "^4.1.2",
"concurrently": "^8.2.0",
"depcheck": "^1.4.2",
"husky": "^8.0.3",
"lerna": "^8.0.0",
"patch-package": "^8.0.0",
"chalk": "^4.1.2",
"concurrently": "^8.2.0"
"rimraf": "^6.0.1",
"typedoc": "^0.27.9",
"typedoc-plugin-markdown": "^4.4.2"
},
"scripts": {
"prepare": "husky install",
@ -19,8 +22,11 @@
"start": "yarn kill:ports && yarn dev",
"dev": "yarn && yarn build --ignore frontend && concurrently --names \"BACKEND,FRONTEND\" --prefix-colors \"blue.bold,green.bold\" --prefix \"[{name}]\" \"yarn start:backend\" \"yarn start:frontend\"",
"start:backend": "yarn workspace backend start",
"start:frontend": "yarn workspace frontend dev",
"kill:ports": "node scripts/kill-ports.js"
"start:frontend": "yarn workspace frontend dev",
"kill:ports": "node scripts/kill-ports.js",
"docs": "node scripts/generate-docs.js",
"docs:clean": "node scripts/generate-docs.js --clean",
"docs:watch": "typedoc --watch"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
}

View File

@ -0,0 +1,237 @@
/**
* This file demonstrates proper TSDoc usage for the Snowball Tools project.
*
* @packageDocumentation
* @module Utils
*/
/**
* Configuration options for the application.
*
* @public
*/
export interface AppConfig {
/**
* The port number the server should listen on.
* @default 3000
*/
port: number;
/**
* The host the server should bind to.
* @default "localhost"
*/
host: string;
/**
* Whether to enable debug mode.
* @default false
*/
debug?: boolean;
}
/**
* Represents a user in the system.
*
* @remarks
* This class is used throughout the application to represent user data.
*
* @example
* ```ts
* const user = new User('John', 'Doe');
* console.log(user.fullName); // "John Doe"
* ```
*/
export class User {
/**
* Creates a new User instance.
*
* @param firstName - The user's first name
* @param lastName - The user's last name
*/
constructor(
/** The user's first name */
public firstName: string,
/** The user's last name */
public lastName: string
) {}
/**
* Gets the user's full name.
*
* @returns The user's full name as a string
*/
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
/**
* Updates the user's name.
*
* @param firstName - The new first name
* @param lastName - The new last name
* @returns The updated user instance
*
* @throws {Error} If either name is empty
*/
updateName(firstName: string, lastName: string): User {
if (!firstName || !lastName) {
throw new Error('First name and last name cannot be empty');
}
this.firstName = firstName;
this.lastName = lastName;
return this;
}
}
/**
* Calculates the sum of two numbers.
*
* @param a - The first number
* @param b - The second number
* @returns The sum of a and b
*
* @example
* ```ts
* const result = add(1, 2);
* console.log(result); // 3
* ```
*/
export function add(a: number, b: number): number {
return a + b;
}
/**
* Formats a date according to the specified format.
*
* @param date - The date to format
* @param format - The format string (default: 'YYYY-MM-DD')
* @returns The formatted date string
*
* @remarks
* This function uses a simple format string where:
* - YYYY: 4-digit year
* - MM: 2-digit month
* - DD: 2-digit day
*
* @example
* ```ts
* const date = new Date('2023-01-15');
* const formatted = formatDate(date);
* console.log(formatted); // "2023-01-15"
* ```
*/
export function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return format
.replace('YYYY', year.toString())
.replace('MM', month)
.replace('DD', day);
}
/**
* Type of log level for the application.
*/
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
/**
* A simple logger utility.
*
* @remarks
* This logger provides methods for different log levels and can be configured
* to filter logs based on minimum level.
*/
export class Logger {
/**
* Creates a new Logger instance.
*
* @param name - The name of the logger
* @param minLevel - The minimum log level to display (default: 'info')
*/
constructor(
private name: string,
private minLevel: LogLevel = 'info'
) {}
/**
* Logs a debug message.
*
* @param message - The message to log
* @param data - Optional data to include
*/
debug(message: string, data?: unknown): void {
this.log('debug', message, data);
}
/**
* Logs an info message.
*
* @param message - The message to log
* @param data - Optional data to include
*/
info(message: string, data?: unknown): void {
this.log('info', message, data);
}
/**
* Logs a warning message.
*
* @param message - The message to log
* @param data - Optional data to include
*/
warn(message: string, data?: unknown): void {
this.log('warn', message, data);
}
/**
* Logs an error message.
*
* @param message - The message to log
* @param error - Optional error to include
*/
error(message: string, error?: Error): void {
this.log('error', message, error);
}
/**
* Internal method to handle logging.
*
* @param level - The log level
* @param message - The message to log
* @param data - Optional data to include
*
* @internal
*/
private log(level: LogLevel, message: string, data?: unknown): void {
const levels: Record<LogLevel, number> = {
debug: 0,
info: 1,
warn: 2,
error: 3
};
if (levels[level] >= levels[this.minLevel]) {
const timestamp = new Date().toISOString();
const formattedMessage = `[${timestamp}] [${level.toUpperCase()}] [${this.name}] ${message}`;
switch (level) {
case 'debug':
console.debug(formattedMessage, data || '');
break;
case 'info':
console.info(formattedMessage, data || '');
break;
case 'warn':
console.warn(formattedMessage, data || '');
break;
case 'error':
console.error(formattedMessage, data || '');
break;
}
}
}
}

View File

@ -65,7 +65,7 @@
"axios": "^1.6.7",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"cmdk": "^1.0.4",
"date-fns": "^4.1.0",
"downshift": "^8.3.2",
"embla-carousel-react": "^8.5.2",

View File

@ -1,11 +1,11 @@
import React, { forwardRef, RefAttributes } from 'react';
import { IconInput, InputProps } from '@/components/ui';
import { IconInput, type IconInputProps } from '@/components/ui/extended/input-w-icons';
import { Search } from 'lucide-react';
const SearchBar: React.ForwardRefRenderFunction<
HTMLInputElement,
InputProps & RefAttributes<HTMLInputElement>
IconInputProps & RefAttributes<HTMLInputElement>
> = ({ value, onChange, placeholder = 'Search', ...props }, ref) => {
return (
<div className="relative flex w-full">

View File

@ -2,7 +2,7 @@ import {
Calendar as CalendarComponent,
CalendarProps,
} from '@/components/shared/Calendar';
import { IconInput, InputProps } from '@/components/ui';
import { IconInput, type IconInputProps } from '@/components/ui/extended/input-w-icons';
import { Value } from '@/types/vendor';
import * as Popover from '@radix-ui/react-popover';
import { format } from 'date-fns';
@ -11,7 +11,7 @@ import { useCallback, useMemo, useState } from 'react';
import { datePickerTheme } from './DatePicker.theme';
export interface DatePickerProps
extends Omit<InputProps, 'onChange' | 'value'> {
extends Omit<IconInputProps, 'onChange' | 'value'> {
/**
* The props for the calendar component.
*/

View File

@ -0,0 +1,113 @@
"use client"
import { Check, ChevronsUpDown } from "lucide-react"
import * as React from "react"
import { Button } from "@/components/ui/button"
import {
Combobox,
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
Popover,
PopoverContent,
PopoverTrigger
} from "@/components/ui/combobox"
import { cn } from "@/lib/utils"
const frameworks = [
{
value: "next.js",
label: "Next.js",
},
{
value: "sveltekit",
label: "SvelteKit",
},
{
value: "nuxt.js",
label: "Nuxt.js",
},
{
value: "remix",
label: "Remix",
},
{
value: "astro",
label: "Astro",
},
]
export function ComboboxDemo() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("")
return (
<div className="flex flex-col gap-4">
{/* Method 1: Using the individual components */}
<div>
<h3 className="mb-2 text-lg font-medium">Method 1: Using individual components</h3>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? frameworks.find((framework) => framework.value === value)?.label
: "Select framework..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search framework..." className="h-9" />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
{framework.label}
<Check
className={cn(
"ml-auto h-4 w-4",
value === framework.value ? "opacity-100" : "opacity-0"
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
{/* Method 2: Using the Combobox component */}
<div>
<h3 className="mb-2 text-lg font-medium">Method 2: Using the Combobox component</h3>
<Combobox
options={frameworks}
value={value}
onChange={setValue}
placeholder="Select framework..."
emptyMessage="No framework found."
searchPlaceholder="Search framework..."
className="w-[200px]"
/>
</div>
</div>
)
}

View File

@ -1,11 +1,51 @@
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDown } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A vertically stacked set of interactive headings that each reveal associated content.
* Composes with Radix UI's Accordion primitives.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'single' | 'multiple'} props.type - Whether single or multiple items can be open
* @param {boolean} [props.collapsible] - Whether an open item can be collapsed
* @param {React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root>} props... - All Radix AccordionRoot props
*
* @example
* <Accordion type="single" collapsible>
* <AccordionItem value="item-1">
* <AccordionTrigger>Is it accessible?</AccordionTrigger>
* <AccordionContent>Yes. Adheres to WAI-ARIA patterns.</AccordionContent>
* </AccordionItem>
* </Accordion>
*
* @see {@link https://ui.shadcn.com/docs/components/accordion | Shadcn Accordion Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/accordion | Radix Accordion Primitive}
*/
const Accordion = AccordionPrimitive.Root
/**
* An individual accordion item that contains the trigger and content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.value - Unique value to identify the item
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>} props... - All Radix Item props
*
* @example
* <AccordionItem value="item-1" className="border-b">
* <AccordionTrigger>Section 1</AccordionTrigger>
* <AccordionContent>Content</AccordionContent>
* </AccordionItem>
*/
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
@ -18,6 +58,23 @@ const AccordionItem = React.forwardRef<
))
AccordionItem.displayName = "AccordionItem"
/**
* The interactive button that toggles the accordion content visibility.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.disabled] - Whether the trigger is disabled
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>} props... - All Radix Trigger props
*
* @example
* <AccordionTrigger className="flex w-full items-center py-4">
* <span>Section Title</span>
* <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
* </AccordionTrigger>
*/
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
@ -26,30 +83,43 @@ const AccordionTrigger = React.forwardRef<
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
/**
* The collapsible content section of the accordion item.
*
* @component
* @public
* @example
* <AccordionContent className="pb-4 pt-0">
* Collapsible content section
* </AccordionContent>
*/
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
className={cn(
"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
className
)}
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
<div className="pb-4 pt-0">{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }

View File

@ -1,15 +1,63 @@
import * as React from "react"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
import * as React from "react"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
/**
* A modal dialog that interrupts the user with important content and expects a response.
*
* @component
* @public
*
* @example
* ```tsx
* <AlertDialog>
* <AlertDialogTrigger>Open</AlertDialogTrigger>
* <AlertDialogContent>
* <AlertDialogHeader>
* <AlertDialogTitle>Are you sure?</AlertDialogTitle>
* <AlertDialogDescription>
* This action cannot be undone.
* </AlertDialogDescription>
* </AlertDialogHeader>
* <AlertDialogFooter>
* <AlertDialogCancel>Cancel</AlertDialogCancel>
* <AlertDialogAction>Continue</AlertDialogAction>
* </AlertDialogFooter>
* </AlertDialogContent>
* </AlertDialog>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/alert-dialog | Shadcn AlertDialog Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/alert-dialog | Radix AlertDialog Primitive}
*/
const AlertDialog = AlertDialogPrimitive.Root
/**
* Button that triggers the alert dialog to open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props onto child
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Trigger>} props... - All Radix AlertDialogTrigger props
*/
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
const AlertDialogPortal = AlertDialogPrimitive.Portal
/**
* A translucent overlay that covers the inert portion of the view when the dialog is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>} props... - All Radix AlertDialogOverlay props
*/
const AlertDialogOverlay = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
@ -25,6 +73,16 @@ const AlertDialogOverlay = React.forwardRef<
))
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
/**
* Contains the content to display in the alert dialog.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>} props... - All Radix AlertDialogContent props
*/
const AlertDialogContent = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
@ -43,6 +101,16 @@ const AlertDialogContent = React.forwardRef<
))
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
/**
* Container for alert dialog header content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*/
const AlertDialogHeader = ({
className,
...props
@ -57,6 +125,16 @@ const AlertDialogHeader = ({
)
AlertDialogHeader.displayName = "AlertDialogHeader"
/**
* Container for alert dialog footer content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*/
const AlertDialogFooter = ({
className,
...props
@ -71,6 +149,16 @@ const AlertDialogFooter = ({
)
AlertDialogFooter.displayName = "AlertDialogFooter"
/**
* Title of the alert dialog.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>} props... - All Radix AlertDialogTitle props
*/
const AlertDialogTitle = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
@ -83,6 +171,16 @@ const AlertDialogTitle = React.forwardRef<
))
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
/**
* Description text for the alert dialog.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>} props... - All Radix AlertDialogDescription props
*/
const AlertDialogDescription = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
@ -93,9 +191,18 @@ const AlertDialogDescription = React.forwardRef<
{...props}
/>
))
AlertDialogDescription.displayName =
AlertDialogPrimitive.Description.displayName
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName
/**
* Button that confirms the alert dialog action.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>} props... - All Radix AlertDialogAction props
*/
const AlertDialogAction = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Action>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
@ -108,6 +215,16 @@ const AlertDialogAction = React.forwardRef<
))
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
/**
* Button that cancels the alert dialog action.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>} props... - All Radix AlertDialogCancel props
*/
const AlertDialogCancel = React.forwardRef<
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
@ -125,15 +242,7 @@ const AlertDialogCancel = React.forwardRef<
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
AlertDialog, AlertDialogAction,
AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger
}

View File

@ -1,5 +1,5 @@
import { cva } from "class-variance-authority"
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
@ -19,21 +19,65 @@ const alertVariants = cva(
}
)
/**
* A contextual notification component for important messages.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'default' | 'destructive'} [props.variant='default'] - Visual style variant
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* ```tsx
* <Alert variant="destructive" className="mb-4">
* <AlertTitle>Error</AlertTitle>
* <AlertDescription>Something went wrong</AlertDescription>
* </Alert>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/alert | Shadcn Alert Documentation}
*/
const Alert = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...props }, ref) => (
React.HTMLAttributes<HTMLDivElement> & {
variant?: 'default' | 'destructive'
}
>(({ className, variant = 'default', ...props }, ref) => (
<div
ref={ref}
role="alert"
className={cn(alertVariants({ variant }), className)}
className={cn(
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4",
variant === 'destructive' && "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
className
)}
{...props}
/>
))
Alert.displayName = "Alert"
/**
* Title element for Alert components.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLHeadingElement>} props... - All heading element props
*
* @example
* ```tsx
* <AlertTitle>Success</AlertTitle>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/alert | Shadcn AlertTitle Documentation}
*/
const AlertTitle = React.forwardRef<
HTMLParagraphElement,
HTMLHeadingElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h5
@ -44,6 +88,25 @@ const AlertTitle = React.forwardRef<
))
AlertTitle.displayName = "AlertTitle"
/**
* Description text for Alert components.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLParagraphElement>} props... - All paragraph element props
*
* @example
* ```tsx
* <AlertDescription>
* Your action was completed successfully.
* </AlertDescription>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/alert | Shadcn AlertDescription Documentation}
*/
const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
@ -56,4 +119,5 @@ const AlertDescription = React.forwardRef<
))
AlertDescription.displayName = "AlertDescription"
export { Alert, AlertTitle, AlertDescription }
export { Alert, AlertDescription, AlertTitle }

View File

@ -1,5 +1,41 @@
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
import * as React from "react"
const AspectRatio = AspectRatioPrimitive.Root
import { cn } from "@/lib/utils"
/**
* A component to maintain consistent aspect ratios for content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.ratio=16/9] - Aspect ratio (width/height)
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* <AspectRatio ratio={16/9}>
* <img src="/image.jpg" alt="Example" />
* </AspectRatio>
*
* @see {@link https://ui.shadcn.com/docs/components/aspect-ratio | Shadcn AspectRatio Documentation}
*/
const AspectRatio = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & { ratio?: number }
>(({ className, ratio = 16 / 9, style, ...props }, ref) => (
<div
ref={ref}
style={{
position: "relative",
width: "100%",
paddingTop: `${100 / ratio}%`,
...style,
}}
className={cn("overflow-hidden", className)}
{...props}
/>
))
AspectRatio.displayName = "AspectRatio"
export { AspectRatio }

View File

@ -1,10 +1,38 @@
"use client"
import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Displays a user's avatar with fallback support.
* Composes Radix UI's Avatar primitives with shadcn styling.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>} props... - All other Radix AvatarRoot props
*
* @example
* ```tsx
* <Avatar>
* <AvatarImage src="/user.png" alt="@username" />
* <AvatarFallback>CN</AvatarFallback>
* </Avatar>
*
* // With custom size
* <Avatar className="h-12 w-12">
* <AvatarImage src="/user.png" />
* <AvatarFallback>UR</AvatarFallback>
* </Avatar>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/avatar | Shadcn Avatar Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/avatar | Radix Avatar Primitive}
*/
const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
@ -18,8 +46,23 @@ const Avatar = React.forwardRef<
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName
Avatar.displayName = "Avatar"
/**
* The image element of the avatar. Should be used inside an Avatar component.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.src - Source URL for the avatar image
* @param {string} props.alt - Accessible alt text description
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>} props... - All other Radix Image props
*
* @see {@link https://ui.shadcn.com/docs/components/avatar | Shadcn AvatarImage Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/avatar#image | Radix AvatarImage Primitive}
*/
const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
@ -30,8 +73,29 @@ const AvatarImage = React.forwardRef<
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName
AvatarImage.displayName = "AvatarImage"
/**
* Fallback component that shows when AvatarImage fails to load.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>} props... - All other Radix Fallback props
* @param {React.ReactNode} props.children - Fallback content to display
*
* @example
* ```tsx
* <AvatarFallback className="bg-muted text-primary">
* JD
* </AvatarFallback>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/avatar | Shadcn AvatarFallback Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/avatar#fallback | Radix AvatarFallback Primitive}
*/
const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
@ -45,6 +109,7 @@ const AvatarFallback = React.forwardRef<
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
AvatarFallback.displayName = "AvatarFallback"
export { Avatar, AvatarFallback, AvatarImage }
export { Avatar, AvatarImage, AvatarFallback }

View File

@ -1,36 +1,47 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
import * as React from "react"
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
/**
* Small status descriptor component for tagging and labeling.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'default' | 'secondary' | 'destructive' | 'outline'} [props.variant='default'] - Visual style variant
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* ```tsx
* <Badge variant="secondary" className="px-3 py-1">
* New Feature
* </Badge>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/badge | Shadcn Badge Documentation}
*/
const Badge = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & {
variant?: 'default' | 'secondary' | 'destructive' | 'outline'
}
)
>(({ className, variant = 'default', ...props }, ref) => (
<div
ref={ref}
className={cn(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80': variant === 'default',
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80': variant === 'secondary',
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80': variant === 'destructive',
'text-foreground': variant === 'outline',
},
className
)}
{...props}
/>
))
Badge.displayName = "Badge"
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}
export { Badge, badgeVariants }
export { Badge }

View File

@ -1,9 +1,36 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { ChevronRight, MoreHorizontal } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A navigation component that helps users keep track of their location within a website.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} [props.separator] - Custom separator between items
* @param {React.ComponentPropsWithoutRef<"nav">} props... - All nav element props
*
* @example
* ```tsx
* <Breadcrumb>
* <BreadcrumbList>
* <BreadcrumbItem>
* <BreadcrumbLink href="/">Home</BreadcrumbLink>
* </BreadcrumbItem>
* <BreadcrumbSeparator />
* <BreadcrumbItem>
* <BreadcrumbPage>Settings</BreadcrumbPage>
* </BreadcrumbItem>
* </BreadcrumbList>
* </Breadcrumb>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/breadcrumb | Shadcn Breadcrumb Documentation}
*/
const Breadcrumb = React.forwardRef<
HTMLElement,
React.ComponentPropsWithoutRef<"nav"> & {
@ -12,6 +39,16 @@ const Breadcrumb = React.forwardRef<
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
Breadcrumb.displayName = "Breadcrumb"
/**
* Container for breadcrumb items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"ol">} props... - All ordered list props
*/
const BreadcrumbList = React.forwardRef<
HTMLOListElement,
React.ComponentPropsWithoutRef<"ol">
@ -27,6 +64,16 @@ const BreadcrumbList = React.forwardRef<
))
BreadcrumbList.displayName = "BreadcrumbList"
/**
* Individual item in the breadcrumb list.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"li">} props... - All list item props
*/
const BreadcrumbItem = React.forwardRef<
HTMLLIElement,
React.ComponentPropsWithoutRef<"li">
@ -39,6 +86,17 @@ const BreadcrumbItem = React.forwardRef<
))
BreadcrumbItem.displayName = "BreadcrumbItem"
/**
* Link component for breadcrumb items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props onto child
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"a">} props... - All anchor element props
*/
const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement,
React.ComponentPropsWithoutRef<"a"> & {
@ -57,6 +115,16 @@ const BreadcrumbLink = React.forwardRef<
})
BreadcrumbLink.displayName = "BreadcrumbLink"
/**
* Current page indicator in the breadcrumb.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"span">} props... - All span element props
*/
const BreadcrumbPage = React.forwardRef<
HTMLSpanElement,
React.ComponentPropsWithoutRef<"span">
@ -72,6 +140,17 @@ const BreadcrumbPage = React.forwardRef<
))
BreadcrumbPage.displayName = "BreadcrumbPage"
/**
* Separator between breadcrumb items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} [props.children] - Custom separator content
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"li">} props... - All list item props
*/
const BreadcrumbSeparator = ({
children,
className,
@ -88,6 +167,16 @@ const BreadcrumbSeparator = ({
)
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
/**
* Ellipsis indicator for truncated breadcrumbs.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"span">} props... - All span element props
*/
const BreadcrumbEllipsis = ({
className,
...props
@ -105,11 +194,8 @@ const BreadcrumbEllipsis = ({
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
export {
Breadcrumb,
BreadcrumbList,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbPage,
BreadcrumbSeparator,
BreadcrumbEllipsis,
Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem,
BreadcrumbLink, BreadcrumbList, BreadcrumbPage,
BreadcrumbSeparator
}

View File

@ -47,6 +47,49 @@ export interface ButtonProps
rightIcon?: React.ReactNode;
}
/**
* Interactive button element with multiple variants and loading states.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'} [props.variant='default'] - Visual style variant
* @param {'default' | 'sm' | 'lg' | 'icon'} [props.size='default'] - Size of the button
* @param {boolean} [props.asChild=false] - Whether to render as a child component using Radix Slot
* @param {boolean} [props.isLoading=false] - Shows loading spinner when true
* @param {string} [props.loadingText='Loading...'] - Text to display when loading
* @param {React.ReactNode} [props.leftIcon] - Icon to display before the button text
* @param {React.ReactNode} [props.rightIcon] - Icon to display after the button text
* @param {string} [props.className] - Additional custom classes
* @param {React.ButtonHTMLAttributes<HTMLButtonElement>} props... - All standard button attributes
*
* @example
* ```tsx
* // Basic usage
* <Button>Click me</Button>
*
* // With variant and size
* <Button
* variant="destructive"
* size="sm"
* isLoading={isDeleting}
* >
* Delete Item
* </Button>
*
* // With icons
* <Button
* variant="outline"
* leftIcon={<PlusIcon />}
* >
* Add New
* </Button>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/button | Shadcn Button Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/utilities/slot | Radix Slot Primitive}
*/
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{

View File

@ -1,10 +1,32 @@
import * as React from "react"
import { ChevronLeft, ChevronRight } from "lucide-react"
import * as React from "react"
import { DayPicker } from "react-day-picker"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
/**
* Date picker component for selecting dates.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {Date} [props.selected] - Currently selected date
* @param {Date} [props.defaultMonth] - Default visible month
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<typeof DayPicker>} props... - All react-day-picker props
*
* @example
* <Calendar
* mode="single"
* selected={date}
* onSelect={setDate}
* className="rounded-md border"
* />
*
* @see {@link https://ui.shadcn.com/docs/components/calendar | Shadcn Calendar Documentation}
*/
export type CalendarProps = React.ComponentProps<typeof DayPicker>
function Calendar({
@ -31,29 +53,18 @@ function Calendar({
nav_button_next: "absolute right-1",
table: "w-full border-collapse space-y-1",
head_row: "flex",
head_cell:
"text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: cn(
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range"
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
: "[&:has([aria-selected])]:rounded-md"
),
cell: "text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
day: cn(
buttonVariants({ variant: "ghost" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100"
"h-9 w-9 p-0 font-normal aria-selected:opacity-100"
),
day_range_start: "day-range-start",
day_range_end: "day-range-end",
day_selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_today: "bg-accent text-accent-foreground",
day_outside:
"day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
day_outside: "text-muted-foreground opacity-50",
day_disabled: "text-muted-foreground opacity-50",
day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible",
...classNames,
}}

View File

@ -2,6 +2,33 @@ import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Flexible container for displaying content with a card-style layout.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All standard div attributes
*
* @example
* ```tsx
* <Card className="w-[350px]">
* <CardHeader>
* <CardTitle>Create Project</CardTitle>
* <CardDescription>Deploy your new project in minutes</CardDescription>
* </CardHeader>
* <CardContent>...</CardContent>
* <CardFooter className="flex justify-between">
* <Button variant="outline">Cancel</Button>
* <Button>Deploy</Button>
* </CardFooter>
* </Card>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/card | Shadcn Card Documentation}
*/
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -17,6 +44,17 @@ const Card = React.forwardRef<
))
Card.displayName = "Card"
/**
* Container for card header content. Typically holds CardTitle and CardDescription.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All standard div attributes
* @param {React.ReactNode} props.children - Should contain CardTitle and CardDescription
*/
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -29,6 +67,12 @@ const CardHeader = React.forwardRef<
))
CardHeader.displayName = "CardHeader"
/**
* Title element for card components. Use for primary header text.
*
* @component
* @public
*/
const CardTitle = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -41,6 +85,12 @@ const CardTitle = React.forwardRef<
))
CardTitle.displayName = "CardTitle"
/**
* Supplementary text for card headers. Use for descriptions or subheadings.
*
* @component
* @public
*/
const CardDescription = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -53,6 +103,12 @@ const CardDescription = React.forwardRef<
))
CardDescription.displayName = "CardDescription"
/**
* Main content area of the card. Use for primary card content.
*
* @component
* @public
*/
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -61,6 +117,12 @@ const CardContent = React.forwardRef<
))
CardContent.displayName = "CardContent"
/**
* Container for card footer content. Typically holds action buttons.
*
* @component
* @public
*/
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
@ -73,4 +135,5 @@ const CardFooter = React.forwardRef<
))
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }

View File

@ -8,6 +8,16 @@ import { cn } from "@/lib/utils"
// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const
/**
* Configuration type for chart colors and themes.
*
* @typedef {Object} ChartConfig
* @property {Object} [key: string] - Configuration for each chart element
* @property {React.ReactNode} [key.label] - Label for the element
* @property {React.ComponentType} [key.icon] - Icon component for the element
* @property {string} [key.color] - Single color for the element
* @property {Record<'light'|'dark', string>} [key.theme] - Theme-specific colors
*/
export type ChartConfig = {
[k in string]: {
label?: React.ReactNode
@ -24,6 +34,12 @@ type ChartContextProps = {
const ChartContext = React.createContext<ChartContextProps | null>(null)
/**
* Hook to access chart configuration from context.
*
* @returns {ChartContextProps} Chart configuration context
* @throws {Error} If used outside of a ChartContainer
*/
function useChart() {
const context = React.useContext(ChartContext)
@ -34,6 +50,37 @@ function useChart() {
return context
}
/**
* Container component for Recharts charts with theme support.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.id] - Unique identifier for the chart
* @param {string} [props.className] - Additional custom classes
* @param {ChartConfig} props.config - Chart configuration object
* @param {React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"]} props.children - Chart content
*
* @example
* ```tsx
* <ChartContainer
* config={{
* sales: {
* label: "Sales",
* theme: {
* light: "#0ea5e9",
* dark: "#38bdf8"
* }
* }
* }}
* >
* <LineChart data={data}>
* <Line dataKey="sales" />
* </LineChart>
* </ChartContainer>
* ```
*/
const ChartContainer = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
@ -67,6 +114,9 @@ const ChartContainer = React.forwardRef<
})
ChartContainer.displayName = "Chart"
/**
* Internal component that generates CSS variables for chart theming.
*/
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
([, config]) => config.theme || config.color
@ -100,8 +150,25 @@ ${colorConfig
)
}
/**
* Re-export of Recharts Tooltip component.
*/
const ChartTooltip = RechartsPrimitive.Tooltip
/**
* Custom tooltip content component for charts.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.hideLabel] - Whether to hide the label
* @param {boolean} [props.hideIndicator] - Whether to hide the color indicator
* @param {'line' | 'dot' | 'dashed'} [props.indicator='dot'] - Style of the color indicator
* @param {string} [props.nameKey] - Key to use for item names
* @param {string} [props.labelKey] - Key to use for label values
* @param {React.ComponentProps<typeof RechartsPrimitive.Tooltip>} props... - All Recharts Tooltip props
*/
const ChartTooltipContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
@ -256,8 +323,50 @@ const ChartTooltipContent = React.forwardRef<
)
ChartTooltipContent.displayName = "ChartTooltip"
/**
* Re-export of Recharts Legend component.
*
* @component
* @public
*
* @see {@link https://recharts.org/en-US/api/Legend | Recharts Legend Documentation}
*/
const ChartLegend = RechartsPrimitive.Legend
/**
* Custom legend content component for charts.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {boolean} [props.hideIcon] - Whether to hide the legend icons
* @param {RechartsPrimitive.LegendProps["payload"]} [props.payload] - Legend payload data
* @param {RechartsPrimitive.LegendProps["verticalAlign"]} [props.verticalAlign] - Vertical alignment of the legend
* @param {string} [props.nameKey] - Key to use for item names
* @param {React.ComponentProps<"div">} props... - All div element props
*
* @example
* ```tsx
* <ChartContainer
* config={{
* sales: {
* label: "Sales",
* theme: {
* light: "#0ea5e9",
* dark: "#38bdf8"
* }
* }
* }}
* >
* <LineChart data={data}>
* <Line dataKey="sales" />
* <ChartLegend content={<ChartLegendContent />} />
* </LineChart>
* </ChartContainer>
* ```
*/
const ChartLegendContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> &
@ -316,7 +425,16 @@ const ChartLegendContent = React.forwardRef<
)
ChartLegendContent.displayName = "ChartLegend"
// Helper to extract item config from a payload.
/**
* Helper function to extract item configuration from a payload.
*
* @internal
*
* @param {ChartConfig} config - Chart configuration object
* @param {unknown} payload - Payload object to extract configuration from
* @param {string} key - Key to look up in the payload and config
* @returns {ChartConfig[string] | undefined} The extracted configuration or undefined if not found
*/
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
@ -356,10 +474,9 @@ function getPayloadConfigFromPayload(
}
export {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
ChartLegend,
ChartContainer, ChartLegend,
ChartLegendContent,
ChartStyle,
ChartStyle, ChartTooltip,
ChartTooltipContent
}

View File

@ -1,9 +1,29 @@
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { Check } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A control that allows the user to toggle between checked and not checked states.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.checked] - Controlled checked state
* @param {boolean} [props.disabled] - Whether the checkbox is disabled
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>} props... - All Radix Checkbox props
*
* @example
* ```tsx
* <Checkbox checked={isChecked} onCheckedChange={setIsChecked} />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/checkbox | Shadcn Checkbox Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/checkbox | Radix Checkbox Primitive}
*/
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
@ -11,7 +31,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}

View File

@ -1,11 +1,66 @@
"use client"
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* An interactive component that can show/hide content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} props.open - Controlled open state
* @param {React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Root>} props... - All Radix CollapsibleRoot props
*
* @example
* <Collapsible open={isOpen} onOpenChange={setIsOpen}>
* <CollapsibleTrigger>Toggle</CollapsibleTrigger>
* <CollapsibleContent>Content</CollapsibleContent>
* </Collapsible>
*
* @see {@link https://ui.shadcn.com/docs/components/collapsible | Shadcn Collapsible Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/collapsible | Radix Collapsible Primitive}
*/
const Collapsible = CollapsiblePrimitive.Root
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
/**
* The button that toggles the collapsible content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Trigger>} props... - All Radix Trigger props
*/
const CollapsibleTrigger = CollapsiblePrimitive.Trigger
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
/**
* The collapsible content area.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>} props... - All Radix Content props
*/
const CollapsibleContent = React.forwardRef<
React.ElementRef<typeof CollapsiblePrimitive.Content>,
React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>
>(({ className, ...props }, ref) => (
<CollapsiblePrimitive.Content
ref={ref}
className={cn(
"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
className
)}
{...props}
/>
))
CollapsibleContent.displayName = CollapsiblePrimitive.Content.displayName
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
export { Collapsible, CollapsibleContent, CollapsibleTrigger }

View File

@ -0,0 +1,273 @@
"use client"
import * as PopoverPrimitive from "@radix-ui/react-popover"
import { Command as CommandPrimitive } from "cmdk"
import { Check, ChevronsUpDown } from "lucide-react"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
/**
* An autocomplete input with dropdown suggestions.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.shouldFilter=true] - Whether to filter options automatically
* @param {React.ComponentPropsWithoutRef<typeof CommandPrimitive>} props... - All Command props
*
* @example
* <Command>
* <CommandInput placeholder="Search..." />
* <CommandList>
* <CommandEmpty>No results found.</CommandEmpty>
* <CommandGroup>
* <CommandItem>Item 1</CommandItem>
* <CommandItem>Item 2</CommandItem>
* </CommandGroup>
* </CommandList>
* </Command>
*
* @see {@link https://ui.shadcn.com/docs/components/combobox | Shadcn Combobox Documentation}
* @see {@link https://cmdk.paco.me/ | CMDK Documentation}
*/
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, shouldFilter = true, ...props }, ref) => (
<CommandPrimitive
ref={ref}
shouldFilter={shouldFilter}
className={cn("relative", className)}
{...props}
/>
))
Command.displayName = CommandPrimitive.displayName
/**
* Input field for the Command component.
*/
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
</div>
))
CommandInput.displayName = CommandPrimitive.Input.displayName
/**
* List container for Command items.
*/
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...props}
/>
))
CommandList.displayName = CommandPrimitive.List.displayName
/**
* Empty state for Command when no results are found.
*/
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Empty
ref={ref}
className={cn("py-6 text-center text-sm", className)}
{...props}
/>
))
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
/**
* Group container for Command items.
*/
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className
)}
{...props}
/>
))
CommandGroup.displayName = CommandPrimitive.Group.displayName
/**
* Separator for Command groups.
*/
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
{...props}
/>
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
/**
* Selectable item in the Command list.
*/
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
/>
))
CommandItem.displayName = CommandPrimitive.Item.displayName
/**
* Popover component for dropdown functionality.
*/
const Popover = PopoverPrimitive.Root
const PopoverTrigger = PopoverPrimitive.Trigger
/**
* Content container for the Popover.
*/
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
))
PopoverContent.displayName = PopoverPrimitive.Content.displayName
/**
* Combobox component that combines Popover and Command for a dropdown selection with search.
*
* @component
* @example
* ```tsx
* <Combobox
* options={[
* { value: "option1", label: "Option 1" },
* { value: "option2", label: "Option 2" }
* ]}
* value={value}
* onChange={setValue}
* placeholder="Select an option..."
* />
* ```
*/
interface ComboboxProps {
options: { value: string; label: string }[]
value: string
onChange: (value: string) => void
placeholder?: string
emptyMessage?: string
className?: string
buttonClassName?: string
popoverClassName?: string
searchPlaceholder?: string
}
const Combobox = ({
options,
value,
onChange,
placeholder = "Select an option...",
emptyMessage = "No results found.",
className,
buttonClassName,
popoverClassName,
searchPlaceholder = "Search...",
}: ComboboxProps) => {
const [open, setOpen] = React.useState(false)
return (
<div className={className}>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className={cn("w-full justify-between", buttonClassName)}
>
{value
? options.find((option) => option.value === value)?.label
: placeholder}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className={cn("w-full p-0", popoverClassName)}>
<Command>
<CommandInput placeholder={searchPlaceholder} className="h-9" />
<CommandList>
<CommandEmpty>{emptyMessage}</CommandEmpty>
<CommandGroup>
{options.map((option) => (
<CommandItem
key={option.value}
value={option.value}
onSelect={(currentValue) => {
onChange(currentValue === value ? "" : currentValue)
setOpen(false)
}}
>
{option.label}
<Check
className={cn(
"ml-auto h-4 w-4",
value === option.value ? "opacity-100" : "opacity-0"
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
)
}
export {
Combobox, Command, CommandEmpty,
CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator,
Popover, PopoverContent, PopoverTrigger
}

View File

@ -1,11 +1,32 @@
import * as React from "react"
import { type DialogProps } from "@radix-ui/react-dialog"
import { Command as CommandPrimitive } from "cmdk"
import { Search } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
import { Dialog, DialogContent } from "@/components/ui/dialog"
import { cn } from "@/lib/utils"
/**
` * A command menu component that provides a searchable list of commands.
*
* @component
* @param {object} props - The component props derived from CommandPrimitive
* @param {string} [props.className] - Additional CSS classes
* @param {boolean} [props.value] - The controlled value of the command menu
* @param {function} [props.onValueChange] - Handler called when the value changes
* @param {boolean} [props.filter] - Custom filter function
*
* @example
* ```tsx
* <Command>
* <CommandInput placeholder="Search..." />
* <CommandList>
* <CommandItem>Item 1</CommandItem>
* <CommandItem>Item 2</CommandItem>
* </CommandList>
* </Command>
* ```
*/
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
@ -21,6 +42,25 @@ const Command = React.forwardRef<
))
Command.displayName = CommandPrimitive.displayName
/**
* A dialog wrapper for the Command component, providing a modal interface.
*
* @component
* @param {object} props - The component props
* @param {ReactNode} props.children - The dialog content
* @param {boolean} [props.open] - Controls the open state of the dialog
* @param {function} [props.onOpenChange] - Handler called when the open state changes
*
* @example
* ```tsx
* <CommandDialog>
* <CommandInput />
* <CommandList>
* <CommandItem>Dialog Item</CommandItem>
* </CommandList>
* </CommandDialog>
* ```
*/
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
@ -33,6 +73,21 @@ const CommandDialog = ({ children, ...props }: DialogProps) => {
)
}
/**
* The input component for the command menu with an integrated search icon.
*
* @component
* @param {object} props - The component props
* @param {string} [props.className] - Additional CSS classes
* @param {string} [props.placeholder] - Input placeholder text
* @param {string} [props.value] - Controlled input value
* @param {function} [props.onValueChange] - Handler called when the value changes
*
* @example
* ```tsx
* <CommandInput placeholder="Search commands..." />
* ```
*/
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
@ -52,6 +107,22 @@ const CommandInput = React.forwardRef<
CommandInput.displayName = CommandPrimitive.Input.displayName
/**
* A container for command items with scrolling support.
*
* @component
* @param {object} props - The component props
* @param {string} [props.className] - Additional CSS classes
* @param {ReactNode} props.children - The list content
*
* @example
* ```tsx
* <CommandList>
* <CommandItem>List Item 1</CommandItem>
* <CommandItem>List Item 2</CommandItem>
* </CommandList>
* ```
*/
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
@ -65,6 +136,19 @@ const CommandList = React.forwardRef<
CommandList.displayName = CommandPrimitive.List.displayName
/**
* Displays when no results are found in the command menu.
*
* @component
* @param {object} props - The component props
* @param {ReactNode} props.children - The content to display when no results are found
* @param {string} [props.className] - Additional CSS classes
*
* @example
* ```tsx
* <CommandEmpty>No results found.</CommandEmpty>
* ```
*/
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
@ -78,6 +162,23 @@ const CommandEmpty = React.forwardRef<
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
/**
* Groups related command items together with an optional heading.
*
* @component
* @param {object} props - The component props
* @param {string} [props.heading] - The group heading text
* @param {string} [props.className] - Additional CSS classes
* @param {ReactNode} props.children - The group content
*
* @example
* ```tsx
* <CommandGroup heading="Suggestions">
* <CommandItem>Suggestion 1</CommandItem>
* <CommandItem>Suggestion 2</CommandItem>
* </CommandGroup>
* ```
*/
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
@ -94,6 +195,22 @@ const CommandGroup = React.forwardRef<
CommandGroup.displayName = CommandPrimitive.Group.displayName
/**
* A visual separator between command items or groups.
*
* @component
* @param {object} props - The component props
* @param {string} [props.className] - Additional CSS classes
*
* @example
* ```tsx
* <CommandGroup>
* <CommandItem>Item 1</CommandItem>
* <CommandSeparator />
* <CommandItem>Item 2</CommandItem>
* </CommandGroup>
* ```
*/
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
@ -106,6 +223,25 @@ const CommandSeparator = React.forwardRef<
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
/**
* An individual item in the command menu.
*
* @component
* @param {object} props - The component props
* @param {string} [props.className] - Additional CSS classes
* @param {boolean} [props.disabled] - Whether the item is disabled
* @param {function} [props.onSelect] - Handler called when the item is selected
* @param {ReactNode} props.children - The item content
*
* @example
* ```tsx
* <CommandItem onSelect={() => console.log('Selected')}>
* <CalendarIcon className="mr-2 h-4 w-4" />
* Calendar
* <CommandShortcut>C</CommandShortcut>
* </CommandItem>
* ```
*/
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
@ -122,6 +258,22 @@ const CommandItem = React.forwardRef<
CommandItem.displayName = CommandPrimitive.Item.displayName
/**
* Displays keyboard shortcuts for command items.
*
* @component
* @param {object} props - The component props
* @param {string} [props.className] - Additional CSS classes
* @param {ReactNode} props.children - The shortcut text to display
*
* @example
* ```tsx
* <CommandItem>
* Settings
* <CommandShortcut>S</CommandShortcut>
* </CommandItem>
* ```
*/
const CommandShortcut = ({
className,
...props
@ -140,12 +292,7 @@ CommandShortcut.displayName = "CommandShortcut"
export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
CommandDialog, CommandEmpty,
CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut
}

View File

@ -1,19 +1,102 @@
import * as React from "react"
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
import { Check, ChevronRight, Circle } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A menu that appears upon right-click/tap-hold interaction.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.sideOffset=4] - Offset from the trigger element
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Root>} props... - All Radix ContextMenuRoot props
*
* @example
* <ContextMenu>
* <ContextMenuTrigger>Right-click here</ContextMenuTrigger>
* <ContextMenuContent>...</ContextMenuContent>
* </ContextMenu>
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu | Radix ContextMenu Primitive}
*/
const ContextMenu = ContextMenuPrimitive.Root
/**
* The component that triggers the context menu on interaction.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Trigger>} props... - All Radix Trigger props
*/
const ContextMenuTrigger = ContextMenuPrimitive.Trigger
/**
* Groups related menu items together.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - The grouped menu items
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Group>} props... - All Radix Group props
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu#group | Radix ContextMenu Group Primitive}
*/
const ContextMenuGroup = ContextMenuPrimitive.Group
/**
* Portal for rendering context menu content outside the DOM hierarchy.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - The content to render in the portal
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Portal>} props... - All Radix Portal props
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu#portal | Radix ContextMenu Portal Primitive}
*/
const ContextMenuPortal = ContextMenuPrimitive.Portal
/**
* Creates a submenu within the context menu.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - The submenu trigger and content
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Sub>} props... - All Radix Sub props
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu#sub | Radix ContextMenu Sub Primitive}
*/
const ContextMenuSub = ContextMenuPrimitive.Sub
/**
* A group of radio items where only one can be checked.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.value - The value of the currently checked item
* @param {function} props.onValueChange - Handler called when the value changes
* @param {React.ReactNode} props.children - The radio items
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioGroup>} props... - All Radix RadioGroup props
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu#radiogroup | Radix ContextMenu RadioGroup Primitive}
*/
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
const ContextMenuSubTrigger = React.forwardRef<
@ -52,6 +135,19 @@ const ContextMenuSubContent = React.forwardRef<
))
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
/**
* The content shown when the ContextMenu is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>} props... - All Radix Content props
*
* @see {@link https://ui.shadcn.com/docs/components/context-menu | Shadcn ContextMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/context-menu#content | Radix ContextMenu Content Primitive}
*/
const ContextMenuContent = React.forwardRef<
React.ElementRef<typeof ContextMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
@ -60,7 +156,7 @@ const ContextMenuContent = React.forwardRef<
<ContextMenuPrimitive.Content
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
@ -180,19 +276,9 @@ const ContextMenuShortcut = ({
ContextMenuShortcut.displayName = "ContextMenuShortcut"
export {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem,
ContextMenuCheckboxItem,
ContextMenuRadioItem,
ContextMenuLabel,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuGroup,
ContextMenuPortal,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuRadioGroup,
ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator,
ContextMenuShortcut, ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger, ContextMenuTrigger
}

View File

@ -0,0 +1,55 @@
import { Calendar } from "@/components/ui/calendar"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { cn } from "@/lib/utils"
import { CalendarIcon } from "lucide-react"
/**
* A date picker component with calendar integration.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {Date} [props.date] - Selected date
* @param {(date?: Date) => void} props.setDate - Date selection handler
* @param {string} [props.className] - Additional custom classes
*
* @example
* <DatePicker date={date} setDate={setDate} />
*
* @see {@link https://ui.shadcn.com/docs/components/date-picker | Shadcn DatePicker Documentation}
*/
export function DatePicker({
date,
setDate,
className,
}: {
date?: Date
setDate: (date?: Date) => void
className?: string
}) {
return (
<Popover>
<PopoverTrigger asChild>
<button
className={cn(
"flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring",
!date && "text-muted-foreground",
className
)}
>
{date ? date.toLocaleDateString() : "Pick a date"}
<CalendarIcon className="ml-2 h-4 w-4 opacity-50" />
</button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
initialFocus
/>
</PopoverContent>
</Popover>
)
}

View File

@ -1,13 +1,41 @@
"use client"
import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { X } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A window overlaid on either the primary window or another dialog window.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>} props... - All Radix DialogRoot props
*
* @example
* <Dialog>
* <DialogTrigger>Open</DialogTrigger>
* <DialogContent>...</DialogContent>
* </Dialog>
*
* @see {@link https://ui.shadcn.com/docs/components/dialog | Shadcn Dialog Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dialog | Radix Dialog Primitive}
*/
const Dialog = DialogPrimitive.Root
/**
* The button that opens the dialog.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>} props... - All Radix Trigger props
*/
const DialogTrigger = DialogPrimitive.Trigger
const DialogPortal = DialogPrimitive.Portal
@ -29,6 +57,24 @@ const DialogOverlay = React.forwardRef<
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
/**
* The content shown when the Dialog is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'start' | 'center' | 'end'} [props.align='center'] - Alignment relative to viewport
* @param {number} [props.sideOffset=4] - Offset from the viewport edge
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>} props... - All Radix Content props
*
* @example
* <DialogContent className="sm:max-w-[425px]">
* <DialogHeader>...</DialogHeader>
* <DialogClose />
* </DialogContent>
*/
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
@ -109,14 +155,7 @@ const DialogDescription = React.forwardRef<
DialogDescription.displayName = DialogPrimitive.Description.displayName
export {
Dialog,
DialogPortal,
DialogOverlay,
DialogTrigger,
DialogClose,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
Dialog, DialogClose,
DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger
}

View File

@ -16,12 +16,64 @@ const Drawer = ({
)
Drawer.displayName = "Drawer"
/**
* The button that opens the drawer when clicked.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Trigger>} props... - All Vaul Trigger props
*
* @see {@link https://ui.shadcn.com/docs/components/drawer | Shadcn Drawer Documentation}
* @see {@link https://vaul.emilkowal.ski/ | Vaul Documentation}
*/
const DrawerTrigger = DrawerPrimitive.Trigger
/**
* Portal for rendering drawer content outside the DOM hierarchy.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - The content to render in the portal
* @param {React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Portal>} props... - All Vaul Portal props
*
* @see {@link https://ui.shadcn.com/docs/components/drawer | Shadcn Drawer Documentation}
* @see {@link https://vaul.emilkowal.ski/ | Vaul Documentation}
*/
const DrawerPortal = DrawerPrimitive.Portal
/**
* A button that closes the drawer when clicked.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Close>} props... - All Vaul Close props
*
* @see {@link https://ui.shadcn.com/docs/components/drawer | Shadcn Drawer Documentation}
* @see {@link https://vaul.emilkowal.ski/ | Vaul Documentation}
*/
const DrawerClose = DrawerPrimitive.Close
/**
* A translucent overlay that covers the inert portion of the view when the drawer is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>} props... - All Vaul Overlay props
*
* @see {@link https://ui.shadcn.com/docs/components/drawer | Shadcn Drawer Documentation}
* @see {@link https://vaul.emilkowal.ski/ | Vaul Documentation}
*/
const DrawerOverlay = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
@ -105,14 +157,7 @@ const DrawerDescription = React.forwardRef<
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
export {
Drawer,
DrawerPortal,
DrawerOverlay,
DrawerTrigger,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerFooter,
DrawerTitle,
DrawerDescription,
Drawer, DrawerClose,
DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger
}

View File

@ -4,18 +4,108 @@ import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Context menu component with submenus, checkboxes, radio groups and keyboard navigation.
* Composes Radix UI's DropdownMenu primitives with shadcn styling.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root>} props - Accepts all Radix DropdownMenuRoot props
*
* @example
* ```tsx
* <DropdownMenu>
* <DropdownMenuTrigger>Open</DropdownMenuTrigger>
* <DropdownMenuContent>
* <DropdownMenuItem>Item 1</DropdownMenuItem>
* <DropdownMenuSub>
* <DropdownMenuSubTrigger>Submenu</DropdownMenuSubTrigger>
* <DropdownMenuSubContent>...</DropdownMenuSubContent>
* </DropdownMenuSub>
* </DropdownMenuContent>
* </DropdownMenu>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenu Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu | Radix DropdownMenu Primitive}
*/
const DropdownMenu = DropdownMenuPrimitive.Root
/**
* The button that toggles the dropdown menu.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>} props - Accepts all Radix Trigger props
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenuTrigger Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#trigger | Radix Trigger Primitive}
*/
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
/**
* Used to group multiple dropdown menu items.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Group>} props - Accepts all Radix Group props
*/
const DropdownMenuGroup = DropdownMenuPrimitive.Group
/**
* Portal wrapper for dropdown content when needing to break out of container boundaries.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Portal>} props - Accepts all Radix Portal props
*/
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
/**
* Container for dropdown submenu components.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Sub>} props - Accepts all Radix Sub props
*/
const DropdownMenuSub = DropdownMenuPrimitive.Sub
/**
* Radio group component for mutually exclusive dropdown menu items.
*
* @component
* @public
*
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioGroup>} props - Accepts all Radix RadioGroup props
*/
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
/**
* Interactive dropdown menu item with nested submenu support.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.inset] - Whether to indent the item for visual hierarchy
* @param {string} [props.className] - Additional class names for custom styling
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger>} props... - All Radix SubTrigger props
*
* @example
* ```tsx
* <DropdownMenuSubTrigger inset className="text-danger">
* Dangerous Action
* </DropdownMenuSubTrigger>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenuSubTrigger Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#subtrigger | Radix SubTrigger Primitive}
*/
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
@ -35,9 +125,21 @@ const DropdownMenuSubTrigger = React.forwardRef<
<ChevronRight className="ml-auto" />
</DropdownMenuPrimitive.SubTrigger>
))
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName
/**
* Container for submenu content that appears when hovering over a SubTrigger.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>} props... - All Radix SubContent props
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenuSubContent Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#subcontent | Radix SubContent Primitive}
*/
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
@ -51,9 +153,22 @@ const DropdownMenuSubContent = React.forwardRef<
{...props}
/>
))
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName
/**
* The content container for the dropdown menu.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.sideOffset=4] - Offset from the trigger element
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>} props... - All Radix Content props
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenuContent Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#content | Radix Content Primitive}
*/
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
@ -73,6 +188,20 @@ const DropdownMenuContent = React.forwardRef<
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
/**
* Individual interactive item within the dropdown menu.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.inset] - Whether to indent the item
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>} props... - All Radix Item props
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn DropdownMenuItem Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#item | Radix Item Primitive}
*/
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
@ -91,6 +220,30 @@ const DropdownMenuItem = React.forwardRef<
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
/**
* Checkbox item for dropdown menus with state management.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {boolean} props.checked - Controlled checked state
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>} props... - All Radix CheckboxItem props
*
* @example
* ```tsx
* <DropdownMenuCheckboxItem
* checked={isChecked}
* onCheckedChange={setIsChecked}
* >
* Show Hidden Files
* </DropdownMenuCheckboxItem>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn CheckboxItem Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#checkbox-item | Radix CheckboxItem Primitive}
*/
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
@ -112,9 +265,30 @@ const DropdownMenuCheckboxItem = React.forwardRef<
{children}
</DropdownMenuPrimitive.CheckboxItem>
))
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName
/**
* Radio item for mutually exclusive selection in dropdown menus.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>} props... - All Radix RadioItem props
*
* @example
* ```tsx
* <DropdownMenuRadioGroup value={selected} onValueChange={setSelected}>
* <DropdownMenuRadioItem value="option1">
* Option 1
* </DropdownMenuRadioItem>
* </DropdownMenuRadioGroup>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn RadioItem Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#radio-item | Radix RadioItem Primitive}
*/
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
@ -137,6 +311,25 @@ const DropdownMenuRadioItem = React.forwardRef<
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
/**
* Label for grouping related menu items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.inset] - Whether to indent the label
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label>} props... - All Radix Label props
*
* @example
* ```tsx
* <DropdownMenuLabel inset>File Options</DropdownMenuLabel>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn Label Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#label | Radix Label Primitive}
*/
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
@ -155,6 +348,24 @@ const DropdownMenuLabel = React.forwardRef<
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
/**
* Visual separator between menu items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>} props... - All Radix Separator props
*
* @example
* ```tsx
* <DropdownMenuSeparator className="my-1" />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/dropdown-menu | Shadcn Separator Docs}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu#separator | Radix Separator Primitive}
*/
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
@ -167,6 +378,24 @@ const DropdownMenuSeparator = React.forwardRef<
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
/**
* Displays keyboard shortcuts for menu items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLSpanElement>} props... - All span element props
*
* @example
* ```tsx
* <DropdownMenuItem>
* Save
* <DropdownMenuShortcut>S</DropdownMenuShortcut>
* </DropdownMenuItem>
* ```
*/
const DropdownMenuShortcut = ({
className,
...props

View File

@ -46,35 +46,22 @@ export interface IconButtonProps extends ButtonProps {
}
/**
* An enhanced button component that supports icons at the start and/or end,
* loading states, and all features of the base shadcn/ui Button.
*
* Enhanced button with icon support and loading states. Extends base Button functionality.
*
* @component
* @example
* ```tsx
* // Basic usage with icons
* <IconButton startIcon={Mail}>
* Send Email
* </IconButton>
*
* // With loading state
* <IconButton
* startIcon={Mail}
* isLoading
* loadingText="Sending..."
* leftIcon={<Mail className="h-4 w-4" />}
* rightIcon={<ArrowRight />}
* isLoading={isSending}
* >
* Send
* </IconButton>
*
* // With custom styling
* <IconButton
* startIcon={Bell}
* variant="outline"
* size="lg"
* className="w-full"
* >
* Notifications
* Send Message
* </IconButton>
* ```
*
* @see {@link Button | Base Button Component} for core functionality
* @see {@link https://ui.shadcn.com/docs/components/button | Shadcn Button Documentation}
*/
const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
(

View File

@ -1,13 +1,13 @@
import { Input, type InputProps } from '@/components/ui/input';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import { Loader2 } from 'lucide-react';
import * as React from 'react';
/**
* Props for the IconInput component.
* Extends the base InputProps from shadcn/ui Input component.
* Extends the base InputHTMLAttributes from React.
*/
export interface IconInputProps extends InputProps {
export interface IconInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
/**
* The icon component to be rendered at the start/left of the input.
* Can be a Lucide icon or any React component that accepts className prop.
@ -45,38 +45,21 @@ export interface IconInputProps extends InputProps {
}
/**
* An enhanced input component that supports icons at the start and/or end,
* loading states, and all features of the base shadcn/ui Input.
*
* Enhanced input field with icon support and loading states.
* Extends base shadcn/ui Input component functionality.
*
* @component
* @example
* ```tsx
* // Basic usage with icons
* <IconInput
* startIcon={Search}
* leftIcon={<Search className="h-4 w-4" />}
* rightIcon={isLoading ? <Loader2 className="animate-spin" /> : undefined}
* placeholder="Search..."
* />
*
* // With loading state
* <IconInput
* startIcon={Mail}
* isLoading
* placeholder="Loading..."
* />
*
* // With both icons
* <IconInput
* startIcon={Mail}
* endIcon={X}
* placeholder="Enter email"
* />
*
* // With custom styling
* <IconInput
* startIcon={User}
* className="border-primary"
* wrapperClassName="w-full max-w-md"
* />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/input | Shadcn Input Documentation}
* @see {@link Input | Base Input Component}
*/
const IconInput = React.forwardRef<HTMLInputElement, IconInputProps>(
(
@ -87,6 +70,7 @@ const IconInput = React.forwardRef<HTMLInputElement, IconInputProps>(
rightIcon: EndIcon,
isLoading,
wrapperClassName,
disabled,
...props
},
ref,
@ -113,7 +97,7 @@ const IconInput = React.forwardRef<HTMLInputElement, IconInputProps>(
EndIcon && 'pr-10',
)}
ref={ref}
disabled={isLoading || props.disabled}
disabled={isLoading || disabled}
{...props}
/>
{EndIcon && !isLoading && (

View File

@ -1,20 +1,52 @@
"use client"
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { Slot } from "@radix-ui/react-slot"
import * as React from "react"
import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
} from "react-hook-form"
import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label"
import { cn } from "@/lib/utils"
/**
* Form context provider that wraps react-hook-form's FormProvider.
* Required at the root of form implementations.
*
* @component
* @public
*
* @example
* ```tsx
* const form = useForm();
*
* return (
* <Form {...form}>
* <form onSubmit={form.handleSubmit(onSubmit)}>
* <FormField name="email" control={form.control} render={({ field }) => (
* <FormItem>
* <FormLabel>Email</FormLabel>
* <FormControl>
* <Input {...field} placeholder="user@example.com" />
* </FormControl>
* <FormDescription>Enter your organization email</FormDescription>
* <FormMessage />
* </FormItem>
* )} />
* </form>
* </Form>
* )
* ```
*
* @see {@link https://react-hook-form.com/ | React Hook Form Documentation}
* @see {@link https://ui.shadcn.com/docs/components/form | Shadcn Form Documentation}
*/
const Form = FormProvider
type FormFieldContextValue<
@ -28,6 +60,34 @@ const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue
)
/**
* Individual form field controller that integrates with react-hook-form.
*
* @component
* @public
*
* @template TFieldValues - Type of form values
* @template TName - Name of the field within the form values
*
* @param control - Form control from useForm()
* @param render - Render prop for field implementation
*
* @example
* ```tsx
* <FormField
* control={form.control}
* name="username"
* render={({ field }) => (
* <FormItem>
* <FormLabel>Username</FormLabel>
* <FormControl>
* <Input {...field} />
* </FormControl>
* </FormItem>
* )}
* />
* ```
*/
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
@ -167,12 +227,8 @@ const FormMessage = React.forwardRef<
FormMessage.displayName = "FormMessage"
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
Form, FormControl,
FormDescription, FormField, FormItem,
FormLabel, FormMessage, useFormField
}

View File

@ -1,14 +1,67 @@
"use client"
import * as React from "react"
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A popup that appears when hovering over an element.
* Composes Radix UI's HoverCard primitives with shadcn styling.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.openDelay=700] - Delay in ms before opening the card
* @param {number} [props.closeDelay=300] - Delay in ms before closing the card
* @param {React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Root>} props... - All Radix HoverCardRoot props
*
* @example
* <HoverCard openDelay={200} closeDelay={100}>
* <HoverCardTrigger>Hover me</HoverCardTrigger>
* <HoverCardContent>Preview content</HoverCardContent>
* </HoverCard>
*
* @see {@link https://ui.shadcn.com/docs/components/hover-card | Shadcn HoverCard Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/hover-card | Radix HoverCard Primitive}
*/
const HoverCard = HoverCardPrimitive.Root
/**
* The element that triggers the HoverCard when hovered.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Trigger>} props... - All Radix Trigger props
*
* @example
* <HoverCardTrigger asChild>
* <Button variant="link">Profile</Button>
* </HoverCardTrigger>
*/
const HoverCardTrigger = HoverCardPrimitive.Trigger
/**
* The content shown when the HoverCard is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'start' | 'center' | 'end'} [props.align='center'] - Alignment relative to trigger
* @param {number} [props.sideOffset=4] - Offset from the trigger element
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>} props... - All Radix Content props
*
* @example
* <HoverCardContent className="w-80" align="start" sideOffset={10}>
* <div className="p-4">Profile Details</div>
* </HoverCardContent>
*/
const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
@ -18,7 +71,7 @@ const HoverCardContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 w-full rounded-md border bg-popover p-4 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-0 data-[state=open]:fade-in data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
@ -26,4 +79,5 @@ const HoverCardContent = React.forwardRef<
))
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
export { HoverCard, HoverCardTrigger, HoverCardContent }
export { HoverCard, HoverCardContent, HoverCardTrigger }

View File

@ -5,6 +5,27 @@
* This file exports all the components from the UI library
*/
/**
* Shadcn UI Components - Collection of accessible, composable UI primitives
*
* @packageDocumentation
* @see {@link https://ui.shadcn.com/docs | Official Shadcn Documentation}
*
* @example
* ```tsx
* // Basic component import
* import { Button } from '@/components/ui/button'
*
* // Form components example
* import {
* Form,
* FormField,
* FormItem,
* FormLabel
* } from '@/components/ui/form'
* ```
*/
export * from './accordion';
export * from './alert';
export * from './alert-dialog';
@ -53,3 +74,4 @@ export * from './toast';
export * from './toggle';
export * from './toggle-group';
export * from './tooltip';

View File

@ -1,9 +1,39 @@
import * as React from "react"
import { OTPInput, OTPInputContext } from "input-otp"
import { Minus } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* One-time password input component for verification codes.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes for the input
* @param {string} [props.containerClassName] - Additional custom classes for the container
* @param {React.ComponentPropsWithoutRef<typeof OTPInput>} props... - All OTPInput props
*
* @example
* ```tsx
* <InputOTP maxLength={6}>
* <InputOTPGroup>
* <InputOTPSlot index={0} />
* <InputOTPSlot index={1} />
* <InputOTPSlot index={2} />
* </InputOTPGroup>
* <InputOTPSeparator />
* <InputOTPGroup>
* <InputOTPSlot index={3} />
* <InputOTPSlot index={4} />
* <InputOTPSlot index={5} />
* </InputOTPGroup>
* </InputOTP>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/input-otp | Shadcn InputOTP Documentation}
*/
const InputOTP = React.forwardRef<
React.ElementRef<typeof OTPInput>,
React.ComponentPropsWithoutRef<typeof OTPInput>
@ -20,6 +50,18 @@ const InputOTP = React.forwardRef<
))
InputOTP.displayName = "InputOTP"
/**
* Container for a group of OTP input slots.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"div">} props... - All div element props
*
* @see {@link https://ui.shadcn.com/docs/components/input-otp | Shadcn InputOTPGroup Documentation}
*/
const InputOTPGroup = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div">
@ -28,6 +70,19 @@ const InputOTPGroup = React.forwardRef<
))
InputOTPGroup.displayName = "InputOTPGroup"
/**
* Individual slot for a single OTP character input.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} props.index - The index of this slot in the OTP sequence
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<"div">} props... - All div element props
*
* @see {@link https://ui.shadcn.com/docs/components/input-otp | Shadcn InputOTPSlot Documentation}
*/
const InputOTPSlot = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> & { index: number }
@ -56,6 +111,17 @@ const InputOTPSlot = React.forwardRef<
})
InputOTPSlot.displayName = "InputOTPSlot"
/**
* Separator component between OTP input groups.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ComponentPropsWithoutRef<"div">} props... - All div element props
*
* @see {@link https://ui.shadcn.com/docs/components/input-otp | Shadcn InputOTPSeparator Documentation}
*/
const InputOTPSeparator = React.forwardRef<
React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div">
@ -66,4 +132,5 @@ const InputOTPSeparator = React.forwardRef<
))
InputOTPSeparator.displayName = "InputOTPSeparator"
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot }

View File

@ -1,23 +1,51 @@
import { cn } from '@/lib/utils';
import * as React from 'react';
import { cn } from "@/lib/utils"
import * as React from "react"
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
/**
* Input field component with built-in focus states and accessibility.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {string} [props.type] - Input type (text, password, email, etc.)
* @param {boolean} [props.disabled] - Disabled state
* @param {string} [props.placeholder] - Placeholder text
* @param {React.InputHTMLAttributes<HTMLInputElement>} props... - All standard input attributes
*
* @example
* ```tsx
* // Basic usage
* <Input placeholder="Enter your email" />
*
* // With type and disabled state
* <Input
* type="password"
* disabled
* placeholder="Enter password"
* className="w-64"
* />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/input | Shadcn Input Documentation}
*/
const Input = React.forwardRef<
HTMLInputElement,
React.InputHTMLAttributes<HTMLInputElement>
>(({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)
})
Input.displayName = "Input"
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
ref={ref}
{...props}
/>
);
},
);
Input.displayName = 'Input';
export { Input };
export { Input }

View File

@ -1,6 +1,6 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"
import { cn } from "@/lib/utils"
@ -8,6 +8,28 @@ const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)
/**
* A form label component with styling and accessibility features.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.htmlFor] - The ID of the form control this label is associated with
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>} props... - All Radix Label props
*
* @example
* ```tsx
* <div className="grid gap-2">
* <Label htmlFor="email">Email</Label>
* <Input id="email" type="email" />
* </div>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/label | Shadcn Label Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/label | Radix Label Primitive}
*/
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &

View File

@ -1,8 +1,8 @@
"use client"
import * as React from "react"
import * as MenubarPrimitive from "@radix-ui/react-menubar"
import { Check, ChevronRight, Circle } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
@ -36,6 +36,24 @@ function MenubarSub({
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
}
/**
* A horizontal menu bar for application navigation.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>} props... - All Radix MenubarRoot props
*
* @example
* <Menubar>
* <MenubarMenu>...</MenubarMenu>
* </Menubar>
*
* @see {@link https://ui.shadcn.com/docs/components/menubar | Shadcn Menubar Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/menubar | Radix Menubar Primitive}
*/
const Menubar = React.forwardRef<
React.ElementRef<typeof MenubarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
@ -237,20 +255,8 @@ const MenubarShortcut = ({
MenubarShortcut.displayname = "MenubarShortcut"
export {
Menubar,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarItem,
MenubarSeparator,
MenubarLabel,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarPortal,
MenubarSubContent,
MenubarSubTrigger,
MenubarGroup,
MenubarSub,
MenubarShortcut,
Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup,
MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent,
MenubarSubTrigger, MenubarTrigger
}

View File

@ -1,18 +1,39 @@
import * as React from "react"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority"
import { ChevronDown } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A collection of links for navigating between related content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'light' | 'dark' | 'custom'} [props.theme='light'] - Visual theme variant
* @param {React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>} props... - All Radix NavigationMenuRoot props
*
* @example
* <NavigationMenu>
* <NavigationMenuList>...</NavigationMenuList>
* </NavigationMenu>
*
* @see {@link https://ui.shadcn.com/docs/components/navigation-menu | Shadcn NavigationMenu Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/navigation-menu | Radix NavigationMenu Primitive}
*/
const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => (
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> & {
theme?: 'light' | 'dark' | 'custom'
}
>(({ className, theme = 'light', children, ...props }, ref) => (
<NavigationMenuPrimitive.Root
ref={ref}
className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center",
"relative z-10 flex flex-1 items-center justify-center",
theme === 'dark' && "bg-card",
className
)}
{...props}
@ -23,6 +44,16 @@ const NavigationMenu = React.forwardRef<
))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
/**
* Container for navigation menu items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>} props... - All Radix List props
*/
const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
@ -38,6 +69,19 @@ const NavigationMenuList = React.forwardRef<
))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
/**
* Individual item within the navigation menu.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - The item content
* @param {React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item>} props... - All Radix Item props
*
* @see {@link https://ui.shadcn.com/docs/components/navigation-menu | Shadcn NavigationMenuItem Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/navigation-menu#item | Radix NavigationMenuItem Primitive}
*/
const NavigationMenuItem = NavigationMenuPrimitive.Item
const navigationMenuTriggerStyle = cva(
@ -77,8 +121,35 @@ const NavigationMenuContent = React.forwardRef<
))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
/**
* Link component for navigation menu items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.href - URL to navigate to
* @param {boolean} [props.active] - Whether this link is currently active
* @param {React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link>} props... - All Radix Link props
*
* @see {@link https://ui.shadcn.com/docs/components/navigation-menu | Shadcn NavigationMenuLink Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/navigation-menu#link | Radix NavigationMenuLink Primitive}
*/
const NavigationMenuLink = NavigationMenuPrimitive.Link
/**
* Viewport component that displays the content of the active navigation menu item.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>} props... - All Radix Viewport props
*
* @see {@link https://ui.shadcn.com/docs/components/navigation-menu | Shadcn NavigationMenuViewport Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/navigation-menu#viewport | Radix NavigationMenuViewport Primitive}
*/
const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
@ -116,13 +187,6 @@ NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.displayName
export {
navigationMenuTriggerStyle,
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuContent,
NavigationMenuTrigger,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle, NavigationMenuViewport
}

View File

@ -1,9 +1,41 @@
import * as React from "react"
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
import { ButtonProps, buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
/**
* A navigation component for paginated content.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"nav">} props... - All nav element props
*
* @example
* ```tsx
* <Pagination>
* <PaginationContent>
* <PaginationItem>
* <PaginationPrevious href="#" />
* </PaginationItem>
* <PaginationItem>
* <PaginationLink href="#">1</PaginationLink>
* </PaginationItem>
* <PaginationItem>
* <PaginationLink href="#" isActive>2</PaginationLink>
* </PaginationItem>
* <PaginationItem>
* <PaginationNext href="#" />
* </PaginationItem>
* </PaginationContent>
* </Pagination>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
<nav
role="navigation"
@ -14,6 +46,18 @@ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
)
Pagination.displayName = "Pagination"
/**
* Container for pagination items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"ul">} props... - All ul element props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationContent = React.forwardRef<
HTMLUListElement,
React.ComponentProps<"ul">
@ -26,6 +70,18 @@ const PaginationContent = React.forwardRef<
))
PaginationContent.displayName = "PaginationContent"
/**
* Individual item in the pagination list.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"li">} props... - All li element props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationItem = React.forwardRef<
HTMLLIElement,
React.ComponentProps<"li">
@ -34,17 +90,29 @@ const PaginationItem = React.forwardRef<
))
PaginationItem.displayName = "PaginationItem"
type PaginationLinkProps = {
isActive?: boolean
} & Pick<ButtonProps, "size"> &
React.ComponentProps<"a">
/**
* Link component for pagination items.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.isActive] - Whether this link is the current page
* @param {string} [props.size='icon'] - Size of the link button
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"a">} props... - All anchor element props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationLink = ({
className,
isActive,
size = "icon",
...props
}: PaginationLinkProps) => (
}: {
isActive?: boolean
} & Pick<ButtonProps, "size"> &
React.ComponentProps<"a">) => (
<a
aria-current={isActive ? "page" : undefined}
className={cn(
@ -59,6 +127,18 @@ const PaginationLink = ({
)
PaginationLink.displayName = "PaginationLink"
/**
* Previous page navigation link.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<typeof PaginationLink>} props... - All PaginationLink props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationPrevious = ({
className,
...props
@ -75,6 +155,18 @@ const PaginationPrevious = ({
)
PaginationPrevious.displayName = "PaginationPrevious"
/**
* Next page navigation link.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<typeof PaginationLink>} props... - All PaginationLink props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationNext = ({
className,
...props
@ -91,6 +183,18 @@ const PaginationNext = ({
)
PaginationNext.displayName = "PaginationNext"
/**
* Ellipsis component indicating skipped pages.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentProps<"span">} props... - All span element props
*
* @see {@link https://ui.shadcn.com/docs/components/pagination | Shadcn Pagination Documentation}
*/
const PaginationEllipsis = ({
className,
...props
@ -108,10 +212,6 @@ PaginationEllipsis.displayName = "PaginationEllipsis"
export {
Pagination,
PaginationContent,
PaginationLink,
PaginationItem,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious
}

View File

@ -1,14 +1,55 @@
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A non-modal dialog that floats around its trigger element.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root>} props... - All Radix PopoverRoot props
*
* @example
* <Popover>
* <PopoverTrigger>Open</PopoverTrigger>
* <PopoverContent>Settings</PopoverContent>
* </Popover>
*
* @see {@link https://ui.shadcn.com/docs/components/popover | Shadcn Popover Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/popover | Radix Popover Primitive}
*/
const Popover = PopoverPrimitive.Root
/**
* @component
* @public
* @example
* <PopoverTrigger asChild>
* <Button variant="outline">Open</Button>
* </PopoverTrigger>
*/
const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverAnchor = PopoverPrimitive.Anchor
/**
* The content shown when the Popover is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'start' | 'center' | 'end'} [props.align='center'] - Alignment relative to trigger
* @param {number} [props.sideOffset=4] - Offset from the trigger element
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>} props... - All Radix Content props
*
* @example
* <PopoverContent className="w-80" align="end" sideOffset={6}>
* <div className="grid gap-4">...</div>
* </PopoverContent>
*/
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
@ -19,7 +60,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 w-full rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
@ -28,4 +69,4 @@ const PopoverContent = React.forwardRef<
))
PopoverContent.displayName = PopoverPrimitive.Content.displayName
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
export { Popover, PopoverContent, PopoverTrigger }

View File

@ -1,28 +1,40 @@
"use client"
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"
import { cn } from "@/lib/utils"
/**
* Displays an indicator showing the completion progress of a task.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.value=0] - Current progress value (0-100)
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* <Progress value={65} className="h-2" />
*
* @see {@link https://ui.shadcn.com/docs/components/progress | Shadcn Progress Documentation}
*/
const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & { value?: number }
>(({ className, value = 0, ...props }, ref) => (
<div
ref={ref}
className={cn(
"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
className
)}
className={cn("relative h-4 w-full overflow-hidden rounded-full bg-secondary", className)}
{...props}
>
<ProgressPrimitive.Indicator
<div
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
</div>
))
Progress.displayName = ProgressPrimitive.Root.displayName
Progress.displayName = "Progress"
export { Progress }

View File

@ -1,9 +1,39 @@
import * as React from "react"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
import { Circle } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A set of checkable buttons where only one can be checked at a time.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {string} props.defaultValue - The value of the radio item that should be checked by default
* @param {string} [props.value] - The controlled value of the radio item that should be checked
* @param {function} [props.onValueChange] - Event handler called when the value changes
* @param {React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>} props... - All Radix RadioGroup props
*
* @example
* ```tsx
* <RadioGroup defaultValue="option-one">
* <div className="flex items-center space-x-2">
* <RadioGroupItem value="option-one" id="option-one" />
* <Label htmlFor="option-one">Option One</Label>
* </div>
* <div className="flex items-center space-x-2">
* <RadioGroupItem value="option-two" id="option-two" />
* <Label htmlFor="option-two">Option Two</Label>
* </div>
* </RadioGroup>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/radio-group | Shadcn RadioGroup Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/radio-group | Radix RadioGroup Primitive}
*/
const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
@ -18,6 +48,20 @@ const RadioGroup = React.forwardRef<
})
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
/**
* An item in the radio group that can be checked.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.value - The unique value of the radio item
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>} props... - All Radix RadioGroupItem props
*
* @see {@link https://ui.shadcn.com/docs/components/radio-group | Shadcn RadioGroupItem Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/radio-group#item | Radix RadioGroupItem Primitive}
*/
const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
@ -26,13 +70,13 @@ const RadioGroupItem = React.forwardRef<
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-3.5 w-3.5 fill-primary" />
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
)

View File

@ -1,10 +1,7 @@
"use client"
import { cn } from "@/lib/utils"
import { GripVertical } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"
const ResizablePanelGroup = ({
className,
...props
@ -42,4 +39,5 @@ const ResizableHandle = ({
</ResizablePrimitive.PanelResizeHandle>
)
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
export { ResizableHandle, ResizablePanel, ResizablePanelGroup }

View File

@ -1,8 +1,29 @@
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A scrollable area with custom scrollbars.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ReactNode} props.children - The content to be scrollable
* @param {React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>} props... - All Radix ScrollArea props
*
* @example
* ```tsx
* <ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
* <div>Long content here</div>
* </ScrollArea>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/scroll-area | Shadcn ScrollArea Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/scroll-area | Radix ScrollArea Primitive}
*/
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
@ -21,6 +42,20 @@ const ScrollArea = React.forwardRef<
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
/**
* Custom scrollbar component for ScrollArea.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'vertical' | 'horizontal'} [props.orientation='vertical'] - The orientation of the scrollbar
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>} props... - All Radix ScrollAreaScrollbar props
*
* @see {@link https://ui.shadcn.com/docs/components/scroll-area | Shadcn ScrollArea Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/scroll-area#scrollbar | Radix ScrollAreaScrollbar Primitive}
*/
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>

View File

@ -1,17 +1,79 @@
"use client"
import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select"
import { Check, ChevronDown, ChevronUp } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Props for the Select component, extending Radix UI's select primitive props.
*
* @public
*/
export interface SelectProps extends SelectPrimitive.SelectProps {
/**
* Additional CSS class to apply to the select container.
*
* @default undefined
*/
className?: string
}
/**
* A dropdown select component for choosing options from a list.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ReactNode} props.children - Select options
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>} props... - All Radix SelectRoot props
*
* @example
* <Select>
* <SelectTrigger className="w-[180px]">
* <SelectValue placeholder="Select a theme" />
* </SelectTrigger>
* <SelectContent>
* <SelectItem value="light">Light</SelectItem>
* </SelectContent>
* </Select>
*
* @see {@link https://ui.shadcn.com/docs/components/select | Shadcn Select Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/select | Radix Select Primitive}
*/
const Select = SelectPrimitive.Root
/**
* Grouping component for Select items, allowing for logical grouping within the dropdown.
*
* @component
* @public
*/
const SelectGroup = SelectPrimitive.Group
/**
* Value display component within the Select trigger.
*
* @component
* @public
*
* @param placeholder - Text to show when no value is selected
*/
const SelectValue = SelectPrimitive.Value
/**
* The button that toggles the select dropdown.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>} props... - All Radix Trigger props
*/
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
@ -19,7 +81,7 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
"flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
@ -32,6 +94,16 @@ const SelectTrigger = React.forwardRef<
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
/**
* Scroll up button for navigating the Select dropdown content.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the scroll up button
* @param props - Additional props are spread to the underlying Radix UI ScrollUpButton component
* @param ref - Ref to attach to the scroll up button element for direct DOM access
*/
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
@ -49,6 +121,16 @@ const SelectScrollUpButton = React.forwardRef<
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
/**
* Scroll down button for navigating the Select dropdown content.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the scroll down button
* @param props - Additional props are spread to the underlying Radix UI ScrollDownButton component
* @param ref - Ref to attach to the scroll down button element for direct DOM access
*/
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
@ -67,6 +149,18 @@ const SelectScrollDownButton = React.forwardRef<
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName
/**
* Content container for Select items, appearing as a dropdown.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the content container
* @param children - Elements to display within the content container
* @param position - Positioning strategy for the dropdown content
* @param props - Additional props are spread to the underlying Radix UI Content component
* @param ref - Ref to attach to the content element for direct DOM access
*/
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
@ -97,8 +191,18 @@ const SelectContent = React.forwardRef<
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
SelectContent.displayName = "SelectContent"
/**
* Label for grouping Select items, providing context within the dropdown.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the label
* @param props - Additional props are spread to the underlying Radix UI Label component
* @param ref - Ref to attach to the label element for direct DOM access
*/
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
@ -111,6 +215,17 @@ const SelectLabel = React.forwardRef<
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
/**
* Individual selectable item within the Select dropdown.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the item
* @param children - Elements to display within the item
* @param props - Additional props are spread to the underlying Radix UI Item component
* @param ref - Ref to attach to the item element for direct DOM access
*/
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
@ -118,12 +233,12 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
@ -131,8 +246,18 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
SelectItem.displayName = "SelectItem"
/**
* Separator for dividing Select items, providing visual separation.
*
* @component
* @public
*
* @param className - Additional CSS class for styling the separator
* @param props - Additional props are spread to the underlying Radix UI Separator component
* @param ref - Ref to attach to the separator element for direct DOM access
*/
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
@ -146,14 +271,15 @@ const SelectSeparator = React.forwardRef<
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue
}

View File

@ -1,8 +1,32 @@
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A visual divider between content areas.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'horizontal' | 'vertical'} [props.orientation='horizontal'] - The orientation of the separator
* @param {boolean} [props.decorative=true] - Whether the separator is purely decorative (affects accessibility)
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>} props... - All Radix Separator props
*
* @example
* ```tsx
* // Horizontal separator
* <Separator />
*
* // Vertical separator
* <Separator orientation="vertical" className="h-6" />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/separator | Shadcn Separator Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/separator | Radix Separator Primitive}
*/
const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>

View File

@ -1,14 +1,43 @@
"use client"
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A sliding panel that appears from the edge of the screen.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'left' | 'right' | 'top' | 'bottom'} [props.side='right'] - Opening direction
* @param {React.ComponentPropsWithoutRef<typeof SheetPrimitive.Root>} props... - All Radix SheetRoot props
*
* @example
* <Sheet>
* <SheetTrigger>Open</SheetTrigger>
* <SheetContent>...</SheetContent>
* </Sheet>
*
* @see {@link https://ui.shadcn.com/docs/components/sheet | Shadcn Sheet Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/dialog | Radix Dialog Primitive}
*/
const Sheet = SheetPrimitive.Root
/**
* The button that opens the sheet.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof SheetPrimitive.Trigger>} props... - All Radix Trigger props
*/
const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close
@ -53,6 +82,17 @@ interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
/**
* The content shown when the Sheet is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'left' | 'right' | 'top' | 'bottom'} [props.side='right'] - Opening direction
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>} props... - All Radix Content props
*/
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
SheetContentProps
@ -127,14 +167,7 @@ const SheetDescription = React.forwardRef<
SheetDescription.displayName = SheetPrimitive.Description.displayName
export {
Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
Sheet, SheetClose,
SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger
}

View File

@ -1,21 +1,21 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { VariantProps, cva } from "class-variance-authority"
import { PanelLeft } from "lucide-react"
import * as React from "react"
import { useIsMobile } from "@/hooks/use-mobile"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator"
import { Sheet, SheetContent } from "@/components/ui/sheet"
import { Skeleton } from "@/components/ui/skeleton"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import { useIsMobile } from "@/hooks/use-mobile"
import { cn } from "@/lib/utils"
const SIDEBAR_COOKIE_NAME = "sidebar_state"
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
@ -154,6 +154,26 @@ const SidebarProvider = React.forwardRef<
)
SidebarProvider.displayName = "SidebarProvider"
/**
* Vertical navigation component with collapsible functionality.
* Composes with Radix UI primitives for accessible interactions.
*
* @component
* @example
* ```tsx
* <Sidebar>
* <SidebarHeader>Navigation</SidebarHeader>
* <SidebarContent>
* <SidebarGroup>
* <SidebarItem>Dashboard</SidebarItem>
* <SidebarItem>Settings</SidebarItem>
* </SidebarGroup>
* </SidebarContent>
* </Sidebar>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/sidebar | Shadcn Sidebar Documentation}
*/
const Sidebar = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
@ -348,6 +368,10 @@ const SidebarInput = React.forwardRef<
})
SidebarInput.displayName = "SidebarInput"
/**
* Sticky header section of the sidebar
* @component
*/
const SidebarHeader = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
@ -393,6 +417,10 @@ const SidebarSeparator = React.forwardRef<
})
SidebarSeparator.displayName = "SidebarSeparator"
/**
* Scrollable content area of the sidebar
* @component
*/
const SidebarContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div">
@ -734,28 +762,29 @@ const SidebarMenuSubButton = React.forwardRef<
SidebarMenuSubButton.displayName = "SidebarMenuSubButton"
export {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInput,
SidebarInset,
SidebarMenu,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
useSidebar,
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInput,
SidebarInset,
SidebarMenu,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSkeleton,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
SidebarProvider,
SidebarRail,
SidebarSeparator,
SidebarTrigger,
useSidebar
}

View File

@ -1,15 +1,31 @@
import { cn } from "@/lib/utils"
import * as React from "react"
function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-primary/10", className)}
{...props}
/>
)
}
/**
* A placeholder loading indicator that animates content loading states.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* <Skeleton className="h-4 w-[200px]" />
*
* @see {@link https://ui.shadcn.com/docs/components/skeleton | Shadcn Skeleton Documentation}
*/
const Skeleton = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
))
Skeleton.displayName = "Skeleton"
export { Skeleton }

View File

@ -1,8 +1,27 @@
import * as React from "react"
import * as SliderPrimitive from "@radix-ui/react-slider"
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* An input where the user selects a value from within a given range.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number[]} [props.defaultValue=[0]] - Initial value(s)
* @param {number} [props.min=0] - Minimum allowed value
* @param {number} [props.max=100] - Maximum allowed value
* @param {number} [props.step=1] - Increment step size
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* <Slider defaultValue={[50]} max={100} step={1} className="w-[60%]" />
*
* @see {@link https://ui.shadcn.com/docs/components/slider | Shadcn Slider Documentation}
*/
const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>

View File

@ -5,6 +5,32 @@ import { Toaster as Sonner } from "sonner"
type ToasterProps = React.ComponentProps<typeof Sonner>
/**
* A toast notification component using Sonner with theme integration.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {React.ComponentProps<typeof Sonner>} props... - All Sonner Toaster props
*
* @example
* ```tsx
* // In your layout or root component
* <Toaster />
*
* // Then anywhere in your app
* import { toast } from "sonner"
*
* toast("Event has been created")
* toast.success("Success!", {
* description: "Your action was completed successfully",
* })
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/sonner | Shadcn Sonner Documentation}
* @see {@link https://sonner.emilkowal.ski/ | Sonner Documentation}
*/
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()

View File

@ -1,27 +1,45 @@
import * as SwitchPrimitive from "@radix-ui/react-switch"
import * as React from "react"
import * as SwitchPrimitives from "@radix-ui/react-switch"
import { cn } from "@/lib/utils"
/**
* A control that allows the user to toggle between checked and not checked states.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.checked] - Controlled checked state
* @param {boolean} [props.disabled] - Whether the switch is disabled
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>} props... - All Radix Switch props
*
* @example
* <Switch checked={isEnabled} onCheckedChange={setIsEnabled} />
*
* @see {@link https://ui.shadcn.com/docs/components/switch | Shadcn Switch Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/switch | Radix Switch Primitive}
*/
const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
React.ElementRef<typeof SwitchPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
<SwitchPrimitive.Root
ref={ref}
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
<SwitchPrimitive.Thumb
className={cn(
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitives.Root>
</SwitchPrimitive.Root>
))
Switch.displayName = SwitchPrimitives.Root.displayName
Switch.displayName = SwitchPrimitive.Root.displayName
export { Switch }

View File

@ -2,6 +2,38 @@ import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Composable table component with built-in responsive styling and accessibility features.
*
* @component
* @public
*
* @example
* ```tsx
* <Table className="rounded-lg border">
* <TableHeader>
* <TableRow>
* <TableHead className="w-[100px]">ID</TableHead>
* <TableHead>Name</TableHead>
* <TableHead className="text-right">Actions</TableHead>
* </TableRow>
* </TableHeader>
* <TableBody>
* {items.map((item) => (
* <TableRow key={item.id}>
* <TableCell className="font-medium">{item.id}</TableCell>
* <TableCell>{item.name}</TableCell>
* <TableCell className="text-right">
* <Button variant="outline">Edit</Button>
* </TableCell>
* </TableRow>
* ))}
* </TableBody>
* </Table>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/table | Shadcn Table Documentation}
*/
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
@ -109,12 +141,7 @@ const TableCaption = React.forwardRef<
TableCaption.displayName = "TableCaption"
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
Table, TableBody, TableCaption, TableCell, TableFooter,
TableHead, TableHeader, TableRow
}

View File

@ -1,10 +1,51 @@
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import * as React from "react"
const Tabs = TabsPrimitive.Root
/**
* Interactive tab navigation component with keyboard support.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.defaultValue - Default active tab value
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>} props... - All Radix TabsRoot props
*
* @example
* ```tsx
* <Tabs defaultValue="account" className="w-[400px]">
* <TabsList>
* <TabsTrigger value="account">Account</TabsTrigger>
* <TabsTrigger value="password">Password</TabsTrigger>
* </TabsList>
* <TabsContent value="account">Account settings</TabsContent>
* <TabsContent value="password">Password settings</TabsContent>
* </Tabs>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/tabs | Shadcn Tabs Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/tabs | Radix Tabs Primitive}
*/
const Tabs = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Root
ref={ref}
className={cn("", className)}
{...props}
/>
))
Tabs.displayName = "Tabs"
/**
* Container for tab triggers. Maintains active state styling.
*
* @component
* @public
*/
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
@ -12,14 +53,28 @@ const TabsList = React.forwardRef<
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName
TabsList.displayName = "TabsList"
/**
* Individual tab trigger button. Manages active/inactive states.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.value - Unique value to associate with corresponding content
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>} props... - All Radix Trigger props
*
* @see {@link https://ui.shadcn.com/docs/components/tabs | Shadcn TabsTrigger Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/tabs#trigger | Radix TabsTrigger Primitive}
*/
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
@ -27,14 +82,25 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
TabsTrigger.displayName = "TabsTrigger"
/**
* Content container for individual tab panels.
*
* @component
* @public
*
* @param value - Must match corresponding trigger's value
*
* @see {@link https://ui.shadcn.com/docs/components/tabs | Shadcn TabsContent Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/tabs#content | Radix TabsContent Primitive}
*/
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
@ -48,6 +114,7 @@ const TabsContent = React.forwardRef<
{...props}
/>
))
TabsContent.displayName = TabsPrimitive.Content.displayName
TabsContent.displayName = "TabsContent"
export { Tabs, TabsContent, TabsList, TabsTrigger }
export { Tabs, TabsList, TabsTrigger, TabsContent }

View File

@ -2,14 +2,28 @@ import * as React from "react"
import { cn } from "@/lib/utils"
/**
* A multi-line text input field. Composes with native textarea element.
*
* @component
* @example
* ```tsx
* <Textarea
* placeholder="Type your message here."
* className="resize-none"
* />
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/textarea | Shadcn Textarea Documentation}
*/
const Textarea = React.forwardRef<
HTMLTextAreaElement,
React.ComponentProps<"textarea">
React.TextareaHTMLAttributes<HTMLTextAreaElement>
>(({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}

View File

@ -1,7 +1,7 @@
import * as React from "react"
import * as ToastPrimitives from "@radix-ui/react-toast"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import * as React from "react"
import { cn } from "@/lib/utils"
@ -38,6 +38,22 @@ const toastVariants = cva(
}
)
/**
* A brief notification that appears temporarily.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {'default' | 'destructive'} [props.variant='default'] - Visual style variant
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLDivElement>} props... - All div element props
*
* @example
* <Toast variant="destructive">Error message</Toast>
*
* @see {@link https://ui.shadcn.com/docs/components/toast | Shadcn Toast Documentation}
*/
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
@ -115,13 +131,6 @@ type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
type ToastActionElement = React.ReactElement<typeof ToastAction>
export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, type ToastActionElement, type ToastProps
}

View File

@ -1,4 +1,3 @@
import { useToast } from "@/hooks/use-toast"
import {
Toast,
ToastClose,
@ -7,7 +6,30 @@ import {
ToastTitle,
ToastViewport,
} from "@/components/ui/toast"
import { useToast } from "@/hooks/use-toast"
/**
* A component that renders toast notifications from the toast context.
*
* @component
* @public
*
* @example
* ```tsx
* // In your layout or root component
* <Toaster />
*
* // Then anywhere in your app
* const { toast } = useToast()
*
* toast({
* title: "Success",
* description: "Your action was completed successfully",
* })
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/toast | Shadcn Toast Documentation}
*/
export function Toaster() {
const { toasts } = useToast()

View File

@ -1,9 +1,9 @@
import * as React from "react"
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
import { type VariantProps } from "class-variance-authority"
import * as React from "react"
import { cn } from "@/lib/utils"
import { toggleVariants } from "@/components/ui/toggle"
import { cn } from "@/lib/utils"
const ToggleGroupContext = React.createContext<
VariantProps<typeof toggleVariants>
@ -12,6 +12,30 @@ const ToggleGroupContext = React.createContext<
variant: "default",
})
/**
* A set of two-state buttons that can be toggled on or off, where only one can be active at a time.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} [props.variant='default'] - Visual style variant
* @param {string} [props.size='default'] - Size of the toggle group
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root>} props... - All Radix ToggleGroup props
*
* @example
* ```tsx
* <ToggleGroup type="single" defaultValue="center">
* <ToggleGroupItem value="left">Left</ToggleGroupItem>
* <ToggleGroupItem value="center">Center</ToggleGroupItem>
* <ToggleGroupItem value="right">Right</ToggleGroupItem>
* </ToggleGroup>
* ```
*
* @see {@link https://ui.shadcn.com/docs/components/toggle-group | Shadcn ToggleGroup Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/toggle-group | Radix ToggleGroup Primitive}
*/
const ToggleGroup = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
@ -30,6 +54,22 @@ const ToggleGroup = React.forwardRef<
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
/**
* An individual item within a ToggleGroup.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {string} props.value - The value of this toggle item
* @param {string} [props.variant] - Visual style variant (overrides parent ToggleGroup)
* @param {string} [props.size] - Size of the toggle item (overrides parent ToggleGroup)
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>} props... - All Radix ToggleGroupItem props
*
* @see {@link https://ui.shadcn.com/docs/components/toggle-group | Shadcn ToggleGroupItem Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/toggle-group#item | Radix ToggleGroupItem Primitive}
*/
const ToggleGroupItem = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &

View File

@ -1,8 +1,7 @@
"use client"
import { cva } from "class-variance-authority"
import * as React from "react"
import * as TogglePrimitive from "@radix-ui/react-toggle"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
@ -28,18 +27,44 @@ const toggleVariants = cva(
}
)
/**
* A two-state button that can be either on or off.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.pressed=false] - Controlled pressed state
* @param {string} [props.variant='default'] - Visual style variant
* @param {string} [props.className] - Additional custom classes
* @param {React.HTMLAttributes<HTMLButtonElement>} props... - All button element props
*
* @example
* <Toggle pressed={isToggled} onPressedChange={setIsToggled}>
* Toggle State
* </Toggle>
*
* @see {@link https://ui.shadcn.com/docs/components/toggle | Shadcn Toggle Documentation}
*/
const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root
HTMLButtonElement,
React.HTMLAttributes<HTMLButtonElement> & {
pressed?: boolean
variant?: 'default' | 'outline'
}
>(({ className, variant = 'default', pressed = false, ...props }, ref) => (
<button
ref={ref}
className={cn(toggleVariants({ variant, size, className }))}
className={cn(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
variant === 'default' && "bg-transparent hover:bg-muted",
variant === 'outline' && "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
pressed && "bg-muted",
className
)}
{...props}
/>
))
Toggle.displayName = TogglePrimitive.Root.displayName
Toggle.displayName = "Toggle"
export { Toggle, toggleVariants }

View File

@ -1,16 +1,61 @@
"use client"
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import * as React from "react"
import { cn } from "@/lib/utils"
const TooltipProvider = TooltipPrimitive.Provider
/**
* A popup that displays information related to an element when focused or hovered.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.delayDuration=300] - Delay in ms before showing the tooltip
* @param {React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>} props... - All Radix TooltipRoot props
*
* @example
* <Tooltip>
* <TooltipTrigger>Hover me</TooltipTrigger>
* <TooltipContent>Additional information</TooltipContent>
* </Tooltip>
*
* @see {@link https://ui.shadcn.com/docs/components/tooltip | Shadcn Tooltip Documentation}
* @see {@link https://www.radix-ui.com/primitives/docs/components/tooltip | Radix Tooltip Primitive}
*/
const Tooltip = TooltipPrimitive.Root
/**
* The element that triggers the Tooltip when hovered.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {boolean} [props.asChild] - Whether to merge props with the child component
* @param {React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>} props... - All Radix Trigger props
*/
const TooltipTrigger = TooltipPrimitive.Trigger
/**
* The content shown when the Tooltip is open.
*
* @component
* @public
*
* @param {Object} props - Component props
* @param {number} [props.sideOffset=4] - Offset from the trigger element
* @param {string} [props.className] - Additional custom classes
* @param {React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>} props... - All Radix Content props
*
* @example
* <TooltipContent className="bg-popover text-popover-foreground">
* Tooltip message
* </TooltipContent>
*/
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
@ -20,7 +65,7 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
@ -29,4 +74,5 @@ const TooltipContent = React.forwardRef<
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }

View File

@ -73,4 +73,15 @@
body {
@apply bg-background text-foreground;
}
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

View File

@ -0,0 +1,194 @@
/**
* This file demonstrates proper TSDoc usage for the Snowball Tools frontend.
*
* @packageDocumentation
* @module Utils
*/
/**
* Theme options for the application UI.
*
* @public
*/
export type Theme = 'light' | 'dark' | 'system';
/**
* Configuration for UI components.
*
* @public
*/
export interface UIConfig {
/**
* The theme to use for the UI.
* @default "system"
*/
theme: Theme;
/**
* Whether to show animations.
* @default true
*/
enableAnimations: boolean;
/**
* The font size in pixels.
* @default 16
*/
fontSize?: number;
}
/**
* A utility class for managing UI preferences.
*
* @remarks
* This class provides methods for getting and setting UI preferences,
* with persistence to localStorage.
*
* @example
* ```tsx
* const preferences = new UIPreferences();
* preferences.setTheme('dark');
* console.log(preferences.getTheme()); // "dark"
* ```
*/
export class UIPreferences {
private storageKey = 'ui-preferences';
/**
* Creates a new UIPreferences instance.
*
* @param defaultConfig - The default configuration to use if none is stored
*/
constructor(
private defaultConfig: UIConfig = {
theme: 'system',
enableAnimations: true,
fontSize: 16
}
) {}
/**
* Gets the current UI configuration.
*
* @returns The current UI configuration
*/
getConfig(): UIConfig {
try {
const stored = localStorage.getItem(this.storageKey);
if (stored) {
return { ...this.defaultConfig, ...JSON.parse(stored) };
}
} catch (error) {
console.error('Failed to load UI preferences', error);
}
return this.defaultConfig;
}
/**
* Updates the UI configuration.
*
* @param config - The new configuration (partial)
* @returns The updated configuration
*/
updateConfig(config: Partial<UIConfig>): UIConfig {
const currentConfig = this.getConfig();
const newConfig = { ...currentConfig, ...config };
try {
localStorage.setItem(this.storageKey, JSON.stringify(newConfig));
} catch (error) {
console.error('Failed to save UI preferences', error);
}
return newConfig;
}
/**
* Gets the current theme.
*
* @returns The current theme
*/
getTheme(): Theme {
return this.getConfig().theme;
}
/**
* Sets the current theme.
*
* @param theme - The theme to set
*/
setTheme(theme: Theme): void {
this.updateConfig({ theme });
}
/**
* Determines if the current theme is dark.
*
* @returns True if the theme is dark, false otherwise
*
* @remarks
* If the theme is set to 'system', this will check the system preference.
*/
isDarkTheme(): boolean {
const theme = this.getTheme();
if (theme === 'system') {
return window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return theme === 'dark';
}
}
/**
* Formats a currency value.
*
* @param value - The value to format
* @param currency - The currency code (default: 'USD')
* @param locale - The locale to use (default: 'en-US')
* @returns The formatted currency string
*
* @example
* ```ts
* const price = formatCurrency(1234.56);
* console.log(price); // "$1,234.56"
* ```
*/
export function formatCurrency(
value: number,
currency: string = 'USD',
locale: string = 'en-US'
): string {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(value);
}
/**
* Truncates a string to a maximum length.
*
* @param text - The text to truncate
* @param maxLength - The maximum length (default: 50)
* @param ellipsis - The ellipsis to use (default: '...')
* @returns The truncated string
*
* @example
* ```ts
* const longText = "This is a very long text that needs to be truncated";
* const truncated = truncateText(longText, 20);
* console.log(truncated); // "This is a very long..."
* ```
*/
export function truncateText(
text: string,
maxLength: number = 50,
ellipsis: string = '...'
): string {
if (text.length <= maxLength) {
return text;
}
return text.slice(0, maxLength - ellipsis.length) + ellipsis;
}

82
scripts/generate-docs.js Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env node
/**
* Script to generate TypeDoc documentation for the monorepo
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const rimraf = require('rimraf');
// Ensure docs directory exists
const docsDir = path.join(__dirname, '..', 'docs');
if (!fs.existsSync(docsDir)) {
fs.mkdirSync(docsDir, { recursive: true });
}
// Run TypeDoc
console.log('Generating documentation...');
try {
// Use npx to run TypeDoc
execSync('npx typedoc', { stdio: 'inherit' });
console.log('Documentation generated successfully in the docs/ directory');
console.log('\nCI/CD Approach for Documentation:');
console.log('1. Add docs/ to your .gitignore file to prevent committing generated docs');
console.log('2. Set up a GitHub Action workflow that:');
console.log(' - Runs on push to main/develop/develop-qwrk branches');
console.log(' - Generates documentation using this script');
console.log(' - Deploys the generated docs to GitHub Pages');
console.log('\nExample GitHub Action workflow (.github/workflows/docs.yml):');
console.log(`
name: Generate and Deploy Docs
on:
push:
branches: [ main, master, develop, develop-qwrk ] # Trigger on these branches
workflow_dispatch: # Allow manual triggering
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Generate documentation
run: node scripts/generate-docs.js
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: docs
clean: true
`);
console.log('\nThis way, your documentation will be:');
console.log('- Generated automatically when you push to main, develop, or develop-qwrk');
console.log('- Deployed to GitHub Pages without cluttering your main branch');
console.log('- Available at https://[username].github.io/[repository]/');
// Clean up docs directory if the --clean flag is provided
if (process.argv.includes('--clean')) {
console.log('\nCleaning up docs directory...');
rimraf.sync(docsDir);
console.log('Docs directory removed. Documentation will only be available through GitHub Pages.');
}
} catch (error) {
console.error('Error generating documentation:', error.message);
process.exit(1);
}

23
tsconfig.doc.json Normal file
View File

@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"resolveJsonModule": true,
"jsx": "react-jsx"
},
"include": [
"packages/*/src/**/*.ts",
"packages/*/src/**/*.tsx"
],
"exclude": [
"node_modules",
"packages/*/node_modules",
"packages/*/dist",
"packages/frontend/src/components",
"packages/frontend/src/stories"
]
}

25
typedoc.json Normal file
View File

@ -0,0 +1,25 @@
{
"$schema": "https://typedoc.org/schema.json",
"entryPoints": ["packages/*/src"],
"entryPointStrategy": "expand",
"out": "docs",
"plugin": ["typedoc-plugin-markdown"],
"readme": "docs-readme.md",
"name": "Snowball Tools API Documentation",
"includeVersion": true,
"excludePrivate": true,
"excludeProtected": false,
"excludeExternals": true,
"excludeInternal": true,
"hideGenerator": true,
"disableSources": false,
"categorizeByGroup": true,
"categoryOrder": ["Core", "API", "Utilities", "*"],
"sort": ["source-order"],
"validation": {
"invalidLink": true,
"notDocumented": true
},
"skipErrorChecking": true,
"tsconfig": "./tsconfig.doc.json"
}

335
yarn.lock
View File

@ -807,7 +807,7 @@
pirates "^4.0.6"
source-map-support "^0.5.16"
"@babel/runtime@^7.10.4", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.6", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.15", "@babel/runtime@^7.25.0", "@babel/runtime@^7.26.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.10.4", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.6", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.15", "@babel/runtime@^7.25.0", "@babel/runtime@^7.26.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433"
integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==
@ -2250,6 +2250,15 @@
resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.1.1.tgz#401803b6ac4c877f5be94088aa89147ed5a2bd85"
integrity sha512-weN3E+rq0Xb3Z93VHJ+Rc7WOQX9ETJPTAJ+gDcaMHtjft67L58sfS65rAjC5tZUXQ2FdZ/V1/sSzCwZ6v05kJw==
"@gerrit0/mini-shiki@^1.24.0":
version "1.27.2"
resolved "https://registry.yarnpkg.com/@gerrit0/mini-shiki/-/mini-shiki-1.27.2.tgz#cf2a9fcb08a6581c78fc94821f0c854ec4b9f899"
integrity sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==
dependencies:
"@shikijs/engine-oniguruma" "^1.27.2"
"@shikijs/types" "^1.27.2"
"@shikijs/vscode-textmate" "^10.0.1"
"@graphql-tools/merge@8.3.1":
version "8.3.1"
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.1.tgz#06121942ad28982a14635dbc87b5d488a041d722"
@ -4451,13 +4460,6 @@
resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46"
integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==
"@radix-ui/primitive@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd"
integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3"
@ -4552,13 +4554,6 @@
"@radix-ui/react-primitive" "2.0.2"
"@radix-ui/react-slot" "1.1.2"
"@radix-ui/react-compose-refs@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989"
integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec"
@ -4576,40 +4571,12 @@
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-context@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c"
integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-context@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a"
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
"@radix-ui/react-dialog@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300"
integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-dismissable-layer" "1.0.5"
"@radix-ui/react-focus-guards" "1.0.1"
"@radix-ui/react-focus-scope" "1.0.4"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-portal" "1.0.4"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-slot" "1.0.2"
"@radix-ui/react-use-controllable-state" "1.0.1"
aria-hidden "^1.1.1"
react-remove-scroll "2.5.5"
"@radix-ui/react-dialog@1.1.6", "@radix-ui/react-dialog@^1.1.1", "@radix-ui/react-dialog@^1.1.6":
"@radix-ui/react-dialog@1.1.6", "@radix-ui/react-dialog@^1.1.1", "@radix-ui/react-dialog@^1.1.2", "@radix-ui/react-dialog@^1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz#65b4465e99ad900f28a98eed9a94bb21ec644bf7"
integrity sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==
@ -4634,18 +4601,6 @@
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==
"@radix-ui/react-dismissable-layer@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4"
integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-callback-ref" "1.0.1"
"@radix-ui/react-use-escape-keydown" "1.0.3"
"@radix-ui/react-dismissable-layer@1.1.5":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774"
@ -4670,28 +4625,11 @@
"@radix-ui/react-primitive" "2.0.2"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-focus-guards@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad"
integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-focus-guards@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe"
integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==
"@radix-ui/react-focus-scope@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525"
integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-callback-ref" "1.0.1"
"@radix-ui/react-focus-scope@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602"
@ -4716,15 +4654,7 @@
"@radix-ui/react-primitive" "2.0.2"
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-id@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0"
integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect" "1.0.1"
"@radix-ui/react-id@1.1.0":
"@radix-ui/react-id@1.1.0", "@radix-ui/react-id@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed"
integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==
@ -4835,14 +4765,6 @@
"@radix-ui/react-use-size" "1.1.0"
"@radix-ui/rect" "1.1.0"
"@radix-ui/react-portal@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15"
integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-portal@1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8"
@ -4851,15 +4773,6 @@
"@radix-ui/react-primitive" "2.0.2"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-presence@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba"
integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-use-layout-effect" "1.0.1"
"@radix-ui/react-presence@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc"
@ -4868,15 +4781,7 @@
"@radix-ui/react-compose-refs" "1.1.1"
"@radix-ui/react-use-layout-effect" "1.1.0"
"@radix-ui/react-primitive@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0"
integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.2"
"@radix-ui/react-primitive@2.0.2":
"@radix-ui/react-primitive@2.0.2", "@radix-ui/react-primitive@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef"
integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==
@ -4988,14 +4893,6 @@
"@radix-ui/react-use-previous" "1.1.0"
"@radix-ui/react-use-size" "1.1.0"
"@radix-ui/react-slot@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab"
integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-slot@1.1.2", "@radix-ui/react-slot@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6"
@ -5088,26 +4985,11 @@
"@radix-ui/react-use-controllable-state" "1.1.0"
"@radix-ui/react-visually-hidden" "1.1.2"
"@radix-ui/react-use-callback-ref@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a"
integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1"
integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==
"@radix-ui/react-use-controllable-state@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286"
integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "1.0.1"
"@radix-ui/react-use-controllable-state@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0"
@ -5115,14 +4997,6 @@
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-escape-keydown@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755"
integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-callback-ref" "1.0.1"
"@radix-ui/react-use-escape-keydown@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754"
@ -5130,13 +5004,6 @@
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.0"
"@radix-ui/react-use-layout-effect@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399"
integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-layout-effect@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27"
@ -5713,6 +5580,27 @@
"@noble/hashes" "~1.7.1"
"@scure/base" "~1.2.4"
"@shikijs/engine-oniguruma@^1.27.2":
version "1.29.2"
resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz#d879717ced61d44e78feab16f701f6edd75434f1"
integrity sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==
dependencies:
"@shikijs/types" "1.29.2"
"@shikijs/vscode-textmate" "^10.0.1"
"@shikijs/types@1.29.2", "@shikijs/types@^1.27.2":
version "1.29.2"
resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.29.2.tgz#a93fdb410d1af8360c67bf5fc1d1a68d58e21c4f"
integrity sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==
dependencies:
"@shikijs/vscode-textmate" "^10.0.1"
"@types/hast" "^3.0.4"
"@shikijs/vscode-textmate@^10.0.1":
version "10.0.2"
resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224"
integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
@ -6930,6 +6818,13 @@
dependencies:
"@types/unist" "^2"
"@types/hast@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa"
integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==
dependencies:
"@types/unist" "*"
"@types/http-errors@*":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
@ -7184,6 +7079,11 @@
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
"@types/unist@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c"
integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==
"@types/unist@^2":
version "2.0.11"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4"
@ -8447,7 +8347,7 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
aria-hidden@^1.1.1, aria-hidden@^1.1.3, aria-hidden@^1.2.4:
aria-hidden@^1.1.3, aria-hidden@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522"
integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==
@ -9394,13 +9294,15 @@ cmd-shim@6.0.3, cmd-shim@^6.0.0:
resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.3.tgz#c491e9656594ba17ac83c4bd931590a9d6e26033"
integrity sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==
cmdk@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.0.tgz#0a095fdafca3dfabed82d1db78a6262fb163ded9"
integrity sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==
cmdk@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.4.tgz#cbddef6f5ade2378f85c80a0b9ad9a8a712779b5"
integrity sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg==
dependencies:
"@radix-ui/react-dialog" "1.0.5"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-dialog" "^1.1.2"
"@radix-ui/react-id" "^1.1.0"
"@radix-ui/react-primitive" "^2.0.0"
use-sync-external-store "^1.2.2"
co@4.6.0:
version "4.6.0"
@ -10541,7 +10443,7 @@ enquirer@~2.3.6:
dependencies:
ansi-colors "^4.1.1"
entities@^4.5.0:
entities@^4.4.0, entities@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
@ -11713,6 +11615,18 @@ glob@^10.0.0, glob@^10.2.2, glob@^10.3.10:
package-json-from-dist "^1.0.0"
path-scurry "^1.11.1"
glob@^11.0.0:
version "11.0.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9"
integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==
dependencies:
foreground-child "^3.1.0"
jackspeak "^4.0.1"
minimatch "^10.0.0"
minipass "^7.1.2"
package-json-from-dist "^1.0.0"
path-scurry "^2.0.0"
glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@ -12643,6 +12557,13 @@ jackspeak@^3.1.2:
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
jackspeak@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b"
integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==
dependencies:
"@isaacs/cliui" "^8.0.2"
jake@^10.8.5:
version "10.9.2"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f"
@ -13249,6 +13170,13 @@ link-module-alias@^1.2.0:
dependencies:
chalk "^2.4.1"
linkify-it@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421"
integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==
dependencies:
uc.micro "^2.0.0"
lit-element@^3.3.0:
version "3.3.3"
resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.3.tgz#10bc19702b96ef5416cf7a70177255bfb17b3209"
@ -13504,6 +13432,11 @@ lru-cache@^10.0.1, lru-cache@^10.2.0, lru-cache@^10.2.2, lru-cache@^10.4.3:
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
lru-cache@^11.0.0:
version "11.0.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@ -13528,6 +13461,11 @@ lucide-react@^0.475.0:
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.475.0.tgz#4b7b62c024f153ee4b52a6a0f33f9e72f07156f0"
integrity sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==
lunr@^2.3.9:
version "2.3.9"
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1"
integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==
luxon@^3.4.4:
version "3.5.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20"
@ -13619,6 +13557,18 @@ map-or-similar@^1.5.0:
resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08"
integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==
markdown-it@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45"
integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==
dependencies:
argparse "^2.0.1"
entities "^4.4.0"
linkify-it "^5.0.0"
mdurl "^2.0.0"
punycode.js "^2.3.1"
uc.micro "^2.1.0"
marky@^1.2.2:
version "1.2.5"
resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0"
@ -13643,6 +13593,11 @@ md5.js@^1.3.4:
inherits "^2.0.1"
safe-buffer "^5.1.2"
mdurl@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0"
integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -13987,6 +13942,13 @@ minimatch@9.0.3:
dependencies:
brace-expansion "^2.0.1"
minimatch@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@ -14015,7 +13977,7 @@ minimatch@^8.0.2:
dependencies:
brace-expansion "^2.0.1"
minimatch@^9.0.0, minimatch@^9.0.4:
minimatch@^9.0.0, minimatch@^9.0.4, minimatch@^9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
@ -15058,6 +15020,14 @@ path-scurry@^1.11.1, path-scurry@^1.6.1:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580"
integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==
dependencies:
lru-cache "^11.0.0"
minipass "^7.1.2"
path-to-regexp@0.1.12:
version "0.1.12"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
@ -15492,6 +15462,11 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
punycode.js@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
punycode@2.3.1, punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
@ -15807,7 +15782,7 @@ react-refresh@^0.14.0, react-refresh@^0.14.2:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7:
react-remove-scroll-bar@^2.3.7:
version "2.3.8"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
@ -15815,17 +15790,6 @@ react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7:
react-style-singleton "^2.2.2"
tslib "^2.0.0"
react-remove-scroll@2.5.5:
version "2.5.5"
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77"
integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==
dependencies:
react-remove-scroll-bar "^2.3.3"
react-style-singleton "^2.2.1"
tslib "^2.1.0"
use-callback-ref "^1.3.0"
use-sidecar "^1.1.2"
react-remove-scroll@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2"
@ -15874,7 +15838,7 @@ react-smooth@^4.0.4:
prop-types "^15.8.1"
react-transition-group "^4.4.5"
react-style-singleton@^2.2.1, react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
@ -16313,6 +16277,14 @@ rimraf@^4.4.1:
dependencies:
glob "^9.2.0"
rimraf@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.1.tgz#ffb8ad8844dd60332ab15f52bc104bc3ed71ea4e"
integrity sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==
dependencies:
glob "^11.0.0"
package-json-from-dist "^1.0.0"
rimraf@~2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@ -17671,6 +17643,22 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
typedoc-plugin-markdown@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.4.2.tgz#fc31779595aa9bf00e66709f3894e048345bf7ed"
integrity sha512-kJVkU2Wd+AXQpyL6DlYXXRrfNrHrEIUgiABWH8Z+2Lz5Sq6an4dQ/hfvP75bbokjNDUskOdFlEEm/0fSVyC7eg==
typedoc@^0.27.9:
version "0.27.9"
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.27.9.tgz#5e0a7bc32bfc7bd0b70a353f4f1d5cba3d667c46"
integrity sha512-/z585740YHURLl9DN2jCWe6OW7zKYm6VoQ93H0sxZ1cwHQEQrUn5BJrEnkWhfzUdyO+BLGjnKUZ9iz9hKloFDw==
dependencies:
"@gerrit0/mini-shiki" "^1.24.0"
lunr "^2.3.9"
markdown-it "^14.1.0"
minimatch "^9.0.5"
yaml "^2.6.1"
typeforce@^1.11.3, typeforce@^1.11.5:
version "1.18.0"
resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc"
@ -17707,6 +17695,11 @@ typescript@5.0.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e"
integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==
uc.micro@^2.0.0, uc.micro@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
ufo@^1.5.4:
version "1.5.4"
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754"
@ -17882,14 +17875,14 @@ uri-js@^4.4.1:
dependencies:
punycode "^2.1.0"
use-callback-ref@^1.3.0, use-callback-ref@^1.3.3:
use-callback-ref@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==
dependencies:
tslib "^2.0.0"
use-sidecar@^1.1.2, use-sidecar@^1.1.3:
use-sidecar@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
@ -18471,7 +18464,7 @@ yaml@^1.10.0:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.2.1, yaml@^2.2.2, yaml@^2.3.4, yaml@^2.6.0:
yaml@^2.2.1, yaml@^2.2.2, yaml@^2.3.4, yaml@^2.6.0, yaml@^2.6.1:
version "2.7.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98"
integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==