feat: enhance accessibility with skip to main content button and improve navigation handling

🔧 fix: update navigation href resolution to include localized paths

🆕 feat: add new FeatureIcon component for feature boxes

🎨 style: improve styling for prose elements in richtext blocks

🛠️ refactor: streamline medialib image loading and caching logic

📦 chore: update mock data handling to support new medialib entries

🔄 chore: synchronize i18n initialization and locale management

📝 docs: update video tour descriptions to reflect recent changes
This commit is contained in:
2026-05-12 13:55:32 +00:00
parent 8fb26fdeba
commit e84b87ed16
41 changed files with 1523 additions and 338 deletions
+96 -2
View File
@@ -1,4 +1,40 @@
import type { SvelteComponent } from "svelte"
import { mount, unmount, type Component, type SvelteComponent } from "svelte"
import BlockRenderer from "./blocks/BlockRenderer.svelte"
const previewCssUrl = new URL("./index.css", import.meta.url).toString()
type BlockRenderContext = {
namespace?: string
apiBase?: string
projectBase?: string
}
type BlockHandle = {
update(row: Record<string, any>, context?: BlockRenderContext): void
destroy(): void
}
type BlockDefinition = {
render(container: HTMLElement | ShadowRoot, row: Record<string, any>, context?: BlockRenderContext): BlockHandle
css?: string[]
previewStyles?: Record<string, string>
label?: string
icon?: string
color?: string
}
type BlockPresentation = {
label: string
icon: string
color: string
}
function getAdminPreviewProps(props?: { [key: string]: any }) {
return {
isAdminPreview: true,
...(props || {}),
}
}
function getRenderedElement(
component: typeof SvelteComponent,
@@ -33,13 +69,71 @@ function getRenderedElement(
new component({
target: target,
props: options?.props,
props: getAdminPreviewProps(options?.props),
})
return el
}
function createContentBlockDefinition(presentation: BlockPresentation): BlockDefinition {
return {
css: [previewCssUrl],
label: presentation.label,
icon: presentation.icon,
color: presentation.color,
previewStyles: {
"background-color": "white",
position: "relative",
},
render(container, row, context) {
const target = document.createElement("div")
target.dataset.adminPreview = "true"
container.appendChild(target)
let mountedComponent = mount(BlockRenderer as Component<any>, {
target,
props: {
blocks: [row as ContentBlockEntry],
isAdminPreview: true,
},
})
return {
update(nextRow) {
unmount(mountedComponent)
target.innerHTML = ""
mountedComponent = mount(BlockRenderer as Component<any>, {
target,
props: {
blocks: [nextRow as ContentBlockEntry],
isAdminPreview: true,
},
})
},
destroy() {
unmount(mountedComponent)
target.remove()
},
}
},
}
}
const blockRegistry = {
hero: createContentBlockDefinition({ label: "Hero", icon: "image", color: "#1d4ed8" }),
features: createContentBlockDefinition({ label: "Features", icon: "view_quilt", color: "#0f766e" }),
richtext: createContentBlockDefinition({ label: "Richtext", icon: "article", color: "#7c3aed" }),
accordion: createContentBlockDefinition({ label: "Accordion", icon: "expand", color: "#b45309" }),
"contact-form": createContentBlockDefinition({
label: "Contact Form",
icon: "mail",
color: "#be185d",
}),
}
export {
getAdminPreviewProps,
getRenderedElement,
blockRegistry,
// pass also required svelte components here
}