format all files

This commit is contained in:
Maze Winther 2026-01-21 12:52:34 +01:00
parent 8500dd770b
commit afdf7d22cf
176 changed files with 2596 additions and 6480 deletions

View File

@ -6,7 +6,7 @@ alwaysApply: true
# Project Context
Ultracite enforces strict type safety, accessibility standards, and consistent code quality for JavaScript/TypeScript projects using Biome's lightning-fast formatter and linter.
Ultracite enforces strict type safety, accessibility standards, and consistent code quality for JavaScript/TypeScript projects using Prettier's formatter.
## Key Principles

View File

@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities

View File

@ -1,6 +1,6 @@
name: Bug report
description: Create a report to help us improve
title: '[BUG] '
title: "[BUG] "
labels: bug
body:
- type: input
@ -15,7 +15,7 @@ body:
id: Browser
attributes:
label: Browser
description: Please enter the browser on which you encountered the bug.
description: Please enter the browser on which you encountered the bug.
placeholder: e.g. Chrome 137, Firefox 137, Safari 17
validations:
required: true
@ -67,4 +67,4 @@ body:
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
required: false

View File

@ -1,6 +1,6 @@
name: Feature request
description: Suggest an idea for OpenCut
title: '[FEATURE] '
title: "[FEATURE] "
labels: enhancement
body:
- type: markdown
@ -39,4 +39,4 @@ body:
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
required: false

2
.github/SECURITY.md vendored
View File

@ -25,4 +25,4 @@ Please do not report security vulnerabilities through public GitHub issues.
- We will provide a detailed response within 5 business days
- We will keep you updated on our progress
Thank you for helping keep OpenCut secure!
Thank you for helping keep OpenCut secure!

6
.github/SUPPORT.md vendored
View File

@ -3,21 +3,25 @@
Thanks for using OpenCut! If you need help, here are your options:
## Documentation
- Check our [README](../README.md) for basic setup instructions
- Review the [Contributing Guidelines](CONTRIBUTING.md) for development setup
## Issues
- **Bug reports**: Use the bug report template
- **Feature requests**: Use the feature request template
- **Questions**: Use GitHub Discussions for general questions
## Community
- Join our discussions on GitHub
- Follow the [Code of Conduct](CODE_OF_CONDUCT.md)
## Response Times
- Issues are typically triaged within 2-3 business days
- Feature requests may take longer to evaluate
- Security issues are handled with priority
We appreciate your patience and contributions to making OpenCut better!
We appreciate your patience and contributions to making OpenCut better!

View File

@ -3,15 +3,18 @@ applyTo: "**/*.{ts,tsx,js,jsx}"
---
# Project Context
Ultracite enforces strict type safety, accessibility standards, and consistent code quality for JavaScript/TypeScript projects using Biome's lightning-fast formatter and linter.
## Key Principles
- Zero configuration required
- Subsecond performance
- Maximum type safety
- AI-friendly code generation
## Before Writing Code
1. Analyze existing patterns in the codebase
2. Consider edge cases and error scenarios
3. Follow the rules below strictly
@ -20,6 +23,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
## Rules
### Accessibility (a11y)
- Don't use `accessKey` attribute on any HTML element.
- Don't set `aria-hidden="true"` on focusable elements.
- Don't add ARIA roles, states, and properties to elements that don't support them.
@ -56,6 +60,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Use correct ISO language/country codes for the `lang` attribute.
### Code Complexity and Quality
- Don't use consecutive spaces in regular expression literals.
- Don't use the `arguments` object.
- Don't use primitive type aliases or misleading types.
@ -111,6 +116,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Don't use literal numbers that lose precision.
### React and JSX Best Practices
- Don't use the return value of React.render.
- Make sure all dependencies are correctly specified in React hooks.
- Make sure all React hooks are called from the top level of component functions.
@ -129,6 +135,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Watch out for possible "wrong" semicolons inside JSX elements.
### Correctness and Safety
- Don't assign a value to itself.
- Don't return a value from a setter.
- Don't compare expressions that modify string case with non-compliant values.
@ -153,7 +160,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Don't use bitwise operators.
- Don't use expressions where the operation doesn't change the value.
- Make sure Promise-like statements are handled appropriately.
- Don't use __dirname and __filename in the global scope.
- Don't use **dirname and **filename in the global scope.
- Prevent import cycles.
- Don't use configured elements.
- Don't hardcode sensitive data like API keys and tokens.
@ -184,6 +191,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Don't use `target="_blank"` without `rel="noopener"`.
### TypeScript Best Practices
- Don't use TypeScript enums.
- Don't export imported variables.
- Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
@ -208,6 +216,7 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
### Style and Consistency
- Don't use global `eval()`.
- Don't use callbacks in asynchronous tests and hooks.
- Don't use negation in `if` statements that have `else` clauses.
@ -295,30 +304,34 @@ Ultracite enforces strict type safety, accessibility standards, and consistent c
- Make sure to use the "use strict" directive in script files.
### Next.js Specific Rules
- Don't use `<img>` elements in Next.js projects.
- Don't use `<head>` elements in Next.js projects.
- Don't import next/document outside of pages/_document.jsx in Next.js projects.
- Don't use the next/head module in pages/_document.js on Next.js projects.
- Don't import next/document outside of pages/\_document.jsx in Next.js projects.
- Don't use the next/head module in pages/\_document.js on Next.js projects.
### Testing Best Practices
- Don't use export or module.exports in test files.
- Don't use focused tests.
- Make sure the assertion function, like expect, is placed inside an it() function call.
- Don't use disabled tests.
## Common Tasks
- `npx ultracite init` - Initialize Ultracite in your project
- `npx ultracite format` - Format and fix code automatically
- `npx ultracite lint` - Check for issues without fixing
## Example: Error Handling
```typescript
// ✅ Good: Comprehensive error handling
try {
const result = await fetchData();
return { success: true, data: result };
} catch (error) {
console.error('API call failed:', error);
console.error("API call failed:", error);
return { success: false, error: error.message };
}
@ -328,4 +341,4 @@ try {
} catch (e) {
console.log(e);
}
```
```

View File

@ -24,9 +24,10 @@ Please describe the tests that you ran to verify your changes. Provide instructi
- [ ] Test B
**Test Configuration**:
* Node version:
* Browser (if applicable):
* Operating System:
- Node version:
- Browser (if applicable):
- Operating System:
## Screenshots (if applicable)
@ -46,4 +47,4 @@ Add screenshots to help explain your changes.
## Additional context
Add any other context about the pull request here.
Add any other context about the pull request here.

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
.git
apps/web/.next/
apps/web/public/

View File

@ -1,3 +1,3 @@
{
"plugins": ["prettier-plugin-tailwindcss"]
}
}

29
.vscode/settings.json vendored
View File

@ -1,17 +1,16 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript][typescript][javascriptreact][typescriptreact][json][jsonc][css][graphql]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"emmet.showExpandedAbbreviation": "never",
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript][typescript][javascriptreact][typescriptreact][json][jsonc][css][graphql]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"emmet.showExpandedAbbreviation": "never",
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View File

@ -32,16 +32,17 @@ import { useEditor } from '@/hooks/use-editor';
function MyComponent() {
const editor = useEditor();
const tracks = editor.timeline.getTracks();
// Call methods
editor.timeline.addTrack({ type: 'media' });
// Display data (auto re-renders on changes)
return <div>{tracks.length} tracks</div>;
}
```
The hook:
- Returns the singleton instance
- Subscribes to all manager changes
- Automatically re-renders when state changes
@ -52,10 +53,10 @@ The hook:
```typescript
// In utilities, event handlers, or non-React code
import { EditorCore } from '@/core';
import { EditorCore } from "@/core";
const editor = EditorCore.getInstance();
await editor.export({ format: 'mp4', quality: 'high' });
await editor.export({ format: "mp4", quality: "high" });
```
## Actions System
@ -65,6 +66,7 @@ Actions are the trigger layer for user-initiated operations. The single source o
**To add a new action:**
1. Add it to `ACTIONS` in `@/lib/actions/definitions.ts`:
```typescript
export const ACTIONS = {
"my-action": {
@ -73,14 +75,19 @@ export const ACTIONS = {
defaultShortcuts: ["ctrl+m"],
},
// ...
}
};
```
2. Add handler in `@/hooks/use-editor-actions.ts`:
```typescript
useActionHandler("my-action", () => {
// implementation
}, undefined);
useActionHandler(
"my-action",
() => {
// implementation
},
undefined,
);
```
**In components, use `invokeAction()` for user-triggered operations:**
@ -102,6 +109,7 @@ Direct `editor.xxx()` calls are for internal use (commands, tests, complex multi
Commands handle undo/redo. They live in `@/lib/commands/` organized by domain (timeline, media, scene).
Each command extends `Command` from `@/lib/commands/base-command` and implements:
- `execute()` - saves current state, then does the mutation
- `undo()` - restores the saved state

View File

@ -1,6 +0,0 @@
[x] Delete all stores we can
[x] Create commands for each action
[x] Finish timeline store
[x] Migrate final timeline store to manager
[x] Delete timeline store
[ ] Update usage of all stores to use the new managers

View File

@ -96,7 +96,7 @@ function buildSortParameter({ query, sort }: { query?: string; sort: string }) {
function applyEffectsFilters({
params,
min_rating,
commercial_only
commercial_only,
}: {
params: URLSearchParams;
min_rating: number;
@ -108,17 +108,19 @@ function applyEffectsFilters({
if (commercial_only) {
params.append(
"filter",
'license:("Attribution" OR "Creative Commons 0" OR "Attribution Noncommercial" OR "Attribution Commercial")'
'license:("Attribution" OR "Creative Commons 0" OR "Attribution Noncommercial" OR "Attribution Commercial")',
);
}
params.append(
"filter",
"tag:sound-effect OR tag:sfx OR tag:foley OR tag:ambient OR tag:nature OR tag:mechanical OR tag:electronic OR tag:impact OR tag:whoosh OR tag:explosion"
"tag:sound-effect OR tag:sfx OR tag:foley OR tag:ambient OR tag:nature OR tag:mechanical OR tag:electronic OR tag:impact OR tag:whoosh OR tag:explosion",
);
}
function transformFreesoundResult(result: z.infer<typeof freesoundResultSchema>) {
function transformFreesoundResult(
result: z.infer<typeof freesoundResultSchema>,
) {
return {
id: result.id,
name: result.name,
@ -169,7 +171,7 @@ export async function GET(request: NextRequest) {
error: "Invalid parameters",
details: validationResult.error.flatten().fieldErrors,
},
{ status: 400 }
{ status: 400 },
);
}
@ -190,7 +192,7 @@ export async function GET(request: NextRequest) {
message:
"Song search functionality is coming soon. Try searching for sound effects instead.",
},
{ status: 501 }
{ status: 501 },
);
}
@ -220,7 +222,7 @@ export async function GET(request: NextRequest) {
console.error("Freesound API error:", response.status, errorText);
return NextResponse.json(
{ error: "Failed to search sounds" },
{ status: response.status }
{ status: response.status },
);
}
@ -230,11 +232,11 @@ export async function GET(request: NextRequest) {
if (!freesoundValidation.success) {
console.error(
"Invalid Freesound API response:",
freesoundValidation.error
freesoundValidation.error,
);
return NextResponse.json(
{ error: "Invalid response from Freesound API" },
{ status: 502 }
{ status: 502 },
);
}
@ -259,11 +261,11 @@ export async function GET(request: NextRequest) {
if (!responseValidation.success) {
console.error(
"Invalid API response structure:",
responseValidation.error
responseValidation.error,
);
return NextResponse.json(
{ error: "Internal response formatting error" },
{ status: 500 }
{ status: 500 },
);
}
@ -272,7 +274,7 @@ export async function GET(request: NextRequest) {
console.error("Error searching sounds:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
{ status: 500 },
);
}
}
}

View File

@ -30,7 +30,7 @@ export function BasePage({
<Header />
<main
className={cn(
"container relative mx-auto flex flex-col gap-12 px-6 pb-24 pt-12 md:pt-24",
"relative container mx-auto flex flex-col gap-12 px-6 pt-12 pb-24 md:pt-24",
maxWidthClass,
mainClassName,
)}

View File

@ -42,7 +42,7 @@ export default async function BlogPage() {
function BlogPostItem({ post }: { post: Post }) {
return (
<Link href={`/blog/${post.slug}`}>
<div className="h-auto w-full opacity-100 transition-opacity hover:opacity-75 flex items-center justify-between py-6">
<div className="flex h-auto w-full items-center justify-between py-6 opacity-100 transition-opacity hover:opacity-75">
<div className="flex flex-col gap-2">
<h2 className="text-xl font-semibold">{post.title}</h2>
<p className="text-muted-foreground">{post.description}</p>

View File

@ -190,7 +190,7 @@ export default function ProjectsPage() {
)}
</div>
</div>
<main className="mx-auto max-w-6xl px-6 pb-6 pt-6">
<main className="mx-auto max-w-6xl px-6 pt-6 pb-6">
<div className="mb-8 flex items-center justify-between">
<div className="flex flex-col gap-3">
<h1 className="text-2xl font-bold tracking-tight md:text-3xl">
@ -419,16 +419,18 @@ function ProjectCard({
const cardContent = (
<Card
className={`bg-background overflow-hidden border-none p-0 transition-all ${isSelectionMode && isSelected ? "ring-primary ring-2" : ""
}`}
className={`bg-background overflow-hidden border-none p-0 transition-all ${
isSelectionMode && isSelected ? "ring-primary ring-2" : ""
}`}
>
<div
className={`bg-muted relative aspect-square transition-opacity ${isDropdownOpen ? "opacity-65" : "opacity-100 group-hover:opacity-65"
}`}
className={`bg-muted relative aspect-square transition-opacity ${
isDropdownOpen ? "opacity-65" : "opacity-100 group-hover:opacity-65"
}`}
>
{isSelectionMode && (
<div className="absolute left-3 top-3 z-10">
<div className="bg-background/80 backdrop-blur-xs flex size-5 items-center justify-center rounded-full border">
<div className="absolute top-3 left-3 z-10">
<div className="bg-background/80 flex size-5 items-center justify-center rounded-full border backdrop-blur-xs">
<Checkbox
checked={isSelected}
onCheckedChange={(checked) =>
@ -462,7 +464,7 @@ function ProjectCard({
<CardContent className="flex flex-col gap-1 px-0 pt-5">
<div className="flex items-start justify-between">
<h3 className="group-hover:text-foreground/90 line-clamp-2 text-sm font-medium leading-snug transition-colors">
<h3 className="group-hover:text-foreground/90 line-clamp-2 text-sm leading-snug font-medium transition-colors">
{project.name}
</h3>
{!isSelectionMode && (
@ -475,10 +477,11 @@ function ProjectCard({
aria-label="project options"
variant="text"
size="sm"
className={`ml-2 size-6 shrink-0 p-0 transition-all ${isDropdownOpen
? "opacity-100"
: "opacity-0 group-hover:opacity-100"
}`}
className={`ml-2 size-6 shrink-0 p-0 transition-all ${
isDropdownOpen
? "opacity-100"
: "opacity-0 group-hover:opacity-100"
}`}
onClick={(event) => event.preventDefault()}
>
<MoreHorizontal aria-hidden="true" />

View File

@ -156,7 +156,7 @@ function RoadmapItem({ item, index }: { item: RoadmapItem; index: number }) {
return (
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2 text-lg font-medium">
<span className="select-none leading-normal">{index + 1}</span>
<span className="leading-normal select-none">{index + 1}</span>
<h3>{item.title}</h3>
<StatusBadge status={item.status} className="ml-1" />
</div>

View File

@ -14,8 +14,9 @@ export async function GET() {
language: "en",
image: `${SITE_INFO.openGraphImage}`,
favicon: `${SITE_INFO.favicon}`,
copyright: `All rights reserved ${new Date().getFullYear()}, ${SITE_INFO.title
}`,
copyright: `All rights reserved ${new Date().getFullYear()}, ${
SITE_INFO.title
}`,
});
for (const post of posts) {

View File

@ -27,15 +27,15 @@ export function MediaDragOverlay({
return (
<div
className="flex flex-col items-center justify-center gap-4 h-full text-center rounded-lg bg-foreground/5 hover:bg-foreground/10 transition-all duration-200 p-8"
className="bg-foreground/5 hover:bg-foreground/10 flex h-full flex-col items-center justify-center gap-4 rounded-lg p-8 text-center transition-all duration-200"
onClick={handleClick}
>
<div className="flex items-center justify-center">
<Upload className="h-10 w-10 text-foreground" />
<Upload className="text-foreground h-10 w-10" />
</div>
<div className="space-y-2">
<p className="text-xs text-muted-foreground max-w-sm">
<p className="text-muted-foreground max-w-sm text-xs">
{isProcessing
? `Processing your files (${progress}%)`
: "Drag and drop videos, photos, and audio files here"}
@ -44,7 +44,7 @@ export function MediaDragOverlay({
{isProcessing && (
<div className="w-full max-w-xs">
<div className="w-full bg-muted/50 rounded-full h-2">
<div className="bg-muted/50 h-2 w-full rounded-full">
<div
className="bg-primary h-2 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}

View File

@ -73,7 +73,7 @@ export function TabBar() {
variant="sidebar"
sideOffset={8}
>
<div className="text-foreground text-sm font-medium leading-none">
<div className="text-foreground text-sm leading-none font-medium">
{tab.label}
</div>
</TooltipContent>
@ -99,7 +99,7 @@ function FadeOverlay({
return (
<div
className={cn(
"pointer-events-none absolute left-0 right-0 h-6 transition-opacity duration-200",
"pointer-events-none absolute right-0 left-0 h-6 transition-opacity duration-200",
direction === "top" && show
? "from-panel top-0 bg-gradient-to-b to-transparent"
: "from-panel bottom-0 bg-gradient-to-t to-transparent",

View File

@ -23,9 +23,7 @@ export function Captions() {
const handleProgress = (progress: TranscriptionProgress) => {
if (progress.status === "loading-model") {
setProcessingStep(
`Loading model ${Math.round(progress.progress)}%`,
);
setProcessingStep(`Loading model ${Math.round(progress.progress)}%`);
} else if (progress.status === "transcribing") {
setProcessingStep("Transcribing...");
}
@ -48,7 +46,8 @@ export function Captions() {
const result = await transcriptionService.transcribe({
audioData: samples,
language: selectedLanguage === "auto" ? "auto" : selectedLanguage.toLowerCase(),
language:
selectedLanguage === "auto" ? "auto" : selectedLanguage.toLowerCase(),
onProgress: handleProgress,
});

View File

@ -49,7 +49,8 @@ export function MediaView() {
const mediaFiles = editor.media.getAssets();
const activeProject = editor.project.getActive();
const { mediaViewMode, setMediaViewMode, highlightMediaId, clearHighlight } = useAssetsPanelStore();
const { mediaViewMode, setMediaViewMode, highlightMediaId, clearHighlight } =
useAssetsPanelStore();
const { highlightedId, registerElement } = useRevealItem(
highlightMediaId,
clearHighlight,
@ -509,7 +510,7 @@ function MediaDurationBadge({ duration }: { duration?: number }) {
if (!duration) return null;
return (
<div className="absolute bottom-1 right-1 rounded bg-black/70 px-1 text-xs text-white">
<div className="absolute right-1 bottom-1 rounded bg-black/70 px-1 text-xs text-white">
{formatDuration({ duration })}
</div>
);
@ -551,7 +552,6 @@ function MediaTypePlaceholder({
}
function MediaPreview({ item }: { item: MediaAsset }) {
if (item.type === "image") {
return (
<div className="flex size-full items-center justify-center">
@ -604,13 +604,7 @@ function MediaPreview({ item }: { item: MediaAsset }) {
);
}
return (
<MediaTypePlaceholder
icon={Image}
label="Unknown"
variant="muted"
/>
);
return <MediaTypePlaceholder icon={Image} label="Unknown" variant="muted" />;
}
function SortMenuItem({

View File

@ -82,11 +82,7 @@ function ProjectSettingsTabs() {
);
}
function getCurrentCanvasSize({
activeProject,
}: {
activeProject: TProject;
}) {
function getCurrentCanvasSize({ activeProject }: { activeProject: TProject }) {
const { canvasSize } = activeProject.settings;
return {
@ -155,9 +151,7 @@ function ProjectInfoView() {
<div className="flex flex-col gap-4">
<PropertyItem direction="column">
<PropertyItemLabel>Name</PropertyItemLabel>
<PropertyItemValue>
{activeProject.metadata.name}
</PropertyItemValue>
<PropertyItemValue>{activeProject.metadata.name}</PropertyItemValue>
</PropertyItem>
<PropertyItem direction="column">
@ -237,7 +231,7 @@ const BlurPreview = memo(
style={{ filter: `blur(${blur.value}px)` }}
loading="eager"
/>
<div className="absolute bottom-1 left-1 right-1 text-center">
<div className="absolute right-1 bottom-1 left-1 text-center">
<span className="rounded bg-black/50 px-1 text-xs text-white">
{blur.label}
</span>
@ -270,18 +264,18 @@ const BackgroundPreviews = memo(
className={cn(
"border-foreground/15 hover:border-primary aspect-square w-full cursor-pointer rounded-sm border",
isColorBackground &&
bg === currentBackgroundColor &&
"border-primary border-2",
bg === currentBackgroundColor &&
"border-primary border-2",
)}
style={
useBackgroundColor
? { backgroundColor: bg }
: {
background: bg,
backgroundSize: "cover",
backgroundPosition: "center",
backgroundRepeat: "no-repeat",
}
background: bg,
backgroundSize: "cover",
backgroundPosition: "center",
backgroundRepeat: "no-repeat",
}
}
onClick={() => handleColorSelect({ bg })}
/>

View File

@ -36,8 +36,8 @@ import { useInfiniteScroll } from "@/hooks/use-infinite-scroll";
export function SoundsView() {
return (
<div className="h-full flex flex-col">
<Tabs defaultValue="sound-effects" className="flex flex-col h-full">
<div className="flex h-full flex-col">
<Tabs defaultValue="sound-effects" className="flex h-full flex-col">
<div className="px-3 pt-4 pb-0">
<TabsList>
<TabsTrigger value="sound-effects">Sound effects</TabsTrigger>
@ -48,19 +48,19 @@ export function SoundsView() {
<Separator className="my-4" />
<TabsContent
value="sound-effects"
className="p-5 pt-0 mt-0 flex-1 flex flex-col min-h-0"
className="mt-0 flex min-h-0 flex-1 flex-col p-5 pt-0"
>
<SoundEffectsView />
</TabsContent>
<TabsContent
value="saved"
className="p-5 pt-0 mt-0 flex-1 flex flex-col min-h-0"
className="mt-0 flex min-h-0 flex-1 flex-col p-5 pt-0"
>
<SavedSoundsView />
</TabsContent>
<TabsContent
value="songs"
className="p-5 pt-0 mt-0 flex-1 flex flex-col min-h-0"
className="mt-0 flex min-h-0 flex-1 flex-col p-5 pt-0"
>
<SongsView />
</TabsContent>
@ -97,12 +97,15 @@ function SoundEffectsView() {
loadMore,
hasNextPage,
isLoadingMore,
} = useSoundSearch({ query: searchQuery, commercialOnly: showCommercialOnly });
} = useSoundSearch({
query: searchQuery,
commercialOnly: showCommercialOnly,
});
// Audio playback state
const [playingId, setPlayingId] = useState<number | null>(null);
const [audioElement, setAudioElement] = useState<HTMLAudioElement | null>(
null
null,
);
const { scrollAreaRef, handleScroll } = useInfiniteScroll({
@ -125,7 +128,7 @@ function SoundEffectsView() {
}
const response = await fetch(
"/api/sounds/search?page_size=50&sort=downloads"
"/api/sounds/search?page_size=50&sort=downloads",
);
if (!ignore) {
@ -146,7 +149,9 @@ function SoundEffectsView() {
console.error("Failed to fetch top sounds:", error);
setError({
error:
error instanceof Error ? error.message : "Failed to load sounds",
error instanceof Error
? error.message
: "Failed to load sounds",
});
}
} finally {
@ -221,7 +226,7 @@ function SoundEffectsView() {
};
return (
<div className="flex flex-col gap-5 mt-1 h-full">
<div className="mt-1 flex h-full flex-col gap-5">
<div className="flex items-center gap-3">
<Input
placeholder="Search sound effects"
@ -249,7 +254,7 @@ function SoundEffectsView() {
>
Show only commercially licensed
</DropdownMenuCheckboxItem>
<div className="px-2 py-1.5 text-xs text-muted-foreground">
<div className="text-muted-foreground px-2 py-1.5 text-xs">
{showCommercialOnly
? "Only showing sounds licensed for commercial use"
: "Showing all sounds regardless of license"}
@ -260,7 +265,7 @@ function SoundEffectsView() {
<div className="relative h-full overflow-hidden">
<ScrollArea
className="flex-1 h-full"
className="h-full flex-1"
ref={scrollAreaRef}
onScrollCapture={handleScrollWithPosition}
>
@ -289,7 +294,7 @@ function SoundEffectsView() {
</div>
)}
{isLoadingMore && (
<div className="text-muted-foreground text-sm text-center py-4">
<div className="text-muted-foreground py-4 text-center text-sm">
Loading more sounds...
</div>
)}
@ -314,7 +319,7 @@ function SavedSoundsView() {
// Audio playback state
const [playingId, setPlayingId] = useState<number | null>(null);
const [audioElement, setAudioElement] = useState<HTMLAudioElement | null>(
null
null,
);
// Clear confirmation dialog state
@ -378,7 +383,7 @@ function SavedSoundsView() {
if (isLoadingSavedSounds) {
return (
<div className="flex items-center justify-center h-full">
<div className="flex h-full items-center justify-center">
<div className="text-muted-foreground text-sm">
Loading saved sounds...
</div>
@ -388,7 +393,7 @@ function SavedSoundsView() {
if (savedSoundsError) {
return (
<div className="flex items-center justify-center h-full">
<div className="flex h-full items-center justify-center">
<div className="text-destructive text-sm">
Error: {savedSoundsError}
</div>
@ -398,14 +403,14 @@ function SavedSoundsView() {
if (savedSounds.length === 0) {
return (
<div className="bg-panel h-full p-4 flex flex-col items-center justify-center gap-3">
<div className="bg-panel flex h-full flex-col items-center justify-center gap-3 p-4">
<HeartIcon
className="w-10 h-10 text-muted-foreground"
className="text-muted-foreground h-10 w-10"
strokeWidth={1.5}
/>
<div className="flex flex-col gap-2 text-center">
<p className="text-lg font-medium">No saved sounds</p>
<p className="text-sm text-muted-foreground text-balance">
<p className="text-muted-foreground text-sm text-balance">
Click the heart icon on any sound to save it here
</p>
</div>
@ -414,9 +419,9 @@ function SavedSoundsView() {
}
return (
<div className="flex flex-col gap-5 mt-1 h-full">
<div className="mt-1 flex h-full flex-col gap-5">
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">
<p className="text-muted-foreground text-sm">
{savedSounds.length} saved{" "}
{savedSounds.length === 1 ? "sound" : "sounds"}
</p>
@ -425,7 +430,7 @@ function SavedSoundsView() {
<Button
variant="text"
size="sm"
className="h-auto text-muted-foreground hover:text-destructive !opacity-100"
className="text-muted-foreground hover:text-destructive h-auto !opacity-100"
>
Clear all
</Button>
@ -457,7 +462,7 @@ function SavedSoundsView() {
</div>
<div className="relative h-full overflow-hidden">
<ScrollArea className="flex-1 h-full">
<ScrollArea className="h-full flex-1">
<div className="flex flex-col gap-4">
{savedSounds.map((sound) => (
<AudioItem
@ -515,11 +520,11 @@ function AudioItem({
return (
<div
className="group flex items-center gap-3 opacity-100 hover:opacity-75 transition-opacity cursor-pointer"
className="group flex cursor-pointer items-center gap-3 opacity-100 transition-opacity hover:opacity-75"
onClick={handleClick}
>
<div className="relative w-12 h-12 bg-accent rounded-md flex items-center justify-center overflow-hidden shrink-0">
<div className="absolute inset-0 bg-gradient-to-br from-primary/20 to-transparent" />
<div className="bg-accent relative flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-md">
<div className="from-primary/20 absolute inset-0 bg-gradient-to-br to-transparent" />
{isPlaying ? (
<PauseIcon className="size-5" />
) : (
@ -527,9 +532,9 @@ function AudioItem({
)}
</div>
<div className="flex-1 min-w-0 overflow-hidden">
<p className="font-medium truncate text-sm">{sound.name}</p>
<span className="text-xs text-muted-foreground truncate block">
<div className="min-w-0 flex-1 overflow-hidden">
<p className="truncate text-sm font-medium">{sound.name}</p>
<span className="text-muted-foreground block truncate text-xs">
{sound.username}
</span>
</div>
@ -538,7 +543,7 @@ function AudioItem({
<Button
variant="text"
size="icon"
className="text-muted-foreground hover:text-foreground !opacity-100 w-auto"
className="text-muted-foreground hover:text-foreground w-auto !opacity-100"
onClick={handleAddToTimeline}
title="Add to timeline"
>
@ -547,10 +552,11 @@ function AudioItem({
<Button
variant="text"
size="icon"
className={`hover:text-foreground !opacity-100 w-auto ${isSaved
? "text-red-500 hover:text-red-600"
: "text-muted-foreground"
}`}
className={`hover:text-foreground w-auto !opacity-100 ${
isSaved
? "text-red-500 hover:text-red-600"
: "text-muted-foreground"
}`}
onClick={handleSaveClick}
title={isSaved ? "Remove from saved" : "Save sound"}
>

View File

@ -108,10 +108,7 @@ function StickerGrid({
};
return (
<div
className="grid gap-2"
style={gridStyle}
>
<div className="grid gap-2" style={gridStyle}>
{icons.map((iconName) => (
<StickerItem
key={iconName}
@ -160,7 +157,7 @@ function EmptyView({ message }: { message: string }) {
/>
<div className="flex flex-col gap-2 text-center">
<p className="text-lg font-medium">No stickers found</p>
<p className="text-muted-foreground text-balance text-sm">{message}</p>
<p className="text-muted-foreground text-sm text-balance">{message}</p>
</div>
</div>
);
@ -211,17 +208,17 @@ function StickersContentView({ category }: { category: StickerCategory }) {
const collection = collections[c.prefix];
return collection
? {
prefix: c.prefix,
name: c.name,
total: collection.total,
}
prefix: c.prefix,
name: c.name,
total: collection.total,
}
: null;
})
.filter(Boolean) as Array<{
prefix: string;
name: string;
total: number;
}>;
prefix: string;
name: string;
total: number;
}>;
}, [collections, category]);
const { scrollAreaRef, handleScroll } = useInfiniteScroll({
@ -485,7 +482,7 @@ function CollectionItem({ title, subtitle, onClick }: CollectionItemProps) {
return (
<Button
variant="outline"
className="h-auto justify-between py-2 rounded-md"
className="h-auto justify-between rounded-md py-2"
onClick={onClick}
>
<div className="text-left">
@ -523,7 +520,7 @@ function StickerItem({
const preview = imageError ? (
<div className="flex h-full w-full items-center justify-center p-2">
<span className="text-muted-foreground break-all text-center text-xs">
<span className="text-muted-foreground text-center text-xs break-all">
{displayName}
</span>
</div>
@ -534,10 +531,10 @@ function StickerItem({
hostIndex === 0
? getIconSvgUrl(iconName, { width: 64, height: 64 })
: buildIconSvgUrl(
ICONIFY_HOSTS[Math.min(hostIndex, ICONIFY_HOSTS.length - 1)],
iconName,
{ width: 64, height: 64 },
)
ICONIFY_HOSTS[Math.min(hostIndex, ICONIFY_HOSTS.length - 1)],
iconName,
{ width: 64, height: 64 },
)
}
alt={displayName}
width={64}
@ -546,9 +543,9 @@ function StickerItem({
style={
capSize
? {
maxWidth: "var(--sticker-max, 160px)",
maxHeight: "var(--sticker-max, 160px)",
}
maxWidth: "var(--sticker-max, 160px)",
maxHeight: "var(--sticker-max, 160px)",
}
: undefined
}
onError={() => {

View File

@ -28,7 +28,7 @@ export function TextView() {
name="Default text"
preview={
<div className="bg-panel-accent flex size-full items-center justify-center rounded">
<span className="select-none text-xs">Default text</span>
<span className="text-xs select-none">Default text</span>
</div>
}
dragData={{

View File

@ -52,11 +52,11 @@ export function ExportButton() {
}
}}
>
<div className="bg-linear-270 relative flex items-center gap-1.5 rounded-[0.8rem] from-[#2567EC] to-[#37B6F7] px-4 py-1 shadow-[0_1px_3px_0px_rgba(0,0,0,0.65)]">
<div className="relative flex items-center gap-1.5 rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7] px-4 py-1 shadow-[0_1px_3px_0px_rgba(0,0,0,0.65)]">
<TransitionUpIcon className="z-50" />
<span className="z-50 text-[0.875rem]">Export</span>
<div className="bg-linear-to-t absolute left-0 top-0 z-10 flex h-full w-full items-center justify-center rounded-[0.8rem] from-white/0 to-white/50">
<div className="bg-linear-270 absolute top-[0.08rem] z-50 h-[calc(100%-2px)] w-[calc(100%-2px)] rounded-[0.8rem] from-[#2567EC] to-[#37B6F7]"></div>
<div className="absolute top-0 left-0 z-10 flex h-full w-full items-center justify-center rounded-[0.8rem] bg-linear-to-t from-white/0 to-white/50">
<div className="absolute top-[0.08rem] z-50 h-[calc(100%-2px)] w-[calc(100%-2px)] rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7]"></div>
</div>
</div>
</button>
@ -263,7 +263,7 @@ function ExportPopover({
<Button
variant="outline"
className="w-full rounded-md"
onClick={() => { }}
onClick={() => {}}
>
Cancel
</Button>

View File

@ -5,11 +5,11 @@ import Image from "next/image";
function TikTokGuide() {
return (
<div className="absolute inset-0 pointer-events-none">
<div className="pointer-events-none absolute inset-0">
<Image
src="/platform-guides/tiktok-blueprint.png"
alt="TikTok layout guide"
className="absolute inset-0 w-full h-full object-contain"
className="absolute inset-0 h-full w-full object-contain"
draggable={false}
fill
/>

View File

@ -42,7 +42,7 @@ export function PanelBaseView({
ref,
}: PanelBaseViewProps) {
return (
<div className={cn("h-full flex flex-col", className)} ref={ref}>
<div className={cn("flex h-full flex-col", className)} ref={ref}>
{!tabs || tabs.length === 0 ? (
<ViewContent className={className}>{children}</ViewContent>
) : (
@ -50,15 +50,15 @@ export function PanelBaseView({
defaultValue={defaultTab}
value={value}
onValueChange={onValueChange}
className="flex flex-col h-full"
className="flex h-full flex-col"
>
<div className="sticky top-0 z-10 bg-panel">
<div className="bg-panel sticky top-0 z-10">
<div className="px-3 pt-3 pb-0">
<TabsList>
{tabs.map((tab) => (
<TabsTrigger key={tab.value} value={tab.value}>
{tab.icon ? (
<span className="inline-flex items-center mr-1">
<span className="mr-1 inline-flex items-center">
{tab.icon}
</span>
) : null}
@ -73,7 +73,7 @@ export function PanelBaseView({
<TabsContent
key={tab.value}
value={tab.value}
className="mt-0 flex-1 flex flex-col min-h-0"
className="mt-0 flex min-h-0 flex-1 flex-col"
>
<ViewContent className={className}>{tab.content}</ViewContent>
</TabsContent>

View File

@ -9,7 +9,7 @@ import { useEditor } from "@/hooks/use-editor";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
export function PropertiesPanel() {
const editor = useEditor();
const editor = useEditor();
const { selectedElements } = useElementSelection();
const elementsWithTracks = editor.timeline.getElementsWithTracks({
@ -57,7 +57,7 @@ function EmptyView() {
/>
<div className="flex flex-col gap-2 text-center">
<p className="text-lg font-medium">Its empty here</p>
<p className="text-muted-foreground text-balance text-sm">
<p className="text-muted-foreground text-sm text-balance">
Click an element on the timeline to edit its properties
</p>
</div>

View File

@ -20,7 +20,7 @@ export function PropertyItem({
direction === "row"
? "items-center justify-between gap-6"
: "flex-col gap-1.5",
className
className,
)}
>
{children}
@ -36,7 +36,7 @@ export function PropertyItemLabel({
className?: string;
}) {
return (
<label className={cn("text-xs text-muted-foreground", className)}>
<label className={cn("text-muted-foreground text-xs", className)}>
{children}
</label>
);
@ -72,7 +72,7 @@ export function PropertyGroup({
return (
<PropertyItem direction="column" className={cn("gap-3", className)}>
<div
className="flex items-center gap-1.5 cursor-pointer"
className="flex cursor-pointer items-center gap-1.5"
onClick={() => setIsExpanded(!isExpanded)}
>
<PropertyItemLabel className={cn("cursor-pointer", titleClassName)}>

View File

@ -118,7 +118,11 @@ export function TextProperties({
});
};
const handleTransparentToggle = ({ isTransparent }: { isTransparent: boolean }) => {
const handleTransparentToggle = ({
isTransparent,
}: {
isTransparent: boolean;
}) => {
const newColor = isTransparent ? "transparent" : lastSelectedColor.current;
editor.timeline.updateTextElement({
trackId,
@ -146,7 +150,7 @@ export function TextProperties({
<Textarea
placeholder="Name"
defaultValue={element.content}
className="min-h-18 bg-panel-accent resize-none"
className="bg-panel-accent min-h-18 resize-none"
onChange={(e) =>
editor.timeline.updateTextElement({
trackId,
@ -287,9 +291,11 @@ export function TextProperties({
value={fontSizeInput}
min={8}
max={300}
onChange={(e) => handleFontSizeChange({ value: e.target.value })}
onChange={(e) =>
handleFontSizeChange({ value: e.target.value })
}
onBlur={handleFontSizeBlur}
className="bg-panel-accent h-7 w-12 rounded-sm px-2 text-center !text-xs [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
className="bg-panel-accent h-7 w-12 [appearance:textfield] rounded-sm px-2 text-center !text-xs [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
/>
</div>
</PropertyItemValue>
@ -299,8 +305,7 @@ export function TextProperties({
<PropertyItemValue>
<ColorPicker
value={uppercase({
string:
(element.color || "FFFFFF").replace("#", "")
string: (element.color || "FFFFFF").replace("#", ""),
})}
onChange={(color) => {
editor.timeline.updateTextElement({
@ -337,9 +342,11 @@ export function TextProperties({
value={opacityInput}
min={0}
max={100}
onChange={(e) => handleOpacityChange({ value: e.target.value })}
onChange={(e) =>
handleOpacityChange({ value: e.target.value })
}
onBlur={handleOpacityBlur}
className="bg-panel-accent h-7 w-12 rounded-sm text-center !text-xs [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
className="bg-panel-accent h-7 w-12 [appearance:textfield] rounded-sm text-center !text-xs [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
/>
</div>
</PropertyItemValue>
@ -353,12 +360,11 @@ export function TextProperties({
string:
element.backgroundColor === "transparent"
? lastSelectedColor.current.replace("#", "")
: (element.backgroundColor).replace(
"#",
"",
),
: element.backgroundColor.replace("#", ""),
})}
onChange={(color) => handleColorChange({ color: `#${color}` })}
onChange={(color) =>
handleColorChange({ color: `#${color}` })
}
containerRef={containerRef}
className={
element.backgroundColor === "transparent"
@ -374,7 +380,8 @@ export function TextProperties({
size="icon"
onClick={() =>
handleTransparentToggle({
isTransparent: element.backgroundColor !== "transparent",
isTransparent:
element.backgroundColor !== "transparent",
})
}
className="bg-panel-accent size-9 overflow-hidden rounded-full p-0"
@ -383,7 +390,7 @@ export function TextProperties({
className={cn(
"text-foreground",
element.backgroundColor === "transparent" &&
"text-primary",
"text-primary",
)}
/>
</Button>

View File

@ -147,11 +147,11 @@ export function ScenesView({ children }: { children: React.ReactNode }) {
className={cn(
"w-full justify-between font-normal",
currentScene?.id === scene.id &&
!isSelectMode &&
"border-primary !text-primary",
!isSelectMode &&
"border-primary !text-primary",
isSelectMode &&
selectedScenes.has(scene.id) &&
"bg-accent border-foreground/30",
selectedScenes.has(scene.id) &&
"bg-accent border-foreground/30",
)}
onClick={() => handleSceneSwitch(scene.id)}
>
@ -159,8 +159,8 @@ export function ScenesView({ children }: { children: React.ReactNode }) {
<div className="flex items-center gap-2">
{((isSelectMode && selectedScenes.has(scene.id)) ||
(!isSelectMode && currentScene?.id === scene.id)) && (
<Check className="h-4 w-4" />
)}
<Check className="h-4 w-4" />
)}
</div>
</Button>
))}

View File

@ -79,8 +79,7 @@ export function AudioWaveform({
} else {
try {
newWaveSurfer.destroy();
} catch {
}
} catch {}
return;
}
@ -121,8 +120,7 @@ export function AudioWaveform({
requestAnimationFrame(() => {
try {
wsToDestroy.destroy();
} catch {
}
} catch {}
if (mounted) {
initWaveSurfer();
}
@ -142,8 +140,7 @@ export function AudioWaveform({
requestAnimationFrame(() => {
try {
wsToDestroy.destroy();
} catch {
}
} catch {}
});
}
};
@ -155,7 +152,7 @@ export function AudioWaveform({
className={`flex items-center justify-center ${className}`}
style={{ height }}
>
<span className="text-xs text-foreground/60">Audio unavailable</span>
<span className="text-foreground/60 text-xs">Audio unavailable</span>
</div>
);
}
@ -164,7 +161,7 @@ export function AudioWaveform({
<div className={`relative ${className}`}>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-xs text-foreground/60">Loading...</span>
<span className="text-foreground/60 text-xs">Loading...</span>
</div>
)}
<div

View File

@ -79,7 +79,7 @@ export function TimelineBookmark({
}}
onClick={(event) => handleBookmarkClick({ event })}
>
<div className="text-primary absolute left-[-5px] top-[-1px]">
<div className="text-primary absolute top-[-1px] left-[-5px]">
<Bookmark className="fill-primary size-3" />
</div>
</div>

View File

@ -14,7 +14,7 @@ export function DragLine({ dropTarget, tracks, isVisible }: DragLineProps) {
return (
<div
className="bg-primary pointer-events-none absolute left-0 right-0 z-50 h-0.5"
className="bg-primary pointer-events-none absolute right-0 left-0 z-50 h-0.5"
style={{ top: `${y}px` }}
/>
);

View File

@ -1,7 +1,15 @@
"use client";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Eye, EyeOff, VolumeOff, Volume2, LucideIcon, EyeIcon, Trash2 } from "lucide-react";
import {
Eye,
EyeOff,
VolumeOff,
Volume2,
LucideIcon,
EyeIcon,
Trash2,
} from "lucide-react";
import {
ContextMenu,
ContextMenuContent,
@ -249,7 +257,7 @@ export function Timeline() {
{tracks.length > 0 && (
<div
ref={trackLabelsRef}
className="z-100 bg-panel w-28 shrink-0 overflow-y-auto border-r"
className="bg-panel z-100 w-28 shrink-0 overflow-y-auto border-r"
style={{ paddingTop: TIMELINE_CONSTANTS.PADDING_TOP }}
>
<ScrollArea className="h-full w-full" ref={trackLabelsScrollRef}>
@ -378,7 +386,7 @@ export function Timeline() {
<ContextMenu key={track.id}>
<ContextMenuTrigger asChild>
<div
className="absolute left-0 right-0"
className="absolute right-0 left-0"
style={{
top: `${getCumulativeHeightBefore({
tracks,
@ -412,7 +420,6 @@ export function Timeline() {
>
<Volume2 />
<span>
{canTracktHaveAudio(track) && track.muted
? "Unmute track"
: "Mute track"}

View File

@ -38,7 +38,7 @@ export function SnapIndicator({
return (
<div
className="z-90 pointer-events-none absolute"
className="pointer-events-none absolute z-90"
style={{
left: `${leftPosition}px`,
top: topPosition,

View File

@ -82,18 +82,14 @@ export function TimelineElement({
const hasAudio = mediaSupportsAudio({ media: mediaAsset });
const {
handleResizeStart,
isResizing,
currentStartTime,
currentDuration,
} = useTimelineElementResize({
element,
track,
zoomLevel,
onSnapPointChange,
onResizeStateChange,
});
const { handleResizeStart, isResizing, currentStartTime, currentDuration } =
useTimelineElementResize({
element,
track,
zoomLevel,
onSnapPointChange,
onResizeStateChange,
});
const isCurrentElementSelected = selectedElements.some(
(selected) =>
@ -139,8 +135,9 @@ export function TimelineElement({
<ContextMenu>
<ContextMenuTrigger asChild>
<div
className={`absolute top-0 h-full select-none ${isBeingDragged ? "z-30" : "z-10"
}`}
className={`absolute top-0 h-full select-none ${
isBeingDragged ? "z-30" : "z-10"
}`}
style={{
left: `${elementLeft}px`,
width: `${elementWidth}px`,
@ -299,7 +296,7 @@ function ElementInner({
</div>
{(hasAudio ? isMuted : canElementBeHidden(element) && element.hidden) && (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div className="bg-opacity-50 pointer-events-none absolute inset-0 flex items-center justify-center bg-black">
{hasAudio ? (
<VolumeX className="size-6 text-white" />
) : (
@ -342,7 +339,7 @@ function ResizeHandle({
const isLeft = side === "left";
return (
<div
className={`bg-primary absolute bottom-0 top-0 z-50 flex w-[0.6rem] items-center justify-center ${isLeft ? "left-0 cursor-w-resize" : "right-0 cursor-e-resize"}`}
className={`bg-primary absolute top-0 bottom-0 z-50 flex w-[0.6rem] items-center justify-center ${isLeft ? "left-0 cursor-w-resize" : "right-0 cursor-e-resize"}`}
onMouseDown={(e) => handleResizeStart({ e, elementId, side })}
>
<div className="bg-foreground h-[1.5rem] w-[0.2rem] rounded-full" />
@ -383,7 +380,8 @@ function ElementContent({
}
if (element.type === "audio") {
const audioBuffer = element.sourceType === "library" ? element.buffer : undefined;
const audioBuffer =
element.sourceType === "library" ? element.buffer : undefined;
const audioUrl =
element.sourceType === "library"
@ -436,7 +434,7 @@ function ElementContent({
className={`relative size-full ${isSelected ? "bg-primary" : "bg-transparent"}`}
>
<div
className="absolute left-0 right-0"
className="absolute right-0 left-0"
style={{
backgroundImage: imageUrl ? `url(${imageUrl})` : "none",
backgroundRepeat: "repeat-x",

View File

@ -99,7 +99,7 @@ export function TimelinePlayhead({
<div className="bg-foreground absolute left-0 h-full w-0.5 cursor-col-resize" />
<div
className={`shadow-xs absolute left-1/2 top-1 size-3 -translate-x-1/2 transform rounded-full border-2 ${isSnappingToPlayhead ? "bg-foreground border-foreground" : "bg-foreground border-foreground/50"}`}
className={`absolute top-1 left-1/2 size-3 -translate-x-1/2 transform rounded-full border-2 shadow-xs ${isSnappingToPlayhead ? "bg-foreground border-foreground" : "bg-foreground border-foreground/50"}`}
/>
</div>
);

View File

@ -52,13 +52,10 @@ export function TimelineToolbar({
const newZoomLevel =
direction === "in"
? Math.min(
TIMELINE_CONSTANTS.ZOOM_MAX,
zoomLevel + TIMELINE_CONSTANTS.ZOOM_STEP,
)
: Math.max(
minZoom,
zoomLevel - TIMELINE_CONSTANTS.ZOOM_STEP,
);
TIMELINE_CONSTANTS.ZOOM_MAX,
zoomLevel + TIMELINE_CONSTANTS.ZOOM_STEP,
)
: Math.max(minZoom, zoomLevel - TIMELINE_CONSTANTS.ZOOM_STEP);
setZoomLevel({ zoom: newZoomLevel });
};
@ -146,7 +143,7 @@ function ToolbarLeftSection() {
icon={<SplitSquareHorizontal />}
tooltip="Coming soon" /* separate audio */
disabled={true}
onClick={({ event }) => { }}
onClick={({ event }) => {}}
/>
<ToolbarButton
@ -161,7 +158,7 @@ function ToolbarLeftSection() {
icon={<Snowflake />}
tooltip="Coming soon" /* freeze frame */
disabled={true}
onClick={({ event }) => { }}
onClick={({ event }) => {}}
/>
<ToolbarButton
@ -231,10 +228,7 @@ function SceneSelector() {
<SplitButtonLeft>{currentScene?.name || "No Scene"}</SplitButtonLeft>
<SplitButtonSeparator />
<ScenesView>
<SplitButtonRight
onClick={() => { }}
type="button"
>
<SplitButtonRight onClick={() => {}} type="button">
<LayersIcon className="size-4" />
</SplitButtonRight>
</ScenesView>
@ -254,19 +248,28 @@ function ToolbarRightSection({
onZoomChange: (zoom: number) => void;
onZoom: (options: { direction: "in" | "out" }) => void;
}) {
const { snappingEnabled, rippleEditingEnabled, toggleSnapping, toggleRippleEditing } = useTimelineStore();
const {
snappingEnabled,
rippleEditingEnabled,
toggleSnapping,
toggleRippleEditing,
} = useTimelineStore();
return (
<div className="flex items-center gap-1">
<TooltipProvider delayDuration={500}>
<ToolbarButton
icon={<Magnet className={cn(snappingEnabled ? "text-primary" : "")} />}
icon={
<Magnet className={cn(snappingEnabled ? "text-primary" : "")} />
}
tooltip="Auto snapping"
onClick={() => toggleSnapping()}
/>
<ToolbarButton
icon={<Link className={cn(rippleEditingEnabled ? "text-primary" : "")} />}
icon={
<Link className={cn(rippleEditingEnabled ? "text-primary" : "")} />
}
tooltip="Ripple editing"
onClick={() => toggleRippleEditing()}
/>

View File

@ -58,7 +58,7 @@ export function TimelineTrackContent({
});
const hasSelectedElements = track.elements.some((element) =>
isElementSelected({ trackId: track.id, elementId: element.id })
isElementSelected({ trackId: track.id, elementId: element.id }),
);
return (

View File

@ -115,7 +115,7 @@ export function Header() {
))}
</nav>
<ThemeToggle
className="absolute bottom-8 right-8 size-10"
className="absolute right-8 bottom-8 size-10"
iconClassName="!size-[1.2rem]"
onToggle={(e) => {
e.preventDefault();

View File

@ -52,11 +52,11 @@ export function KeyboardShortcutsHelp() {
// Auto-save the new keybinding
const conflict = validateKeybinding(
keyString,
recordingShortcut.action
recordingShortcut.action,
);
if (conflict) {
toast.error(
`Key "${keyString}" is already bound to "${conflict.existingAction}"`
`Key "${keyString}" is already bound to "${conflict.existingAction}"`,
);
setRecordingShortcut(null);
return;
@ -110,10 +110,10 @@ export function KeyboardShortcutsHelp() {
Shortcuts
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl max-h-[80vh] flex flex-col p-0">
<DialogContent className="flex max-h-[80vh] max-w-2xl flex-col p-0">
<DialogHeader className="flex-shrink-0 p-6 pb-0">
<DialogTitle className="flex items-center gap-2">
<Keyboard className="w-5 h-5" />
<Keyboard className="h-5 w-5" />
Keyboard Shortcuts
</DialogTitle>
<DialogDescription>
@ -122,11 +122,11 @@ export function KeyboardShortcutsHelp() {
</DialogDescription>
</DialogHeader>
<div className="overflow-y-auto flex-grow scrollbar-thin">
<div className="scrollbar-thin flex-grow overflow-y-auto">
<div className="space-y-6 p-6 pt-2">
{categories.map((category) => (
<div key={category} className="flex flex-col gap-1">
<h3 className="text-xs text-muted-foreground uppercase tracking-wide font-medium">
<h3 className="text-muted-foreground text-xs font-medium tracking-wide uppercase">
{category}
</h3>
<div className="space-y-1">
@ -153,7 +153,6 @@ export function KeyboardShortcutsHelp() {
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
@ -204,7 +203,7 @@ function ShortcutItem({
})}
</div>
{index < displayKeys.length - 1 && (
<span className="text-xs text-muted-foreground">or</span>
<span className="text-muted-foreground text-xs">or</span>
)}
</div>
))}
@ -240,4 +239,4 @@ function EditableShortcutKey({
{children}
</Button>
);
}
}

View File

@ -111,12 +111,12 @@ export function Handlebars({ children }: HandlebarsProps) {
width > 0 ? (rightHandle / (width + 10)) * 100 : 0;
return (
<div className="leading-16 flex justify-center gap-4">
<div className="flex justify-center gap-4 leading-16">
<div ref={containerRef} className="relative mt-0.5 -rotate-[2.76deg]">
<div className="absolute inset-0 z-10 flex h-full w-full justify-between rounded-2xl border border-yellow-500">
<div
ref={leftHandleRef}
className="bg-background absolute left-0 z-20 flex h-full w-7 cursor-ew-resize touch-none select-none items-center justify-center rounded-full border border-yellow-500"
className="bg-background absolute left-0 z-20 flex h-full w-7 cursor-ew-resize touch-none items-center justify-center rounded-full border border-yellow-500 select-none"
style={{
translate: `${leftHandle}px 0`,
}}
@ -135,7 +135,7 @@ export function Handlebars({ children }: HandlebarsProps) {
<div
ref={rightHandleRef}
className="bg-background absolute -left-[30px] z-20 flex h-full w-7 cursor-ew-resize touch-none select-none items-center justify-center rounded-full border border-yellow-500"
className="bg-background absolute -left-[30px] z-20 flex h-full w-7 cursor-ew-resize touch-none items-center justify-center rounded-full border border-yellow-500 select-none"
style={{
translate: `${rightHandle}px 0`,
}}

View File

@ -8,31 +8,31 @@ import Link from "next/link";
export function Hero() {
return (
<div className="min-h-[calc(100svh-4.5rem)] flex flex-col justify-between items-center text-center px-4">
<div className="flex min-h-[calc(100svh-4.5rem)] flex-col items-center justify-between px-4 text-center">
<Image
className="absolute top-0 left-0 -z-50 size-full object-cover invert dark:invert-0 opacity-85"
className="absolute top-0 left-0 -z-50 size-full object-cover opacity-85 invert dark:invert-0"
src="/landing-page-dark.png"
height={1903.5}
width={1269}
alt="landing-page.bg"
/>
<div className="max-w-3xl mx-auto w-full flex-1 flex flex-col justify-center">
<div className="inline-block font-bold tracking-tighter text-4xl md:text-[4rem]">
<div className="mx-auto flex w-full max-w-3xl flex-1 flex-col justify-center">
<div className="inline-block text-4xl font-bold tracking-tighter md:text-[4rem]">
<h1>The open source</h1>
<Handlebars>Video Editor</Handlebars>
</div>
<p className="mt-10 text-base sm:text-xl text-muted-foreground font-light tracking-wide max-w-xl mx-auto">
<p className="text-muted-foreground mx-auto mt-10 max-w-xl text-base font-light tracking-wide sm:text-xl">
A simple but powerful video editor that gets the job done. Works on
any platform.
</p>
<div className="mt-8 flex gap-8 justify-center">
<div className="mt-8 flex justify-center gap-8">
<Link href="/projects">
<Button
type="submit"
size="lg"
className="px-6 h-11 text-base bg-foreground"
className="bg-foreground h-11 px-6 text-base"
>
Try early beta
<ArrowRight className="ml-0.5" />

View File

@ -19,7 +19,7 @@ interface LanguageSelectProps {
function FlagPreloader({ languages }: { languages: Language[] }) {
return (
<div className="absolute -top-[9999px] left-0 pointer-events-none">
<div className="pointer-events-none absolute -top-[9999px] left-0">
{languages.map((language) => (
<ReactCountryFlag
key={language.code}
@ -74,7 +74,7 @@ export function LanguageSelect({
}, [expanded]);
const selectedLanguage = languages.find(
(lang) => lang.code === selectedCountry
(lang) => lang.code === selectedCountry,
);
const handleSelect = ({
@ -91,14 +91,14 @@ export function LanguageSelect({
};
return (
<div className="relative w-full h-9">
<div className="relative h-9 w-full">
<FlagPreloader languages={languages} />
<motion.button
type="button"
className={cn(
"absolute w-full h-full flex flex-col overflow-hidden items-start justify-between z-10 rounded-lg px-3 cursor-pointer",
"!bg-foreground/10 backdrop-blur-md text-foreground py-0",
"transition-[color,box-shadow] focus:border-ring focus:ring-ring/50 focus:ring-[1px]"
"absolute z-10 flex h-full w-full cursor-pointer flex-col items-start justify-between overflow-hidden rounded-lg px-3",
"!bg-foreground/10 text-foreground py-0 backdrop-blur-md",
"focus:border-ring focus:ring-ring/50 transition-[color,box-shadow] focus:ring-[1px]",
)}
initial={{
height: collapsedHeight,
@ -117,7 +117,7 @@ export function LanguageSelect({
>
{!expanded ? (
<div
className="flex items-center justify-between w-full"
className="flex w-full items-center justify-between"
style={{
height: collapsedHeight,
}}
@ -138,7 +138,7 @@ export function LanguageSelect({
</div>
</div>
) : (
<div className="flex flex-col gap-2 my-2.5 w-full overflow-y-auto scrollbar-hidden">
<div className="scrollbar-hidden my-2.5 flex w-full flex-col gap-2 overflow-y-auto">
<LanguageButton
language={{ code: "auto", name: "Auto" }}
onSelect={handleSelect}
@ -157,7 +157,7 @@ export function LanguageSelect({
</motion.button>
<motion.div
className="absolute top-1/2 right-3 -translate-y-1/2 pointer-events-none z-20 mt-0.5"
className="pointer-events-none absolute top-1/2 right-3 z-20 mt-0.5 -translate-y-1/2"
initial={{ opacity: 1 }}
animate={{ opacity: expanded ? 0 : 1 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
@ -186,7 +186,7 @@ function LanguageButton({
return (
<button
type="button"
className="flex items-center gap-2 cursor-pointer text-foreground hover:text-foreground/75"
className="text-foreground hover:text-foreground/75 flex cursor-pointer items-center gap-2"
onClick={(e) => onSelect({ code: language.code, e })}
>
{language.code === "auto" ? (

View File

@ -49,7 +49,7 @@ export function StorageProvider({ children }: StorageProviderProps) {
if (!hasSupport) {
toast.warning(
"Storage not fully supported. Some features may not work."
"Storage not fully supported. Some features may not work.",
);
}

View File

@ -11,7 +11,11 @@ interface ThemeToggleProps {
onToggle?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}
export function ThemeToggle({ className, iconClassName, onToggle }: ThemeToggleProps) {
export function ThemeToggle({
className,
iconClassName,
onToggle,
}: ThemeToggleProps) {
const { theme, setTheme } = useTheme();
return (

View File

@ -49,7 +49,7 @@ const AccordionContent = React.forwardRef<
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
<div className={cn("pt-0 pb-4", className)}>{children}</div>
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;

View File

@ -18,8 +18,8 @@ const AlertDialogOverlay = React.forwardRef<
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
className,
)}
{...props}
ref={ref}
@ -36,8 +36,8 @@ const AlertDialogContent = React.forwardRef<
<AlertDialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className
"bg-background 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
className,
)}
{...props}
/>
@ -52,7 +52,7 @@ const AlertDialogHeader = ({
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
className,
)}
{...props}
/>
@ -66,7 +66,7 @@ const AlertDialogFooter = ({
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
className,
)}
{...props}
/>
@ -91,7 +91,7 @@ const AlertDialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<AlertDialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));
@ -119,7 +119,7 @@ const AlertDialogCancel = React.forwardRef<
className={cn(
buttonVariants({ variant: "outline" }),
"mt-2 sm:mt-0",
className
className,
)}
{...props}
/>

View File

@ -16,7 +16,7 @@ const alertVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
const Alert = React.forwardRef<
@ -38,7 +38,7 @@ const AlertTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<h5
ref={ref}
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
className={cn("mb-1 leading-none font-medium tracking-tight", className)}
{...props}
/>
));

View File

@ -13,7 +13,7 @@ const Avatar = React.forwardRef<
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
className,
)}
{...props}
/>
@ -39,8 +39,8 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
"bg-muted flex h-full w-full items-center justify-center rounded-full",
className,
)}
{...props}
/>

View File

@ -20,12 +20,13 @@ const badgeVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> { }
extends
React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (

View File

@ -19,8 +19,8 @@ const BreadcrumbList = React.forwardRef<
<ol
ref={ref}
className={cn(
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
className
"text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
className,
)}
{...props}
/>
@ -50,7 +50,7 @@ const BreadcrumbLink = React.forwardRef<
return (
<Comp
ref={ref}
className={cn("transition-colors hover:text-foreground", className)}
className={cn("hover:text-foreground transition-colors", className)}
{...props}
/>
);
@ -66,7 +66,7 @@ const BreadcrumbPage = React.forwardRef<
role="link"
aria-disabled="true"
aria-current="page"
className={cn("font-normal text-foreground", className)}
className={cn("text-foreground font-normal", className)}
{...props}
/>
));
@ -80,7 +80,7 @@ const BreadcrumbSeparator = ({
<li
role="presentation"
aria-hidden="true"
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
className={cn("[&>svg]:h-3.5 [&>svg]:w-3.5", className)}
{...props}
>
{children ?? <ChevronRight />}

View File

@ -41,8 +41,9 @@ const buttonVariants = cva(
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
extends
React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}

View File

@ -27,7 +27,7 @@ function Calendar({
nav: "space-x-1 flex items-center",
nav_button: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
),
nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1",
@ -40,11 +40,11 @@ function Calendar({
"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"
: "[&:has([aria-selected])]:rounded-md",
),
day: cn(
buttonVariants({ variant: "text" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100"
"h-8 w-8 p-0 font-normal aria-selected:opacity-100",
),
day_range_start: "day-range-start",
day_range_end: "day-range-end",

View File

@ -8,7 +8,7 @@ const Card = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("rounded-2xl border bg-card text-card-foreground", className)}
className={cn("bg-card text-card-foreground rounded-2xl border", className)}
{...props}
/>
));
@ -32,7 +32,7 @@ const CardTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("font-semibold leading-none tracking-tight", className)}
className={cn("leading-none font-semibold tracking-tight", className)}
{...props}
/>
));
@ -44,7 +44,7 @@ const CardDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));

View File

@ -56,14 +56,14 @@ const Carousel = React.forwardRef<
children,
...props
},
ref
ref,
) => {
const [carouselRef, api] = useEmblaCarousel(
{
...opts,
axis: orientation === "horizontal" ? "x" : "y",
},
plugins
plugins,
);
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
const [canScrollNext, setCanScrollNext] = React.useState(false);
@ -95,7 +95,7 @@ const Carousel = React.forwardRef<
scrollNext();
}
},
[scrollPrev, scrollNext]
[scrollPrev, scrollNext],
);
React.useEffect(() => {
@ -146,7 +146,7 @@ const Carousel = React.forwardRef<
</div>
</CarouselContext.Provider>
);
}
},
);
Carousel.displayName = "Carousel";
@ -163,7 +163,7 @@ const CarouselContent = React.forwardRef<
className={cn(
"flex",
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
className
className,
)}
{...props}
/>
@ -186,7 +186,7 @@ const CarouselItem = React.forwardRef<
className={cn(
"min-w-0 shrink-0 grow-0 basis-full",
orientation === "horizontal" ? "pl-4" : "pt-4",
className
className,
)}
{...props}
/>
@ -206,11 +206,11 @@ const CarouselPrevious = React.forwardRef<
variant={variant}
size={size}
className={cn(
"absolute h-8 w-8 rounded-full",
"absolute h-8 w-8 rounded-full",
orientation === "horizontal"
? "-left-12 top-1/2 -translate-y-1/2"
? "top-1/2 -left-12 -translate-y-1/2"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
className
className,
)}
disabled={!canScrollPrev}
onClick={scrollPrev}
@ -237,9 +237,9 @@ const CarouselNext = React.forwardRef<
className={cn(
"absolute h-8 w-8 rounded-full",
orientation === "horizontal"
? "-right-12 top-1/2 -translate-y-1/2"
? "top-1/2 -right-12 -translate-y-1/2"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
className
className,
)}
disabled={!canScrollNext}
onClick={scrollNext}

View File

@ -57,8 +57,8 @@ const ChartContainer = React.forwardRef<
data-chart={chartId}
ref={ref}
className={cn(
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-hidden [&_.recharts-surface]:outline-hidden",
className
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
className,
)}
{...props}
>
@ -74,7 +74,7 @@ ChartContainer.displayName = "Chart";
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
const colorConfig = Object.entries(config).filter(
([_, config]) => config.theme || config.color
([_, config]) => config.theme || config.color,
);
if (!colorConfig.length) {
@ -89,15 +89,15 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
([theme, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color;
return color ? ` --color-${key}: ${color};` : null;
})
.join("\n")}
.map(([key, itemConfig]) => {
const color =
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
itemConfig.color;
return color ? ` --color-${key}: ${color};` : null;
})
.join("\n")}
}
`
`,
)
.join("\n"),
}}
@ -110,13 +110,13 @@ const ChartTooltip = RechartsPrimitive.Tooltip;
const ChartTooltipContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
React.ComponentProps<"div"> & {
hideLabel?: boolean;
hideIndicator?: boolean;
indicator?: "line" | "dot" | "dashed";
nameKey?: string;
labelKey?: string;
}
React.ComponentProps<"div"> & {
hideLabel?: boolean;
hideIndicator?: boolean;
indicator?: "line" | "dot" | "dashed";
nameKey?: string;
labelKey?: string;
}
>(
(
{
@ -134,7 +134,7 @@ const ChartTooltipContent = React.forwardRef<
nameKey,
labelKey,
},
ref
ref,
) => {
const { config } = useChart();
@ -184,8 +184,8 @@ const ChartTooltipContent = React.forwardRef<
<div
ref={ref}
className={cn(
"grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
className
"border-border/50 bg-background grid min-w-32 items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
className,
)}
>
{nestLabel ? null : tooltipLabel}
@ -199,8 +199,8 @@ const ChartTooltipContent = React.forwardRef<
<div
key={item.dataKey}
className={cn(
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
indicator === "dot" && "items-center"
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
indicator === "dot" && "items-center",
)}
>
{formatter && item?.value !== undefined && item.name ? (
@ -220,7 +220,7 @@ const ChartTooltipContent = React.forwardRef<
"w-0 border-[1.5px] border-dashed bg-transparent":
indicator === "dashed",
"my-0.5": nestLabel && indicator === "dashed",
}
},
)}
style={
{
@ -234,7 +234,7 @@ const ChartTooltipContent = React.forwardRef<
<div
className={cn(
"flex flex-1 justify-between leading-none",
nestLabel ? "items-end" : "items-center"
nestLabel ? "items-end" : "items-center",
)}
>
<div className="grid gap-1.5">
@ -244,7 +244,7 @@ const ChartTooltipContent = React.forwardRef<
</span>
</div>
{item.value && (
<span className="font-mono font-medium tabular-nums text-foreground">
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}
@ -257,7 +257,7 @@ const ChartTooltipContent = React.forwardRef<
</div>
</div>
);
}
},
);
ChartTooltipContent.displayName = "ChartTooltip";
@ -266,14 +266,14 @@ const ChartLegend = RechartsPrimitive.Legend;
const ChartLegendContent = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> &
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean;
nameKey?: string;
}
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
hideIcon?: boolean;
nameKey?: string;
}
>(
(
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
ref
ref,
) => {
const { config } = useChart();
@ -287,7 +287,7 @@ const ChartLegendContent = React.forwardRef<
className={cn(
"flex items-center justify-center gap-4",
verticalAlign === "top" ? "pb-3" : "pt-3",
className
className,
)}
>
{payload.map((item) => {
@ -298,7 +298,7 @@ const ChartLegendContent = React.forwardRef<
<div
key={item.value}
className={cn(
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3",
)}
>
{itemConfig?.icon && !hideIcon ? (
@ -317,7 +317,7 @@ const ChartLegendContent = React.forwardRef<
})}
</div>
);
}
},
);
ChartLegendContent.displayName = "ChartLegend";
@ -325,7 +325,7 @@ ChartLegendContent.displayName = "ChartLegend";
function getPayloadConfigFromPayload(
config: ChartConfig,
payload: unknown,
key: string
key: string,
) {
if (typeof payload !== "object" || payload === null) {
return;
@ -333,8 +333,8 @@ function getPayloadConfigFromPayload(
const payloadPayload =
"payload" in payload &&
typeof payload.payload === "object" &&
payload.payload !== null
typeof payload.payload === "object" &&
payload.payload !== null
? payload.payload
: undefined;

View File

@ -13,8 +13,8 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow-sm focus-visible:outline-hidden 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",
className
"peer border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground h-4 w-4 shrink-0 rounded-sm border shadow-sm focus-visible:ring-1 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
>

View File

@ -135,11 +135,11 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
const rect = saturationRef.current.getBoundingClientRect();
const x = Math.max(
0,
Math.min(1, (e.clientX - rect.left) / rect.width)
Math.min(1, (e.clientX - rect.left) / rect.width),
);
const y = Math.max(
0,
Math.min(1, (e.clientY - rect.top) / rect.height)
Math.min(1, (e.clientY - rect.top) / rect.height),
);
const newS = x;
const newV = 1 - y;
@ -151,7 +151,7 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
const rect = hueRef.current.getBoundingClientRect();
const x = Math.max(
0,
Math.min(1, (e.clientX - rect.left) / rect.width)
Math.min(1, (e.clientX - rect.left) / rect.width),
);
const newH = x * 360;
setInternalHue(newH);
@ -231,14 +231,14 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
<div
ref={ref}
className={cn(
"bg-panel-accent h-9 rounded-full flex items-center gap-2 px-[0.45rem]",
className
"bg-panel-accent flex h-9 items-center gap-2 rounded-full px-[0.45rem]",
className,
)}
{...props}
>
<div
ref={triggerRef}
className="size-6 rounded-full cursor-pointer hover:ring-2 hover:ring-white/20 transition-all"
className="size-6 cursor-pointer rounded-full transition-all hover:ring-2 hover:ring-white/20"
style={{ backgroundColor: `#${value}` }}
onClick={() => {
if (!isOpen && triggerRef.current && containerRef?.current) {
@ -252,9 +252,9 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
setIsOpen(!isOpen);
}}
/>
<div className="flex-1 flex items-center">
<div className="flex flex-1 items-center">
<Input
className="bg-transparent p-0 !ring-0 !ring-offset-0 !border-0"
className="!border-0 bg-transparent p-0 !ring-0 !ring-offset-0"
containerClassName="w-full"
value={inputValue}
onChange={handleInputChange}
@ -268,7 +268,7 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
createPortal(
<div
ref={pickerRef}
className="fixed z-50 p-4 bg-popover border border-border rounded-lg shadow-lg select-none"
className="bg-popover border-border fixed z-50 rounded-lg border p-4 shadow-lg select-none"
style={{
right: pickerPosition.right,
bottom: pickerPosition.bottom,
@ -276,7 +276,7 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
>
<div
ref={saturationRef}
className="relative w-48 h-32 cursor-crosshair mb-3"
className="relative mb-3 h-32 w-48 cursor-crosshair"
style={saturationStyle}
onMouseDown={handleSaturationMouseDown}
>
@ -289,7 +289,7 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
<div
ref={hueRef}
className="relative w-48 h-4 rounded-lg cursor-pointer"
className="relative h-4 w-48 cursor-pointer rounded-lg"
style={hueStyle}
onMouseDown={handleHueMouseDown}
>
@ -303,11 +303,11 @@ const ColorPicker = React.forwardRef<HTMLDivElement, ColorPickerProps>(
/>
</div>
</div>,
document.body
document.body,
)}
</div>
);
}
},
);
ColorPicker.displayName = "ColorPicker";
@ -321,8 +321,9 @@ const ColorCircle = ({
color: string;
}) => (
<div
className={`absolute border-3 border-white rounded-full shadow-lg pointer-events-none ${size === "sm" ? "size-3" : "size-4"
}`}
className={`pointer-events-none absolute rounded-full border-3 border-white shadow-lg ${
size === "sm" ? "size-3" : "size-4"
}`}
style={{
left: position.left,
top: position.top,

View File

@ -14,8 +14,8 @@ const Command = React.forwardRef<
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
className,
)}
{...props}
/>
@ -26,7 +26,7 @@ const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children}
</Command>
</DialogContent>
@ -43,8 +43,8 @@ const CommandInput = React.forwardRef<
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
/>
@ -59,7 +59,7 @@ const CommandList = React.forwardRef<
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
className={cn("max-h-[300px] overflow-x-hidden overflow-y-auto", className)}
{...props}
/>
));
@ -86,8 +86,8 @@ const CommandGroup = React.forwardRef<
<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
"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
className,
)}
{...props}
/>
@ -101,7 +101,7 @@ const CommandSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
className={cn("bg-border -mx-1 h-px", className)}
{...props}
/>
));
@ -114,8 +114,8 @@ const CommandItem = React.forwardRef<
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className,
)}
{...props}
/>
@ -130,8 +130,8 @@ const CommandShortcut = ({
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
"text-muted-foreground ml-auto text-xs tracking-widest",
className,
)}
{...props}
/>

View File

@ -31,7 +31,7 @@ const contextMenuItemVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
const ContextMenuSubTrigger = React.forwardRef<
@ -47,7 +47,7 @@ const ContextMenuSubTrigger = React.forwardRef<
contextMenuItemVariants({ variant }),
"data-[state=open]:bg-accent data-[state=open]:opacity-65",
inset && "pl-8",
className
className,
)}
{...props}
>
@ -64,8 +64,8 @@ const ContextMenuSubContent = React.forwardRef<
<ContextMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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
"bg-popover text-popover-foreground 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-32 overflow-hidden rounded-md border p-1 shadow-lg",
className,
)}
{...props}
/>
@ -80,9 +80,9 @@ const ContextMenuContent = React.forwardRef<
<ContextMenuPrimitive.Content
ref={ref}
className={cn(
"z-50 min-w-32 overflow-hidden rounded-md border p-1 bg-popover text-popover-foreground shadow-md",
"bg-popover text-popover-foreground z-50 min-w-32 overflow-hidden rounded-md border p-1 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",
className
className,
)}
{...props}
/>
@ -102,7 +102,7 @@ const ContextMenuItem = React.forwardRef<
className={cn(
contextMenuItemVariants({ variant }),
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -117,7 +117,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
>(({ className, children, checked, variant = "default", ...props }, ref) => (
<ContextMenuPrimitive.CheckboxItem
ref={ref}
className={cn(contextMenuItemVariants({ variant }), "pl-8 pr-2", className)}
className={cn(contextMenuItemVariants({ variant }), "pr-2 pl-8", className)}
checked={checked}
{...props}
>
@ -140,7 +140,7 @@ const ContextMenuRadioItem = React.forwardRef<
>(({ className, children, variant = "default", ...props }, ref) => (
<ContextMenuPrimitive.RadioItem
ref={ref}
className={cn(contextMenuItemVariants({ variant }), "pl-8 pr-2", className)}
className={cn(contextMenuItemVariants({ variant }), "pr-2 pl-8", className)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
@ -164,7 +164,7 @@ const ContextMenuLabel = React.forwardRef<
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -177,7 +177,7 @@ const ContextMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<ContextMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-foreground/10", className)}
className={cn("bg-foreground/10 -mx-1 my-1 h-px", className)}
{...props}
/>
));

View File

@ -22,8 +22,8 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-250 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-250 bg-black/50",
className,
)}
{...props}
/>
@ -39,8 +39,8 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] p-6 z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-popover shadow-lg duration-200 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 rounded-lg",
className
"bg-popover 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 fixed top-[50%] left-[50%] z-250 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200",
className,
)}
onCloseAutoFocus={(e) => {
e.stopPropagation();
@ -49,7 +49,7 @@ const DialogContent = React.forwardRef<
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground cursor-pointer">
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 cursor-pointer opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
@ -63,10 +63,7 @@ const DialogHeader = ({
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-left",
className
)}
className={cn("flex flex-col space-y-2 text-left", className)}
{...props}
/>
);
@ -79,7 +76,7 @@ const DialogFooter = ({
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
className,
)}
{...props}
/>
@ -93,8 +90,8 @@ const DialogTitle = React.forwardRef<
<DialogPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className
"text-lg leading-none font-semibold tracking-tight",
className,
)}
{...props}
/>
@ -107,7 +104,7 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));

View File

@ -170,7 +170,7 @@ export function DraggableItem({
typeof document !== "undefined" &&
createPortal(
<div
className="z-9999 pointer-events-none fixed"
className="pointer-events-none fixed z-9999"
style={{
left: dragPosition.x - 40,
top: dragPosition.y - 40,
@ -179,7 +179,7 @@ export function DraggableItem({
<div className="w-[80px]">
<AspectRatio
ratio={1}
className="ring-3 ring-primary relative overflow-hidden rounded-md shadow-2xl"
className="ring-primary relative overflow-hidden rounded-md shadow-2xl ring-3"
>
<div className="h-full w-full [&_img]:h-full [&_img]:w-full [&_img]:rounded-none [&_img]:object-cover">
{preview}
@ -212,7 +212,7 @@ function PlusButton({
<Button
size="icon"
className={cn(
"bg-background hover:bg-panel text-foreground absolute bottom-2 right-2 size-5",
"bg-background hover:bg-panel text-foreground absolute right-2 bottom-2 size-5",
className,
)}
onClick={(e) => {

View File

@ -43,12 +43,12 @@ const DrawerContent = React.forwardRef<
<DrawerPrimitive.Content
ref={ref}
className={cn(
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
className
"bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border",
className,
)}
{...props}
>
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
<div className="bg-muted mx-auto mt-4 h-2 w-[100px] rounded-full" />
{children}
</DrawerPrimitive.Content>
</DrawerPortal>
@ -84,8 +84,8 @@ const DrawerTitle = React.forwardRef<
<DrawerPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className
"text-lg leading-none font-semibold tracking-tight",
className,
)}
{...props}
/>
@ -98,7 +98,7 @@ const DrawerDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));

View File

@ -31,7 +31,7 @@ const dropdownMenuItemVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
const DropdownMenuSubTrigger = React.forwardRef<
@ -47,7 +47,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
dropdownMenuItemVariants({ variant }),
"data-[state=open]:bg-accent data-[state=open]:opacity-65",
inset && "pl-8",
className
className,
)}
{...props}
>
@ -65,8 +65,8 @@ const DropdownMenuSubContent = React.forwardRef<
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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
"bg-popover text-popover-foreground 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-32 overflow-hidden rounded-md border p-1 shadow-lg",
className,
)}
{...props}
/>
@ -87,9 +87,9 @@ const DropdownMenuContent = React.forwardRef<
e.preventDefault();
}}
className={cn(
"z-50 min-w-32 overflow-hidden rounded-md border p-1 bg-popover text-popover-foreground shadow-md",
"bg-popover text-popover-foreground z-50 min-w-32 overflow-hidden rounded-md border p-1 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",
className
className,
)}
{...props}
/>
@ -109,7 +109,7 @@ const DropdownMenuItem = React.forwardRef<
className={cn(
dropdownMenuItemVariants({ variant }),
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -126,8 +126,8 @@ const DropdownMenuCheckboxItem = React.forwardRef<
ref={ref}
className={cn(
dropdownMenuItemVariants({ variant }),
"pl-2 pr-8",
className
"pr-8 pl-2",
className,
)}
checked={checked}
onSelect={(e) => {
@ -157,8 +157,8 @@ const DropdownMenuRadioItem = React.forwardRef<
ref={ref}
className={cn(
dropdownMenuItemVariants({ variant }),
"pl-8 pr-2",
className
"pr-2 pl-8",
className,
)}
{...props}
>
@ -183,7 +183,7 @@ const DropdownMenuLabel = React.forwardRef<
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -196,7 +196,7 @@ const DropdownMenuSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-foreground/10", className)}
className={cn("bg-foreground/10 -mx-1 my-1 h-px", className)}
{...props}
/>
));

View File

@ -20,7 +20,9 @@ export function FontPicker({
}: FontPickerProps) {
return (
<Select defaultValue={defaultValue} onValueChange={onValueChange}>
<SelectTrigger className={`w-full bg-panel-accent h-8 text-xs ${className || ""}`}>
<SelectTrigger
className={`bg-panel-accent h-8 w-full text-xs ${className || ""}`}
>
<SelectValue placeholder="Select a font" />
</SelectTrigger>
<SelectContent>

View File

@ -25,7 +25,7 @@ type FormFieldContextValue<
};
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue
{} as FormFieldContextValue,
);
const FormField = <
@ -69,7 +69,7 @@ type FormItemContextValue = {
};
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue
{} as FormItemContextValue,
);
const FormItem = React.forwardRef<
@ -134,7 +134,7 @@ const FormDescription = React.forwardRef<
<p
ref={ref}
id={formDescriptionId}
className={cn("text-[0.8rem] text-muted-foreground", className)}
className={cn("text-muted-foreground text-[0.8rem]", className)}
{...props}
/>
);
@ -156,7 +156,7 @@ const FormMessage = React.forwardRef<
<p
ref={ref}
id={formMessageId}
className={cn("text-[0.8rem] font-medium text-destructive", className)}
className={cn("text-destructive text-[0.8rem] font-medium", className)}
{...props}
>
{body}

View File

@ -18,8 +18,8 @@ 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-hidden 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
"bg-popover text-popover-foreground 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-64 rounded-md border p-4 shadow-md outline-hidden",
className,
)}
{...props}
/>

View File

@ -14,7 +14,7 @@ const InputOTP = React.forwardRef<
ref={ref}
containerClassName={cn(
"flex items-center justify-between gap-2 w-full has-disabled:opacity-50",
containerClassName
containerClassName,
)}
className={cn("disabled:cursor-not-allowed", className)}
{...props}
@ -28,7 +28,7 @@ const InputOTPGroup = React.forwardRef<
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center flex-1 gap-2", className)}
className={cn("flex flex-1 items-center gap-2", className)}
{...props}
/>
));
@ -45,16 +45,16 @@ const InputOTPSlot = React.forwardRef<
<div
ref={ref}
className={cn(
"relative flex aspect-square flex-1 min-w-[36px] items-center justify-center border border-input text-lg shadow-xs transition-all first:rounded-l-md first:border-l last:rounded-r-md",
isActive && "z-10 ring-1 ring-ring",
className
"border-input relative flex aspect-square min-w-[36px] flex-1 items-center justify-center border text-lg shadow-xs transition-all first:rounded-l-md first:border-l last:rounded-r-md",
isActive && "ring-ring z-10 ring-1",
className,
)}
{...props}
>
{char}
{hasFakeCaret && (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
<div className="animate-caret-blink bg-foreground h-4 w-px duration-1000" />
</div>
)}
</div>

View File

@ -41,7 +41,7 @@ export function InputWithBack({
return (
<div ref={setContainerRef} className="relative w-full">
<motion.div
className="absolute left-0 top-1/2 -translate-y-1/2 cursor-pointer hover:opacity-75 transition-opacity z-10"
className="absolute top-1/2 left-0 z-10 -translate-y-1/2 cursor-pointer transition-opacity hover:opacity-75"
initial={{
x: isExpanded ? 0 : buttonOffset,
opacity: isExpanded ? 1 : 0.5,
@ -55,7 +55,7 @@ export function InputWithBack({
>
<Button
variant="outline"
className="!size-9 rounded-full bg-panel-accent"
className="bg-panel-accent !size-9 rounded-full"
>
<ArrowLeft />
</Button>
@ -74,10 +74,10 @@ export function InputWithBack({
}}
transition={smoothTransition}
>
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
placeholder={placeholder}
className="pl-9 bg-panel-accent w-full"
className="bg-panel-accent w-full pl-9"
value={value}
onChange={(e) => onChange?.(e.target.value)}
/>

View File

@ -29,7 +29,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
onBlur,
...props
},
ref
ref,
) => {
const [isFocused, setIsFocused] = useState(false);
@ -49,15 +49,17 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
iconCount === 2 ? "pr-20" : iconCount === 1 ? "pr-10" : "";
return (
<div className={cn(hasIcons ? "relative w-full" : "", containerClassName)}>
<div
className={cn(hasIcons ? "relative w-full" : "", containerClassName)}
>
<input
type={inputType}
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input flex h-9 w-full min-w-0 rounded-md border bg-background px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input bg-background flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[2px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
paddingRight,
className
className,
)}
ref={ref}
value={value}
@ -80,7 +82,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
e.preventDefault();
onClear?.();
}}
className="absolute right-0 top-0 h-full px-3 text-muted-foreground !opacity-100"
className="text-muted-foreground absolute top-0 right-0 h-full px-3 !opacity-100"
aria-label="Clear input"
>
<X className="!size-[0.85]" />
@ -93,8 +95,8 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
size="icon"
onClick={() => onShowPasswordChange?.(!showPassword)}
className={cn(
"absolute top-0 h-full px-3 text-muted-foreground hover:text-foreground",
showClear ? "right-10" : "right-0"
"text-muted-foreground hover:text-foreground absolute top-0 h-full px-3",
showClear ? "right-10" : "right-0",
)}
aria-label={showPassword ? "Hide password" : "Show password"}
>
@ -107,7 +109,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
)}
</div>
);
}
},
);
Input.displayName = "Input";

View File

@ -7,13 +7,13 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/utils/ui";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}

View File

@ -23,8 +23,8 @@ const Menubar = React.forwardRef<
<MenubarPrimitive.Root
ref={ref}
className={cn(
"flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-xs",
className
"bg-background flex h-9 items-center space-x-1 rounded-md border p-1 shadow-xs",
className,
)}
{...props}
/>
@ -38,8 +38,8 @@ const MenubarTrigger = React.forwardRef<
<MenubarPrimitive.Trigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
className
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-3 py-1 text-sm font-medium outline-hidden select-none",
className,
)}
{...props}
/>
@ -55,9 +55,9 @@ const MenubarSubTrigger = React.forwardRef<
<MenubarPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none",
inset && "pl-8",
className
className,
)}
{...props}
>
@ -74,8 +74,8 @@ const MenubarSubContent = React.forwardRef<
<MenubarPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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
"bg-popover text-popover-foreground 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-32 overflow-hidden rounded-md border p-1 shadow-lg",
className,
)}
{...props}
/>
@ -88,7 +88,7 @@ const MenubarContent = React.forwardRef<
>(
(
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
ref
ref,
) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
@ -97,13 +97,13 @@ const MenubarContent = React.forwardRef<
alignOffset={alignOffset}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-48 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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
"bg-popover text-popover-foreground data-[state=open]:animate-in 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-48 overflow-hidden rounded-md border p-1 shadow-md",
className,
)}
{...props}
/>
</MenubarPrimitive.Portal>
)
),
);
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
@ -116,9 +116,9 @@ const MenubarItem = React.forwardRef<
<MenubarPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -132,8 +132,8 @@ const MenubarCheckboxItem = React.forwardRef<
<MenubarPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50",
className,
)}
checked={checked}
{...props}
@ -155,8 +155,8 @@ const MenubarRadioItem = React.forwardRef<
<MenubarPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50",
className,
)}
{...props}
>
@ -181,7 +181,7 @@ const MenubarLabel = React.forwardRef<
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -194,7 +194,7 @@ const MenubarSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
className={cn("bg-muted -mx-1 my-1 h-px", className)}
{...props}
/>
));
@ -207,8 +207,8 @@ const MenubarShortcut = ({
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
"text-muted-foreground ml-auto text-xs tracking-widest",
className,
)}
{...props}
/>

View File

@ -13,7 +13,7 @@ const NavigationMenu = React.forwardRef<
ref={ref}
className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center",
className
className,
)}
{...props}
>
@ -31,7 +31,7 @@ const NavigationMenuList = React.forwardRef<
ref={ref}
className={cn(
"group flex flex-1 list-none items-center justify-center space-x-1",
className
className,
)}
{...props}
/>
@ -41,7 +41,7 @@ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
const NavigationMenuItem = NavigationMenuPrimitive.Item;
const navigationMenuTriggerStyle = cva(
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-hidden disabled:pointer-events-none disabled:opacity-50 data-active:bg-accent/50 data-[state=open]:bg-accent/50"
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-hidden disabled:pointer-events-none disabled:opacity-50 data-active:bg-accent/50 data-[state=open]:bg-accent/50",
);
const NavigationMenuTrigger = React.forwardRef<
@ -69,8 +69,8 @@ const NavigationMenuContent = React.forwardRef<
<NavigationMenuPrimitive.Content
ref={ref}
className={cn(
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
className
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full md:absolute md:w-auto",
className,
)}
{...props}
/>
@ -83,11 +83,11 @@ const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<div className={cn("absolute top-full left-0 flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-(--radix-navigation-menu-viewport-width)",
className
"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden rounded-md border shadow-sm md:w-(--radix-navigation-menu-viewport-width)",
className,
)}
ref={ref}
{...props}
@ -104,12 +104,12 @@ const NavigationMenuIndicator = React.forwardRef<
<NavigationMenuPrimitive.Indicator
ref={ref}
className={cn(
"top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
className
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-1 flex h-1.5 items-end justify-center overflow-hidden",
className,
)}
{...props}
>
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
</NavigationMenuPrimitive.Indicator>
));
NavigationMenuIndicator.displayName =

View File

@ -52,7 +52,7 @@ const PaginationLink = ({
variant: isActive ? "outline" : "text",
size,
}),
className
className,
)}
{...props}
/>

View File

@ -52,7 +52,7 @@ const PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps> =
{...props}
/>
);
}
},
);
PhoneInput.displayName = "PhoneInput";
@ -61,7 +61,7 @@ const InputComponent = React.forwardRef<
React.ComponentProps<"input">
>(({ className, ...props }, ref) => (
<Input
className={cn("rounded-e-lg rounded-s-none", className)}
className={cn("rounded-s-none rounded-e-lg", className)}
{...props}
ref={ref}
/>
@ -89,7 +89,7 @@ const CountrySelect = ({
<Button
type="button"
variant="outline"
className="flex gap-1 rounded-e-none rounded-s-lg border-r-0 px-3 focus:z-10"
className="flex gap-1 rounded-s-lg rounded-e-none border-r-0 px-3 focus:z-10"
disabled={disabled}
>
<FlagComponent
@ -99,7 +99,7 @@ const CountrySelect = ({
<ChevronsUpDown
className={cn(
"-mr-2 size-4 opacity-50",
disabled ? "hidden" : "opacity-100"
disabled ? "hidden" : "opacity-100",
)}
/>
</Button>
@ -120,7 +120,7 @@ const CountrySelect = ({
selectedCountry={selectedCountry}
onChange={onChange}
/>
) : null
) : null,
)}
</CommandGroup>
</ScrollArea>
@ -146,7 +146,7 @@ const CountrySelectOption = ({
<CommandItem className="gap-2" onSelect={() => onChange(country)}>
<FlagComponent country={country} countryName={countryName} />
<span className="flex-1 text-sm">{countryName}</span>
<span className="text-sm text-foreground/50">{`+${RPNInput.getCountryCallingCode(country)}`}</span>
<span className="text-foreground/50 text-sm">{`+${RPNInput.getCountryCallingCode(country)}`}</span>
<CheckIcon
className={`ml-auto size-4 ${country === selectedCountry ? "opacity-100" : "opacity-0"}`}
/>
@ -158,7 +158,7 @@ const FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {
const Flag = flags[country];
return (
<span className="flex h-4 w-6 overflow-hidden rounded-sm bg-foreground/20 [&_svg]:size-full">
<span className="bg-foreground/20 flex h-4 w-6 overflow-hidden rounded-sm [&_svg]:size-full">
{Flag && <Flag title={countryName} />}
</span>
);

View File

@ -21,8 +21,8 @@ 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-[0_0_10px_rgba(0,0,0,0.15)] outline-hidden 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
"bg-popover text-popover-foreground 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-72 rounded-md border p-4 shadow-[0_0_10px_rgba(0,0,0,0.15)] outline-hidden",
className,
)}
{...props}
/>

View File

@ -12,13 +12,13 @@ const Progress = React.forwardRef<
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-2 w-full overflow-hidden rounded-full bg-accent",
className
"bg-accent relative h-2 w-full overflow-hidden rounded-full",
className,
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-foreground transition-all"
className="bg-foreground h-full w-full flex-1 transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>

View File

@ -10,8 +10,8 @@ function Prose({ children, html, className }: ProseProps) {
return (
<article
className={cn(
"prose prose-h2:font-semibold max-w-none prose-h1:text-xl prose-a:text-blue-600 prose-p:text-justify dark:prose-invert mx-auto",
className
"prose prose-h2:font-semibold prose-h1:text-xl prose-a:text-blue-600 prose-p:text-justify dark:prose-invert mx-auto max-w-none",
className,
)}
>
{html ? <div dangerouslySetInnerHTML={{ __html: html }} /> : children}

View File

@ -28,13 +28,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-sm focus:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
"border-primary text-primary focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border shadow-sm focus:outline-hidden focus-visible:ring-1 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="fill-primary h-3.5 w-3.5" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);

View File

@ -11,7 +11,7 @@ const ResizablePanelGroup = ({
<ResizablePrimitive.PanelGroup
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
className,
)}
{...props}
/>
@ -28,8 +28,8 @@ const ResizableHandle = ({
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center bg-transparent after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
"focus-visible:ring-ring relative flex w-px items-center justify-center bg-transparent after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className,
)}
{...props}
/>

View File

@ -7,7 +7,7 @@ const ScrollArea = React.forwardRef<
>(({ className, children, ...props }, ref) => (
<div
ref={ref}
className={cn("overflow-auto scrollbar-thin", className)}
className={cn("scrollbar-thin overflow-auto", className)}
{...props}
>
{children}

View File

@ -25,7 +25,7 @@ const selectItemVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
const SelectTrigger = React.forwardRef<
@ -35,8 +35,8 @@ const SelectTrigger = React.forwardRef<
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex gap-1 h-7 cursor-pointer w-auto items-center justify-between whitespace-nowrap rounded-md bg-accent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
"bg-accent ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-7 w-auto cursor-pointer items-center justify-between gap-1 rounded-md px-3 py-2 text-sm whitespace-nowrap focus:ring-1 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className,
)}
{...props}
>
@ -56,7 +56,7 @@ const SelectScrollUpButton = React.forwardRef<
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
className,
)}
{...props}
>
@ -73,7 +73,7 @@ const SelectScrollDownButton = React.forwardRef<
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
className,
)}
{...props}
>
@ -91,10 +91,10 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover 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",
"bg-popover text-popover-foreground 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 relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border shadow-md",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className,
)}
position={position}
onCloseAutoFocus={(e) => {
@ -108,7 +108,7 @@ const SelectContent = React.forwardRef<
className={cn(
"p-1",
position === "popper" &&
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)"
"h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)",
)}
>
{children}
@ -158,7 +158,7 @@ const SelectSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-foreground/10", className)}
className={cn("bg-foreground/10 -mx-1 my-1 h-px", className)}
{...props}
/>
));

View File

@ -11,20 +11,20 @@ const Separator = React.forwardRef<
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
"shrink-0 bg-border",
"bg-border shrink-0",
orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
className
className,
)}
{...props}
/>
)
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;

View File

@ -21,8 +21,8 @@ const SheetOverlay = React.forwardRef<
>(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay
className={cn(
"fixed inset-0 z-200 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-200 bg-black/50",
className,
)}
{...props}
ref={ref}
@ -46,12 +46,13 @@ const sheetVariants = cva(
defaultVariants: {
side: "right",
},
}
},
);
interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> { }
extends
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>,
@ -68,7 +69,7 @@ const SheetContent = React.forwardRef<
}}
{...props}
>
<SheetPrimitive.Close className="absolute cursor-pointer right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 cursor-pointer rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<X className="size-5" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
@ -85,7 +86,7 @@ const SheetHeader = ({
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
className,
)}
{...props}
/>
@ -99,7 +100,7 @@ const SheetFooter = ({
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
className,
)}
{...props}
/>
@ -112,7 +113,7 @@ const SheetTitle = React.forwardRef<
>(({ className, ...props }, ref) => (
<SheetPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold text-foreground", className)}
className={cn("text-foreground text-lg font-semibold", className)}
{...props}
/>
));
@ -124,7 +125,7 @@ const SheetDescription = React.forwardRef<
>(({ className, ...props }, ref) => (
<SheetPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));

View File

@ -6,7 +6,7 @@ function Skeleton({
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-primary/10", className)}
className={cn("bg-primary/10 animate-pulse rounded-md", className)}
{...props}
/>
);

View File

@ -12,15 +12,15 @@ const Slider = React.forwardRef<
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className
"relative flex w-full touch-none items-center select-none",
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
<SliderPrimitive.Track className="bg-primary/20 relative h-1.5 w-full grow overflow-hidden rounded-full">
<SliderPrimitive.Range className="bg-primary absolute h-full" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow-sm transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
<SliderPrimitive.Thumb className="border-primary/50 bg-background focus-visible:ring-ring block h-4 w-4 rounded-full border shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
));
Slider.displayName = SliderPrimitive.Root.displayName;

View File

@ -18,15 +18,15 @@ const SplitButton = forwardRef<HTMLDivElement, SplitButtonProps>(
<div
ref={ref}
className={cn(
"inline-flex rounded-full h-7 border border-input bg-panel-accent overflow-hidden",
className
"border-input bg-panel-accent inline-flex h-7 overflow-hidden rounded-full border",
className,
)}
{...props}
>
{children}
</div>
);
}
},
);
SplitButton.displayName = "SplitButton";
@ -39,18 +39,18 @@ const SplitButtonSide = forwardRef<
ref={ref}
variant="text"
className={cn(
"h-full rounded-none bg-panel-accent !opacity-100 border-0 gap-0 font-normal transition-colors disabled:text-muted-foreground",
"bg-panel-accent disabled:text-muted-foreground h-full gap-0 rounded-none border-0 font-normal !opacity-100 transition-colors",
onClick
? "hover:bg-foreground/10 hover:opacity-100 cursor-pointer"
? "hover:bg-foreground/10 cursor-pointer hover:opacity-100"
: "cursor-default select-text",
paddingClass,
className
className,
)}
onClick={onClick}
{...props}
>
{typeof children === "string" ? (
<span className="font-normal cursor-text">{children}</span>
<span className="cursor-text font-normal">{children}</span>
) : (
children
)}
@ -62,14 +62,14 @@ SplitButtonSide.displayName = "SplitButtonSide";
const SplitButtonLeft = forwardRef<HTMLButtonElement, SplitButtonSideProps>(
({ ...props }, ref) => {
return <SplitButtonSide ref={ref} paddingClass="pl-3 pr-2" {...props} />;
}
},
);
SplitButtonLeft.displayName = "SplitButtonLeft";
const SplitButtonRight = forwardRef<HTMLButtonElement, SplitButtonSideProps>(
({ ...props }, ref) => {
return <SplitButtonSide ref={ref} paddingClass="pl-2 pr-3" {...props} />;
}
},
);
SplitButtonRight.displayName = "SplitButtonRight";
@ -79,11 +79,11 @@ const SplitButtonSeparator = forwardRef<HTMLDivElement, { className?: string }>(
<Separator
ref={ref}
orientation="vertical"
className={cn("h-full bg-foreground/15", className)}
className={cn("bg-foreground/15 h-full", className)}
{...props}
/>
);
}
},
);
SplitButtonSeparator.displayName = "SplitButtonSeparator";

View File

@ -11,15 +11,15 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:outline-hidden 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
"peer focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-input inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
ref={ref}
>
<SwitchPrimitives.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"
"bg-background pointer-events-none block h-4 w-4 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
)}
/>
</SwitchPrimitives.Root>

View File

@ -43,8 +43,8 @@ const TableFooter = React.forwardRef<
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium last:[&>tr]:border-b-0",
className
"bg-muted/50 border-t font-medium last:[&>tr]:border-b-0",
className,
)}
{...props}
/>
@ -58,8 +58,8 @@ const TableRow = React.forwardRef<
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
className,
)}
{...props}
/>
@ -73,8 +73,8 @@ const TableHead = React.forwardRef<
<th
ref={ref}
className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
"text-muted-foreground h-10 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className,
)}
{...props}
/>
@ -89,7 +89,7 @@ const TableCell = React.forwardRef<
ref={ref}
className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
className,
)}
{...props}
/>
@ -102,7 +102,7 @@ const TableCaption = React.forwardRef<
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
className={cn("text-muted-foreground mt-4 text-sm", className)}
{...props}
/>
));

View File

@ -14,8 +14,8 @@ const TabsList = React.forwardRef<
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-auto items-center justify-center gap-2 rounded-lg bg-transparent p-0 text-muted-foreground",
className
"text-muted-foreground inline-flex h-auto items-center justify-center gap-2 rounded-lg bg-transparent p-0",
className,
)}
{...props}
/>
@ -29,8 +29,8 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center cursor-pointer justify-center whitespace-nowrap rounded-lg px-3 py-1 text-sm font-medium ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-panel-accent data-[state=active]:text-foreground",
className
"ring-offset-background focus-visible:ring-ring data-[state=active]:bg-panel-accent data-[state=active]:text-foreground inline-flex cursor-pointer items-center justify-center rounded-lg px-3 py-1 text-sm font-medium whitespace-nowrap focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50",
className,
)}
{...props}
/>
@ -44,8 +44,8 @@ const TabsContent = React.forwardRef<
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
"ring-offset-background focus-visible:ring-ring mt-2 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden",
className,
)}
{...props}
/>

View File

@ -9,10 +9,10 @@ const Textarea = React.forwardRef<
return (
<textarea
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex min-h-[60px] w-full rounded-md border bg-accent/50 px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input bg-accent/50 flex min-h-[60px] w-full rounded-md border px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[2px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
className,
)}
ref={ref}
{...props}

View File

@ -16,8 +16,8 @@ const ToastViewport = React.forwardRef<
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-100 flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
className
"fixed top-0 z-100 flex max-h-screen w-full flex-col-reverse p-4 sm:top-auto sm:right-0 sm:bottom-0 sm:flex-col md:max-w-[420px]",
className,
)}
{...props}
/>
@ -37,13 +37,13 @@ const toastVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>
VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
@ -62,8 +62,8 @@ const ToastAction = React.forwardRef<
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus-visible:outline-hidden focus-visible:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 hover:group-[.destructive]:border-destructive/30 hover:group-[.destructive]:bg-destructive hover:group-[.destructive]:text-destructive-foreground group-[.destructive]:focus-visible::ring-destructive",
className
"hover:bg-secondary focus:ring-ring group-[.destructive]:border-muted/40 hover:group-[.destructive]:border-destructive/30 hover:group-[.destructive]:bg-destructive hover:group-[.destructive]:text-destructive-foreground group-[.destructive]:focus-visible::ring-destructive inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors focus-visible:ring-1 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50",
className,
)}
{...props}
/>
@ -77,8 +77,8 @@ const ToastClose = React.forwardRef<
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-hidden focus-visible::ring-1 group-hover:opacity-100 group-[.destructive]:text-muted-foreground hover:group-[.destructive]:text-red-50 focus-visible:group-[.destructive]:ring-red-400 focus-visible:group-[.destructive]:ring-offset-red-600",
className
"text-foreground/50 hover:text-foreground focus-visible::ring-1 group-[.destructive]:text-muted-foreground absolute top-1 right-1 rounded-md p-1 opacity-0 transition-opacity group-hover:opacity-100 hover:group-[.destructive]:text-red-50 focus:opacity-100 focus:outline-hidden focus-visible:group-[.destructive]:ring-red-400 focus-visible:group-[.destructive]:ring-offset-red-600",
className,
)}
toast-close=""
{...props}

View File

@ -17,7 +17,7 @@ const ToggleGroupContext = React.createContext<
const ToggleGroup = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
VariantProps<typeof toggleVariants>
VariantProps<typeof toggleVariants>
>(({ className, variant, size, children, ...props }, ref) => (
<ToggleGroupPrimitive.Root
ref={ref}
@ -35,7 +35,7 @@ ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
const ToggleGroupItem = React.forwardRef<
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
VariantProps<typeof toggleVariants>
VariantProps<typeof toggleVariants>
>(({ className, children, variant, size, ...props }, ref) => {
const context = React.useContext(ToggleGroupContext);
@ -47,7 +47,7 @@ const ToggleGroupItem = React.forwardRef<
variant: context.variant || variant,
size: context.size || size,
}),
className
className,
)}
{...props}
>

View File

@ -25,13 +25,13 @@ const toggleVariants = cva(
variant: "default",
size: "default",
},
}
},
);
const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
VariantProps<typeof toggleVariants>
VariantProps<typeof toggleVariants>
>(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root
ref={ref}

View File

@ -1,8 +1,8 @@
import { cva, type VariantProps } from 'class-variance-authority';
import { Tooltip as TooltipPrimitive } from 'radix-ui';
import * as React from 'react';
import { cva, type VariantProps } from "class-variance-authority";
import { Tooltip as TooltipPrimitive } from "radix-ui";
import * as React from "react";
import { cn } from '@/utils/ui';
import { cn } from "@/utils/ui";
const TooltipProvider = TooltipPrimitive.Provider;
@ -11,36 +11,37 @@ const Tooltip = TooltipPrimitive.Root;
const TooltipTrigger = TooltipPrimitive.Trigger;
const tooltipVariants = cva(
'z-50 overflow-visible rounded-sm text-sm 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',
"z-50 overflow-visible rounded-sm text-sm 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",
{
variants: {
variant: {
default: 'bg-popover text-popover-foreground border px-3 py-1.5',
default: "bg-popover text-popover-foreground border px-3 py-1.5",
destructive:
'bg-destructive/10 text-destructive dark:bg-destructive/20 border-destructive [border-width:0.5px]',
outline: 'border-border',
"bg-destructive/10 text-destructive dark:bg-destructive/20 border-destructive [border-width:0.5px]",
outline: "border-border",
important:
'bg-amber-100/90 text-amber-900 dark:bg-amber-900/20 dark:text-amber-300 border-amber-900 [border-width:0.5px]',
"bg-amber-100/90 text-amber-900 dark:bg-amber-900/20 dark:text-amber-300 border-amber-900 [border-width:0.5px]",
promotions:
'bg-red-100/90 text-red-900 dark:bg-red-900/20 dark:text-red-300 border-red-900 [border-width:0.5px]',
"bg-red-100/90 text-red-900 dark:bg-red-900/20 dark:text-red-300 border-red-900 [border-width:0.5px]",
personal:
'bg-green-100/90 text-green-900 dark:bg-green-900/20 dark:text-green-300 border-green-900 [border-width:0.5px]',
"bg-green-100/90 text-green-900 dark:bg-green-900/20 dark:text-green-300 border-green-900 [border-width:0.5px]",
updates:
'bg-purple-100/90 text-purple-900 dark:bg-purple-900/20 dark:text-purple-300 border-purple-900 [border-width:0.5px]',
"bg-purple-100/90 text-purple-900 dark:bg-purple-900/20 dark:text-purple-300 border-purple-900 [border-width:0.5px]",
forums:
'bg-blue-100/90 text-blue-900 dark:bg-blue-900/20 dark:text-blue-300 border-blue-900 [border-width:0.5px]',
sidebar: 'bg-white dark:bg-[#413F3E] p-2.5 flex flex-col gap-2',
"bg-blue-100/90 text-blue-900 dark:bg-blue-900/20 dark:text-blue-300 border-blue-900 [border-width:0.5px]",
sidebar: "bg-white dark:bg-[#413F3E] p-2.5 flex flex-col gap-2",
},
},
defaultVariants: {
variant: 'default',
variant: "default",
},
},
);
interface TooltipContentProps
extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,
VariantProps<typeof tooltipVariants> { }
extends
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,
VariantProps<typeof tooltipVariants> {}
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
@ -52,16 +53,19 @@ const TooltipContent = React.forwardRef<
className={cn(tooltipVariants({ variant }), className)}
{...props}
>
{variant === 'sidebar' && (
{variant === "sidebar" && (
<svg
width="6"
height="10"
viewBox="0 0 6 10"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute left-[-6px] top-1/2 -translate-y-1/2"
className="absolute top-1/2 left-[-6px] -translate-y-1/2"
>
<path d="M6 0L0 5L6 10V0Z" className="fill-white/80 dark:fill-[#413F3E]" />
<path
d="M6 0L0 5L6 10V0Z"
className="fill-white/80 dark:fill-[#413F3E]"
/>
</svg>
)}
{props.children}
@ -69,4 +73,4 @@ const TooltipContent = React.forwardRef<
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };

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