/*
[RFC-0104] Canonical CtaConfig and CtaGroupConfig — one structured shape used
by every section that renders a call-to-action. Replaces the four ad-hoc CTA
shapes that lived on hero / final-cta / hero-decision-card / notausgang-block.
- Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.
- RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.
- RFC-1257: structured CtaTarget + scenario-plumbed contact links
*/
import { z } from "zod";
import { horizontalAlignSchema } from "./horizontal-align.ts";
import { vendorIconConfigSchema } from "./standard-list-item.ts";
import { TARGET_QUERY_KEY_PATTERN, TARGET_QUERY_VALUE_PATTERN } from "../referral/patterns.ts";
export const ctaVariantSchema = z.enum(["primary", "secondary", "ghost", "danger"]);
export type CtaVariant = z.infer;
export const ctaSizeSchema = z.enum(["sm", "md", "lg"]);
export type CtaSize = z.infer;
export const ctaIconPositionSchema = z.enum(["leading", "trailing"]);
export type CtaIconPosition = z.infer;
export const ctaTargetSchema = z.discriminatedUnion("kind", [
z
.object({
kind: z.literal("internal"),
pageId: z.string().min(1),
// RFC-1257: bounded query map — emitted as path?k=v before #anchor.
query: z
.record(
z.string().regex(TARGET_QUERY_KEY_PATTERN),
z.string().regex(TARGET_QUERY_VALUE_PATTERN),
)
.optional(),
anchor: z.string().optional(),
})
.strict(),
z
.object({
kind: z.literal("external"),
href: z.string().min(1),
rel: z.string().optional(),
})
.strict(),
z
.object({
kind: z.literal("anchor"),
anchor: z.string().min(1),
})
.strict(),
]);
export type CtaTarget = z.infer;
export const ctaConfigSchema = z
.object({
label: z.string().min(1),
target: ctaTargetSchema,
ariaLabel: z.string().optional(),
variant: ctaVariantSchema.optional(),
icon: vendorIconConfigSchema.optional(),
iconPosition: ctaIconPositionSchema.optional(),
size: ctaSizeSchema.optional(),
fullWidth: z.boolean().optional(),
})
.strict();
export type CtaConfig = z.infer;
export const ctaGroupConfigSchema = z
.object({
align: horizontalAlignSchema.optional(),
items: z.array(ctaConfigSchema).min(1),
})
.strict();
export type CtaGroupConfig = z.infer;