package main import ( "context" "github.com/a-h/templ" "git.dev.alexdunmow.com/block/core/blocks" "git.dev.alexdunmow.com/block/core/plugin" "git.dev.alexdunmow.com/block/core/templates" ) // wrap adapts a templ-returning render function to templates.TemplateFunc. // templ.Component already implements templates.HTMLComponent via Render. func wrap(f func(ctx context.Context, doc map[string]any) templ.Component) templates.TemplateFunc { return func(ctx context.Context, doc map[string]any) templates.HTMLComponent { return f(ctx, doc) } } // Register is the plugin entry point. It registers the system template, page // templates, theme-owned blocks, built-in overrides, and the email wrapper. // // Order of operations matters: br.LoadSchemasFromFS MUST run before any // br.Register call so schema binding sees the blocks as they register. func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error { // System template registration. tr.RegisterSystemTemplate(templates.SystemTemplateMeta{ Key: "pastel-dream", Title: "Pastel Dream", Description: "Soft watercolor theme with blush, mint, and butter palettes for wellness, parenting, and spa brands.", }) // Page templates per spec §"Page templates". if err := tr.RegisterPageTemplate("pastel-dream", templates.PageTemplateMeta{ Key: "default", Title: "Default", Description: "Soft layered hero, masthead nav, footer with newsletter.", Slots: []string{"header", "main", "footer"}, }, wrap(RenderPastelDefault)); err != nil { return err } if err := tr.RegisterPageTemplate("pastel-dream", templates.PageTemplateMeta{ Key: "landing", Title: "Soft Landing", Description: "Watercolor hero, affirmation strip, CTA, footer.", Slots: []string{"hero", "main", "cta", "footer"}, }, wrap(RenderPastelLanding)); err != nil { return err } if err := tr.RegisterPageTemplate("pastel-dream", templates.PageTemplateMeta{ Key: "article", Title: "Reading Room", Description: "Narrow, centered editorial column with side rail.", Slots: []string{"header", "main", "footer"}, }, wrap(RenderPastelArticle)); err != nil { return err } if err := tr.RegisterPageTemplate("pastel-dream", templates.PageTemplateMeta{ Key: "full-width", Title: "Open Air", Description: "Edge-to-edge sections for galleries and seasonal looks.", Slots: []string{"header", "main", "footer"}, }, wrap(RenderPastelFullWidth)); err != nil { return err } // Schemas MUST load before blocks register so editor metadata binds. if err := br.LoadSchemasFromFS(Schemas()); err != nil { return err } // Theme-owned blocks. br.Register(SoftNavbarMeta, SoftNavbarBlock) br.Register(WatercolorHeroMeta, WatercolorHeroBlock) br.Register(AffirmationMeta, AffirmationBlock) br.Register(TestimonialSoftMeta, TestimonialSoftBlock) br.Register(FeatureGridSoftMeta, FeatureGridSoftBlock) br.Register(CozyFooterMeta, CozyFooterBlock) // Overrides for built-ins, only when this theme is active. br.RegisterTemplateOverride("pastel-dream", "heading", PastelHeadingBlock) br.RegisterTemplateOverride("pastel-dream", "text", PastelTextBlock) br.RegisterTemplateOverride("pastel-dream", "button", PastelButtonBlock) br.RegisterTemplateOverride("pastel-dream", "card", PastelCardBlock) // Email wrapper. tr.RegisterEmailWrapper("pastel-dream", PastelEmailWrapper) return nil } // DefaultMasterPages returns the master pages seeded on first plugin load. // Two definitions per spec §"Master pages": // - pastel-dream:default-master — used by default and article page templates // - pastel-dream:landing-master — used by the landing page template func DefaultMasterPages() []plugin.MasterPageDefinition { return []plugin.MasterPageDefinition{ { Key: "pastel-dream:default-master", Title: "Pastel Dream Default Master", PageTemplates: []string{"default", "article"}, Blocks: []plugin.MasterPageBlock{ { BlockKey: "pastel-dream:soft-navbar", Title: "Soft Nav", Content: map[string]any{ "menuName": "main", "logo": "Pastel Dream", }, Slot: "header", SortOrder: 0, }, { BlockKey: "slot", Title: "Main Slot", Content: map[string]any{ "slotName": "main", "placeholder": "Page content", }, Slot: "main", SortOrder: 0, }, { BlockKey: "pastel-dream:cozy-footer", Title: "Cozy Footer", Content: map[string]any{ "showSignup": "yes", "affirmation": "Be gentle with yourself today.", }, Slot: "footer", SortOrder: 0, }, }, }, { Key: "pastel-dream:landing-master", Title: "Pastel Dream Landing Master", PageTemplates: []string{"landing"}, Blocks: []plugin.MasterPageBlock{ { BlockKey: "pastel-dream:watercolor-hero", Title: "Watercolor Hero", Content: map[string]any{ "eyebrow": "new", "headline": "Soft starts", "body": "A gentle place to begin.", "ctaText": "Begin", }, Slot: "hero", SortOrder: 0, }, { BlockKey: "slot", Title: "Main Slot", Content: map[string]any{ "slotName": "main", }, Slot: "main", SortOrder: 0, }, { BlockKey: "pastel-dream:affirmation", Title: "Affirmation Strip", Content: map[string]any{ "quote": "You are doing enough.", "author": "Pastel Dream", }, Slot: "cta", SortOrder: 0, }, { BlockKey: "pastel-dream:cozy-footer", Title: "Cozy Footer", Content: map[string]any{ "showSignup": "yes", }, Slot: "footer", SortOrder: 0, }, }, }, } }