@eldrajs/theme-vue 0.0.0 → 0.2.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.
- package/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/README.md +29 -1
- package/dist/index.d.ts +548 -0
- package/dist/index.js +1057 -0
- package/package.json +48 -2
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
import { InjectionKey, MaybeRefOrGetter, PropType, Ref, VNode, VNodeChild } from "vue";
|
|
2
|
+
import { ThemeMessages } from "@eldrajs/theme-core/i18n";
|
|
3
|
+
import { BlockFieldDefinition, BlockFieldsMap, BuildRichTextTreeOptions, DEFAULT_IMAGE_FRAMING, EldraClient, EntryDoc, EntryQuery, ImageFraming, PageLike, ReusableComponentProjection, RichTextFieldIdentity, RichTextMark, RichTextNode, RichTextRenderChild, RichTextRenderNode, RouteTemplateLike, ThemeDesignTokens, buildRichTextTree, imageFramingAttrs, imageFramingStyle, isBlockFieldLocalized, normalizeImageFraming, registerBlockFields } from "@eldrajs/theme-core";
|
|
4
|
+
import { LinkKind, LinkRouteContext, LinkTarget, LinkTargetInfo, LinkTargetInfo as LinkTargetInfo$1, LinkValue, ResolvedLink, ResolvedLink as ResolvedLink$1, linkTargetKeys, resolveLink, safeLinkHref } from "@eldrajs/theme-core/links";
|
|
5
|
+
import { BridgePayloads } from "@eldrajs/theme-core/bridge";
|
|
6
|
+
//#region src/context.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* One rendered editor slot marker's geometry. Derives from the bridge payload
|
|
9
|
+
* type so the wire format stays the single source of truth.
|
|
10
|
+
*/
|
|
11
|
+
type SlotGeometry = BridgePayloads['theme:slots-rendered']['slots'][number];
|
|
12
|
+
type SlotGeometryReporter = (slots: SlotGeometry[]) => void;
|
|
13
|
+
/**
|
|
14
|
+
* What `resolveLink` needs, as one reactive slice of the theme context: the
|
|
15
|
+
* site's pages and route templates, and what it knows about the objects its
|
|
16
|
+
* links point at, keyed `${_type}:${id}`. An adapter fills it where it already
|
|
17
|
+
* resolves the route — one place, one read per type — so a prerendered page
|
|
18
|
+
* carries every href in its payload.
|
|
19
|
+
*/
|
|
20
|
+
interface EldraLinkState {
|
|
21
|
+
pages: PageLike[];
|
|
22
|
+
templates: RouteTemplateLike[];
|
|
23
|
+
targets: Map<string, LinkTargetInfo$1>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Which content locale the page a visitor is looking at is, and what the others are — the slice an
|
|
27
|
+
* adapter fills from the site's own routing so a **block** can read it without reaching for the
|
|
28
|
+
* router or the runtime config.
|
|
29
|
+
*
|
|
30
|
+
* It lives on the theme context rather than in a framework composable for the same reason the link
|
|
31
|
+
* state does: a block must render in a Storybook story and a unit test with no Nuxt around it, so
|
|
32
|
+
* everything it needs arrives through one `inject`. `useEldraLocale()` is the accessor.
|
|
33
|
+
*
|
|
34
|
+
* `path` is the one every link goes through and it is **idempotent** — see the adapter's own
|
|
35
|
+
* implementation (`@eldrajs/theme-nuxt`'s `localeHref`): a destination can pass through more than
|
|
36
|
+
* one prefixer, and a second prefix would produce a path nothing on the site answers.
|
|
37
|
+
*/
|
|
38
|
+
interface EldraLocaleState {
|
|
39
|
+
/**
|
|
40
|
+
* The active content locale, or `null` on a site that configures none. In a Studio preview this
|
|
41
|
+
* is the locale the editor is driving, which wins over the one the path names.
|
|
42
|
+
*/
|
|
43
|
+
active: string | null;
|
|
44
|
+
/** The locale served at `/`, unprefixed. `null` on a site that configures none. */
|
|
45
|
+
defaultLocale: string | null;
|
|
46
|
+
/** Every locale the site serves, `defaultLocale` first. Empty on a site that configures none. */
|
|
47
|
+
supported: readonly string[];
|
|
48
|
+
/**
|
|
49
|
+
* One locale's name **in that locale** — "íslenska (Ísland)", "American English" — for a language
|
|
50
|
+
* switcher's option label, with the tag itself as the fallback.
|
|
51
|
+
*
|
|
52
|
+
* It is on the state rather than left to the caller because the answer is ICU data and a renderer
|
|
53
|
+
* and a browser do not always have the same of it: Node answers "íslenska (Ísland)" for `is-IS`
|
|
54
|
+
* where a reduced-ICU browser build answers "Icelandic (Iceland)". An adapter therefore resolves
|
|
55
|
+
* these **once, on the server**, and carries them to the browser, so a switcher that renders one
|
|
56
|
+
* does not hydrate into a mismatch and repaint.
|
|
57
|
+
*/
|
|
58
|
+
name: (locale: string) => string;
|
|
59
|
+
/**
|
|
60
|
+
* One same-site destination (`/products/x`, `/search?q=mug`) under the active locale. Anything
|
|
61
|
+
* that is not a path on this site — an absolute URL, `mailto:`, `#main` — and anything already
|
|
62
|
+
* spelled in one of the site's locales comes back untouched.
|
|
63
|
+
*/
|
|
64
|
+
path: (href: string) => string;
|
|
65
|
+
/** The page the visitor is on, spelled in `locale`. The default locale's spelling has no prefix. */
|
|
66
|
+
switchPath: (locale: string) => string;
|
|
67
|
+
/** Go to `switchPath(locale)` — what a language switcher calls when its value changes. */
|
|
68
|
+
select: (locale: string) => void;
|
|
69
|
+
}
|
|
70
|
+
interface EldraContext {
|
|
71
|
+
client: EldraClient;
|
|
72
|
+
links: EldraLinkState;
|
|
73
|
+
/**
|
|
74
|
+
* Optional so a context assembled before locales existed still type-checks and still renders:
|
|
75
|
+
* every reader treats its absence as "one unprefixed site, no switcher", which is what such a
|
|
76
|
+
* site is.
|
|
77
|
+
*/
|
|
78
|
+
locales?: EldraLocaleState;
|
|
79
|
+
/**
|
|
80
|
+
* The theme's resolved message catalogue — the manifest's own `messages` block (or the fallback
|
|
81
|
+
* catalogue, `{ defaultLocale: 'en-US', locales: {} }`, for a theme that ships no `i18n/`
|
|
82
|
+
* directory), merged with the platform's own overrides and resolved over the organisation's
|
|
83
|
+
* locales at build time (`@eldrajs/theme-nuxt`'s module, `@eldrajs/theme-core/i18n`'s
|
|
84
|
+
* `resolveMessageCatalogue`). Flat dotted keys, one record per locale tag — the starter's
|
|
85
|
+
* `vue-i18n` plugin is the one consumer that unflattens it.
|
|
86
|
+
*
|
|
87
|
+
* Reactive so a live `editor:theme-messages` push from Studio's preview (`useEldraPreview`)
|
|
88
|
+
* updates every block reading a message through it with no re-render plumbing of its own.
|
|
89
|
+
*/
|
|
90
|
+
messages: ThemeMessages;
|
|
91
|
+
preview: {
|
|
92
|
+
active: boolean;
|
|
93
|
+
mode: 'preview' | 'edit';
|
|
94
|
+
locale: string | null;
|
|
95
|
+
sourceDrafts: Record<string, Record<string, unknown>>;
|
|
96
|
+
drafts: Record<string, Record<string, unknown>>;
|
|
97
|
+
draftSchemaApiIds: Record<string, string>;
|
|
98
|
+
refreshRevision: number;
|
|
99
|
+
revision: number;
|
|
100
|
+
designTokensRevision: number;
|
|
101
|
+
/**
|
|
102
|
+
* The revision of the last `editor:theme-messages` push applied to `context.messages`.
|
|
103
|
+
* Mirrors `designTokensRevision`'s role: a push whose `revision` is not strictly greater than
|
|
104
|
+
* this is stale (an out-of-order delivery, a reconnect replay) and is ignored rather than
|
|
105
|
+
* rolling a live edit backwards.
|
|
106
|
+
*/
|
|
107
|
+
messagesRevision: number;
|
|
108
|
+
/**
|
|
109
|
+
* Bumped every time `editor:init` carries a preview token that differs
|
|
110
|
+
* from the one before it — so a consumer can tell "the editor handed me a
|
|
111
|
+
* *new* token" apart from "the editor sent another content update"
|
|
112
|
+
* (`refreshRevision` bumps for both). `useEldraPage` reads it to decide
|
|
113
|
+
* whether a 401 is the first failure of a token, which the editor may
|
|
114
|
+
* still recover from, or the failure of a token it has already replaced,
|
|
115
|
+
* which is the operator's to see.
|
|
116
|
+
*/
|
|
117
|
+
tokenRevision: number;
|
|
118
|
+
/**
|
|
119
|
+
* Negotiated from the editor's editor:hello capabilities (the
|
|
120
|
+
* `block-slots` capability), re-negotiated on every hello. Gates the
|
|
121
|
+
* editor-only slot markers, which `EldraLayout` renders — the one
|
|
122
|
+
* negotiated capability a Vue component has to read.
|
|
123
|
+
*
|
|
124
|
+
* The `image-framing` and `rich-text-inline` gates are deliberately not
|
|
125
|
+
* mirrored here: theme-core's preview message router negotiates them and
|
|
126
|
+
* forwards them straight to the overlay runtime
|
|
127
|
+
* (`setFramingEnabled`/`setRichTextEnabled`), so there is one owner per
|
|
128
|
+
* capability rather than one per framework binding.
|
|
129
|
+
*/
|
|
130
|
+
editorSupportsSlots: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* §18 v3: bumped once for every change theme-core reports through
|
|
133
|
+
* `onRichTextRenderState`, so a rich-text field re-evaluates whether its
|
|
134
|
+
* render is deferred. It is only a change signal — the answer itself is
|
|
135
|
+
* `isRichTextRenderDeferred`, which is core's, not a mirror of it.
|
|
136
|
+
*/
|
|
137
|
+
richTextRenderRevision: number;
|
|
138
|
+
/**
|
|
139
|
+
* §18 v3: theme-core's predicate, installed by startEldraPreview. While it
|
|
140
|
+
* answers true for a field, the browser owns that field's DOM (a native
|
|
141
|
+
* text op is in flight) and the renderer must not replace it. Undefined in
|
|
142
|
+
* static output and outside a preview, where nothing is ever deferred.
|
|
143
|
+
*/
|
|
144
|
+
isRichTextRenderDeferred?: (identity: RichTextFieldIdentity) => boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Installed by startEldraPreview; posts bounded theme:slots-rendered
|
|
147
|
+
* geometry over the bridge. Undefined in static output.
|
|
148
|
+
*/
|
|
149
|
+
slotGeometryReporter?: SlotGeometryReporter;
|
|
150
|
+
};
|
|
151
|
+
designTokens: ThemeDesignTokens;
|
|
152
|
+
}
|
|
153
|
+
export declare const ELDRA_KEY: InjectionKey<EldraContext>;
|
|
154
|
+
/**
|
|
155
|
+
* The preview slice of a fresh theme context, reactive and complete. Every
|
|
156
|
+
* adapter that assembles an `EldraContext` by hand — theme-nuxt's runtime
|
|
157
|
+
* plugin, or an equivalent entry for another framework — must build it from
|
|
158
|
+
* here: the hand-written literal had already drifted several fields behind
|
|
159
|
+
* this interface, and a missing field is a runtime error rather than a type
|
|
160
|
+
* error once the object is assembled elsewhere.
|
|
161
|
+
*/
|
|
162
|
+
export declare function createEldraPreviewState(): EldraContext['preview'];
|
|
163
|
+
/**
|
|
164
|
+
* The link slice of a fresh theme context, reactive and empty. Built here for
|
|
165
|
+
* the same reason `createEldraPreviewState` is: a missing field is a runtime
|
|
166
|
+
* error rather than a type error once the object is assembled elsewhere.
|
|
167
|
+
*/
|
|
168
|
+
/**
|
|
169
|
+
* The locale slice of a context with no router behind it — a Storybook story, a unit-test mount, a
|
|
170
|
+
* site whose organisation configures no locales. Every answer is the one-unprefixed-site answer,
|
|
171
|
+
* so a block written against `useEldraLocale()` renders identically in all three.
|
|
172
|
+
*
|
|
173
|
+
* An adapter that *has* routing builds its own (see `@eldrajs/theme-nuxt`'s runtime plugin): the
|
|
174
|
+
* active locale and the paths are derived from the route, which this layer knows nothing about.
|
|
175
|
+
*/
|
|
176
|
+
export declare function createEldraLocaleState(): EldraLocaleState;
|
|
177
|
+
export declare function createEldraLinkState(): EldraLinkState;
|
|
178
|
+
export declare function provideEldra(opts: {
|
|
179
|
+
client: EldraClient;
|
|
180
|
+
designTokens?: unknown;
|
|
181
|
+
/** Defaults to the fallback catalogue (`{ defaultLocale: 'en-US', locales: {} }`) — a Storybook mount
|
|
182
|
+
* or a unit test that does not pass one renders exactly as a theme with no `i18n/` directory
|
|
183
|
+
* does. An adapter with a real build (`@eldrajs/theme-nuxt`'s runtime plugin) passes the
|
|
184
|
+
* resolved `virtual:eldra/messages` content instead. */
|
|
185
|
+
messages?: ThemeMessages;
|
|
186
|
+
}): EldraContext;
|
|
187
|
+
export declare function useEldra(): EldraContext;
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/useEldraLink.d.ts
|
|
190
|
+
/**
|
|
191
|
+
* Resolve a `link` field's value against the site's own routes.
|
|
192
|
+
*
|
|
193
|
+
* Call it once per component and keep the returned function — it closes over
|
|
194
|
+
* the reactive link state, so every call reads whatever the adapter has filled
|
|
195
|
+
* in by then, and a row re-resolves when a target arrives or a preview draft
|
|
196
|
+
* changes the value.
|
|
197
|
+
*
|
|
198
|
+
* Outside a themed app (a block rendered in isolation, a story with no
|
|
199
|
+
* provider) it resolves nothing: every value comes back `null`, which a block
|
|
200
|
+
* already has to handle for a target that no longer exists.
|
|
201
|
+
*
|
|
202
|
+
* Every href it hands back is spelled in the **active content locale**
|
|
203
|
+
* (`useEldraLocale()`), so a navigation resolved on `/is-IS/about` points at
|
|
204
|
+
* `/is-IS/products/x` and a visitor cannot be dropped back into the default
|
|
205
|
+
* language by following a link. The rewrite is idempotent, which is what lets a
|
|
206
|
+
* theme's router-link component prefix as well without the two compounding.
|
|
207
|
+
*/
|
|
208
|
+
export declare function useEldraLink(): (value: unknown) => ResolvedLink$1 | null;
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/useEldraLocale.d.ts
|
|
211
|
+
/**
|
|
212
|
+
* The locale this page is in, the locales the site serves, and how to spell a destination in one
|
|
213
|
+
* of them.
|
|
214
|
+
*
|
|
215
|
+
* Call it once per component and keep what it returns — the state is reactive, so a template that
|
|
216
|
+
* reads `active` or calls `path()` re-renders when the visitor changes language.
|
|
217
|
+
*
|
|
218
|
+
* Outside a themed app, and on a site whose organisation configures no locales, it answers the
|
|
219
|
+
* one-unprefixed-site answer: `active` and `defaultLocale` `null`, `supported` empty, `path()` the
|
|
220
|
+
* identity. A block can therefore read it unconditionally and render the same markup in a
|
|
221
|
+
* Storybook story as on a single-locale site — which is also why a language switcher's own rule is
|
|
222
|
+
* `supported.length > 1`, never "is there a locale at all".
|
|
223
|
+
*/
|
|
224
|
+
export declare function useEldraLocale(): EldraLocaleState;
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/EldraBlockZone.d.ts
|
|
227
|
+
/**
|
|
228
|
+
* Resolve a block entry's **bare** block apiId across both supported gateway
|
|
229
|
+
* response shapes. Core spells a theme's block schema `<themeId>:<apiId>` on
|
|
230
|
+
* the wire; the theme's own id is stripped here (and only its own), so
|
|
231
|
+
* `blockImports`, `data-eldra-schema`, the slot catalog and the overlay all
|
|
232
|
+
* keep speaking the bare id `block.json` declares.
|
|
233
|
+
*/
|
|
234
|
+
export declare function getBlockSchemaApiId(entry: EntryDoc): string | null;
|
|
235
|
+
export declare const EldraBlockZone: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
236
|
+
blocks: {
|
|
237
|
+
type: PropType<EntryDoc[]>;
|
|
238
|
+
required: true;
|
|
239
|
+
};
|
|
240
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
241
|
+
[key: string]: any;
|
|
242
|
+
}>[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
243
|
+
blocks: {
|
|
244
|
+
type: PropType<EntryDoc[]>;
|
|
245
|
+
required: true;
|
|
246
|
+
};
|
|
247
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/EldraLayout.d.ts
|
|
250
|
+
/**
|
|
251
|
+
* Render a validated responsive layout with the same model and stylesheet used
|
|
252
|
+
* by static generation. Invalid documents and unresolved entry references fail
|
|
253
|
+
* closed before any customer block component is mounted.
|
|
254
|
+
*/
|
|
255
|
+
export declare const EldraLayout: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
256
|
+
layout: {
|
|
257
|
+
type: PropType<unknown>;
|
|
258
|
+
required: true;
|
|
259
|
+
};
|
|
260
|
+
blocks: {
|
|
261
|
+
type: PropType<EntryDoc[]>;
|
|
262
|
+
required: true;
|
|
263
|
+
};
|
|
264
|
+
nonce: {
|
|
265
|
+
type: StringConstructor;
|
|
266
|
+
required: false;
|
|
267
|
+
default: undefined;
|
|
268
|
+
};
|
|
269
|
+
designTokens: {
|
|
270
|
+
type: PropType<unknown>;
|
|
271
|
+
required: false;
|
|
272
|
+
default: undefined;
|
|
273
|
+
};
|
|
274
|
+
reusableComponentProjection: {
|
|
275
|
+
type: PropType<ReusableComponentProjection | undefined>;
|
|
276
|
+
required: false;
|
|
277
|
+
default: undefined;
|
|
278
|
+
};
|
|
279
|
+
templateEntry: {
|
|
280
|
+
type: PropType<EntryDoc | undefined>;
|
|
281
|
+
required: false;
|
|
282
|
+
default: undefined;
|
|
283
|
+
};
|
|
284
|
+
}>, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
285
|
+
[key: string]: any;
|
|
286
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
287
|
+
layout: {
|
|
288
|
+
type: PropType<unknown>;
|
|
289
|
+
required: true;
|
|
290
|
+
};
|
|
291
|
+
blocks: {
|
|
292
|
+
type: PropType<EntryDoc[]>;
|
|
293
|
+
required: true;
|
|
294
|
+
};
|
|
295
|
+
nonce: {
|
|
296
|
+
type: StringConstructor;
|
|
297
|
+
required: false;
|
|
298
|
+
default: undefined;
|
|
299
|
+
};
|
|
300
|
+
designTokens: {
|
|
301
|
+
type: PropType<unknown>;
|
|
302
|
+
required: false;
|
|
303
|
+
default: undefined;
|
|
304
|
+
};
|
|
305
|
+
reusableComponentProjection: {
|
|
306
|
+
type: PropType<ReusableComponentProjection | undefined>;
|
|
307
|
+
required: false;
|
|
308
|
+
default: undefined;
|
|
309
|
+
};
|
|
310
|
+
templateEntry: {
|
|
311
|
+
type: PropType<EntryDoc | undefined>;
|
|
312
|
+
required: false;
|
|
313
|
+
default: undefined;
|
|
314
|
+
};
|
|
315
|
+
}>> & Readonly<{}>, {
|
|
316
|
+
nonce: string;
|
|
317
|
+
designTokens: undefined;
|
|
318
|
+
reusableComponentProjection: ReusableComponentProjection | undefined;
|
|
319
|
+
templateEntry: EntryDoc | undefined;
|
|
320
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
321
|
+
//#endregion
|
|
322
|
+
//#region src/EldraRichText.d.ts
|
|
323
|
+
/**
|
|
324
|
+
* Renders a §18 rich-text field's TipTap JSON document. Read render only —
|
|
325
|
+
* the theme SDK is a bridge, not an editor: it hosts no editing UI and
|
|
326
|
+
* depends on neither TipTap nor a component library.
|
|
327
|
+
*
|
|
328
|
+
* §18 v3: the operator edits this render natively — theme-core's overlay
|
|
329
|
+
* makes the root `contenteditable` in edit mode and reports selection, text
|
|
330
|
+
* ops and commands in ProseMirror document positions; Studio owns the one
|
|
331
|
+
* headless editor and the docked toolbar and echoes the document back
|
|
332
|
+
* through `editor:content-update`. While Studio is editing, the root is
|
|
333
|
+
* marked `data-eldra-rich-text-editing`; nothing is hidden or overlaid.
|
|
334
|
+
*
|
|
335
|
+
* The root carries the marking attributes the overlay's
|
|
336
|
+
* `decorateStegaTextNodes`/`applyEditable`/`reconcileExternalDrafts`
|
|
337
|
+
* recognize (`[data-eldra-rich-text]`) so the overlay skips per-leaf stega
|
|
338
|
+
* decoration here and hands click-to-select to `theme:field-clicked`
|
|
339
|
+
* instead (see theme-core's `overlay.ts`).
|
|
340
|
+
*
|
|
341
|
+
* Per-block toolbar: the `metadata.toolbar` data path is unchanged
|
|
342
|
+
* (`block.json` → manifest → Core field metadata → Studio), but the theme no
|
|
343
|
+
* longer reads it — Studio's docked toolbar does. The vite plugin's scanner
|
|
344
|
+
* still validates the control ids at build time.
|
|
345
|
+
*
|
|
346
|
+
* Locale: an omitted `locale` prop defaults to the preview's active content
|
|
347
|
+
* locale when the manifest marks the field `localized`, and to `null`
|
|
348
|
+
* otherwise. That resolved locale is what `data-eldra-locale` carries, so
|
|
349
|
+
* Studio edits the locale the render actually used.
|
|
350
|
+
*
|
|
351
|
+
* Heading outline: `minHeadingLevel` floors every heading tag at render time,
|
|
352
|
+
* so one stored document fits under two different page outlines without being
|
|
353
|
+
* rewritten (see that prop's own comment).
|
|
354
|
+
*/
|
|
355
|
+
export declare const EldraRichText: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
356
|
+
entryId: {
|
|
357
|
+
type: StringConstructor;
|
|
358
|
+
required: true;
|
|
359
|
+
};
|
|
360
|
+
field: {
|
|
361
|
+
type: StringConstructor;
|
|
362
|
+
required: true;
|
|
363
|
+
};
|
|
364
|
+
locale: {
|
|
365
|
+
type: PropType<string | null>;
|
|
366
|
+
required: false;
|
|
367
|
+
default: null;
|
|
368
|
+
};
|
|
369
|
+
doc: {
|
|
370
|
+
type: PropType<unknown>;
|
|
371
|
+
required: true;
|
|
372
|
+
};
|
|
373
|
+
/** The owning block's schema id — a block component passes `getBlockSchemaApiId(entry)`.
|
|
374
|
+
* Used to resolve the field's `localized` flag from the block manifest. */
|
|
375
|
+
apiId: {
|
|
376
|
+
type: PropType<string | null | undefined>;
|
|
377
|
+
required: false;
|
|
378
|
+
default: undefined;
|
|
379
|
+
};
|
|
380
|
+
/**
|
|
381
|
+
* A floor for every heading in the document: a `heading` node renders as
|
|
382
|
+
* `h{max(minHeadingLevel, level)}`, still capped at 6. Defaults to 1 — the
|
|
383
|
+
* generic clamp, i.e. whatever level the document carries.
|
|
384
|
+
*
|
|
385
|
+
* A page owns its heading outline; a rich-text field does not. The same body
|
|
386
|
+
* document is legitimately an h2-and-down section in one block and an
|
|
387
|
+
* h3-and-down one in another (the starter's `article` body starts at h2, its
|
|
388
|
+
* `rich-text` block at h3), and nothing in the document or in `block.json`
|
|
389
|
+
* can say so — `metadata.toolbar`'s `heading` control id is one
|
|
390
|
+
* level-agnostic entry, so an editor can insert any level anywhere. Without
|
|
391
|
+
* this prop the only place to enforce it was a per-block transform over the
|
|
392
|
+
* TipTap JSON before handing it in (the starter shipped one); doing it here
|
|
393
|
+
* instead means the **document is never rewritten** — no copy, no
|
|
394
|
+
* reactive-state surgery, and an editor's own level survives a round trip
|
|
395
|
+
* through Studio untouched, because only the rendered tag moves.
|
|
396
|
+
*
|
|
397
|
+
* A floor, never an offset: an author who already wrote h3 under
|
|
398
|
+
* `minHeadingLevel: 3` keeps h3, and h4 stays h4 — only levels above the
|
|
399
|
+
* floor move. Every guard is in `@eldrajs/theme-core`'s own
|
|
400
|
+
* `clampHeadingLevel`, so an out-of-range or non-integer value can never
|
|
401
|
+
* produce an `<h0>`/`<h7>`.
|
|
402
|
+
*
|
|
403
|
+
* Rendering-only, deliberately: the value takes no part in position
|
|
404
|
+
* stamping (`data-eldra-pos` is the document's own numbering, which a
|
|
405
|
+
* rendered tag name cannot change), so native editing, selection reporting
|
|
406
|
+
* and `restampRichTextPositions` all behave exactly as they do without it.
|
|
407
|
+
*/
|
|
408
|
+
minHeadingLevel: {
|
|
409
|
+
type: NumberConstructor;
|
|
410
|
+
required: false;
|
|
411
|
+
default: number;
|
|
412
|
+
};
|
|
413
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
414
|
+
[key: string]: any;
|
|
415
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
416
|
+
entryId: {
|
|
417
|
+
type: StringConstructor;
|
|
418
|
+
required: true;
|
|
419
|
+
};
|
|
420
|
+
field: {
|
|
421
|
+
type: StringConstructor;
|
|
422
|
+
required: true;
|
|
423
|
+
};
|
|
424
|
+
locale: {
|
|
425
|
+
type: PropType<string | null>;
|
|
426
|
+
required: false;
|
|
427
|
+
default: null;
|
|
428
|
+
};
|
|
429
|
+
doc: {
|
|
430
|
+
type: PropType<unknown>;
|
|
431
|
+
required: true;
|
|
432
|
+
};
|
|
433
|
+
/** The owning block's schema id — a block component passes `getBlockSchemaApiId(entry)`.
|
|
434
|
+
* Used to resolve the field's `localized` flag from the block manifest. */
|
|
435
|
+
apiId: {
|
|
436
|
+
type: PropType<string | null | undefined>;
|
|
437
|
+
required: false;
|
|
438
|
+
default: undefined;
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* A floor for every heading in the document: a `heading` node renders as
|
|
442
|
+
* `h{max(minHeadingLevel, level)}`, still capped at 6. Defaults to 1 — the
|
|
443
|
+
* generic clamp, i.e. whatever level the document carries.
|
|
444
|
+
*
|
|
445
|
+
* A page owns its heading outline; a rich-text field does not. The same body
|
|
446
|
+
* document is legitimately an h2-and-down section in one block and an
|
|
447
|
+
* h3-and-down one in another (the starter's `article` body starts at h2, its
|
|
448
|
+
* `rich-text` block at h3), and nothing in the document or in `block.json`
|
|
449
|
+
* can say so — `metadata.toolbar`'s `heading` control id is one
|
|
450
|
+
* level-agnostic entry, so an editor can insert any level anywhere. Without
|
|
451
|
+
* this prop the only place to enforce it was a per-block transform over the
|
|
452
|
+
* TipTap JSON before handing it in (the starter shipped one); doing it here
|
|
453
|
+
* instead means the **document is never rewritten** — no copy, no
|
|
454
|
+
* reactive-state surgery, and an editor's own level survives a round trip
|
|
455
|
+
* through Studio untouched, because only the rendered tag moves.
|
|
456
|
+
*
|
|
457
|
+
* A floor, never an offset: an author who already wrote h3 under
|
|
458
|
+
* `minHeadingLevel: 3` keeps h3, and h4 stays h4 — only levels above the
|
|
459
|
+
* floor move. Every guard is in `@eldrajs/theme-core`'s own
|
|
460
|
+
* `clampHeadingLevel`, so an out-of-range or non-integer value can never
|
|
461
|
+
* produce an `<h0>`/`<h7>`.
|
|
462
|
+
*
|
|
463
|
+
* Rendering-only, deliberately: the value takes no part in position
|
|
464
|
+
* stamping (`data-eldra-pos` is the document's own numbering, which a
|
|
465
|
+
* rendered tag name cannot change), so native editing, selection reporting
|
|
466
|
+
* and `restampRichTextPositions` all behave exactly as they do without it.
|
|
467
|
+
*/
|
|
468
|
+
minHeadingLevel: {
|
|
469
|
+
type: NumberConstructor;
|
|
470
|
+
required: false;
|
|
471
|
+
default: number;
|
|
472
|
+
};
|
|
473
|
+
}>> & Readonly<{}>, {
|
|
474
|
+
locale: string | null;
|
|
475
|
+
apiId: string | null | undefined;
|
|
476
|
+
minHeadingLevel: number;
|
|
477
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
478
|
+
//#endregion
|
|
479
|
+
//#region src/richTextRender.d.ts
|
|
480
|
+
/**
|
|
481
|
+
* Vue binding for theme-core's framework-neutral rich-text render tree. Every
|
|
482
|
+
* node/mark rule, the `safeHref` gating and the attribute whitelist live in
|
|
483
|
+
* `buildRichTextTree`; this file only maps the resulting tree onto `h()` and
|
|
484
|
+
* supplies the vnode keys Vue wants (the tree itself carries none — keys are
|
|
485
|
+
* a framework concern).
|
|
486
|
+
*/
|
|
487
|
+
type RenderRichTextOptions = BuildRichTextTreeOptions;
|
|
488
|
+
/**
|
|
489
|
+
* Render a TipTap JSON document's content as Vue VNodes. Non-doc input renders
|
|
490
|
+
* as an empty root.
|
|
491
|
+
*
|
|
492
|
+
* `generation` changes the key prefix, which makes Vue discard the subtree and
|
|
493
|
+
* build it again instead of patching. §18 v3's deferred rendering needs that
|
|
494
|
+
* exactly once per deferral: while a field is deferred the browser edits the
|
|
495
|
+
* DOM behind Vue's back, so the vnode tree Vue is holding no longer describes
|
|
496
|
+
* what is on screen, and an ordinary patch can skip a change it believes is
|
|
497
|
+
* already applied. Generation 0 keeps the original keys, so nothing about the
|
|
498
|
+
* ordinary render path changes.
|
|
499
|
+
*/
|
|
500
|
+
export declare function renderRichTextDoc(doc: unknown, options: RenderRichTextOptions, generation?: number): VNodeChild[];
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/useEldraEntry.d.ts
|
|
503
|
+
export declare function useEldraEntry(opts: {
|
|
504
|
+
schemaApiId: string;
|
|
505
|
+
entryId?: MaybeRefOrGetter<string | undefined>;
|
|
506
|
+
uniqueField?: {
|
|
507
|
+
fieldId: string;
|
|
508
|
+
value: MaybeRefOrGetter<string>;
|
|
509
|
+
};
|
|
510
|
+
query?: EntryQuery;
|
|
511
|
+
}): {
|
|
512
|
+
entry: Ref<EntryDoc | null>;
|
|
513
|
+
pending: Ref<boolean>;
|
|
514
|
+
error: Ref<string | null>;
|
|
515
|
+
refresh: () => Promise<void>;
|
|
516
|
+
};
|
|
517
|
+
//#endregion
|
|
518
|
+
//#region src/useEldraBlockField.d.ts
|
|
519
|
+
/**
|
|
520
|
+
* Vue-facing name for theme-core's block-field lookup. The registry and the
|
|
521
|
+
* `localized` resolution live in `@eldrajs/theme-core` so every framework
|
|
522
|
+
* binding shares one implementation; this wrapper exists only so themes keep
|
|
523
|
+
* calling a composable-shaped API.
|
|
524
|
+
*
|
|
525
|
+
* There is no `toolbar` here any more: §18 v3 keeps the rich-text toolbar in
|
|
526
|
+
* Studio, which reads `metadata.toolbar` from Core's field definitions. The
|
|
527
|
+
* vite plugin still validates the control ids at build time.
|
|
528
|
+
*/
|
|
529
|
+
export declare function useEldraBlockField(apiId: string | undefined, fieldId: string): {
|
|
530
|
+
localized: boolean;
|
|
531
|
+
};
|
|
532
|
+
//#endregion
|
|
533
|
+
//#region src/useEldraPreview.d.ts
|
|
534
|
+
export declare function startEldraPreview(context: EldraContext, opts: {
|
|
535
|
+
allowedOrigins: string[];
|
|
536
|
+
onNavigate?: (path: string) => void;
|
|
537
|
+
}): {
|
|
538
|
+
active: Readonly<Ref<boolean>>;
|
|
539
|
+
destroy: () => void;
|
|
540
|
+
};
|
|
541
|
+
export declare function useEldraPreview(opts: {
|
|
542
|
+
allowedOrigins: string[];
|
|
543
|
+
onNavigate?: (path: string) => void;
|
|
544
|
+
}): {
|
|
545
|
+
active: Readonly<Ref<boolean>>;
|
|
546
|
+
};
|
|
547
|
+
//#endregion
|
|
548
|
+
export { type BlockFieldDefinition, type BlockFieldsMap, DEFAULT_IMAGE_FRAMING, type EldraContext, type EldraLinkState, type EldraLocaleState, type ImageFraming, type LinkKind, type LinkRouteContext, type LinkTarget, type LinkTargetInfo, type LinkValue, type RenderRichTextOptions, type ResolvedLink, type RichTextMark, type RichTextNode, type RichTextRenderChild, type RichTextRenderNode, type SlotGeometry, type SlotGeometryReporter, buildRichTextTree, imageFramingAttrs, imageFramingStyle, isBlockFieldLocalized, linkTargetKeys, normalizeImageFraming, registerBlockFields, resolveLink, safeLinkHref };
|