Files
WRNexusJS/packages/design-system/src/catalog-recipes.ts
T

46 lines
2.1 KiB
TypeScript

import { CATALOG_COMPONENT_CONTRACTS } from "./catalog-contracts.ts";
import type { ComponentRecipe, RecipeStyles } from "./types.ts";
/** Family defaults change styling only: no display, dimensions, positioning, clipping or graph geometry. */
export function catalogRecipes(): Record<string, ComponentRecipe> {
const recipes: Record<string, ComponentRecipe> = {};
const ref = (name: string) => ({ ref: name });
for (const [name, contract] of Object.entries(CATALOG_COMPONENT_CONTRACTS)) {
const base: Record<string, RecipeStyles> = {};
const axes: Record<string, { default: string }> = contract.axes;
for (const [part, descriptor] of Object.entries(contract.parts)) {
if (descriptor.ownership !== "framework" || descriptor.profile === "managed") continue;
const styles: RecipeStyles = {};
if (
descriptor.properties.includes("fontFamily") &&
descriptor.role !== "code" &&
name !== "Kbd"
)
styles.fontFamily = ref(
/^title|heading|headline/i.test(part) ? "type.heading" : "type.body",
);
const roundedFalse = axes.rounded?.default === "false";
const circle = ["circle", "round"].includes(axes.shape?.default ?? "");
const semanticGeometry =
/thumb|track|spinner|progress|marker|port$|status|dot|star|srOnly/i.test(part);
if (
descriptor.properties.includes("borderRadius") &&
!roundedFalse &&
!circle &&
!semanticGeometry
) {
styles.borderRadius = ref(
descriptor.profile === "control" ? "shape.control" : "shape.panel",
);
}
// Only existing surfaces receive elevation. Layout wrappers and provider hosts are untouched.
if (descriptor.profile === "surface" && descriptor.properties.includes("boxShadow"))
styles.boxShadow = ref("elevation.panel");
if (Object.keys(styles).length) base[part] = styles;
}
// Every catalog component has a deliberate recipe, even if only its text wrapper is styled.
recipes[name] = { contractVersion: 1, base };
}
return recipes;
}