map() Insert
map() Insert demo built with Expressive MVC - the complete source below runs as an editable sandbox when JavaScript is enabled.
App.tsx
import './App.css';
import { Component, map } from '@expressive/react';
// `map<K, V>()` is the insert mode: a reactive Map of values you place by
// key with `set(key, value)` - no factory, no spawning. Bumping one key
// notifies only that entry; adding or removing a key notifies shape.
export default class Inventory extends Component {
stock = map<string, number>();
item = '';
protected new() {
this.stock.set('apples', 3);
this.stock.set('bread', 1);
this.stock.set('milk', 2);
}
add(name = this.item) {
name = name.trim().toLowerCase();
if (!name) return;
this.stock.set(name, (this.stock.get(name) ?? 0) + 1);
this.item = '';
}
render() {
const { stock, item } = this;
const total = [...stock.values()].reduce((sum, n) => sum + n, 0);
return (
<div className="container inv">
<h1>Reactive Map</h1>
<p>
<code>map<string, number>()</code> keys values you insert with{' '}
<code>set(key, value)</code>. Re-adding a name bumps its count in
place.
</p>
<ul className="stock">
{[...stock].map(([name, qty]) => (
<li key={name}>
<span className="name">{name}</span>
<span className="qty">
<button onClick={() => stock.set(name, Math.max(0, qty - 1))}>−</button>
<output>{qty}</output>
<button onClick={() => stock.set(name, qty + 1)}>+</button>
</span>
</li>
))}
</ul>
<form
onSubmit={(e) => {
e.preventDefault();
this.add();
}}>
<input
value={item}
placeholder="Add or bump an item…"
onChange={(e) => (this.item = e.target.value)}
/>
<button type="submit">Add</button>
</form>
<footer>
<small>{stock.size} items · {total} in stock</small>
</footer>
</div>
);
}
}
App.css
.inv {
max-width: 26rem;
}
.stock {
display: flex;
flex-direction: column;
gap: var(--s2);
width: 100%;
margin: 0;
padding: 0;
list-style: none;
}
.stock li {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s3);
padding: var(--s2) var(--s3);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--r);
cursor: default;
}
.stock .name {
font-weight: 500;
text-transform: capitalize;
}
.qty {
display: flex;
align-items: center;
gap: var(--s2);
}
.qty button {
width: 1.75rem;
height: 1.75rem;
padding: 0;
font-family: var(--font-mono);
line-height: 1;
}
.qty output {
min-width: 1.5ch;
font-family: var(--font-mono);
font-size: var(--t-lg);
text-align: center;
color: var(--accent);
}
.inv form {
display: flex;
gap: var(--s2);
width: 100%;
}
.inv form button {
flex: 0 0 auto;
}