import '@signature.digital/catalog'; import { html, render } from '@design.estate/dees-element'; type TWorkspaceView = 'inbox' | 'compose' | 'sign' | 'audit' | 'developers' | 'templates' | 'team' | 'settings'; type TDocumentRow = { id: string; title: string; status: 'awaiting' | 'signed' | 'draft' | 'declined'; recipients: Array<{ name: string; initials: string; signed: boolean }>; updated: string; sender: string; pages: number; deadline?: string; }; const workspaceViews: TWorkspaceView[] = ['inbox', 'compose', 'sign', 'audit', 'developers', 'templates', 'team', 'settings']; const appDocuments: TDocumentRow[] = [ { id: 'app_doc_001', title: 'Platform Services Agreement - App-owned data', status: 'awaiting', recipients: [{ name: 'Sarah Chen', initials: 'SC', signed: true }, { name: 'David Park', initials: 'DP', signed: false }], updated: 'just now', sender: 'App Service', pages: 14, deadline: 'May 5' }, { id: 'app_doc_002', title: 'Security Addendum - Catalog Integration', status: 'draft', recipients: [{ name: 'Philipp K.', initials: 'PK', signed: false }], updated: '12 min ago', sender: 'App Service', pages: 5 }, { id: 'app_doc_003', title: 'Completed Vendor NDA - Signed from App', status: 'signed', recipients: [{ name: 'Lila Brooks', initials: 'LB', signed: true }, { name: 'Philipp K.', initials: 'PK', signed: true }], updated: '1h ago', sender: 'App Service', pages: 3 }, ]; const isWorkspaceView = (view: string): view is TWorkspaceView => workspaceViews.includes(view as TWorkspaceView); const routeFromLocation = (): { view: TWorkspaceView; documentId: string } => { const [view = '', documentId = ''] = globalThis.location.hash.replace(/^#/, '').split(':'); return { view: isWorkspaceView(view) ? view : 'inbox', documentId }; }; const hashForRoute = (view: TWorkspaceView, documentId = ''): string => { return documentId && (view === 'sign' || view === 'audit') ? `#${view}:${documentId}` : `#${view}`; }; let currentRoute = routeFromLocation(); let currentView = currentRoute.view; let activeDocumentId = currentRoute.documentId; let appRoot: HTMLElement | null = null; let routeChangeFrame: number | null = null; const createAppRoot = () => { document.getElementById('signature-digital-app')?.remove(); appRoot = document.createElement('div'); appRoot.id = 'signature-digital-app'; document.body.append(appRoot); }; const handleViewChange = (event: Event) => { const view = (event as CustomEvent<{ view?: TWorkspaceView }>).detail?.view; if (!view || !isWorkspaceView(view)) return; currentView = view; const nextHash = hashForRoute(view, activeDocumentId); if (globalThis.location.hash !== nextHash) { globalThis.location.hash = nextHash.slice(1); } }; const handleDocumentOpen = (event: Event) => { const document = (event as CustomEvent<{ document?: TDocumentRow }>).detail?.document; if (!document) return; activeDocumentId = document.id; }; const handleWorkspaceViewRequest = (event: Event) => { const view = (event as CustomEvent<{ view?: TWorkspaceView }>).detail?.view; if (!view || !isWorkspaceView(view)) return; currentView = view; const nextHash = hashForRoute(view, activeDocumentId); if (globalThis.location.hash !== nextHash) { globalThis.location.hash = nextHash.slice(1); } else { renderApp(); } }; const handleRouteChange = () => { if (routeChangeFrame !== null) { globalThis.cancelAnimationFrame(routeChangeFrame); } routeChangeFrame = globalThis.requestAnimationFrame(() => { routeChangeFrame = null; currentRoute = routeFromLocation(); currentView = currentRoute.view; activeDocumentId = currentRoute.documentId; renderApp(); }); }; const renderApp = () => { if (!appRoot) createAppRoot(); render( html` `, appRoot! ); }; const run = async () => { createAppRoot(); document.body.addEventListener('view-change', handleViewChange); document.body.addEventListener('document-open', handleDocumentOpen); document.body.addEventListener('workspace-view-request', handleWorkspaceViewRequest); globalThis.addEventListener('popstate', handleRouteChange); globalThis.addEventListener('hashchange', handleRouteChange); renderApp(); }; run();