refactor: move constants to domain modules
This commit is contained in:
parent
34c67ef8e8
commit
6de6c7fd95
|
|
@ -3,7 +3,7 @@ import Link from "next/link";
|
||||||
import { GitHubContributeSection } from "@/components/gitHub-contribute-section";
|
import { GitHubContributeSection } from "@/components/gitHub-contribute-section";
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { EXTERNAL_TOOLS } from "@/constants/site-constants";
|
import { EXTERNAL_TOOLS } from "@/lib/site/external-tools";
|
||||||
import { BasePage } from "../base-page";
|
import { BasePage } from "../base-page";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { SITE_INFO, SITE_URL } from "@/constants/site-constants";
|
import { SITE_INFO, SITE_URL } from "@/lib/site/brand";
|
||||||
|
|
||||||
export const baseMetaData: Metadata = {
|
export const baseMetaData: Metadata = {
|
||||||
metadataBase: new URL(SITE_URL),
|
metadataBase: new URL(SITE_URL),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Hero } from "@/components/landing/hero";
|
||||||
import { Header } from "@/components/header";
|
import { Header } from "@/components/header";
|
||||||
import { Footer } from "@/components/footer";
|
import { Footer } from "@/components/footer";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { SITE_URL } from "@/constants/site-constants";
|
import { SITE_URL } from "@/lib/site/brand";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
alternates: {
|
alternates: {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "@/components/ui/accordion";
|
} from "@/components/ui/accordion";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { SOCIAL_LINKS } from "@/constants/site-constants";
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Privacy Policy - OpenCut",
|
title: "Privacy Policy - OpenCut",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { MetadataRoute } from "next";
|
import type { MetadataRoute } from "next";
|
||||||
import { SITE_URL } from "@/constants/site-constants";
|
import { SITE_URL } from "@/lib/site/brand";
|
||||||
|
|
||||||
export default function robots(): MetadataRoute.Robots {
|
export default function robots(): MetadataRoute.Robots {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Feed } from "feed";
|
import { Feed } from "feed";
|
||||||
import { getPosts } from "@/lib/blog/query";
|
import { getPosts } from "@/lib/blog/query";
|
||||||
import { SITE_INFO, SITE_URL } from "@/constants/site-constants";
|
import { SITE_INFO, SITE_URL } from "@/lib/site/brand";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { SITE_URL } from "@/constants/site-constants";
|
import { SITE_URL } from "@/lib/site/brand";
|
||||||
import { getPosts } from "@/lib/blog/query";
|
import { getPosts } from "@/lib/blog/query";
|
||||||
import type { MetadataRoute } from "next";
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { BasePage } from "@/app/base-page";
|
import { BasePage } from "@/app/base-page";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { SPONSORS, type Sponsor } from "@/constants/site-constants";
|
import { SPONSORS, type Sponsor } from "@/lib/site/sponsors";
|
||||||
import { HugeiconsIcon } from "@hugeicons/react";
|
import { HugeiconsIcon } from "@hugeicons/react";
|
||||||
import { LinkSquare02Icon } from "@hugeicons/core-free-icons";
|
import { LinkSquare02Icon } from "@hugeicons/core-free-icons";
|
||||||
import { cn } from "@/utils/ui";
|
import { cn } from "@/utils/ui";
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "@/components/ui/accordion";
|
} from "@/components/ui/accordion";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { SOCIAL_LINKS } from "@/constants/site-constants";
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Terms of Service - OpenCut",
|
title: "Terms of Service - OpenCut",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ import { useRouter } from "next/navigation";
|
||||||
import { FaDiscord } from "react-icons/fa6";
|
import { FaDiscord } from "react-icons/fa6";
|
||||||
import { ExportButton } from "./export-button";
|
import { ExportButton } from "./export-button";
|
||||||
import { ThemeToggle } from "../theme-toggle";
|
import { ThemeToggle } from "../theme-toggle";
|
||||||
import { DEFAULT_LOGO_URL, SOCIAL_LINKS } from "@/constants/site-constants";
|
import { DEFAULT_LOGO_URL } from "@/lib/site/brand";
|
||||||
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import { CommandIcon, Logout05Icon } from "@hugeicons/core-free-icons";
|
import { CommandIcon, Logout05Icon } from "@hugeicons/core-free-icons";
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import {
|
||||||
SectionTitle,
|
SectionTitle,
|
||||||
} from "@/components/section";
|
} from "@/components/section";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import { DEFAULT_EXPORT_OPTIONS } from "@/constants/export-constants";
|
import { DEFAULT_EXPORT_OPTIONS } from "@/lib/export/defaults";
|
||||||
|
|
||||||
function isExportFormat(value: string): value is ExportFormat {
|
function isExportFormat(value: string): value is ExportFormat {
|
||||||
return EXPORT_FORMAT_VALUES.some((formatValue) => formatValue === value);
|
return EXPORT_FORMAT_VALUES.some((formatValue) => formatValue === value);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import { ArrowRightIcon } from "lucide-react";
|
import { ArrowRightIcon } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import { SOCIAL_LINKS } from "@/constants/site-constants";
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
import { useLocalStorage } from "@/hooks/storage/use-local-storage";
|
import { useLocalStorage } from "@/hooks/storage/use-local-storage";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Dialog, DialogBody, DialogContent, DialogTitle } from "../ui/dialog";
|
import { Dialog, DialogBody, DialogContent, DialogTitle } from "../ui/dialog";
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ import { extractTimelineAudio } from "@/lib/media/mediabunny";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import {
|
import {
|
||||||
DEFAULT_TRANSCRIPTION_SAMPLE_RATE,
|
DEFAULT_TRANSCRIPTION_SAMPLE_RATE,
|
||||||
TRANSCRIPTION_LANGUAGES,
|
} from "@/lib/transcription/audio";
|
||||||
} from "@/constants/transcription-constants";
|
import { TRANSCRIPTION_LANGUAGES } from "@/lib/transcription/supported-languages";
|
||||||
import type {
|
import type {
|
||||||
CaptionChunk,
|
CaptionChunk,
|
||||||
TranscriptionLanguage,
|
TranscriptionLanguage,
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import {
|
||||||
import {
|
import {
|
||||||
BACKGROUND_BLUR_INTENSITY_PRESETS,
|
BACKGROUND_BLUR_INTENSITY_PRESETS,
|
||||||
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
||||||
DEFAULT_BACKGROUND_COLOR,
|
} from "@/lib/background/blur";
|
||||||
} from "@/lib/background/constants";
|
import { DEFAULT_BACKGROUND_COLOR } from "@/lib/background/color";
|
||||||
import { patternCraftGradients } from "@/data/colors/pattern-craft";
|
import { patternCraftGradients } from "@/data/colors/pattern-craft";
|
||||||
import { colors } from "@/data/colors/solid";
|
import { colors } from "@/data/colors/solid";
|
||||||
import { syntaxUIGradients } from "@/data/colors/syntax-ui";
|
import { syntaxUIGradients } from "@/data/colors/syntax-ui";
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { FPS_PRESETS } from "@/lib/fps/constants";
|
import { FPS_PRESETS } from "@/lib/fps/presets";
|
||||||
import { floatToFrameRate, frameRateToFloat } from "@/lib/fps/utils";
|
import { floatToFrameRate, frameRateToFloat } from "@/lib/fps/utils";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
buildGraphicElement,
|
buildGraphicElement,
|
||||||
buildStickerElement,
|
buildStickerElement,
|
||||||
} from "@/lib/timeline/element-utils";
|
} from "@/lib/timeline/element-utils";
|
||||||
import { STICKER_CATEGORIES } from "@/constants/sticker-constants";
|
import { STICKER_CATEGORIES } from "@/lib/stickers/categories";
|
||||||
import { getRegionLabel, resolveQueryToRegions } from "@/lib/stickers";
|
import { getRegionLabel, resolveQueryToRegions } from "@/lib/stickers";
|
||||||
import { parseShapeStickerId } from "@/lib/stickers/providers/shapes";
|
import { parseShapeStickerId } from "@/lib/stickers/providers/shapes";
|
||||||
import type { TimelineDragData } from "@/lib/timeline/drag";
|
import type { TimelineDragData } from "@/lib/timeline/drag";
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import {
|
||||||
screenToCanvas,
|
screenToCanvas,
|
||||||
} from "@/lib/preview/preview-coords";
|
} from "@/lib/preview/preview-coords";
|
||||||
import { clamp, isNearlyEqual } from "@/utils/math";
|
import { clamp, isNearlyEqual } from "@/utils/math";
|
||||||
import { PREVIEW_ZOOM } from "@/lib/preview/constants";
|
import { PREVIEW_ZOOM } from "@/lib/preview/zoom";
|
||||||
|
|
||||||
const MIDDLE_MOUSE_BUTTON = 1;
|
const MIDDLE_MOUSE_BUTTON = 1;
|
||||||
const IS_AT_FIT_EPSILON = 0.001;
|
const IS_AT_FIT_EPSILON = 0.001;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { useEditor } from "@/hooks/use-editor";
|
||||||
import type { TextElement } from "@/lib/timeline";
|
import type { TextElement } from "@/lib/timeline";
|
||||||
import {
|
import {
|
||||||
FONT_SIZE_SCALE_REFERENCE,
|
FONT_SIZE_SCALE_REFERENCE,
|
||||||
} from "@/constants/text-constants";
|
} from "@/lib/text/typography";
|
||||||
import { DEFAULTS } from "@/lib/timeline/defaults";
|
import { DEFAULTS } from "@/lib/timeline/defaults";
|
||||||
import {
|
import {
|
||||||
getElementLocalTime,
|
getElementLocalTime,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import {
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectSeparator,
|
SelectSeparator,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { PREVIEW_ZOOM_PRESETS } from "@/lib/preview/constants";
|
import { PREVIEW_ZOOM_PRESETS } from "@/lib/preview/zoom";
|
||||||
import { usePreviewViewport } from "./preview-viewport";
|
import { usePreviewViewport } from "./preview-viewport";
|
||||||
import { GridPopover } from "./guide-popover";
|
import { GridPopover } from "./guide-popover";
|
||||||
import { usePreviewStore } from "@/stores/preview-store";
|
import { usePreviewStore } from "@/stores/preview-store";
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,13 @@ import { clamp, formatNumberForDisplay } from "@/utils/math";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import {
|
import {
|
||||||
CORNER_RADIUS_MAX,
|
CORNER_RADIUS_MAX,
|
||||||
DEFAULT_TEXT_COLOR,
|
|
||||||
CORNER_RADIUS_MIN,
|
CORNER_RADIUS_MIN,
|
||||||
|
} from "@/lib/text/background";
|
||||||
|
import {
|
||||||
|
DEFAULT_TEXT_COLOR,
|
||||||
MAX_FONT_SIZE,
|
MAX_FONT_SIZE,
|
||||||
MIN_FONT_SIZE,
|
MIN_FONT_SIZE,
|
||||||
} from "@/lib/text/constants";
|
} from "@/lib/text/typography";
|
||||||
import { usePropertyDraft } from "../hooks/use-property-draft";
|
import { usePropertyDraft } from "../hooks/use-property-draft";
|
||||||
import { useKeyframedColorProperty } from "../hooks/use-keyframed-color-property";
|
import { useKeyframedColorProperty } from "../hooks/use-keyframed-color-property";
|
||||||
import { useKeyframedNumberProperty } from "../hooks/use-keyframed-number-property";
|
import { useKeyframedNumberProperty } from "../hooks/use-keyframed-number-property";
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
DEFAULT_TIMELINE_BOOKMARK_COLOR,
|
DEFAULT_TIMELINE_BOOKMARK_COLOR,
|
||||||
} from "./theme";
|
} from "./theme";
|
||||||
import { TIMELINE_BOOKMARK_ROW_HEIGHT_PX } from "./layout";
|
import { TIMELINE_BOOKMARK_ROW_HEIGHT_PX } from "./layout";
|
||||||
import { DEFAULT_FPS } from "@/lib/fps/constants";
|
import { DEFAULT_FPS } from "@/lib/fps/defaults";
|
||||||
import { snappedSeekTime } from "opencut-wasm";
|
import { snappedSeekTime } from "opencut-wasm";
|
||||||
import {
|
import {
|
||||||
ArrowTurnBackwardIcon,
|
ArrowTurnBackwardIcon,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
import { mediaTimeToSeconds } from "opencut-wasm";
|
import { mediaTimeToSeconds } from "opencut-wasm";
|
||||||
import { TICKS_PER_SECOND } from "@/lib/wasm";
|
import { TICKS_PER_SECOND } from "@/lib/wasm";
|
||||||
import { TIMELINE_RULER_HEIGHT_PX } from "./layout";
|
import { TIMELINE_RULER_HEIGHT_PX } from "./layout";
|
||||||
import { DEFAULT_FPS } from "@/lib/fps/constants";
|
import { DEFAULT_FPS } from "@/lib/fps/defaults";
|
||||||
import { useEditor } from "@/hooks/use-editor";
|
import { useEditor } from "@/hooks/use-editor";
|
||||||
import { getRulerConfig, shouldShowLabel } from "@/lib/timeline/ruler-utils";
|
import { getRulerConfig, shouldShowLabel } from "@/lib/timeline/ruler-utils";
|
||||||
import { useScrollPosition } from "@/hooks/timeline/use-scroll-position";
|
import { useScrollPosition } from "@/hooks/timeline/use-scroll-position";
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import Link from "next/link";
|
||||||
import { RiDiscordFill, RiTwitterXLine } from "react-icons/ri";
|
import { RiDiscordFill, RiTwitterXLine } from "react-icons/ri";
|
||||||
import { FaGithub } from "react-icons/fa6";
|
import { FaGithub } from "react-icons/fa6";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { DEFAULT_LOGO_URL, SOCIAL_LINKS } from "@/constants/site-constants";
|
import { DEFAULT_LOGO_URL } from "@/lib/site/brand";
|
||||||
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
import { capitalizeFirstLetter } from "@/utils/string";
|
import { capitalizeFirstLetter } from "@/utils/string";
|
||||||
|
|
||||||
type Category = "resources" | "company";
|
type Category = "resources" | "company";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Button } from "./ui/button";
|
import { Button } from "./ui/button";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { SOCIAL_LINKS } from "@/constants/site-constants";
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
import { GithubIcon, Link04Icon } from "@hugeicons/core-free-icons";
|
import { GithubIcon, Link04Icon } from "@hugeicons/core-free-icons";
|
||||||
import { HugeiconsIcon } from "@hugeicons/react";
|
import { HugeiconsIcon } from "@hugeicons/react";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ import {
|
||||||
} from "@hugeicons/core-free-icons";
|
} from "@hugeicons/core-free-icons";
|
||||||
import { HugeiconsIcon } from "@hugeicons/react";
|
import { HugeiconsIcon } from "@hugeicons/react";
|
||||||
import { cn } from "@/utils/ui";
|
import { cn } from "@/utils/ui";
|
||||||
import { DEFAULT_LOGO_URL, SOCIAL_LINKS } from "@/constants/site-constants";
|
import { DEFAULT_LOGO_URL, SITE_URL } from "@/lib/site/brand";
|
||||||
|
import { SOCIAL_LINKS } from "@/lib/site/social";
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { loadFullFont } from "@/lib/fonts/google-fonts";
|
import { loadFullFont } from "@/lib/fonts/google-fonts";
|
||||||
import { SYSTEM_FONTS } from "@/constants/font-constants";
|
import { SYSTEM_FONTS } from "@/lib/fonts/system-fonts";
|
||||||
import type { FontAtlas, FontAtlasEntry } from "@/lib/fonts/types";
|
import type { FontAtlas, FontAtlasEntry } from "@/lib/fonts/types";
|
||||||
import { useFontAtlas } from "@/hooks/use-font-atlas";
|
import { useFontAtlas } from "@/hooks/use-font-atlas";
|
||||||
import { cn } from "@/utils/ui";
|
import { cn } from "@/utils/ui";
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
export type TPlatformLayout =
|
|
||||||
| "tiktok"
|
|
||||||
| "instagram"
|
|
||||||
| "youtube"
|
|
||||||
| "snapchat";
|
|
||||||
|
|
||||||
export const PREVIEW_ZOOM_PRESETS = [25, 50, 75, 100, 150, 200];
|
|
||||||
|
|
||||||
export const PREVIEW_ZOOM = {
|
|
||||||
min: 0.25,
|
|
||||||
max: 16,
|
|
||||||
step: 1.25,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const PANEL_CONFIG = {
|
|
||||||
panels: {
|
|
||||||
tools: 25,
|
|
||||||
preview: 50,
|
|
||||||
properties: 25,
|
|
||||||
mainContent: 50,
|
|
||||||
timeline: 50,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import type { ExportOptions } from "@/lib/export";
|
|
||||||
|
|
||||||
export const DEFAULT_EXPORT_OPTIONS = {
|
|
||||||
format: "mp4",
|
|
||||||
quality: "high",
|
|
||||||
includeAudio: true,
|
|
||||||
} satisfies ExportOptions;
|
|
||||||
|
|
||||||
export const EXPORT_MIME_TYPES = {
|
|
||||||
webm: "video/webm",
|
|
||||||
mp4: "video/mp4",
|
|
||||||
} as const;
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import type { TCanvasSize } from "@/lib/project/types";
|
|
||||||
|
|
||||||
export const DEFAULT_CANVAS_PRESETS: TCanvasSize[] = [
|
|
||||||
{ width: 1920, height: 1080 },
|
|
||||||
{ width: 1080, height: 1920 },
|
|
||||||
{ width: 1080, height: 1080 },
|
|
||||||
{ width: 1440, height: 1080 },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const FPS_PRESETS = [
|
|
||||||
{ value: "24", label: "24 fps" },
|
|
||||||
{ value: "25", label: "25 fps" },
|
|
||||||
{ value: "30", label: "30 fps" },
|
|
||||||
{ value: "60", label: "60 fps" },
|
|
||||||
{ value: "120", label: "120 fps" },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const BLUR_INTENSITY_PRESETS: { label: string; value: number }[] = [
|
|
||||||
{ label: "Light", value: 50 },
|
|
||||||
{ label: "Medium", value: 250 },
|
|
||||||
{ label: "Heavy", value: 500 },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const DEFAULT_CANVAS_SIZE: TCanvasSize = { width: 1920, height: 1080 };
|
|
||||||
export const DEFAULT_FPS = 30;
|
|
||||||
export const DEFAULT_BLUR_INTENSITY = 50;
|
|
||||||
export const DEFAULT_COLOR = "#000000";
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
import { OcDataBuddyIcon, OcMarbleIcon } from "@/components/icons";
|
|
||||||
|
|
||||||
export const SITE_URL = "https://opencut.app";
|
|
||||||
|
|
||||||
export const SITE_INFO = {
|
|
||||||
title: "OpenCut",
|
|
||||||
description:
|
|
||||||
"A simple but powerful video editor that gets the job done. In your browser.",
|
|
||||||
url: SITE_URL,
|
|
||||||
openGraphImage: "/open-graph/default.jpg",
|
|
||||||
twitterImage: "/open-graph/default.jpg",
|
|
||||||
favicon: "/favicon.ico",
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExternalTool = {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
url: string;
|
|
||||||
icon: React.ElementType;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EXTERNAL_TOOLS: ExternalTool[] = [
|
|
||||||
{
|
|
||||||
name: "Marble",
|
|
||||||
description:
|
|
||||||
"Modern headless CMS for content management and the blog for OpenCut",
|
|
||||||
url: "https://marblecms.com?utm_source=opencut",
|
|
||||||
icon: OcMarbleIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Databuddy",
|
|
||||||
description: "GDPR compliant analytics and user insights for OpenCut",
|
|
||||||
url: "https://databuddy.cc?utm_source=opencut",
|
|
||||||
icon: OcDataBuddyIcon,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const DEFAULT_LOGO_URL = "/logos/opencut/svg/logo.svg";
|
|
||||||
|
|
||||||
export const SOCIAL_LINKS = {
|
|
||||||
x: "https://x.com/opencutapp",
|
|
||||||
github: "https://github.com/OpenCut-app/OpenCut",
|
|
||||||
discord: "https://discord.com/invite/Mu3acKZvCp",
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Sponsor = {
|
|
||||||
name: string;
|
|
||||||
url: string;
|
|
||||||
logo: string;
|
|
||||||
description: string;
|
|
||||||
invertOnDark?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SPONSORS: Sponsor[] = [
|
|
||||||
{
|
|
||||||
name: "Fal.ai",
|
|
||||||
url: "https://fal.ai?utm_source=opencut",
|
|
||||||
logo: "/logos/others/fal.svg",
|
|
||||||
description: "Generative image, video, and audio models all in one place.",
|
|
||||||
invertOnDark: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Vercel",
|
|
||||||
url: "https://vercel.com?utm_source=opencut",
|
|
||||||
logo: "/logos/others/vercel.svg",
|
|
||||||
description: "Platform where we deploy and host OpenCut.",
|
|
||||||
invertOnDark: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
export const MIN_FONT_SIZE = 5;
|
|
||||||
export const MAX_FONT_SIZE = 300;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* higher value: smaller font size
|
|
||||||
* lower value: larger font size
|
|
||||||
*/
|
|
||||||
export const FONT_SIZE_SCALE_REFERENCE = 90;
|
|
||||||
|
|
||||||
export const CORNER_RADIUS_MIN = 0;
|
|
||||||
export const CORNER_RADIUS_MAX = 100;
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
import type { TrackType } from "@/lib/timeline";
|
|
||||||
|
|
||||||
export const TRACK_CONFIG: Record<
|
|
||||||
TrackType,
|
|
||||||
{
|
|
||||||
height: number;
|
|
||||||
defaultName: string;
|
|
||||||
}
|
|
||||||
> = {
|
|
||||||
video: {
|
|
||||||
height: 65,
|
|
||||||
defaultName: "Video track",
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
height: 25,
|
|
||||||
defaultName: "Text track",
|
|
||||||
},
|
|
||||||
audio: {
|
|
||||||
height: 50,
|
|
||||||
defaultName: "Audio track",
|
|
||||||
},
|
|
||||||
graphic: {
|
|
||||||
height: 25,
|
|
||||||
defaultName: "Graphic track",
|
|
||||||
},
|
|
||||||
effect: {
|
|
||||||
height: 25,
|
|
||||||
defaultName: "Effect track",
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const ELEMENT_TYPE_CONFIG: Record<
|
|
||||||
TrackType,
|
|
||||||
{
|
|
||||||
background: string;
|
|
||||||
waveformColor?: string;
|
|
||||||
}
|
|
||||||
> = {
|
|
||||||
video: { background: "transparent" },
|
|
||||||
text: { background: "bg-[#5DBAA0]" },
|
|
||||||
audio: {
|
|
||||||
background: "bg-[#8F5DBA]",
|
|
||||||
waveformColor: "rgba(255, 255, 255, 0.5)",
|
|
||||||
},
|
|
||||||
graphic: { background: "bg-[#BA5D7A]" },
|
|
||||||
effect: { background: "bg-[#5d93ba]" },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const TRACK_GAP = 6;
|
|
||||||
export const TRACK_LABELS_WIDTH_PX = 112;
|
|
||||||
|
|
||||||
export const TIMELINE_RULER_HEIGHT = 22;
|
|
||||||
export const TIMELINE_BOOKMARK_ROW_HEIGHT = 16;
|
|
||||||
|
|
||||||
export const DEFAULT_BOOKMARK_COLOR = "#009dff";
|
|
||||||
export const DRAG_THRESHOLD_PX = 5;
|
|
||||||
export const TIMELINE_SCROLLBAR_SIZE_PX = 12;
|
|
||||||
export const TIMELINE_LAYERS = {
|
|
||||||
trackContent: 10,
|
|
||||||
dragLine: 20,
|
|
||||||
playhead: 30,
|
|
||||||
snapIndicator: 40,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const TIMELINE_CONSTANTS = {
|
|
||||||
PIXELS_PER_SECOND: 50,
|
|
||||||
DEFAULT_ELEMENT_DURATION: 5,
|
|
||||||
PADDING_TOP_PX: 2,
|
|
||||||
HORIZONTAL_WHEEL_STEP_PX: 40,
|
|
||||||
ZOOM_MIN: 0.1,
|
|
||||||
ZOOM_MAX: 100,
|
|
||||||
ZOOM_BUTTON_FACTOR: 1.7,
|
|
||||||
ZOOM_ANCHOR_PLAYHEAD_THRESHOLD: 0.15,
|
|
||||||
TRACK_SELECTED_BG: "bg-accent/50",
|
|
||||||
} as const;
|
|
||||||
|
|
@ -12,9 +12,9 @@ import { storageService } from "@/services/storage/service";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { generateUUID } from "@/utils/id";
|
import { generateUUID } from "@/utils/id";
|
||||||
import { UpdateProjectSettingsCommand } from "@/lib/commands/project";
|
import { UpdateProjectSettingsCommand } from "@/lib/commands/project";
|
||||||
import { DEFAULT_BACKGROUND_COLOR } from "@/lib/background/constants";
|
import { DEFAULT_BACKGROUND_COLOR } from "@/lib/background/color";
|
||||||
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/constants";
|
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/sizes";
|
||||||
import { DEFAULT_FPS } from "@/lib/fps/constants";
|
import { DEFAULT_FPS } from "@/lib/fps/defaults";
|
||||||
import { buildDefaultScene, getProjectDurationFromScenes } from "@/lib/scenes";
|
import { buildDefaultScene, getProjectDurationFromScenes } from "@/lib/scenes";
|
||||||
import { buildScene } from "@/services/renderer/scene-builder";
|
import { buildScene } from "@/services/renderer/scene-builder";
|
||||||
import { CanvasRenderer } from "@/services/renderer/canvas-renderer";
|
import { CanvasRenderer } from "@/services/renderer/canvas-renderer";
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
clearFontAtlasCache,
|
clearFontAtlasCache,
|
||||||
} from "@/lib/fonts/google-fonts";
|
} from "@/lib/fonts/google-fonts";
|
||||||
import type { FontAtlas } from "@/lib/fonts/types";
|
import type { FontAtlas } from "@/lib/fonts/types";
|
||||||
import { SYSTEM_FONTS } from "@/constants/font-constants";
|
import { SYSTEM_FONTS } from "@/lib/fonts/system-fonts";
|
||||||
|
|
||||||
type Status = "idle" | "loading" | "error";
|
type Status = "idle" | "loading" | "error";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import type {
|
||||||
} from "@/lib/animation/types";
|
} from "@/lib/animation/types";
|
||||||
import { parseColorToLinearRgba } from "./binding-values";
|
import { parseColorToLinearRgba } from "./binding-values";
|
||||||
import type { TimelineElement } from "@/lib/timeline";
|
import type { TimelineElement } from "@/lib/timeline";
|
||||||
import { MIN_TRANSFORM_SCALE } from "@/constants/animation-constants";
|
import { MIN_TRANSFORM_SCALE } from "@/lib/animation/transform";
|
||||||
import {
|
import {
|
||||||
CORNER_RADIUS_MAX,
|
CORNER_RADIUS_MAX,
|
||||||
CORNER_RADIUS_MIN,
|
CORNER_RADIUS_MIN,
|
||||||
} from "@/constants/text-constants";
|
} from "@/lib/text/background";
|
||||||
import {
|
import {
|
||||||
canElementHaveAudio,
|
canElementHaveAudio,
|
||||||
isVisualElement,
|
isVisualElement,
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,3 @@ export const BACKGROUND_BLUR_INTENSITY_PRESETS: Array<{
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const DEFAULT_BACKGROUND_BLUR_INTENSITY = 10;
|
export const DEFAULT_BACKGROUND_BLUR_INTENSITY = 10;
|
||||||
export const DEFAULT_BACKGROUND_COLOR = "#000000";
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export const DEFAULT_BACKGROUND_COLOR = "#000000";
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type { ExportOptions } from "./index";
|
||||||
|
|
||||||
|
export const DEFAULT_EXPORT_OPTIONS = {
|
||||||
|
format: "mp4",
|
||||||
|
quality: "high",
|
||||||
|
includeAudio: true,
|
||||||
|
} satisfies ExportOptions;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { FrameRate } from "opencut-wasm";
|
import type { FrameRate } from "opencut-wasm";
|
||||||
import { EXPORT_MIME_TYPES } from "@/constants/export-constants";
|
import { EXPORT_MIME_TYPES } from "./mime-types";
|
||||||
|
|
||||||
export const EXPORT_QUALITY_VALUES = [
|
export const EXPORT_QUALITY_VALUES = [
|
||||||
"low",
|
"low",
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const EXPORT_MIME_TYPES = {
|
||||||
|
webm: "video/webm",
|
||||||
|
mp4: "video/mp4",
|
||||||
|
} as const;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { FontAtlas } from "@/lib/fonts/types";
|
import type { FontAtlas } from "@/lib/fonts/types";
|
||||||
import { SYSTEM_FONTS } from "@/constants/font-constants";
|
import { SYSTEM_FONTS } from "@/lib/fonts/system-fonts";
|
||||||
|
|
||||||
const GOOGLE_FONTS_CSS = "https://fonts.googleapis.com/css2";
|
const GOOGLE_FONTS_CSS = "https://fonts.googleapis.com/css2";
|
||||||
const FONT_ATLAS_PATH = "/fonts/font-atlas.json";
|
const FONT_ATLAS_PATH = "/fonts/font-atlas.json";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export const SYSTEM_FONTS = new Set([
|
export const SYSTEM_FONTS = new Set([
|
||||||
"Arial",
|
"Arial",
|
||||||
"Helvetica",
|
"Helvetica",
|
||||||
"Times New Roman",
|
"Times New Roman",
|
||||||
"Courier New",
|
"Courier New",
|
||||||
"Verdana",
|
"Verdana",
|
||||||
"Georgia",
|
"Georgia",
|
||||||
"monospace",
|
"monospace",
|
||||||
"sans-serif",
|
"sans-serif",
|
||||||
"serif",
|
"serif",
|
||||||
]);
|
]);
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { FrameRate } from "opencut-wasm";
|
||||||
|
|
||||||
|
export const DEFAULT_FPS: FrameRate = { numerator: 30, denominator: 1 };
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import type { FrameRate } from "opencut-wasm";
|
|
||||||
|
|
||||||
export const FPS_PRESETS = [
|
export const FPS_PRESETS = [
|
||||||
{ value: "24", label: "24 fps" },
|
{ value: "24", label: "24 fps" },
|
||||||
{ value: "25", label: "25 fps" },
|
{ value: "25", label: "25 fps" },
|
||||||
|
|
@ -7,5 +5,3 @@ export const FPS_PRESETS = [
|
||||||
{ value: "60", label: "60 fps" },
|
{ value: "60", label: "60 fps" },
|
||||||
{ value: "120", label: "120 fps" },
|
{ value: "120", label: "120 fps" },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const DEFAULT_FPS: FrameRate = { numerator: 30, denominator: 1 };
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
GRID_MIN,
|
GRID_MIN,
|
||||||
GRID_MAX,
|
GRID_MAX,
|
||||||
DEFAULT_GRID_CONFIG,
|
DEFAULT_GRID_CONFIG,
|
||||||
} from "@/constants/guide-constants";
|
} from "@/lib/guides/grid";
|
||||||
import { usePreviewStore } from "@/stores/preview-store";
|
import { usePreviewStore } from "@/stores/preview-store";
|
||||||
import { clampRound } from "@/utils/math";
|
import { clampRound } from "@/utils/math";
|
||||||
import { cn } from "@/utils/ui";
|
import { cn } from "@/utils/ui";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const GRID_MIN = 1;
|
export const GRID_MIN = 1;
|
||||||
export const GRID_MAX = 24;
|
export const GRID_MAX = 24;
|
||||||
|
|
||||||
export const DEFAULT_GRID_CONFIG = { rows: 3, cols: 3 } as const;
|
export const DEFAULT_GRID_CONFIG = { rows: 3, cols: 3 } as const;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
DEFAULT_SHAPE_MASK_SHORT_SIDE_RATIO,
|
DEFAULT_SHAPE_MASK_SHORT_SIDE_RATIO,
|
||||||
MIN_MASK_DIMENSION,
|
MIN_MASK_DIMENSION,
|
||||||
} from "@/constants/mask-constants";
|
} from "@/lib/masks/dimensions";
|
||||||
import { computeFeatherUpdate } from "../param-update";
|
import { computeFeatherUpdate } from "../param-update";
|
||||||
import type {
|
import type {
|
||||||
BaseMaskParams,
|
BaseMaskParams,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,2 @@
|
||||||
export const MAX_FEATHER = 1000;
|
export const DEFAULT_SHAPE_MASK_SHORT_SIDE_RATIO = 0.6;
|
||||||
export const FEATHER_HANDLE_SCALE = 0.11;
|
export const MIN_MASK_DIMENSION = 0.01;
|
||||||
export const DEFAULT_SHAPE_MASK_SHORT_SIDE_RATIO = 0.6;
|
|
||||||
export const MIN_MASK_DIMENSION = 0.01;
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const MAX_FEATHER = 1000;
|
||||||
|
export const FEATHER_HANDLE_SCALE = 0.11;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
||||||
import type { SnapLine } from "@/lib/preview/preview-snap";
|
import type { SnapLine } from "@/lib/preview/preview-snap";
|
||||||
import { MIN_MASK_DIMENSION } from "@/constants/mask-constants";
|
import { MIN_MASK_DIMENSION } from "@/lib/masks/dimensions";
|
||||||
import type { ParamValues } from "@/lib/params";
|
import type { ParamValues } from "@/lib/params";
|
||||||
import type { RectangleMaskParams } from "@/lib/masks/types";
|
import type { RectangleMaskParams } from "@/lib/masks/types";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { FEATHER_HANDLE_SCALE } from "@/constants/mask-constants";
|
import { FEATHER_HANDLE_SCALE } from "@/lib/masks/feather";
|
||||||
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
||||||
import type {
|
import type {
|
||||||
MaskFeatures,
|
MaskFeatures,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { FEATHER_HANDLE_SCALE, MAX_FEATHER } from "@/constants/mask-constants";
|
import { FEATHER_HANDLE_SCALE, MAX_FEATHER } from "@/lib/masks/feather";
|
||||||
import { masksRegistry } from "@/lib/masks";
|
import { masksRegistry } from "@/lib/masks";
|
||||||
import type { ParamValues } from "@/lib/params";
|
import type { ParamValues } from "@/lib/params";
|
||||||
import type {
|
import type {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { MAX_FEATHER } from "@/constants/mask-constants";
|
import { MAX_FEATHER } from "@/lib/masks/feather";
|
||||||
import type { ParamDefinition } from "@/lib/params";
|
import type { ParamDefinition } from "@/lib/params";
|
||||||
import type { BaseMaskParams, MaskDefinition, MaskType } from "@/lib/masks/types";
|
import type { BaseMaskParams, MaskDefinition, MaskType } from "@/lib/masks/types";
|
||||||
import type { HugeiconsIconProps } from "@hugeicons/react";
|
import type { HugeiconsIconProps } from "@hugeicons/react";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
import type { ElementBounds } from "@/lib/preview/element-bounds";
|
||||||
import { MIN_MASK_DIMENSION } from "@/constants/mask-constants";
|
import { MIN_MASK_DIMENSION } from "@/lib/masks/dimensions";
|
||||||
import {
|
import {
|
||||||
snapPosition,
|
snapPosition,
|
||||||
snapRotation,
|
snapRotation,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import { canTrackHaveAudio } from "@/lib/timeline";
|
||||||
import { mediaSupportsAudio } from "@/lib/media/media-utils";
|
import { mediaSupportsAudio } from "@/lib/media/media-utils";
|
||||||
import { getSourceTimeAtClipTime, renderRetimedBuffer } from "@/lib/retime";
|
import { getSourceTimeAtClipTime, renderRetimedBuffer } from "@/lib/retime";
|
||||||
import { Input, ALL_FORMATS, BlobSource, AudioBufferSink } from "mediabunny";
|
import { Input, ALL_FORMATS, BlobSource, AudioBufferSink } from "mediabunny";
|
||||||
|
|
||||||
import { TICKS_PER_SECOND } from "@/lib/wasm";
|
import { TICKS_PER_SECOND } from "@/lib/wasm";
|
||||||
|
|
||||||
const MAX_AUDIO_CHANNELS = 2;
|
const MAX_AUDIO_CHANNELS = 2;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { SceneTracks, TimelineElement } from "@/lib/timeline";
|
import type { SceneTracks, TimelineElement } from "@/lib/timeline";
|
||||||
import type { MediaAsset } from "@/lib/media/types";
|
import type { MediaAsset } from "@/lib/media/types";
|
||||||
import { STICKER_INTRINSIC_SIZE_FALLBACK } from "@/constants/sticker-constants";
|
import { STICKER_INTRINSIC_SIZE_FALLBACK } from "@/lib/stickers/intrinsic-size";
|
||||||
import { DEFAULT_GRAPHIC_SOURCE_SIZE } from "@/lib/graphics";
|
import { DEFAULT_GRAPHIC_SOURCE_SIZE } from "@/lib/graphics";
|
||||||
import { measureTextElement } from "@/lib/text/measure-element";
|
import { measureTextElement } from "@/lib/text/measure-element";
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
export const SELECTABLE_ITEM_ATTRIBUTE = "data-selectable-item";
|
export const SELECTABLE_ITEM_ATTRIBUTE = "data-selectable-item";
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { forwardRef, useCallback } from "react";
|
import { forwardRef, useCallback } from "react";
|
||||||
import { useSelectionContext } from "@/lib/selection/context";
|
import { useSelectionContext } from "@/lib/selection/context";
|
||||||
import { SELECTABLE_ITEM_ATTRIBUTE } from "@/lib/selection/constants";
|
import { SELECTABLE_ITEM_ATTRIBUTE } from "@/lib/selection/attributes";
|
||||||
import type { SelectableItemProps } from "@/lib/selection/types";
|
import type { SelectableItemProps } from "@/lib/selection/types";
|
||||||
import { cn } from "@/utils/ui";
|
import { cn } from "@/utils/ui";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { SelectionBox } from "@/lib/selection/selection-box";
|
import { SelectionBox } from "@/lib/selection/selection-box";
|
||||||
import { SelectionContext } from "@/lib/selection/context";
|
import { SelectionContext } from "@/lib/selection/context";
|
||||||
import { SELECTABLE_ITEM_ATTRIBUTE } from "@/lib/selection/constants";
|
import { SELECTABLE_ITEM_ATTRIBUTE } from "@/lib/selection/attributes";
|
||||||
import { resolveElementIntersections } from "@/lib/selection/hit-testing";
|
import { resolveElementIntersections } from "@/lib/selection/hit-testing";
|
||||||
import {
|
import {
|
||||||
applyBoxSelection,
|
applyBoxSelection,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export const SITE_URL = "https://opencut.app";
|
||||||
|
|
||||||
|
export const SITE_INFO = {
|
||||||
|
title: "OpenCut",
|
||||||
|
description:
|
||||||
|
"A simple but powerful video editor that gets the job done. In your browser.",
|
||||||
|
url: SITE_URL,
|
||||||
|
openGraphImage: "/open-graph/default.jpg",
|
||||||
|
twitterImage: "/open-graph/default.jpg",
|
||||||
|
favicon: "/favicon.ico",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_LOGO_URL = "/logos/opencut/svg/logo.svg";
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { OcDataBuddyIcon, OcMarbleIcon } from "@/components/icons";
|
||||||
|
|
||||||
|
export type ExternalTool = {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
url: string;
|
||||||
|
icon: React.ElementType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EXTERNAL_TOOLS: ExternalTool[] = [
|
||||||
|
{
|
||||||
|
name: "Marble",
|
||||||
|
description:
|
||||||
|
"Modern headless CMS for content management and the blog for OpenCut",
|
||||||
|
url: "https://marblecms.com?utm_source=opencut",
|
||||||
|
icon: OcMarbleIcon,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Databuddy",
|
||||||
|
description: "GDPR compliant analytics and user insights for OpenCut",
|
||||||
|
url: "https://databuddy.cc?utm_source=opencut",
|
||||||
|
icon: OcDataBuddyIcon,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const SOCIAL_LINKS = {
|
||||||
|
x: "https://x.com/opencutapp",
|
||||||
|
github: "https://github.com/OpenCut-app/OpenCut",
|
||||||
|
discord: "https://discord.com/invite/Mu3acKZvCp",
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
export type Sponsor = {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
logo: string;
|
||||||
|
description: string;
|
||||||
|
invertOnDark?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SPONSORS: Sponsor[] = [
|
||||||
|
{
|
||||||
|
name: "Fal.ai",
|
||||||
|
url: "https://fal.ai?utm_source=opencut",
|
||||||
|
logo: "/logos/others/fal.svg",
|
||||||
|
description: "Generative image, video, and audio models all in one place.",
|
||||||
|
invertOnDark: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Vercel",
|
||||||
|
url: "https://vercel.com?utm_source=opencut",
|
||||||
|
logo: "/logos/others/vercel.svg",
|
||||||
|
description: "Platform where we deploy and host OpenCut.",
|
||||||
|
invertOnDark: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
export const STICKER_INTRINSIC_SIZE_FALLBACK = 200;
|
|
||||||
|
|
||||||
export const STICKER_CATEGORIES = {
|
export const STICKER_CATEGORIES = {
|
||||||
all: "All",
|
all: "All",
|
||||||
// v0.4.0
|
// v0.4.0
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
STICKER_CATEGORIES,
|
STICKER_CATEGORIES,
|
||||||
STICKER_INTRINSIC_SIZE_FALLBACK,
|
} from "@/lib/stickers/categories";
|
||||||
} from "@/constants/sticker-constants";
|
import { STICKER_INTRINSIC_SIZE_FALLBACK } from "@/lib/stickers/intrinsic-size";
|
||||||
import type { StickerCategory } from "@/lib/stickers/types";
|
import type { StickerCategory } from "@/lib/stickers/types";
|
||||||
import { stickersRegistry } from "./registry";
|
import { stickersRegistry } from "./registry";
|
||||||
import { resolveStickerId } from "./resolver";
|
import { resolveStickerId } from "./resolver";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export const STICKER_INTRINSIC_SIZE_FALLBACK = 200;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { STICKER_CATEGORIES } from "@/constants/sticker-constants";
|
import type { STICKER_CATEGORIES } from "@/lib/stickers/categories";
|
||||||
|
|
||||||
export type StickerCategory = keyof typeof STICKER_CATEGORIES;
|
export type StickerCategory = keyof typeof STICKER_CATEGORIES;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { FONT_SIZE_SCALE_REFERENCE } from "@/constants/text-constants";
|
import { FONT_SIZE_SCALE_REFERENCE } from "@/lib/text/typography";
|
||||||
import {
|
import {
|
||||||
getTextVisualRect,
|
getTextVisualRect,
|
||||||
measureTextBlock,
|
measureTextBlock,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const CORNER_RADIUS_MIN = 0;
|
||||||
|
export const CORNER_RADIUS_MAX = 100;
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import {
|
import { CORNER_RADIUS_MIN } from "@/lib/text/background";
|
||||||
CORNER_RADIUS_MIN,
|
import { FONT_SIZE_SCALE_REFERENCE } from "@/lib/text/typography";
|
||||||
FONT_SIZE_SCALE_REFERENCE,
|
|
||||||
} from "@/constants/text-constants";
|
|
||||||
import { resolveNumberAtTime } from "@/lib/animation";
|
import { resolveNumberAtTime } from "@/lib/animation";
|
||||||
import { DEFAULTS } from "@/lib/timeline/defaults";
|
import { DEFAULTS } from "@/lib/timeline/defaults";
|
||||||
import type { TextBackground, TextElement } from "@/lib/timeline";
|
import type { TextBackground, TextElement } from "@/lib/timeline";
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,3 @@ export const DEFAULT_TEXT_COLOR = "#000000";
|
||||||
* lower value: larger font size
|
* lower value: larger font size
|
||||||
*/
|
*/
|
||||||
export const FONT_SIZE_SCALE_REFERENCE = 90;
|
export const FONT_SIZE_SCALE_REFERENCE = 90;
|
||||||
|
|
||||||
export const CORNER_RADIUS_MIN = 0;
|
|
||||||
export const CORNER_RADIUS_MAX = 100;
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
import { TICKS_PER_SECOND } from "@/lib/wasm";
|
import { TICKS_PER_SECOND } from "@/lib/wasm/ticks";
|
||||||
|
|
||||||
export const DEFAULT_NEW_ELEMENT_DURATION = 5 * TICKS_PER_SECOND;
|
export const DEFAULT_NEW_ELEMENT_DURATION = 5 * TICKS_PER_SECOND;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const DEFAULT_TRANSCRIPTION_SAMPLE_RATE = 16000;
|
||||||
|
|
||||||
|
export const DEFAULT_CHUNK_LENGTH_SECONDS = 30;
|
||||||
|
export const DEFAULT_STRIDE_SECONDS = 5;
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const DEFAULT_WORDS_PER_CAPTION = 3;
|
||||||
|
export const MIN_CAPTION_DURATION_SECONDS = 0.8;
|
||||||
|
|
@ -2,7 +2,7 @@ import type { TranscriptionSegment, CaptionChunk } from "@/lib/transcription/typ
|
||||||
import {
|
import {
|
||||||
DEFAULT_WORDS_PER_CAPTION,
|
DEFAULT_WORDS_PER_CAPTION,
|
||||||
MIN_CAPTION_DURATION_SECONDS,
|
MIN_CAPTION_DURATION_SECONDS,
|
||||||
} from "@/constants/transcription-constants";
|
} from "@/lib/transcription/caption-defaults";
|
||||||
|
|
||||||
export function buildCaptionChunks({
|
export function buildCaptionChunks({
|
||||||
segments,
|
segments,
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,34 @@
|
||||||
import { LANGUAGES } from "@/constants/language-constants";
|
import type {
|
||||||
import type {
|
TranscriptionModel,
|
||||||
TranscriptionModel,
|
TranscriptionModelId,
|
||||||
TranscriptionModelId,
|
} from "./types";
|
||||||
} from "@/lib/transcription/types";
|
|
||||||
import type { LanguageCode } from "@/constants/language-constants";
|
export const TRANSCRIPTION_MODELS: TranscriptionModel[] = [
|
||||||
|
{
|
||||||
const SUPPORTED_TRANSCRIPTION_LANGS: ReadonlyArray<LanguageCode> = [
|
id: "whisper-tiny",
|
||||||
"en",
|
name: "Tiny",
|
||||||
"es",
|
huggingFaceId: "onnx-community/whisper-tiny",
|
||||||
"it",
|
description: "Fastest, lower accuracy",
|
||||||
"fr",
|
},
|
||||||
"de",
|
{
|
||||||
"pt",
|
id: "whisper-small",
|
||||||
"ru",
|
name: "Small",
|
||||||
"ja",
|
huggingFaceId: "onnx-community/whisper-small",
|
||||||
"zh",
|
description: "Good balance of speed and accuracy",
|
||||||
];
|
},
|
||||||
|
{
|
||||||
export const TRANSCRIPTION_LANGUAGES = LANGUAGES.filter((language) =>
|
id: "whisper-medium",
|
||||||
SUPPORTED_TRANSCRIPTION_LANGS.includes(language.code),
|
name: "Medium",
|
||||||
);
|
huggingFaceId: "onnx-community/whisper-medium",
|
||||||
|
description: "Higher accuracy, slower",
|
||||||
export const TRANSCRIPTION_MODELS: TranscriptionModel[] = [
|
},
|
||||||
{
|
{
|
||||||
id: "whisper-tiny",
|
id: "whisper-large-v3-turbo",
|
||||||
name: "Tiny",
|
name: "Large v3 Turbo",
|
||||||
huggingFaceId: "onnx-community/whisper-tiny",
|
huggingFaceId: "onnx-community/whisper-large-v3-turbo",
|
||||||
description: "Fastest, lower accuracy",
|
description: "Best accuracy, requires WebGPU for good performance",
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
id: "whisper-small",
|
|
||||||
name: "Small",
|
export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId =
|
||||||
huggingFaceId: "onnx-community/whisper-small",
|
"whisper-small";
|
||||||
description: "Good balance of speed and accuracy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "whisper-medium",
|
|
||||||
name: "Medium",
|
|
||||||
huggingFaceId: "onnx-community/whisper-medium",
|
|
||||||
description: "Higher accuracy, slower",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "whisper-large-v3-turbo",
|
|
||||||
name: "Large v3 Turbo",
|
|
||||||
huggingFaceId: "onnx-community/whisper-large-v3-turbo",
|
|
||||||
description: "Best accuracy, requires WebGPU for good performance",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const DEFAULT_TRANSCRIPTION_MODEL: TranscriptionModelId =
|
|
||||||
"whisper-small";
|
|
||||||
|
|
||||||
export const DEFAULT_TRANSCRIPTION_SAMPLE_RATE = 16000;
|
|
||||||
|
|
||||||
export const DEFAULT_CHUNK_LENGTH_SECONDS = 30;
|
|
||||||
export const DEFAULT_STRIDE_SECONDS = 5;
|
|
||||||
|
|
||||||
export const DEFAULT_WORDS_PER_CAPTION = 3;
|
|
||||||
export const MIN_CAPTION_DURATION_SECONDS = 0.8;
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { LANGUAGES as TRANSCRIPTION_LANGUAGES } from "./languages";
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { LanguageCode } from "@/constants/language-constants";
|
import type { LanguageCode } from "./languages";
|
||||||
|
|
||||||
export type TranscriptionLanguage = LanguageCode | "auto";
|
export type TranscriptionLanguage = LanguageCode | "auto";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
export * from "./constants";
|
export * from "./ticks";
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import type { Transform } from "@/lib/rendering";
|
||||||
import {
|
import {
|
||||||
CORNER_RADIUS_MAX,
|
CORNER_RADIUS_MAX,
|
||||||
CORNER_RADIUS_MIN,
|
CORNER_RADIUS_MIN,
|
||||||
} from "@/constants/text-constants";
|
} from "@/lib/text/background";
|
||||||
import {
|
import {
|
||||||
drawTextDecoration,
|
drawTextDecoration,
|
||||||
getTextBackgroundRect,
|
getTextBackgroundRect,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { BlurBackgroundNode } from "./nodes/blur-background-node";
|
||||||
import { EffectLayerNode } from "./nodes/effect-layer-node";
|
import { EffectLayerNode } from "./nodes/effect-layer-node";
|
||||||
import type { AnyBaseNode } from "./nodes/base-node";
|
import type { AnyBaseNode } from "./nodes/base-node";
|
||||||
import type { TBackground, TCanvasSize } from "@/lib/project/types";
|
import type { TBackground, TCanvasSize } from "@/lib/project/types";
|
||||||
import { DEFAULT_BACKGROUND_BLUR_INTENSITY } from "@/lib/background/constants";
|
import { DEFAULT_BACKGROUND_BLUR_INTENSITY } from "@/lib/background/blur";
|
||||||
|
|
||||||
const PREVIEW_MAX_IMAGE_SIZE = 2048;
|
const PREVIEW_MAX_IMAGE_SIZE = 2048;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import {
|
import {
|
||||||
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
||||||
DEFAULT_BACKGROUND_COLOR,
|
} from "@/lib/background/blur";
|
||||||
} from "@/lib/background/constants";
|
import { DEFAULT_BACKGROUND_COLOR } from "@/lib/background/color";
|
||||||
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/constants";
|
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/sizes";
|
||||||
const DEFAULT_FPS = 30;
|
const DEFAULT_FPS = 30;
|
||||||
import type { MediaAssetData } from "@/services/storage/types";
|
import type { MediaAssetData } from "@/services/storage/types";
|
||||||
import { getProjectId, transformProjectV1ToV2 } from "../transformers/v1-to-v2";
|
import { getProjectId, transformProjectV1ToV2 } from "../transformers/v1-to-v2";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import { DEFAULT_BLUR_INTENSITY } from "@/constants/project-constants";
|
|
||||||
import { transformProjectV20ToV21 } from "../transformers/v20-to-v21";
|
import { transformProjectV20ToV21 } from "../transformers/v20-to-v21";
|
||||||
|
|
||||||
|
const LEGACY_DEFAULT_BACKGROUND_BLUR_INTENSITY = 50;
|
||||||
|
|
||||||
describe("V20 to V21 Migration", () => {
|
describe("V20 to V21 Migration", () => {
|
||||||
test("multiplies blur background intensity by 5", () => {
|
test("multiplies blur background intensity by 5", () => {
|
||||||
const result = transformProjectV20ToV21({
|
const result = transformProjectV20ToV21({
|
||||||
|
|
@ -46,7 +47,9 @@ describe("V20 to V21 Migration", () => {
|
||||||
expect(result.skipped).toBe(false);
|
expect(result.skipped).toBe(false);
|
||||||
const settings = result.project.settings as Record<string, unknown>;
|
const settings = result.project.settings as Record<string, unknown>;
|
||||||
const background = settings.background as Record<string, unknown>;
|
const background = settings.background as Record<string, unknown>;
|
||||||
expect(background.blurIntensity).toBe(DEFAULT_BLUR_INTENSITY);
|
expect(background.blurIntensity).toBe(
|
||||||
|
LEGACY_DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("leaves color background unchanged", () => {
|
test("leaves color background unchanged", () => {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
DEFAULT_BACKGROUND_BLUR_INTENSITY,
|
||||||
DEFAULT_BACKGROUND_COLOR,
|
} from "@/lib/background/blur";
|
||||||
} from "@/lib/background/constants";
|
import { DEFAULT_BACKGROUND_COLOR } from "@/lib/background/color";
|
||||||
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/constants";
|
import { DEFAULT_CANVAS_SIZE } from "@/lib/canvas/sizes";
|
||||||
const DEFAULT_FPS = 30;
|
const DEFAULT_FPS = 30;
|
||||||
import { IndexedDBAdapter } from "@/services/storage/indexeddb-adapter";
|
import { IndexedDBAdapter } from "@/services/storage/indexeddb-adapter";
|
||||||
import type { MediaAssetData } from "@/services/storage/types";
|
import type { MediaAssetData } from "@/services/storage/types";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { STICKER_INTRINSIC_SIZE_FALLBACK } from "@/constants/sticker-constants";
|
import { STICKER_INTRINSIC_SIZE_FALLBACK } from "@/lib/stickers/intrinsic-size";
|
||||||
import type { MigrationResult, ProjectRecord } from "./types";
|
import type { MigrationResult, ProjectRecord } from "./types";
|
||||||
import { getProjectId, isRecord } from "./utils";
|
import { getProjectId, isRecord } from "./utils";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { DEFAULT_BLUR_INTENSITY } from "@/constants/project-constants";
|
|
||||||
import { INTENSITY_TO_SIGMA_DIVISOR } from "@/lib/effects/definitions/blur";
|
import { INTENSITY_TO_SIGMA_DIVISOR } from "@/lib/effects/definitions/blur";
|
||||||
import type { MigrationResult, ProjectRecord } from "./types";
|
import type { MigrationResult, ProjectRecord } from "./types";
|
||||||
import { getProjectId, isRecord } from "./utils";
|
import { getProjectId, isRecord } from "./utils";
|
||||||
|
|
||||||
|
const LEGACY_DEFAULT_BACKGROUND_BLUR_INTENSITY = 50;
|
||||||
|
|
||||||
export function transformProjectV20ToV21({
|
export function transformProjectV20ToV21({
|
||||||
project,
|
project,
|
||||||
}: {
|
}: {
|
||||||
|
|
@ -51,7 +52,7 @@ function migrateBackgroundBlurScale({
|
||||||
const blurIntensity =
|
const blurIntensity =
|
||||||
typeof raw === "number" && Number.isFinite(raw)
|
typeof raw === "number" && Number.isFinite(raw)
|
||||||
? raw * INTENSITY_TO_SIGMA_DIVISOR
|
? raw * INTENSITY_TO_SIGMA_DIVISOR
|
||||||
: DEFAULT_BLUR_INTENSITY;
|
: LEGACY_DEFAULT_BACKGROUND_BLUR_INTENSITY;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...project,
|
...project,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
import {
|
import {
|
||||||
DEFAULT_TRANSCRIPTION_MODEL,
|
DEFAULT_TRANSCRIPTION_MODEL,
|
||||||
TRANSCRIPTION_MODELS,
|
TRANSCRIPTION_MODELS,
|
||||||
} from "@/constants/transcription-constants";
|
} from "@/lib/transcription/models";
|
||||||
import type { WorkerMessage, WorkerResponse } from "./worker";
|
import type { WorkerMessage, WorkerResponse } from "./worker";
|
||||||
|
|
||||||
type ProgressCallback = (progress: TranscriptionProgress) => void;
|
type ProgressCallback = (progress: TranscriptionProgress) => void;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import type { TranscriptionSegment } from "@/lib/transcription/types";
|
||||||
import {
|
import {
|
||||||
DEFAULT_CHUNK_LENGTH_SECONDS,
|
DEFAULT_CHUNK_LENGTH_SECONDS,
|
||||||
DEFAULT_STRIDE_SECONDS,
|
DEFAULT_STRIDE_SECONDS,
|
||||||
} from "@/constants/transcription-constants";
|
} from "@/lib/transcription/audio";
|
||||||
|
|
||||||
export type WorkerMessage =
|
export type WorkerMessage =
|
||||||
| { type: "init"; modelId: string }
|
| { type: "init"; modelId: string }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { DEFAULT_CANVAS_PRESETS } from "@/lib/canvas/constants";
|
import { DEFAULT_CANVAS_PRESETS } from "@/lib/canvas/sizes";
|
||||||
import type { TCanvasSize } from "@/lib/project/types";
|
import type { TCanvasSize } from "@/lib/project/types";
|
||||||
|
|
||||||
interface EditorState {
|
interface EditorState {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
import { PANEL_CONFIG } from "@/lib/panels/constants";
|
import { PANEL_CONFIG } from "@/lib/panels/layout";
|
||||||
|
|
||||||
export interface PanelSizes {
|
export interface PanelSizes {
|
||||||
tools: number;
|
tools: number;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
import { isGuideId, type GuideId } from "@/lib/guides";
|
import { isGuideId, type GuideId } from "@/lib/guides";
|
||||||
import { DEFAULT_GRID_CONFIG } from "@/constants/guide-constants";
|
import { DEFAULT_GRID_CONFIG } from "@/lib/guides/grid";
|
||||||
import type { GridConfig } from "@/lib/guides/types";
|
import type { GridConfig } from "@/lib/guides/types";
|
||||||
|
|
||||||
interface PreviewOverlaysState {
|
interface PreviewOverlaysState {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
searchStickers as searchStickersFromProviders,
|
searchStickers as searchStickersFromProviders,
|
||||||
} from "@/lib/stickers";
|
} from "@/lib/stickers";
|
||||||
import type { StickerBrowseResult, StickerSearchResult } from "@/lib/stickers";
|
import type { StickerBrowseResult, StickerSearchResult } from "@/lib/stickers";
|
||||||
import { STICKER_CATEGORIES } from "@/constants/sticker-constants";
|
import { STICKER_CATEGORIES } from "@/lib/stickers/categories";
|
||||||
import type { StickerCategory } from "@/lib/stickers/types";
|
import type { StickerCategory } from "@/lib/stickers/types";
|
||||||
import { registerDefaultStickerProviders } from "@/lib/stickers/providers";
|
import { registerDefaultStickerProviders } from "@/lib/stickers/providers";
|
||||||
import { stickersRegistry } from "@/lib/stickers/registry";
|
import { stickersRegistry } from "@/lib/stickers/registry";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue