Files
MiragenFlow/web/src/stores/use-canvas-side-panel-store.ts
T
HouYunFeiandClaude Opus 4.8 219b3e84db feat(canvas): 左侧面板可调宽收起 + 元素多选导出与跳转动画
- 左侧画布面板支持拖拽调整宽度、展开/收起(带动画),状态与宽度持久化
- 顶栏菜单左侧新增面板开关按钮,并缩小菜单/开关按钮
- 顶栏菜单新增「导出当前画布」为压缩包
- 画布元素列表支持多选并批量导出:图片/视频/音频为文件、文本为 txt、其余各自为 json
- 画布/资产切换改为滑动下划线动画,点击元素跳转带缓动动画
- 移除文本/配置/视频等非图片元素图标的灰色底色,并写入 AGENTS.md 规范

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 16:21:26 +08:00

54 lines
1.9 KiB
TypeScript

import { create } from "zustand";
export const CANVAS_SIDE_PANEL_MOTION_MS = 500;
export const CANVAS_SIDE_PANEL_MIN_WIDTH = 220;
export const CANVAS_SIDE_PANEL_MAX_WIDTH = 480;
export const CANVAS_SIDE_PANEL_DEFAULT_WIDTH = 280;
const WIDTH_KEY = "canvas-side-panel-width";
const OPEN_KEY = "canvas-side-panel-open";
function initialWidth() {
if (typeof window === "undefined") return CANVAS_SIDE_PANEL_DEFAULT_WIDTH;
const stored = Number(localStorage.getItem(WIDTH_KEY));
if (!stored) return CANVAS_SIDE_PANEL_DEFAULT_WIDTH;
return Math.min(CANVAS_SIDE_PANEL_MAX_WIDTH, Math.max(CANVAS_SIDE_PANEL_MIN_WIDTH, stored));
}
function initialOpen() {
if (typeof window === "undefined") return true;
return localStorage.getItem(OPEN_KEY) !== "0";
}
type CanvasSidePanelStore = {
width: number;
panelOpen: boolean;
panelMounted: boolean;
panelClosing: boolean;
setWidth: (width: number) => void;
openPanel: () => void;
closePanel: () => void;
togglePanel: () => void;
};
export const useCanvasSidePanelStore = create<CanvasSidePanelStore>((set, get) => ({
width: initialWidth(),
panelOpen: initialOpen(),
panelMounted: initialOpen(),
panelClosing: false,
setWidth: (width) => set({ width }),
openPanel: () => {
if (typeof window !== "undefined") localStorage.setItem(OPEN_KEY, "1");
set({ panelOpen: true, panelMounted: true, panelClosing: false });
},
closePanel: () => {
if (!get().panelMounted || get().panelClosing) return;
if (typeof window !== "undefined") localStorage.setItem(OPEN_KEY, "0");
set({ panelOpen: false, panelClosing: true });
setTimeout(() => {
if (get().panelClosing) set({ panelMounted: false, panelClosing: false });
}, CANVAS_SIDE_PANEL_MOTION_MS);
},
togglePanel: () => (get().panelOpen ? get().closePanel() : get().openPanel()),
}));