@levo-so/site-runtime 0.1.113 → 0.2.1

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 (40) hide show
  1. package/CollectionInput-5QMoXahu.js +147 -0
  2. package/DateTimeWidget-CARoq7bQ.js +254 -0
  3. package/PhoneWidget-vtDO9CFq.js +99 -0
  4. package/Popover-B76-bN-a.js +57 -0
  5. package/RichTextWidget-CafZBEKI.js +912 -0
  6. package/ThemeProvider-Cm2jJC7a.js +381 -0
  7. package/Tooltip-Bx-BfR7T.js +78 -0
  8. package/VerifyButton-D1Mwk04d.js +299 -0
  9. package/index.d.ts +674 -0
  10. package/index.js +5752 -0
  11. package/package.json +63 -31
  12. package/styles.css +2 -0
  13. package/README.md +0 -93
  14. package/dist/LevoSiteProvider.d.ts +0 -25
  15. package/dist/LevoSiteProvider.js +0 -23
  16. package/dist/client.d.ts +0 -26
  17. package/dist/client.js +0 -14
  18. package/dist/data/index.d.ts +0 -101
  19. package/dist/data/index.js +0 -79
  20. package/dist/index.d.ts +0 -26
  21. package/dist/index.js +0 -6
  22. package/dist/inspector/dom.d.ts +0 -56
  23. package/dist/inspector/dom.js +0 -224
  24. package/dist/inspector/editorChannel.d.ts +0 -7
  25. package/dist/inspector/editorChannel.js +0 -19
  26. package/dist/inspector/historyWatcher.d.ts +0 -8
  27. package/dist/inspector/historyWatcher.js +0 -24
  28. package/dist/inspector/index.d.ts +0 -2
  29. package/dist/inspector/index.js +0 -191
  30. package/dist/inspector/messageRouter.d.ts +0 -38
  31. package/dist/inspector/messageRouter.js +0 -134
  32. package/dist/inspector/originalsStash.d.ts +0 -12
  33. package/dist/inspector/originalsStash.js +0 -24
  34. package/dist/inspector/protocol.d.ts +0 -180
  35. package/dist/inspector/stagedOverrides.d.ts +0 -28
  36. package/dist/inspector/stagedOverrides.js +0 -60
  37. package/dist/inspector/textEditController.d.ts +0 -24
  38. package/dist/inspector/textEditController.js +0 -62
  39. package/dist/pageHead.d.ts +0 -75
  40. package/dist/pageHead.js +0 -102
package/index.d.ts ADDED
@@ -0,0 +1,674 @@
1
+ import { ILemaCollection } from '@levo-so/core';
2
+ import { ILevoClient } from '@levo-so/core';
3
+ import { ILevoInsights } from '@levo-so/insights';
4
+ import { JSX } from 'react/jsx-runtime';
5
+ import { LevoQuery } from '@levo-so/core';
6
+
7
+ /**
8
+ * Build the site's `levoHead` from its `site.json`. Each route passes its OWN imported
9
+ * meta file (`head: levoHead(meta)`) — no path matching anywhere; the import IS the
10
+ * pairing. The argument default lets a meta-less route render pure site defaults.
11
+ *
12
+ * Dynamic (`$slug`) routes pass a second argument naming the record fields that feed the
13
+ * head (`head: levoHead(meta, { source: "post", title: "title", … })`), so every slug
14
+ * gets its own title/description/share image instead of the route's shared static meta.
15
+ * Pages that set no `canonical` get a self-referencing one derived from the site domain
16
+ * + request path (og:url follows it in pageHead) — per-slug correct on dynamic routes.
17
+ */
18
+ export declare const createLevoHead: (site: ISiteJson) => (meta?: IPlatformMetaFile, dynamic?: ILevoDynamicHead) => (ctx?: IHeadCtx) => IComposedHead;
19
+
20
+ /**
21
+ * Build the one-line route loader (`loader: levoLoader(dataSources)`): prefetch the
22
+ * page's declared data sources on the server so SSR ships fully-rendered HTML, and
23
+ * return them keyed by source key — that map is the route's `loaderData`, which
24
+ * `levoHead`'s dynamic config reads for per-record heads. An empty `dataSources` ({})
25
+ * resolves to an empty map. Context is typed structurally (just `queryClient`) so the
26
+ * scaffold's router types never enter the package.
27
+ */
28
+ export declare const createLevoLoader: (config: ILevoSiteConfig) => (sources: ILevoDataSources) => ({ context, params, }: {
29
+ context: {
30
+ queryClient: IQueryClientLike;
31
+ };
32
+ params?: Record<string, string>;
33
+ }) => Promise<Record<string, unknown>>;
34
+
35
+ /**
36
+ * Build the site's core Levo client from config, or `null` when the site isn't wired to a
37
+ * backend yet (no `apiUrl`). SSR-safe — `createLevoClient` guards its window/document reads.
38
+ *
39
+ * Explicit return type on purpose: inference would inline core-internal names its rolled-up
40
+ * d.ts doesn't export → TS4023 on declaration emit.
41
+ */
42
+ export declare const createSiteClient: (config?: ILevoSiteConfig) => ILevoClient | null;
43
+
44
+ export declare interface IComposedHead {
45
+ meta: IHeadEntry[];
46
+ links: IHeadEntry[];
47
+ scripts: IHeadEntry[];
48
+ }
49
+
50
+ /** Editor → preview (received by `onMessage`; dashboard's `IOutboundMessage`). */
51
+ export declare type IEditorToPreview = {
52
+ type: "set-inspect";
53
+ enabled: boolean;
54
+ } | {
55
+ type: "set-text-edit";
56
+ enabled: boolean;
57
+ } | {
58
+ type: "clear-selection";
59
+ } | {
60
+ type: "select-element";
61
+ element: IElementLocator;
62
+ } | {
63
+ type: "edit-element";
64
+ element: IElementLocator;
65
+ } | {
66
+ type: "highlight-element";
67
+ element: IElementLocator;
68
+ } | {
69
+ type: "clear-highlight";
70
+ } | {
71
+ type: "request-layers";
72
+ } | {
73
+ type: "request-sources";
74
+ } | {
75
+ type: "revert-text";
76
+ element: IElementLocator;
77
+ } | {
78
+ type: "navigate";
79
+ route: string;
80
+ } | {
81
+ type: "stage-style";
82
+ stageId: string;
83
+ element: IElementLocator;
84
+ styles: Record<string, string>;
85
+ media?: string;
86
+ } | {
87
+ type: "stage-text";
88
+ stageId: string;
89
+ element: IElementLocator;
90
+ value: string;
91
+ } | {
92
+ type: "clear-staged";
93
+ stageId?: string;
94
+ };
95
+
96
+ /** A nested element locator — `file:line:col` + occurrence index. Never top-level. */
97
+ export declare interface IElementLocator {
98
+ source: string;
99
+ index?: number;
100
+ }
101
+
102
+ /**
103
+ * The slice of the router's head-fn context we read. Structural on purpose (like
104
+ * IQueryClientLike) so the package never depends on the router's types: `loaderData` is
105
+ * the loader's return value — `prefetchLevoSources`' source-keyed map — and
106
+ * `match.pathname` is the request path. Both read defensively; absent = skipped.
107
+ */
108
+ declare interface IHeadCtx {
109
+ loaderData?: unknown;
110
+ match?: {
111
+ pathname?: string;
112
+ };
113
+ }
114
+
115
+ declare interface IHeadEntry {
116
+ [attr: string]: string | undefined;
117
+ }
118
+
119
+ export declare type IHistoryFn = History["pushState"];
120
+
121
+ export declare interface ILayersNode {
122
+ tag: string;
123
+ source?: string;
124
+ index?: number;
125
+ text?: string;
126
+ /** The element carries the `hidden` utility (display:none) — a reachability hint the
127
+ * Layers panel surfaces. Live + class-based, so it covers component internals too
128
+ * (the dashboard no longer parses JSX for this). Present only when true. */
129
+ hidden?: boolean;
130
+ childCount: number;
131
+ children: ILayersNode[];
132
+ }
133
+
134
+ /** The shape a page exports so its route loader can prefetch every binding it renders. */
135
+ export declare type ILevoDataSources = Record<string, ILevoSourceDef>;
136
+
137
+ /**
138
+ * Per-record head config for a dynamic (`$slug`) route — `levoHead`'s optional second
139
+ * argument. A static literal (AI/editor-written, next to the route's meta import); each
140
+ * field names a FIELD on the loaded record (the `dataSources` entry named by `source`).
141
+ * At request time the record's values override the static meta file per-field, so every
142
+ * slug ships its own title, description, and share image.
143
+ */
144
+ export declare interface ILevoDynamicHead {
145
+ /** Key in the page's `dataSources` whose loaded record feeds the head. */
146
+ source: string;
147
+ /** Record field holding the page title (the site name is appended automatically). */
148
+ title?: string;
149
+ /** Record field holding the description. */
150
+ description?: string;
151
+ /** Record field holding the share image (platform image object or URL). */
152
+ image?: string;
153
+ }
154
+
155
+ /**
156
+ * A form binding — the fields + submit for a collection. `LevoForm` renders it (the schema
157
+ * drives which inputs appear); submissions go to the collection. Forms only bind to
158
+ * collections, so there's no `module` variance — but it's kept for symmetry with the other
159
+ * configs and so the editor binding reads uniformly.
160
+ */
161
+ export declare interface ILevoFormConfig {
162
+ module: "collection";
163
+ /** Collection key. */
164
+ identifier: string;
165
+ }
166
+
167
+ export declare interface ILevoFormProps {
168
+ /** The form binding. Declare it in the page's `dataSources` (`mode: "form"`) so the route loader prefetches the schema SSR, then pass that entry here. */
169
+ source: ILevoFormConfig;
170
+ /** Submit-button label. */
171
+ submitLabel?: string;
172
+ /** Field keys to hide from the rendered form (matched against field key/id, recursively into nested fields). */
173
+ hiddenFields?: string[];
174
+ /** Layout: all fields at once, one-at-a-time (Typeform), or stepped by section. */
175
+ formVariant?: "default" | "single-field" | "steps" | "steps-2";
176
+ /** Success-screen copy + the post-submit action (show a message, let them submit another, or redirect). */
177
+ successConfig?: {
178
+ title?: string;
179
+ message?: string;
180
+ action?: {
181
+ type: "none" | "submit_another" | "redirect";
182
+ value?: string;
183
+ };
184
+ };
185
+ /** Brand the form. Optional — defaults to the site theme; only override the few colors you want to diverge. */
186
+ theme?: ILevoFormTheme;
187
+ className?: string;
188
+ }
189
+
190
+ export declare interface ILevoFormResult {
191
+ /** The collection schema (`sections[].fields[]`) the form renders. null until loaded / unwired. */
192
+ schema: ILemaCollection | null;
193
+ isLoading: boolean;
194
+ error: string | null;
195
+ /** Spread onto the form container — stamps the editor binding. */
196
+ bind: {
197
+ "data-levo-source": string;
198
+ };
199
+ }
200
+
201
+ /**
202
+ * Per-form color/radius overrides. Every value is any CSS color/length — pass a site token
203
+ * (`"var(--color-brand)"`) or a literal (`"#0ea5e9"`). Omitted keys fall through to the site
204
+ * theme (see `DEFAULT_FORM_TOKENS`), so a form auto-matches the brand without any theme prop.
205
+ */
206
+ declare interface ILevoFormTheme {
207
+ colors?: Partial<{
208
+ /** Buttons, focus accents. */
209
+ primary: string;
210
+ /** Text/icon on `primary`. */
211
+ primaryForeground: string;
212
+ /** Body text. */
213
+ foreground: string;
214
+ /** Field + card backgrounds. */
215
+ input: string;
216
+ /** Field borders + dividers. */
217
+ border: string;
218
+ /** Focus ring. */
219
+ ring: string;
220
+ /** Error text + invalid fields. */
221
+ destructive: string;
222
+ }>;
223
+ /** Corner radius for inputs/buttons (default: the site's `--radius-token`). */
224
+ radius?: string;
225
+ /** Vertical space between fields (default: `1.5rem`). Tighten with `"1rem"`, open up with `"2rem"`. */
226
+ gap?: string;
227
+ }
228
+
229
+ /** A single-record binding — one collection record / blog post / event by `slug` (a detail page). */
230
+ export declare interface ILevoRecordConfig {
231
+ module: "collection" | "blog" | "event";
232
+ /** Collection key / blog key / event series id. Round-tripped; the event single endpoint is flat (slug only). */
233
+ identifier: string;
234
+ /**
235
+ * Reserved for field projection. The slug endpoints return the whole record today, so
236
+ * this is round-tripped through the binding but not yet sent to the API.
237
+ */
238
+ query?: Pick<LevoQuery.FindQuery, "select" | "include">;
239
+ }
240
+
241
+ export declare interface ILevoRecordResult<T = Record<string, unknown>> {
242
+ data: T | null;
243
+ isLoading: boolean;
244
+ error: string | null;
245
+ bind: {
246
+ "data-levo-source": string;
247
+ };
248
+ }
249
+
250
+ /** Site-level Levo config — the scaffold shim fills this from Vite env. */
251
+ export declare interface ILevoSiteConfig {
252
+ /** Origin of the Levo public API / proxy the site's data calls go through. */
253
+ apiUrl?: string;
254
+ /** The site's workspace id (`W…`). Invalid/absent → client runs workspace-less. */
255
+ workspace?: string;
256
+ /** The site's id, stamped onto analytics events. */
257
+ siteId?: string;
258
+ /**
259
+ * Analytics reverse-proxy URL. Absent/null → identity + DOM trackers still run
260
+ * (popup triggers work) but nothing is sent — queued events are dropped.
261
+ */
262
+ insightsUrl?: string | null;
263
+ /** Forwarded to the client's APP_MODE; defaults to "production". */
264
+ appMode?: string;
265
+ }
266
+
267
+ /** A list binding — collection records, blog posts, or events matching `query`. */
268
+ export declare interface ILevoSourceConfig {
269
+ /** "collection" | "blog" | "event". Community has no core client module yet. */
270
+ module: "collection" | "blog" | "event";
271
+ /** Collection key / blog key / event series id. */
272
+ identifier: string;
273
+ /** where / sort / limit / page / search. `limit: -1` = all. */
274
+ query?: LevoQuery.FindQuery;
275
+ /** Reserved (blog sub-module identifiers etc.); round-tripped through the binding. */
276
+ options?: Record<string, unknown>;
277
+ }
278
+
279
+ /**
280
+ * One entry in a page's `dataSources` export — a list, record, or form binding, discriminated
281
+ * by `mode`. The route loader reads these to prefetch; the page passes each to its hook. `mode`
282
+ * is optional for lists (the default); required for records (so the loader uses the route slug)
283
+ * and forms (so the loader prefetches the collection schema instead of content).
284
+ */
285
+ export declare type ILevoSourceDef = (ILevoSourceConfig & {
286
+ mode?: "list";
287
+ }) | (ILevoRecordConfig & {
288
+ mode: "record";
289
+ }) | (ILevoFormConfig & {
290
+ mode: "form";
291
+ });
292
+
293
+ export declare interface ILevoSourceResult<T = Record<string, unknown>> {
294
+ /** null until loaded, on error, and on an unwired site. */
295
+ data: T[] | null;
296
+ meta: {
297
+ total: number;
298
+ pages: number;
299
+ } | null;
300
+ isLoading: boolean;
301
+ error: string | null;
302
+ /** Spread onto the container that renders the list — stamps the editor binding. */
303
+ bind: {
304
+ "data-levo-source": string;
305
+ };
306
+ }
307
+
308
+ export declare function Inspector(): null;
309
+
310
+ /** One page's head metadata. Every field optional — site defaults fill gaps per-field. */
311
+ export declare interface IPageMeta {
312
+ title?: string;
313
+ description?: string;
314
+ /** Absolute URL. Rendered as `<link rel="canonical">`. */
315
+ canonical?: string;
316
+ /** e.g. "index,follow" / "noindex,nofollow". */
317
+ robots?: string;
318
+ og?: {
319
+ title?: string;
320
+ description?: string;
321
+ image?: string;
322
+ /** Absolute share URL. Falls back to `canonical` when unset. */
323
+ url?: string;
324
+ /** Defaults to "website" when any og field is present. */
325
+ type?: string;
326
+ };
327
+ twitter?: {
328
+ /** Defaults to "summary_large_image" when any twitter field is present. */
329
+ card?: string;
330
+ title?: string;
331
+ description?: string;
332
+ image?: string;
333
+ };
334
+ /** JSON-LD object(s) — each becomes a `<script type="application/ld+json">`. */
335
+ ldJson?: Record<string, unknown> | Array<Record<string, unknown>>;
336
+ /**
337
+ * Raw head snippet for THIS page. v1 supports `<script>`, `<meta>` and `<link>` tags
338
+ * only (the analytics / verification / preload cases) — anything else is dropped by
339
+ * `parseRawHead`, since arbitrary markup can't be expressed as document metadata.
340
+ */
341
+ customHead?: string;
342
+ }
343
+
344
+ /**
345
+ * One platform-data binding found on the page — a `data-levo-source` container. Emitted in
346
+ * `sources-list` (reply to `request-sources`) so the editor's page-level Data manager can list
347
+ * every binding without a selection. `element` is the container's own `data-tsd-source` locator
348
+ * (a data edit targets the hook call site); `config` is the parsed binding, omitted when the
349
+ * attribute is malformed JSON.
350
+ */
351
+ export declare interface IPageSource {
352
+ raw: string;
353
+ config?: unknown;
354
+ element: IElementLocator;
355
+ tag: string;
356
+ label: string;
357
+ }
358
+
359
+ export declare interface IPatchedHistoryFn {
360
+ (this: History, ...args: Parameters<IHistoryFn>): ReturnType<IHistoryFn>;
361
+ __inspectorPatched?: boolean;
362
+ __orig?: IHistoryFn;
363
+ }
364
+
365
+ /** The full `meta/<route>.json` shape: page identity (platform-owned) + the SEO object. */
366
+ export declare interface IPlatformMetaFile {
367
+ title?: string;
368
+ description?: string;
369
+ meta?: IPlatformPageMeta;
370
+ }
371
+
372
+ /** The platform's per-page SEO object — the `meta` key of `meta/<route>.json`. */
373
+ export declare interface IPlatformPageMeta {
374
+ meta_title?: string;
375
+ meta_description?: string;
376
+ keywords?: string;
377
+ og_title?: string;
378
+ og_description?: string;
379
+ /** Plain URL string, or the platform media object (older rows) — `.location` is read. */
380
+ og_image?: string | {
381
+ location?: string;
382
+ } | null;
383
+ og_url?: string;
384
+ canonical?: string;
385
+ twitter_card?: string;
386
+ /** JSON-LD structured data — rendered as an `application/ld+json` script tag. */
387
+ ld_json?: Record<string, unknown> | Array<Record<string, unknown>>;
388
+ /** Page-scoped raw head snippet — script/meta/link tags only. */
389
+ head_code?: string;
390
+ disable_indexing?: boolean;
391
+ robots?: string;
392
+ }
393
+
394
+ /** Preview → editor (emitted by `send`; dashboard's `IInboundMessage`). */
395
+ export declare type IPreviewToEditor = {
396
+ type: "ready";
397
+ } | {
398
+ type: "inspect-state";
399
+ enabled: boolean;
400
+ } | {
401
+ type: "text-edit-state";
402
+ enabled: boolean;
403
+ } | {
404
+ type: "element-selected";
405
+ element: ISelectedElement;
406
+ } | {
407
+ type: "element-text-changed";
408
+ element: ITextChangedElement;
409
+ }
410
+ /**
411
+ * `route` is the pathname (always present). `file` is the route's repo-relative source
412
+ * file (e.g. `src/routes/pricing.tsx`, no leading slash, no `:line:col`) — reserved:
413
+ * the runtime doesn't emit it yet; the dashboard falls back to url → file mapping.
414
+ */
415
+ | {
416
+ type: "route";
417
+ route: string;
418
+ file?: string;
419
+ } | {
420
+ type: "staged-ack";
421
+ stageId: string;
422
+ } | {
423
+ type: "layers-tree";
424
+ tree: ILayersNode;
425
+ truncated: boolean;
426
+ } | {
427
+ type: "sources-list";
428
+ sources: IPageSource[];
429
+ } | {
430
+ type: "select-miss";
431
+ element: IElementLocator;
432
+ } | {
433
+ type: "highlight-miss";
434
+ element: IElementLocator;
435
+ };
436
+
437
+ /**
438
+ * The minimal QueryClient surface `prefetchLevoSources` needs. Structural on purpose — a
439
+ * branded `QueryClient` type in the public API would clash whenever the consuming site
440
+ * resolves a different `@tanstack/react-query` copy/version than the one this package was
441
+ * built against (peer dep). Any real QueryClient satisfies this.
442
+ */
443
+ export declare interface IQueryClientLike {
444
+ ensureQueryData: (options: {
445
+ queryKey: readonly unknown[];
446
+ queryFn: () => Promise<unknown>;
447
+ }) => Promise<unknown>;
448
+ }
449
+
450
+ /** The element-selected payload — see `selectedPayload`. */
451
+ export declare interface ISelectedElement {
452
+ tag: string;
453
+ classes: string;
454
+ text: string;
455
+ label: string;
456
+ path: string;
457
+ /** null when the element carries no `data-tsd-source` stamp. */
458
+ source: string | null;
459
+ index: number;
460
+ occurrences: number;
461
+ ancestors: {
462
+ tag: string;
463
+ text: string;
464
+ source?: string;
465
+ }[];
466
+ /** Whole normalized textContent — present ONLY for text-mode-editable nodes. */
467
+ fullText?: string;
468
+ /**
469
+ * The nearest `data-levo-source` binding container above the selection (inclusive) — a
470
+ * platform-data-bound region (`useLevoSource`/`useLevoRecord`). Present only when the
471
+ * selection sits inside one. `config` is the parsed binding ({mode, module, identifier,
472
+ * query,…}), omitted when the attribute is malformed JSON. `element` is the binding
473
+ * CONTAINER's own locator, so a data edit targets the hook call site — not the clicked
474
+ * child. Lets the editor's "Integrate" dialog open pre-filled without parsing JSX.
475
+ */
476
+ sourceBinding?: {
477
+ raw: string;
478
+ config?: unknown;
479
+ element: IElementLocator;
480
+ };
481
+ }
482
+
483
+ /** The slice of the project's root `site.json` the runtime reads. */
484
+ export declare interface ISiteJson {
485
+ id?: string;
486
+ workspace_id?: string;
487
+ name?: string;
488
+ description?: string;
489
+ /** The site's live URL host (with or without protocol) — feeds auto-canonicals. */
490
+ domain?: string;
491
+ settings?: {
492
+ head_code?: string;
493
+ };
494
+ levo?: {
495
+ api_url?: string;
496
+ insights_url?: string | null;
497
+ app_mode?: string;
498
+ };
499
+ }
500
+
501
+ /** Site-wide defaults + site-wide raw head, from `src/pages/_site.meta.ts`. */
502
+ export declare interface ISiteMeta extends IPageMeta {
503
+ /** "%s · Acme" — %s is the page title. Applied only when the page provides a title. */
504
+ titleTemplate?: string;
505
+ }
506
+
507
+ export declare type IStagedEntry = IStagedStyleEntry | IStagedTextEntry;
508
+
509
+ export declare interface IStagedStyleEntry {
510
+ kind: "style";
511
+ source: string;
512
+ index: number;
513
+ styles: Record<string, string>;
514
+ media?: string;
515
+ }
516
+
517
+ export declare interface IStagedTextEntry {
518
+ kind: "text";
519
+ source: string;
520
+ index: number;
521
+ value: string;
522
+ }
523
+
524
+ /** The element-text-changed payload — see `commit`. */
525
+ export declare interface ITextChangedElement {
526
+ source: string | null;
527
+ index: number;
528
+ tag: string;
529
+ value: string;
530
+ previous?: string;
531
+ occurrences: number;
532
+ }
533
+
534
+ /**
535
+ * Self-contained event registration widget for generated Studio v3 sites — ticket
536
+ * selection, coupons, attendee details, payment (Razorpay by default; Stripe Embedded
537
+ * Checkout when the booking API returns `provider: "stripe"`), and a booking confirmation.
538
+ *
539
+ * The AI drops this onto an event page and NEVER rebuilds the flow: it owns the entire
540
+ * booking + payment path against the Levo event API. The site client (`useLevoSite`)
541
+ * auto-stamps the workspace on every request, so no auth/workspace wiring is needed.
542
+ * `external` turns it into a plain link out to a third-party ticketing URL.
543
+ */
544
+ export declare const LevoEventRegister: ({ eventID, title, external, buttonText, }: {
545
+ /** Event id (or slug the single-event endpoint resolves). */
546
+ eventID: string;
547
+ /** Event name, shown in the modal header. */
548
+ title?: string;
549
+ /** External ticketing URL — when set, renders a link out instead of the modal flow. */
550
+ external?: string;
551
+ buttonText?: string;
552
+ }) => JSX.Element;
553
+
554
+ /**
555
+ * A collection-backed form for generated Studio v3 sites — renders the collection's fields
556
+ * (from its SSR-prefetched schema) and submits entries into that collection. The AI drops it
557
+ * in and never rebuilds the form engine.
558
+ *
559
+ * Colors follow the site theme (`src/styles/theme.css`) by default, so a form matches the
560
+ * brand out of the box; `theme` overrides per form. `CollectionFormRenderer` resolves its
561
+ * client via `@levo-so/react`'s `useLevo()` — the same context `LevoSiteProvider` mounts at
562
+ * the site root, so no per-form provider is needed. Declare the form in the page's
563
+ * `dataSources` as `mode: "form"` so the loader prefetches the schema (no field-flash, SSR-safe).
564
+ */
565
+ export declare const LevoForm: React.FC<ILevoFormProps>;
566
+
567
+ /**
568
+ * Mounts the Levo client + insights for a generated site. Rendered once from the
569
+ * scaffold's `__root` (via the env-reading shim); SSR-safe — construction guards its
570
+ * window/document reads, and `insights.init()` (client-side only by contract) runs in
571
+ * an effect after mount.
572
+ */
573
+ export declare const LevoSiteProvider: React.FC<{
574
+ config?: ILevoSiteConfig;
575
+ children: React.ReactNode;
576
+ }>;
577
+
578
+ /**
579
+ * Renders a page's metadata as document tags. Pages include it anywhere in their JSX —
580
+ * React 19 hoists <title>/<meta>/<link> into <head> (SSR too); scripts render in place
581
+ * (see the file header caveat). The studio wires this automatically on a page's first
582
+ * meta save:
583
+ *
584
+ * import meta from "./about.meta";
585
+ * import siteMeta from "./_site.meta";
586
+ * import { PageHead } from "../lib/pageHead";
587
+ * …
588
+ * <PageHead meta={meta} site={siteMeta} />
589
+ */
590
+ export declare function PageHead({ meta, site }: {
591
+ meta?: IPageMeta;
592
+ site?: ISiteMeta;
593
+ }): JSX.Element;
594
+
595
+ /**
596
+ * Compose one page's document metadata from its sidecar + the site defaults. Page
597
+ * values win per-FIELD (an empty page og.title still inherits the site og.title).
598
+ * The object shape doubles as a TanStack Start route `head()` result for when the
599
+ * scaffold wires routes directly.
600
+ */
601
+ export declare const pageHead: (meta?: IPageMeta, site?: ISiteMeta) => IComposedHead;
602
+
603
+ /**
604
+ * Tolerant extraction of `<script>` / `<meta>` / `<link>` tags from a raw head snippet.
605
+ * Unsupported tags are DROPPED (documented v1 limitation) — silently at runtime; the
606
+ * editor warns at save time.
607
+ */
608
+ export declare const parseRawHead: (raw: string) => IComposedHead;
609
+
610
+ /**
611
+ * Prefetch every binding a page declares into the router's QueryClient — call it (awaited)
612
+ * from the route `loader` so SSR renders fully-populated HTML. Builds its own client from
613
+ * the site config (loaders run outside React, so `useLevoSite` isn't available). Record
614
+ * bindings pull their slug from the route `params` (`$slug`). Resilient: a single failed
615
+ * source resolves to null so it doesn't blank the whole page — the hook surfaces that
616
+ * binding's error while the rest render.
617
+ *
618
+ * Returns the fetched values keyed by source key (records as the record object, lists as
619
+ * `{data, meta}`). The route loader returns this map, making it the route's `loaderData` —
620
+ * which `levoHead`'s dynamic config reads for per-record titles/descriptions/share images.
621
+ */
622
+ export declare const prefetchLevoSources: ({ queryClient, config, sources, params, }: {
623
+ queryClient: IQueryClientLike;
624
+ /** Site env config — same object the LevoSiteProvider receives. */
625
+ config: ILevoSiteConfig | undefined;
626
+ /** The page's `dataSources` export (undefined = page has none). */
627
+ sources: ILevoDataSources | undefined;
628
+ /** Route params; record bindings read `params.slug`. */
629
+ params?: Record<string, string>;
630
+ }) => Promise<Record<string, unknown>>;
631
+
632
+ /**
633
+ * The site's Levo client config from its `site.json`. The platform stamps that file at
634
+ * provision and re-syncs it on settings saves; the `?.` on `levo` is load-bearing — a
635
+ * site provisioned before the block shipped degrades to an inert client, never a crash.
636
+ */
637
+ export declare const siteConfigFromJson: (site: ISiteJson) => ILevoSiteConfig;
638
+
639
+ /**
640
+ * Load a collection's SCHEMA so `LevoForm` can render its fields. Like the other hooks the
641
+ * config is a static literal (the editor binding); it reads the warm cache the route loader
642
+ * filled via `prefetchLevoSources`, so a form declared in `dataSources` renders SSR with no
643
+ * fetch flash. `schema` is null until loaded and on an unwired site.
644
+ */
645
+ export declare const useLevoForm: (config: ILevoFormConfig) => ILevoFormResult;
646
+
647
+ /** The site's insights (analytics/track), or `null` on an unwired site. */
648
+ export declare const useLevoInsights: () => ILevoInsights | null;
649
+
650
+ /**
651
+ * Render ONE record by slug — a detail page. `slug` is a RUNTIME arg (the page's route
652
+ * param), kept OUT of the config literal so the binding stays static and editable. No slug
653
+ * (or unwired site) → inert. `data` null after load = not found: render a friendly fallback.
654
+ */
655
+ export declare const useLevoRecord: <T = Record<string, unknown>>(config: ILevoRecordConfig, slug: string | undefined) => ILevoRecordResult<T>;
656
+
657
+ /**
658
+ * The site's Levo client, or `null` when the site isn't wired to a Levo backend yet
659
+ * (no `apiUrl` in config — e.g. env not injected at provision). Consumers no-op on null.
660
+ *
661
+ * Explicit return type on purpose: inference would inline core-internal names
662
+ * (`IPageContext`) that the rolled-up d.ts doesn't export → TS4023 on declaration emit.
663
+ */
664
+ export declare const useLevoSite: () => ILevoClient | null;
665
+
666
+ /**
667
+ * Render a LIST of platform content. The config is a static literal (the editor rewrites
668
+ * it). Reads the router QueryClient: if the route loader prefetched this binding, the first
669
+ * render has data (SSR ships it); otherwise it fetches client-side. Always render a loading
670
+ * and an empty state — `data` is null before the first load and on unwired sites.
671
+ */
672
+ export declare const useLevoSource: <T = Record<string, unknown>>(config: ILevoSourceConfig) => ILevoSourceResult<T>;
673
+
674
+ export { }