{{/* Hugo Blox Parser v3 - Preact Component Support */}} {{/* Documentation: https://hugoblox.com/blocks/ */}} {{/* License: https://github.com/HugoBlox/kit/blob/main/LICENSE.md */}} {{ $page := .page }} {{ $block := .block }} {{- $block_type := partial "hbx/resolve-block-param" (dict "config" $block "context" "content section") | default "markdown" -}} {{ $block_type = lower $block_type }} {{/* Handle block renames/aliases */}} {{ range $r := hugo.Data.blox_aliases.renames }} {{ $block_type = cond (eq $block_type $r.old) $r.new $block_type }} {{ end }} {{/* Check if this is a Preact-enabled block by looking for component file */}} {{ $component_path := printf "js/hbx/blocks/%s/component.jsx" $block_type }} {{ $is_preact := resources.Get $component_path }} {{/* Apply styling wrapper for all blocks (both Preact and traditional) */}} {{ $bg := $block.design.background }} {{ $style := "" }} {{ $style_bg := "" }} {{/* Process background colors */}} {{ if $bg.color }} {{ $color_type := printf "%T" $bg.color }} {{ if eq $color_type "map[string]interface {}" }} {{ if and $bg.color.light $bg.color.dark }} {{ $light_color := $bg.color.light }} {{ $dark_color := $bg.color.dark }} {{ $style_bg = printf "background-color: %s;" $light_color }} {{ $style_bg = printf "%s--dark-bg-color: %s;" $style_bg $dark_color }} {{ else if $bg.color.light }} {{ $light_color := $bg.color.light }} {{ $style_bg = printf "background-color: %s;" $light_color }} {{ else if $bg.color.dark }} {{ $dark_color := $bg.color.dark }} {{ $style_bg = printf "--dark-bg-color: %s; background-color: var(--dark-bg-color);" $dark_color }} {{ end }} {{ else }} {{ $bg_color := $bg.color }} {{ $style_bg = printf "background-color: %s;" $bg_color }} {{ end }} {{ end }} {{/* Process gradients and images */}} {{ $background_layers := slice }} {{ $gradient_layer := "" }} {{ $has_gradient_mesh := false }} {{ $gradient_mesh_html := "" }} {{/* Enhanced Gradient Mesh System */}} {{ $gradient_mesh := $bg.gradient_mesh | default dict }} {{ if $gradient_mesh.enable }} {{ $has_gradient_mesh = true }} {{/* Stacking-fix: the mesh wrapper sits at z-index:-10, while .home-section-bg sits at z-index:-1. If we leave bg-color on home-section-bg, the colour paints OVER the mesh and the orbs are hidden. Migrate the bg-color off home-section-bg and onto the section element itself, so the section's own background paints BEHIND the mesh layer (orbs visible) and the radial gradient + image layers on home-section-bg paint ABOVE the mesh (still visible). */}} {{ if $style_bg }} {{ $style = print $style $style_bg }} {{ $style_bg = "" }} {{ end }} {{ $mesh_style := $gradient_mesh.style | default "orbs" }} {{ $mesh_animation_raw := $gradient_mesh.animation | default "pulse" }} {{ $mesh_intensity := $gradient_mesh.intensity | default "subtle" }} {{/* Auto-theme: Mix Primary and Secondary brand colors for dynamic personalization */}} {{ $mesh_colors := $gradient_mesh.colors | default (slice "primary-500/20" "secondary-500/20") }} {{/* Map animation names to CSS classes */}} {{ $mesh_animation := "" }} {{ if eq $mesh_animation_raw "pulse" }} {{ $mesh_animation = "pulse" }} {{ else if eq $mesh_animation_raw "float" }} {{ $mesh_animation = "float" }} {{ else if eq $mesh_animation_raw "rotate" }} {{ $mesh_animation = "rotate-slow" }} {{ else if ne $mesh_animation_raw "none" }} {{ $mesh_animation = "pulse" }} {{/* Default fallback */}} {{ end }} {{/* Build gradient mesh HTML */}} {{ $mesh_html := "
" }} {{/* Base gradient overlay */}} {{ $base_gradient := printf "
" (index $mesh_colors 0) (index $mesh_colors 1) }} {{ $mesh_html = printf "%s%s" $mesh_html $base_gradient }} {{/* Animated elements based on style */}} {{ if eq $mesh_style "orbs" }} {{ $orb_count := $gradient_mesh.orb_count | default 2 }} {{ $orb_positions := $gradient_mesh.positions | default (slice "top-0 left-1/4" "bottom-0 right-1/4") }} {{ $orb_sizes := $gradient_mesh.sizes | default (slice "w-96 h-96" "w-96 h-96") }} {{ range $index, $position := first $orb_count $orb_positions }} {{ $size := index $orb_sizes $index | default "w-96 h-96" }} {{ $color := index $mesh_colors $index | default "primary-500/30" }} {{ $blur_class := cond (eq $mesh_intensity "bold") "blur-2xl" (cond (eq $mesh_intensity "medium") "blur-3xl" "blur-3xl") }} {{ $opacity := cond (eq $mesh_intensity "bold") "40" (cond (eq $mesh_intensity "medium") "30" "30") }} {{/* Extract base color and adjust opacity for orbs */}} {{ $orb_color := $color }} {{ if not (in $color "/") }} {{ $orb_color = printf "%s/%s" $color $opacity }} {{ end }} {{ $animation_delay := "" }} {{ if gt $index 0 }} {{ $animation_delay = printf " style=\"animation-delay: %ds;\"" (mul $index 2) }} {{ end }} {{/* Build orb with or without animation */}} {{ $animate_class := cond (ne $mesh_animation "") (printf "animate-%s" $mesh_animation) "" }} {{ $orb := printf "
" $position $size $orb_color $blur_class $animate_class $animation_delay }} {{ $mesh_html = printf "%s%s" $mesh_html $orb }} {{ end }} {{ else if eq $mesh_style "waves" }} {{/* Flowing wave effect - multiple horizontal bands */}} {{ $wave_count := $gradient_mesh.wave_count | default 3 }} {{ $blur_class := cond (eq $mesh_intensity "bold") "blur-2xl" (cond (eq $mesh_intensity "medium") "blur-3xl" "blur-3xl") }} {{ range $index := seq 0 (sub $wave_count 1) }} {{ $color_index := mod $index (len $mesh_colors) }} {{ $color := index $mesh_colors $color_index }} {{ $top_pos := mul $index 33 }} {{ $height := "h-64" }} {{ $anim_delay := printf " style=\"animation-delay: %ds; animation-duration: %ds;\"" (mul $index 1) (add 8 (mul $index 2)) }} {{/* Apply animation if not none */}} {{ $animate_class := cond (ne $mesh_animation "") (printf "animate-%s" $mesh_animation) "" }} {{ $wave := printf "
" $height $color $blur_class $animate_class $top_pos $anim_delay }} {{ $mesh_html = printf "%s%s" $mesh_html $wave }} {{ end }} {{ else if eq $mesh_style "dots" }} {{/* Dotted grid pattern */}} {{ $dot_size := $gradient_mesh.dot_size | default "w-4 h-4" }} {{ $spacing := $gradient_mesh.spacing | default "16" }} {{ $color := index $mesh_colors 0 | default "primary-500/20" }} {{/* Create a dotted pattern background */}} {{ $dots := printf "
" $spacing $spacing (div (int $spacing) 2) (div (int $spacing) 2) }} {{ $mesh_html = printf "%s%s" $mesh_html $dots }} {{ else if eq $mesh_style "grid" }} {{/* Grid lines pattern */}} {{ $color := index $mesh_colors 0 | default "primary-500/10" }} {{ $line_width := $gradient_mesh.line_width | default "1" }} {{ $spacing := $gradient_mesh.spacing | default "32" }} {{/* Create grid pattern */}} {{ $grid := printf "
" $line_width $line_width $line_width $line_width $spacing $spacing }} {{ $mesh_html = printf "%s%s" $mesh_html $grid }} {{ end }} {{ $mesh_html = printf "%s
" $mesh_html }} {{ $gradient_mesh_html = $mesh_html | safeHTML }} {{ end }} {{/* Linear or radial gradient (radial added for 2026 hero spotlight pattern) */}} {{ if and $bg.gradient.start $bg.gradient.end }} {{ $start_color := $bg.gradient.start }} {{ $end_color := $bg.gradient.end }} {{ $gradient_type := $bg.gradient.type | default "linear" }} {{ if eq $gradient_type "radial" }} {{ $shape := $bg.gradient.shape | default "ellipse" }} {{ $position := $bg.gradient.position | default "center" }} {{ $size := $bg.gradient.size | default "farthest-corner" }} {{ $gradient_layer = printf "radial-gradient(%s %s at %s, %s, %s)" $shape $size $position $start_color $end_color }} {{ else }} {{ $angle := string $bg.gradient.direction | default "135" }} {{ $gradient_layer = printf "linear-gradient(%sdeg, %s, %s)" $angle $start_color $end_color }} {{ end }} {{ end }} {{/* Process video backgrounds */}} {{ $bg_video := "" }} {{ $bg_video_class := "" }} {{ if $bg.video.filename }} {{ $bg_video = resources.Get (printf "media/%s" $bg.video.filename) }} {{ if $bg.video.flip }} {{ $bg_video_class = "flip" }} {{ end }} {{ end }} {{/* Process image backgrounds */}} {{ if $bg.image.filename }} {{ $bg_img := resources.Get (printf "media/%s" $bg.image.filename) }} {{ if $bg_img }} {{ if reflect.IsImageResourceProcessable $bg_img }} {{ $bg_img = $bg_img.Fit "1920x1920 webp" }} {{ end }} {{ $image_layer := printf "url('%s')" $bg_img.RelPermalink }} {{ $background_layers = $background_layers | append $image_layer }} {{ else }} {{ errorf "Couldn't find `%s` in the `assets/media/` folder - please add it." $bg.image.filename }} {{ end }} {{ end }} {{ if or $background_layers $gradient_layer }} {{ $all_layers := $background_layers }} {{ if $gradient_layer }} {{ $all_layers = $all_layers | append $gradient_layer }} {{ end }} {{ if $all_layers }} {{ $combined_backgrounds := delimit $all_layers ", " }} {{ $style_bg = printf "%sbackground-image: %s;" $style_bg $combined_backgrounds }} {{/* Background image size/position/repeat properties */}} {{ $layer_count := len $all_layers }} {{ if gt $layer_count 1 }} {{/* Multiple layers: image + gradient */}} {{ $img_size := $bg.image.size | default "cover" }} {{ $img_position := $bg.image.position | default "center" }} {{ $img_repeat := $bg.image.repeat | default "no-repeat" }} {{ if eq $img_position "repeat" }} {{ $img_repeat = "repeat" }} {{ $img_position = "center" }} {{ end }} {{ $style_bg = printf "%sbackground-size: %s, cover;" $style_bg $img_size }} {{ $style_bg = printf "%sbackground-position: %s, center;" $style_bg $img_position }} {{ $style_bg = printf "%sbackground-repeat: %s, no-repeat;" $style_bg $img_repeat }} {{ else }} {{/* Single layer */}} {{ if $background_layers }} {{ with $bg.image.size }} {{ $style_bg = printf "%sbackground-size: %s;" $style_bg . }} {{ end }} {{ with $bg.image.position }} {{ if eq . "repeat" }} {{ $style_bg = printf "%sbackground-position: center;" $style_bg }} {{ $style_bg = printf "%sbackground-repeat: repeat;" $style_bg }} {{ else }} {{ $style_bg = printf "%sbackground-position: %s;" $style_bg . }} {{ end }} {{ end }} {{ end }} {{ end }} {{ end }} {{ end }} {{/* Background image filters: brightness, blur, contrast, saturate, grayscale */}} {{ with $bg.image.filters }} {{ $filter_parts := slice }} {{ with .brightness }} {{ $filter_parts = $filter_parts | append (printf "brightness(%s)" (string .)) }} {{ end }} {{ with .blur }} {{ $filter_parts = $filter_parts | append (printf "blur(%s)" (string .)) }} {{ end }} {{ with .contrast }} {{ $filter_parts = $filter_parts | append (printf "contrast(%s)" (string .)) }} {{ end }} {{ with .saturate }} {{ $filter_parts = $filter_parts | append (printf "saturate(%s)" (string .)) }} {{ end }} {{ with .grayscale }} {{ $filter_parts = $filter_parts | append (printf "grayscale(%s)" (string .)) }} {{ end }} {{ if $filter_parts }} {{ $style_bg = printf "%sfilter: %s;" $style_bg (delimit $filter_parts " ") }} {{ end }} {{ end }} {{ with $block.design.spacing.padding }} {{ $style_pad := printf "padding: %s;" (delimit . " ") }} {{ $style = print $style $style_pad }} {{ end }} {{ with $block.design.css_style }} {{ $style = print $style . }} {{ end }} {{/* Support for clip path (design.clip_path) */}} {{ with $block.design.clip_path }} {{ $style = printf "%sclip-path: %s;" $style . }} {{ end }} {{/* Section break: smooth transitions between sibling sections via gradient overlay divs at the section's top/bottom edges. Each edge fades from transparent (toward the section's content) to a user-specified colour (matching the adjacent sibling's background). Example — hero fading into a dark logos band beneath: section_break: fade_bottom: "#101828" # any CSS colour (hex, rgb, var, named) fade_top: "#0a0e27" # optional, independent of fade_bottom size: "6rem" # optional, default 6rem (applies to both edges) Why explicit colour: a gradient overlay needs to know what colour to fade INTO. Hugo can't reliably auto-detect the next sibling's background at parse time, so the user declares intent. */}} {{ $break_overlay := "" }} {{ with $block.design.section_break }} {{ $sb_size := .size | default "6rem" }} {{ $overlays := slice }} {{ with .fade_bottom }} {{ $overlays = $overlays | append (printf "
" $sb_size .) }} {{ end }} {{ with .fade_top }} {{ $overlays = $overlays | append (printf "
" $sb_size .) }} {{ end }} {{ $break_overlay = delimit $overlays "" }} {{ end }} {{ $hash_id := $block.id | default (printf "section-%s" (replace $block_type "." "-")) }} {{ $css_classes := $block.design.css_class | default "" }} {{ $widget_class := printf "blox-%s" (strings.ReplacePairs $block_type "." "-" "_" "-") }} {{/* Extract background-specific CSS classes */}} {{ $bg_css_classes := $bg.css_class | default "" }} {{/* Route to appropriate handler */}} {{ if $is_preact }} {{/* Render Preact block with styling wrapper */}} {{/* `isolate` forces a stacking context on the section so the home-section-bg (z-index:-1) and gradient mesh (z-index:-10) layers stay contained — without it, negative-z descendants escape the section and paint behind the page root. */}}
{{/* Gradient Mesh Background */}} {{ if $has_gradient_mesh }}{{ $gradient_mesh_html }}{{ end }}
{{with $bg_video}}{{end}}
{{/* Section-break gradient overlays (above bg, below content) */}} {{ with $break_overlay }}{{ . | safeHTML }}{{ end }} {{/* Use generic Preact wrapper for content */}} {{ partial "blox/preact-wrapper" (dict "wcPage" $page "wcBlock" $block "wcBlockType" $block_type "wcIdentifier" $hash_id) }}
{{ else }} {{/* Fall back to traditional Go template blocks */}} {{ $block_path := printf "hbx/blocks/%s/block.html" $block_type }} {{ if not (templates.Exists (printf "_partials/%s" $block_path)) }} {{ errorf "%s uses a `%s` block but the `%s` block was not found at `%s`. Check the name of the block and ensure it exists in the blox/%s/ directory." $page.File.Path $block_type $block_type $block_path $block_type }} {{ end }} {{/* Handle legacy block requirements */}} {{ if $block.Page.Store.Get "has_mermaid" }} {{ $page.Page.Store.Set "has_mermaid" true }} {{ end }} {{ if (gt (len (findRE `\{\{< gallery` $block.content.text 1)) 0) }} {{ $page.Page.Store.Set "has_gallery" true }} {{ end }} {{ $widget_args := dict "wcPage" $page "wcBlock" $block "wcIdentifier" $hash_id }} {{/* Render traditional block with wrapper */}} {{/* `isolate` forces a stacking context on the section so the home-section-bg (z-index:-1) and gradient mesh (z-index:-10) layers stay contained — without it, negative-z descendants escape the section and paint behind the page root. */}}
{{/* Gradient Mesh Background */}} {{ if $has_gradient_mesh }}{{ $gradient_mesh_html }}{{ end }}
{{with $bg_video}}{{end}}
{{/* Section-break gradient overlays (above bg, below content) */}} {{ with $break_overlay }}{{ . | safeHTML }}{{ end }} {{ partial $block_path $widget_args }}
{{ end }}