63 lines
2.6 KiB
TypeScript
63 lines
2.6 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);
|
|
// Joined surfaces share the outer component's corners. Rounding each
|
|
// child creates seams, scalloped panels and rounded splitter rails.
|
|
const joined = (
|
|
{
|
|
StatsBar: ["item", "content"],
|
|
AuthSplitLayout: ["content"],
|
|
Collapse: ["trigger", "panel", "content"],
|
|
InputNumber: ["button", "content", "input"],
|
|
LayoutSplitter: ["handle"],
|
|
} as Record<string, string[]>
|
|
)[name]?.includes(part);
|
|
if (
|
|
descriptor.properties.includes("borderRadius") &&
|
|
!roundedFalse &&
|
|
!circle &&
|
|
!semanticGeometry &&
|
|
!joined
|
|
) {
|
|
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") &&
|
|
!joined &&
|
|
!(name === "PreferenceSwitcher" && part === "menu")
|
|
)
|
|
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;
|
|
}
|