///
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,
};
});