/// import { Cell, cell, handler, ifElse, lift, NAME, navigateTo, OpaqueRef, recipe, UI, } from "commontools"; // the simple charm (to which we'll store references within a cell) const SimpleRecipe = recipe("Simple Recipe", () => ({ [NAME]: "Some Simple Recipe", [UI]:
Some Simple Recipe
, })); // Create a cell to store an array of charms const createCellRef = lift( { type: "object", properties: { isInitialized: { type: "boolean", "default": false, asCell: true }, storedCellRef: { type: "object", asCell: true }, }, }, undefined, ({ isInitialized, storedCellRef }) => { if (!isInitialized.get()) { console.log("Creating cellRef - first time"); const newCellRef = Cell.for("charmsArray"); newCellRef.set([]); storedCellRef.set(newCellRef); isInitialized.set(true); return { cellRef: newCellRef, }; } else { console.log("cellRef already initialized"); } // If already initialized, return the stored cellRef return { cellRef: storedCellRef, }; }, ); // Add a charm to the array and navigate to it // we get a new isInitialized passed in for each // charm we add to the list. this makes sure // we only try to add the charm once to the list // and we only call navigateTo once const addCharmAndNavigate = lift( { type: "object", properties: { charm: { type: "object" }, cellRef: { type: "array", asCell: true }, isInitialized: { type: "boolean", asCell: true }, }, }, undefined, ({ charm, cellRef, isInitialized }) => { if (!isInitialized.get()) { if (cellRef) { cellRef.push(charm); isInitialized.set(true); return navigateTo(charm); } else { console.log("addCharmAndNavigate undefined cellRef"); } } return undefined; }, ); // Create a new SimpleRecipe and add it to the array const createSimpleRecipe = handler }>( (_, { cellRef }) => { // Create isInitialized cell for this charm addition const isInitialized = cell(false); // Create the charm const charm = SimpleRecipe({}); // Store the charm in the array and navigate return addCharmAndNavigate({ charm, cellRef, isInitialized }); }, ); // Handler to navigate to a specific charm from the list const goToCharm = handler( (_, { charm }) => { console.log("goToCharm clicked"); return navigateTo(charm); }, ); // create the named cell inside the recipe body, so we do it just once export default recipe("Charms Launcher", () => { // cell to store array of charms we created const { cellRef } = createCellRef({ isInitialized: cell(false), storedCellRef: cell(), }); // Type assertion to help TypeScript understand cellRef is an OpaqueRef // Without this, TypeScript infers `any` and the closure transformer won't detect it const typedCellRef = cellRef as OpaqueRef; return { [NAME]: "Charms Launcher", [UI]: (

Stored Charms:

{ifElse( !typedCellRef?.length,
No charms created yet
,
    {typedCellRef.map((charm: any, index: number) => (
  • Go to Charm {index + 1} Charm {index + 1}: {charm[NAME] || "Unnamed"}
  • ))}
, )} Create New Charm
), cellRef, }; });