import {DOMMap, renderViewTemplate, ViewTemplateOptions} from './template'; type Container = { id: string; options: ViewTemplateOptions, view: HTMLElement; content: HTMLDivElement; dom: DOMMap; }; const containers: Array = []; let activeContainerIndex = -1; export const getViewContent = () => containers[activeContainerIndex]?.content; /** * clears current view so it is empty and ready to be re-used. * only clears the current view, not all views */ export const clearView = () => { const domMap = containers[activeContainerIndex]?.dom; Object.keys(domMap).forEach(eventId => delete domMap[eventId]); getViewContent().replaceChildren(); }; /** * get elmenet stored in internal DOMMap of the current view * alternative to internal map in view.dom, is to use id="" attribute, however same event could be shown in different views so event.id is not unique. */ export const getViewElem = (id: string) => { return containers[activeContainerIndex]?.dom[id]; }; /** * store element in internal view.dom map using id as key */ export const setViewElem = (id: string, node: HTMLElement) => { const container = containers[activeContainerIndex]; if (container) { container.dom[id] = node; } return node; }; const mainContainer = document.querySelector('main') as HTMLElement; const createContainer = ( route: string, options: ViewTemplateOptions, ) => { const {content, dom, view} = renderViewTemplate(options); const container = {id: route, options, view, content, dom}; mainContainer.append(view); containers.push(container); return container; }; type GetViewOptions = () => ViewTemplateOptions; /** * get options for current view * @returns {id: 'home' | 'feed' | 'profile' | 'note' | 'contacts' | 'event', id?: string} */ export const getViewOptions: GetViewOptions = () => containers[activeContainerIndex]?.options || {type: 'feed'}; /** * changes the current view and transitions to the view specified by route * example: * view('/npub0293ji3gojaed32r4r412', {type: 'feed}) */ export const view = ( route: string, options: ViewTemplateOptions, ) => { const active = containers[activeContainerIndex]; const nextContainer = containers.find(c => c.id === route) || createContainer(route, options); const nextContainerIndex = containers.indexOf(nextContainer); if (nextContainerIndex === activeContainerIndex) { return; } if (active) { nextContainer.view.classList.add('view-next'); } requestAnimationFrame(() => { requestAnimationFrame(() => { nextContainer.view.classList.remove('view-next', 'view-prev'); }); active?.view.classList.add(nextContainerIndex < activeContainerIndex ? 'view-next' : 'view-prev'); activeContainerIndex = nextContainerIndex; }); };