feat(modal): route-targeted content modals on navigation
Add a global modal/popup system driven entirely from the CMS. A new `modal` config collection self-targets routes via a glob/regex urlPattern (optional time window), and its `content` array of block references renders through the existing BlockRenderer — so markdown, HTML and YouTube blocks work exactly like a page row. A `modals` list collection holds the active set behind an enable flag (analogous to `campaigns`). - modal-match.ts: glob (`*`/`**`) + `~regex` pathname matcher, time window and modal selection helpers (+ unit tests) - ContentModal.svelte: immediate/delay/scroll/exit_intent triggers, session vs. permanent dismiss (sessionStorage + localStorage, keyed by slug+version) - +layout.server.ts: load `modals-global` in the bootstrap batch, resolve block images server-side - +layout.svelte: mount on non-embed routes, match against the current path Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
import AnnouncementBanner from '$lib/components/AnnouncementBanner.svelte';
|
||||
import DeadlineBannerBlock from '$lib/components/blocks/DeadlineBannerBlock.svelte';
|
||||
import TranslationProvider from '$lib/components/TranslationProvider.svelte';
|
||||
import ContentModal from '$lib/components/ContentModal.svelte';
|
||||
import Breadcrumbs from '$lib/ui/Breadcrumbs.svelte';
|
||||
import type { LayoutData } from './$types';
|
||||
import { ensureTransformedImage } from '$lib/rusty-image';
|
||||
@@ -406,5 +407,11 @@
|
||||
<Footer footer={data.footerData} translations={data.translations} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ContentModal
|
||||
modals={data.modals}
|
||||
pathname={$page.url.pathname}
|
||||
translations={data.translations}
|
||||
/>
|
||||
{/if}
|
||||
</TranslationProvider>
|
||||
|
||||
Reference in New Issue
Block a user