///
/**
* TEST PATTERN: Pattern Composition with Shared Cell References
*
* CLAIM: "Both patterns receive the same `items` cell reference... Changes in
* one view automatically update the other (they share the same cell)"
* SOURCE: docs/common/PATTERNS.md, patterns.md folk wisdom
*
* WHAT THIS TESTS:
* Two sub-patterns (BasicList and CategoryList) both receive the same `items`
* cell. When you modify data through one pattern's UI, we verify whether the
* other pattern's UI updates automatically.
*
* EXPECTED BEHAVIOR IF CLAIM IS TRUE:
* 1. Adding an item via BasicList's input updates CategoryList instantly
* 2. Toggling done state in either view updates the other view
* 3. Removing an item from either view removes it from both
* 4. The cell reference is truly shared, not copied
*
* MANUAL VERIFICATION STEPS:
* 1. Note the items shown in both "Basic List" and "Category List" sections
* 2. Add a new item using "Basic List" input with category
* 3. Verify it appears immediately in BOTH views
* 4. Check an item as done in "Basic List"
* 5. Verify it shows as done (strikethrough) in "Category List"
* 6. Remove an item from "Category List" using x button
* 7. Verify it disappears from "Basic List" too
*/
import {
Cell,
computed,
Default,
derive,
handler,
ifElse,
NAME,
pattern,
UI,
} from "commontools";
interface ShoppingItem {
title: string;
done: Default;
category: Default;
}
// Sub-pattern 1: Basic list view
interface BasicListInput {
items: Cell;
}
const BasicList = pattern(({ items }) => {
const removeItem = handler<
unknown,
{ items: Cell>>; item: Cell }
>(
(_event, { items: itemsList, item }) => {
const current = itemsList.get();
const index = current.findIndex((el) => el.equals(item));
if (index >= 0) {
itemsList.set(current.toSpliced(index, 1));
}
},
);
const addItem = handler<
{ detail: { message: string } },
{ items: Cell }
>(
({ detail }, { items: itemsList }) => {
const input = detail?.message?.trim();
if (input) {
const [title, category = "Uncategorized"] = input.split(":");
itemsList.push({
title: title.trim(),
done: false,
category: category.trim(),
});
}
},
);
return {
[NAME]: "Basic Shopping List",
[UI]: (