@siteable/core 0.1.0

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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +4 -0
  3. package/README.md +82 -0
  4. package/dist/index.d.ts +401 -0
  5. package/dist/index.js +5389 -0
  6. package/package.json +66 -0
  7. package/src/blocks/BlockWrapper.tsx +149 -0
  8. package/src/blocks/banner/BannerBlock.tsx +38 -0
  9. package/src/blocks/contact/ContactBlock.tsx +63 -0
  10. package/src/blocks/content/ContentBlock.tsx +38 -0
  11. package/src/blocks/cta/CtaBlock.tsx +67 -0
  12. package/src/blocks/divider/DividerBlock.tsx +30 -0
  13. package/src/blocks/faq/FaqBlock.tsx +82 -0
  14. package/src/blocks/features/FeaturesBlock.tsx +170 -0
  15. package/src/blocks/footer/FooterBlock.tsx +136 -0
  16. package/src/blocks/gallery/GalleryBlock.tsx +67 -0
  17. package/src/blocks/hero/HeroBlock.tsx +163 -0
  18. package/src/blocks/image/ImageBlock.tsx +78 -0
  19. package/src/blocks/logocloud/LogoCloudBlock.tsx +70 -0
  20. package/src/blocks/navbar/NavbarBlock.tsx +102 -0
  21. package/src/blocks/newsletter/NewsletterBlock.tsx +51 -0
  22. package/src/blocks/pricing/PricingBlock.tsx +173 -0
  23. package/src/blocks/registry.tsx +90 -0
  24. package/src/blocks/stats/StatsBlock.tsx +96 -0
  25. package/src/blocks/team/TeamBlock.tsx +50 -0
  26. package/src/blocks/testimonials/TestimonialsBlock.tsx +203 -0
  27. package/src/blocks/types.ts +72 -0
  28. package/src/blocks/video/VideoBlock.tsx +58 -0
  29. package/src/editor/AgentPanel.tsx +318 -0
  30. package/src/editor/Canvas.tsx +95 -0
  31. package/src/editor/CanvasEmpty.tsx +40 -0
  32. package/src/editor/CanvasToolbar.tsx +366 -0
  33. package/src/editor/DesignPanel.tsx +224 -0
  34. package/src/editor/EditorLayout.tsx +196 -0
  35. package/src/editor/GenerationOverlay.tsx +201 -0
  36. package/src/editor/JsonDrawer.tsx +139 -0
  37. package/src/editor/LayersPanel.tsx +259 -0
  38. package/src/editor/LeftSidebar.tsx +136 -0
  39. package/src/editor/PropertiesPanel.tsx +564 -0
  40. package/src/editor/RightSidebar.tsx +85 -0
  41. package/src/editor/ShortcutsModal.tsx +126 -0
  42. package/src/editor/VersionHistory.tsx +110 -0
  43. package/src/index.ts +133 -0
  44. package/src/lib/block-metadata.ts +167 -0
  45. package/src/lib/export-html.ts +1424 -0
  46. package/src/lib/generate-site.ts +206 -0
  47. package/src/lib/generation-prompt.ts +64 -0
  48. package/src/lib/markdown.ts +88 -0
  49. package/src/lib/templates.ts +139 -0
  50. package/src/lib/theme-presets.ts +330 -0
  51. package/src/lib/useGoogleFonts.ts +49 -0
  52. package/src/lib/useScrollReveal.ts +28 -0
  53. package/src/settings/GeminiKeyInputField.tsx +82 -0
  54. package/src/store/configStore.ts +344 -0
  55. package/src/store/editorStore.ts +50 -0
  56. package/src/styles.css +210 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Federico De Ponte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,4 @@
1
+ OpenPage MIT attribution provenance
2
+
3
+ This package is the engine subset of OpenPage, distributed under the MIT License
4
+ — see LICENSE for the full text and copyright.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # @siteable/core
2
+
3
+ A visual website builder engine: 19 typed block components, a drag-edit canvas, theme
4
+ presets, AI generation, and a one-click HTML export. JSON is the source of truth — every
5
+ edit produces clean, diffable JSON that humans and AI agents can both read and write.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @siteable/core
11
+ ```
12
+
13
+ ## Peer Dependencies
14
+
15
+ The host app supplies these — `@siteable/core` declares them as peerDependencies but does
16
+ not bundle them. Install with caret ranges matching the package's own peer spec:
17
+
18
+ ```bash
19
+ npm install react@^19.2.0 react-dom@^19.2.0 zustand@^5.0.11 immer@^11.1.4 \
20
+ @dnd-kit/core@^6.3.1 @dnd-kit/sortable@^10.0.0 @dnd-kit/utilities@^3.2.2 \
21
+ sonner@^2.0.7 lucide-react@^0.575.0 tailwindcss@^4.2.1
22
+ ```
23
+
24
+ `react-router-dom` is **not** a peer — the engine is router-agnostic.
25
+
26
+ ## Tailwind v4 Setup
27
+
28
+ Add `@source` and `@import` to your app's global CSS so Tailwind v4's scanner picks up the
29
+ package's block component classes:
30
+
31
+ ```css
32
+ /* app.css */
33
+ @import "tailwindcss";
34
+
35
+ @source "./node_modules/@siteable/core/src/**/*.{ts,tsx}";
36
+ @import "@siteable/core/src/styles.css";
37
+ ```
38
+
39
+ The package ships raw, unbuilt Tailwind v4 source (no precompiled CSS in `dist/`).
40
+
41
+ ## Usage
42
+
43
+ ```tsx
44
+ import { EditorLayout } from '@siteable/core'
45
+
46
+ function App() {
47
+ return <EditorLayout />
48
+ }
49
+ ```
50
+
51
+ `validateSiteConfig`, `generateSiteConfig`, `exportSiteToHTML`, `themePresets`, and the
52
+ two zustand stores (`useConfigStore`, `useEditorStore`) are all available from the package
53
+ entry.
54
+
55
+ ## Single-store invariant
56
+
57
+ `useConfigStore` and `useEditorStore` are zustand module singletons. Always import through
58
+ the package entry (`@siteable/core`) — never deep-import `@siteable/core/src/...` in an app
59
+ that also imports the package's main entry. Two copies of the same store in one app silently
60
+ produce divergent state.
61
+
62
+ ## Browser Support
63
+
64
+ Modern evergreen browsers (last 2 Chrome / Firefox / Safari / Edge versions). No IE.
65
+
66
+ ## Contributing
67
+
68
+ Issues and PRs welcome via [GitHub](https://github.com/Siteable/siteable-core/issues).
69
+
70
+ ## License
71
+
72
+ MIT — see [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
73
+
74
+ ---
75
+
76
+ ### Provenance
77
+
78
+ This is the engine subset extracted from
79
+ [OpenPage](https://github.com/buildingopen/openpage). The MIT body, attribution, and
80
+ adopted-conventions headers carry over from that codebase; the package is maintained
81
+ independently under the `@siteable` npm scope with `Siteable Contributors` as the copyright
82
+ holder (see NOTICE for the full lineage statement).
@@ -0,0 +1,401 @@
1
+ import { JSX } from 'react';
2
+ import { PersistOptions } from 'zustand/middleware';
3
+ import { ReactNode } from 'react';
4
+ import { RefObject } from 'react';
5
+ import { StoreApi } from 'zustand';
6
+ import { UseBoundStore } from 'zustand';
7
+
8
+ export declare function AgentPanel(): JSX.Element;
9
+
10
+ export declare function BannerBlock({ block }: {
11
+ block: BlockConfig;
12
+ }): JSX.Element;
13
+
14
+ export declare interface BlockConfig {
15
+ id: string;
16
+ type: BlockType;
17
+ variant: BlockVariant;
18
+ props: Record<string, unknown>;
19
+ }
20
+
21
+ export declare interface BlockMeta {
22
+ type: BlockType;
23
+ label: string;
24
+ description: string;
25
+ category: string;
26
+ variants: string[];
27
+ defaultProps: Record<string, unknown>;
28
+ }
29
+
30
+ export declare const blockMetadata: BlockMeta[];
31
+
32
+ export declare type BlockType = 'navbar' | 'hero' | 'features' | 'pricing' | 'cta' | 'footer' | 'testimonials' | 'stats' | 'faq' | 'team' | 'contact' | 'newsletter' | 'logocloud' | 'divider' | 'banner' | 'content' | 'image' | 'video' | 'gallery';
33
+
34
+ export declare type BlockVariant = string;
35
+
36
+ export declare function BlockWrapper({ block, isSelected, onSelect, children }: Props): JSX.Element;
37
+
38
+ export declare function buildTemplate(id: string, name: string): SiteConfig;
39
+
40
+ export declare function Canvas(): JSX.Element;
41
+
42
+ export declare function CanvasEmpty(): JSX.Element;
43
+
44
+ export declare function CanvasToolbar({ activeProject, onExit }?: CanvasToolbarProps): JSX.Element;
45
+
46
+ export declare interface CanvasToolbarProps {
47
+ activeProject?: {
48
+ name: string;
49
+ settings?: ExportSiteSettings;
50
+ };
51
+ onExit?: () => void;
52
+ }
53
+
54
+ export declare const categories: string[];
55
+
56
+ declare interface ConfigState {
57
+ config: SiteConfig;
58
+ activePageId: string;
59
+ undoStack: UndoEntry[];
60
+ redoStack: UndoEntry[];
61
+ setConfig: (config: SiteConfig) => void;
62
+ setActivePage: (id: string) => void;
63
+ getActivePageBlocks: () => BlockConfig[];
64
+ updateBlock: (id: string, updates: Partial<BlockConfig>) => void;
65
+ updateBlockProps: (id: string, props: Record<string, unknown>) => void;
66
+ addBlock: (block: BlockConfig, index?: number) => void;
67
+ removeBlock: (id: string) => void;
68
+ duplicateBlock: (id: string) => void;
69
+ moveBlock: (fromIndex: number, toIndex: number) => void;
70
+ addPage: (name: string, path: string) => string;
71
+ removePage: (id: string) => void;
72
+ renamePage: (id: string, name: string) => void;
73
+ setTheme: (theme: Partial<ThemeConfig>) => void;
74
+ updateTheme: (partial: Partial<ThemeConfig>) => void;
75
+ previewTheme: (partial: Partial<ThemeConfig>) => void;
76
+ undo: () => void;
77
+ redo: () => void;
78
+ canUndo: () => boolean;
79
+ canRedo: () => boolean;
80
+ }
81
+
82
+ export declare function ContactBlock({ block }: {
83
+ block: BlockConfig;
84
+ }): JSX.Element;
85
+
86
+ export declare function ContentBlock({ block }: {
87
+ block: BlockConfig;
88
+ }): JSX.Element;
89
+
90
+ export declare function CtaBlock({ block }: {
91
+ block: BlockConfig;
92
+ }): JSX.Element;
93
+
94
+ export declare const defaultConfig: SiteConfig;
95
+
96
+ export declare const defaultTheme: ThemeConfig;
97
+
98
+ export declare function DesignPanel(): JSX.Element;
99
+
100
+ export declare function DividerBlock({ block }: {
101
+ block: BlockConfig;
102
+ }): JSX.Element;
103
+
104
+ export declare function downloadHTML(html: string, filename: string): void;
105
+
106
+ export declare function EditorLayout({ onConfigChange, onRename, onCreate, activeProject, onExit, onServerFallback }?: EditorLayoutProps): JSX.Element;
107
+
108
+ export declare interface EditorLayoutProps {
109
+ onConfigChange?: (id: string, config: SiteConfig) => void;
110
+ onRename?: (id: string, name: string) => void;
111
+ onCreate?: (name: string) => string;
112
+ activeProject?: {
113
+ name: string;
114
+ settings?: ExportSiteSettings;
115
+ };
116
+ onExit?: () => void;
117
+ onServerFallback?: (prompt: string, signal?: AbortSignal) => Promise<SiteConfig>;
118
+ }
119
+
120
+ declare interface EditorState {
121
+ selectedBlockId: string | null;
122
+ viewport: Viewport;
123
+ jsonDrawerOpen: boolean;
124
+ historyOpen: boolean;
125
+ shortcutsModalOpen: boolean;
126
+ previewMode: boolean;
127
+ activeProjectId: string | null;
128
+ isGenerating: boolean;
129
+ generationPrompt: string | null;
130
+ generationError: string | null;
131
+ selectBlock: (id: string | null) => void;
132
+ setViewport: (vp: Viewport) => void;
133
+ toggleJsonDrawer: () => void;
134
+ toggleHistory: () => void;
135
+ toggleShortcutsModal: () => void;
136
+ togglePreview: () => void;
137
+ setActiveProject: (id: string | null) => void;
138
+ setGenerating: (prompt: string | null) => void;
139
+ setGenerationError: (err: string | null) => void;
140
+ clearGeneration: () => void;
141
+ }
142
+
143
+ export declare interface ExportSiteOptions {
144
+ settings?: ExportSiteSettings;
145
+ }
146
+
147
+ export declare interface ExportSiteSettings {
148
+ siteName?: string;
149
+ siteDescription?: string;
150
+ faviconUrl?: string;
151
+ language?: string;
152
+ seoTitle?: string;
153
+ seoDescription?: string;
154
+ ogImageUrl?: string;
155
+ gaId?: string;
156
+ posthogKey?: string;
157
+ }
158
+
159
+ export declare function exportSiteToHTML(config: SiteConfig, options?: ExportSiteOptions): string;
160
+
161
+ export declare function exportToHTML(config: SiteConfig, options?: ExportSiteOptions): Promise<string>;
162
+
163
+ export declare function FaqBlock({ block }: {
164
+ block: BlockConfig;
165
+ }): JSX.Element;
166
+
167
+ export declare function FeaturesBlock({ block }: {
168
+ block: BlockConfig;
169
+ }): JSX.Element;
170
+
171
+ export declare function FooterBlock({ block }: {
172
+ block: BlockConfig;
173
+ }): JSX.Element;
174
+
175
+ export declare function GalleryBlock({ block }: {
176
+ block: BlockConfig;
177
+ }): JSX.Element;
178
+
179
+ /**
180
+ * Gemini API Key FieldGroup — BYOK (bring-your-own-key) input with show/hide and a
181
+ * live validation button that pings the Google Gemini REST API.
182
+ *
183
+ * Extracted from src/routes/Settings.tsx ApiPanel (Gemini FieldGroup only).
184
+ * - Local state for show/hide + testing in-flight flag.
185
+ * - Persists the key in localStorage under `openpage-gemini-key`; cleared when empty.
186
+ * - Validates by GET https://generativelanguage.googleapis.com/v1beta/models?key=...
187
+ * - `toast` (sonner) is the only external dependency preserved from the inline source.
188
+ */
189
+ export declare function GeminiKeyInputField(): JSX.Element;
190
+
191
+ export declare function generateSiteConfig(prompt: string, signal?: AbortSignal, onServerFallback?: (prompt: string, signal?: AbortSignal) => Promise<SiteConfig>): Promise<GenerationResult>;
192
+
193
+ export declare const GENERATION_PROMPT = "You are a website configuration generator for OpenPage, a visual website builder.\n\nGiven a user's description, generate a complete JSON site configuration.\n\n## Output Schema\n\nReturn a JSON object matching this exact schema:\n\n{\n \"name\": \"Site Name\",\n \"theme\": {\n \"bg0\": \"#hex\", \"bg1\": \"#hex\", \"bg2\": \"#hex\", \"bg3\": \"#hex\", \"bg4\": \"#hex\", \"bg5\": \"#hex\",\n \"text0\": \"#hex\", \"text1\": \"#hex\", \"text2\": \"#hex\", \"text3\": \"#hex\",\n \"accent\": \"#hex\", \"accentDim\": \"#hex\",\n \"borderDefault\": \"#hex\", \"borderSubtle\": \"#hex\", \"borderHover\": \"#hex\",\n \"fontSans\": \"Font Name\", \"fontDisplay\": \"Font Name\", \"fontMono\": \"Font Name\",\n \"radius\": 8, \"radiusLg\": 12\n },\n \"pages\": [\n { \"id\": \"page-home\", \"name\": \"Home\", \"path\": \"/\", \"blocks\": [...] },\n { \"id\": \"page-about\", \"name\": \"About\", \"path\": \"/about\", \"blocks\": [...] }\n ],\n \"blocks\": []\n}\n\nEach page has its own blocks array. Generate at least 2 pages: Home and one additional page (About, Pricing, or Features depending on the site type). The top-level \"blocks\" array should be empty (blocks live inside pages).\n\n## Available Block Types\n\n1. navbar (variants: default, centered) - Props: { logo, links[], ctaText }\n2. hero (variants: centered, split, gradient, minimal) - Props: { badge?, headline, subheadline, primaryCta, secondaryCta? }\n3. features (variants: grid, list, alternating) - Props: { label?, title, subtitle?, items: [{ icon?, title, description }] }\n4. pricing (variants: simple, comparison) - Props: { title, subtitle?, tiers?: [{ name, price, period?, description?, features[], cta, featured? }] }\n5. cta (variants: simple, split) - Props: { headline, subheadline?, buttonText }\n6. footer (variants: simple, multi-column, minimal) - Props: { logo, copyright, links[] }\n7. testimonials (variants: cards, carousel, spotlight) - Props: { title?, items?: [{ name, role?, quote, rating? }] }\n8. stats (variants: grid, bar, counter) - Props: { title?, items?: [{ value, label }] }\n9. faq (variants: accordion) - Props: { title?, items?: [{ question, answer }] }\n10. team (variants: grid) - Props: { title?, subtitle?, members?: [{ name, role }] }\n11. contact (variants: form) - Props: { title?, subtitle? }\n12. newsletter (variants: simple) - Props: { title?, subtitle?, buttonText? }\n13. logocloud (variants: default) - Props: { title? }\n14. content (variants: prose, columns, highlight) - Props: { body } (markdown: **bold**, *italic*, ## headers, - lists)\n15. image (variants: hero-image, side-by-side, grid) - Props: { src?, alt?, title?, subtitle?, images?: [{ src, alt }], imageSide? }\n16. video (variants: youtube, vimeo) - Props: { url, title? }\n17. gallery (variants: grid, masonry) - Props: { title?, images?: [{ src?, alt?, caption? }] }\n18. divider (variants: line, space, dots) - Props: { height?, width? }\n19. banner (variants: ribbon, bar) - Props: { text, linkText?, linkUrl? }\n\nIcons: Blocks, Code, Bot, Zap, Shield, Globe, Layers, Palette, Rocket, Star, Lock, Settings\nFonts: DM Sans, Inter, Space Grotesk, Poppins, Manrope, Outfit, Plus Jakarta Sans, Sora, Nunito Sans, Work Sans, Rubik, Raleway\n\n## Rules\n\n1. ALWAYS generate at least 2 pages. The Home page MUST include: navbar, hero, at least 2 content sections, a CTA, and a footer\n2. Generate 6-10 blocks per page\n3. Write specific, realistic copy matching the user's description\n4. Pick a theme that fits the vibe (dark for tech, warm for food, clean for agencies)\n5. Use unique block IDs (format: block-type-1, block-hero-1, etc.)\n6. Do NOT use placeholder text like \"Lorem ipsum\"\n7. Make copy compelling and specific to the described business\n8. Each page needs a unique id (page-home, page-about, etc.), a name, and a path (/, /about, etc.)\n\nReturn ONLY valid JSON. No markdown, no code fences, no explanation.";
194
+
195
+ export declare function GenerationOverlay(): JSX.Element | null;
196
+
197
+ export declare interface GenerationResult {
198
+ config: SiteConfig;
199
+ source: 'ai' | 'template';
200
+ }
201
+
202
+ export declare function getTemplateForPrompt(prompt: string): SiteConfig;
203
+
204
+ export declare const googleFontOptions: string[];
205
+
206
+ export declare function HeroBlock({ block }: {
207
+ block: BlockConfig;
208
+ }): JSX.Element;
209
+
210
+ export declare function hexToRgb(hex: string): string;
211
+
212
+ export declare function ImageBlock({ block }: {
213
+ block: BlockConfig;
214
+ }): JSX.Element;
215
+
216
+ export declare function JsonDrawer(): JSX.Element;
217
+
218
+ export declare function LayersPanel(): JSX.Element;
219
+
220
+ export declare function LeftSidebar(): JSX.Element;
221
+
222
+ export declare function LogoCloudBlock({ block }: {
223
+ block: BlockConfig;
224
+ }): JSX.Element;
225
+
226
+ export declare function NavbarBlock({ block }: {
227
+ block: BlockConfig;
228
+ }): JSX.Element;
229
+
230
+ export declare function NewsletterBlock({ block }: {
231
+ block: BlockConfig;
232
+ }): JSX.Element;
233
+
234
+ export declare interface PageConfig {
235
+ id: string;
236
+ name: string;
237
+ path: string;
238
+ blocks: BlockConfig[];
239
+ }
240
+
241
+ export declare function previewHTML(html: string): void;
242
+
243
+ export declare function PricingBlock({ block }: {
244
+ block: BlockConfig;
245
+ }): JSX.Element;
246
+
247
+ export declare function PropertiesPanel({ block }: {
248
+ block: BlockConfig;
249
+ }): JSX.Element;
250
+
251
+ declare interface Props {
252
+ block: BlockConfig;
253
+ isSelected: boolean;
254
+ onSelect: () => void;
255
+ children: ReactNode;
256
+ }
257
+
258
+ export declare function RenderBlock({ block }: {
259
+ block: BlockConfig;
260
+ }): ReactNode;
261
+
262
+ /**
263
+ * Simple markdown-to-React renderer. No dangerouslySetInnerHTML, no XSS surface.
264
+ * Supports: ## headers, **bold**, *italic*, - lists, line breaks.
265
+ */
266
+ export declare function renderMarkdown(text: string): ReactNode[];
267
+
268
+ export declare function resolveTheme(partial?: Partial<ThemeConfig>): ThemeConfig;
269
+
270
+ export declare function RightSidebar(): JSX.Element;
271
+
272
+ export declare function ShortcutsModal(): JSX.Element | null;
273
+
274
+ export declare interface SiteConfig {
275
+ name: string;
276
+ pages?: PageConfig[];
277
+ blocks: BlockConfig[];
278
+ theme?: Partial<ThemeConfig>;
279
+ }
280
+
281
+ export declare function StatsBlock({ block }: {
282
+ block: BlockConfig;
283
+ }): JSX.Element;
284
+
285
+ export declare function TeamBlock({ block }: {
286
+ block: BlockConfig;
287
+ }): JSX.Element;
288
+
289
+ export declare const templateMeta: readonly [{
290
+ readonly id: "portfolio";
291
+ readonly name: "Portfolio";
292
+ readonly description: "Showcase your work and skills";
293
+ readonly accent: "#06b6d4";
294
+ readonly blockCount: 7;
295
+ readonly templateIndex: 0;
296
+ readonly icon: "Briefcase";
297
+ }, {
298
+ readonly id: "restaurant";
299
+ readonly name: "Restaurant";
300
+ readonly description: "Menu, reservations, and ambiance";
301
+ readonly accent: "#e8a838";
302
+ readonly blockCount: 7;
303
+ readonly templateIndex: 1;
304
+ readonly icon: "UtensilsCrossed";
305
+ }, {
306
+ readonly id: "agency";
307
+ readonly name: "Agency";
308
+ readonly description: "Services, case studies, and team";
309
+ readonly accent: "#228be6";
310
+ readonly blockCount: 8;
311
+ readonly templateIndex: 2;
312
+ readonly icon: "Building2";
313
+ }, {
314
+ readonly id: "blog";
315
+ readonly name: "Blog";
316
+ readonly description: "Articles, topics, and subscribers";
317
+ readonly accent: "#4f46e5";
318
+ readonly blockCount: 7;
319
+ readonly templateIndex: 3;
320
+ readonly icon: "BookOpen";
321
+ }];
322
+
323
+ export declare function TestimonialsBlock({ block }: {
324
+ block: BlockConfig;
325
+ }): JSX.Element;
326
+
327
+ export declare interface ThemeConfig {
328
+ bg0: string;
329
+ bg1: string;
330
+ bg2: string;
331
+ bg3: string;
332
+ bg4: string;
333
+ bg5: string;
334
+ text0: string;
335
+ text1: string;
336
+ text2: string;
337
+ text3: string;
338
+ accent: string;
339
+ accentDim: string;
340
+ borderDefault: string;
341
+ borderSubtle: string;
342
+ borderHover: string;
343
+ fontSans: string;
344
+ fontDisplay: string;
345
+ fontMono: string;
346
+ radius: number;
347
+ radiusLg: number;
348
+ }
349
+
350
+ export declare interface ThemePreset {
351
+ id: string;
352
+ name: string;
353
+ theme: ThemeConfig;
354
+ }
355
+
356
+ export declare const themePresets: ThemePreset[];
357
+
358
+ export declare function themeToCSS(theme: ThemeConfig): Record<string, string>;
359
+
360
+ declare interface UndoEntry {
361
+ pages?: PageConfig[];
362
+ blocks: BlockConfig[];
363
+ theme?: Partial<ThemeConfig>;
364
+ label: string;
365
+ timestamp: number;
366
+ }
367
+
368
+ export declare const useConfigStore: UseBoundStore<Omit<StoreApi<ConfigState>, "setState" | "persist"> & {
369
+ setState(partial: ConfigState | Partial<ConfigState> | ((state: ConfigState) => ConfigState | Partial<ConfigState>), replace?: false | undefined): unknown;
370
+ setState(state: ConfigState | ((state: ConfigState) => ConfigState), replace: true): unknown;
371
+ persist: {
372
+ setOptions: (options: Partial<PersistOptions<ConfigState, Record<string, unknown>, unknown>>) => void;
373
+ clearStorage: () => void;
374
+ rehydrate: () => Promise<void> | void;
375
+ hasHydrated: () => boolean;
376
+ onHydrate: (fn: (state: ConfigState) => void) => () => void;
377
+ onFinishHydration: (fn: (state: ConfigState) => void) => () => void;
378
+ getOptions: () => Partial<PersistOptions<ConfigState, Record<string, unknown>, unknown>>;
379
+ };
380
+ }>;
381
+
382
+ export declare const useEditorStore: UseBoundStore<StoreApi<EditorState>>;
383
+
384
+ export declare function useGoogleFonts(fonts: string[]): void;
385
+
386
+ export declare function useScrollReveal(disabled?: boolean): {
387
+ ref: RefObject<HTMLDivElement | null>;
388
+ isRevealed: boolean;
389
+ };
390
+
391
+ export declare function validateSiteConfig(raw: unknown, prompt?: string): SiteConfig;
392
+
393
+ export declare function VersionHistory(): JSX.Element;
394
+
395
+ export declare function VideoBlock({ block }: {
396
+ block: BlockConfig;
397
+ }): JSX.Element;
398
+
399
+ export declare type Viewport = 'desktop' | 'tablet' | 'mobile';
400
+
401
+ export { }