61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
export interface ApplicationWorkspaceSnapshot<ViewId extends string = string> {
|
|
navigationOpen: boolean;
|
|
activeView: ViewId | null;
|
|
contentOpen: boolean;
|
|
contentExpanded: boolean;
|
|
}
|
|
|
|
export interface ApplicationWorkspaceController<ViewId extends string = string> {
|
|
getState: () => ApplicationWorkspaceSnapshot<ViewId>;
|
|
openNavigation: () => void;
|
|
toggleNavigation: () => void;
|
|
closeNavigation: () => void;
|
|
openView: (view: ViewId) => void;
|
|
closeView: () => void;
|
|
setContentExpanded: (expanded: boolean) => void;
|
|
}
|
|
|
|
export interface ApplicationWorkspaceOptions<ViewId extends string = string> {
|
|
root?: HTMLElement;
|
|
navigationOpen?: boolean;
|
|
activeView?: ViewId | null;
|
|
contentExpanded?: boolean;
|
|
onChange?: (state: ApplicationWorkspaceSnapshot<ViewId>) => void;
|
|
}
|
|
|
|
export function createApplicationWorkspaceController<ViewId extends string = string>({
|
|
root,
|
|
navigationOpen = false,
|
|
activeView = null,
|
|
contentExpanded = true,
|
|
onChange,
|
|
}: ApplicationWorkspaceOptions<ViewId> = {}): ApplicationWorkspaceController<ViewId> {
|
|
let state: ApplicationWorkspaceSnapshot<ViewId> = {
|
|
navigationOpen: navigationOpen || activeView !== null,
|
|
activeView,
|
|
contentOpen: activeView !== null,
|
|
contentExpanded,
|
|
};
|
|
|
|
const commit = (patch: Partial<ApplicationWorkspaceSnapshot<ViewId>>) => {
|
|
state = { ...state, ...patch };
|
|
state.contentOpen = state.activeView !== null;
|
|
root?.toggleAttribute("data-navigation-open", state.navigationOpen);
|
|
root?.toggleAttribute("data-content-open", state.contentOpen);
|
|
root?.toggleAttribute("data-content-expanded", state.contentOpen && state.contentExpanded);
|
|
onChange?.({ ...state });
|
|
};
|
|
|
|
commit({});
|
|
|
|
return {
|
|
getState: () => ({ ...state }),
|
|
openNavigation: () => commit({ navigationOpen: true }),
|
|
toggleNavigation: () => commit({ navigationOpen: !state.navigationOpen, activeView: state.navigationOpen ? null : state.activeView }),
|
|
closeNavigation: () => commit({ navigationOpen: false, activeView: null }),
|
|
openView: (view) => commit({ navigationOpen: true, activeView: view, contentExpanded: true }),
|
|
closeView: () => commit({ activeView: null }),
|
|
setContentExpanded: (expanded) => commit({ contentExpanded: expanded }),
|
|
};
|
|
}
|