Page MenuHomePhorge

index.js
No OneTemporary

Size
17 KB
Referenced Files
None
Subscribers
None

index.js

import { Screen, List, ProgressBar, Input, Table, colors, box, keys, codes, modal, confirm, pad, padCenter, truncate } from './tuey.js';
const screen = new Screen({ fullscreen: true, hideCursor: true });
const tasks = [
{ id: 1, name: 'Build TUI library', status: 'done', priority: 'high' },
{ id: 2, name: 'Add modal support', status: 'done', priority: 'high' },
{ id: 3, name: 'Implement themes', status: 'in_progress', priority: 'medium' },
{ id: 4, name: 'Write documentation', status: 'todo', priority: 'low' },
{ id: 5, name: 'Add animation support', status: 'todo', priority: 'low' },
{ id: 6, name: 'Create widget system', status: 'in_progress', priority: 'medium' },
{ id: 7, name: 'Performance optimization', status: 'todo', priority: 'high' },
{ id: 8, name: 'Add mouse support', status: 'todo', priority: 'low' },
{ id: 9, name: 'Create color picker', status: 'todo', priority: 'medium' },
{ id: 10, name: 'Build file browser', status: 'in_progress', priority: 'high' }
];
const logs = [
{ time: '10:23:45', level: 'INFO', message: 'Application started' },
{ time: '10:23:46', level: 'DEBUG', message: 'Loading configuration...' },
{ time: '10:23:47', level: 'INFO', message: 'Config loaded successfully' },
{ time: '10:23:48', level: 'WARN', message: 'Cache directory not found, creating...' },
{ time: '10:23:49', level: 'INFO', message: 'Cache initialized' },
{ time: '10:24:01', level: 'DEBUG', message: 'Connecting to database...' },
{ time: '10:24:02', level: 'INFO', message: 'Database connection established' },
{ time: '10:24:05', level: 'ERROR', message: 'Failed to load plugin: missing-plugin' },
{ time: '10:24:06', level: 'WARN', message: 'Running with reduced functionality' },
{ time: '10:24:10', level: 'INFO', message: 'Ready to accept connections' }
];
let state = {
view: 'dashboard',
taskFilter: 'all',
searchMode: false,
searchQuery: '',
cpuUsage: 45,
memUsage: 62,
diskUsage: 78,
networkIn: 0,
networkOut: 0
};
const taskList = new List({
items: tasks,
x: 2,
y: 5,
width: 50,
height: 12,
selectedStyle: colors.bgBlue + colors.bold + colors.white,
renderItem: task => {
const statusIcon =
task.status === 'done'
? `${colors.green}${codes.reset}`
: task.status === 'in_progress'
? `${colors.yellow}${codes.reset}`
: `${colors.gray}${codes.reset}`;
const priorityColor = task.priority === 'high' ? colors.red : task.priority === 'medium' ? colors.yellow : colors.gray;
return ` ${statusIcon} ${task.name} ${priorityColor}[${task.priority}]${codes.reset}`;
}
});
const logList = new List({
items: logs,
x: 2,
y: 5,
width: screen.width - 4,
height: 15,
selectedStyle: colors.bgGray + colors.white,
renderItem: log => {
const levelColor = log.level === 'ERROR' ? colors.red : log.level === 'WARN' ? colors.yellow : log.level === 'DEBUG' ? colors.cyan : colors.green;
return `${colors.dim}${log.time}${codes.reset} ${levelColor}${pad(log.level, 5)}${codes.reset} ${log.message}`;
}
});
const cpuBar = new ProgressBar({ width: 25, filledStyle: colors.green, showPercent: true });
const memBar = new ProgressBar({ width: 25, filledStyle: colors.blue, showPercent: true });
const diskBar = new ProgressBar({ width: 25, filledStyle: colors.yellow, showPercent: true });
const searchInput = new Input({ width: 30, placeholder: 'Search tasks...' });
function filterTasks() {
let filtered = tasks;
if (state.taskFilter !== 'all') {
filtered = filtered.filter(t => t.status === state.taskFilter);
}
if (state.searchQuery) {
const q = state.searchQuery.toLowerCase();
filtered = filtered.filter(t => t.name.toLowerCase().includes(q));
}
taskList.setItems(filtered);
}
function drawHeader() {
const title = ' TUI Demo - Press ? for help ';
const w = screen.width;
screen.write(0, 0, colors.bgBlue + colors.bold + colors.white + padCenter(title, w) + codes.reset);
const tabs = [
{ key: '1', name: 'Dashboard', view: 'dashboard' },
{ key: '2', name: 'Tasks', view: 'tasks' },
{ key: '3', name: 'Logs', view: 'logs' },
{ key: '4', name: 'Settings', view: 'settings' }
];
let tabLine = ' ';
for (const tab of tabs) {
const isActive = state.view === tab.view;
const style = isActive ? colors.bgWhite + colors.black + colors.bold : colors.dim;
tabLine += `${style} ${tab.key}:${tab.name} ${codes.reset} `;
}
screen.write(0, 1, tabLine);
}
function drawFooter() {
const w = screen.width;
const h = screen.height;
const help =
state.view === 'tasks' ? ' ↑↓:Navigate Enter:Toggle a:All t:Todo p:Progress d:Done /:Search q:Quit ' : ' 1-4:Switch tabs ?:Help q:Quit ';
screen.write(0, h - 1, colors.bgGray + colors.white + pad(help, w) + codes.reset);
}
function drawDashboard() {
const w = screen.width;
screen.write(2, 3, colors.bold + colors.cyan + '┌─ System Status ─────────────────────────┐' + codes.reset);
cpuBar.setValue(state.cpuUsage);
memBar.setValue(state.memUsage);
diskBar.setValue(state.diskUsage);
screen.write(2, 4, colors.cyan + '│' + codes.reset);
screen.write(4, 4, `CPU: ${cpuBar.render()}`);
screen.write(45, 4, colors.cyan + '│' + codes.reset);
screen.write(2, 5, colors.cyan + '│' + codes.reset);
screen.write(4, 5, `Memory: ${memBar.render()}`);
screen.write(45, 5, colors.cyan + '│' + codes.reset);
screen.write(2, 6, colors.cyan + '│' + codes.reset);
screen.write(4, 6, `Disk: ${diskBar.render()}`);
screen.write(45, 6, colors.cyan + '│' + codes.reset);
screen.write(2, 7, colors.cyan + '└──────────────────────────────────────────┘' + codes.reset);
screen.write(2, 9, colors.bold + colors.yellow + '┌─ Task Summary ──────────────────────────┐' + codes.reset);
const done = tasks.filter(t => t.status === 'done').length;
const inProgress = tasks.filter(t => t.status === 'in_progress').length;
const todo = tasks.filter(t => t.status === 'todo').length;
screen.write(2, 10, colors.yellow + '│' + codes.reset);
screen.write(
4,
10,
`${colors.green}✓ Completed:${codes.reset} ${done} ${colors.yellow}◐ In Progress:${codes.reset} ${inProgress} ${colors.gray}○ Todo:${codes.reset} ${todo}`
);
screen.write(45, 10, colors.yellow + '│' + codes.reset);
const progress = new ProgressBar({
value: done,
max: tasks.length,
width: 35,
filledStyle: colors.green,
showPercent: true
});
screen.write(2, 11, colors.yellow + '│' + codes.reset);
screen.write(4, 11, `Progress: ${progress.render()}`);
screen.write(45, 11, colors.yellow + '│' + codes.reset);
screen.write(2, 12, colors.yellow + '└──────────────────────────────────────────┘' + codes.reset);
screen.write(2, 14, colors.bold + colors.magenta + '┌─ Recent Activity ───────────────────────┐' + codes.reset);
for (let i = 0; i < Math.min(5, logs.length); i++) {
const log = logs[logs.length - 1 - i];
const levelColor = log.level === 'ERROR' ? colors.red : log.level === 'WARN' ? colors.yellow : colors.green;
screen.write(2, 15 + i, colors.magenta + '│' + codes.reset);
screen.write(4, 15 + i, `${colors.dim}${log.time}${codes.reset} ${levelColor}${log.level}${codes.reset} ${truncate(log.message, 30)}`);
screen.write(45, 15 + i, colors.magenta + '│' + codes.reset);
}
screen.write(2, 20, colors.magenta + '└──────────────────────────────────────────┘' + codes.reset);
if (w > 55) {
screen.box(50, 3, 30, 10, box.rounded, 'Quick Stats', colors.bold + colors.green);
screen.write(52, 5, `${colors.bold}Uptime:${codes.reset} 2h 34m`);
screen.write(52, 6, `${colors.bold}Network In:${codes.reset} ${state.networkIn} KB/s`);
screen.write(52, 7, `${colors.bold}Network Out:${codes.reset} ${state.networkOut} KB/s`);
screen.write(52, 8, `${colors.bold}Active Users:${codes.reset} 42`);
screen.write(52, 9, `${colors.bold}Requests/s:${codes.reset} 1,234`);
screen.write(52, 10, `${colors.bold}Errors:${codes.reset} ${colors.red}3${codes.reset}`);
}
}
function drawTasks() {
const filterLabel =
state.taskFilter === 'all' ? 'All' : state.taskFilter === 'todo' ? 'Todo' : state.taskFilter === 'in_progress' ? 'In Progress' : 'Done';
screen.write(2, 3, colors.bold + `Tasks [${filterLabel}] - ${taskList.items.length} items` + codes.reset);
if (state.searchMode) {
screen.write(2, 4, colors.cyan + 'Search: ' + codes.reset + searchInput.render());
}
taskList.y = state.searchMode ? 6 : 5;
taskList.height = state.searchMode ? screen.height - 9 : screen.height - 8;
taskList.width = Math.min(60, screen.width - 4);
taskList.render(screen);
const selected = taskList.getSelected();
if (selected && screen.width > 65) {
const detailX = taskList.width + 5;
screen.box(detailX, 5, 35, 12, box.rounded, 'Details', colors.bold + colors.cyan);
screen.write(detailX + 2, 7, `${colors.bold}ID:${codes.reset} ${selected.id}`);
screen.write(detailX + 2, 8, `${colors.bold}Name:${codes.reset} ${truncate(selected.name, 25)}`);
screen.write(detailX + 2, 9, `${colors.bold}Status:${codes.reset} ${selected.status}`);
screen.write(detailX + 2, 10, `${colors.bold}Priority:${codes.reset} ${selected.priority}`);
screen.write(detailX + 2, 12, colors.dim + 'Enter to toggle status' + codes.reset);
screen.write(detailX + 2, 13, colors.dim + 'D to delete task' + codes.reset);
screen.write(detailX + 2, 14, colors.dim + 'N to add new task' + codes.reset);
}
}
function drawLogs() {
screen.write(2, 3, colors.bold + `System Logs - ${logs.length} entries` + codes.reset);
logList.width = screen.width - 4;
logList.height = screen.height - 8;
logList.render(screen);
}
function drawSettings() {
screen.write(2, 3, colors.bold + colors.cyan + 'Settings' + codes.reset);
const table = new Table({
x: 2,
y: 5,
width: 60,
columns: [
{ key: 'setting', header: 'Setting' },
{ key: 'value', header: 'Value' },
{ key: 'description', header: 'Description' }
],
rows: [
{ setting: 'Theme', value: 'Dark', description: 'UI color scheme' },
{ setting: 'Refresh Rate', value: '1000ms', description: 'Dashboard update interval' },
{ setting: 'Log Level', value: 'INFO', description: 'Minimum log level to display' },
{ setting: 'Notifications', value: 'Enabled', description: 'Show system notifications' },
{ setting: 'Auto-save', value: 'On', description: 'Automatically save changes' }
],
borderStyle: box.rounded,
headerStyle: colors.bold + colors.cyan
});
table.render(screen);
screen.write(2, 15, colors.dim + 'Press Enter on a setting to modify it' + codes.reset);
}
function render() {
screen.clear();
drawHeader();
switch (state.view) {
case 'dashboard':
drawDashboard();
break;
case 'tasks':
drawTasks();
break;
case 'logs':
drawLogs();
break;
case 'settings':
drawSettings();
break;
}
drawFooter();
screen.render();
}
function showHelp() {
modal(screen, {
id: 'help',
width: 50,
height: 18,
title: 'Keyboard Shortcuts',
titleStyle: colors.bold + colors.cyan,
borderStyle: box.double,
onKey: key => {
if (key === keys.ESCAPE || key === keys.ENTER || key === '?') {
screen.popModal('help');
render();
}
return false;
},
render: (buf, w, _h, ox, oy) => {
const shortcuts = [
['1-4', 'Switch between tabs'],
['↑/↓ or j/k', 'Navigate lists'],
['Enter', 'Select/Toggle item'],
['/', 'Search (in Tasks)'],
['Escape', 'Cancel/Close'],
['a', 'Show all tasks'],
['t', 'Filter: Todo only'],
['p', 'Filter: In Progress'],
['d', 'Filter: Done'],
['m', 'Show memory stats'],
['?', 'Show this help'],
['q', 'Quit application']
];
for (let i = 0; i < shortcuts.length; i++) {
const [key, desc] = shortcuts[i];
buf.writeStyled(ox, oy + i + 1, ` ${colors.cyan}${pad(key, 12)}${codes.reset} ${desc}`);
}
buf.writeStyled(ox, oy + shortcuts.length + 2, colors.dim + padCenter('Press Escape to close', w) + codes.reset);
}
});
screen.render();
}
function showMemoryModal() {
const fmt = bytes => {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
return (bytes / 1024 / 1024).toFixed(2) + ' MB';
};
modal(screen, {
id: 'memory',
width: 40,
height: 14,
title: 'Memory Usage',
titleStyle: colors.bold + colors.yellow,
borderStyle: box.rounded,
onKey: key => {
if (key === 'm' || key === keys.ESCAPE) {
screen.popModal('memory');
render();
} else if (key === 'g') {
Ant.gc();
screen.popModal('memory');
showMemoryModal();
}
return false;
},
render: (buf, _w, _h, ox, oy) => {
const mem = Ant.stats();
buf.writeStyled(ox, oy + 1, `${colors.cyan}Arena${codes.reset}`);
buf.writeStyled(ox, oy + 2, ` Used: ${colors.bold}${fmt(mem.arenaUsed)}${codes.reset}`);
buf.writeStyled(ox, oy + 3, ` Size: ${colors.bold}${fmt(mem.arenaSize)}${codes.reset}`);
buf.writeStyled(ox, oy + 5, `${colors.cyan}Process${codes.reset}`);
buf.writeStyled(ox, oy + 6, ` RSS: ${colors.bold}${fmt(mem.rss)}${codes.reset}`);
buf.writeStyled(ox, oy + 8, `${colors.cyan}C Stack${codes.reset}`);
buf.writeStyled(ox, oy + 9, ` Max: ${colors.bold}${fmt(mem.cstack)}${codes.reset}`);
buf.writeStyled(ox, oy + 11, colors.dim + ' g: Run GC m/Esc: Close' + codes.reset);
}
});
screen.render();
}
function handleKey(key) {
if (screen.hasModal()) return;
if (state.searchMode) {
if (key === keys.ESCAPE) {
state.searchMode = false;
state.searchQuery = '';
searchInput.clear();
filterTasks();
} else if (key === keys.ENTER) {
state.searchMode = false;
state.searchQuery = searchInput.value;
filterTasks();
} else {
searchInput.handleKey(key);
state.searchQuery = searchInput.value;
filterTasks();
}
render();
return;
}
switch (key) {
case 'q':
case keys.CTRL_C:
confirm(screen, {
title: 'Quit',
message: 'Are you sure you want to quit?'
}).then(confirmed => {
if (confirmed) screen.exit(0);
render();
});
return;
case '1':
state.view = 'dashboard';
render();
break;
case '2':
state.view = 'tasks';
render();
break;
case '3':
state.view = 'logs';
render();
break;
case '4':
state.view = 'settings';
render();
break;
case '?':
showHelp();
break;
case 'm':
showMemoryModal();
break;
case keys.UP:
case 'k':
if (state.view === 'tasks') taskList.selectPrev();
else if (state.view === 'logs') logList.selectPrev();
render();
break;
case keys.DOWN:
case 'j':
if (state.view === 'tasks') taskList.selectNext();
else if (state.view === 'logs') logList.selectNext();
render();
break;
case keys.PAGE_UP:
if (state.view === 'tasks') taskList.pageUp();
else if (state.view === 'logs') logList.pageUp();
render();
break;
case keys.PAGE_DOWN:
if (state.view === 'tasks') taskList.pageDown();
else if (state.view === 'logs') logList.pageDown();
render();
break;
case keys.ENTER:
if (state.view === 'tasks') {
const task = taskList.getSelected();
if (task) {
task.status = task.status === 'done' ? 'todo' : task.status === 'todo' ? 'in_progress' : 'done';
filterTasks();
}
}
render();
break;
case '/':
if (state.view === 'tasks') {
state.searchMode = true;
searchInput.clear();
}
render();
break;
case 'a':
if (state.view === 'tasks') {
state.taskFilter = 'all';
filterTasks();
render();
}
break;
case 't':
if (state.view === 'tasks') {
state.taskFilter = 'todo';
filterTasks();
render();
}
break;
case 'p':
if (state.view === 'tasks') {
state.taskFilter = 'in_progress';
filterTasks();
render();
}
break;
case 'd':
if (state.view === 'tasks') {
state.taskFilter = 'done';
filterTasks();
render();
}
break;
}
}
screen.onKey(handleKey);
screen.onResize(() => {
render();
});
setInterval(() => {
state.cpuUsage = Math.max(5, Math.min(95, state.cpuUsage + (Math.random() - 0.5) * 10));
state.memUsage = Math.max(20, Math.min(90, state.memUsage + (Math.random() - 0.5) * 5));
state.networkIn = Math.floor(Math.random() * 500);
state.networkOut = Math.floor(Math.random() * 200);
if (state.view === 'dashboard' && !screen.hasModal()) {
render();
}
}, 1000);
screen.start();
render();

File Metadata

Mime Type
application/javascript
Expires
Fri, Mar 27, 1:02 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
513128
Default Alt Text
index.js (17 KB)

Event Timeline