/** * Marketing blocks plugin (inline, template-local). * * Registers the five marketing block types so editors can insert and edit them * in the admin's Portable Text editor. Block Kit `fields` describe the form * shown when inserting or editing a block. * * Constraints worth knowing: * * - Block Kit has no "object group" element, so nested object shapes (e.g. a * CTA's { label, url }) are flattened to sibling fields like ctaLabel and * ctaUrl. The site-side renderer reads the flat keys. * - Repeater sub-fields are scalar only: text_input, number_input, select, * toggle. Nested repeaters are not allowed -- list-of-strings becomes a * single multiline text field, split on newline at render time (see * Pricing.astro for the pattern). * - There is no media picker element in the editor's plugin-block modal yet, * so image fields (avatars, hero images) are URL strings entered by hand. * * Site-side rendering still goes through MarketingBlocks.astro -- * componentsEntry auto-wiring is a separate cleanup. */ import { definePlugin } from "emdash"; import type { PluginDefinition } from "emdash"; const ICON_OPTIONS = [ { label: "Lightning", value: "zap" }, { label: "Shield", value: "shield" }, { label: "Users", value: "users" }, { label: "Chart", value: "chart" }, { label: "Code", value: "code" }, { label: "Globe", value: "globe" }, { label: "Heart", value: "heart" }, { label: "Star", value: "star" }, { label: "Check", value: "check" }, { label: "Lock", value: "lock" }, { label: "Clock", value: "clock" }, { label: "Cloud", value: "cloud" }, ]; const definition: PluginDefinition = { id: "marketing-blocks", version: "0.1.0", admin: { portableTextBlocks: [ { type: "marketing.hero", label: "Hero", category: "Sections", description: "Big headline section with optional CTAs", fields: [ { type: "text_input", action_id: "headline", label: "Headline" }, { type: "text_input", action_id: "subheadline", label: "Subheadline", multiline: true, }, { type: "text_input", action_id: "primaryCtaLabel", label: "Primary CTA label" }, { type: "text_input", action_id: "primaryCtaUrl", label: "Primary CTA URL" }, { type: "text_input", action_id: "secondaryCtaLabel", label: "Secondary CTA label", }, { type: "text_input", action_id: "secondaryCtaUrl", label: "Secondary CTA URL" }, { type: "toggle", action_id: "centered", label: "Center the layout" }, ], }, { type: "marketing.features", label: "Features", category: "Sections", description: "Grid of feature cards with icons", fields: [ { type: "text_input", action_id: "headline", label: "Headline" }, { type: "text_input", action_id: "subheadline", label: "Subheadline", multiline: true, }, { type: "repeater", action_id: "features", label: "Features", item_label: "Feature", min_items: 1, max_items: 12, fields: [ { type: "select", action_id: "icon", label: "Icon", options: ICON_OPTIONS, }, { type: "text_input", action_id: "title", label: "Title" }, { type: "text_input", action_id: "description", label: "Description", multiline: true, }, ], }, ], }, { type: "marketing.testimonials", label: "Testimonials", category: "Sections", description: "Customer testimonial cards", fields: [ { type: "text_input", action_id: "headline", label: "Headline" }, { type: "repeater", action_id: "testimonials", label: "Testimonials", item_label: "Testimonial", min_items: 1, fields: [ { type: "text_input", action_id: "quote", label: "Quote", multiline: true }, { type: "text_input", action_id: "author", label: "Author name" }, { type: "text_input", action_id: "role", label: "Role / title" }, { type: "text_input", action_id: "company", label: "Company" }, { type: "text_input", action_id: "avatar", label: "Avatar URL" }, ], }, ], }, { type: "marketing.pricing", label: "Pricing", category: "Sections", description: "Pricing plan comparison cards", fields: [ { type: "text_input", action_id: "headline", label: "Headline" }, { type: "repeater", action_id: "plans", label: "Plans", item_label: "Plan", min_items: 1, max_items: 6, fields: [ { type: "text_input", action_id: "name", label: "Plan name" }, { type: "text_input", action_id: "price", label: "Price", placeholder: "$29 or Custom", }, { type: "text_input", action_id: "period", label: "Period", placeholder: "/month", }, { type: "text_input", action_id: "description", label: "Description", multiline: true, }, { type: "text_input", action_id: "features", label: "Features (one per line)", multiline: true, placeholder: "Unlimited projects\nPriority support\nSSO", }, { type: "text_input", action_id: "ctaLabel", label: "CTA label" }, { type: "text_input", action_id: "ctaUrl", label: "CTA URL" }, { type: "toggle", action_id: "highlighted", label: "Highlight this plan" }, ], }, ], }, { type: "marketing.faq", label: "FAQ", category: "Sections", description: "Frequently asked questions", fields: [ { type: "text_input", action_id: "headline", label: "Headline" }, { type: "repeater", action_id: "items", label: "Questions", item_label: "Question", min_items: 1, fields: [ { type: "text_input", action_id: "question", label: "Question" }, { type: "text_input", action_id: "answer", label: "Answer", multiline: true, }, ], }, ], }, ], }, }; export function createPlugin() { return definePlugin(definition); } export default createPlugin;