mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Initial scaffold: spec, architecture playbook, and M0 skeleton
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { create } from 'zustand';
|
||||
import type { UiTheme } from '@core/theme';
|
||||
|
||||
/**
|
||||
* 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 };
|
||||
|
||||
/** Which modal, if any, is currently open. At most one at a time (spec §01C). */
|
||||
export type ModalName = 'datasets' | 'settings' | 'about' | 'donate' | 'chartBuilder' | 'extract';
|
||||
|
||||
export interface AppState {
|
||||
/** Active UI theme; mirrored onto <html data-theme> by a subscriber. */
|
||||
uiTheme: UiTheme;
|
||||
/** The currently open modal, or null. */
|
||||
activeModal: ModalName | null;
|
||||
|
||||
setTheme: (theme: UiTheme) => 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<AppState>((set) => ({
|
||||
uiTheme: 'light',
|
||||
activeModal: null,
|
||||
|
||||
setTheme: (uiTheme) => set({ uiTheme }),
|
||||
setActiveModal: (activeModal) => set({ activeModal }),
|
||||
}));
|
||||
Reference in New Issue
Block a user