/// import { Cell, Default, derive, handler, NAME, recipe, str, Stream, UI, } from "commontools"; // How many times to increment per click const INCREMENTS_PER_CLICK = 50; interface RecipeState { value: Default; } interface RecipeOutput { value: Default; increment: Stream; decrement: Stream; } // Inline handlers to avoid import resolution issues const increment = handler< unknown, { value: Cell } >( (_args, state) => { // Increment multiple times per click to trigger derive() multiple times for (let i = 0; i < INCREMENTS_PER_CLICK; i++) { state.value.set(state.value.get() + 1); } }, ); const decrement = handler< unknown, { value: Cell } >( (_args, state) => { state.value.set(state.value.get() - 1); }, ); function nth(value: number) { if (value === 1) return "1st"; if (value === 2) return "2nd"; if (value === 3) return "3rd"; return `${value}th`; } function previous(value: number) { return value - 1; } export default recipe("Counter", (state) => { const array = derive(state.value, (value: number) => { // Clamp to prevent negative array length const length = Math.max(0, value); return new Array(length).fill(0); }); return { [NAME]: str`Simple counter: ${state.value}`, [UI]: ( dec to {previous(state.value)} Counter is the {nth(state.value)} number inc to {state.value + 1} {array.map((v: number, i: number) => {v % 10})} ), value: state.value, increment: increment(state), decrement: decrement(state), }; });