Files
dees-catalog/ts_web/elements/dees-table/dees-table.demo.ts

679 lines
27 KiB
TypeScript
Raw Normal View History

2023-09-12 13:42:55 +02:00
import { type ITableAction } from './dees-table.js';
import * as plugins from '../00plugins.js';
2025-06-27 17:50:54 +00:00
import { html, css, cssManager } from '@design.estate/dees-element';
2023-09-12 13:42:55 +02:00
2023-09-13 21:13:47 +02:00
interface ITableDemoData {
date: string;
amount: string;
description: string;
}
2023-09-12 13:42:55 +02:00
export const demoFunc = () => html`
<style>
2025-06-27 17:50:54 +00:00
${css`
.demoWrapper {
box-sizing: border-box;
position: absolute;
width: 100%;
height: 100%;
padding: 32px;
background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 5%)')};
overflow-y: auto;
}
.demo-container {
max-width: 1200px;
margin: 0 auto;
}
.demo-section {
margin-bottom: 48px;
}
.demo-title {
font-size: 24px;
font-weight: 600;
margin-bottom: 8px;
color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
}
.demo-description {
font-size: 14px;
color: ${cssManager.bdTheme('hsl(215.4 16.3% 46.9%)', 'hsl(215 20.2% 65.1%)')};
margin-bottom: 24px;
}
.theme-toggle {
position: fixed;
top: 16px;
right: 16px;
z-index: 1000;
}
`}
2023-09-12 13:42:55 +02:00
</style>
<div class="demoWrapper">
2025-06-27 17:50:54 +00:00
<dees-button class="theme-toggle" @click=${() => {
document.body.classList.toggle('bright');
document.body.classList.toggle('dark');
}}>Toggle Theme</dees-button>
<div class="demo-container">
<div class="demo-section">
<h2 class="demo-title">Basic Table with Actions</h2>
<p class="demo-description">A standard table with row actions, editable fields, and context menu support. Double-click on descriptions to edit. Grid lines are enabled by default.</p>
<dees-table
heading1="Current Account Statement"
heading2="Bunq - Payment Account 2 - April 2021"
.editableFields="${['description']}"
.data=${[
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Printing Paper (Office Supplies) - STAPLES BREMEN',
},
{
date: '2021-04-02',
amount: '165.65 €',
description: 'Logitech Mouse (Hardware) - logi.com OnlineShop',
},
{
date: '2021-04-03',
amount: '2999,00 €',
description: 'Macbook Pro 16inch (Hardware) - Apple.de OnlineShop',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
{
date: '2021-04-01',
amount: '2464.65 €',
description: 'Office-Supplies - STAPLES BREMEN',
},
]}
dataName="transactions"
.dataActions="${[
{
name: 'upload',
iconName: 'bell',
useTableBehaviour: 'upload',
type: ['inRow'],
actionFunc: async (optionsArg) => {
alert(optionsArg.item.amount);
},
},
{
name: 'visibility',
iconName: 'copy',
type: ['inRow'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'create new',
iconName: 'instagram',
type: ['header'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'to gallery',
iconName: 'message',
type: ['footer'],
useTableBehaviour: 'preview',
actionFunc: async (itemArg: any) => {},
},
{
name: 'copy',
iconName: 'copySolid',
type: ['contextmenu', 'inRow'],
action: async () => {
return null;
},
},
{
name: 'edit (from demo)',
iconName: 'penToSquare',
type: ['contextmenu'],
action: async () => {
return null;
},
},
{
name: 'paste',
iconName: 'pasteSolid',
type: ['contextmenu'],
action: async () => {
return null;
},
},
{
name: 'preview',
type: ['doubleClick', 'contextmenu'],
iconName: 'eye',
actionFunc: async (itemArg) => {
alert(itemArg.item.amount);
return null;
},
}
] as ITableAction[]}"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Table with Vertical Lines</h2>
<p class="demo-description">Enhanced column separation for better data tracking.</p>
<dees-table
heading1="Product Inventory"
heading2="Current stock levels across warehouses"
.showVerticalLines=${true}
.data=${[
{
product: 'MacBook Pro 16"',
warehouse_a: '45',
warehouse_b: '32',
warehouse_c: '28',
total: '105',
status: '✓ In Stock'
},
{
product: 'iPhone 15 Pro',
warehouse_a: '120',
warehouse_b: '89',
warehouse_c: '156',
total: '365',
status: '✓ In Stock'
},
{
product: 'AirPods Pro',
warehouse_a: '0',
warehouse_b: '12',
warehouse_c: '5',
total: '17',
status: '⚠ Low Stock'
},
{
product: 'iPad Air',
warehouse_a: '23',
warehouse_b: '45',
warehouse_c: '67',
total: '135',
status: '✓ In Stock'
}
]}
dataName="products"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Table with Full Grid</h2>
<p class="demo-description">Complete grid lines for maximum readability and structure.</p>
<dees-table
heading1="Server Monitoring Dashboard"
heading2="Real-time metrics across regions"
.showGrid=${true}
.data=${[
{
server: 'API-1',
region: 'US-East',
cpu: '45%',
memory: '62%',
disk: '78%',
latency: '12ms',
uptime: '99.9%',
status: '🟢 Healthy'
},
{
server: 'API-2',
region: 'EU-West',
cpu: '38%',
memory: '55%',
disk: '45%',
latency: '25ms',
uptime: '99.8%',
status: '🟢 Healthy'
},
{
server: 'DB-Master',
region: 'US-East',
cpu: '72%',
memory: '81%',
disk: '92%',
latency: '8ms',
uptime: '100%',
status: '🟡 Warning'
},
{
server: 'DB-Replica',
region: 'EU-West',
cpu: '23%',
memory: '34%',
disk: '45%',
latency: '15ms',
uptime: '99.7%',
status: '🟢 Healthy'
},
{
server: 'Cache-1',
region: 'AP-South',
cpu: '89%',
memory: '92%',
disk: '12%',
latency: '120ms',
uptime: '98.5%',
status: '🔴 Critical'
}
]}
dataName="servers"
.dataActions="${[
{
name: 'SSH Connect',
iconName: 'lucide:terminal',
type: ['inRow'],
actionFunc: async (optionsArg) => {
console.log('Connecting to:', optionsArg.item.server);
},
},
{
name: 'View Logs',
iconName: 'lucide:file-text',
type: ['inRow', 'contextmenu'],
actionFunc: async (optionsArg) => {
console.log('Viewing logs for:', optionsArg.item.server);
},
},
{
name: 'Restart Server',
iconName: 'lucide:refresh-cw',
type: ['contextmenu'],
actionFunc: async (optionsArg) => {
console.log('Restarting:', optionsArg.item.server);
},
}
] as ITableAction[]}"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Table with Horizontal Lines Only</h2>
<p class="demo-description">Emphasis on row separation without column dividers.</p>
<dees-table
heading1="Sales Performance"
heading2="Top performers this quarter"
.showHorizontalLines=${true}
.showVerticalLines=${false}
.data=${[
{
salesperson: 'Emily Johnson',
region: 'North America',
deals_closed: '42',
revenue: '$1.2M',
quota_achievement: '128%',
rating: '⭐⭐⭐⭐⭐'
},
{
salesperson: 'Michael Chen',
region: 'Asia Pacific',
deals_closed: '38',
revenue: '$980K',
quota_achievement: '115%',
rating: '⭐⭐⭐⭐⭐'
},
{
salesperson: 'Sarah Williams',
region: 'Europe',
deals_closed: '35',
revenue: '$875K',
quota_achievement: '108%',
rating: '⭐⭐⭐⭐'
},
{
salesperson: 'David Garcia',
region: 'Latin America',
deals_closed: '31',
revenue: '$750K',
quota_achievement: '95%',
rating: '⭐⭐⭐⭐'
}
]}
dataName="sales reps"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Simple Table (No Grid)</h2>
<p class="demo-description">Clean, minimal design without grid lines. Set showGrid to false to disable the default grid.</p>
<dees-table
heading1="Team Members"
heading2="Engineering Department"
.showGrid=${false}
.data=${[
{
name: 'Alice Johnson',
role: 'Lead Engineer',
email: 'alice@company.com',
location: 'San Francisco',
joined: '2020-03-15'
},
{
name: 'Bob Smith',
role: 'Senior Developer',
email: 'bob@company.com',
location: 'New York',
joined: '2019-07-22'
},
{
name: 'Charlie Davis',
role: 'DevOps Engineer',
email: 'charlie@company.com',
location: 'London',
joined: '2021-01-10'
},
{
name: 'Diana Martinez',
role: 'Frontend Developer',
email: 'diana@company.com',
location: 'Barcelona',
joined: '2022-05-18'
}
]}
dataName="team members"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Table with Custom Display Function</h2>
<p class="demo-description">Transform data for display using custom formatting.</p>
<dees-table
heading1="Sales Report"
heading2="Q4 2023 Performance"
.data=${[
{
product: 'Enterprise License',
units: 45,
revenue: 225000,
growth: 0.23,
forecast: 280000
},
{
product: 'Professional License',
units: 128,
revenue: 128000,
growth: 0.15,
forecast: 147000
},
{
product: 'Starter License',
units: 342,
revenue: 68400,
growth: 0.42,
forecast: 97000
}
]}
.displayFunction=${(item) => ({
Product: item.product,
'Units Sold': item.units.toLocaleString(),
Revenue: '$' + item.revenue.toLocaleString(),
Growth: (item.growth * 100).toFixed(1) + '%',
'Q1 2024 Forecast': '$' + item.forecast.toLocaleString()
})}
dataName="products"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Empty Table State</h2>
<p class="demo-description">How the table looks when no data is available.</p>
<dees-table
heading1="No Data Available"
heading2="This table is currently empty"
.data=${[]}
dataName="items"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Schema-First Columns (New)</h2>
<p class="demo-description">Defines columns explicitly and renders via schema. No displayFunction needed.</p>
<dees-table
heading1="Users (Schema-First)"
heading2="Columns define rendering and order"
.columns=${[
{ key: 'name', header: 'Name', sortable: true },
{ key: 'email', header: 'Email', renderer: (v: string) => html`<dees-badge>${v}</dees-badge>` },
{ key: 'joinedAt', header: 'Joined', renderer: (v: string) => new Date(v).toLocaleDateString() },
]}
.data=${[
{ name: 'Alice', email: 'alice@example.com', joinedAt: '2022-08-01' },
{ name: 'Bob', email: 'bob@example.com', joinedAt: '2021-12-11' },
{ name: 'Carol', email: 'carol@example.com', joinedAt: '2023-03-22' },
]}
dataName="users"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Partial Schema + Augment (New)</h2>
<p class="demo-description">Provides only the important columns; the rest are merged in from displayFunction.</p>
<dees-table
heading1="Users (Partial + Augment)"
heading2="Missing columns are derived"
.columns=${[
{ key: 'name', header: 'Name', sortable: true },
]}
.displayFunction=${(u: any) => ({ name: u.name, email: u.email, role: u.role })}
.augmentFromDisplayFunction=${true}
.data=${[
{ name: 'Erin', email: 'erin@example.com', role: 'Admin' },
{ name: 'Finn', email: 'finn@example.com', role: 'User' },
{ name: 'Gina', email: 'gina@example.com', role: 'User' },
]}
dataName="users"
></dees-table>
</div>
<div class="demo-section"
@selectionChange=${(e: CustomEvent) => { console.log('Selection changed', e.detail); }}
@search-changed=${(e: CustomEvent) => {
const tbl = document.getElementById('tableFilterSelectDemo') as any;
if (tbl) tbl.setFilterText(e.detail.value);
}}
@search-submit=${(e: CustomEvent) => {
const tbl = document.getElementById('tableFilterSelectDemo') as any;
if (tbl) tbl.setFilterText(e.detail.value);
}}
>
<h2 class="demo-title">Filtering + Multi-Selection (New)</h2>
<p class="demo-description">Use the search bar to filter rows; toggle selection via checkboxes. Click headers to sort.</p>
<dees-searchbar></dees-searchbar>
<div style="height: 12px"></div>
<dees-table
id="tableFilterSelectDemo"
heading1="Inventory (Filter + Select)"
heading2="Try typing to filter and selecting multiple rows"
.selectionMode=${'multi'}
.rowKey=${'sku'}
.columns=${[
{ key: 'sku', header: 'SKU', sortable: true },
{ key: 'name', header: 'Name', sortable: true },
{ key: 'stock', header: 'Stock', sortable: true },
]}
.data=${[
{ sku: 'A-100', name: 'USB-C Cable', stock: 120 },
{ sku: 'A-101', name: 'Wireless Mouse', stock: 55 },
{ sku: 'A-102', name: 'Laptop Stand', stock: 18 },
{ sku: 'B-200', name: 'Keyboard (ISO)', stock: 89 },
{ sku: 'B-201', name: 'HDMI Adapter', stock: 0 },
{ sku: 'C-300', name: 'Webcam 1080p', stock: 42 },
]}
dataName="items"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Column Filters + Sticky Header (New)</h2>
<p class="demo-description">Per-column quick filters and sticky header with internal scroll. Try filtering the Name column. Uses --table-max-height var.</p>
<style>
dees-table[sticky-header] { --table-max-height: 220px; }
</style>
<dees-table
heading1="Employees"
heading2="Quick filter per column + sticky header"
.showColumnFilters=${true}
.stickyHeader=${true}
.columns=${[
{ key: 'name', header: 'Name', sortable: true },
{ key: 'email', header: 'Email', sortable: true },
{ key: 'department', header: 'Department', sortable: true },
]}
.data=${[
{ name: 'Alice Johnson', email: 'alice@corp.com', department: 'Engineering' },
{ name: 'Bob Smith', email: 'bob@corp.com', department: 'Sales' },
{ name: 'Charlie Davis', email: 'charlie@corp.com', department: 'HR' },
{ name: 'Diana Martinez', email: 'diana@corp.com', department: 'Engineering' },
{ name: 'Ethan Brown', email: 'ethan@corp.com', department: 'Finance' },
{ name: 'Fiona Clark', email: 'fiona@corp.com', department: 'Sales' },
{ name: 'Grace Lee', email: 'grace@corp.com', department: 'Engineering' },
{ name: 'Henry Wilson', email: 'henry@corp.com', department: 'Marketing' },
{ name: 'Irene Walker', email: 'irene@corp.com', department: 'Finance' },
{ name: 'Jack Turner', email: 'jack@corp.com', department: 'Support' },
]}
dataName="employees"
></dees-table>
</div>
<div class="demo-section"
@searchRequest=${async (e: CustomEvent) => {
const { query } = e.detail || { query: '' };
const table = document.getElementById('serverSearchDemo') as any;
const baseData = [
{ id: 1, name: 'Alice', city: 'Berlin', title: 'Engineer' },
{ id: 2, name: 'Bob', city: 'Paris', title: 'Designer' },
{ id: 3, name: 'Charlie', city: 'London', title: 'Manager' },
{ id: 4, name: 'Diana', city: 'Madrid', title: 'Engineer' },
{ id: 5, name: 'Ethan', city: 'Rome', title: 'Support' },
];
// Simulate async request
await new Promise((r) => setTimeout(r, 300));
const q = String(query || '').toLowerCase();
const filtered = q
? baseData.filter((r) => Object.values(r).some((v) => String(v).toLowerCase().includes(q)))
: baseData;
table.data = filtered;
}}
>
<h2 class="demo-title">Server Search (New)</h2>
<p class="demo-description">Select Server mode, type a query, and watch the table fetch simulated results.</p>
<dees-table
id="serverSearchDemo"
heading1="People (Server Search)"
heading2="Click Search, choose Server mode, and type"
.columns=${[
{ key: 'name', header: 'Name' },
{ key: 'city', header: 'City' },
{ key: 'title', header: 'Title' },
]}
.data=${[
{ id: 1, name: 'Alice', city: 'Berlin', title: 'Engineer' },
{ id: 2, name: 'Bob', city: 'Paris', title: 'Designer' },
{ id: 3, name: 'Charlie', city: 'London', title: 'Manager' },
{ id: 4, name: 'Diana', city: 'Madrid', title: 'Engineer' },
{ id: 5, name: 'Ethan', city: 'Rome', title: 'Support' },
]}
dataName="people"
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Wide Properties + Many Actions</h2>
<p class="demo-description">A table with many columns and rich actions to stress test layout and sticky Actions.</p>
<dees-table
heading1="People Directory"
heading2="Many properties and actions"
.columns=${[
{ key: 'id', header: 'ID', sortable: true },
{ key: 'name', header: 'Name', sortable: true },
{ key: 'role', header: 'Role', sortable: true },
{ key: 'department', header: 'Department', sortable: true },
{ key: 'email', header: 'Email' },
{ key: 'phone', header: 'Phone' },
{ key: 'location', header: 'Location', sortable: true },
{ key: 'status', header: 'Status', sortable: true },
{ key: 'createdAt', header: 'Created', sortable: true },
{ key: 'updatedAt', header: 'Updated', sortable: true },
{ key: 'lastLogin', header: 'Last Login', sortable: true },
{ key: 'projects', header: 'Projects' },
{ key: 'tags', header: 'Tags' },
{ key: 'notes', header: 'Notes' },
]}
.data=${[
{ id: 1, name: 'Alice Johnson', role: 'Engineer', department: 'R&D', email: 'alice@corp.com', phone: '+1 202 555 0111', location: 'Berlin', status: 'Active', createdAt: '2023-01-12', updatedAt: '2024-05-03', lastLogin: '2024-10-01', projects: 5, tags: 'typescript, ui', notes: 'Mentor' },
{ id: 2, name: 'Bob Smith', role: 'Designer', department: 'Design', email: 'bob@corp.com', phone: '+1 202 555 0112', location: 'Paris', status: 'Active', createdAt: '2022-11-05', updatedAt: '2024-04-10', lastLogin: '2024-09-28', projects: 8, tags: 'figma, brand', notes: 'Part-time' },
{ id: 3, name: 'Charlie Davis', role: 'Manager', department: 'Ops', email: 'charlie@corp.com', phone: '+1 202 555 0113', location: 'London', status: 'On Leave', createdAt: '2021-04-21', updatedAt: '2024-02-15', lastLogin: '2024-08-12', projects: 3, tags: 'sre, leadership', notes: '' },
{ id: 4, name: 'Diana Martinez', role: 'Engineer', department: 'Platform', email: 'diana@corp.com', phone: '+1 202 555 0114', location: 'Madrid', status: 'Active', createdAt: '2020-06-30', updatedAt: '2024-06-25', lastLogin: '2024-10-02', projects: 6, tags: 'node, api', notes: 'On-call' },
{ id: 5, name: 'Ethan Brown', role: 'Support', department: 'CS', email: 'ethan@corp.com', phone: '+1 202 555 0115', location: 'Rome', status: 'Inactive', createdAt: '2019-09-18', updatedAt: '2024-03-09', lastLogin: '2024-06-19', projects: 2, tags: 'zendesk', notes: 'Rehire' },
{ id: 6, name: 'Fiona Clark', role: 'QA', department: 'QA', email: 'fiona@corp.com', phone: '+1 202 555 0116', location: 'Vienna', status: 'Active', createdAt: '2022-03-14', updatedAt: '2024-03-01', lastLogin: '2024-09-07', projects: 7, tags: 'playwright', notes: '' },
]}
.dataActions=${[
{ name: 'View', iconName: 'lucide:eye', type: ['inRow', 'contextmenu'], actionFunc: async ({ item }) => { console.log('view', item); } },
{ name: 'Edit', iconName: 'lucide:edit', type: ['inRow', 'contextmenu'], actionFunc: async ({ item }) => { console.log('edit', item); } },
{ name: 'Delete', iconName: 'lucide:trash', type: ['inRow', 'contextmenu'], actionFunc: async ({ item }) => { console.log('delete', item); } },
{ name: 'Message', iconName: 'lucide:message-square', type: ['inRow'], actionFunc: async ({ item }) => { console.log('message', item); } },
{ name: 'History', iconName: 'lucide:clock', type: ['inRow'], actionFunc: async ({ item }) => { console.log('history', item); } },
{ name: 'Add New', iconName: 'lucide:plus', type: ['header'], actionFunc: async ({ table }) => { console.log('add'); } },
{ name: 'Export CSV', iconName: 'lucide:download', type: ['header'], actionFunc: async ({ table }) => { console.log('export'); } },
{ name: 'Bulk Delete', iconName: 'lucide:trash-2', type: ['footer'], actionFunc: async ({ table }) => { console.log('bulk delete'); } },
] as ITableAction[]}
></dees-table>
</div>
<div class="demo-section">
<h2 class="demo-title">Scrollable Small Height</h2>
<p class="demo-description">Same as above, but with many items and a small fixed height to force vertical scrolling inside the table. Actions remain visible on the right; horizontal scroll appears if needed.</p>
<style>
#scrollSmallHeight { --table-max-height: 240px; }
</style>
<dees-table
id="scrollSmallHeight"
.stickyHeader=${true}
heading1="People Directory (Scrollable)"
heading2="Forced scrolling with many items"
.columns=${[
{ key: 'id', header: 'ID', sortable: true },
{ key: 'name', header: 'Name', sortable: true },
{ key: 'role', header: 'Role', sortable: true },
{ key: 'department', header: 'Department', sortable: true },
{ key: 'email', header: 'Email' },
{ key: 'phone', header: 'Phone' },
{ key: 'location', header: 'Location', sortable: true },
{ key: 'status', header: 'Status', sortable: true },
{ key: 'createdAt', header: 'Created', sortable: true },
{ key: 'updatedAt', header: 'Updated', sortable: true },
{ key: 'lastLogin', header: 'Last Login', sortable: true },
{ key: 'projects', header: 'Projects' },
{ key: 'tags', header: 'Tags' },
{ key: 'notes', header: 'Notes' },
]}
.data=${Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: `User ${i + 1}`,
role: ['Engineer','Designer','Manager','QA','Support'][i % 5],
department: ['R&D','Design','Ops','QA','CS'][i % 5],
email: `user${i+1}@corp.com`,
phone: `+1 202 555 ${String(1000 + i).slice(-4)}`,
location: ['Berlin','Paris','London','Madrid','Rome'][i % 5],
status: ['Active','Inactive','On Leave'][i % 3],
createdAt: `2023-${String((i%12)+1).padStart(2,'0')}-${String((i%28)+1).padStart(2,'0')}`,
updatedAt: `2024-${String(((i+3)%12)+1).padStart(2,'0')}-${String(((i+7)%28)+1).padStart(2,'0')}`,
lastLogin: `2024-${String(((i+6)%12)+1).padStart(2,'0')}-${String(((i+10)%28)+1).padStart(2,'0')}`,
projects: (i % 12),
tags: i % 2 ? 'typescript' : 'design',
notes: i % 3 ? '' : 'Note',
}))}
.dataActions=${[
{ name: 'View', iconName: 'lucide:eye', type: ['inRow'], actionFunc: async ({ item }) => {} },
{ name: 'Edit', iconName: 'lucide:edit', type: ['inRow'], actionFunc: async ({ item }) => {} },
{ name: 'Delete', iconName: 'lucide:trash', type: ['inRow'], actionFunc: async ({ item }) => {} },
] as ITableAction[]}
></dees-table>
</div>
2025-06-27 17:50:54 +00:00
</div>
2023-09-12 13:42:55 +02:00
</div>
`;