feat: convert to codeless .bnp — templates + manifest, Go/templ deleted (WO-WZ-021)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b38c0d3a57
commit
dccd269ab2
40
Makefile
40
Makefile
@ -1,26 +1,27 @@
|
|||||||
# kindergarten — build & publish helpers (wasm .bnp workflow)
|
# kindergarten — build & publish helpers (CODELESS .bnp workflow, WO-WZ-021)
|
||||||
#
|
#
|
||||||
# The theme compiles to a wasip1 reactor-mode wasm module packed into a .bnp
|
# This theme is a CODELESS .bnp: pure declaration the host runs — blocks
|
||||||
# artifact (`ninja plugin build`). The legacy .so path is retired (WO-WZ-015):
|
# (blocks/blocks.yaml + .ninjatpl), page/system templates, template overrides,
|
||||||
# the CMS is wasm-native and can no longer load .so plugins. Distribution is
|
# an email wrapper, master pages, presets, fonts and CSS in manifest.yaml. No
|
||||||
# publish-to-registry -> InstallFromRegistry (hot-load, no restart).
|
# Go, no templ, no plugin.wasm, no block/core dependency. `ninja plugin build`
|
||||||
|
# classifies the repo as codeless (no Go at the root) and packs the artifact
|
||||||
|
# with manifest.pb (codeless: true) and NO plugin.wasm.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# make build # compile wasm + pack kindergarten-<version>.bnp
|
# make build # pack kindergarten-<version>.bnp (codeless — no wasm)
|
||||||
# make verify # validate the built .bnp (layout/abi/name/size)
|
# make verify # validate the built .bnp (loader-identical checks)
|
||||||
# make archive-check # prove a clean `git archive HEAD` compiles to wasm
|
# make archive-check # prove a clean `git archive HEAD` still builds codeless
|
||||||
# make publish # ninja plugin publish --bnp (to the active registry)
|
# make publish # ninja plugin publish --bnp (to the active registry)
|
||||||
# make templ # regenerate templ Go files
|
|
||||||
# make clean # remove build artefacts
|
# make clean # remove build artefacts
|
||||||
|
|
||||||
.PHONY: build verify archive-check publish templ clean help
|
.PHONY: build verify archive-check publish clean help
|
||||||
|
|
||||||
PLUGIN_NAME := kindergarten
|
PLUGIN_NAME := kindergarten
|
||||||
NINJA := ninja
|
NINJA := ninja
|
||||||
BNP := $(PLUGIN_NAME)-$(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/').bnp
|
BNP := $(PLUGIN_NAME)-$(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/').bnp
|
||||||
|
|
||||||
# Compile to wasm and pack the .bnp (GOOS=wasip1 GOARCH=wasm, DESCRIBE probe,
|
# Pack the codeless .bnp (manifest.pb synthesized from plugin.mod + manifest.yaml
|
||||||
# tar.zst of plugin.wasm + plugin.mod + manifest.pb + schemas/ + assets/).
|
# + blocks/ + templates/; no wasm compile, no DESCRIBE probe).
|
||||||
build:
|
build:
|
||||||
$(NINJA) plugin build --dir .
|
$(NINJA) plugin build --dir .
|
||||||
|
|
||||||
@ -28,12 +29,12 @@ build:
|
|||||||
verify:
|
verify:
|
||||||
$(NINJA) plugin verify $(BNP)
|
$(NINJA) plugin verify $(BNP)
|
||||||
|
|
||||||
# Prove a clean `git archive HEAD` (what publish ships) compiles to wasm.
|
# Prove a clean `git archive HEAD` (what publish ships) still packs codeless.
|
||||||
archive-check:
|
archive-check:
|
||||||
@T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \
|
@T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \
|
||||||
trap 'rm -rf "$$T"' EXIT && \
|
trap 'rm -rf "$$T"' EXIT && \
|
||||||
git archive HEAD | tar -x -C "$$T" && \
|
git archive HEAD | tar -x -C "$$T" && \
|
||||||
cd "$$T" && GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o "$$T/check.wasm" . && \
|
cd "$$T" && $(NINJA) plugin build --dir . && \
|
||||||
echo "archive-check OK"
|
echo "archive-check OK"
|
||||||
|
|
||||||
# Publish the prebuilt .bnp to the active registry.
|
# Publish the prebuilt .bnp to the active registry.
|
||||||
@ -41,19 +42,14 @@ archive-check:
|
|||||||
publish: build
|
publish: build
|
||||||
$(NINJA) plugin publish --bnp $(BNP)
|
$(NINJA) plugin publish --bnp $(BNP)
|
||||||
|
|
||||||
# Regenerate templ Go files locally.
|
|
||||||
templ:
|
|
||||||
templ generate
|
|
||||||
|
|
||||||
# Remove build artefacts.
|
# Remove build artefacts.
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PLUGIN_NAME)-*.bnp $(PLUGIN_NAME).so plugin.wasm
|
rm -f $(PLUGIN_NAME)-*.bnp plugin.wasm
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Targets:"
|
@echo "Targets:"
|
||||||
@echo " build Compile wasm + pack the .bnp"
|
@echo " build Pack the codeless .bnp (no wasm)"
|
||||||
@echo " verify Validate the built .bnp (loader-identical checks)"
|
@echo " verify Validate the built .bnp (loader-identical checks)"
|
||||||
@echo " archive-check Prove a clean git archive HEAD compiles to wasm"
|
@echo " archive-check Prove a clean git archive HEAD packs codeless"
|
||||||
@echo " publish Publish the .bnp to the active registry"
|
@echo " publish Publish the .bnp to the active registry"
|
||||||
@echo " templ Regenerate templ Go files"
|
|
||||||
@echo " clean Remove build artefacts"
|
@echo " clean Remove build artefacts"
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AlphabetStripBlockMeta defines metadata for the alphabet strip block.
|
|
||||||
var AlphabetStripBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "alphabet_strip",
|
|
||||||
Title: "Alphabet Strip",
|
|
||||||
Description: "Decorative letter band; jumps to anchors when used as TOC.",
|
|
||||||
Category: blocks.CategoryNavigation,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlphabetStripData contains the letters + colorway for the rendered strip.
|
|
||||||
type AlphabetStripData struct {
|
|
||||||
Letters []string
|
|
||||||
ColorMode string
|
|
||||||
}
|
|
||||||
|
|
||||||
// AlphabetStripBlock renders a decorative letter band.
|
|
||||||
// Content shape: {letters,colorMode}.
|
|
||||||
func AlphabetStripBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getStringDefault(content, "letters", "")
|
|
||||||
colorMode := getStringDefault(content, "colorMode", "rainbow")
|
|
||||||
|
|
||||||
// Validate colorMode against allowed set.
|
|
||||||
switch colorMode {
|
|
||||||
case "primary", "rainbow", "mono":
|
|
||||||
default:
|
|
||||||
colorMode = "rainbow"
|
|
||||||
}
|
|
||||||
|
|
||||||
letters := splitLetters(raw)
|
|
||||||
data := AlphabetStripData{
|
|
||||||
Letters: letters,
|
|
||||||
ColorMode: colorMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = alphabetStripComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitLetters returns one entry per visible rune. Whitespace is trimmed.
|
|
||||||
func splitLetters(s string) []string {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if s == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
letters := make([]string, 0, len(s))
|
|
||||||
for _, r := range s {
|
|
||||||
if r == ' ' || r == '\t' || r == '\n' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
letters = append(letters, string(r))
|
|
||||||
}
|
|
||||||
return letters
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// alphabetStripComponent renders the letter band.
|
|
||||||
templ alphabetStripComponent(data AlphabetStripData) {
|
|
||||||
<nav class={ "kg-alphabet-strip", alphabetClass(data.ColorMode) } aria-label="Alphabet strip" data-block="kindergarten:alphabet_strip">
|
|
||||||
if len(data.Letters) == 0 {
|
|
||||||
<span class="kg-empty" data-empty="true">No letters configured</span>
|
|
||||||
}
|
|
||||||
for _, letter := range data.Letters {
|
|
||||||
<span class="kg-alphabet-letter">{ letter }</span>
|
|
||||||
}
|
|
||||||
</nav>
|
|
||||||
}
|
|
||||||
|
|
||||||
// alphabetClass returns the modifier class for the chosen colorway.
|
|
||||||
func alphabetClass(mode string) string {
|
|
||||||
switch mode {
|
|
||||||
case "primary":
|
|
||||||
return "kg-alphabet-primary"
|
|
||||||
case "mono":
|
|
||||||
return "kg-alphabet-mono"
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// alphabetStripComponent renders the letter band.
|
|
||||||
func alphabetStripComponent(data AlphabetStripData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
var templ_7745c5c3_Var2 = []any{"kg-alphabet-strip", alphabetClass(data.ColorMode)}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<nav class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `alphabet_strip.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" aria-label=\"Alphabet strip\" data-block=\"kindergarten:alphabet_strip\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if len(data.Letters) == 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<span class=\"kg-empty\" data-empty=\"true\">No letters configured</span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, letter := range data.Letters {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<span class=\"kg-alphabet-letter\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(letter)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `alphabet_strip.templ`, Line: 10, Col: 44}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// alphabetClass returns the modifier class for the chosen colorway.
|
|
||||||
func alphabetClass(mode string) string {
|
|
||||||
switch mode {
|
|
||||||
case "primary":
|
|
||||||
return "kg-alphabet-primary"
|
|
||||||
case "mono":
|
|
||||||
return "kg-alphabet-mono"
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
45
big_cta.go
45
big_cta.go
@ -1,45 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BigCTABlockMeta defines metadata for the oversized CTA block.
|
|
||||||
var BigCTABlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "big_cta",
|
|
||||||
Title: "Big CTA",
|
|
||||||
Description: "Oversized pill button with crayon underline.",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// BigCTAData is the renderer input.
|
|
||||||
type BigCTAData struct {
|
|
||||||
Label string
|
|
||||||
Href string
|
|
||||||
ColorVariant string
|
|
||||||
}
|
|
||||||
|
|
||||||
// BigCTABlock renders the oversized pill button.
|
|
||||||
// Content shape: {label,href,colorVariant}.
|
|
||||||
func BigCTABlock(ctx context.Context, content map[string]any) string {
|
|
||||||
color := getStringDefault(content, "colorVariant", "yellow")
|
|
||||||
switch color {
|
|
||||||
case "red", "blue", "yellow", "green":
|
|
||||||
default:
|
|
||||||
color = "yellow"
|
|
||||||
}
|
|
||||||
|
|
||||||
data := BigCTAData{
|
|
||||||
Label: getString(content, "label"),
|
|
||||||
Href: getStringDefault(content, "href", "#"),
|
|
||||||
ColorVariant: color,
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = bigCTAComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// bigCTAComponent renders the oversized pill CTA.
|
|
||||||
templ bigCTAComponent(data BigCTAData) {
|
|
||||||
<section class="kg-big-cta" data-block="kindergarten:big_cta">
|
|
||||||
<div class="kg-container">
|
|
||||||
if data.Label != "" {
|
|
||||||
<a href={ templ.SafeURL(data.Href) } class={ "kg-pill", "kg-crayon-underline", ctaColorClass(data.ColorVariant) }>{ data.Label }</a>
|
|
||||||
} else {
|
|
||||||
<span class="kg-empty" data-empty="true">Add a label and link to publish this call-to-action.</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
// ctaColorClass picks the modifier class for the four-color CTA variants.
|
|
||||||
func ctaColorClass(variant string) string {
|
|
||||||
switch variant {
|
|
||||||
case "red":
|
|
||||||
return "kg-pill-red"
|
|
||||||
case "blue":
|
|
||||||
return "kg-pill-blue"
|
|
||||||
case "green":
|
|
||||||
return "kg-pill-green"
|
|
||||||
default:
|
|
||||||
return "kg-pill-yellow"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
114
big_cta_templ.go
114
big_cta_templ.go
@ -1,114 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// bigCTAComponent renders the oversized pill CTA.
|
|
||||||
func bigCTAComponent(data BigCTAData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-big-cta\" data-block=\"kindergarten:big_cta\"><div class=\"kg-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Label != "" {
|
|
||||||
var templ_7745c5c3_Var2 = []any{"kg-pill", "kg-crayon-underline", ctaColorClass(data.ColorVariant)}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(data.Href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `big_cta.templ`, Line: 8, Col: 38}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `big_cta.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `big_cta.templ`, Line: 8, Col: 130}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<span class=\"kg-empty\" data-empty=\"true\">Add a label and link to publish this call-to-action.</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ctaColorClass picks the modifier class for the four-color CTA variants.
|
|
||||||
func ctaColorClass(variant string) string {
|
|
||||||
switch variant {
|
|
||||||
case "red":
|
|
||||||
return "kg-pill-red"
|
|
||||||
case "blue":
|
|
||||||
return "kg-pill-blue"
|
|
||||||
case "green":
|
|
||||||
return "kg-pill-green"
|
|
||||||
default:
|
|
||||||
return "kg-pill-yellow"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
1
blocks/alphabet_strip.ninjatpl
Normal file
1
blocks/alphabet_strip.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<nav class="kg-alphabet-strip {% if colorMode == "primary" %}kg-alphabet-primary{% elif colorMode == "mono" %}kg-alphabet-mono{% endif %}" aria-label="Alphabet strip" data-block="kindergarten:alphabet_strip">{% if not letters|cut:" " %}<span class="kg-empty" data-empty="true">No letters configured</span>{% endif %}{% for letter in letters|cut:" " %}<span class="kg-alphabet-letter">{{ letter }}</span>{% endfor %}</nav>
|
||||||
1
blocks/big_cta.ninjatpl
Normal file
1
blocks/big_cta.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-big-cta" data-block="kindergarten:big_cta"><div class="kg-container">{% if label %}<a href="{{ href|default:'#' }}" class="kg-pill kg-crayon-underline {% if colorVariant == "red" %}kg-pill-red{% elif colorVariant == "blue" %}kg-pill-blue{% elif colorVariant == "green" %}kg-pill-green{% else %}kg-pill-yellow{% endif %}">{{ label }}</a>{% else %}<span class="kg-empty" data-empty="true">Add a label and link to publish this call-to-action.</span>{% endif %}</div></section>
|
||||||
54
blocks/blocks.yaml
Normal file
54
blocks/blocks.yaml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Kindergarten theme block definitions (codeless .bnp, WO-WZ-021).
|
||||||
|
# Keys are fully qualified (kindergarten:<key>) because the codeless loader
|
||||||
|
# registers definitions verbatim — there is no PluginBlockRegistry prefixing
|
||||||
|
# in the codeless path (unlike the wasm/templ path). The qualified keys match
|
||||||
|
# the hardcoded data-block attributes and the master_pages.json references.
|
||||||
|
blocks:
|
||||||
|
- key: kindergarten:mascot_hero
|
||||||
|
title: Mascot Hero
|
||||||
|
description: Big rounded panel with mascot SVG and primary-colored confetti.
|
||||||
|
category: content
|
||||||
|
schema: mascot_hero.schema.json
|
||||||
|
template: mascot_hero.ninjatpl
|
||||||
|
- key: kindergarten:alphabet_strip
|
||||||
|
title: Alphabet Strip
|
||||||
|
description: Decorative letter band; jumps to anchors when used as TOC.
|
||||||
|
category: navigation
|
||||||
|
schema: alphabet_strip.schema.json
|
||||||
|
template: alphabet_strip.ninjatpl
|
||||||
|
- key: kindergarten:schedule
|
||||||
|
title: Day Schedule
|
||||||
|
description: Daycare/classroom day plan with crayon time-pills.
|
||||||
|
category: content
|
||||||
|
schema: schedule.schema.json
|
||||||
|
template: schedule.ninjatpl
|
||||||
|
- key: kindergarten:gallery_of_art
|
||||||
|
title: Gallery of Art
|
||||||
|
description: Polaroid-style grid for kid artwork.
|
||||||
|
category: content
|
||||||
|
schema: gallery_of_art.schema.json
|
||||||
|
template: gallery_of_art.ninjatpl
|
||||||
|
- key: kindergarten:numbers_counter
|
||||||
|
title: Numbers Counter
|
||||||
|
description: Big circular numeral badges for stats (e.g. '12 teachers').
|
||||||
|
category: content
|
||||||
|
schema: numbers_counter.schema.json
|
||||||
|
template: numbers_counter.ninjatpl
|
||||||
|
- key: kindergarten:storybook_quote
|
||||||
|
title: Storybook Quote
|
||||||
|
description: Picture-book page treatment for a quote with optional illustration.
|
||||||
|
category: content
|
||||||
|
schema: storybook_quote.schema.json
|
||||||
|
template: storybook_quote.ninjatpl
|
||||||
|
- key: kindergarten:big_cta
|
||||||
|
title: Big CTA
|
||||||
|
description: Oversized pill button with crayon underline.
|
||||||
|
category: content
|
||||||
|
schema: big_cta.schema.json
|
||||||
|
template: big_cta.ninjatpl
|
||||||
|
- key: kindergarten:footer
|
||||||
|
title: Friendly Footer
|
||||||
|
description: Mascot wave, signup, contact, crayon-rule divider.
|
||||||
|
category: layout
|
||||||
|
schema: footer.schema.json
|
||||||
|
template: footer.ninjatpl
|
||||||
1
blocks/footer.ninjatpl
Normal file
1
blocks/footer.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div class="kg-footer" data-block="kindergarten:footer"><div class="kg-container"><div class="kg-footer-mascot"><span aria-hidden="true">👋</span><span>{{ mascotName|default:'Pip' }} says hi!</span></div>{% if showSignup != false %}<form class="kg-footer-signup" aria-label="Newsletter signup" method="post" action="/subscribe"><input type="email" name="email" placeholder="Your email" aria-label="Email address" required><button type="submit" class="kg-pill kg-pill-yellow">Sign up</button></form>{% endif %}{% if socialLinks %}<div class="kg-social-row" aria-label="Social media">{% for link in socialLinks %}<a href="{{ link.href }}" class="kg-social-link" aria-label="{% if link.platform == "facebook" %}Visit our Facebook{% elif link.platform == "instagram" %}Visit our Instagram{% elif link.platform == "youtube" %}Visit our YouTube{% elif link.platform == "tiktok" %}Visit our TikTok{% elif link.platform == "email" %}Send us an email{% else %}Open social link{% endif %}">{% if link.platform == "facebook" %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg>{% elif link.platform == "instagram" %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg>{% elif link.platform == "youtube" %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"></path><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"></polygon></svg>{% elif link.platform == "tiktok" %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12a4 4 0 1 0 4 4V4a5 5 0 0 0 5 5"></path></svg>{% elif link.platform == "email" %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>{% else %}<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle></svg>{% endif %}</a>{% endfor %}</div>{% endif %}</div></div>
|
||||||
1
blocks/gallery_of_art.ninjatpl
Normal file
1
blocks/gallery_of_art.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-section" data-block="kindergarten:gallery_of_art"><div class="kg-container">{% set showNames = true %}{% if showChildName == false %}{% set showNames = false %}{% endif %}{% if title %}<h2 class="kg-display kg-crayon-underline" style="font-size: 2rem; margin-bottom: 1.5rem;">{{ title }}</h2>{% endif %}{% if not items %}<div class="kg-empty" data-empty="true">No artworks yet — add one to fill the gallery wall.</div>{% else %}<div class="kg-gallery-grid">{% for art in items %}<figure class="kg-polaroid">{% if art.image %}<img src="{{ art.image|mediaURL }}" alt="{% if showNames and art.childName %}Artwork by {{ art.childName }}{% else %}Children's artwork{% endif %}">{% else %}<span class="kg-polaroid-image" role="img" aria-label="Placeholder for child artwork"></span>{% endif %}<figcaption class="kg-polaroid-caption">{% if showNames and art.childName %}<span>{{ art.childName }}</span>{% endif %}{% if showNames and art.childName and art.age|integer > 0 %}, {% endif %}{% if art.age|integer > 0 %}<span>age {{ art.age|integer }}</span>{% endif %}</figcaption></figure>{% endfor %}</div>{% endif %}</div></section>
|
||||||
1
blocks/mascot_hero.ninjatpl
Normal file
1
blocks/mascot_hero.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-section" data-block="kindergarten:mascot_hero"><div class="kg-container"><div class="kg-hero-panel"><div class="kg-confetti" aria-hidden="true"></div><div style="position: relative; z-index: 1; display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: center;" class="kg-mascot-hero-grid"><div>{% if headline %}<h1 class="kg-display kg-crayon-underline" style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;">{{ headline }}</h1>{% else %}<h1 class="kg-display" style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;" data-empty="true">Welcome!</h1>{% endif %}{% if tagline %}<p class="kg-text" style="font-size: 1.25rem; margin-top: 1.5rem;">{{ tagline }}</p>{% endif %}{% if ctaLabel and ctaHref %}<div style="margin-top: 2rem;"><a href="{{ ctaHref }}" class="kg-pill">{{ ctaLabel }}</a></div>{% endif %}</div><div style="display: flex; justify-content: center; align-items: center;">{% if mascot == "blocks" %}<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Alphabet blocks mascot"><rect x="20" y="60" width="60" height="60" rx="12" fill="hsl(var(--primary))"></rect><rect x="90" y="40" width="60" height="60" rx="12" fill="hsl(var(--secondary))"></rect><rect x="60" y="120" width="60" height="60" rx="12" fill="hsl(var(--accent))"></rect><text x="50" y="98" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--primary-foreground))">A</text><text x="120" y="78" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--secondary-foreground))">B</text><text x="90" y="158" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--accent-foreground))">C</text></svg>{% elif mascot == "star" %}<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Friendly star mascot"><polygon points="100,10 122,75 190,75 135,115 155,180 100,140 45,180 65,115 10,75 78,75" fill="hsl(var(--accent))" stroke="hsl(var(--foreground))" stroke-width="4" stroke-linejoin="round"></polygon><circle cx="80" cy="95" r="6" fill="hsl(var(--foreground))"></circle><circle cx="120" cy="95" r="6" fill="hsl(var(--foreground))"></circle><path d="M 80 120 Q 100 135 120 120" stroke="hsl(var(--foreground))" stroke-width="4" fill="none" stroke-linecap="round"></path></svg>{% elif mascot == "balloon" %}<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Balloon mascot"><ellipse cx="100" cy="80" rx="50" ry="60" fill="hsl(var(--primary))" stroke="hsl(var(--foreground))" stroke-width="4"></ellipse><path d="M 100 140 L 95 150 L 100 145 L 105 150 Z" fill="hsl(var(--foreground))"></path><path d="M 100 150 Q 90 175 100 195" stroke="hsl(var(--foreground))" stroke-width="2" fill="none"></path><circle cx="85" cy="65" r="6" fill="hsl(var(--foreground))"></circle><circle cx="115" cy="65" r="6" fill="hsl(var(--foreground))"></circle><path d="M 85 90 Q 100 105 115 90" stroke="hsl(var(--foreground))" stroke-width="4" fill="none" stroke-linecap="round"></path></svg>{% else %}<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Pip the mascot"><circle cx="100" cy="115" r="70" fill="hsl(var(--accent))" stroke="hsl(var(--foreground))" stroke-width="4"></circle><circle cx="78" cy="100" r="8" fill="hsl(var(--foreground))"></circle><circle cx="122" cy="100" r="8" fill="hsl(var(--foreground))"></circle><circle cx="78" cy="98" r="3" fill="hsl(var(--background))"></circle><circle cx="122" cy="98" r="3" fill="hsl(var(--background))"></circle><path d="M 75 130 Q 100 155 125 130" stroke="hsl(var(--foreground))" stroke-width="5" fill="none" stroke-linecap="round"></path><circle cx="60" cy="115" r="6" fill="hsl(var(--secondary))"></circle><circle cx="140" cy="115" r="6" fill="hsl(var(--secondary))"></circle><path d="M 50 60 L 60 35 L 80 50 Z" fill="hsl(var(--primary))"></path><path d="M 150 60 L 140 35 L 120 50 Z" fill="hsl(var(--primary))"></path></svg>{% endif %}</div></div></div></div></section>
|
||||||
1
blocks/numbers_counter.ninjatpl
Normal file
1
blocks/numbers_counter.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-section" data-block="kindergarten:numbers_counter"><div class="kg-container">{% if not items %}<div class="kg-empty" data-empty="true">No numbers yet — add a few stats to celebrate.</div>{% else %}<div class="kg-numbers-grid">{% for item in items %}<div class="kg-numbers-item"><span class="kg-numeral" data-number="{{ item.number|integer }}">{{ item.number|integer }}</span>{% if item.label %}<span class="kg-numbers-label">{{ item.label }}</span>{% endif %}</div>{% endfor %}</div>{% endif %}</div></section>
|
||||||
1
blocks/schedule.ninjatpl
Normal file
1
blocks/schedule.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-section" data-block="kindergarten:schedule"><div class="kg-container">{% if title %}<h2 class="kg-display kg-crayon-underline" style="font-size: 2rem; margin-bottom: 1.5rem;">{{ title }}</h2>{% endif %}{% if not items %}<div class="kg-empty" data-empty="true">No schedule items yet — add a time block to get started.</div>{% else %}<ol style="list-style: none; padding: 0; margin: 0;">{% for item in items %}<li class="kg-schedule-item"><span class="kg-schedule-time">{% if item.time %}{{ item.time }}{% else %}--:--{% endif %}</span><span class="kg-schedule-activity">{% if item.activity %}{{ item.activity }}{% else %}Activity{% endif %}</span><span class="kg-schedule-icon" aria-hidden="true">{% if item.icon == "sun" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m4.93 19.07 1.41-1.41"></path><path d="m17.66 6.34 1.41-1.41"></path></svg>{% elif item.icon == "book" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>{% elif item.icon == "paint" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 11h2m-1 -1v2"></path><circle cx="13" cy="6" r="2"></circle><circle cx="19" cy="11" r="2"></circle><circle cx="6" cy="14" r="2"></circle><circle cx="10" cy="20" r="2"></circle><path d="M7.4 12.4l3.6 -2.4"></path><path d="M11.6 8.6l1.4 -0.6"></path><path d="M15 6l4 5"></path><path d="M8 16l2 4"></path></svg>{% elif item.icon == "snack" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M8 14s1.5 2 4 2 4-2 4-2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>{% elif item.icon == "play" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>{% elif item.icon == "nap" %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>{% else %}<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.8 5.8 21 7 14 2 9.3 9 8.5 12 2"></polygon></svg>{% endif %}</span></li>{% endfor %}</ol>{% endif %}</div></section>
|
||||||
1
blocks/storybook_quote.ninjatpl
Normal file
1
blocks/storybook_quote.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section class="kg-section" data-block="kindergarten:storybook_quote"><div class="kg-container"><figure class="kg-storybook"><blockquote style="margin: 0;">{% if quote %}<p class="kg-storybook-quote">"{{ quote }}"</p>{% else %}<p class="kg-storybook-quote" data-empty="true">Add a quote to inspire your readers.</p>{% endif %}{% if author %}<figcaption class="kg-storybook-author">— {{ author }}</figcaption>{% endif %}</blockquote><div>{% if illustration %}<img class="kg-storybook-illustration" src="{{ illustration|mediaURL }}" alt="Illustration accompanying the quote">{% else %}<svg viewBox="0 0 200 150" width="100%" height="auto" class="kg-storybook-illustration" role="img" aria-label="Storybook illustration"><rect width="200" height="150" rx="24" fill="hsl(var(--muted))"></rect><circle cx="60" cy="60" r="20" fill="hsl(var(--accent))"></circle><rect x="100" y="40" width="60" height="40" rx="8" fill="hsl(var(--primary))"></rect><path d="M 30 110 Q 100 90 170 110 L 170 130 L 30 130 Z" fill="hsl(var(--secondary))"></path></svg>{% endif %}</div></figure></div></section>
|
||||||
@ -1,31 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KindergartenButtonBlock renders a pill (border-radius 9999px) button with
|
|
||||||
// the sticker drop-shadow effect from spec §9.
|
|
||||||
//
|
|
||||||
// Content shape (matches built-in button): {"text": "...", "href": "...", "variant": "..."}.
|
|
||||||
func KindergartenButtonBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
label := getString(content, "text")
|
|
||||||
if label == "" {
|
|
||||||
// Some installs may store the label under "label" instead.
|
|
||||||
label = getString(content, "label")
|
|
||||||
}
|
|
||||||
href := getStringDefault(content, "href", "#")
|
|
||||||
variant := getStringDefault(content, "variant", "yellow")
|
|
||||||
switch variant {
|
|
||||||
case "red", "blue", "yellow", "green":
|
|
||||||
default:
|
|
||||||
variant = "yellow"
|
|
||||||
}
|
|
||||||
|
|
||||||
data := BigCTAData{Label: label, Href: href, ColorVariant: variant}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = kgButtonComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// kgButtonComponent renders a pill-shaped button override.
|
|
||||||
templ kgButtonComponent(data BigCTAData) {
|
|
||||||
if data.Label != "" {
|
|
||||||
<a href={ templ.SafeURL(data.Href) } class={ "kg-pill", ctaColorClass(data.ColorVariant) }>{ data.Label }</a>
|
|
||||||
} else {
|
|
||||||
<span class="kg-empty" data-empty="true">Add label and link to render this button.</span>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// kgButtonComponent renders a pill-shaped button override.
|
|
||||||
func kgButtonComponent(data BigCTAData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
if data.Label != "" {
|
|
||||||
var templ_7745c5c3_Var2 = []any{"kg-pill", ctaColorClass(data.ColorVariant)}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(data.Href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 6, Col: 36}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 6, Col: 105}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"kg-empty\" data-empty=\"true\">Add label and link to render this button.</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KindergartenCardBlock renders a soft cream card with a 4px primary-colored
|
|
||||||
// top stripe (spec §9).
|
|
||||||
//
|
|
||||||
// Content shape: {"title": "...", "body": "...", "class": "..."}. The body
|
|
||||||
// is rendered as raw HTML so it can host inline formatting.
|
|
||||||
func KindergartenCardBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
title := getString(content, "title")
|
|
||||||
body := getString(content, "body")
|
|
||||||
class := getString(content, "class")
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = kgCardComponent(title, body, class).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// kgCardComponent renders the rounded card override.
|
|
||||||
templ kgCardComponent(title, body, class string) {
|
|
||||||
<div class={ "kg-card", class }>
|
|
||||||
if title != "" {
|
|
||||||
<h3 class="kg-display" style="margin-top: 0; margin-bottom: 1rem; font-size: 1.5rem;">{ title }</h3>
|
|
||||||
}
|
|
||||||
if body != "" {
|
|
||||||
<div class="kg-text">
|
|
||||||
@templ.Raw(body)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
if title == "" && body == "" {
|
|
||||||
<div data-empty="true" class="kg-empty">Add a title or body to fill this card.</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// kgCardComponent renders the rounded card override.
|
|
||||||
func kgCardComponent(title, body, class string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
var templ_7745c5c3_Var2 = []any{"kg-card", class}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `card_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if title != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<h3 class=\"kg-display\" style=\"margin-top: 0; margin-bottom: 1rem; font-size: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `card_override.templ`, Line: 7, Col: 96}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h3>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if body != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"kg-text\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(body).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if title == "" && body == "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div data-empty=\"true\" class=\"kg-empty\">Add a title or body to fill this card.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KindergartenEmailWrapper wraps email body content in a Kindergarten-branded
|
|
||||||
// rounded card. Uses a centered 600px table with a 32px border-radius card for
|
|
||||||
// clients that support it; Outlook degrades gracefully to a square card.
|
|
||||||
func KindergartenEmailWrapper(body string, emailCtx templates.EmailContext) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = kindergartenEmailTemplate(emailCtx, body).Render(context.Background(), &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgEmailColor returns the supplied hex color or the cream/foreground/etc.
|
|
||||||
// fallback when the engine has not resolved a value for the token.
|
|
||||||
func kgEmailColor(value, fallback string) string {
|
|
||||||
if value != "" {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgEmailBg / etc. group fallbacks for the cream/navy palette per spec §10.
|
|
||||||
func kgEmailBg(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.Background, "#fdf9ed")
|
|
||||||
}
|
|
||||||
func kgEmailCard(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.Card, "#ffffff")
|
|
||||||
}
|
|
||||||
func kgEmailFg(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.Foreground, "#1a253b")
|
|
||||||
}
|
|
||||||
func kgEmailMuted(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.MutedForeground, "#5a6480")
|
|
||||||
}
|
|
||||||
func kgEmailAccent(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.Primary, "#fbcd1f")
|
|
||||||
}
|
|
||||||
func kgEmailAccentFg(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.PrimaryForeground, "#1a253b")
|
|
||||||
}
|
|
||||||
func kgEmailBorder(ctx templates.EmailContext) string {
|
|
||||||
return kgEmailColor(ctx.Colors.Border, "#e6d9b3")
|
|
||||||
}
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// kindergartenEmailTemplate is the Kindergarten-branded email wrapper. Renders
|
|
||||||
// a centered 600px table with a 32px-radius card. Outlook degrades to square.
|
|
||||||
templ kindergartenEmailTemplate(emailCtx templates.EmailContext, body string) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
||||||
<meta name="x-apple-disable-message-reformatting"/>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
|
||||||
<!--[if mso]>
|
|
||||||
<noscript>
|
|
||||||
<xml>
|
|
||||||
<o:OfficeDocumentSettings>
|
|
||||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
|
||||||
</o:OfficeDocumentSettings>
|
|
||||||
</xml>
|
|
||||||
</noscript>
|
|
||||||
<![endif]-->
|
|
||||||
<title>{ emailCtx.SiteSettings.SiteName }</title>
|
|
||||||
<style type="text/css">
|
|
||||||
body, table, td, p, a, li, blockquote { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
|
||||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
|
||||||
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
|
||||||
body { margin: 0 !important; padding: 0 !important; width: 100% !important; }
|
|
||||||
a[x-apple-data-detectors] { color: inherit !important; text-decoration: none !important; }
|
|
||||||
h1, h2, h3, h4, h5, h6 { font-family: 'Quicksand', 'Nunito', -apple-system, sans-serif; font-weight: 700; }
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
.email-container { width: 100% !important; max-width: 100% !important; }
|
|
||||||
.content-padding { padding-left: 24px !important; padding-right: 24px !important; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body style={ fmt.Sprintf("background-color: %s; margin: 0; padding: 0; font-family: 'Nunito', 'Quicksand', -apple-system, sans-serif;", kgEmailBg(emailCtx)) }>
|
|
||||||
if emailCtx.PreviewText != "" {
|
|
||||||
<div style="display: none; max-height: 0; overflow: hidden; mso-hide: all;">
|
|
||||||
{ emailCtx.PreviewText }
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td align="center" style={ fmt.Sprintf("padding: 48px 10px; background-color: %s;", kgEmailBg(emailCtx)) }>
|
|
||||||
<table role="presentation" class="email-container" width="600" cellspacing="0" cellpadding="0" border="0" style={ fmt.Sprintf("max-width: 600px; background-color: %s; border: 1px solid %s; border-radius: 32px;", kgEmailCard(emailCtx), kgEmailBorder(emailCtx)) }>
|
|
||||||
<tr>
|
|
||||||
<td align="center" style={ fmt.Sprintf("padding: 32px 40px; background-color: %s; border-bottom: 2px dashed %s; border-radius: 32px 32px 0 0;", kgEmailCard(emailCtx), kgEmailBorder(emailCtx)) }>
|
|
||||||
if emailCtx.SiteSettings.LogoURL != "" {
|
|
||||||
<img src={ emailCtx.SiteSettings.LogoURL } alt={ emailCtx.SiteSettings.SiteName } style="max-height: 48px; width: auto; display: block;"/>
|
|
||||||
} else if emailCtx.SiteSettings.SiteName != "" {
|
|
||||||
<h1 style={ fmt.Sprintf("margin: 0; font-size: 28px; font-weight: 700; color: %s; letter-spacing: -0.5px; font-family: 'Quicksand', 'Nunito', sans-serif;", kgEmailFg(emailCtx)) }>
|
|
||||||
{ emailCtx.SiteSettings.SiteName }
|
|
||||||
</h1>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="content-padding" style={ fmt.Sprintf("padding: 40px 48px; color: %s; font-size: 16px; line-height: 1.7; font-family: 'Nunito', sans-serif;", kgEmailFg(emailCtx)) }>
|
|
||||||
@templ.Raw(body)
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center" style={ fmt.Sprintf("padding: 0 48px 32px 48px; background-color: %s;", kgEmailCard(emailCtx)) }>
|
|
||||||
if emailCtx.SiteSettings.SiteURL != "" {
|
|
||||||
<a href={ templ.SafeURL(emailCtx.SiteSettings.SiteURL) } style={ fmt.Sprintf("display: inline-block; padding: 16px 32px; border-radius: 9999px; background-color: %s; color: %s; text-decoration: none; font-family: 'Quicksand', sans-serif; font-weight: 700; font-size: 16px;", kgEmailAccent(emailCtx), kgEmailAccentFg(emailCtx)) }>
|
|
||||||
Visit { emailCtx.SiteSettings.SiteName }
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style={ fmt.Sprintf("padding: 32px 48px; border-top: 2px dashed %s; border-radius: 0 0 32px 32px; background-color: %s;", kgEmailBorder(emailCtx), kgEmailCard(emailCtx)) }>
|
|
||||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<p style={ fmt.Sprintf("margin: 0 0 8px; font-size: 14px; font-weight: 700; color: %s; font-family: 'Quicksand', sans-serif;", kgEmailFg(emailCtx)) }>
|
|
||||||
👋 { emailCtx.SiteSettings.SiteName }
|
|
||||||
</p>
|
|
||||||
if emailCtx.SiteSettings.SupportEmail != "" {
|
|
||||||
<p style={ fmt.Sprintf("margin: 0 0 8px; font-size: 13px; color: %s;", kgEmailMuted(emailCtx)) }>
|
|
||||||
Need a hand? { emailCtx.SiteSettings.SupportEmail }
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
if emailCtx.UnsubscribeURL != "" {
|
|
||||||
<p style={ fmt.Sprintf("margin: 0; font-size: 11px; color: %s;", kgEmailMuted(emailCtx)) }>
|
|
||||||
<a href={ templ.SafeURL(emailCtx.UnsubscribeURL) } style={ fmt.Sprintf("color: %s; text-decoration: none;", kgEmailMuted(emailCtx)) }>
|
|
||||||
Unsubscribe
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
@ -1,406 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// kindergartenEmailTemplate is the Kindergarten-branded email wrapper. Renders
|
|
||||||
// a centered 600px table with a 32px-radius card. Outlook degrades to square.
|
|
||||||
func kindergartenEmailTemplate(emailCtx templates.EmailContext, body string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><meta name=\"x-apple-disable-message-reformatting\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><!--[if mso]>\n\t\t\t<noscript>\n\t\t\t\t<xml>\n\t\t\t\t\t<o:OfficeDocumentSettings>\n\t\t\t\t\t\t<o:PixelsPerInch>96</o:PixelsPerInch>\n\t\t\t\t\t</o:OfficeDocumentSettings>\n\t\t\t\t</xml>\n\t\t\t</noscript>\n\t\t\t<![endif]--><title>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 28, Col: 42}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><style type=\"text/css\">\n\t\t\t\tbody, table, td, p, a, li, blockquote { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }\n\t\t\t\ttable, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }\n\t\t\t\timg { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }\n\t\t\t\tbody { margin: 0 !important; padding: 0 !important; width: 100% !important; }\n\t\t\t\ta[x-apple-data-detectors] { color: inherit !important; text-decoration: none !important; }\n\t\t\t\th1, h2, h3, h4, h5, h6 { font-family: 'Quicksand', 'Nunito', -apple-system, sans-serif; font-weight: 700; }\n\t\t\t\t@media only screen and (max-width: 620px) {\n\t\t\t\t\t.email-container { width: 100% !important; max-width: 100% !important; }\n\t\t\t\t\t.content-padding { padding-left: 24px !important; padding-right: 24px !important; }\n\t\t\t\t}\n\t\t\t</style></head><body style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("background-color: %s; margin: 0; padding: 0; font-family: 'Nunito', 'Quicksand', -apple-system, sans-serif;", kgEmailBg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 42, Col: 159}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.PreviewText != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div style=\"display: none; max-height: 0; overflow: hidden; mso-hide: all;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.PreviewText)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 45, Col: 27}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<table role=\"presentation\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td align=\"center\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("padding: 48px 10px; background-color: %s;", kgEmailBg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 50, Col: 109}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"><table role=\"presentation\" class=\"email-container\" width=\"600\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("max-width: 600px; background-color: %s; border: 1px solid %s; border-radius: 32px;", kgEmailCard(emailCtx), kgEmailBorder(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 51, Col: 265}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"><tr><td align=\"center\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("padding: 32px 40px; background-color: %s; border-bottom: 2px dashed %s; border-radius: 32px 32px 0 0;", kgEmailCard(emailCtx), kgEmailBorder(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 53, Col: 199}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.SiteSettings.LogoURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<img src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(emailCtx.SiteSettings.LogoURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 55, Col: 50}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" alt=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 55, Col: 89}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" style=\"max-height: 48px; width: auto; display: block;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else if emailCtx.SiteSettings.SiteName != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<h1 style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var10 string
|
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("margin: 0; font-size: 28px; font-weight: 700; color: %s; letter-spacing: -0.5px; font-family: 'Quicksand', 'Nunito', sans-serif;", kgEmailFg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 57, Col: 186}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 string
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 58, Col: 43}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</td></tr><tr><td class=\"content-padding\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("padding: 40px 48px; color: %s; font-size: 16px; line-height: 1.7; font-family: 'Nunito', sans-serif;", kgEmailFg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 64, Col: 180}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(body).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</td></tr><tr><td align=\"center\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var13 string
|
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("padding: 0 48px 32px 48px; background-color: %s;", kgEmailCard(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 69, Col: 121}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.SiteSettings.SiteURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var14 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(emailCtx.SiteSettings.SiteURL))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 71, Col: 64}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var15 string
|
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("display: inline-block; padding: 16px 32px; border-radius: 9999px; background-color: %s; color: %s; text-decoration: none; font-family: 'Quicksand', sans-serif; font-weight: 700; font-size: 16px;", kgEmailAccent(emailCtx), kgEmailAccentFg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 71, Col: 336}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\">Visit ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var16 string
|
|
||||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 72, Col: 49}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</td></tr><tr><td style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var17 string
|
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("padding: 32px 48px; border-top: 2px dashed %s; border-radius: 0 0 32px 32px; background-color: %s;", kgEmailBorder(emailCtx), kgEmailCard(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 78, Col: 181}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\"><table role=\"presentation\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr><td align=\"center\"><p style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var18 string
|
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("margin: 0 0 8px; font-size: 14px; font-weight: 700; color: %s; font-family: 'Quicksand', sans-serif;", kgEmailFg(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 82, Col: 159}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\">👋 ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var19 string
|
|
||||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 83, Col: 50}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.SiteSettings.SupportEmail != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<p style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var20 string
|
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("margin: 0 0 8px; font-size: 13px; color: %s;", kgEmailMuted(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 86, Col: 107}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\">Need a hand? ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var21 string
|
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SupportEmail)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 87, Col: 63}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if emailCtx.UnsubscribeURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<p style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var22 string
|
|
||||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("margin: 0; font-size: 11px; color: %s;", kgEmailMuted(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 91, Col: 101}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var23 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(emailCtx.UnsubscribeURL))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 92, Col: 62}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" style=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var24 string
|
|
||||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(fmt.Sprintf("color: %s; text-decoration: none;", kgEmailMuted(emailCtx)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 92, Col: 145}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\">Unsubscribe</a></p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</td></tr></table></td></tr></table></td></tr></table></body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
64
embed.go
64
embed.go
@ -1,64 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/plugin"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed assets/*
|
|
||||||
var assetsFS embed.FS
|
|
||||||
|
|
||||||
//go:embed schemas/*
|
|
||||||
var schemasFS embed.FS
|
|
||||||
|
|
||||||
//go:embed presets.json
|
|
||||||
var presetsData []byte
|
|
||||||
|
|
||||||
//go:embed fonts.json
|
|
||||||
var fontsData []byte
|
|
||||||
|
|
||||||
//go:embed plugin.mod
|
|
||||||
var pluginModBytes []byte
|
|
||||||
|
|
||||||
// Assets returns the embedded assets filesystem.
|
|
||||||
func Assets() fs.FS {
|
|
||||||
sub, _ := fs.Sub(assetsFS, "assets")
|
|
||||||
return sub
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schemas returns the embedded schemas filesystem.
|
|
||||||
func Schemas() fs.FS {
|
|
||||||
sub, _ := fs.Sub(schemasFS, "schemas")
|
|
||||||
return sub
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssetsHandler returns an http.Handler that serves the embedded assets.
|
|
||||||
func AssetsHandler() http.Handler {
|
|
||||||
return http.FileServer(http.FS(Assets()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ThemePresets returns the embedded theme presets JSON.
|
|
||||||
func ThemePresets() []byte {
|
|
||||||
return presetsData
|
|
||||||
}
|
|
||||||
|
|
||||||
// BundledFonts returns the embedded fonts manifest JSON.
|
|
||||||
func BundledFonts() []byte {
|
|
||||||
return fontsData
|
|
||||||
}
|
|
||||||
|
|
||||||
// ThemeCSSManifest returns the CSS manifest used by host Tailwind to pick up
|
|
||||||
// theme-owned utility classes (crayon underline, dotted-paper background,
|
|
||||||
// sticker drop-shadow, font-family fallback stacks, etc.).
|
|
||||||
func ThemeCSSManifest() *plugin.CSSManifest {
|
|
||||||
css, err := assetsFS.ReadFile("assets/style.css")
|
|
||||||
if err != nil {
|
|
||||||
return &plugin.CSSManifest{}
|
|
||||||
}
|
|
||||||
return &plugin.CSSManifest{
|
|
||||||
InputCSSAppend: string(css),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
53
footer.go
53
footer.go
@ -1,53 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FooterBlockMeta defines metadata for the friendly footer block.
|
|
||||||
var FooterBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "footer",
|
|
||||||
Title: "Friendly Footer",
|
|
||||||
Description: "Mascot wave, signup, contact, crayon-rule divider.",
|
|
||||||
Category: blocks.CategoryLayout,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterSocial is a single social link entry.
|
|
||||||
type FooterSocial struct {
|
|
||||||
Platform string
|
|
||||||
Href string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterData is the renderer input.
|
|
||||||
type FooterData struct {
|
|
||||||
ShowSignup bool
|
|
||||||
MascotName string
|
|
||||||
SocialLinks []FooterSocial
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterBlock renders the friendly footer.
|
|
||||||
// Content shape: {showSignup,mascotName,socialLinks}.
|
|
||||||
func FooterBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getSlice(content, "socialLinks")
|
|
||||||
links := make([]FooterSocial, 0, len(raw))
|
|
||||||
for _, m := range raw {
|
|
||||||
links = append(links, FooterSocial{
|
|
||||||
Platform: getString(m, "platform"),
|
|
||||||
Href: getString(m, "href"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data := FooterData{
|
|
||||||
ShowSignup: getBool(content, "showSignup", true),
|
|
||||||
MascotName: getStringDefault(content, "mascotName", "Pip"),
|
|
||||||
SocialLinks: links,
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = footerComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
64
footer.templ
64
footer.templ
@ -1,64 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// footerComponent renders the friendly footer.
|
|
||||||
templ footerComponent(data FooterData) {
|
|
||||||
<div class="kg-footer" data-block="kindergarten:footer">
|
|
||||||
<div class="kg-container">
|
|
||||||
<div class="kg-footer-mascot">
|
|
||||||
<span aria-hidden="true">👋</span>
|
|
||||||
<span>{ data.MascotName } says hi!</span>
|
|
||||||
</div>
|
|
||||||
if data.ShowSignup {
|
|
||||||
<form class="kg-footer-signup" aria-label={ "Newsletter signup" } method="post" action="/subscribe">
|
|
||||||
<input type="email" name="email" placeholder="Your email" aria-label="Email address" required />
|
|
||||||
<button type="submit" class="kg-pill kg-pill-yellow">Sign up</button>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
if len(data.SocialLinks) > 0 {
|
|
||||||
<div class="kg-social-row" aria-label={ "Social media" }>
|
|
||||||
for _, link := range data.SocialLinks {
|
|
||||||
<a href={ templ.SafeURL(link.Href) } class="kg-social-link" aria-label={ socialLabel(link.Platform) }>
|
|
||||||
@socialIcon(link.Platform)
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
// socialLabel renders an accessible label for the icon link.
|
|
||||||
func socialLabel(platform string) string {
|
|
||||||
switch platform {
|
|
||||||
case "facebook":
|
|
||||||
return "Visit our Facebook"
|
|
||||||
case "instagram":
|
|
||||||
return "Visit our Instagram"
|
|
||||||
case "youtube":
|
|
||||||
return "Visit our YouTube"
|
|
||||||
case "tiktok":
|
|
||||||
return "Visit our TikTok"
|
|
||||||
case "email":
|
|
||||||
return "Send us an email"
|
|
||||||
default:
|
|
||||||
return "Open social link"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// socialIcon renders a small social icon (Lucide-style stroke).
|
|
||||||
templ socialIcon(platform string) {
|
|
||||||
switch platform {
|
|
||||||
case "facebook":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg>
|
|
||||||
case "instagram":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg>
|
|
||||||
case "youtube":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"/><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"/></svg>
|
|
||||||
case "tiktok":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12a4 4 0 1 0 4 4V4a5 5 0 0 0 5 5"/></svg>
|
|
||||||
case "email":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
|
|
||||||
default:
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/></svg>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
216
footer_templ.go
216
footer_templ.go
@ -1,216 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// footerComponent renders the friendly footer.
|
|
||||||
func footerComponent(data FooterData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"kg-footer\" data-block=\"kindergarten:footer\"><div class=\"kg-container\"><div class=\"kg-footer-mascot\"><span aria-hidden=\"true\">👋</span> <span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.MascotName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 9, Col: 27}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " says hi!</span></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.ShowSignup {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<form class=\"kg-footer-signup\" aria-label=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue("Newsletter signup")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 12, Col: 67}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" method=\"post\" action=\"/subscribe\"><input type=\"email\" name=\"email\" placeholder=\"Your email\" aria-label=\"Email address\" required> <button type=\"submit\" class=\"kg-pill kg-pill-yellow\">Sign up</button></form>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(data.SocialLinks) > 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"kg-social-row\" aria-label=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue("Social media")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 18, Col: 58}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, link := range data.SocialLinks {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(link.Href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 20, Col: 40}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" class=\"kg-social-link\" aria-label=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.ResolveAttributeValue(socialLabel(link.Platform))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 20, Col: 105}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = socialIcon(link.Platform).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// socialLabel renders an accessible label for the icon link.
|
|
||||||
func socialLabel(platform string) string {
|
|
||||||
switch platform {
|
|
||||||
case "facebook":
|
|
||||||
return "Visit our Facebook"
|
|
||||||
case "instagram":
|
|
||||||
return "Visit our Instagram"
|
|
||||||
case "youtube":
|
|
||||||
return "Visit our YouTube"
|
|
||||||
case "tiktok":
|
|
||||||
return "Visit our TikTok"
|
|
||||||
case "email":
|
|
||||||
return "Send us an email"
|
|
||||||
default:
|
|
||||||
return "Open social link"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// socialIcon renders a small social icon (Lucide-style stroke).
|
|
||||||
func socialIcon(platform string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var7 == nil {
|
|
||||||
templ_7745c5c3_Var7 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
switch platform {
|
|
||||||
case "facebook":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "instagram":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"5\" ry=\"5\"></rect><path d=\"M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z\"></path><line x1=\"17.5\" y1=\"6.5\" x2=\"17.51\" y2=\"6.5\"></line></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "youtube":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z\"></path><polygon points=\"9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02\"></polygon></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "tiktok":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 12a4 4 0 1 0 4 4V4a5 5 0 0 0 5 5\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "email":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z\"></path><polyline points=\"22,6 12,13 2,6\"></polyline></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GalleryOfArtBlockMeta defines metadata for the gallery of art block.
|
|
||||||
var GalleryOfArtBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "gallery_of_art",
|
|
||||||
Title: "Gallery of Art",
|
|
||||||
Description: "Polaroid-style grid for kid artwork.",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// GalleryArt represents a single artwork entry.
|
|
||||||
type GalleryArt struct {
|
|
||||||
Image string
|
|
||||||
ChildName string
|
|
||||||
Age int
|
|
||||||
}
|
|
||||||
|
|
||||||
// GalleryData is the renderer input.
|
|
||||||
type GalleryData struct {
|
|
||||||
Title string
|
|
||||||
ShowChildName bool
|
|
||||||
Items []GalleryArt
|
|
||||||
}
|
|
||||||
|
|
||||||
// GalleryOfArtBlock renders the polaroid grid.
|
|
||||||
// Content shape: {title,showChildName,items:[{image,childName,age}]}.
|
|
||||||
//
|
|
||||||
// Privacy: when showChildName=false, no child names are rendered.
|
|
||||||
func GalleryOfArtBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getSlice(content, "items")
|
|
||||||
items := make([]GalleryArt, 0, len(raw))
|
|
||||||
for _, m := range raw {
|
|
||||||
items = append(items, GalleryArt{
|
|
||||||
Image: getString(m, "image"),
|
|
||||||
ChildName: getString(m, "childName"),
|
|
||||||
Age: getInt(m, "age", 0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data := GalleryData{
|
|
||||||
Title: getString(content, "title"),
|
|
||||||
ShowChildName: getBool(content, "showChildName", true),
|
|
||||||
Items: items,
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = galleryOfArtComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// galleryOfArtComponent renders a polaroid-style grid of artworks.
|
|
||||||
templ galleryOfArtComponent(data GalleryData) {
|
|
||||||
<section class="kg-section" data-block="kindergarten:gallery_of_art">
|
|
||||||
<div class="kg-container">
|
|
||||||
if data.Title != "" {
|
|
||||||
<h2 class="kg-display kg-crayon-underline" style="font-size: 2rem; margin-bottom: 1.5rem;">{ data.Title }</h2>
|
|
||||||
}
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
<div class="kg-empty" data-empty="true">No artworks yet — add one to fill the gallery wall.</div>
|
|
||||||
} else {
|
|
||||||
<div class="kg-gallery-grid">
|
|
||||||
for _, art := range data.Items {
|
|
||||||
<figure class="kg-polaroid">
|
|
||||||
if art.Image != "" {
|
|
||||||
<img src={ blocks.ResolveMediaPath(art.Image) } alt={ polaroidAlt(art, data.ShowChildName) } />
|
|
||||||
} else {
|
|
||||||
<span class="kg-polaroid-image" role="img" aria-label="Placeholder for child artwork"></span>
|
|
||||||
}
|
|
||||||
<figcaption class="kg-polaroid-caption">
|
|
||||||
if data.ShowChildName && art.ChildName != "" {
|
|
||||||
<span>{ art.ChildName }</span>
|
|
||||||
}
|
|
||||||
if data.ShowChildName && art.ChildName != "" && art.Age > 0 {
|
|
||||||
{ ", " }
|
|
||||||
}
|
|
||||||
if art.Age > 0 {
|
|
||||||
<span>{ fmt.Sprintf("age %d", art.Age) }</span>
|
|
||||||
}
|
|
||||||
</figcaption>
|
|
||||||
</figure>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
// polaroidAlt produces a respectful alt-text that honours the privacy toggle.
|
|
||||||
func polaroidAlt(art GalleryArt, showChildName bool) string {
|
|
||||||
if showChildName && art.ChildName != "" {
|
|
||||||
return fmt.Sprintf("Artwork by %s", art.ChildName)
|
|
||||||
}
|
|
||||||
return "Children's artwork"
|
|
||||||
}
|
|
||||||
@ -1,197 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// galleryOfArtComponent renders a polaroid-style grid of artworks.
|
|
||||||
func galleryOfArtComponent(data GalleryData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-section\" data-block=\"kindergarten:gallery_of_art\"><div class=\"kg-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Title != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2 class=\"kg-display kg-crayon-underline\" style=\"font-size: 2rem; margin-bottom: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 14, Col: 107}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"kg-empty\" data-empty=\"true\">No artworks yet — add one to fill the gallery wall.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"kg-gallery-grid\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, art := range data.Items {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<figure class=\"kg-polaroid\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if art.Image != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<img src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(blocks.ResolveMediaPath(art.Image))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 23, Col: 53}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" alt=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(polaroidAlt(art, data.ShowChildName))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 23, Col: 98}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<span class=\"kg-polaroid-image\" role=\"img\" aria-label=\"Placeholder for child artwork\"></span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<figcaption class=\"kg-polaroid-caption\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.ShowChildName && art.ChildName != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(art.ChildName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 29, Col: 30}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if data.ShowChildName && art.ChildName != "" && art.Age > 0 {
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(", ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 32, Col: 15}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if art.Age > 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("age %d", art.Age))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `gallery_of_art.templ`, Line: 35, Col: 47}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</figcaption></figure>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// polaroidAlt produces a respectful alt-text that honours the privacy toggle.
|
|
||||||
func polaroidAlt(art GalleryArt, showChildName bool) string {
|
|
||||||
if showChildName && art.ChildName != "" {
|
|
||||||
return fmt.Sprintf("Artwork by %s", art.ChildName)
|
|
||||||
}
|
|
||||||
return "Children's artwork"
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
20
go.mod
20
go.mod
@ -1,20 +0,0 @@
|
|||||||
module git.dev.alexdunmow.com/block/themes/kindergarten
|
|
||||||
|
|
||||||
go 1.26.4
|
|
||||||
|
|
||||||
require (
|
|
||||||
git.dev.alexdunmow.com/block/core v0.15.2
|
|
||||||
github.com/a-h/templ v0.3.1020
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
connectrpc.com/connect v1.20.0 // indirect
|
|
||||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
|
||||||
github.com/jackc/pgx/v5 v5.9.2 // indirect
|
|
||||||
golang.org/x/mod v0.34.0 // indirect
|
|
||||||
golang.org/x/text v0.36.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
|
||||||
)
|
|
||||||
46
go.sum
46
go.sum
@ -1,46 +0,0 @@
|
|||||||
connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ=
|
|
||||||
connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4=
|
|
||||||
git.dev.alexdunmow.com/block/core v0.15.2 h1:qTjJxa1pClxwehkdTxXiJDpHQLr5DoXBUCa40QRO0L8=
|
|
||||||
git.dev.alexdunmow.com/block/core v0.15.2/go.mod h1:A+mgA9oeWoPhXruv4Mjpywwl2A9B5I3cKzlJjalBdlE=
|
|
||||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
|
||||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
|
|
||||||
github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
|
||||||
github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
|
|
||||||
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
|
||||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
|
||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
|
||||||
github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZopYU=
|
|
||||||
github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0=
|
|
||||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
|
||||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
|
||||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
|
||||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
|
||||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
|
||||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
|
||||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KindergartenHeadingBlock renders a heading with the Kindergarten crayon-underline
|
|
||||||
// accent and an optional numeral step badge.
|
|
||||||
//
|
|
||||||
// Content expects: {"text": "...", "level": 1-6, "textClass": "...", "step": 1-9}
|
|
||||||
func KindergartenHeadingBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
text := getString(content, "text")
|
|
||||||
textClass := getString(content, "textClass")
|
|
||||||
level := parseHeadingLevel(content)
|
|
||||||
step := parseStep(content)
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = kgHeadingComponent(level, text, textClass, step).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseHeadingLevel parses the level from content, defaulting to 2.
|
|
||||||
func parseHeadingLevel(content map[string]any) int {
|
|
||||||
if level, ok := content["level"].(float64); ok {
|
|
||||||
l := int(level)
|
|
||||||
if l >= 1 && l <= 6 {
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if level, ok := content["level"].(int); ok {
|
|
||||||
if level >= 1 && level <= 6 {
|
|
||||||
return level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if level, ok := content["level"].(string); ok {
|
|
||||||
if l, err := strconv.Atoi(level); err == nil && l >= 1 && l <= 6 {
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseStep parses an optional step badge (1-9). Returns 0 if not provided
|
|
||||||
// or out of range; renderer skips the badge when step == 0.
|
|
||||||
func parseStep(content map[string]any) int {
|
|
||||||
if v, ok := content["step"].(float64); ok {
|
|
||||||
s := int(v)
|
|
||||||
if s >= 1 && s <= 9 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v, ok := content["step"].(int); ok {
|
|
||||||
if v >= 1 && v <= 9 {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v, ok := content["step"].(string); ok {
|
|
||||||
if s, err := strconv.Atoi(v); err == nil && s >= 1 && s <= 9 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// kgHeadingBaseClass returns size classes per heading level (Tailwind-like
|
|
||||||
// utilities scoped to the kindergarten CSS).
|
|
||||||
func kgHeadingBaseClass(level int) string {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
return "kg-display kg-crayon-underline"
|
|
||||||
case 2:
|
|
||||||
return "kg-display kg-crayon-underline"
|
|
||||||
case 3:
|
|
||||||
return "kg-display"
|
|
||||||
case 4:
|
|
||||||
return "kg-display"
|
|
||||||
case 5:
|
|
||||||
return "kg-display"
|
|
||||||
case 6:
|
|
||||||
return "kg-display"
|
|
||||||
default:
|
|
||||||
return "kg-display"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgHeadingComponent renders a heading with Kindergarten accents, optionally
|
|
||||||
// preceded by a circular step badge (e.g. for "Step 1", "Step 2" sections).
|
|
||||||
templ kgHeadingComponent(level int, text, textClass string, step int) {
|
|
||||||
if step > 0 {
|
|
||||||
<div class="kg-heading-stepped">
|
|
||||||
<span class="kg-heading-step-badge" aria-hidden="true">{ fmt.Sprintf("%d", step) }</span>
|
|
||||||
@kgHeadingTag(level, text, textClass)
|
|
||||||
</div>
|
|
||||||
} else {
|
|
||||||
@kgHeadingTag(level, text, textClass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgHeadingTag emits the actual <h1>..<h6> tag at the requested level.
|
|
||||||
templ kgHeadingTag(level int, text, textClass string) {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
<h1 class={ kgHeadingBaseClass(1), textClass } style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;">{ text }</h1>
|
|
||||||
case 2:
|
|
||||||
<h2 class={ kgHeadingBaseClass(2), textClass } style="font-size: 2.25rem; margin: 0;">{ text }</h2>
|
|
||||||
case 3:
|
|
||||||
<h3 class={ kgHeadingBaseClass(3), textClass } style="font-size: 1.75rem; margin: 0;">{ text }</h3>
|
|
||||||
case 4:
|
|
||||||
<h4 class={ kgHeadingBaseClass(4), textClass } style="font-size: 1.5rem; margin: 0;">{ text }</h4>
|
|
||||||
case 5:
|
|
||||||
<h5 class={ kgHeadingBaseClass(5), textClass } style="font-size: 1.25rem; margin: 0;">{ text }</h5>
|
|
||||||
case 6:
|
|
||||||
<h6 class={ kgHeadingBaseClass(6), textClass } style="font-size: 1.125rem; margin: 0;">{ text }</h6>
|
|
||||||
default:
|
|
||||||
<h2 class={ kgHeadingBaseClass(2), textClass } style="font-size: 2.25rem; margin: 0;">{ text }</h2>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,373 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// kgHeadingBaseClass returns size classes per heading level (Tailwind-like
|
|
||||||
// utilities scoped to the kindergarten CSS).
|
|
||||||
func kgHeadingBaseClass(level int) string {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
return "kg-display kg-crayon-underline"
|
|
||||||
case 2:
|
|
||||||
return "kg-display kg-crayon-underline"
|
|
||||||
case 3:
|
|
||||||
return "kg-display"
|
|
||||||
case 4:
|
|
||||||
return "kg-display"
|
|
||||||
case 5:
|
|
||||||
return "kg-display"
|
|
||||||
case 6:
|
|
||||||
return "kg-display"
|
|
||||||
default:
|
|
||||||
return "kg-display"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgHeadingComponent renders a heading with Kindergarten accents, optionally
|
|
||||||
// preceded by a circular step badge (e.g. for "Step 1", "Step 2" sections).
|
|
||||||
func kgHeadingComponent(level int, text, textClass string, step int) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
if step > 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"kg-heading-stepped\"><span class=\"kg-heading-step-badge\" aria-hidden=\"true\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", step))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 31, Col: 83}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = kgHeadingTag(level, text, textClass).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = kgHeadingTag(level, text, textClass).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// kgHeadingTag emits the actual <h1>..<h6> tag at the requested level.
|
|
||||||
func kgHeadingTag(level int, text, textClass string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var3 == nil {
|
|
||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
var templ_7745c5c3_Var4 = []any{kgHeadingBaseClass(1), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<h1 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" style=\"font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 43, Col: 112}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
var templ_7745c5c3_Var7 = []any{kgHeadingBaseClass(2), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<h2 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var7).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" style=\"font-size: 2.25rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 45, Col: 95}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
var templ_7745c5c3_Var10 = []any{kgHeadingBaseClass(3), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<h3 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 string
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var10).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" style=\"font-size: 1.75rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 47, Col: 95}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</h3>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
var templ_7745c5c3_Var13 = []any{kgHeadingBaseClass(4), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var13...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<h4 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var14 string
|
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var13).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\" style=\"font-size: 1.5rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var15 string
|
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 49, Col: 94}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</h4>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 5:
|
|
||||||
var templ_7745c5c3_Var16 = []any{kgHeadingBaseClass(5), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<h5 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var17 string
|
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var16).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" style=\"font-size: 1.25rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var18 string
|
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 51, Col: 95}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</h5>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
var templ_7745c5c3_Var19 = []any{kgHeadingBaseClass(6), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var19...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<h6 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var20 string
|
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var19).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" style=\"font-size: 1.125rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var21 string
|
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 53, Col: 96}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</h6>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
var templ_7745c5c3_Var22 = []any{kgHeadingBaseClass(2), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var22...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<h2 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var23 string
|
|
||||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var22).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" style=\"font-size: 2.25rem; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var24 string
|
|
||||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 55, Col: 95}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
63
helpers.go
63
helpers.go
@ -1,63 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// getString extracts a string value from content map.
|
|
||||||
func getString(content map[string]any, key string) string {
|
|
||||||
if v, ok := content[key].(string); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStringDefault extracts a string value from content with a fallback.
|
|
||||||
func getStringDefault(content map[string]any, key, def string) string {
|
|
||||||
if v, ok := content[key].(string); ok && v != "" {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return def
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBool extracts a bool value from content. Accepts native bool, "true"/"false"
|
|
||||||
// strings, and the JSON-encoded float forms ("true" via 1, 0). Defaults to def.
|
|
||||||
func getBool(content map[string]any, key string, def bool) bool {
|
|
||||||
switch v := content[key].(type) {
|
|
||||||
case bool:
|
|
||||||
return v
|
|
||||||
case string:
|
|
||||||
switch v {
|
|
||||||
case "true":
|
|
||||||
return true
|
|
||||||
case "false":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
return v != 0
|
|
||||||
}
|
|
||||||
return def
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInt extracts an int value from content map (handles float64 from JSON).
|
|
||||||
func getInt(content map[string]any, key string, defaultVal int) int {
|
|
||||||
if v, ok := content[key].(float64); ok {
|
|
||||||
return int(v)
|
|
||||||
}
|
|
||||||
if v, ok := content[key].(int); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return defaultVal
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSlice extracts a slice of maps from content. If the underlying value is
|
|
||||||
// not a JSON array of objects (e.g. malformed content provides a bare string),
|
|
||||||
// the function returns nil so renderers can fall back to their empty state.
|
|
||||||
func getSlice(content map[string]any, key string) []map[string]any {
|
|
||||||
if v, ok := content[key].([]any); ok {
|
|
||||||
result := make([]map[string]any, 0, len(v))
|
|
||||||
for _, item := range v {
|
|
||||||
if m, ok := item.(map[string]any); ok {
|
|
||||||
result = append(result, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
17
main.go
17
main.go
@ -1,17 +0,0 @@
|
|||||||
//go:build wasip1
|
|
||||||
|
|
||||||
// Package main compiles the kindergarten theme to a wasip1 reactor-mode wasm guest
|
|
||||||
// (WO-WZ-015). The .so build path is retired; `ninja plugin build` produces the
|
|
||||||
// .bnp artifact the registry serves.
|
|
||||||
//
|
|
||||||
// Reactor mode: the host runs `_initialize` once per pooled instance, which
|
|
||||||
// runs this init func (hence wasmguest.Serve) before any bn_invoke. Serve is
|
|
||||||
// non-blocking; all theme work then arrives over the ABI hook calls. main is
|
|
||||||
// never called.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "git.dev.alexdunmow.com/block/core/plugin/wasmguest"
|
|
||||||
|
|
||||||
func init() { wasmguest.Serve(Registration) }
|
|
||||||
|
|
||||||
func main() {} // never called — reactor mode
|
|
||||||
532
manifest.yaml
Normal file
532
manifest.yaml
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
# Kindergarten theme — codeless .bnp manifest (WO-WZ-021 Phase B).
|
||||||
|
# Synthesized into manifest.pb by `ninja plugin build` (no plugin.wasm).
|
||||||
|
theme_presets: presets.json
|
||||||
|
bundled_fonts: fonts.json
|
||||||
|
master_pages: master_pages.json
|
||||||
|
|
||||||
|
system_templates:
|
||||||
|
- key: kindergarten
|
||||||
|
title: Kindergarten
|
||||||
|
description: "Primary-colored, hand-lettered theme for schools, daycares, toy shops, museums, and kids' publishers."
|
||||||
|
|
||||||
|
page_templates:
|
||||||
|
- system: kindergarten
|
||||||
|
key: default
|
||||||
|
title: Default
|
||||||
|
description: "Standard rounded layout with header, main, footer"
|
||||||
|
slots: [header, main, footer]
|
||||||
|
- system: kindergarten
|
||||||
|
key: landing
|
||||||
|
title: Landing
|
||||||
|
description: "Mascot-led hero plus stacked feature sections"
|
||||||
|
slots: [hero, main, cta, footer]
|
||||||
|
- system: kindergarten
|
||||||
|
key: article
|
||||||
|
title: Story Page
|
||||||
|
description: "Picture-book reading layout for blog posts and stories"
|
||||||
|
slots: [header, main, aside, footer]
|
||||||
|
- system: kindergarten
|
||||||
|
key: full-width
|
||||||
|
title: Full Width
|
||||||
|
description: "Edge-to-edge gallery / classroom showcase"
|
||||||
|
slots: [header, main, footer]
|
||||||
|
|
||||||
|
template_overrides:
|
||||||
|
- { template: kindergarten, block: heading }
|
||||||
|
- { template: kindergarten, block: text }
|
||||||
|
- { template: kindergarten, block: button }
|
||||||
|
- { template: kindergarten, block: card }
|
||||||
|
|
||||||
|
email_wrappers:
|
||||||
|
- kindergarten
|
||||||
|
|
||||||
|
css:
|
||||||
|
input_css_append: |
|
||||||
|
/* ============================================================
|
||||||
|
Kindergarten — Primary-colored, hand-lettered theme
|
||||||
|
------------------------------------------------------------
|
||||||
|
Token strategy: every color reference goes through
|
||||||
|
`hsl(var(--<token>))` and font-family goes through
|
||||||
|
`var(--font-{heading|body|mono}, <fallback-stack>)`.
|
||||||
|
============================================================ */
|
||||||
|
|
||||||
|
/* ---- Typography (CSS-variable consumers + fallbacks) ------- */
|
||||||
|
|
||||||
|
.kg-page {
|
||||||
|
font-family: var(--font-body, "Nunito", "Quicksand", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
|
||||||
|
line-height: 1.7;
|
||||||
|
background-color: hsl(var(--background));
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-display,
|
||||||
|
.kg-page h1,
|
||||||
|
.kg-page h2,
|
||||||
|
.kg-page h3,
|
||||||
|
.kg-page h4,
|
||||||
|
.kg-page h5,
|
||||||
|
.kg-page h6 {
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", "Nunito", -apple-system, sans-serif);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-mono {
|
||||||
|
font-family: var(--font-mono, "Fira Code", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Layout utilities -------------------------------------- */
|
||||||
|
|
||||||
|
.kg-section {
|
||||||
|
padding-block: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-container {
|
||||||
|
max-width: 72rem;
|
||||||
|
margin-inline: auto;
|
||||||
|
padding-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Rounded primitives ------------------------------------ */
|
||||||
|
|
||||||
|
.kg-chip {
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-card {
|
||||||
|
border-radius: 32px;
|
||||||
|
background-color: hsl(var(--card));
|
||||||
|
color: hsl(var(--card-foreground, var(--foreground)));
|
||||||
|
padding: 2rem;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-card::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0 0 auto 0;
|
||||||
|
height: 4px;
|
||||||
|
background-color: hsl(var(--primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-hero-panel {
|
||||||
|
border-radius: 48px;
|
||||||
|
padding: clamp(2rem, 6vw, 4rem);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: hsl(var(--accent) / 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1.25rem 2.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", "Nunito", sans-serif);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
background-color: hsl(var(--primary));
|
||||||
|
color: hsl(var(--primary-foreground));
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 0 0 hsl(var(--foreground) / 0.15);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: transform 120ms ease, box-shadow 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-pill:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 5px 0 0 hsl(var(--foreground) / 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-pill:active {
|
||||||
|
transform: translateY(2px);
|
||||||
|
box-shadow: 0 2px 0 0 hsl(var(--foreground) / 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-pill:focus-visible {
|
||||||
|
outline: 3px solid hsl(var(--ring));
|
||||||
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CTA colorways */
|
||||||
|
.kg-pill-red { background-color: hsl(var(--destructive)); color: hsl(var(--destructive-foreground)); }
|
||||||
|
.kg-pill-blue { background-color: hsl(var(--secondary)); color: hsl(var(--secondary-foreground)); }
|
||||||
|
.kg-pill-yellow { background-color: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }
|
||||||
|
.kg-pill-green { background-color: hsl(145 65% 45%); color: hsl(0 0% 100%); }
|
||||||
|
|
||||||
|
/* ---- Crayon underline (utility on headings) ---------------- */
|
||||||
|
|
||||||
|
.kg-crayon-underline {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-crayon-underline::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: -6px;
|
||||||
|
height: 8px;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
hsl(var(--primary)) 0 22%,
|
||||||
|
hsl(var(--accent)) 22% 50%,
|
||||||
|
hsl(var(--secondary)) 50% 78%,
|
||||||
|
currentColor 78% 100%);
|
||||||
|
border-radius: 4px;
|
||||||
|
transform: rotate(-1deg);
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Numeral badges ---------------------------------------- */
|
||||||
|
|
||||||
|
.kg-numeral {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
border-radius: 50%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
background-color: hsl(var(--accent));
|
||||||
|
color: hsl(var(--accent-foreground));
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", sans-serif);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
box-shadow: 0 4px 0 0 hsl(var(--foreground) / 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Polaroid frame for gallery_of_art --------------------- */
|
||||||
|
|
||||||
|
.kg-polaroid {
|
||||||
|
background-color: hsl(var(--card));
|
||||||
|
border-radius: 16px;
|
||||||
|
padding-top: 12px;
|
||||||
|
padding-inline: 12px;
|
||||||
|
padding-bottom: 36px;
|
||||||
|
box-shadow: 0 6px 24px hsl(var(--foreground) / 0.12);
|
||||||
|
transform: rotate(-1deg);
|
||||||
|
transition: transform 200ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-polaroid:nth-child(2n) { transform: rotate(1.5deg); }
|
||||||
|
.kg-polaroid:nth-child(3n) { transform: rotate(-0.5deg); }
|
||||||
|
.kg-polaroid:hover { transform: rotate(0deg); }
|
||||||
|
|
||||||
|
.kg-polaroid > img,
|
||||||
|
.kg-polaroid > .kg-polaroid-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: hsl(var(--muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-polaroid-caption {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", sans-serif);
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Alphabet strip ---------------------------------------- */
|
||||||
|
|
||||||
|
.kg-alphabet-strip {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-alphabet-letter {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: hsl(var(--primary));
|
||||||
|
color: hsl(var(--primary-foreground));
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", sans-serif);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
box-shadow: 0 4px 0 0 hsl(var(--foreground) / 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-alphabet-letter:nth-child(4n+1) { background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }
|
||||||
|
.kg-alphabet-letter:nth-child(4n+2) { background-color: hsl(var(--secondary)); color: hsl(var(--secondary-foreground)); }
|
||||||
|
.kg-alphabet-letter:nth-child(4n+3) { background-color: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }
|
||||||
|
.kg-alphabet-letter:nth-child(4n+4) { background-color: hsl(145 65% 45%); color: hsl(0 0% 100%); }
|
||||||
|
|
||||||
|
.kg-alphabet-mono .kg-alphabet-letter {
|
||||||
|
background-color: hsl(var(--muted));
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-alphabet-primary .kg-alphabet-letter {
|
||||||
|
background-color: hsl(var(--primary));
|
||||||
|
color: hsl(var(--primary-foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Day schedule pills ------------------------------------ */
|
||||||
|
|
||||||
|
.kg-schedule-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: hsl(var(--card));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-schedule-time {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
background-color: hsl(var(--accent));
|
||||||
|
color: hsl(var(--accent-foreground));
|
||||||
|
font-family: var(--font-mono, "Fira Code", monospace);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-schedule-activity {
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-schedule-icon {
|
||||||
|
color: hsl(var(--primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Storybook quote --------------------------------------- */
|
||||||
|
|
||||||
|
.kg-storybook {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 32px;
|
||||||
|
background-color: hsl(var(--card));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.kg-storybook {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-storybook-quote {
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", serif);
|
||||||
|
font-size: clamp(1.25rem, 3vw, 2rem);
|
||||||
|
line-height: 1.4;
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-storybook-author {
|
||||||
|
margin-top: 1rem;
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-storybook-illustration {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 4 / 3;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: hsl(var(--muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Friendly footer --------------------------------------- */
|
||||||
|
|
||||||
|
.kg-footer {
|
||||||
|
padding: 3rem 1.5rem;
|
||||||
|
background-color: hsl(var(--muted));
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
border-top: 6px dashed hsl(var(--primary));
|
||||||
|
border-radius: 48px 48px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-footer-mascot {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-family: var(--font-heading, "Quicksand", sans-serif);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-footer-signup {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-block: 1.5rem;
|
||||||
|
max-width: 32rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-footer-signup input {
|
||||||
|
flex: 1 1 12rem;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
border: 2px solid hsl(var(--border));
|
||||||
|
background-color: hsl(var(--input));
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-footer-signup input:focus-visible {
|
||||||
|
outline: 3px solid hsl(var(--ring));
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-social-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-social-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 9999px;
|
||||||
|
background-color: hsl(var(--card));
|
||||||
|
color: hsl(var(--primary));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-social-link:focus-visible {
|
||||||
|
outline: 3px solid hsl(var(--ring));
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Mascot hero confetti dots ----------------------------- */
|
||||||
|
|
||||||
|
.kg-confetti {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(circle, hsl(var(--primary) / 0.5) 8px, transparent 9px),
|
||||||
|
radial-gradient(circle, hsl(var(--secondary) / 0.5) 6px, transparent 7px),
|
||||||
|
radial-gradient(circle, hsl(var(--accent) / 0.5) 5px, transparent 6px);
|
||||||
|
background-size: 80px 80px, 50px 50px, 30px 30px;
|
||||||
|
background-position: 10% 20%, 70% 30%, 40% 80%;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Dotted paper layer (page background) ------------------ */
|
||||||
|
|
||||||
|
.kg-dotted-paper {
|
||||||
|
background-color: hsl(var(--background));
|
||||||
|
background-image: radial-gradient(circle, hsl(var(--muted-foreground) / 0.15) 1px, transparent 1.5px);
|
||||||
|
background-size: 24px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Heading override (numeral badge variant) -------------- */
|
||||||
|
|
||||||
|
.kg-heading-stepped {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-heading-step-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: hsl(var(--accent));
|
||||||
|
color: hsl(var(--accent-foreground));
|
||||||
|
font-family: var(--font-heading, "Quicksand", "Sniglet", sans-serif);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Text override: rounded selection highlight ------------ */
|
||||||
|
|
||||||
|
.kg-text ::selection {
|
||||||
|
background-color: hsl(var(--accent));
|
||||||
|
color: hsl(var(--accent-foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-text {
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
line-height: 1.7;
|
||||||
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Numbers counter grid ---------------------------------- */
|
||||||
|
|
||||||
|
.kg-numbers-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-numbers-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kg-numbers-label {
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Gallery grid ------------------------------------------ */
|
||||||
|
|
||||||
|
.kg-gallery-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) { .kg-gallery-grid { grid-template-columns: repeat(2, 1fr); } }
|
||||||
|
@media (min-width: 1024px) { .kg-gallery-grid { grid-template-columns: repeat(3, 1fr); } }
|
||||||
|
|
||||||
|
/* ---- Big CTA panel (spec §9 button override) --------------- */
|
||||||
|
|
||||||
|
.kg-big-cta {
|
||||||
|
text-align: center;
|
||||||
|
padding: 3rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Empty-state placeholder ------------------------------- */
|
||||||
|
|
||||||
|
.kg-empty {
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 24px;
|
||||||
|
border: 2px dashed hsl(var(--border));
|
||||||
|
color: hsl(var(--muted-foreground));
|
||||||
|
font-family: var(--font-body, "Nunito", sans-serif);
|
||||||
|
}
|
||||||
@ -1,44 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MascotHeroBlockMeta defines metadata for the mascot hero block.
|
|
||||||
var MascotHeroBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "mascot_hero",
|
|
||||||
Title: "Mascot Hero",
|
|
||||||
Description: "Big rounded panel with mascot SVG and primary-colored confetti.",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// MascotHeroData carries the strongly-typed shape consumed by the templ component.
|
|
||||||
type MascotHeroData struct {
|
|
||||||
Mascot string
|
|
||||||
Headline string
|
|
||||||
Tagline string
|
|
||||||
CTALabel string
|
|
||||||
CTAHref string
|
|
||||||
BgColor string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MascotHeroBlock renders the mascot hero block from the unstructured content map.
|
|
||||||
// Content shape: {mascot,headline,tagline,ctaLabel,ctaHref,bgColor}.
|
|
||||||
func MascotHeroBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := MascotHeroData{
|
|
||||||
Mascot: getStringDefault(content, "mascot", "pip"),
|
|
||||||
Headline: getString(content, "headline"),
|
|
||||||
Tagline: getString(content, "tagline"),
|
|
||||||
CTALabel: getString(content, "ctaLabel"),
|
|
||||||
CTAHref: getString(content, "ctaHref"),
|
|
||||||
BgColor: getString(content, "bgColor"),
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = mascotHeroComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// mascotHeroComponent renders the mascot hero panel.
|
|
||||||
templ mascotHeroComponent(data MascotHeroData) {
|
|
||||||
<section class="kg-section" data-block="kindergarten:mascot_hero">
|
|
||||||
<div class="kg-container">
|
|
||||||
<div class="kg-hero-panel">
|
|
||||||
<div class="kg-confetti" aria-hidden="true"></div>
|
|
||||||
<div style="position: relative; z-index: 1; display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: center;" class="kg-mascot-hero-grid">
|
|
||||||
<div>
|
|
||||||
if data.Headline != "" {
|
|
||||||
<h1 class="kg-display kg-crayon-underline" style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;">{ data.Headline }</h1>
|
|
||||||
} else {
|
|
||||||
<h1 class="kg-display" style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;" data-empty="true">Welcome!</h1>
|
|
||||||
}
|
|
||||||
if data.Tagline != "" {
|
|
||||||
<p class="kg-text" style="font-size: 1.25rem; margin-top: 1.5rem;">{ data.Tagline }</p>
|
|
||||||
}
|
|
||||||
if data.CTALabel != "" && data.CTAHref != "" {
|
|
||||||
<div style="margin-top: 2rem;">
|
|
||||||
<a href={ templ.SafeURL(data.CTAHref) } class="kg-pill">{ data.CTALabel }</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; justify-content: center; align-items: center;">
|
|
||||||
@mascotSVG(data.Mascot)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
// mascotSVG renders a primitive, license-free mascot illustration.
|
|
||||||
// The SVGs intentionally use `currentColor` (and the theme primary) so they
|
|
||||||
// inherit colorways from the active preset.
|
|
||||||
templ mascotSVG(name string) {
|
|
||||||
switch name {
|
|
||||||
case "blocks":
|
|
||||||
<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Alphabet blocks mascot">
|
|
||||||
<rect x="20" y="60" width="60" height="60" rx="12" fill="hsl(var(--primary))" />
|
|
||||||
<rect x="90" y="40" width="60" height="60" rx="12" fill="hsl(var(--secondary))" />
|
|
||||||
<rect x="60" y="120" width="60" height="60" rx="12" fill="hsl(var(--accent))" />
|
|
||||||
<text x="50" y="98" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--primary-foreground))">A</text>
|
|
||||||
<text x="120" y="78" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--secondary-foreground))">B</text>
|
|
||||||
<text x="90" y="158" text-anchor="middle" font-family="var(--font-heading, Quicksand)" font-weight="700" font-size="32" fill="hsl(var(--accent-foreground))">C</text>
|
|
||||||
</svg>
|
|
||||||
case "star":
|
|
||||||
<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Friendly star mascot">
|
|
||||||
<polygon points="100,10 122,75 190,75 135,115 155,180 100,140 45,180 65,115 10,75 78,75" fill="hsl(var(--accent))" stroke="hsl(var(--foreground))" stroke-width="4" stroke-linejoin="round" />
|
|
||||||
<circle cx="80" cy="95" r="6" fill="hsl(var(--foreground))" />
|
|
||||||
<circle cx="120" cy="95" r="6" fill="hsl(var(--foreground))" />
|
|
||||||
<path d="M 80 120 Q 100 135 120 120" stroke="hsl(var(--foreground))" stroke-width="4" fill="none" stroke-linecap="round" />
|
|
||||||
</svg>
|
|
||||||
case "balloon":
|
|
||||||
<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Balloon mascot">
|
|
||||||
<ellipse cx="100" cy="80" rx="50" ry="60" fill="hsl(var(--primary))" stroke="hsl(var(--foreground))" stroke-width="4" />
|
|
||||||
<path d="M 100 140 L 95 150 L 100 145 L 105 150 Z" fill="hsl(var(--foreground))" />
|
|
||||||
<path d="M 100 150 Q 90 175 100 195" stroke="hsl(var(--foreground))" stroke-width="2" fill="none" />
|
|
||||||
<circle cx="85" cy="65" r="6" fill="hsl(var(--foreground))" />
|
|
||||||
<circle cx="115" cy="65" r="6" fill="hsl(var(--foreground))" />
|
|
||||||
<path d="M 85 90 Q 100 105 115 90" stroke="hsl(var(--foreground))" stroke-width="4" fill="none" stroke-linecap="round" />
|
|
||||||
</svg>
|
|
||||||
default:
|
|
||||||
<svg viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="Pip the mascot">
|
|
||||||
<circle cx="100" cy="115" r="70" fill="hsl(var(--accent))" stroke="hsl(var(--foreground))" stroke-width="4" />
|
|
||||||
<circle cx="78" cy="100" r="8" fill="hsl(var(--foreground))" />
|
|
||||||
<circle cx="122" cy="100" r="8" fill="hsl(var(--foreground))" />
|
|
||||||
<circle cx="78" cy="98" r="3" fill="hsl(var(--background))" />
|
|
||||||
<circle cx="122" cy="98" r="3" fill="hsl(var(--background))" />
|
|
||||||
<path d="M 75 130 Q 100 155 125 130" stroke="hsl(var(--foreground))" stroke-width="5" fill="none" stroke-linecap="round" />
|
|
||||||
<circle cx="60" cy="115" r="6" fill="hsl(var(--secondary))" />
|
|
||||||
<circle cx="140" cy="115" r="6" fill="hsl(var(--secondary))" />
|
|
||||||
<path d="M 50 60 L 60 35 L 80 50 Z" fill="hsl(var(--primary))" />
|
|
||||||
<path d="M 150 60 L 140 35 L 120 50 Z" fill="hsl(var(--primary))" />
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// mascotHeroComponent renders the mascot hero panel.
|
|
||||||
func mascotHeroComponent(data MascotHeroData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-section\" data-block=\"kindergarten:mascot_hero\"><div class=\"kg-container\"><div class=\"kg-hero-panel\"><div class=\"kg-confetti\" aria-hidden=\"true\"></div><div style=\"position: relative; z-index: 1; display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: center;\" class=\"kg-mascot-hero-grid\"><div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Headline != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h1 class=\"kg-display kg-crayon-underline\" style=\"font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Headline)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `mascot_hero.templ`, Line: 12, Col: 121}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<h1 class=\"kg-display\" style=\"font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;\" data-empty=\"true\">Welcome!</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if data.Tagline != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<p class=\"kg-text\" style=\"font-size: 1.25rem; margin-top: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.Tagline)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `mascot_hero.templ`, Line: 17, Col: 88}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if data.CTALabel != "" && data.CTAHref != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div style=\"margin-top: 2rem;\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(data.CTAHref))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `mascot_hero.templ`, Line: 21, Col: 45}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" class=\"kg-pill\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.CTALabel)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `mascot_hero.templ`, Line: 21, Col: 79}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</a></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><div style=\"display: flex; justify-content: center; align-items: center;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = mascotSVG(data.Mascot).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></div></div></div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// mascotSVG renders a primitive, license-free mascot illustration.
|
|
||||||
// The SVGs intentionally use `currentColor` (and the theme primary) so they
|
|
||||||
// inherit colorways from the active preset.
|
|
||||||
func mascotSVG(name string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var6 == nil {
|
|
||||||
templ_7745c5c3_Var6 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
switch name {
|
|
||||||
case "blocks":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<svg viewBox=\"0 0 200 200\" width=\"200\" height=\"200\" role=\"img\" aria-label=\"Alphabet blocks mascot\"><rect x=\"20\" y=\"60\" width=\"60\" height=\"60\" rx=\"12\" fill=\"hsl(var(--primary))\"></rect> <rect x=\"90\" y=\"40\" width=\"60\" height=\"60\" rx=\"12\" fill=\"hsl(var(--secondary))\"></rect> <rect x=\"60\" y=\"120\" width=\"60\" height=\"60\" rx=\"12\" fill=\"hsl(var(--accent))\"></rect> <text x=\"50\" y=\"98\" text-anchor=\"middle\" font-family=\"var(--font-heading, Quicksand)\" font-weight=\"700\" font-size=\"32\" fill=\"hsl(var(--primary-foreground))\">A</text> <text x=\"120\" y=\"78\" text-anchor=\"middle\" font-family=\"var(--font-heading, Quicksand)\" font-weight=\"700\" font-size=\"32\" fill=\"hsl(var(--secondary-foreground))\">B</text> <text x=\"90\" y=\"158\" text-anchor=\"middle\" font-family=\"var(--font-heading, Quicksand)\" font-weight=\"700\" font-size=\"32\" fill=\"hsl(var(--accent-foreground))\">C</text></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "star":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<svg viewBox=\"0 0 200 200\" width=\"200\" height=\"200\" role=\"img\" aria-label=\"Friendly star mascot\"><polygon points=\"100,10 122,75 190,75 135,115 155,180 100,140 45,180 65,115 10,75 78,75\" fill=\"hsl(var(--accent))\" stroke=\"hsl(var(--foreground))\" stroke-width=\"4\" stroke-linejoin=\"round\"></polygon> <circle cx=\"80\" cy=\"95\" r=\"6\" fill=\"hsl(var(--foreground))\"></circle> <circle cx=\"120\" cy=\"95\" r=\"6\" fill=\"hsl(var(--foreground))\"></circle> <path d=\"M 80 120 Q 100 135 120 120\" stroke=\"hsl(var(--foreground))\" stroke-width=\"4\" fill=\"none\" stroke-linecap=\"round\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "balloon":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<svg viewBox=\"0 0 200 200\" width=\"200\" height=\"200\" role=\"img\" aria-label=\"Balloon mascot\"><ellipse cx=\"100\" cy=\"80\" rx=\"50\" ry=\"60\" fill=\"hsl(var(--primary))\" stroke=\"hsl(var(--foreground))\" stroke-width=\"4\"></ellipse> <path d=\"M 100 140 L 95 150 L 100 145 L 105 150 Z\" fill=\"hsl(var(--foreground))\"></path> <path d=\"M 100 150 Q 90 175 100 195\" stroke=\"hsl(var(--foreground))\" stroke-width=\"2\" fill=\"none\"></path> <circle cx=\"85\" cy=\"65\" r=\"6\" fill=\"hsl(var(--foreground))\"></circle> <circle cx=\"115\" cy=\"65\" r=\"6\" fill=\"hsl(var(--foreground))\"></circle> <path d=\"M 85 90 Q 100 105 115 90\" stroke=\"hsl(var(--foreground))\" stroke-width=\"4\" fill=\"none\" stroke-linecap=\"round\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<svg viewBox=\"0 0 200 200\" width=\"200\" height=\"200\" role=\"img\" aria-label=\"Pip the mascot\"><circle cx=\"100\" cy=\"115\" r=\"70\" fill=\"hsl(var(--accent))\" stroke=\"hsl(var(--foreground))\" stroke-width=\"4\"></circle> <circle cx=\"78\" cy=\"100\" r=\"8\" fill=\"hsl(var(--foreground))\"></circle> <circle cx=\"122\" cy=\"100\" r=\"8\" fill=\"hsl(var(--foreground))\"></circle> <circle cx=\"78\" cy=\"98\" r=\"3\" fill=\"hsl(var(--background))\"></circle> <circle cx=\"122\" cy=\"98\" r=\"3\" fill=\"hsl(var(--background))\"></circle> <path d=\"M 75 130 Q 100 155 125 130\" stroke=\"hsl(var(--foreground))\" stroke-width=\"5\" fill=\"none\" stroke-linecap=\"round\"></path> <circle cx=\"60\" cy=\"115\" r=\"6\" fill=\"hsl(var(--secondary))\"></circle> <circle cx=\"140\" cy=\"115\" r=\"6\" fill=\"hsl(var(--secondary))\"></circle> <path d=\"M 50 60 L 60 35 L 80 50 Z\" fill=\"hsl(var(--primary))\"></path> <path d=\"M 150 60 L 140 35 L 120 50 Z\" fill=\"hsl(var(--primary))\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
25
master_pages.json
Normal file
25
master_pages.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "kindergarten:default-master",
|
||||||
|
"title": "Kindergarten Default Master",
|
||||||
|
"page_templates": ["default", "article"],
|
||||||
|
"blocks": [
|
||||||
|
{ "block_key": "navbar", "title": "Crayon Nav", "content": { "menuName": "main" }, "slot": "header", "sort_order": 0 },
|
||||||
|
{ "block_key": "kindergarten:alphabet_strip", "title": "ABC Strip", "content": { "letters": "ABCDEFGHIJ", "colorMode": "rainbow" }, "slot": "header", "sort_order": 1 },
|
||||||
|
{ "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main", "placeholder": "Page content" }, "slot": "main", "sort_order": 0 },
|
||||||
|
{ "block_key": "kindergarten:footer", "title": "Friendly Footer", "content": { "showSignup": "true", "mascotName": "Pip" }, "slot": "footer", "sort_order": 0 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "kindergarten:landing-master",
|
||||||
|
"title": "Kindergarten Landing Master",
|
||||||
|
"page_templates": ["landing", "full-width"],
|
||||||
|
"blocks": [
|
||||||
|
{ "block_key": "navbar", "title": "Crayon Nav", "content": { "menuName": "main" }, "slot": "header", "sort_order": 0 },
|
||||||
|
{ "block_key": "kindergarten:mascot_hero", "title": "Mascot Hero", "content": { "mascot": "pip", "headline": "Welcome to school!", "tagline": "Big fun, small humans." }, "slot": "hero", "sort_order": 0 },
|
||||||
|
{ "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main" }, "slot": "main", "sort_order": 0 },
|
||||||
|
{ "block_key": "kindergarten:big_cta", "title": "Big Yellow CTA", "content": { "label": "Enrol today", "href": "/enrol", "colorVariant": "yellow" }, "slot": "cta", "sort_order": 0 },
|
||||||
|
{ "block_key": "kindergarten:footer", "title": "Friendly Footer", "content": { "showSignup": "true" }, "slot": "footer", "sort_order": 0 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -1,47 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NumbersCounterBlockMeta defines metadata for the numbers counter block.
|
|
||||||
var NumbersCounterBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "numbers_counter",
|
|
||||||
Title: "Numbers Counter",
|
|
||||||
Description: "Big circular numeral badges for stats (e.g. '12 teachers').",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberItem is a single numeral + label pair.
|
|
||||||
type NumberItem struct {
|
|
||||||
Number int
|
|
||||||
Label string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumbersData is the renderer input.
|
|
||||||
type NumbersData struct {
|
|
||||||
Items []NumberItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumbersCounterBlock renders the round numeral grid.
|
|
||||||
// Content shape: {items:[{number,label}]}.
|
|
||||||
func NumbersCounterBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getSlice(content, "items")
|
|
||||||
items := make([]NumberItem, 0, len(raw))
|
|
||||||
for _, m := range raw {
|
|
||||||
items = append(items, NumberItem{
|
|
||||||
Number: getInt(m, "number", 0),
|
|
||||||
Label: getString(m, "label"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data := NumbersData{Items: items}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = numbersCounterComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// numbersCounterComponent renders circular numeral badges.
|
|
||||||
templ numbersCounterComponent(data NumbersData) {
|
|
||||||
<section class="kg-section" data-block="kindergarten:numbers_counter">
|
|
||||||
<div class="kg-container">
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
<div class="kg-empty" data-empty="true">No numbers yet — add a few stats to celebrate.</div>
|
|
||||||
} else {
|
|
||||||
<div class="kg-numbers-grid">
|
|
||||||
for _, item := range data.Items {
|
|
||||||
<div class="kg-numbers-item">
|
|
||||||
<span class="kg-numeral" data-number={ fmt.Sprintf("%d", item.Number) }>{ fmt.Sprintf("%d", item.Number) }</span>
|
|
||||||
if item.Label != "" {
|
|
||||||
<span class="kg-numbers-label">{ item.Label }</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// numbersCounterComponent renders circular numeral badges.
|
|
||||||
func numbersCounterComponent(data NumbersData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-section\" data-block=\"kindergarten:numbers_counter\"><div class=\"kg-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"kg-empty\" data-empty=\"true\">No numbers yet — add a few stats to celebrate.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"kg-numbers-grid\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, item := range data.Items {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"kg-numbers-item\"><span class=\"kg-numeral\" data-number=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(fmt.Sprintf("%d", item.Number))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `numbers_counter.templ`, Line: 15, Col: 76}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", item.Number))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `numbers_counter.templ`, Line: 15, Col: 111}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if item.Label != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<span class=\"kg-numbers-label\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(item.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `numbers_counter.templ`, Line: 17, Col: 51}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -2,11 +2,8 @@
|
|||||||
name = "kindergarten"
|
name = "kindergarten"
|
||||||
display_name = "Kindergarten"
|
display_name = "Kindergarten"
|
||||||
scope = "@themes"
|
scope = "@themes"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
description = "Primary-colored, hand-lettered theme for schools, daycares, toy shops, museums, and kids' publishers."
|
description = "Primary-colored, hand-lettered theme for schools, daycares, toy shops, museums, and kids' publishers."
|
||||||
kind = "theme"
|
kind = "theme"
|
||||||
categories = ["templates"]
|
categories = ["templates"]
|
||||||
tags = ["kids", "education", "playful", "family", "school", "museum", "friendly", "daycare", "publisher"]
|
tags = ["kids", "education", "playful", "family", "school", "museum", "friendly", "daycare", "publisher"]
|
||||||
|
|
||||||
[compatibility]
|
|
||||||
block_core = ">=0.15.0 <0.16.0"
|
|
||||||
|
|||||||
181
register.go
181
register.go
@ -1,181 +0,0 @@
|
|||||||
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 satisfies 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 wires the Kindergarten theme into the host registries. The call
|
|
||||||
// order matters: the system template + page templates are registered first,
|
|
||||||
// then schemas are loaded before any block registrations so the schema
|
|
||||||
// bindings resolve.
|
|
||||||
func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error {
|
|
||||||
tr.RegisterSystemTemplate(templates.SystemTemplateMeta{
|
|
||||||
Key: "kindergarten",
|
|
||||||
Title: "Kindergarten",
|
|
||||||
Description: "Primary-colored, hand-lettered theme for schools, daycares, toy shops, museums, and kids' publishers.",
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("kindergarten", templates.PageTemplateMeta{
|
|
||||||
Key: "default",
|
|
||||||
Title: "Default",
|
|
||||||
Description: "Standard rounded layout with header, main, footer",
|
|
||||||
Slots: []string{"header", "main", "footer"},
|
|
||||||
}, wrap(RenderKindergarten)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("kindergarten", templates.PageTemplateMeta{
|
|
||||||
Key: "landing",
|
|
||||||
Title: "Landing",
|
|
||||||
Description: "Mascot-led hero plus stacked feature sections",
|
|
||||||
Slots: []string{"hero", "main", "cta", "footer"},
|
|
||||||
}, wrap(RenderKindergartenLanding)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("kindergarten", templates.PageTemplateMeta{
|
|
||||||
Key: "article",
|
|
||||||
Title: "Story Page",
|
|
||||||
Description: "Picture-book reading layout for blog posts and stories",
|
|
||||||
Slots: []string{"header", "main", "aside", "footer"},
|
|
||||||
}, wrap(RenderKindergartenArticle)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("kindergarten", templates.PageTemplateMeta{
|
|
||||||
Key: "full-width",
|
|
||||||
Title: "Full Width",
|
|
||||||
Description: "Edge-to-edge gallery / classroom showcase",
|
|
||||||
Slots: []string{"header", "main", "footer"},
|
|
||||||
}, wrap(RenderKindergartenFullWidth)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schemas must be loaded before block registrations so each Register()
|
|
||||||
// call can bind to its declared schema.
|
|
||||||
if err := br.LoadSchemasFromFS(Schemas()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Theme-owned blocks (eight per spec §8). Registered unqualified; the host
|
|
||||||
// addresses them as "kindergarten:<key>" downstream.
|
|
||||||
br.Register(MascotHeroBlockMeta, MascotHeroBlock)
|
|
||||||
br.Register(AlphabetStripBlockMeta, AlphabetStripBlock)
|
|
||||||
br.Register(ScheduleBlockMeta, ScheduleBlock)
|
|
||||||
br.Register(GalleryOfArtBlockMeta, GalleryOfArtBlock)
|
|
||||||
br.Register(NumbersCounterBlockMeta, NumbersCounterBlock)
|
|
||||||
br.Register(StorybookQuoteBlockMeta, StorybookQuoteBlock)
|
|
||||||
br.Register(BigCTABlockMeta, BigCTABlock)
|
|
||||||
br.Register(FooterBlockMeta, FooterBlock)
|
|
||||||
|
|
||||||
// Built-in overrides (spec §9). Each is scoped to the kindergarten template,
|
|
||||||
// so they only apply when this theme is active.
|
|
||||||
br.RegisterTemplateOverride("kindergarten", "heading", KindergartenHeadingBlock)
|
|
||||||
br.RegisterTemplateOverride("kindergarten", "text", KindergartenTextBlock)
|
|
||||||
br.RegisterTemplateOverride("kindergarten", "button", KindergartenButtonBlock)
|
|
||||||
br.RegisterTemplateOverride("kindergarten", "card", KindergartenCardBlock)
|
|
||||||
|
|
||||||
// Branded email wrapper.
|
|
||||||
tr.RegisterEmailWrapper("kindergarten", KindergartenEmailWrapper)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultMasterPages returns the default master pages that Kindergarten ships.
|
|
||||||
// Per spec §7, two masters: default-master (used by default + article page
|
|
||||||
// templates) and landing-master (used by landing + full-width).
|
|
||||||
func DefaultMasterPages() []plugin.MasterPageDefinition {
|
|
||||||
return []plugin.MasterPageDefinition{
|
|
||||||
{
|
|
||||||
Key: "kindergarten:default-master",
|
|
||||||
Title: "Kindergarten Default Master",
|
|
||||||
PageTemplates: []string{"default", "article"},
|
|
||||||
Blocks: []plugin.MasterPageBlock{
|
|
||||||
{
|
|
||||||
BlockKey: "navbar",
|
|
||||||
Title: "Crayon Nav",
|
|
||||||
Content: map[string]any{"menuName": "main"},
|
|
||||||
Slot: "header",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "kindergarten:alphabet_strip",
|
|
||||||
Title: "ABC Strip",
|
|
||||||
Content: map[string]any{"letters": "ABCDEFGHIJ", "colorMode": "rainbow"},
|
|
||||||
Slot: "header",
|
|
||||||
SortOrder: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "slot",
|
|
||||||
Title: "Main Slot",
|
|
||||||
Content: map[string]any{"slotName": "main", "placeholder": "Page content"},
|
|
||||||
Slot: "main",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "kindergarten:footer",
|
|
||||||
Title: "Friendly Footer",
|
|
||||||
Content: map[string]any{"showSignup": "true", "mascotName": "Pip"},
|
|
||||||
Slot: "footer",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "kindergarten:landing-master",
|
|
||||||
Title: "Kindergarten Landing Master",
|
|
||||||
PageTemplates: []string{"landing", "full-width"},
|
|
||||||
Blocks: []plugin.MasterPageBlock{
|
|
||||||
{
|
|
||||||
BlockKey: "navbar",
|
|
||||||
Title: "Crayon Nav",
|
|
||||||
Content: map[string]any{"menuName": "main"},
|
|
||||||
Slot: "header",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "kindergarten:mascot_hero",
|
|
||||||
Title: "Mascot Hero",
|
|
||||||
Content: map[string]any{"mascot": "pip", "headline": "Welcome to school!", "tagline": "Big fun, small humans."},
|
|
||||||
Slot: "hero",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "slot",
|
|
||||||
Title: "Main Slot",
|
|
||||||
Content: map[string]any{"slotName": "main"},
|
|
||||||
Slot: "main",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "kindergarten:big_cta",
|
|
||||||
Title: "Big Yellow CTA",
|
|
||||||
Content: map[string]any{"label": "Enrol today", "href": "/enrol", "colorVariant": "yellow"},
|
|
||||||
Slot: "cta",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "kindergarten:footer",
|
|
||||||
Title: "Friendly Footer",
|
|
||||||
Content: map[string]any{"showSignup": "true"},
|
|
||||||
Slot: "footer",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
"git.dev.alexdunmow.com/block/core/plugin"
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Registration is the compile-time plugin registration for the Kindergarten theme.
|
|
||||||
var Registration = plugin.PluginRegistration{
|
|
||||||
Name: "kindergarten",
|
|
||||||
Version: plugin.ParseModVersion(pluginModBytes),
|
|
||||||
Register: func(tr templates.TemplateRegistry, br blocks.BlockRegistry) error {
|
|
||||||
return Register(tr, br)
|
|
||||||
},
|
|
||||||
Assets: func() http.Handler { return AssetsHandler() },
|
|
||||||
Schemas: func() fs.FS { return Schemas() },
|
|
||||||
ThemePresets: func() []byte { return ThemePresets() },
|
|
||||||
BundledFonts: func() []byte { return BundledFonts() },
|
|
||||||
MasterPages: func() []plugin.MasterPageDefinition { return DefaultMasterPages() },
|
|
||||||
CSSManifest: func() *plugin.CSSManifest { return ThemeCSSManifest() },
|
|
||||||
}
|
|
||||||
53
schedule.go
53
schedule.go
@ -1,53 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ScheduleBlockMeta defines metadata for the day schedule block.
|
|
||||||
var ScheduleBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "schedule",
|
|
||||||
Title: "Day Schedule",
|
|
||||||
Description: "Daycare/classroom day plan with crayon time-pills.",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScheduleItem is a single time/activity row.
|
|
||||||
type ScheduleItem struct {
|
|
||||||
Time string
|
|
||||||
Activity string
|
|
||||||
Icon string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScheduleData is the renderer's strongly-typed input.
|
|
||||||
type ScheduleData struct {
|
|
||||||
Title string
|
|
||||||
Items []ScheduleItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScheduleBlock renders the day-schedule block.
|
|
||||||
// Content shape: {title,items:[{time,activity,icon}]}.
|
|
||||||
func ScheduleBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getSlice(content, "items")
|
|
||||||
items := make([]ScheduleItem, 0, len(raw))
|
|
||||||
for _, m := range raw {
|
|
||||||
items = append(items, ScheduleItem{
|
|
||||||
Time: getString(m, "time"),
|
|
||||||
Activity: getString(m, "activity"),
|
|
||||||
Icon: getString(m, "icon"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data := ScheduleData{
|
|
||||||
Title: getString(content, "title"),
|
|
||||||
Items: items,
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = scheduleComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// scheduleComponent renders the day schedule.
|
|
||||||
templ scheduleComponent(data ScheduleData) {
|
|
||||||
<section class="kg-section" data-block="kindergarten:schedule">
|
|
||||||
<div class="kg-container">
|
|
||||||
if data.Title != "" {
|
|
||||||
<h2 class="kg-display kg-crayon-underline" style="font-size: 2rem; margin-bottom: 1.5rem;">{ data.Title }</h2>
|
|
||||||
}
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
<div class="kg-empty" data-empty="true">No schedule items yet — add a time block to get started.</div>
|
|
||||||
} else {
|
|
||||||
<ol style="list-style: none; padding: 0; margin: 0;">
|
|
||||||
for _, item := range data.Items {
|
|
||||||
<li class="kg-schedule-item">
|
|
||||||
<span class="kg-schedule-time">
|
|
||||||
if item.Time != "" {
|
|
||||||
{ item.Time }
|
|
||||||
} else {
|
|
||||||
--:--
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
<span class="kg-schedule-activity">
|
|
||||||
if item.Activity != "" {
|
|
||||||
{ item.Activity }
|
|
||||||
} else {
|
|
||||||
Activity
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
<span class="kg-schedule-icon" aria-hidden="true">
|
|
||||||
@scheduleIcon(item.Icon)
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ol>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduleIcon renders a small SVG matching the icon name. Defaults to a star
|
|
||||||
// shape when the icon is missing or unknown so we never render a broken image.
|
|
||||||
templ scheduleIcon(name string) {
|
|
||||||
switch name {
|
|
||||||
case "sun":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m4.93 19.07 1.41-1.41"/><path d="m17.66 6.34 1.41-1.41"/></svg>
|
|
||||||
case "book":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
|
|
||||||
case "paint":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 11h2m-1 -1v2"/><circle cx="13" cy="6" r="2"/><circle cx="19" cy="11" r="2"/><circle cx="6" cy="14" r="2"/><circle cx="10" cy="20" r="2"/><path d="M7.4 12.4l3.6 -2.4"/><path d="M11.6 8.6l1.4 -0.6"/><path d="M15 6l4 5"/><path d="M8 16l2 4"/></svg>
|
|
||||||
case "snack":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
|
|
||||||
case "play":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
|
|
||||||
case "nap":
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
|
||||||
default:
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.8 5.8 21 7 14 2 9.3 9 8.5 12 2"/></svg>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,197 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// scheduleComponent renders the day schedule.
|
|
||||||
func scheduleComponent(data ScheduleData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-section\" data-block=\"kindergarten:schedule\"><div class=\"kg-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Title != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2 class=\"kg-display kg-crayon-underline\" style=\"font-size: 2rem; margin-bottom: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `schedule.templ`, Line: 8, Col: 107}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(data.Items) == 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"kg-empty\" data-empty=\"true\">No schedule items yet — add a time block to get started.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<ol style=\"list-style: none; padding: 0; margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, item := range data.Items {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<li class=\"kg-schedule-item\"><span class=\"kg-schedule-time\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if item.Time != "" {
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(item.Time)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `schedule.templ`, Line: 18, Col: 20}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "--:--")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</span> <span class=\"kg-schedule-activity\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if item.Activity != "" {
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(item.Activity)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `schedule.templ`, Line: 25, Col: 24}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "Activity")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</span> <span class=\"kg-schedule-icon\" aria-hidden=\"true\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = scheduleIcon(item.Icon).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</span></li>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</ol>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduleIcon renders a small SVG matching the icon name. Defaults to a star
|
|
||||||
// shape when the icon is missing or unknown so we never render a broken image.
|
|
||||||
func scheduleIcon(name string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var5 == nil {
|
|
||||||
templ_7745c5c3_Var5 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
switch name {
|
|
||||||
case "sun":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"4\"></circle><path d=\"M12 2v2\"></path><path d=\"M12 20v2\"></path><path d=\"m4.93 4.93 1.41 1.41\"></path><path d=\"m17.66 17.66 1.41 1.41\"></path><path d=\"M2 12h2\"></path><path d=\"M20 12h2\"></path><path d=\"m4.93 19.07 1.41-1.41\"></path><path d=\"m17.66 6.34 1.41-1.41\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "book":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\"></path><path d=\"M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "paint":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 11h2m-1 -1v2\"></path><circle cx=\"13\" cy=\"6\" r=\"2\"></circle><circle cx=\"19\" cy=\"11\" r=\"2\"></circle><circle cx=\"6\" cy=\"14\" r=\"2\"></circle><circle cx=\"10\" cy=\"20\" r=\"2\"></circle><path d=\"M7.4 12.4l3.6 -2.4\"></path><path d=\"M11.6 8.6l1.4 -0.6\"></path><path d=\"M15 6l4 5\"></path><path d=\"M8 16l2 4\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "snack":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"></path><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"></line><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"></line></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "play":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"5 3 19 12 5 21 5 3\"></polygon></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "nap":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.8 5.8 21 7 14 2 9.3 9 8.5 12 2\"></polygon></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StorybookQuoteBlockMeta defines metadata for the storybook quote block.
|
|
||||||
var StorybookQuoteBlockMeta = blocks.BlockMeta{
|
|
||||||
Key: "storybook_quote",
|
|
||||||
Title: "Storybook Quote",
|
|
||||||
Description: "Picture-book page treatment for a quote with optional illustration.",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "kindergarten",
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorybookQuoteData is the renderer input.
|
|
||||||
type StorybookQuoteData struct {
|
|
||||||
Quote string
|
|
||||||
Author string
|
|
||||||
Illustration string
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorybookQuoteBlock renders the quote panel.
|
|
||||||
// Content shape: {quote,author,illustration}.
|
|
||||||
func StorybookQuoteBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := StorybookQuoteData{
|
|
||||||
Quote: getString(content, "quote"),
|
|
||||||
Author: getString(content, "author"),
|
|
||||||
Illustration: getString(content, "illustration"),
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = storybookQuoteComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
|
|
||||||
// storybookQuoteComponent renders a quote with optional illustration.
|
|
||||||
templ storybookQuoteComponent(data StorybookQuoteData) {
|
|
||||||
<section class="kg-section" data-block="kindergarten:storybook_quote">
|
|
||||||
<div class="kg-container">
|
|
||||||
<figure class="kg-storybook">
|
|
||||||
<blockquote style="margin: 0;">
|
|
||||||
if data.Quote != "" {
|
|
||||||
<p class="kg-storybook-quote">"{ data.Quote }"</p>
|
|
||||||
} else {
|
|
||||||
<p class="kg-storybook-quote" data-empty="true">Add a quote to inspire your readers.</p>
|
|
||||||
}
|
|
||||||
if data.Author != "" {
|
|
||||||
<figcaption class="kg-storybook-author">— { data.Author }</figcaption>
|
|
||||||
}
|
|
||||||
</blockquote>
|
|
||||||
<div>
|
|
||||||
if data.Illustration != "" {
|
|
||||||
<img class="kg-storybook-illustration" src={ blocks.ResolveMediaPath(data.Illustration) } alt={ "Illustration accompanying the quote" } />
|
|
||||||
} else {
|
|
||||||
@storybookFallbackIllustration()
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</figure>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
// storybookFallbackIllustration renders a friendly SVG when no illustration
|
|
||||||
// is supplied. It guarantees a visible, themed graphic instead of a broken
|
|
||||||
// image icon.
|
|
||||||
templ storybookFallbackIllustration() {
|
|
||||||
<svg viewBox="0 0 200 150" width="100%" height="auto" class="kg-storybook-illustration" role="img" aria-label="Storybook illustration">
|
|
||||||
<rect width="200" height="150" rx="24" fill="hsl(var(--muted))" />
|
|
||||||
<circle cx="60" cy="60" r="20" fill="hsl(var(--accent))" />
|
|
||||||
<rect x="100" y="40" width="60" height="40" rx="8" fill="hsl(var(--primary))" />
|
|
||||||
<path d="M 30 110 Q 100 90 170 110 L 170 130 L 30 130 Z" fill="hsl(var(--secondary))" />
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
@ -1,163 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import "git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
|
|
||||||
// storybookQuoteComponent renders a quote with optional illustration.
|
|
||||||
func storybookQuoteComponent(data StorybookQuoteData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"kg-section\" data-block=\"kindergarten:storybook_quote\"><div class=\"kg-container\"><figure class=\"kg-storybook\"><blockquote style=\"margin: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Quote != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"kg-storybook-quote\">\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Quote)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `storybook_quote.templ`, Line: 12, Col: 49}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<p class=\"kg-storybook-quote\" data-empty=\"true\">Add a quote to inspire your readers.</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if data.Author != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<figcaption class=\"kg-storybook-author\">— ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.Author)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `storybook_quote.templ`, Line: 17, Col: 63}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</figcaption>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</blockquote><div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Illustration != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<img class=\"kg-storybook-illustration\" src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(blocks.ResolveMediaPath(data.Illustration))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `storybook_quote.templ`, Line: 22, Col: 93}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" alt=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue("Illustration accompanying the quote")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `storybook_quote.templ`, Line: 22, Col: 139}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = storybookFallbackIllustration().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></figure></div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// storybookFallbackIllustration renders a friendly SVG when no illustration
|
|
||||||
// is supplied. It guarantees a visible, themed graphic instead of a broken
|
|
||||||
// image icon.
|
|
||||||
func storybookFallbackIllustration() templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var6 == nil {
|
|
||||||
templ_7745c5c3_Var6 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<svg viewBox=\"0 0 200 150\" width=\"100%\" height=\"auto\" class=\"kg-storybook-illustration\" role=\"img\" aria-label=\"Storybook illustration\"><rect width=\"200\" height=\"150\" rx=\"24\" fill=\"hsl(var(--muted))\"></rect> <circle cx=\"60\" cy=\"60\" r=\"20\" fill=\"hsl(var(--accent))\"></circle> <rect x=\"100\" y=\"40\" width=\"60\" height=\"40\" rx=\"8\" fill=\"hsl(var(--primary))\"></rect> <path d=\"M 30 110 Q 100 90 170 110 L 170 130 L 30 130 Z\" fill=\"hsl(var(--secondary))\"></path></svg>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
257
template.templ
257
template.templ
@ -1,257 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates/bn"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PageData carries everything the page templates need to render.
|
|
||||||
type PageData struct {
|
|
||||||
Title string
|
|
||||||
Slots map[string]string
|
|
||||||
ThemeMode string
|
|
||||||
ThemeCSS string
|
|
||||||
SiteSettings bn.SiteSettingsData
|
|
||||||
PageMeta bn.PageMeta
|
|
||||||
StructuredData string
|
|
||||||
CSSHash string
|
|
||||||
PageviewNonce string
|
|
||||||
EngagementConfig bn.EngagementConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseKindergartenPageData converts the unstructured doc map the engine
|
|
||||||
// passes in into the strongly-typed PageData used by the templ components.
|
|
||||||
func parseKindergartenPageData(doc map[string]any) PageData {
|
|
||||||
title := "Untitled"
|
|
||||||
if t, ok := doc["title"].(string); ok {
|
|
||||||
title = t
|
|
||||||
}
|
|
||||||
|
|
||||||
slots := make(map[string]string)
|
|
||||||
if s, ok := doc["slots"].(map[string]string); ok {
|
|
||||||
slots = s
|
|
||||||
}
|
|
||||||
|
|
||||||
themeCSS := ""
|
|
||||||
if tc, ok := doc["theme_css"].(string); ok {
|
|
||||||
themeCSS = tc
|
|
||||||
}
|
|
||||||
|
|
||||||
structuredData := ""
|
|
||||||
if sd, ok := doc["structured_data"].(string); ok {
|
|
||||||
structuredData = sd
|
|
||||||
}
|
|
||||||
|
|
||||||
cssHash := ""
|
|
||||||
if ch, ok := doc["css_hash"].(string); ok {
|
|
||||||
cssHash = ch
|
|
||||||
}
|
|
||||||
|
|
||||||
pageviewNonce := ""
|
|
||||||
if pn, ok := doc["pageview_nonce"].(string); ok {
|
|
||||||
pageviewNonce = pn
|
|
||||||
}
|
|
||||||
|
|
||||||
themeMode := "light"
|
|
||||||
if tm, ok := doc["theme_mode"].(string); ok && tm != "" {
|
|
||||||
themeMode = tm
|
|
||||||
}
|
|
||||||
|
|
||||||
siteSettings := bn.ParseSiteSettings(doc)
|
|
||||||
pageMeta := bn.ParsePageMeta(doc)
|
|
||||||
engagementConfig := bn.ParseEngagementConfig(doc)
|
|
||||||
|
|
||||||
return PageData{
|
|
||||||
Title: title,
|
|
||||||
Slots: slots,
|
|
||||||
ThemeMode: themeMode,
|
|
||||||
ThemeCSS: themeCSS,
|
|
||||||
SiteSettings: siteSettings,
|
|
||||||
PageMeta: pageMeta,
|
|
||||||
StructuredData: structuredData,
|
|
||||||
CSSHash: cssHash,
|
|
||||||
PageviewNonce: pageviewNonce,
|
|
||||||
EngagementConfig: engagementConfig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pluginStyles is the canonical list of theme stylesheet URLs each page sends to <head>.
|
|
||||||
var pluginStyles = []string{"/templates/kindergarten/style.css"}
|
|
||||||
|
|
||||||
// Kindergarten — default template.
|
|
||||||
templ Kindergarten(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="kg-page kg-dotted-paper">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
<header class="kg-section" style="padding-block: 1.5rem;">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<main class="kg-container" style="padding-block: 2rem; flex: 1;">
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
@templ.Raw(main)
|
|
||||||
} else {
|
|
||||||
<div class="kg-empty">No content blocks assigned to this page.</div>
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
<footer style="margin-top: auto;">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — landing template with mascot hero + CTA strip.
|
|
||||||
templ KindergartenLanding(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="kg-page kg-dotted-paper">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
<header class="kg-section" style="padding-block: 1.5rem;">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<section class="kg-section" style="padding-top: 0;">
|
|
||||||
@templ.Raw(data.Slots["hero"])
|
|
||||||
</section>
|
|
||||||
<main class="kg-container">
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
@templ.Raw(main)
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
<section>
|
|
||||||
@templ.Raw(data.Slots["cta"])
|
|
||||||
</section>
|
|
||||||
<footer style="margin-top: auto;">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — article (storybook reading) template.
|
|
||||||
templ KindergartenArticle(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="kg-page kg-dotted-paper">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
<header class="kg-section" style="padding-block: 1.5rem;">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<div class="kg-container" style="display: grid; grid-template-columns: 1fr; gap: 2rem; padding-block: 2rem;">
|
|
||||||
<main>
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
<article class="kg-text">
|
|
||||||
@templ.Raw(main)
|
|
||||||
</article>
|
|
||||||
} else {
|
|
||||||
<div class="kg-empty">No content yet — start a story.</div>
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
if aside, ok := data.Slots["aside"]; ok && aside != "" {
|
|
||||||
<aside class="kg-card">
|
|
||||||
@templ.Raw(aside)
|
|
||||||
</aside>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<footer style="margin-top: auto;">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — full-width gallery / showcase template.
|
|
||||||
templ KindergartenFullWidth(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="kg-page kg-dotted-paper">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
<header class="kg-section" style="padding-block: 1.5rem;">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<main style="flex: 1;">
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
@templ.Raw(main)
|
|
||||||
} else {
|
|
||||||
<div class="kg-container">
|
|
||||||
<div class="kg-empty">No content blocks assigned to this page.</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
<footer style="margin-top: auto;">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render functions invoked by the registry.
|
|
||||||
|
|
||||||
func RenderKindergarten(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return Kindergarten(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenLanding(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenLanding(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenArticle(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenArticle(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenFullWidth(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenFullWidth(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
@ -1,529 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates/bn"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PageData carries everything the page templates need to render.
|
|
||||||
type PageData struct {
|
|
||||||
Title string
|
|
||||||
Slots map[string]string
|
|
||||||
ThemeMode string
|
|
||||||
ThemeCSS string
|
|
||||||
SiteSettings bn.SiteSettingsData
|
|
||||||
PageMeta bn.PageMeta
|
|
||||||
StructuredData string
|
|
||||||
CSSHash string
|
|
||||||
PageviewNonce string
|
|
||||||
EngagementConfig bn.EngagementConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseKindergartenPageData converts the unstructured doc map the engine
|
|
||||||
// passes in into the strongly-typed PageData used by the templ components.
|
|
||||||
func parseKindergartenPageData(doc map[string]any) PageData {
|
|
||||||
title := "Untitled"
|
|
||||||
if t, ok := doc["title"].(string); ok {
|
|
||||||
title = t
|
|
||||||
}
|
|
||||||
|
|
||||||
slots := make(map[string]string)
|
|
||||||
if s, ok := doc["slots"].(map[string]string); ok {
|
|
||||||
slots = s
|
|
||||||
}
|
|
||||||
|
|
||||||
themeCSS := ""
|
|
||||||
if tc, ok := doc["theme_css"].(string); ok {
|
|
||||||
themeCSS = tc
|
|
||||||
}
|
|
||||||
|
|
||||||
structuredData := ""
|
|
||||||
if sd, ok := doc["structured_data"].(string); ok {
|
|
||||||
structuredData = sd
|
|
||||||
}
|
|
||||||
|
|
||||||
cssHash := ""
|
|
||||||
if ch, ok := doc["css_hash"].(string); ok {
|
|
||||||
cssHash = ch
|
|
||||||
}
|
|
||||||
|
|
||||||
pageviewNonce := ""
|
|
||||||
if pn, ok := doc["pageview_nonce"].(string); ok {
|
|
||||||
pageviewNonce = pn
|
|
||||||
}
|
|
||||||
|
|
||||||
themeMode := "light"
|
|
||||||
if tm, ok := doc["theme_mode"].(string); ok && tm != "" {
|
|
||||||
themeMode = tm
|
|
||||||
}
|
|
||||||
|
|
||||||
siteSettings := bn.ParseSiteSettings(doc)
|
|
||||||
pageMeta := bn.ParsePageMeta(doc)
|
|
||||||
engagementConfig := bn.ParseEngagementConfig(doc)
|
|
||||||
|
|
||||||
return PageData{
|
|
||||||
Title: title,
|
|
||||||
Slots: slots,
|
|
||||||
ThemeMode: themeMode,
|
|
||||||
ThemeCSS: themeCSS,
|
|
||||||
SiteSettings: siteSettings,
|
|
||||||
PageMeta: pageMeta,
|
|
||||||
StructuredData: structuredData,
|
|
||||||
CSSHash: cssHash,
|
|
||||||
PageviewNonce: pageviewNonce,
|
|
||||||
EngagementConfig: engagementConfig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pluginStyles is the canonical list of theme stylesheet URLs each page sends to <head>.
|
|
||||||
var pluginStyles = []string{"/templates/kindergarten/style.css"}
|
|
||||||
|
|
||||||
// Kindergarten — default template.
|
|
||||||
func Kindergarten(data PageData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body class=\"kg-page kg-dotted-paper\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<header class=\"kg-section\" style=\"padding-block: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</header><main class=\"kg-container\" style=\"padding-block: 2rem; flex: 1;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"kg-empty\">No content blocks assigned to this page.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</main><footer style=\"margin-top: auto;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</footer>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — landing template with mascot hero + CTA strip.
|
|
||||||
func KindergartenLanding(data PageData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var2 == nil {
|
|
||||||
templ_7745c5c3_Var2 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<!doctype html><html lang=\"en\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<body class=\"kg-page kg-dotted-paper\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<header class=\"kg-section\" style=\"padding-block: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</header><section class=\"kg-section\" style=\"padding-top: 0;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["hero"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</section><main class=\"kg-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</main><section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["cta"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</section><footer style=\"margin-top: auto;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</footer>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — article (storybook reading) template.
|
|
||||||
func KindergartenArticle(data PageData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var3 == nil {
|
|
||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<!doctype html><html lang=\"en\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<body class=\"kg-page kg-dotted-paper\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<header class=\"kg-section\" style=\"padding-block: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</header><div class=\"kg-container\" style=\"display: grid; grid-template-columns: 1fr; gap: 2rem; padding-block: 2rem;\"><main>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<article class=\"kg-text\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</article>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div class=\"kg-empty\">No content yet — start a story.</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</main>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if aside, ok := data.Slots["aside"]; ok && aside != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<aside class=\"kg-card\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(aside).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</aside>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</div><footer style=\"margin-top: auto;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</footer>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kindergarten — full-width gallery / showcase template.
|
|
||||||
func KindergartenFullWidth(data PageData) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var4 == nil {
|
|
||||||
templ_7745c5c3_Var4 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<!doctype html><html lang=\"en\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: pluginStyles,
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
}).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<body class=\"kg-page kg-dotted-paper\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<header class=\"kg-section\" style=\"padding-block: 1.5rem;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</header><main style=\"flex: 1;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"kg-container\"><div class=\"kg-empty\">No content blocks assigned to this page.</div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</main><footer style=\"margin-top: auto;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</footer>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render functions invoked by the registry.
|
|
||||||
|
|
||||||
func RenderKindergarten(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return Kindergarten(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenLanding(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenLanding(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenArticle(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenArticle(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RenderKindergartenFullWidth(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return KindergartenFullWidth(parseKindergartenPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
68
templates/email/kindergarten.ninjatpl
Normal file
68
templates/email/kindergarten.ninjatpl
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="x-apple-disable-message-reformatting">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<!--[if mso]>
|
||||||
|
<noscript>
|
||||||
|
<xml>
|
||||||
|
<o:OfficeDocumentSettings>
|
||||||
|
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||||
|
</o:OfficeDocumentSettings>
|
||||||
|
</xml>
|
||||||
|
</noscript>
|
||||||
|
<![endif]-->
|
||||||
|
<title>{{ site_name }}</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body, table, td, p, a, li, blockquote { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||||
|
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||||
|
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
||||||
|
body { margin: 0 !important; padding: 0 !important; width: 100% !important; }
|
||||||
|
a[x-apple-data-detectors] { color: inherit !important; text-decoration: none !important; }
|
||||||
|
h1, h2, h3, h4, h5, h6 { font-family: 'Quicksand', 'Nunito', -apple-system, sans-serif; font-weight: 700; }
|
||||||
|
@media only screen and (max-width: 620px) {
|
||||||
|
.email-container { width: 100% !important; max-width: 100% !important; }
|
||||||
|
.content-padding { padding-left: 24px !important; padding-right: 24px !important; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="background-color: {{ colors.background|default:'#fdf9ed' }}; margin: 0; padding: 0; font-family: &#39;Nunito&#39;, &#39;Quicksand&#39;, -apple-system, sans-serif;">
|
||||||
|
{% if preview_text %}<div style="display: none; max-height: 0; overflow: hidden; mso-hide: all;">{{ preview_text }}</div>{% endif %}
|
||||||
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding: 48px 10px; background-color: {{ colors.background|default:'#fdf9ed' }};">
|
||||||
|
<table role="presentation" class="email-container" width="600" cellspacing="0" cellpadding="0" border="0" style="max-width: 600px; background-color: {{ colors.card|default:'#ffffff' }}; border: 1px solid {{ colors.border|default:'#e6d9b3' }}; border-radius: 32px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding: 32px 40px; background-color: {{ colors.card|default:'#ffffff' }}; border-bottom: 2px dashed {{ colors.border|default:'#e6d9b3' }}; border-radius: 32px 32px 0 0;">
|
||||||
|
{% if logo_url %}<img src="{{ logo_url }}" alt="{{ site_name }}" style="max-height: 48px; width: auto; display: block;">{% elif site_name %}<h1 style="margin: 0; font-size: 28px; font-weight: 700; color: {{ colors.foreground|default:'#1a253b' }}; letter-spacing: -0.5px; font-family: &#39;Quicksand&#39;, &#39;Nunito&#39;, sans-serif;">{{ site_name }}</h1>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-padding" style="padding: 40px 48px; color: {{ colors.foreground|default:'#1a253b' }}; font-size: 16px; line-height: 1.7; font-family: &#39;Nunito&#39;, sans-serif;">{{ body|safe }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding: 0 48px 32px 48px; background-color: {{ colors.card|default:'#ffffff' }};">
|
||||||
|
{% if site_url %}<a href="{{ site_url }}" style="display: inline-block; padding: 16px 32px; border-radius: 9999px; background-color: {{ colors.primary|default:'#fbcd1f' }}; color: {{ colors.primaryForeground|default:'#1a253b' }}; text-decoration: none; font-family: &#39;Quicksand&#39;, sans-serif; font-weight: 700; font-size: 16px;">Visit {{ site_name }}</a>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 32px 48px; border-top: 2px dashed {{ colors.border|default:'#e6d9b3' }}; border-radius: 0 0 32px 32px; background-color: {{ colors.card|default:'#ffffff' }};">
|
||||||
|
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<p style="margin: 0 0 8px; font-size: 14px; font-weight: 700; color: {{ colors.foreground|default:'#1a253b' }}; font-family: &#39;Quicksand&#39;, sans-serif;">👋 {{ site_name }}</p>
|
||||||
|
{% if support_email %}<p style="margin: 0 0 8px; font-size: 13px; color: {{ colors.mutedForeground|default:'#5a6480' }};">Need a hand? {{ support_email }}</p>{% endif %}
|
||||||
|
{% if unsubscribe_url %}<p style="margin: 0; font-size: 11px; color: {{ colors.mutedForeground|default:'#5a6480' }};"><a href="{{ unsubscribe_url }}" style="color: {{ colors.mutedForeground|default:'#5a6480' }}; text-decoration: none;">Unsubscribe</a></p>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
16
templates/kindergarten/article.ninjatpl
Normal file
16
templates/kindergarten/article.ninjatpl
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="kg-page kg-dotted-paper">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<header class="kg-section" style="padding-block: 1.5rem;">{{ slots.header|safe }}</header>
|
||||||
|
<div class="kg-container" style="display: grid; grid-template-columns: 1fr; gap: 2rem; padding-block: 2rem;">
|
||||||
|
<main>
|
||||||
|
{% if slots.main %}<article class="kg-text">{{ slots.main|safe }}</article>{% else %}<div class="kg-empty">No content yet — start a story.</div>{% endif %}
|
||||||
|
</main>
|
||||||
|
{% if slots.aside %}<aside class="kg-card">{{ slots.aside|safe }}</aside>{% endif %}
|
||||||
|
</div>
|
||||||
|
<footer style="margin-top: auto;">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
templates/kindergarten/default.ninjatpl
Normal file
13
templates/kindergarten/default.ninjatpl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="kg-page kg-dotted-paper">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<header class="kg-section" style="padding-block: 1.5rem;">{{ slots.header|safe }}</header>
|
||||||
|
<main class="kg-container" style="padding-block: 2rem; flex: 1;">
|
||||||
|
{% if slots.main %}{{ slots.main|safe }}{% else %}<div class="kg-empty">No content blocks assigned to this page.</div>{% endif %}
|
||||||
|
</main>
|
||||||
|
<footer style="margin-top: auto;">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
templates/kindergarten/full-width.ninjatpl
Normal file
13
templates/kindergarten/full-width.ninjatpl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="kg-page kg-dotted-paper">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<header class="kg-section" style="padding-block: 1.5rem;">{{ slots.header|safe }}</header>
|
||||||
|
<main style="flex: 1;">
|
||||||
|
{% if slots.main %}{{ slots.main|safe }}{% else %}<div class="kg-container"><div class="kg-empty">No content blocks assigned to this page.</div></div>{% endif %}
|
||||||
|
</main>
|
||||||
|
<footer style="margin-top: auto;">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
templates/kindergarten/landing.ninjatpl
Normal file
15
templates/kindergarten/landing.ninjatpl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="kg-page kg-dotted-paper">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<header class="kg-section" style="padding-block: 1.5rem;">{{ slots.header|safe }}</header>
|
||||||
|
<section class="kg-section" style="padding-top: 0;">{{ slots.hero|safe }}</section>
|
||||||
|
<main class="kg-container">
|
||||||
|
{% if slots.main %}{{ slots.main|safe }}{% endif %}
|
||||||
|
</main>
|
||||||
|
<section>{{ slots.cta|safe }}</section>
|
||||||
|
<footer style="margin-top: auto;">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
templates/overrides/kindergarten/button.ninjatpl
Normal file
1
templates/overrides/kindergarten/button.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if text %}{% set lbl = text %}{% else %}{% set lbl = label %}{% endif %}{% if lbl %}<a href="{{ href|default:'#' }}" class="kg-pill {% if variant == "red" %}kg-pill-red{% elif variant == "blue" %}kg-pill-blue{% elif variant == "green" %}kg-pill-green{% else %}kg-pill-yellow{% endif %}">{{ lbl }}</a>{% else %}<span class="kg-empty" data-empty="true">Add label and link to render this button.</span>{% endif %}
|
||||||
1
templates/overrides/kindergarten/card.ninjatpl
Normal file
1
templates/overrides/kindergarten/card.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div class="kg-card {{ class }}">{% if title %}<h3 class="kg-display" style="margin-top: 0; margin-bottom: 1rem; font-size: 1.5rem;">{{ title }}</h3>{% endif %}{% if body %}<div class="kg-text">{{ body|safe }}</div>{% endif %}{% if not title and not body %}<div data-empty="true" class="kg-empty">Add a title or body to fill this card.</div>{% endif %}</div>
|
||||||
1
templates/overrides/kindergarten/heading.ninjatpl
Normal file
1
templates/overrides/kindergarten/heading.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if step|integer >= 1 and step|integer <= 9 %}<div class="kg-heading-stepped"><span class="kg-heading-step-badge" aria-hidden="true">{{ step|integer }}</span>{% endif %}{% if level|integer == 1 %}<h1 class="kg-display kg-crayon-underline {{ textClass }}" style="font-size: clamp(2.5rem, 6vw, 4rem); margin: 0;">{{ text }}</h1>{% elif level|integer == 3 %}<h3 class="kg-display {{ textClass }}" style="font-size: 1.75rem; margin: 0;">{{ text }}</h3>{% elif level|integer == 4 %}<h4 class="kg-display {{ textClass }}" style="font-size: 1.5rem; margin: 0;">{{ text }}</h4>{% elif level|integer == 5 %}<h5 class="kg-display {{ textClass }}" style="font-size: 1.25rem; margin: 0;">{{ text }}</h5>{% elif level|integer == 6 %}<h6 class="kg-display {{ textClass }}" style="font-size: 1.125rem; margin: 0;">{{ text }}</h6>{% else %}<h2 class="kg-display kg-crayon-underline {{ textClass }}" style="font-size: 2.25rem; margin: 0;">{{ text }}</h2>{% endif %}{% if step|integer >= 1 and step|integer <= 9 %}</div>{% endif %}
|
||||||
1
templates/overrides/kindergarten/text.ninjatpl
Normal file
1
templates/overrides/kindergarten/text.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div class="kg-text {{ class }}">{{ text|safe }}</div>
|
||||||
@ -1,17 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KindergartenTextBlock renders text with Nunito body, 1.7 line-height,
|
|
||||||
// and the rounded ::selection highlight in primary yellow.
|
|
||||||
func KindergartenTextBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
text := getString(content, "text")
|
|
||||||
class := getString(content, "class")
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = kgTextComponent(text, class).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// kgTextComponent renders rich text body styled to match the Kindergarten
|
|
||||||
// reading rhythm.
|
|
||||||
templ kgTextComponent(text, class string) {
|
|
||||||
<div class={ "kg-text", class }>
|
|
||||||
@templ.Raw(text)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// kgTextComponent renders rich text body styled to match the Kindergarten
|
|
||||||
// reading rhythm.
|
|
||||||
func kgTextComponent(text, class string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
var templ_7745c5c3_Var2 = []any{"kg-text", class}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `text_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(text).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
Loading…
x
Reference in New Issue
Block a user