Files

41 lines
2.2 KiB
JavaScript

// Cards and tiles: a rounded group of fields, a pressable tile, and the grid that lays tiles out.
import { define, lookup } from "../internals/register.js";
import { el } from "../internals/el.js";
import { setText } from "../internals/text.js";
/** Related fields on one rounded card. Takes handles, like a stack. */
define("card", "default", ({ children = [], gap = "md" } = {}) => {
const stack = lookup("region", "stack")({ children, gap });
stack.node.classList.add("cx-fieldcard");
return stack;
});
/** Tiles in rows. `pair` is two columns; `cards` fills the width with columns at least 190 wide. */
for (const kind of ["pair", "cards"]) {
define("grid", kind, ({ children = [] } = {}) => {
const stack = lookup("region", "stack")({ children, gap: "none" });
stack.node.classList.add("cx-grid", `cx-grid-${kind}`);
return stack;
});
}
const TONES = { ready: "Ready", needs: "Needs attention", skipped: "Skipped: not available" };
function tile(kind, { title, sub, onClick, state, label } = {}) {
if (state !== undefined && !TONES[state]) throw new RangeError(`Unknown tile state "${state}". Known: ${Object.keys(TONES).join(", ")}.`);
const head = el("span", { cls: "cx-tile-title", text: title });
const hint = el("span", { cls: "cx-tile-sub", text: sub });
const dot = state ? el("span", { cls: ["cx-tile-state", `cx-tile-${state}`], attrs: { title: TONES[state] } }) : null;
const node = el("button", { cls: ["cx-tile", `cx-tile-${kind}`, "cx-focusable"], attrs: { type: "button", "aria-label": label },
children: [dot, head, sub != null && sub !== "" ? hint : null].filter(Boolean) });
if (onClick) node.addEventListener("click", onClick);
return { node, setTitle: (v) => setText(head, v), setSub: (v) => setText(hint, v), destroy: () => node.remove() };
}
/** A whole-tile button: a title over one line of hint. */
define("tile", "action", (props = {}) => tile("action", props));
/** A node of the pipeline: title, one line of what is set, and a dot that says whether it is ready. */
define("tile", "node", (props = {}) => tile("node", { state: "ready", ...props }));
/** The empty slot at the end of a group: "+ Add". */
define("tile", "add", (props = {}) => tile("add", props));