fix(structure): group components into groups inside the repo
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
import { html, DeesElement, customElement, css, cssManager } from '@design.estate/dees-element';
|
||||
import type { IView } from './dees-simple-appdash.js';
|
||||
import '../../00group-form/dees-form/dees-form.js';
|
||||
import '../../00group-input/dees-input-text/dees-input-text.js';
|
||||
import '../../00group-input/dees-input-checkbox/dees-input-checkbox.js';
|
||||
import '../../00group-input/dees-input-dropdown/dees-input-dropdown.js';
|
||||
import '../../00group-input/dees-input-radiogroup/dees-input-radiogroup.js';
|
||||
import '../../00group-form/dees-form-submit/dees-form-submit.js';
|
||||
import '../../dees-statsgrid/dees-statsgrid.js';
|
||||
import type { IStatsTile } from '../../dees-statsgrid/dees-statsgrid.js';
|
||||
|
||||
// Create demo view components
|
||||
@customElement('demo-view-dashboard')
|
||||
class DemoViewDashboard extends DeesElement {
|
||||
static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 40px;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 20px 0;
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
}
|
||||
dees-statsgrid {
|
||||
margin-top: 20px;
|
||||
}
|
||||
`
|
||||
];
|
||||
|
||||
private statsTiles: IStatsTile[] = [
|
||||
{
|
||||
id: 'users',
|
||||
title: 'Active Users',
|
||||
value: 1234,
|
||||
type: 'number',
|
||||
icon: 'faUsers',
|
||||
description: '+15% from last week',
|
||||
color: '#22c55e'
|
||||
},
|
||||
{
|
||||
id: 'pageviews',
|
||||
title: 'Page Views',
|
||||
value: 56700,
|
||||
type: 'number',
|
||||
icon: 'faEye',
|
||||
description: '56.7k total views',
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{
|
||||
id: 'uptime',
|
||||
title: 'System Uptime',
|
||||
value: 89,
|
||||
unit: '%',
|
||||
type: 'gauge',
|
||||
icon: 'faServer',
|
||||
description: 'Last 30 days',
|
||||
color: '#10b981',
|
||||
gaugeOptions: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
thresholds: [
|
||||
{ value: 80, color: '#ef4444' },
|
||||
{ value: 90, color: '#f59e0b' },
|
||||
{ value: 100, color: '#10b981' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'response',
|
||||
title: 'Avg Response Time',
|
||||
value: 3.2,
|
||||
unit: 's',
|
||||
type: 'number',
|
||||
icon: 'faClock',
|
||||
description: '-0.5s improvement',
|
||||
color: '#f59e0b'
|
||||
},
|
||||
{
|
||||
id: 'revenue',
|
||||
title: 'Monthly Revenue',
|
||||
value: 48520,
|
||||
unit: '$',
|
||||
type: 'trend',
|
||||
icon: 'faDollarSign',
|
||||
description: '+8.2% growth',
|
||||
color: '#22c55e',
|
||||
trendData: [35000, 38000, 37500, 41000, 39800, 42000, 44100, 43200, 45600, 47100, 46800, 48520]
|
||||
},
|
||||
{
|
||||
id: 'traffic',
|
||||
title: 'Traffic Trend',
|
||||
value: 1680,
|
||||
type: 'trend',
|
||||
icon: 'faChartLine',
|
||||
description: 'Last 7 days',
|
||||
color: '#3b82f6',
|
||||
trendData: [1200, 1350, 1100, 1450, 1600, 1550, 1680]
|
||||
}
|
||||
];
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<h1>Dashboard</h1>
|
||||
<p>Welcome to your application dashboard. Here's an overview of your metrics:</p>
|
||||
<dees-statsgrid
|
||||
.tiles=${this.statsTiles}
|
||||
@tile-action=${(e: CustomEvent) => {
|
||||
console.log('Tile action:', e.detail);
|
||||
}}
|
||||
></dees-statsgrid>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('demo-view-analytics')
|
||||
class DemoViewAnalytics extends DeesElement {
|
||||
static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 40px;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 20px 0;
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
}
|
||||
`
|
||||
];
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<h1>Analytics</h1>
|
||||
<p>This is the analytics view. You can add charts and metrics here.</p>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('demo-view-settings')
|
||||
class DemoViewSettings extends DeesElement {
|
||||
static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 40px;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 20px 0;
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
}
|
||||
.settings-section {
|
||||
margin-top: 30px;
|
||||
}
|
||||
.settings-section h2 {
|
||||
font-size: 18px;
|
||||
margin: 0 0 15px 0;
|
||||
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||
}
|
||||
.horizontal-form-section {
|
||||
background: ${cssManager.bdTheme('#f5f5f5', '#1a1a1a')};
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
`
|
||||
];
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<h1>Settings</h1>
|
||||
<p>Configure your application settings below:</p>
|
||||
|
||||
<div class="settings-section">
|
||||
<h2>General Settings</h2>
|
||||
<dees-form>
|
||||
<dees-input-text key="appName" label="Application Name" value="My App"></dees-input-text>
|
||||
<dees-input-text key="apiEndpoint" label="API Endpoint" value="https://api.example.com"></dees-input-text>
|
||||
<dees-input-dropdown
|
||||
key="environment"
|
||||
label="Environment"
|
||||
.options=${[
|
||||
{ option: 'Development', key: 'dev' },
|
||||
{ option: 'Staging', key: 'staging' },
|
||||
{ option: 'Production', key: 'prod' }
|
||||
]}
|
||||
.selectedOption=${{ option: 'Production', key: 'prod' }}
|
||||
></dees-input-dropdown>
|
||||
<dees-input-checkbox key="enableNotifications" label="Enable Notifications" value="true"></dees-input-checkbox>
|
||||
<dees-input-checkbox key="enableAnalytics" label="Enable Analytics" value="false"></dees-input-checkbox>
|
||||
<dees-form-submit>Save General Settings</dees-form-submit>
|
||||
</dees-form>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h2>Display Preferences</h2>
|
||||
<div class="horizontal-form-section">
|
||||
<p style="margin-top: 0; margin-bottom: 16px;">Quick display settings using horizontal layout:</p>
|
||||
<dees-form horizontal-layout>
|
||||
<dees-input-dropdown
|
||||
key="theme"
|
||||
label="Theme"
|
||||
.enableSearch=${false}
|
||||
.options=${[
|
||||
{ option: 'Light', key: 'light' },
|
||||
{ option: 'Dark', key: 'dark' },
|
||||
{ option: 'Auto', key: 'auto' }
|
||||
]}
|
||||
.selectedOption=${{ option: 'Dark', key: 'dark' }}
|
||||
></dees-input-dropdown>
|
||||
<dees-input-dropdown
|
||||
key="language"
|
||||
label="Language"
|
||||
.enableSearch=${false}
|
||||
.options=${[
|
||||
{ option: 'English', key: 'en' },
|
||||
{ option: 'German', key: 'de' },
|
||||
{ option: 'Spanish', key: 'es' },
|
||||
{ option: 'French', key: 'fr' }
|
||||
]}
|
||||
.selectedOption=${{ option: 'English', key: 'en' }}
|
||||
></dees-input-dropdown>
|
||||
<dees-input-checkbox key="compactMode" label="Compact Mode"></dees-input-checkbox>
|
||||
</dees-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h2>Notification Settings</h2>
|
||||
<dees-form>
|
||||
<dees-input-radiogroup
|
||||
.label=${'Email Frequency'}
|
||||
.options=${['Real-time', 'Daily Digest', 'Weekly Summary', 'Never']}
|
||||
.selectedOption=${'Real-time'}
|
||||
.key=${'emailFrequency'}
|
||||
></dees-input-radiogroup>
|
||||
<dees-input-checkbox key="pushNotifications" label="Enable Push Notifications" value="true"></dees-input-checkbox>
|
||||
<dees-input-checkbox key="soundAlerts" label="Play Sound for Alerts" value="true"></dees-input-checkbox>
|
||||
<dees-form-submit>Update Notifications</dees-form-submit>
|
||||
</dees-form>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
export const demoFunc = () => html`
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.demo-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="demo-container">
|
||||
<dees-simple-appdash
|
||||
name="My Application"
|
||||
terminalSetupCommand="echo 'Welcome to the terminal!'"
|
||||
.viewTabs=${[
|
||||
{
|
||||
name: 'Dashboard',
|
||||
iconName: 'home',
|
||||
element: DemoViewDashboard,
|
||||
},
|
||||
{
|
||||
name: 'Analytics',
|
||||
iconName: 'lineChart',
|
||||
element: DemoViewAnalytics,
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
iconName: 'settings',
|
||||
element: DemoViewSettings,
|
||||
}
|
||||
] as IView[]}
|
||||
@logout=${() => {
|
||||
console.log('Logout event triggered');
|
||||
alert('Logout clicked!');
|
||||
}}
|
||||
@view-select=${(e: CustomEvent) => {
|
||||
console.log('View selected:', e.detail.view.name);
|
||||
}}
|
||||
></dees-simple-appdash>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,364 @@
|
||||
import { demoFunc } from './dees-simple-appdash.demo.js';
|
||||
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
DeesElement,
|
||||
property,
|
||||
type TemplateResult,
|
||||
cssManager,
|
||||
css,
|
||||
unsafeCSS,
|
||||
type CSSResult,
|
||||
state,
|
||||
domtools,
|
||||
} from '@design.estate/dees-element';
|
||||
import '../../dees-icon/dees-icon.js';
|
||||
import type { DeesTerminal } from '../../dees-terminal/dees-terminal.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'dees-simple-appdash': DeesSimpleAppDash;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IView {
|
||||
name: string;
|
||||
iconName?: string;
|
||||
element: DeesElement['constructor']['prototype'];
|
||||
}
|
||||
|
||||
@customElement('dees-simple-appdash')
|
||||
export class DeesSimpleAppDash extends DeesElement {
|
||||
// STATIC
|
||||
public static demo = demoFunc;
|
||||
// INSTANCE
|
||||
|
||||
@property()
|
||||
accessor name: string = 'Application Dashboard';
|
||||
|
||||
@property({ type: Array })
|
||||
accessor viewTabs: IView[] = [];
|
||||
|
||||
@property({ type: String })
|
||||
accessor terminalSetupCommand: string = `echo "Terminal ready"`;
|
||||
|
||||
@state()
|
||||
accessor selectedView: IView;
|
||||
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||
user-select: none;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.maincontainer {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.appbar {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: calc(100% - 24px);
|
||||
width: 240px;
|
||||
background: ${cssManager.bdTheme('#fafafa', '#000')};
|
||||
border-right: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
|
||||
font-size: 12px;
|
||||
font-family: 'Geist Sans', sans-serif;
|
||||
z-index: 2;
|
||||
display: grid;
|
||||
grid-template-rows: auto min-content;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 16px 12px;
|
||||
border-bottom: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.appName {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.viewTabs-container {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.viewTabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.viewTab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
cursor: default;
|
||||
transition: background 0.1s;
|
||||
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||
user-select: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.viewTab:hover {
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.08)')};
|
||||
}
|
||||
|
||||
.viewTab:active {
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
|
||||
}
|
||||
|
||||
.viewTab.selected {
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.12)')};
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.viewTab.selected::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 3px;
|
||||
background: ${cssManager.bdTheme('#26a69a', '#26a69a')};
|
||||
}
|
||||
|
||||
.viewTab dees-icon {
|
||||
font-size: 14px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
||||
.appActions {
|
||||
padding: 12px;
|
||||
border-top: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
transition: background 0.1s;
|
||||
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||
}
|
||||
|
||||
.action:hover {
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.08)')};
|
||||
}
|
||||
|
||||
.action dees-icon {
|
||||
font-size: 14px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.appcontent {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
height: calc(100% - 24px);
|
||||
bottom: 24px;
|
||||
width: calc(100% - 240px);
|
||||
overflow: auto;
|
||||
background: ${cssManager.bdTheme('#f5f5f5', '#000')};
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.controlbar {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
border-top: 1px solid ${cssManager.bdTheme('#00000020', '#ffffff20')};
|
||||
height: 24px;
|
||||
background: ${cssManager.bdTheme('#2196f3', '#1565c0')};
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-right: 16px;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.control:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.control dees-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
`,
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="maincontainer">
|
||||
<div class="appbar">
|
||||
<div>
|
||||
<div class="sidebar-header">
|
||||
<dees-icon .icon="${'lucide:grid3x3'}" style="font-size: 18px;"></dees-icon>
|
||||
<div class="appName">${this.name}</div>
|
||||
</div>
|
||||
<div class="viewTabs-container">
|
||||
<div class="viewTabs">
|
||||
${this.viewTabs.map(
|
||||
(view) => html`
|
||||
<div
|
||||
class="viewTab ${this.selectedView === view ? 'selected' : ''}"
|
||||
@click=${() => this.loadView(view)}
|
||||
>
|
||||
${view.iconName ? html`
|
||||
<dees-icon .icon="${`${view.iconName}`}"></dees-icon>
|
||||
` : ''}
|
||||
<span style="flex: 1;">${view.name}</span>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="appActions">
|
||||
<div class="action" @click=${() => {
|
||||
this.dispatchEvent(new CustomEvent('logout', { bubbles: true, composed: true }));
|
||||
}}>
|
||||
<dees-icon .icon="${'lucide:logOut'}"></dees-icon>
|
||||
<span>Logout</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="appcontent">
|
||||
<!-- Content goes here -->
|
||||
</div>
|
||||
<div class="controlbar">
|
||||
<div class="control">
|
||||
<dees-icon .icon="${'lucide:wifi'}"></dees-icon>
|
||||
<span>Connected</span>
|
||||
</div>
|
||||
<div class="control" @click=${this.launchTerminal}>
|
||||
<dees-icon .icon="${'lucide:terminal'}"></dees-icon>
|
||||
<span>Terminal</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
public async firstUpdated(_changedProperties): Promise<void> {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
super.firstUpdated(_changedProperties);
|
||||
if (this.viewTabs && this.viewTabs.length > 0) {
|
||||
await this.loadView(this.viewTabs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public currentTerminal: DeesTerminal;
|
||||
public async launchTerminal() {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
if (this.currentTerminal) {
|
||||
// If terminal already exists, remove it
|
||||
await this.closeTerminal();
|
||||
return;
|
||||
}
|
||||
|
||||
const maincontainer = this.shadowRoot.querySelector('.maincontainer');
|
||||
const { DeesTerminal } = await import('../../dees-terminal/dees-terminal.js');
|
||||
const terminal = new DeesTerminal();
|
||||
terminal.setupCommand = this.terminalSetupCommand;
|
||||
this.currentTerminal = terminal;
|
||||
maincontainer.appendChild(terminal);
|
||||
terminal.style.position = 'absolute';
|
||||
terminal.style.zIndex = '10';
|
||||
terminal.style.top = '0px';
|
||||
terminal.style.left = '240px';
|
||||
terminal.style.right = '0px';
|
||||
terminal.style.bottom = '24px';
|
||||
terminal.style.opacity = '0';
|
||||
terminal.style.transform = 'translateY(20px)';
|
||||
terminal.style.transition = 'all 0.2s';
|
||||
terminal.style.background = '#000';
|
||||
terminal.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';
|
||||
terminal.style.maxWidth = `calc(${maincontainer.clientWidth}px -240px)`;
|
||||
terminal.style.maxHeight = `calc(${maincontainer.clientHeight}px - 24px)`;
|
||||
|
||||
// Add close button to terminal
|
||||
terminal.addEventListener('close', () => this.closeTerminal());
|
||||
|
||||
await domtools.convenience.smartdelay.delayFor(0);
|
||||
terminal.style.opacity = '1';
|
||||
terminal.style.transform = 'translateY(0px)';
|
||||
return terminal;
|
||||
}
|
||||
|
||||
private async closeTerminal() {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
if (this.currentTerminal) {
|
||||
this.currentTerminal.style.opacity = '0';
|
||||
this.currentTerminal.style.transform = 'translateY(20px)';
|
||||
await domtools.convenience.smartdelay.delayFor(200);
|
||||
this.currentTerminal.remove();
|
||||
this.currentTerminal = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private currentView: DeesElement;
|
||||
public async loadView(viewArg: IView) {
|
||||
const appcontent = this.shadowRoot.querySelector('.appcontent');
|
||||
const view = new viewArg.element();
|
||||
if (this.currentView) {
|
||||
this.currentView.remove();
|
||||
}
|
||||
appcontent.appendChild(view);
|
||||
this.currentView = view;
|
||||
this.selectedView = viewArg;
|
||||
|
||||
// Emit view-select event
|
||||
this.dispatchEvent(new CustomEvent('view-select', {
|
||||
detail: { view: viewArg },
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './dees-simple-appdash.js';
|
||||
@@ -0,0 +1,37 @@
|
||||
import { html } from '@design.estate/dees-element';
|
||||
|
||||
export const demoFunc = () => html`
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.demo-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="demo-container">
|
||||
<dees-simple-login
|
||||
name="My Application"
|
||||
@login=${(e: CustomEvent) => {
|
||||
console.log('Login event received:', e.detail);
|
||||
const loginData = e.detail?.data || e.detail;
|
||||
if (loginData?.username && loginData?.password) {
|
||||
alert(`Login attempted with:\nUsername: ${loginData.username}\nPassword: ${loginData.password}`);
|
||||
// Here you would typically validate credentials and show the slotted content
|
||||
} else {
|
||||
console.error('Invalid login data structure:', e.detail);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style="padding: 40px; text-align: center;">
|
||||
<h1>Welcome!</h1>
|
||||
<p>This is the slotted content that appears after login.</p>
|
||||
</div>
|
||||
</dees-simple-login>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,152 @@
|
||||
import { demoFunc } from './dees-simple-login.demo.js';
|
||||
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
DeesElement,
|
||||
property,
|
||||
type TemplateResult,
|
||||
cssManager,
|
||||
css,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'dees-simple-login': DeesSimpleLogin;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('dees-simple-login')
|
||||
export class DeesSimpleLogin extends DeesElement {
|
||||
// STATIC
|
||||
public static demo = demoFunc
|
||||
// INSTANCE
|
||||
|
||||
@property()
|
||||
accessor name: string = 'Application';
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||
user-select: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: 'Geist Sans', sans-serif;
|
||||
}
|
||||
|
||||
.loginContainer {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: ${cssManager.bdTheme('#f5f5f5', '#000')};
|
||||
}
|
||||
|
||||
.slotContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.login {
|
||||
min-width: 320px;
|
||||
background: ${cssManager.bdTheme('#ffffff', '#111')};
|
||||
box-shadow: ${cssManager.bdTheme(
|
||||
'0 4px 12px rgba(0, 0, 0, 0.15)',
|
||||
'0 4px 12px rgba(0, 0, 0, 0.3)'
|
||||
)};
|
||||
border-radius: 8px;
|
||||
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#202020')};
|
||||
padding: 24px;
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
color: ${cssManager.bdTheme('#000', '#fff')};
|
||||
}
|
||||
|
||||
.login dees-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.login dees-input-text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.login dees-form-submit {
|
||||
margin-top: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<div class="loginContainer">
|
||||
<div class="login">
|
||||
<div class="header">Login to ${this.name}</div>
|
||||
<dees-form>
|
||||
<dees-input-text key="username" label="Username" required></dees-input-text>
|
||||
<dees-input-text key="password" label="Password" isPasswordBool required></dees-input-text>
|
||||
<dees-form-submit>Login</dees-form-submit>
|
||||
</dees-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slotContainer">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): Promise<void> {
|
||||
super.firstUpdated(_changedProperties);
|
||||
|
||||
const form = this.shadowRoot.querySelector('dees-form') as any;
|
||||
if (form) {
|
||||
form.addEventListener('formData', (event: CustomEvent) => {
|
||||
this.dispatchEvent(new CustomEvent('login', {
|
||||
detail: event.detail,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* allows switching to slotted content
|
||||
*/
|
||||
public async switchToSlottedContent() {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
const loginDiv: HTMLDivElement = this.shadowRoot.querySelector('.login');
|
||||
const loginContainerDiv: HTMLDivElement = this.shadowRoot.querySelector('.loginContainer');
|
||||
const slotContainerDiv: HTMLDivElement = this.shadowRoot.querySelector('.slotContainer');
|
||||
loginDiv.style.opacity = '0';
|
||||
loginDiv.style.transform = 'translateY(20px)';
|
||||
loginContainerDiv.style.pointerEvents = 'none';
|
||||
slotContainerDiv.style.transform = 'translateY(20px)';
|
||||
await domtools.convenience.smartdelay.delayFor(300);
|
||||
slotContainerDiv.style.opacity = '1';
|
||||
slotContainerDiv.style.transform = 'translateY(0px)';
|
||||
await domtools.convenience.smartdelay.delayFor(300);
|
||||
slotContainerDiv.style.pointerEvents = 'all';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './dees-simple-login.js';
|
||||
3
ts_web/elements/00group-simple/index.ts
Normal file
3
ts_web/elements/00group-simple/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// Simple Components
|
||||
export * from './dees-simple-appdash/index.js';
|
||||
export * from './dees-simple-login/index.js';
|
||||
Reference in New Issue
Block a user