feat: implement Dynamic Data Binding system and tags registry
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 1m0s
All checks were successful
Production Build & Deploy / build-and-deploy (push) Successful in 1m0s
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
---
|
||||
import type { SiteConfig, UIComponent } from '../../utils/configLoader';
|
||||
import { resolveDynamicBinding } from '../../utils/dynamicDataBinding';
|
||||
|
||||
interface Props {
|
||||
config: SiteConfig['hero'];
|
||||
contextData?: Record<string, any>;
|
||||
}
|
||||
|
||||
const { config } = Astro.props;
|
||||
const { config, contextData = {} } = Astro.props;
|
||||
|
||||
const heroTitle = resolveDynamicBinding(config.title, contextData);
|
||||
const heroSubtitle = resolveDynamicBinding(config.subtitle, contextData);
|
||||
const heroBadge = resolveDynamicBinding(config.badge, contextData);
|
||||
|
||||
const elements = config.elements || [];
|
||||
const badgeElements = elements.filter((el: UIComponent) => el.slotId === 'hero-badge-slot');
|
||||
@@ -21,41 +27,41 @@ const customElements = elements.filter((el: UIComponent) => !el.slotId || el.slo
|
||||
|
||||
<!-- Slot 1: Badge Slot -->
|
||||
<div id="hero-badge-slot" class="inline-flex flex-wrap items-center justify-center gap-2">
|
||||
{config.badge && (
|
||||
{heroBadge && (
|
||||
<div class="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full border border-sky-400/20 bg-sky-400/10 text-sky-400 text-xs font-mono tracking-wide backdrop-blur-md">
|
||||
<span>{config.badge}</span>
|
||||
<span>{heroBadge}</span>
|
||||
</div>
|
||||
)}
|
||||
{badgeElements.map(el => (
|
||||
<span class={`inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full border border-sky-400/30 bg-sky-400/20 text-sky-300 text-xs font-mono ${el.animation0 ? `anim-${el.animation0}` : ''}`}>
|
||||
{el.content}
|
||||
{resolveDynamicBinding(el.content, contextData)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h1 class="text-4xl sm:text-6xl font-extrabold tracking-tight text-white leading-tight">
|
||||
{config.title}
|
||||
{heroTitle}
|
||||
</h1>
|
||||
|
||||
<p class="text-slate-400 text-xs sm:text-lg max-w-2xl mx-auto leading-relaxed font-normal">
|
||||
{config.subtitle}
|
||||
{heroSubtitle}
|
||||
</p>
|
||||
|
||||
<!-- Slot 2: Action Buttons Slot -->
|
||||
<div id="hero-actions-slot" class="flex flex-wrap items-center justify-center gap-4 pt-4">
|
||||
{config.ctaPrimaryText && (
|
||||
<a href={config.ctaPrimaryLink} class="px-8 py-3.5 rounded-xl bg-sky-400 text-slate-950 font-bold text-xs hover:bg-white transition-all duration-300 shadow-lg shadow-sky-400/20 active:scale-95">
|
||||
{config.ctaPrimaryText}
|
||||
{resolveDynamicBinding(config.ctaPrimaryText, contextData)}
|
||||
</a>
|
||||
)}
|
||||
{config.ctaSecondaryText && (
|
||||
<a href={config.ctaSecondaryLink} class="px-8 py-3.5 rounded-xl glass-panel text-white font-semibold text-xs glass-panel-hover active:scale-95">
|
||||
{config.ctaSecondaryText}
|
||||
{resolveDynamicBinding(config.ctaSecondaryText, contextData)}
|
||||
</a>
|
||||
)}
|
||||
{actionElements.map(el => (
|
||||
<a href={el.link || '#'} class={`px-8 py-3.5 rounded-xl font-bold text-xs transition-all active:scale-95 ${el.style === 'glass' ? 'glass-panel text-white' : 'bg-sky-400 text-slate-950 hover:bg-white'} ${el.animation0 ? `anim-${el.animation0}` : ''}`}>
|
||||
{el.content}
|
||||
{resolveDynamicBinding(el.content, contextData)}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
@@ -66,7 +72,7 @@ const customElements = elements.filter((el: UIComponent) => !el.slotId || el.slo
|
||||
{customElements.map(el => (
|
||||
<div class="p-4 rounded-xl glass-panel text-xs text-slate-300">
|
||||
<span class="font-bold text-sky-400 block mb-1 uppercase text-[10px]">{el.type} [ID: {el.id}]</span>
|
||||
{el.content}
|
||||
{resolveDynamicBinding(el.content, contextData)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user