Overview

Typed factories live on the atom namespace (atom.number, atom.bool, atom.string, atom.array, atom.object). Each returns a normal atom plus domain methods that finish with an internal set/update so subscribers notify.

Pure read helpers (has, find, keys, isEmpty, …) do not notify — they only register a dependency when you also read the atom via () / .get() in a reactive context (or when a mutator already notified).

For keyed UI lists, stacks, queues, and native Map/Set, see Lists, stacks, maps.

Factory vs plain atom

API
Extra
Prefer when
atom(0) Core only Fine when set/updater is enough.
atom.number(0) incr / decr / clamp Counters and clamped ranges.
atom.array([]) push / render / … Lists with helpers; string id or index keys.
atom.list([]) Keyed rows Dedicated leaf — unique readonly keys.

number / bool / string

Small helpers for common scalar mutations — all notify like set().

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

const App = () => {
const n = atom.number(5);
const on = atom.bool(true);
const s = atom.string(' mates ');

return () => html`
<div class="m-col m-gap">
<div class="m-grid m-grid-cols-3 m-gap">
<div class="card card-body center">
<span class="overline">number</span>
<span class="card-title">${n()}</span>
</div>
<div class="card card-body center">
<span class="overline">bool</span>
<span class="card-title">${on()}</span>
</div>
<div class="card card-body center">
<span class="overline">string</span>
<span class="card-title">"${s()}" (${s.length})</span>
</div>
</div>
<div class="m-flex m-items-center m-justify-center m-gap-sm">
<button class="btn-primary" @click=${() => n.incr()}>incr</button>
<button @click=${() => n.decr()}>decr</button>
<button @click=${() => n.clamp(0, 10)}>clamp 0–10</button>
<button @click=${() => on.toggle()}>toggle</button>
<button @click=${() => s.trim()}>trim</button>
<button @click=${() => s.append('!')}>append !</button>
</div>
</div>
`;
};
renderApp(App, document.getElementById('app'));

array + object

Collection helpers + render(). addItem stamps id on plain objects when missing.

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

const App = () => {
const todos = atom.array([
{ id: '1', text: 'Ship docs', done: false },
]);
const meta = atom.object({ owner: 'Ada', tags: 1 });

return () => html`
<div class="m-col m-gap">
<ul class="muted">
${todos.render((t) => html`
<li>
<label>
<input type="checkbox" .checked=${t.done}
@change=${() => todos.updateItem(t.id, (row) => { row.done = !row.done; })} />
${t.text}
</label>
</li>
`, (t) => t.id)}
</ul>
<div class="m-flex m-items-center m-justify-center m-gap-sm">
<button class="btn-primary" @click=${() =>
todos.addItem({ text: 'New item', done: false })
}>addItem</button>
<button @click=${() => todos.clear()}>clear</button>
<button @click=${() => meta.setItem('tags', meta().tags + 1)}>
tags=${meta().tags}
</button>
</div>
<p class="muted m-t-5">size=${todos.size} · empty=${todos.isEmpty}</p>
</div>
`;
};
renderApp(App, document.getElementById('app'));