@frontlit/page-builder 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { ThemeModeSwitcher } from './chunk-BBI7UHOA.js';
3
- import { DataSlot, CodeSnippetBlock, Embed, Marquee, MediaBlock, Grid, RichText, Footer, SupportForm, EmailForm, Banner, Pricing, Faq, Featured, Content, Hero, Header } from './chunk-K4WCLHMS.js';
3
+ import { DataSlot, CodeSnippetBlock, Embed, Marquee, MediaBlock, Grid, RichText, Footer, SupportForm, EmailForm, Banner, Pricing, Faq, Featured, Content, Hero, Header } from './chunk-5J6TLS5U.js';
4
4
  import { PageBuilderLinkProvider } from './chunk-36QHCIPM.js';
5
5
  import { cn } from './chunk-J7Z4UW45.js';
6
6
  import { useRef, useId, useEffect } from 'react';
@@ -334,5 +334,5 @@ function PageRenderer({
334
334
  }
335
335
 
336
336
  export { EditableBlock, LAYOUT_BLOCK_NAMES, NON_ADDABLE_BLOCK_NAMES, PageRenderer, blockRegistry, generateThemeStyles, getAddableBlocks, getWidget, registerBlock, resolveThemeColor };
337
- //# sourceMappingURL=chunk-IU4KATI2.js.map
338
- //# sourceMappingURL=chunk-IU4KATI2.js.map
337
+ //# sourceMappingURL=chunk-USPQ3AOW.js.map
338
+ //# sourceMappingURL=chunk-USPQ3AOW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry-names.ts","../src/registry.ts","../src/renderer/editable-block.tsx","../src/renderer/generate-theme-styles.ts","../src/renderer/page-renderer.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-IU4KATI2.js","sourcesContent":["/** Blocks placed outside the normal flow by the renderer. */\nexport const LAYOUT_BLOCK_NAMES = [\"header\", \"footer\"];\n","import type { Widget } from \"./models\";\nimport { LAYOUT_BLOCK_NAMES } from \"./registry-names\";\nimport {\n Header,\n Hero,\n Content,\n Featured,\n Faq,\n Pricing,\n Banner,\n EmailForm,\n SupportForm,\n Footer,\n RichText,\n Grid,\n MediaBlock,\n Marquee,\n Embed,\n CodeSnippetBlock,\n DataSlot,\n} from \"./blocks\";\n\n/**\n * Every block available to the page builder, keyed by its\n * `metadata.name`. `header` and `footer` are singleton, layout-level\n * blocks placed outside the normal flow by the renderer.\n */\nexport const blockRegistry: Record<string, Widget<any>> = {\n header: Header,\n hero: Hero,\n content: Content,\n featured: Featured,\n faq: Faq,\n pricing: Pricing,\n banner: Banner,\n \"email-form\": EmailForm,\n \"support-form\": SupportForm,\n footer: Footer,\n \"rich-text\": RichText,\n grid: Grid,\n media: MediaBlock,\n marquee: Marquee,\n embed: Embed,\n \"code-snippet\": CodeSnippetBlock,\n \"data-slot\": DataSlot,\n};\n\nexport { LAYOUT_BLOCK_NAMES };\nexport const NON_ADDABLE_BLOCK_NAMES = [...LAYOUT_BLOCK_NAMES, \"data-slot\"];\n\n/**\n * Adds a host application's block to the shared renderer and builder\n * registry. Register blocks while the application module initializes, before\n * rendering either `PageBuilder` or `PageRenderer`.\n *\n * Built-in names are intentionally protected: a persisted page must always\n * have one stable implementation for a block name. Give host blocks a\n * namespaced name such as `acme-event-list`.\n */\nexport function registerBlock(widget: Widget<any>): void {\n const name = widget.metadata.name.trim();\n if (!name) {\n throw new Error(\"A page-builder block must have a non-empty name.\");\n }\n if (blockRegistry[name]) {\n throw new Error(`A page-builder block named \\\"${name}\\\" is already registered.`);\n }\n if (NON_ADDABLE_BLOCK_NAMES.includes(name)) {\n throw new Error(\n `\\\"${name}\\\" is a reserved page-builder block name and cannot be registered by a host application.`,\n );\n }\n blockRegistry[name] = widget;\n}\n\nexport function getWidget(name: string): Widget<any> | undefined {\n return blockRegistry[name];\n}\n\n/** Blocks a user can add to the body of a page. */\nexport function getAddableBlocks(): Widget<any>[] {\n return Object.values(blockRegistry).filter(\n (widget) => !NON_ADDABLE_BLOCK_NAMES.includes(widget.metadata.name),\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { ArrowDown, ArrowUp, Plus, Settings2, Trash2 } from \"lucide-react\";\nimport { cn } from \"../primitives/lib/utils\";\n\nexport interface EditableBlockProps {\n children: React.ReactNode;\n editing: boolean;\n /** Ref to the wrapper element so the canvas can scroll the block into view. */\n containerRef?: React.Ref<HTMLDivElement>;\n selected?: boolean;\n /** Draws a temporary attention flash, e.g. right after the block was moved. */\n highlighted?: boolean;\n label?: string;\n onSelect?: () => void;\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n onDelete?: () => void;\n onAddBelow?: () => void;\n}\n\nfunction ToolbarButton({\n icon: Icon,\n label,\n onClick,\n}: {\n icon: React.ComponentType<{ className?: string }>;\n label: string;\n onClick?: () => void;\n}) {\n if (!onClick) return null;\n return (\n <button\n type=\"button\"\n title={label}\n aria-label={label}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded bg-background text-foreground shadow-sm hover:bg-muted\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n </button>\n );\n}\n\n/**\n * Wraps a rendered block with hover/selection affordances when the page\n * builder is in editing mode. In non-editing (plain display) mode it's a\n * transparent passthrough.\n */\nexport function EditableBlock({\n children,\n editing,\n containerRef,\n selected,\n highlighted,\n label,\n onSelect,\n onMoveUp,\n onMoveDown,\n onDelete,\n onAddBelow,\n}: EditableBlockProps) {\n if (!editing) {\n return <>{children}</>;\n }\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"group/block relative outline outline-1 outline-transparent transition-colors hover:outline-primary/40\",\n selected && \"outline-2 outline-primary\",\n highlighted && \"outline-2 outline-primary/70\",\n )}\n onClick={onSelect}\n >\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 z-10 bg-primary/10 opacity-0 transition-opacity duration-500\",\n highlighted && \"opacity-100\",\n )}\n />\n <div className=\"pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center opacity-0 transition-opacity group-hover/block:opacity-100\">\n <div className=\"pointer-events-auto flex items-center gap-1 rounded-b-md border border-t-0 border-border bg-background px-1.5 py-1 shadow-sm\">\n {label && (\n <span className=\"px-1.5 text-xs font-medium text-muted-foreground\">\n {label}\n </span>\n )}\n <ToolbarButton icon={Settings2} label=\"Edit settings\" onClick={onSelect} />\n <ToolbarButton icon={ArrowUp} label=\"Move up\" onClick={onMoveUp} />\n <ToolbarButton icon={ArrowDown} label=\"Move down\" onClick={onMoveDown} />\n <ToolbarButton icon={Trash2} label=\"Delete\" onClick={onDelete} />\n </div>\n </div>\n {children}\n {/* z-30: stay above the next block's (invisible) toolbar, which overlaps this strip. */}\n {onAddBelow && (\n <div className=\"pointer-events-none absolute inset-x-0 -bottom-3 z-30 flex justify-center opacity-0 transition-opacity group-hover/block:opacity-100\">\n <button\n type=\"button\"\n title=\"Add block below\"\n aria-label=\"Add block below\"\n className=\"pointer-events-auto inline-flex h-6 w-6 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-sm hover:bg-primary hover:text-primary-foreground\"\n onClick={(e) => {\n e.stopPropagation();\n onAddBelow();\n }}\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n","import convert, { HSL } from \"color-convert\";\nimport type { Theme } from \"../models\";\n\nfunction formatHSL(hsl: HSL): string {\n return `${hsl[0]} ${hsl[1]}% ${hsl[2]}%`;\n}\n\nconst SHORT_OR_LONG_HEX = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;\nconst HEX_WITH_ALPHA = /^#([0-9a-f]{4}|[0-9a-f]{8})$/i;\nconst CSS_COLOR_FUNCTION =\n /^(oklch|oklab|lab|lch|hwb|hsla?|rgba?|color)\\(\\s*[-+0-9a-z%.,/\\s]+\\)$/i;\n\n/**\n * Turns a theme colour into a CSS colour value, or \"\" when it isn't a\n * colour we can use. Hex (the stored format) is converted to hsl();\n * modern CSS colour functions such as `oklch(...)` are passed through.\n */\nexport function resolveThemeColor(value?: string): string {\n const color = value?.trim();\n if (!color) return \"\";\n if (SHORT_OR_LONG_HEX.test(color)) {\n return `hsl(${formatHSL(convert.hex.hsl(color.replace(\"#\", \"\")))})`;\n }\n if (HEX_WITH_ALPHA.test(color) || CSS_COLOR_FUNCTION.test(color)) return color;\n return \"\";\n}\n\n/**\n * Generates full CSS color values for the custom properties every primitive\n * reads. Full colors (rather than bare HSL channels) let the renderer coexist\n * with Tailwind v4 hosts whose semantic utilities use `var(--primary)` while\n * still accepting CourseLit-derived hex theme data.\n *\n * Callers rendering more than one theme in a document should pass a unique\n * selector so one renderer cannot overwrite another renderer's variables.\n */\nexport function generateThemeStyles(theme: Theme, selector = \".pb-theme\"): string {\n const colors = theme?.theme?.colors;\n if (!colors) {\n return \"\";\n }\n\n const { light, dark } = colors;\n if (!light || !dark) {\n return \"\";\n }\n\n const block = (c: typeof light) => `\n --background: ${resolveThemeColor(c.background)};\n --foreground: ${resolveThemeColor(c.foreground)};\n --card: ${resolveThemeColor(c.card)};\n --card-foreground: ${resolveThemeColor(c.cardForeground)};\n --popover: ${resolveThemeColor(c.popover)};\n --popover-foreground: ${resolveThemeColor(c.popoverForeground)};\n --primary: ${resolveThemeColor(c.primary)};\n --primary-foreground: ${resolveThemeColor(c.primaryForeground)};\n --secondary: ${resolveThemeColor(c.secondary)};\n --secondary-foreground: ${resolveThemeColor(c.secondaryForeground)};\n --muted: ${resolveThemeColor(c.muted)};\n --muted-foreground: ${resolveThemeColor(c.mutedForeground)};\n --accent: ${resolveThemeColor(c.accent)};\n --accent-foreground: ${resolveThemeColor(c.accentForeground)};\n --destructive: ${resolveThemeColor(c.destructive)};\n --border: ${resolveThemeColor(c.border)};\n --input: ${resolveThemeColor(c.input)};\n --ring: ${resolveThemeColor(c.ring)};\n --chart-1: ${resolveThemeColor(c.chart1)};\n --chart-2: ${resolveThemeColor(c.chart2)};\n --chart-3: ${resolveThemeColor(c.chart3)};\n --chart-4: ${resolveThemeColor(c.chart4)};\n --chart-5: ${resolveThemeColor(c.chart5)};\n --sidebar-background: ${resolveThemeColor(c.sidebar)};\n --sidebar-foreground: ${resolveThemeColor(c.sidebarForeground)};\n --sidebar-primary: ${resolveThemeColor(c.sidebarPrimary)};\n --sidebar-primary-foreground: ${resolveThemeColor(c.sidebarPrimaryForeground)};\n --sidebar-accent: ${resolveThemeColor(c.sidebarAccent)};\n --sidebar-accent-foreground: ${resolveThemeColor(c.sidebarAccentForeground)};\n --sidebar-border: ${resolveThemeColor(c.sidebarBorder)};\n --sidebar-ring: ${resolveThemeColor(c.sidebarRing)};\n --shadow-2xs: ${c.shadow2xs ?? \"\"};\n --shadow-xs: ${c.shadowXs ?? \"\"};\n --shadow-sm: ${c.shadowSm ?? \"\"};\n --shadow-md: ${c.shadowMd ?? \"\"};\n --shadow-lg: ${c.shadowLg ?? \"\"};\n --shadow-xl: ${c.shadowXl ?? \"\"};\n --shadow-2xl: ${c.shadow2xl ?? \"\"};\n `;\n\n return `\n ${selector} {\n ${block(light)}\n }\n ${selector}:is(.dark, .dark *) {\n ${block(dark)}\n }\n `;\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useRef } from \"react\";\nimport type { PageData, Theme, WidgetInstance } from \"../models\";\nimport { getWidget, LAYOUT_BLOCK_NAMES } from \"../registry\";\nimport { EditableBlock } from \"./editable-block\";\nimport { ThemeModeSwitcher } from \"../components/theme-mode-switcher\";\nimport { generateThemeStyles } from \"./generate-theme-styles\";\nimport { cn } from \"../primitives/lib/utils\";\nimport {\n PageBuilderLinkProvider,\n type PageBuilderLinkComponent,\n} from \"../components/nav-link\";\n\nexport interface PageRendererProps {\n layout: WidgetInstance[];\n theme: Theme;\n pageData: PageData;\n /** Optional content rendered between the shared header and footer. */\n children?: React.ReactNode;\n /** Host-resolved data keyed by a generic data-slot's configured name. */\n dataSlots?: Record<string, React.ReactNode>;\n /** Resolved palette currently painted (`system` is already applied). */\n nextTheme?: \"light\" | \"dark\";\n onThemeModeChange?: (mode: \"light\" | \"dark\" | \"system\") => void;\n /** When true, renders hover controls (edit/move/delete/add) for use inside the builder canvas. */\n editing?: boolean;\n selectedWidgetId?: string;\n /** Widget to briefly highlight, e.g. right after it was moved. */\n highlightedWidgetId?: string;\n onSelectWidget?: (widgetId: string) => void;\n onMoveWidgetUp?: (widgetId: string) => void;\n onMoveWidgetDown?: (widgetId: string) => void;\n onDeleteWidget?: (widgetId: string) => void;\n onAddWidgetBelow?: (widgetId: string) => void;\n /** Injects the theme's generated CSS custom properties as a `<style>` tag. Disable if the host app renders it elsewhere. */\n injectThemeStyles?: boolean;\n /**\n * Optional host link (e.g. Next.js `Link`) used for internal `/...` paths\n * inside block widgets. Omit it to render native `<a>` tags — no\n * framework dependency.\n */\n linkComponent?: PageBuilderLinkComponent;\n className?: string;\n}\n\n/**\n * Renders a page's widget layout using the block registry. Used both for\n * plain (non-editable) display and, with `editing`, as the live canvas\n * inside the page builder.\n */\nexport function PageRenderer({\n layout,\n theme,\n pageData,\n children,\n dataSlots,\n nextTheme = \"light\",\n onThemeModeChange,\n editing = false,\n selectedWidgetId,\n highlightedWidgetId,\n onSelectWidget,\n onMoveWidgetUp,\n onMoveWidgetDown,\n onDeleteWidget,\n onAddWidgetBelow,\n injectThemeStyles = true,\n linkComponent,\n className,\n}: PageRendererProps) {\n // Refs to each block's wrapper, keyed by widget id. Refs (unlike DOM\n // attribute lookups) stay correct even when SSR and client render\n // different generated widget ids.\n const blockRefs = useRef(new Map<string, HTMLDivElement>());\n const themeScope = `pb-${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n const themeSelector = `[data-pb-theme=\"${themeScope}\"]`;\n\n // Keep the highlighted (just-moved) block in view. Keyed on `layout` too\n // so repeated move clicks on the same widget re-scroll as it travels.\n useEffect(() => {\n if (!highlightedWidgetId) return;\n blockRefs.current\n .get(highlightedWidgetId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [highlightedWidgetId, layout]);\n\n const header = layout.find((widget) => widget.name === \"header\");\n const footer = layout.find((widget) => widget.name === \"footer\");\n const body = layout.filter((widget) => !LAYOUT_BLOCK_NAMES.includes(widget.name));\n\n const themeSwitcher = onThemeModeChange ? (\n <ThemeModeSwitcher\n resolved={nextTheme}\n onToggle={() => onThemeModeChange(nextTheme === \"dark\" ? \"light\" : \"dark\")}\n theme={theme.theme}\n size=\"sm\"\n variant=\"outline\"\n />\n ) : undefined;\n\n const resolvedPageData: PageData = {\n ...pageData,\n };\n\n function renderInstance(\n instance: WidgetInstance,\n options: {\n allowUp: boolean;\n allowDown: boolean;\n locked: boolean;\n allowAddBelow: boolean;\n },\n ) {\n const definition = getWidget(instance.name);\n if (!definition) return null;\n\n const Widget = definition.widget;\n const settings = {\n ...definition.getDefaultSettings?.(),\n ...instance.settings,\n };\n\n return (\n <EditableBlock\n key={instance.widgetId}\n editing={editing}\n containerRef={(node) => {\n if (node) {\n blockRefs.current.set(instance.widgetId, node);\n } else {\n blockRefs.current.delete(instance.widgetId);\n }\n }}\n selected={selectedWidgetId === instance.widgetId}\n highlighted={highlightedWidgetId === instance.widgetId}\n label={definition.metadata.displayName}\n onSelect={() => onSelectWidget?.(instance.widgetId)}\n onMoveUp={\n options.allowUp ? () => onMoveWidgetUp?.(instance.widgetId) : undefined\n }\n onMoveDown={\n options.allowDown ? () => onMoveWidgetDown?.(instance.widgetId) : undefined\n }\n onDelete={\n !options.locked ? () => onDeleteWidget?.(instance.widgetId) : undefined\n }\n onAddBelow={\n options.allowAddBelow && onAddWidgetBelow\n ? () => onAddWidgetBelow(instance.widgetId)\n : undefined\n }\n >\n <Widget\n settings={settings as any}\n state={{ theme }}\n pageData={resolvedPageData}\n data={\n instance.name === \"data-slot\"\n ? dataSlots?.[String(settings.slot ?? \"\")]\n : undefined\n }\n editing={editing}\n themeSwitcher={themeSwitcher}\n />\n </EditableBlock>\n );\n }\n\n return (\n <PageBuilderLinkProvider component={linkComponent}>\n <div\n data-pb-theme={themeScope}\n className={cn(\n \"pb-theme flex min-h-full flex-col bg-background text-foreground\",\n nextTheme === \"dark\" && \"dark\",\n className,\n )}\n >\n {/* Emitted first so the variables exist before any content paints. */}\n {injectThemeStyles && (\n <style>{generateThemeStyles(theme, themeSelector)}</style>\n )}\n {header &&\n renderInstance(header, {\n allowUp: false,\n allowDown: false,\n locked: true,\n allowAddBelow: true,\n })}\n <div className=\"flex flex-1 flex-col\">\n {children !== undefined &&\n !body.some((instance) => instance.name === \"data-slot\")\n ? children\n : body.map((instance, index) =>\n renderInstance(instance, {\n allowUp: instance.moveable && index !== 0,\n allowDown: instance.moveable && index !== body.length - 1,\n locked: !instance.deletable,\n allowAddBelow: true,\n }),\n )}\n </div>\n {footer &&\n renderInstance(footer, {\n allowUp: false,\n allowDown: false,\n locked: true,\n allowAddBelow: false,\n })}\n </div>\n </PageBuilderLinkProvider>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/registry-names.ts","../src/registry.ts","../src/renderer/editable-block.tsx","../src/renderer/generate-theme-styles.ts","../src/renderer/page-renderer.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-USPQ3AOW.js","sourcesContent":["/** Blocks placed outside the normal flow by the renderer. */\nexport const LAYOUT_BLOCK_NAMES = [\"header\", \"footer\"];\n","import type { Widget } from \"./models\";\nimport { LAYOUT_BLOCK_NAMES } from \"./registry-names\";\nimport {\n Header,\n Hero,\n Content,\n Featured,\n Faq,\n Pricing,\n Banner,\n EmailForm,\n SupportForm,\n Footer,\n RichText,\n Grid,\n MediaBlock,\n Marquee,\n Embed,\n CodeSnippetBlock,\n DataSlot,\n} from \"./blocks\";\n\n/**\n * Every block available to the page builder, keyed by its\n * `metadata.name`. `header` and `footer` are singleton, layout-level\n * blocks placed outside the normal flow by the renderer.\n */\nexport const blockRegistry: Record<string, Widget<any>> = {\n header: Header,\n hero: Hero,\n content: Content,\n featured: Featured,\n faq: Faq,\n pricing: Pricing,\n banner: Banner,\n \"email-form\": EmailForm,\n \"support-form\": SupportForm,\n footer: Footer,\n \"rich-text\": RichText,\n grid: Grid,\n media: MediaBlock,\n marquee: Marquee,\n embed: Embed,\n \"code-snippet\": CodeSnippetBlock,\n \"data-slot\": DataSlot,\n};\n\nexport { LAYOUT_BLOCK_NAMES };\nexport const NON_ADDABLE_BLOCK_NAMES = [...LAYOUT_BLOCK_NAMES, \"data-slot\"];\n\n/**\n * Adds a host application's block to the shared renderer and builder\n * registry. Register blocks while the application module initializes, before\n * rendering either `PageBuilder` or `PageRenderer`.\n *\n * Built-in names are intentionally protected: a persisted page must always\n * have one stable implementation for a block name. Give host blocks a\n * namespaced name such as `acme-event-list`.\n */\nexport function registerBlock(widget: Widget<any>): void {\n const name = widget.metadata.name.trim();\n if (!name) {\n throw new Error(\"A page-builder block must have a non-empty name.\");\n }\n if (blockRegistry[name]) {\n throw new Error(`A page-builder block named \\\"${name}\\\" is already registered.`);\n }\n if (NON_ADDABLE_BLOCK_NAMES.includes(name)) {\n throw new Error(\n `\\\"${name}\\\" is a reserved page-builder block name and cannot be registered by a host application.`,\n );\n }\n blockRegistry[name] = widget;\n}\n\nexport function getWidget(name: string): Widget<any> | undefined {\n return blockRegistry[name];\n}\n\n/** Blocks a user can add to the body of a page. */\nexport function getAddableBlocks(): Widget<any>[] {\n return Object.values(blockRegistry).filter(\n (widget) => !NON_ADDABLE_BLOCK_NAMES.includes(widget.metadata.name),\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { ArrowDown, ArrowUp, Plus, Settings2, Trash2 } from \"lucide-react\";\nimport { cn } from \"../primitives/lib/utils\";\n\nexport interface EditableBlockProps {\n children: React.ReactNode;\n editing: boolean;\n /** Ref to the wrapper element so the canvas can scroll the block into view. */\n containerRef?: React.Ref<HTMLDivElement>;\n selected?: boolean;\n /** Draws a temporary attention flash, e.g. right after the block was moved. */\n highlighted?: boolean;\n label?: string;\n onSelect?: () => void;\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n onDelete?: () => void;\n onAddBelow?: () => void;\n}\n\nfunction ToolbarButton({\n icon: Icon,\n label,\n onClick,\n}: {\n icon: React.ComponentType<{ className?: string }>;\n label: string;\n onClick?: () => void;\n}) {\n if (!onClick) return null;\n return (\n <button\n type=\"button\"\n title={label}\n aria-label={label}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded bg-background text-foreground shadow-sm hover:bg-muted\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n </button>\n );\n}\n\n/**\n * Wraps a rendered block with hover/selection affordances when the page\n * builder is in editing mode. In non-editing (plain display) mode it's a\n * transparent passthrough.\n */\nexport function EditableBlock({\n children,\n editing,\n containerRef,\n selected,\n highlighted,\n label,\n onSelect,\n onMoveUp,\n onMoveDown,\n onDelete,\n onAddBelow,\n}: EditableBlockProps) {\n if (!editing) {\n return <>{children}</>;\n }\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"group/block relative outline outline-1 outline-transparent transition-colors hover:outline-primary/40\",\n selected && \"outline-2 outline-primary\",\n highlighted && \"outline-2 outline-primary/70\",\n )}\n onClick={onSelect}\n >\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 z-10 bg-primary/10 opacity-0 transition-opacity duration-500\",\n highlighted && \"opacity-100\",\n )}\n />\n <div className=\"pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center opacity-0 transition-opacity group-hover/block:opacity-100\">\n <div className=\"pointer-events-auto flex items-center gap-1 rounded-b-md border border-t-0 border-border bg-background px-1.5 py-1 shadow-sm\">\n {label && (\n <span className=\"px-1.5 text-xs font-medium text-muted-foreground\">\n {label}\n </span>\n )}\n <ToolbarButton icon={Settings2} label=\"Edit settings\" onClick={onSelect} />\n <ToolbarButton icon={ArrowUp} label=\"Move up\" onClick={onMoveUp} />\n <ToolbarButton icon={ArrowDown} label=\"Move down\" onClick={onMoveDown} />\n <ToolbarButton icon={Trash2} label=\"Delete\" onClick={onDelete} />\n </div>\n </div>\n {children}\n {/* z-30: stay above the next block's (invisible) toolbar, which overlaps this strip. */}\n {onAddBelow && (\n <div className=\"pointer-events-none absolute inset-x-0 -bottom-3 z-30 flex justify-center opacity-0 transition-opacity group-hover/block:opacity-100\">\n <button\n type=\"button\"\n title=\"Add block below\"\n aria-label=\"Add block below\"\n className=\"pointer-events-auto inline-flex h-6 w-6 items-center justify-center rounded-full border border-border bg-background text-foreground shadow-sm hover:bg-primary hover:text-primary-foreground\"\n onClick={(e) => {\n e.stopPropagation();\n onAddBelow();\n }}\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n","import convert, { HSL } from \"color-convert\";\nimport type { Theme } from \"../models\";\n\nfunction formatHSL(hsl: HSL): string {\n return `${hsl[0]} ${hsl[1]}% ${hsl[2]}%`;\n}\n\nconst SHORT_OR_LONG_HEX = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;\nconst HEX_WITH_ALPHA = /^#([0-9a-f]{4}|[0-9a-f]{8})$/i;\nconst CSS_COLOR_FUNCTION =\n /^(oklch|oklab|lab|lch|hwb|hsla?|rgba?|color)\\(\\s*[-+0-9a-z%.,/\\s]+\\)$/i;\n\n/**\n * Turns a theme colour into a CSS colour value, or \"\" when it isn't a\n * colour we can use. Hex (the stored format) is converted to hsl();\n * modern CSS colour functions such as `oklch(...)` are passed through.\n */\nexport function resolveThemeColor(value?: string): string {\n const color = value?.trim();\n if (!color) return \"\";\n if (SHORT_OR_LONG_HEX.test(color)) {\n return `hsl(${formatHSL(convert.hex.hsl(color.replace(\"#\", \"\")))})`;\n }\n if (HEX_WITH_ALPHA.test(color) || CSS_COLOR_FUNCTION.test(color)) return color;\n return \"\";\n}\n\n/**\n * Generates full CSS color values for the custom properties every primitive\n * reads. Full colors (rather than bare HSL channels) let the renderer coexist\n * with Tailwind v4 hosts whose semantic utilities use `var(--primary)` while\n * still accepting CourseLit-derived hex theme data.\n *\n * Callers rendering more than one theme in a document should pass a unique\n * selector so one renderer cannot overwrite another renderer's variables.\n */\nexport function generateThemeStyles(theme: Theme, selector = \".pb-theme\"): string {\n const colors = theme?.theme?.colors;\n if (!colors) {\n return \"\";\n }\n\n const { light, dark } = colors;\n if (!light || !dark) {\n return \"\";\n }\n\n const block = (c: typeof light) => `\n --background: ${resolveThemeColor(c.background)};\n --foreground: ${resolveThemeColor(c.foreground)};\n --card: ${resolveThemeColor(c.card)};\n --card-foreground: ${resolveThemeColor(c.cardForeground)};\n --popover: ${resolveThemeColor(c.popover)};\n --popover-foreground: ${resolveThemeColor(c.popoverForeground)};\n --primary: ${resolveThemeColor(c.primary)};\n --primary-foreground: ${resolveThemeColor(c.primaryForeground)};\n --secondary: ${resolveThemeColor(c.secondary)};\n --secondary-foreground: ${resolveThemeColor(c.secondaryForeground)};\n --muted: ${resolveThemeColor(c.muted)};\n --muted-foreground: ${resolveThemeColor(c.mutedForeground)};\n --accent: ${resolveThemeColor(c.accent)};\n --accent-foreground: ${resolveThemeColor(c.accentForeground)};\n --destructive: ${resolveThemeColor(c.destructive)};\n --border: ${resolveThemeColor(c.border)};\n --input: ${resolveThemeColor(c.input)};\n --ring: ${resolveThemeColor(c.ring)};\n --chart-1: ${resolveThemeColor(c.chart1)};\n --chart-2: ${resolveThemeColor(c.chart2)};\n --chart-3: ${resolveThemeColor(c.chart3)};\n --chart-4: ${resolveThemeColor(c.chart4)};\n --chart-5: ${resolveThemeColor(c.chart5)};\n --sidebar-background: ${resolveThemeColor(c.sidebar)};\n --sidebar-foreground: ${resolveThemeColor(c.sidebarForeground)};\n --sidebar-primary: ${resolveThemeColor(c.sidebarPrimary)};\n --sidebar-primary-foreground: ${resolveThemeColor(c.sidebarPrimaryForeground)};\n --sidebar-accent: ${resolveThemeColor(c.sidebarAccent)};\n --sidebar-accent-foreground: ${resolveThemeColor(c.sidebarAccentForeground)};\n --sidebar-border: ${resolveThemeColor(c.sidebarBorder)};\n --sidebar-ring: ${resolveThemeColor(c.sidebarRing)};\n --shadow-2xs: ${c.shadow2xs ?? \"\"};\n --shadow-xs: ${c.shadowXs ?? \"\"};\n --shadow-sm: ${c.shadowSm ?? \"\"};\n --shadow-md: ${c.shadowMd ?? \"\"};\n --shadow-lg: ${c.shadowLg ?? \"\"};\n --shadow-xl: ${c.shadowXl ?? \"\"};\n --shadow-2xl: ${c.shadow2xl ?? \"\"};\n `;\n\n return `\n ${selector} {\n ${block(light)}\n }\n ${selector}:is(.dark, .dark *) {\n ${block(dark)}\n }\n `;\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useRef } from \"react\";\nimport type { PageData, Theme, WidgetInstance } from \"../models\";\nimport { getWidget, LAYOUT_BLOCK_NAMES } from \"../registry\";\nimport { EditableBlock } from \"./editable-block\";\nimport { ThemeModeSwitcher } from \"../components/theme-mode-switcher\";\nimport { generateThemeStyles } from \"./generate-theme-styles\";\nimport { cn } from \"../primitives/lib/utils\";\nimport {\n PageBuilderLinkProvider,\n type PageBuilderLinkComponent,\n} from \"../components/nav-link\";\n\nexport interface PageRendererProps {\n layout: WidgetInstance[];\n theme: Theme;\n pageData: PageData;\n /** Optional content rendered between the shared header and footer. */\n children?: React.ReactNode;\n /** Host-resolved data keyed by a generic data-slot's configured name. */\n dataSlots?: Record<string, React.ReactNode>;\n /** Resolved palette currently painted (`system` is already applied). */\n nextTheme?: \"light\" | \"dark\";\n onThemeModeChange?: (mode: \"light\" | \"dark\" | \"system\") => void;\n /** When true, renders hover controls (edit/move/delete/add) for use inside the builder canvas. */\n editing?: boolean;\n selectedWidgetId?: string;\n /** Widget to briefly highlight, e.g. right after it was moved. */\n highlightedWidgetId?: string;\n onSelectWidget?: (widgetId: string) => void;\n onMoveWidgetUp?: (widgetId: string) => void;\n onMoveWidgetDown?: (widgetId: string) => void;\n onDeleteWidget?: (widgetId: string) => void;\n onAddWidgetBelow?: (widgetId: string) => void;\n /** Injects the theme's generated CSS custom properties as a `<style>` tag. Disable if the host app renders it elsewhere. */\n injectThemeStyles?: boolean;\n /**\n * Optional host link (e.g. Next.js `Link`) used for internal `/...` paths\n * inside block widgets. Omit it to render native `<a>` tags — no\n * framework dependency.\n */\n linkComponent?: PageBuilderLinkComponent;\n className?: string;\n}\n\n/**\n * Renders a page's widget layout using the block registry. Used both for\n * plain (non-editable) display and, with `editing`, as the live canvas\n * inside the page builder.\n */\nexport function PageRenderer({\n layout,\n theme,\n pageData,\n children,\n dataSlots,\n nextTheme = \"light\",\n onThemeModeChange,\n editing = false,\n selectedWidgetId,\n highlightedWidgetId,\n onSelectWidget,\n onMoveWidgetUp,\n onMoveWidgetDown,\n onDeleteWidget,\n onAddWidgetBelow,\n injectThemeStyles = true,\n linkComponent,\n className,\n}: PageRendererProps) {\n // Refs to each block's wrapper, keyed by widget id. Refs (unlike DOM\n // attribute lookups) stay correct even when SSR and client render\n // different generated widget ids.\n const blockRefs = useRef(new Map<string, HTMLDivElement>());\n const themeScope = `pb-${useId().replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n const themeSelector = `[data-pb-theme=\"${themeScope}\"]`;\n\n // Keep the highlighted (just-moved) block in view. Keyed on `layout` too\n // so repeated move clicks on the same widget re-scroll as it travels.\n useEffect(() => {\n if (!highlightedWidgetId) return;\n blockRefs.current\n .get(highlightedWidgetId)\n ?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\n }, [highlightedWidgetId, layout]);\n\n const header = layout.find((widget) => widget.name === \"header\");\n const footer = layout.find((widget) => widget.name === \"footer\");\n const body = layout.filter((widget) => !LAYOUT_BLOCK_NAMES.includes(widget.name));\n\n const themeSwitcher = onThemeModeChange ? (\n <ThemeModeSwitcher\n resolved={nextTheme}\n onToggle={() => onThemeModeChange(nextTheme === \"dark\" ? \"light\" : \"dark\")}\n theme={theme.theme}\n size=\"sm\"\n variant=\"outline\"\n />\n ) : undefined;\n\n const resolvedPageData: PageData = {\n ...pageData,\n };\n\n function renderInstance(\n instance: WidgetInstance,\n options: {\n allowUp: boolean;\n allowDown: boolean;\n locked: boolean;\n allowAddBelow: boolean;\n },\n ) {\n const definition = getWidget(instance.name);\n if (!definition) return null;\n\n const Widget = definition.widget;\n const settings = {\n ...definition.getDefaultSettings?.(),\n ...instance.settings,\n };\n\n return (\n <EditableBlock\n key={instance.widgetId}\n editing={editing}\n containerRef={(node) => {\n if (node) {\n blockRefs.current.set(instance.widgetId, node);\n } else {\n blockRefs.current.delete(instance.widgetId);\n }\n }}\n selected={selectedWidgetId === instance.widgetId}\n highlighted={highlightedWidgetId === instance.widgetId}\n label={definition.metadata.displayName}\n onSelect={() => onSelectWidget?.(instance.widgetId)}\n onMoveUp={\n options.allowUp ? () => onMoveWidgetUp?.(instance.widgetId) : undefined\n }\n onMoveDown={\n options.allowDown ? () => onMoveWidgetDown?.(instance.widgetId) : undefined\n }\n onDelete={\n !options.locked ? () => onDeleteWidget?.(instance.widgetId) : undefined\n }\n onAddBelow={\n options.allowAddBelow && onAddWidgetBelow\n ? () => onAddWidgetBelow(instance.widgetId)\n : undefined\n }\n >\n <Widget\n settings={settings as any}\n state={{ theme }}\n pageData={resolvedPageData}\n data={\n instance.name === \"data-slot\"\n ? dataSlots?.[String(settings.slot ?? \"\")]\n : undefined\n }\n editing={editing}\n themeSwitcher={themeSwitcher}\n />\n </EditableBlock>\n );\n }\n\n return (\n <PageBuilderLinkProvider component={linkComponent}>\n <div\n data-pb-theme={themeScope}\n className={cn(\n \"pb-theme flex min-h-full flex-col bg-background text-foreground\",\n nextTheme === \"dark\" && \"dark\",\n className,\n )}\n >\n {/* Emitted first so the variables exist before any content paints. */}\n {injectThemeStyles && (\n <style>{generateThemeStyles(theme, themeSelector)}</style>\n )}\n {header &&\n renderInstance(header, {\n allowUp: false,\n allowDown: false,\n locked: true,\n allowAddBelow: true,\n })}\n <div className=\"flex flex-1 flex-col\">\n {children !== undefined &&\n !body.some((instance) => instance.name === \"data-slot\")\n ? children\n : body.map((instance, index) =>\n renderInstance(instance, {\n allowUp: instance.moveable && index !== 0,\n allowDown: instance.moveable && index !== body.length - 1,\n locked: !instance.deletable,\n allowAddBelow: true,\n }),\n )}\n </div>\n {footer &&\n renderInstance(footer, {\n allowUp: false,\n allowDown: false,\n locked: true,\n allowAddBelow: false,\n })}\n </div>\n </PageBuilderLinkProvider>\n );\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { A as Alignment, H as HeadingLevel, a as HorizontalAlignment, R as Respo
9
9
  export { TextEditorContent } from '@frontlit/text-editor';
10
10
  export { EditableBlock, EditableBlockProps, PageRenderer, PageRendererProps, generateThemeStyles, resolveThemeColor } from './renderer/index.js';
11
11
  export { P as PageBuilderLinkComponent, a as PageBuilderLinkProps, b as PageBuilderLinkProvider } from './nav-link-BfxvQ1s6.js';
12
- export { BlockPicker, BuilderTopBar, ColorSelector, ContentPaddingSelector, MaxWidthSelector, PATTERN_PRESETS, PageBuilder, PageBuilderPropertyHeader, PageBuilderProps, PageBuilderSlider, PageBuilderState, PatternPreset, PatternPresetCategory, PreviewDevice, SectionBackgroundPanel, SeoEditor, SettingsPanel, ThemeEditor, ThemeEditorProps, VerticalPaddingSelector, getMaxWidthTWClass, getVerticalPaddingTWClass } from './builder/index.js';
12
+ export { BlockPicker, BuilderTopBar, ColorSelector, ContentPaddingSelector, MaxWidthSelector, PATTERN_PRESETS, PageBuilder, PageBuilderPropertyHeader, PageBuilderProps, PageBuilderSlider, PageBuilderState, PatternPreset, PatternPresetCategory, PreviewDevice, SectionBackgroundPanel, SeoEditor, SettingsPanel, ThemeEditor, ThemeEditorProps, VerticalPaddingSelector, getMaxWidthTWClass, getVerticalPaddingTWClass, resolveIcon } from './builder/index.js';
13
13
  export { DataSlotLoadRequest, DataSlotLoader, DataSlotLoaders, loadDataSlots } from './data-slots.js';
14
14
  import 'react';
15
15
  import 'lucide-react';
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import './chunk-HWOVSHIW.js';
3
- export { BlockPicker, BuilderTopBar, ColorSelector, ContentPaddingSelector, MaxWidthSelector, PATTERN_PRESETS, PageBuilder, PageBuilderPropertyHeader, PageBuilderSlider, SectionBackgroundPanel, SeoEditor, SettingsPanel, ThemeEditor, VerticalPaddingSelector, createDefaultLayout, createWidgetInstance, ensureRequiredSharedWidgets, getDefaultTheme, getMaxWidthTWClass, getVerticalPaddingTWClass, withDefaultSettings } from './chunk-GIKTOAQS.js';
4
- export { EditableBlock, LAYOUT_BLOCK_NAMES, NON_ADDABLE_BLOCK_NAMES, PageRenderer, blockRegistry, generateThemeStyles, getAddableBlocks, getWidget, registerBlock, resolveThemeColor } from './chunk-IU4KATI2.js';
3
+ export { BlockPicker, BuilderTopBar, ColorSelector, ContentPaddingSelector, MaxWidthSelector, PATTERN_PRESETS, PageBuilder, PageBuilderPropertyHeader, PageBuilderSlider, SectionBackgroundPanel, SeoEditor, SettingsPanel, ThemeEditor, VerticalPaddingSelector, createDefaultLayout, createWidgetInstance, ensureRequiredSharedWidgets, getDefaultTheme, getMaxWidthTWClass, getVerticalPaddingTWClass, resolveIcon, withDefaultSettings } from './chunk-LMCEOWQG.js';
4
+ export { EditableBlock, LAYOUT_BLOCK_NAMES, NON_ADDABLE_BLOCK_NAMES, PageRenderer, blockRegistry, generateThemeStyles, getAddableBlocks, getWidget, registerBlock, resolveThemeColor } from './chunk-USPQ3AOW.js';
5
5
  import './chunk-BBI7UHOA.js';
6
- import './chunk-K4WCLHMS.js';
6
+ import './chunk-5J6TLS5U.js';
7
7
  export { PageBuilderLinkProvider } from './chunk-36QHCIPM.js';
8
8
  import './chunk-J7Z4UW45.js';
9
9
  export { getMediaAlt, getMediaUrl } from './chunk-XU7ALPGQ.js';
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- export { EditableBlock, PageRenderer, generateThemeStyles, resolveThemeColor } from '../chunk-IU4KATI2.js';
2
+ export { EditableBlock, PageRenderer, generateThemeStyles, resolveThemeColor } from '../chunk-USPQ3AOW.js';
3
3
  import '../chunk-BBI7UHOA.js';
4
- import '../chunk-K4WCLHMS.js';
4
+ import '../chunk-5J6TLS5U.js';
5
5
  export { PageBuilderLinkProvider } from '../chunk-36QHCIPM.js';
6
6
  import '../chunk-J7Z4UW45.js';
7
7
  import '../chunk-XU7ALPGQ.js';
@@ -89,6 +89,7 @@ function cn(...inputs) {
89
89
 
90
90
  // src/blocks/header/widget.tsx
91
91
  import clsx2 from "clsx";
92
+ import { Github } from "lucide-react";
92
93
 
93
94
  // src/components/image.tsx
94
95
  import { jsx } from "react/jsx-runtime";
@@ -866,6 +867,15 @@ function HeaderLink({
866
867
 
867
868
  // src/blocks/header/widget.tsx
868
869
  import { HeaderMobileMenu } from "./islands/header-mobile-menu.js";
870
+ import { GithubStars } from "./islands/header-github-stars.js";
871
+
872
+ // src/blocks/header/github.ts
873
+ function parseGithubRepo(value) {
874
+ const match = value?.trim().match(/^(?:https?:\/\/(?:www\.)?github\.com\/)?([\w.-]+\/[\w.-]+?)(?:\.git)?\/?$/);
875
+ return match?.[1];
876
+ }
877
+
878
+ // src/blocks/header/widget.tsx
869
879
  import { jsx as jsx16, jsxs as jsxs2 } from "react/jsx-runtime";
870
880
  function HeaderWidget({
871
881
  settings: {
@@ -876,6 +886,8 @@ function HeaderWidget({
876
886
  linkAlignment = "left",
877
887
  layout = "fixed",
878
888
  backdropBlur = false,
889
+ githubRepo,
890
+ showGithubStars,
879
891
  cssId,
880
892
  maxWidth,
881
893
  verticalPadding,
@@ -896,6 +908,8 @@ function HeaderWidget({
896
908
  const resolvedLogoText = pageData.siteTitle;
897
909
  const resolvedLogoAlt = pageData.siteLogoAlt || resolvedLogoText || "";
898
910
  const effectiveLogoCorners = logoCorners ?? 2;
911
+ const hasCta = Boolean(ctaLabel && ctaHref);
912
+ const repo = parseGithubRepo(githubRepo);
899
913
  const logo = /* @__PURE__ */ jsx16(NavLink2, { href: "/", className: "no-underline", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
900
914
  resolvedLogoImage && /* @__PURE__ */ jsx16(
901
915
  Image,
@@ -912,9 +926,22 @@ function HeaderWidget({
912
926
  resolvedLogoText && /* @__PURE__ */ jsx16(Header4, { theme: overriddenTheme, as: "span", children: resolvedLogoText })
913
927
  ] }) });
914
928
  const ctaAndMenu = /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
929
+ repo && /* @__PURE__ */ jsx16(
930
+ "a",
931
+ {
932
+ href: `https://github.com/${repo}`,
933
+ target: "_blank",
934
+ rel: "noopener noreferrer",
935
+ children: /* @__PURE__ */ jsxs2(Button2, { theme: overriddenTheme, variant: "ghost", size: "sm", className: "gap-1.5", children: [
936
+ /* @__PURE__ */ jsx16(Github, { className: "h-4 w-4", "aria-hidden": true }),
937
+ /* @__PURE__ */ jsx16("span", { className: "sr-only", children: "GitHub repository" }),
938
+ showGithubStars && /* @__PURE__ */ jsx16(GithubStars, { repo })
939
+ ] })
940
+ }
941
+ ),
915
942
  buttonLinks.map((link) => /* @__PURE__ */ jsx16("div", { className: "hidden lg:!block", children: /* @__PURE__ */ jsx16(HeaderLink, { link, theme: overriddenTheme }) }, link.id)),
916
- ctaLabel && ctaHref && /* @__PURE__ */ jsx16("div", { className: "hidden lg:!block", children: /* @__PURE__ */ jsx16(NavLink2, { href: ctaHref, children: /* @__PURE__ */ jsx16(Button2, { theme: overriddenTheme, size: "sm", children: ctaLabel }) }) }),
917
- /* @__PURE__ */ jsx16("div", { className: "lg:hidden", children: /* @__PURE__ */ jsx16(
943
+ hasCta && /* @__PURE__ */ jsx16("div", { className: "hidden lg:!block", children: /* @__PURE__ */ jsx16(NavLink2, { href: ctaHref, children: /* @__PURE__ */ jsx16(Button2, { theme: overriddenTheme, size: "sm", children: ctaLabel }) }) }),
944
+ (links.length > 0 || hasCta) && /* @__PURE__ */ jsx16("div", { className: "lg:hidden", children: /* @__PURE__ */ jsx16(
918
945
  HeaderMobileMenu,
919
946
  {
920
947
  links,
@@ -1567,8 +1594,17 @@ var faqDefaults = {
1567
1594
 
1568
1595
  // src/blocks/pricing/widget.tsx
1569
1596
  import clsx7 from "clsx";
1597
+ import { PricingPeriodSwitch } from "./islands/pricing-period-switch.js";
1570
1598
  import { NavLink as NavLink4 } from "./islands/nav-link.js";
1571
- import { jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
1599
+ import { Fragment as Fragment2, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
1600
+ var lgColumns = {
1601
+ 1: "lg:grid-cols-1",
1602
+ 2: "lg:grid-cols-2",
1603
+ 3: "lg:grid-cols-3",
1604
+ 4: "lg:grid-cols-4"
1605
+ };
1606
+ var monthlyOnly = "group-data-[period=yearly]/pricing:hidden";
1607
+ var yearlyOnly = "hidden group-data-[period=yearly]/pricing:block";
1572
1608
  function PricingWidget({
1573
1609
  settings: {
1574
1610
  title,
@@ -1578,6 +1614,10 @@ function PricingWidget({
1578
1614
  headerAlignment = "center",
1579
1615
  tiers,
1580
1616
  layout = "grid",
1617
+ pricingSwitcher,
1618
+ monthlyPriceCaption,
1619
+ yearlyPriceCaption,
1620
+ defaultPeriod = "yearly",
1581
1621
  cssId,
1582
1622
  maxWidth,
1583
1623
  verticalPadding,
@@ -1588,6 +1628,76 @@ function PricingWidget({
1588
1628
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
1589
1629
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
1590
1630
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
1631
+ const plans = tiers && tiers.length > 0 && /* @__PURE__ */ jsx21(
1632
+ "div",
1633
+ {
1634
+ className: clsx7(
1635
+ layout === "stacked" ? "mx-auto flex w-full max-w-xl flex-col gap-6" : [
1636
+ "grid grid-cols-1 gap-6 items-stretch",
1637
+ tiers.length === 1 && "mx-auto w-full max-w-xl",
1638
+ tiers.length >= 2 && "md:grid-cols-2",
1639
+ lgColumns[Math.min(tiers.length, 4)]
1640
+ ]
1641
+ ),
1642
+ children: tiers.map((tier, index) => /* @__PURE__ */ jsx21(
1643
+ PageCard,
1644
+ {
1645
+ theme: overriddenTheme,
1646
+ className: clsx7(
1647
+ tier.highlighted && "ring-2 ring-primary",
1648
+ layout === "highlight" && tier.highlighted && "relative z-10 shadow-xl md:-translate-y-3"
1649
+ ),
1650
+ children: /* @__PURE__ */ jsxs7(
1651
+ PageCardContent,
1652
+ {
1653
+ theme: overriddenTheme,
1654
+ className: "h-full flex flex-col gap-4",
1655
+ children: [
1656
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2", children: [
1657
+ /* @__PURE__ */ jsx21(Preheader, { theme: overriddenTheme, children: tier.name }),
1658
+ tier.highlighted && /* @__PURE__ */ jsx21(Badge2, { theme: overriddenTheme, children: "Most popular" })
1659
+ ] }),
1660
+ /* @__PURE__ */ jsx21(PageCardHeader, { theme: overriddenTheme, children: pricingSwitcher ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
1661
+ /* @__PURE__ */ jsx21("span", { className: monthlyOnly, children: tier.price }),
1662
+ /* @__PURE__ */ jsx21("span", { className: yearlyOnly, children: tier.priceYearly || tier.price })
1663
+ ] }) : tier.price }),
1664
+ tier.description && /* @__PURE__ */ jsx21(Text1, { theme: overriddenTheme, children: tier.description }),
1665
+ tier.features && tier.features.length > 0 && /* @__PURE__ */ jsx21("div", { className: "grow flex flex-col gap-2", children: tier.features.map((feature, i) => /* @__PURE__ */ jsx21(Text2, { theme: overriddenTheme, children: feature }, i)) }),
1666
+ pricingSwitcher && tier.buttonActionYearly && tier.buttonActionYearly !== tier.buttonAction ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
1667
+ /* @__PURE__ */ jsx21(
1668
+ TierButton,
1669
+ {
1670
+ tier,
1671
+ href: tier.buttonAction,
1672
+ className: monthlyOnly,
1673
+ theme: overriddenTheme
1674
+ }
1675
+ ),
1676
+ /* @__PURE__ */ jsx21(
1677
+ TierButton,
1678
+ {
1679
+ tier,
1680
+ href: tier.buttonActionYearly,
1681
+ className: yearlyOnly,
1682
+ theme: overriddenTheme
1683
+ }
1684
+ )
1685
+ ] }) : /* @__PURE__ */ jsx21(
1686
+ TierButton,
1687
+ {
1688
+ tier,
1689
+ href: tier.buttonAction,
1690
+ theme: overriddenTheme
1691
+ }
1692
+ )
1693
+ ]
1694
+ }
1695
+ )
1696
+ },
1697
+ index
1698
+ ))
1699
+ }
1700
+ );
1591
1701
  return /* @__PURE__ */ jsx21(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-8", children: [
1592
1702
  /* @__PURE__ */ jsxs7(
1593
1703
  "div",
@@ -1602,50 +1712,35 @@ function PricingWidget({
1602
1712
  ]
1603
1713
  }
1604
1714
  ),
1605
- tiers && tiers.length > 0 && /* @__PURE__ */ jsx21(
1606
- "div",
1715
+ tiers && tiers.length > 0 && (pricingSwitcher ? /* @__PURE__ */ jsx21(
1716
+ PricingPeriodSwitch,
1607
1717
  {
1608
- className: layout === "stacked" ? "mx-auto flex w-full max-w-xl flex-col gap-6" : "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-stretch",
1609
- children: tiers.map((tier, index) => /* @__PURE__ */ jsx21(
1610
- PageCard,
1611
- {
1612
- theme: overriddenTheme,
1613
- className: clsx7(
1614
- tier.highlighted && "ring-2 ring-primary",
1615
- layout === "highlight" && tier.highlighted && "relative z-10 shadow-xl md:-translate-y-3"
1616
- ),
1617
- children: /* @__PURE__ */ jsxs7(
1618
- PageCardContent,
1619
- {
1620
- theme: overriddenTheme,
1621
- className: "h-full flex flex-col gap-4",
1622
- children: [
1623
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2", children: [
1624
- /* @__PURE__ */ jsx21(Preheader, { theme: overriddenTheme, children: tier.name }),
1625
- tier.highlighted && /* @__PURE__ */ jsx21(Badge2, { theme: overriddenTheme, children: "Most popular" })
1626
- ] }),
1627
- /* @__PURE__ */ jsx21(PageCardHeader, { theme: overriddenTheme, children: tier.price }),
1628
- tier.description && /* @__PURE__ */ jsx21(Text1, { theme: overriddenTheme, children: tier.description }),
1629
- tier.features && tier.features.length > 0 && /* @__PURE__ */ jsx21("div", { className: "grow flex flex-col gap-2", children: tier.features.map((feature, i) => /* @__PURE__ */ jsx21(Text2, { theme: overriddenTheme, children: feature }, i)) }),
1630
- tier.buttonAction && tier.buttonCaption && /* @__PURE__ */ jsx21(NavLink4, { href: tier.buttonAction, className: "w-full mt-auto", children: /* @__PURE__ */ jsx21(
1631
- Button2,
1632
- {
1633
- theme: overriddenTheme,
1634
- variant: tier.highlighted ? "default" : "secondary",
1635
- className: "w-full",
1636
- children: tier.buttonCaption
1637
- }
1638
- ) })
1639
- ]
1640
- }
1641
- )
1642
- },
1643
- index
1644
- ))
1718
+ defaultPeriod,
1719
+ monthlyCaption: monthlyPriceCaption || "Monthly",
1720
+ yearlyCaption: yearlyPriceCaption || "Yearly",
1721
+ theme: overriddenTheme,
1722
+ children: plans
1645
1723
  }
1646
- )
1724
+ ) : plans)
1647
1725
  ] }) });
1648
1726
  }
1727
+ function TierButton({
1728
+ tier,
1729
+ href,
1730
+ className,
1731
+ theme
1732
+ }) {
1733
+ if (!href || !tier.buttonCaption) return null;
1734
+ return /* @__PURE__ */ jsx21(NavLink4, { href, className: clsx7("w-full mt-auto", className), children: /* @__PURE__ */ jsx21(
1735
+ Button2,
1736
+ {
1737
+ theme,
1738
+ variant: tier.highlighted ? "default" : "secondary",
1739
+ className: "w-full",
1740
+ children: tier.buttonCaption
1741
+ }
1742
+ ) });
1743
+ }
1649
1744
 
1650
1745
  // src/blocks/pricing/defaults.ts
1651
1746
  var pricingDefaults = {
@@ -1688,7 +1783,7 @@ var pricingDefaults = {
1688
1783
  // src/blocks/banner/widget.tsx
1689
1784
  import clsx8 from "clsx";
1690
1785
  import { NavLink as NavLink5 } from "./islands/nav-link.js";
1691
- import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1786
+ import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1692
1787
  function BannerWidget({
1693
1788
  settings: {
1694
1789
  title,
@@ -1714,7 +1809,7 @@ function BannerWidget({
1714
1809
  const isCentered = contentAlignment === "center";
1715
1810
  const isSplit = layout === "split";
1716
1811
  const isBoxed = layout === "boxed";
1717
- const heading = /* @__PURE__ */ jsxs8(Fragment2, { children: [
1812
+ const heading = /* @__PURE__ */ jsxs8(Fragment3, { children: [
1718
1813
  /* @__PURE__ */ jsx22(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
1719
1814
  description && /* @__PURE__ */ jsx22(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx22(TextRenderer, { json: description, theme: overriddenTheme }) })
1720
1815
  ] });
@@ -2088,7 +2183,7 @@ var richTextDefaults = {
2088
2183
  import clsx11 from "clsx";
2089
2184
  import * as Icons2 from "lucide-react";
2090
2185
  import { NavLink as NavLink7 } from "./islands/nav-link.js";
2091
- import { Fragment as Fragment3, jsx as jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
2186
+ import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
2092
2187
  function resolveIcon2(name) {
2093
2188
  if (!name) return null;
2094
2189
  return Icons2[name] ?? null;
@@ -2125,10 +2220,10 @@ function GridItemCard({ item, theme }) {
2125
2220
  item.description && /* @__PURE__ */ jsx27(Text2, { theme, children: item.description }),
2126
2221
  item.buttonAction && item.buttonCaption && /* @__PURE__ */ jsx27(NavLink7, { href: item.buttonAction, className: "mt-2", children: /* @__PURE__ */ jsx27(Button2, { theme, variant: "secondary", size: "sm", children: item.buttonCaption }) })
2127
2222
  ] });
2128
- return /* @__PURE__ */ jsx27(PageCard, { theme, children: /* @__PURE__ */ jsx27(PageCardContent, { theme, className: "flex h-full flex-col gap-3", children: mediaFirst ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
2223
+ return /* @__PURE__ */ jsx27(PageCard, { theme, children: /* @__PURE__ */ jsx27(PageCardContent, { theme, className: "flex h-full flex-col gap-3", children: mediaFirst ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
2129
2224
  media,
2130
2225
  text
2131
- ] }) : /* @__PURE__ */ jsxs12(Fragment3, { children: [
2226
+ ] }) : /* @__PURE__ */ jsxs12(Fragment4, { children: [
2132
2227
  text,
2133
2228
  media
2134
2229
  ] }) }) });
@@ -2293,7 +2388,7 @@ import React5 from "react";
2293
2388
  import * as Icons3 from "lucide-react";
2294
2389
  import { NavLink as NavLink8 } from "./islands/nav-link.js";
2295
2390
  import { MarqueeTrack } from "./islands/marquee-track.js";
2296
- import { Fragment as Fragment4, jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
2391
+ import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs13 } from "react/jsx-runtime";
2297
2392
  function resolveIcon3(name) {
2298
2393
  if (!name) return null;
2299
2394
  return Icons3[name] ?? null;
@@ -2344,7 +2439,7 @@ function MarqueeWidget({
2344
2439
  };
2345
2440
  return /* @__PURE__ */ jsx29(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs13("div", { className: "relative", "aria-hidden": "true", children: [
2346
2441
  /* @__PURE__ */ jsx29(MarqueeTrack, { speed, direction, pauseOnHover, children: items.map(renderItem) }),
2347
- fadeWidth > 0 && /* @__PURE__ */ jsxs13(Fragment4, { children: [
2442
+ fadeWidth > 0 && /* @__PURE__ */ jsxs13(Fragment5, { children: [
2348
2443
  /* @__PURE__ */ jsx29(
2349
2444
  "div",
2350
2445
  {