import type { CSSProperties, FormEvent } from "react";
import { z } from "zod";
import type { GenerativeUILibrary } from "../types";
import { ALIGNS, JUSTIFIES } from "../ir";
import { fire } from "./dispatch";
import { collectFormValuesFromEvent } from "./collectFormValues";
import { toTextContent } from "./toTextContent";
const toCssLength = (value: string | number): string =>
typeof value === "number" ? `${value}px` : value;
const cardActionSchema = z.looseObject({
type: z
.string()
.describe("The action type, resolved by the host's action registry."),
});
const cardFooterButtonSchema = z.object({
label: z.string().describe("Footer button label."),
$action: cardActionSchema
.optional()
.describe("Action fired when the button is activated."),
});
export const layoutVocabulary = {
Card: {
description:
"A titled section of related content, the default way to break a response into parts. It renders as plain content, so several in a row read as one answer rather than a stack of boxes; it takes on a framed surface only when `background` is set, when `confirm`/`cancel` add a footer, or when it is a slot in a `Carousel`. Set `asForm` to collect named child control values on submit.",
properties: z.object({
title: z.string().optional().describe("Optional card title."),
padding: z
.number()
.min(0)
.max(8)
.optional()
.describe(
"Padding in 4px units (e.g. 2 = 8px). 0 to 8 is the supported range.",
),
background: z
.string()
.optional()
.describe(
"Background color or gradient (any CSS background value). Setting this also switches the card's own text to white, since a custom background makes the card a tinted surface; children can still opt into a different color explicitly.",
),
asForm: z
.boolean()
.optional()
.describe(
"Render as a form; submitting it fires `confirm.$action` with every named child control's value, keyed by `name`.",
),
confirm: cardFooterButtonSchema
.optional()
.describe("Confirm button shown in the footer."),
cancel: cardFooterButtonSchema
.optional()
.describe("Cancel button shown in the footer."),
}),
render: ({
title,
padding,
background,
asForm,
confirm,
cancel,
$dispatch,
children,
}) => {
const Root = asForm ? "form" : "section";
const cardTitle = toTextContent(title);
const footer =
confirm || cancel ? (
) : null;
return (