NODEDC_DESIGN_GUIDELINE/packages/ui-dom/src/applicationWorkspace.ts

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 }),
};
}