From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- .../editor/panels/assets/assets-panel-store.tsx | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 apps/web/src/components/editor/panels/assets/assets-panel-store.tsx (limited to 'apps/web/src/components/editor/panels/assets/assets-panel-store.tsx') diff --git a/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx new file mode 100644 index 00000000..1539d305 --- /dev/null +++ b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx @@ -0,0 +1,124 @@ +import type { ElementType } from "react"; +import { create } from "zustand"; +import { persist } from "zustand/middleware"; +import { + ArrowRightDoubleIcon, + ClosedCaptionIcon, + Folder03Icon, + Happy01Icon, + HeadphonesIcon, + MagicWand05Icon, + TextIcon, + Settings01Icon, + SlidersHorizontalIcon, + ColorsIcon, +} from "@hugeicons/core-free-icons"; +import { HugeiconsIcon, type IconSvgElement } from "@hugeicons/react"; + +export const TAB_KEYS = [ + "media", + "sounds", + "text", + "stickers", + "effects", + "transitions", + "captions", + "adjustment", + "settings", +] as const; + +export type Tab = (typeof TAB_KEYS)[number]; + +const createHugeiconsIcon = + ({ icon }: { icon: IconSvgElement }) => + ({ className }: { className?: string }) => ( + + ); + +export const tabs = { + media: { + icon: createHugeiconsIcon({ icon: Folder03Icon }), + label: "Media", + }, + sounds: { + icon: createHugeiconsIcon({ icon: HeadphonesIcon }), + label: "Sounds", + }, + text: { + icon: createHugeiconsIcon({ icon: TextIcon }), + label: "Text", + }, + stickers: { + icon: createHugeiconsIcon({ icon: Happy01Icon }), + label: "Stickers", + }, + effects: { + icon: createHugeiconsIcon({ icon: MagicWand05Icon }), + label: "Effects", + }, + transitions: { + icon: createHugeiconsIcon({ icon: ArrowRightDoubleIcon }), + label: "Transitions", + }, + captions: { + icon: createHugeiconsIcon({ icon: ClosedCaptionIcon }), + label: "Captions", + }, + adjustment: { + icon: createHugeiconsIcon({ icon: SlidersHorizontalIcon }), + label: "Adjustment", + }, + settings: { + icon: createHugeiconsIcon({ icon: Settings01Icon }), + label: "Settings", + }, +} satisfies Record< + Tab, + { icon: ElementType<{ className?: string }>; label: string } +>; + +export type MediaViewMode = "grid" | "list"; +export type MediaSortKey = "name" | "type" | "duration" | "size"; +export type MediaSortOrder = "asc" | "desc"; + +interface AssetsPanelStore { + activeTab: Tab; + setActiveTab: (tab: Tab) => void; + highlightMediaId: string | null; + requestRevealMedia: (mediaId: string) => void; + clearHighlight: () => void; + + /* Media */ + mediaViewMode: MediaViewMode; + setMediaViewMode: (mode: MediaViewMode) => void; + mediaSortBy: MediaSortKey; + mediaSortOrder: MediaSortOrder; + setMediaSort: (key: MediaSortKey, order: MediaSortOrder) => void; +} + +export const useAssetsPanelStore = create()( + persist( + (set) => ({ + activeTab: "media", + setActiveTab: (tab) => set({ activeTab: tab }), + highlightMediaId: null, + requestRevealMedia: (mediaId) => + set({ activeTab: "media", highlightMediaId: mediaId }), + clearHighlight: () => set({ highlightMediaId: null }), + mediaViewMode: "grid", + setMediaViewMode: (mode) => set({ mediaViewMode: mode }), + mediaSortBy: "name", + mediaSortOrder: "asc", + setMediaSort: (key, order) => + set({ mediaSortBy: key, mediaSortOrder: order }), + }), + { + name: "assets-panel", + partialize: (state) => ({ + mediaViewMode: state.mediaViewMode, + mediaSortBy: state.mediaSortBy, + mediaSortOrder: state.mediaSortOrder, + }), + }, + ), +); -- cgit v1.3.1