84 lines
3.2 KiB
JavaScript
84 lines
3.2 KiB
JavaScript
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
// DONAU2SPACE // DEV ENTITY — Utilities
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
export const $ = (sel, ctx = document) => ctx.querySelector(sel);
|
|
export const $$ = (sel, ctx = document) => [...ctx.querySelectorAll(sel)];
|
|
|
|
export const sleep = ms => new Promise(r => setTimeout(r, ms));
|
|
export const random = (min, max) => Math.random() * (max - min) + min;
|
|
export const randInt = (min, max) => (random(min, max) | 0);
|
|
export const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
export const lerp = (a, b, t) => a + (b - a) * t;
|
|
export const pick = arr => arr[(Math.random() * arr.length) | 0];
|
|
|
|
export function esc(s) {
|
|
const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
|
|
return (s ?? '').replace(/[&<>"']/g, m => map[m]);
|
|
}
|
|
|
|
export function nowISO() {
|
|
return new Date().toISOString().replace('T', ' ').replace('Z', ' UTC');
|
|
}
|
|
|
|
export function timeGreeting() {
|
|
const h = new Date().getHours();
|
|
if (h < 5) return 'Deep night. Perfect time for dev.';
|
|
if (h < 8) return 'Early bird mode. Coffee recommended.';
|
|
if (h < 12) return 'Morning session. Systems nominal.';
|
|
if (h < 14) return 'Midday. Hunger may affect judgment.';
|
|
if (h < 18) return 'Afternoon cycle. Productivity variable.';
|
|
if (h < 22) return 'Evening mode. Creative peak for some.';
|
|
return 'Late night. Here be dragons.';
|
|
}
|
|
|
|
// ── Event Bus ──────────────────────────────────
|
|
const listeners = {};
|
|
|
|
export const bus = {
|
|
on(event, fn) {
|
|
(listeners[event] = listeners[event] || []).push(fn);
|
|
return () => this.off(event, fn);
|
|
},
|
|
off(event, fn) {
|
|
listeners[event] = (listeners[event] || []).filter(f => f !== fn);
|
|
},
|
|
emit(event, data) {
|
|
(listeners[event] || []).forEach(fn => {
|
|
try { fn(data); } catch (e) { console.warn(`[bus:${event}]`, e); }
|
|
});
|
|
}
|
|
};
|
|
|
|
// ── Storage helpers ────────────────────────────
|
|
const PREFIX = 'd2s_';
|
|
|
|
export const store = {
|
|
get(key, fallback = null) {
|
|
try {
|
|
const raw = localStorage.getItem(PREFIX + key);
|
|
return raw !== null ? JSON.parse(raw) : fallback;
|
|
} catch { return fallback; }
|
|
},
|
|
set(key, val) {
|
|
try { localStorage.setItem(PREFIX + key, JSON.stringify(val)); } catch {}
|
|
},
|
|
remove(key) {
|
|
try { localStorage.removeItem(PREFIX + key); } catch {}
|
|
}
|
|
};
|
|
|
|
// ── DOM helper ─────────────────────────────────
|
|
export function el(tag, attrs = {}, children = []) {
|
|
const node = document.createElement(tag);
|
|
for (const [k, v] of Object.entries(attrs)) {
|
|
if (k === 'className') node.className = v;
|
|
else if (k === 'textContent') node.textContent = v;
|
|
else if (k.startsWith('on')) node.addEventListener(k.slice(2).toLowerCase(), v);
|
|
else node.setAttribute(k, v);
|
|
}
|
|
for (const c of children) {
|
|
node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c);
|
|
}
|
|
return node;
|
|
}
|