Overview

Small helpers you reach for constantly: identity generation, deep copy/freeze, emptiness checks, idle scheduling, cookie parsing, and timing wrappers.

debounce and throttle return enhanced functions with .cancel() and .flush() — create them once outside the template. Runtime probes like isAtom live on Type Guards.

UUID generation & debounce

Generate RFC 4122 UUIDs on demand and observe debounce — the bottom value only updates 400 ms after you stop typing.

import { html, atom, renderApp, uuid, debounce } from 'mates';

const App = () => {
const ids = atom([uuid()]);
const search = atom('');
const debouncedSearch = atom('');

const doSearch = debounce((q) => debouncedSearch.set(q), 400);

return () => html`
<div class="m-col m-gap">
<div class="m-flex m-gap-sm m-items-center">
<button class="btn-primary" @click=${() => ids.set(prev => [...prev, uuid()])}>
Generate UUID
</button>
<button class="btn-ghost" @click=${() => ids.set([uuid()])}>Reset</button>
</div>
<div class="card card-body">
<span class="overline">Generated IDs</span>
${ids().map(id => html`<div class="mono">${id}</div>`)}
</div>
<div class="m-col m-gap m-gap-sm">
<input
.value=${search()}
@input=${e => { search.set(e.target.value); doSearch(e.target.value); }}
placeholder="Type to test debounce (400ms)…"
/>
<div class="m-flex m-gap-sm m-items-center">
<span class="label">Typed:</span> <span>${search() || '—'}</span>
</div>
<div class="m-flex m-gap-sm m-items-center">
<span class="label">Debounced:</span>
<span>${debouncedSearch() || '—'}</span>
</div>
</div>
</div>

deepClone / deepFreeze / isEmpty

Clone mutates independently; freeze blocks further edits.

import { html, atom, renderApp, deepClone, deepFreeze, isEmpty } from 'mates';

const App = () => {
const note = atom('idle');

const run = () => {
const src = { nested: [1, 2], ok: true };
const copy = deepClone(src);
copy.nested.push(3);
deepFreeze(copy);
let froze = false;
try { copy.nested.push(4); } catch { froze = true; }
note.set(
'empty? ' + isEmpty({}) +
' | clone grew to ' + copy.nested.length +
' | freeze ' + (froze ? 'ok' : 'skipped')
);
};

return () => html`
<div class="m-col m-gap">
<button class="btn-primary" @click=${run}>deepClone + deepFreeze + isEmpty</button>
<p class="muted">${note()}</p>
</div>
`;
};
renderApp(App, document.getElementById('app'));