import { html, css, DeesElement, customElement, state } from '@design.estate/dees-element'; import type { DeesAppui } from './dees-appui.js'; import type { IAppConfig, IViewActivationContext } from '../../interfaces/appconfig.js'; import type * as interfaces from '../../interfaces/index.js'; import '@design.estate/dees-wcctools/demotools'; // Demo view component with lifecycle hooks @customElement('demo-dashboard-view') class DemoDashboardView extends DeesElement { @state() accessor activated: boolean = false; private ctx: IViewActivationContext; onActivate(context: IViewActivationContext) { this.ctx = context; this.activated = true; console.log('Dashboard activated with context:', context); // Set view-specific secondary menu with new item types context.appui.setSecondaryMenu({ heading: 'Dashboard', groups: [ { name: 'Quick Access', iconName: 'lucide:zap', items: [ { key: 'Overview', iconName: 'layoutDashboard', action: () => console.log('Overview') }, { key: 'Recent', iconName: 'clock', badge: 5, action: () => console.log('Recent') }, { type: 'divider' }, { type: 'action', key: 'Refresh Data', iconName: 'lucide:refreshCw', action: () => alert('Refreshing dashboard data...') }, ] as interfaces.ISecondaryMenuItem[] }, { name: 'Filters', iconName: 'lucide:filter', items: [ { type: 'header', label: 'Time Range' }, { type: 'filter', key: 'Live Updates', iconName: 'lucide:radio', active: true, onToggle: (active) => console.log('Live updates:', active) }, { type: 'filter', key: 'Show Archived', iconName: 'lucide:archive', active: false, onToggle: (active) => console.log('Show archived:', active) }, { type: 'divider' }, { type: 'multiFilter', key: 'Data Sources', iconName: 'lucide:database', options: [ { key: 'api', label: 'API Server', checked: true, iconName: 'lucide:server' }, { key: 'web', label: 'Web Traffic', checked: true, iconName: 'lucide:globe' }, { key: 'mobile', label: 'Mobile App', checked: false, iconName: 'lucide:smartphone' }, ], onChange: (keys) => console.log('Data sources:', keys) }, ] as interfaces.ISecondaryMenuItem[] }, { name: 'Analytics', iconName: 'lucide:barChart3', items: [ { key: 'Metrics', iconName: 'activity', action: () => console.log('Metrics') }, { key: 'Reports', iconName: 'fileText', badge: 'new', badgeVariant: 'success', action: () => console.log('Reports') }, { type: 'divider' }, { type: 'link', key: 'Analytics Docs', iconName: 'lucide:externalLink', href: 'https://docs.example.com/analytics' }, ] as interfaces.ISecondaryMenuItem[] } ] }); // Set content tabs for dashboard context.appui.setContentTabs([ { key: 'Overview', iconName: 'lucide:layoutDashboard', action: () => console.log('Overview tab') }, { key: 'Analytics', iconName: 'lucide:barChart', action: () => console.log('Analytics tab') }, { key: 'Reports', iconName: 'lucide:fileText', action: () => console.log('Reports tab') }, ]); } onDeactivate() { this.activated = false; console.log('Dashboard deactivated'); } render() { return html`

Dashboard

Welcome back! Here's an overview of your system.

Active Users

1,234
Online

API Calls

45.2K

+12% from last hour

System Health

99.9%

All systems operational

Context Actions (ctx.appui)

`; } private tabCounter = 0; private addCloseableTab() { if (!this.ctx) return; this.tabCounter++; const tabKey = `Tab ${this.tabCounter}`; this.ctx.appui.addContentTab({ key: tabKey, iconName: 'lucide:file', action: () => console.log(`Selected ${tabKey}`), closeable: true, onClose: () => { this.ctx?.appui.removeContentTab(tabKey); } }); } } // Settings view with route params and canDeactivate guard @customElement('demo-settings-view') class DemoSettingsView extends DeesElement { @state() accessor section: string = 'general'; @state() accessor hasChanges: boolean = false; private appui: DeesAppui; onActivate(context: IViewActivationContext) { this.appui = context.appui as any; console.log('Settings activated with params:', context.params); if (context.params?.section) { this.section = context.params.section; } // Set settings-specific secondary menu context.appui.setSecondaryMenu({ heading: 'Settings', groups: [ { name: 'Account', iconName: 'lucide:user', items: [ { key: 'general', iconName: 'settings', action: () => this.showSection('general') }, { key: 'profile', iconName: 'user', action: () => this.showSection('profile') }, { key: 'security', iconName: 'shield', action: () => this.showSection('security') }, ] }, { name: 'Preferences', iconName: 'lucide:sliders', items: [ { key: 'notifications', iconName: 'bell', badge: 3, action: () => this.showSection('notifications') }, { key: 'appearance', iconName: 'palette', action: () => this.showSection('appearance') }, ] } ] }); context.appui.setSecondaryMenuSelection(this.section); // Clear content tabs for settings context.appui.setContentTabs([]); } onDeactivate() { console.log('Settings deactivated'); this.hasChanges = false; } canDeactivate(): boolean | string { if (this.hasChanges) { return 'You have unsaved changes. Leave anyway?'; } return true; } showSection(section: string) { this.section = section; this.appui?.setSecondaryMenuSelection(section); } simulateChange() { this.hasChanges = true; } render() { return html`

Settings

Manage your account and application preferences.

Current section: ${this.section}
${this.hasChanges ? html`

You have unsaved changes. Navigation will prompt for confirmation.

` : ''} `; } } // Projects view @customElement('demo-projects-view') class DemoProjectsView extends DeesElement { onActivate(context: IViewActivationContext) { context.appui.setSecondaryMenu({ heading: 'Projects', groups: [ { name: 'My Projects', iconName: 'lucide:folder', items: [ { key: 'Active', iconName: 'folder', badge: 3, action: () => console.log('Active') }, { key: 'Archived', iconName: 'archive', action: () => console.log('Archived') }, { key: 'Shared', iconName: 'users', badge: 2, badgeVariant: 'warning', action: () => console.log('Shared') }, ] as interfaces.ISecondaryMenuItem[] }, { name: 'Quick Actions', iconName: 'lucide:zap', items: [ { type: 'action', key: 'New Project', iconName: 'lucide:folderPlus', action: () => alert('Create new project') }, { type: 'action', key: 'Import', iconName: 'lucide:download', action: () => alert('Import project') }, { type: 'divider' }, { type: 'link', key: 'Templates', iconName: 'lucide:layoutTemplate', href: 'https://templates.example.com' }, ] as interfaces.ISecondaryMenuItem[] } ] }); context.appui.setContentTabs([ { key: 'Grid', iconName: 'lucide:grid', action: () => console.log('Grid view') }, { key: 'List', iconName: 'lucide:list', action: () => console.log('List view') }, { key: 'Board', iconName: 'lucide:kanban', action: () => console.log('Board view') }, ]); } render() { return html`

Projects

Frontend App Active

React-based dashboard application

API Server Active

Node.js REST API backend

Mobile App Active

React Native iOS/Android app

Documentation

Technical documentation site

`; } } // Tasks view showing inline template content @customElement('demo-tasks-view') class DemoTasksView extends DeesElement { onActivate(context: IViewActivationContext) { context.appui.setSecondaryMenu({ heading: 'Tasks', groups: [ { name: 'Views', iconName: 'lucide:eye', items: [ { key: 'All Tasks', iconName: 'list', badge: 12, action: () => console.log('All') }, { key: 'Today', iconName: 'calendar', badge: 3, action: () => console.log('Today') }, { key: 'Upcoming', iconName: 'clock', action: () => console.log('Upcoming') }, { key: 'Completed', iconName: 'checkCircle', action: () => console.log('Completed') }, ] as interfaces.ISecondaryMenuItem[] }, { name: 'Filters', iconName: 'lucide:filter', items: [ { type: 'header', label: 'Priority' }, { type: 'multiFilter', key: 'Priority', iconName: 'lucide:flag', options: [ { key: 'high', label: 'High', checked: true, iconName: 'lucide:alertCircle' }, { key: 'medium', label: 'Medium', checked: true, iconName: 'lucide:minusCircle' }, { key: 'low', label: 'Low', checked: false, iconName: 'lucide:circle' }, ], onChange: (keys) => console.log('Priority filter:', keys) }, { type: 'divider' }, { type: 'header', label: 'Options' }, { type: 'filter', key: 'Show Subtasks', iconName: 'lucide:listTree', active: true, onToggle: (active) => console.log('Show subtasks:', active) }, { type: 'filter', key: 'Show Completed', iconName: 'lucide:checkSquare', active: false, onToggle: (active) => console.log('Show completed:', active) }, ] as interfaces.ISecondaryMenuItem[] }, { name: 'Actions', iconName: 'lucide:zap', items: [ { type: 'action', key: 'Add Task', iconName: 'lucide:plus', action: () => alert('Add new task') }, { type: 'action', key: 'Import Tasks', iconName: 'lucide:upload', action: () => alert('Import tasks') }, { type: 'divider' }, { type: 'action', key: 'Clear Completed', iconName: 'lucide:trash2', variant: 'danger', confirmMessage: 'Delete all completed tasks?', action: () => alert('Cleared completed tasks') }, ] as interfaces.ISecondaryMenuItem[] } ] }); context.appui.setContentTabs([ { key: 'List', iconName: 'lucide:list', action: () => console.log('List') }, { key: 'Calendar', iconName: 'lucide:calendar', action: () => console.log('Calendar') }, ]); } render() { return html`

Tasks

Review pull request #42 Today High
Update documentation Tomorrow Medium
Write unit tests Dec 20
`; } } export const demoFunc = () => { // App configuration using the new unified API const appConfig: IAppConfig = { branding: { logoIcon: 'lucide:box', logoText: 'Acme App' }, appBar: { menuItems: [ { name: 'File', action: async () => {}, submenu: [ { name: 'New Project', shortcut: 'Cmd+N', iconName: 'filePlus', action: async () => console.log('New') }, { name: 'Open...', shortcut: 'Cmd+O', iconName: 'folderOpen', action: async () => console.log('Open') }, { name: 'Recent Projects', action: async () => {}, submenu: [ { name: 'my-app', action: async () => console.log('Open my-app') }, { name: 'component-lib', action: async () => console.log('Open component-lib') }, ]}, { divider: true }, { name: 'Save All', shortcut: 'Cmd+S', iconName: 'save', action: async () => console.log('Save') }, ] }, { name: 'Edit', action: async () => {}, submenu: [ { name: 'Undo', shortcut: 'Cmd+Z', iconName: 'undo', action: async () => console.log('Undo') }, { name: 'Redo', shortcut: 'Cmd+Shift+Z', iconName: 'redo', action: async () => console.log('Redo') }, { divider: true }, { name: 'Cut', shortcut: 'Cmd+X', iconName: 'scissors', action: async () => console.log('Cut') }, { name: 'Copy', shortcut: 'Cmd+C', iconName: 'copy', action: async () => console.log('Copy') }, { name: 'Paste', shortcut: 'Cmd+V', iconName: 'clipboard', action: async () => console.log('Paste') }, ] }, { name: 'View', action: async () => {}, submenu: [ { name: 'Toggle Sidebar', shortcut: 'Cmd+B', action: async () => console.log('Toggle sidebar') }, { name: 'Toggle Activity Log', shortcut: 'Cmd+Shift+A', action: async () => console.log('Toggle activity') }, ] }, { name: 'Help', action: async () => {}, submenu: [ { name: 'Documentation', iconName: 'book', action: async () => console.log('Docs') }, { name: 'Keyboard Shortcuts', iconName: 'keyboard', shortcut: 'Cmd+/', action: async () => console.log('Shortcuts') }, { divider: true }, { name: 'About', iconName: 'info', action: async () => console.log('About') }, ] } ], breadcrumbs: 'Dashboard', showWindowControls: true, showSearch: true, user: { name: 'Jane Smith', email: 'jane.smith@example.com', status: 'online' }, profileMenuItems: [ { name: 'Profile', iconName: 'user', action: async () => console.log('Profile') }, { name: 'Account Settings', iconName: 'settings', action: async () => console.log('Settings') }, { divider: true }, { name: 'Help & Support', iconName: 'helpCircle', action: async () => console.log('Help') }, { divider: true }, { name: 'Sign Out', iconName: 'logOut', action: async () => console.log('Sign out') } ] }, views: [ { id: 'dashboard', name: 'Dashboard', iconName: 'lucide:home', content: 'demo-dashboard-view', route: 'dashboard' }, { id: 'projects', name: 'Projects', iconName: 'lucide:folder', content: 'demo-projects-view', route: 'projects', badge: 3 }, { id: 'tasks', name: 'Tasks', iconName: 'lucide:checkSquare', content: 'demo-tasks-view', route: 'tasks', badge: 12 }, { id: 'settings', name: 'Settings', iconName: 'lucide:settings', content: 'demo-settings-view', route: 'settings/:section?' }, ], mainMenu: { sections: [ { name: 'Main', views: ['dashboard'] }, { name: 'Workspace', views: ['projects', 'tasks'] }, ], bottomItems: ['settings'] }, defaultView: 'dashboard', bottomBar: { visible: true, widgets: [ { id: 'status', iconName: 'lucide:activity', label: 'System Online', status: 'success', tooltip: 'All systems operational', onClick: () => console.log('Status clicked'), }, { id: 'notifications', iconName: 'lucide:bell', label: '3 notifications', status: 'warning', tooltip: 'You have unread notifications', onClick: () => console.log('Notifications clicked'), }, { id: 'version', iconName: 'lucide:gitBranch', label: 'v1.2.3', position: 'right', tooltip: 'Current version', }, ], actions: [ { id: 'terminal', iconName: 'lucide:terminal', tooltip: 'Open Terminal', position: 'right', onClick: () => console.log('Terminal clicked'), }, ], }, onViewChange: (viewId, view) => { console.log(`View changed to: ${viewId} (${view.name})`); }, onSearch: (query) => { console.log('Search query:', query); } }; // Use a container element to properly initialize the demo const containerElement = document.createElement('div'); containerElement.className = 'demo-container'; containerElement.style.cssText = 'position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;'; const appuiElement = document.createElement('dees-appui') as DeesAppui; containerElement.appendChild(appuiElement); // Initialize after element is connected setTimeout(async () => { await appuiElement.updateComplete; // Configure using the unified API appuiElement.configure(appConfig); // Add demo activity entries setTimeout(() => { appuiElement.activityLog.addMany([ { type: 'login', user: 'Jane Smith', message: 'logged in from Chrome on macOS' }, { type: 'create', user: 'Jane Smith', message: 'created project "Frontend App"' }, { type: 'update', user: 'John Doe', message: 'updated API documentation' }, { type: 'view', user: 'Jane Smith', message: 'viewed dashboard analytics' }, { type: 'delete', user: 'Admin', message: 'removed deprecated endpoint' }, { type: 'custom', user: 'System', message: 'scheduled backup completed', iconName: 'lucide:database' } ]); }, 500); // Subscribe to view changes appuiElement.viewChanged$.subscribe((event) => { console.log('View changed event:', event); // Update breadcrumbs based on view appuiElement.setBreadcrumbs(event.view.name); }); // Subscribe to lifecycle events appuiElement.viewLifecycle$.subscribe((event) => { console.log('Lifecycle event:', event.type, event.viewId); }); // Demo: Dynamically update a badge after 5 seconds setTimeout(() => { appuiElement.setMainMenuBadge('tasks', 15); appuiElement.activityLog.add({ type: 'update', user: 'System', message: 'new tasks added' }); }, 5000); }, 0); return html` ${containerElement} `; };