import { create } from 'zustand'; import type { FitMode } from '@core/rendering'; import type { UiTheme } from '@core/theme'; import type { ChartThemeId } from '@core/vega-themes'; import type { ModalName } from '../modals/types'; /** * Centralized cross-cutting application state, as a Zustand store. Keep this * lean — durable, feature-specific state (snippets, datasets, settings) lands * in its own store module (e.g. stores/SnippetStore) as the app grows. * * Usable inside React via the `useAppStore` hook (with a selector) and outside * React via `useAppStore.getState()` / `.setState()` / `.subscribe()` — see * docs/architecture/01-state-and-stores.md. */ export type { UiTheme }; // The modal union is defined once in the modal system (docs/architecture/03) and // re-exported here for the many callers that reach it through the app store. export type { ModalName }; export interface AppState { /** Active UI theme; mirrored onto by a subscriber. */ uiTheme: UiTheme; /** Preview sizing mode (spec §04); persisted to Settings as `previewFitMode`. */ previewFitMode: FitMode; /** Chart theme selection (spec §04); persisted to Settings as `chartTheme`. */ chartTheme: ChartThemeId; /** The currently open modal, or null. */ activeModal: ModalName | null; setTheme: (theme: UiTheme) => void; /** Flip between light and dark — the header ThemeToggle's action. */ toggleTheme: () => void; /** Set the preview fit mode — the Live Preview Fit control's action. */ setPreviewFitMode: (mode: FitMode) => void; /** Set the chart theme — the Live Preview settings cluster's action. */ setChartTheme: (theme: ChartThemeId) => void; /** * Low-level modal setter — the single primitive that mutates `activeModal`. * High-level open/close (snapshot for unsaved-change detection, URL sync, * discard confirmation) lives in the modal coordinator (docs/architecture/03), * which calls this; arrives with the modal system in M3. */ setActiveModal: (modal: ModalName | null) => void; } export const useAppStore = create((set) => ({ uiTheme: 'light', previewFitMode: 'default', chartTheme: 'astrolabe', activeModal: null, setTheme: (uiTheme) => set({ uiTheme }), toggleTheme: () => set((s) => ({ uiTheme: s.uiTheme === 'dark' ? 'light' : 'dark' })), setPreviewFitMode: (previewFitMode) => set({ previewFitMode }), setChartTheme: (chartTheme) => set({ chartTheme }), setActiveModal: (activeModal) => set({ activeModal }), }));