@paged-media/plugin-api 0.2.6-canary.0 → 0.2.8-canary.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/dist/assets.d.ts +49 -0
- package/dist/contributions.d.ts +1 -1
- package/dist/editor.d.ts +152 -2
- package/dist/host.d.ts +464 -14
- package/dist/index.d.ts +5 -2
- package/dist/manifest.d.ts +137 -4
- package/dist/mutations.d.ts +1 -1
- package/dist/panel-schema.d.ts +92 -0
- package/dist/widgets.d.ts +48 -0
- package/dist/wire.d.ts +370 -27
- package/package.json +1 -1
- package/src/manifest.schema.json +103 -1
package/dist/host.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { CollectionName, DocumentMeta, ElementGeometryItem, ElementId, HitFilter, HitResult, Mutation, PageId, PathAnchorsResult, SceneTreeNode, SelectionMode } from "./wire";
|
|
2
|
-
import type { CommandContribution, KeybindingContribution, OverlayContribution, PagedEditor, PanelContribution, ToolContribution, ToolPreviewShape } from "./editor";
|
|
2
|
+
import type { CommandContribution, ExporterContribution, ImporterContribution, KeybindingContribution, OverlayContribution, PagedEditor, PanelContribution, ToolContribution, ToolPreviewShape } from "./editor";
|
|
3
|
+
import type { SceneLayer } from "./wire";
|
|
4
|
+
import type { AssetSurface } from "./assets";
|
|
3
5
|
import type { PluginManifest } from "./manifest";
|
|
6
|
+
import type { SchemaPanelContribution } from "./panel-schema";
|
|
7
|
+
import type { WidgetSurface } from "./widgets";
|
|
4
8
|
/** Everything a bundle registers is disposable; the host ALSO tracks
|
|
5
9
|
* it, so deactivation teardown is structural, not conventional. */
|
|
6
10
|
export interface Disposable {
|
|
@@ -14,20 +18,162 @@ export interface PluginLogger {
|
|
|
14
18
|
warn(message: string, ...args: unknown[]): void;
|
|
15
19
|
error(message: string, ...args: unknown[]): void;
|
|
16
20
|
}
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
+
/**
|
|
22
|
+
* What a matcher sees about a candidate element — a plain snapshot, so
|
|
23
|
+
* the predicate is clonable + isolate-portable (DESIGN.md §6). The host
|
|
24
|
+
* resolves it once per double-click (or programmatic test) from the
|
|
25
|
+
* engine: the element's kind, its containing-group ancestry, and —
|
|
26
|
+
* crucially — this plugin's OWN metadata envelope on the element (the
|
|
27
|
+
* `x-paged:<id>` carrier, W-02). A bundle matches on the namespace it
|
|
28
|
+
* already owns; it never sees a foreign plugin's metadata.
|
|
29
|
+
*/
|
|
30
|
+
export interface EditContextCandidate {
|
|
31
|
+
/** The hit leaf element. */
|
|
32
|
+
id: ElementId;
|
|
33
|
+
/** The element's engine kind (`"polygon"`, `"rectangle"`, …) when the
|
|
34
|
+
* host knows it; `undefined` when the hit carried none. */
|
|
35
|
+
kind?: string;
|
|
36
|
+
/** Containing-group ancestry, outer-most first (the hit's
|
|
37
|
+
* `groupChain`). Empty when the element is not nested. */
|
|
38
|
+
groupChain: readonly string[];
|
|
39
|
+
/** THIS plugin's metadata envelope on the element, pre-resolved by the
|
|
40
|
+
* host (the `x-paged:<manifest id>` carrier — never a foreign key).
|
|
41
|
+
* `null` when the element carries none. The objectType matcher reads
|
|
42
|
+
* this to claim a webFrame ("has my source metadata"). */
|
|
43
|
+
metadata: PluginMetadataEnvelope | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* An edit-context CLAIM (paged.draw B-02 / paged.web §8). Entering one
|
|
47
|
+
* (double-click on a matching element, or programmatically) pushes a
|
|
48
|
+
* context onto the shell's stack with: a restricted active tool-set, an
|
|
49
|
+
* emphasized panel-set, a breadcrumb, a narrowed write-scope (the
|
|
50
|
+
* context element's subtree), and Esc-pops-one-level. The plugin owns
|
|
51
|
+
* the matcher + the lifecycle hooks; the shell owns the stack, the
|
|
52
|
+
* chrome, and the scope enforcement.
|
|
53
|
+
*/
|
|
54
|
+
export interface EditContextContribution {
|
|
55
|
+
/** The context TYPE — must match a `contributes.editContexts[].type`
|
|
56
|
+
* the manifest declares (the capability gate). Not namespace-prefixed
|
|
57
|
+
* (a content-type name, e.g. `"vectorGraphic"`, `"webFrame"`), but
|
|
58
|
+
* the bundle can only claim a type it declared. */
|
|
21
59
|
type: string;
|
|
60
|
+
/** How the user enters it. `"doubleClick"` wires the canvas
|
|
61
|
+
* double-click entry; `"command"` is programmatic / menu-driven. */
|
|
22
62
|
entry: "doubleClick" | "command";
|
|
63
|
+
/** Does this element warrant entering THIS context? Pure predicate
|
|
64
|
+
* over the candidate snapshot (kind / groupChain / this plugin's
|
|
65
|
+
* metadata). When an `objectType` already routes a double-click to a
|
|
66
|
+
* context (via `editContextType`), this matcher is not consulted —
|
|
67
|
+
* it is the fallback path for elements claimed by KIND, not metadata
|
|
68
|
+
* (the vectorGraphic case). Optional: a context entered only by
|
|
69
|
+
* command needs no matcher. */
|
|
70
|
+
matches?(candidate: EditContextCandidate): boolean;
|
|
71
|
+
/** Tool ids the context restricts the rail to (the active tool-set
|
|
72
|
+
* swap). Namespaced ids the bundle registered, plus host built-ins it
|
|
73
|
+
* names. Empty = no restriction (all tools stay available). */
|
|
74
|
+
toolIds?: string[];
|
|
75
|
+
/** Panel ids the cockpit emphasizes / raises on enter (the panel-set
|
|
76
|
+
* swap). The shell opens/raises these; it does not hide others. */
|
|
77
|
+
panelIds?: string[];
|
|
78
|
+
/** Called when the context becomes active (after the stack push + the
|
|
79
|
+
* scope narrowing). The element entered on is passed so the hook can
|
|
80
|
+
* prime panel state / publish bindings. */
|
|
81
|
+
onEnter?(ctx: EnteredEditContext): void;
|
|
82
|
+
/** Called when the context pops (Esc, or a programmatic exit), before
|
|
83
|
+
* the stack unwinds. */
|
|
84
|
+
onExit?(ctx: EnteredEditContext): void;
|
|
85
|
+
/** K-1 — pointer inside the context's frame, delivered in FRAME-CONTENT
|
|
86
|
+
* coordinates: the editor resolved the frame's content transform
|
|
87
|
+
* (`frame_outer ∘ content-box offset`), inverted it, and mapped the
|
|
88
|
+
* page-space pointer into the plugin's own space — so the plugin (a
|
|
89
|
+
* sheet grid) hit-tests in content coords regardless of how the frame
|
|
90
|
+
* is moved / scaled / rotated (§8.5 — the plugin never compensates).
|
|
91
|
+
* Optional: a context that doesn't edit by pointer omits them. */
|
|
92
|
+
onContentPointerDown?(e: ContentPointerEvent): void;
|
|
93
|
+
onContentPointerMove?(e: ContentPointerEvent): void;
|
|
94
|
+
onContentPointerUp?(e: ContentPointerEvent): void;
|
|
95
|
+
/** K-1 — a key while the context is active. The shell owns Esc (→
|
|
96
|
+
* `onCancel`) and Enter (→ `onCommit`); every other key forwards here. */
|
|
97
|
+
onContentKey?(e: KeyboardEvent): void;
|
|
98
|
+
/** K-1 — unsaved-edit probe: gates the discard prompt + the §8.0
|
|
99
|
+
* seamless-undo boundary. Absent ⇒ treated as never dirty. */
|
|
100
|
+
isDirty?(): boolean;
|
|
101
|
+
/** K-1 — modal COMMIT (Enter / a click outside the frame): keep the
|
|
102
|
+
* in-flight edits. Fires before `onExit`. */
|
|
103
|
+
onCommit?(): void;
|
|
104
|
+
/** K-1 — modal CANCEL (Esc): revert the in-flight edits. Fires before
|
|
105
|
+
* `onExit`. */
|
|
106
|
+
onCancel?(): void;
|
|
107
|
+
/** HOST-STAMPED, not author-supplied: the `x-paged:<manifest id>`
|
|
108
|
+
* metadata key the host resolves the candidate's `metadata` from
|
|
109
|
+
* before calling `matches`. The SDK adapter fills this from the
|
|
110
|
+
* bundle's manifest at registration; authors leave it undefined. */
|
|
111
|
+
metadataKey?: string;
|
|
23
112
|
}
|
|
24
|
-
/**
|
|
25
|
-
* the
|
|
26
|
-
export interface
|
|
113
|
+
/** The live handle a context's `onEnter` / `onExit` receives — the
|
|
114
|
+
* element entered on + the context type, a clonable snapshot. */
|
|
115
|
+
export interface EnteredEditContext {
|
|
116
|
+
type: string;
|
|
117
|
+
/** The element the context was entered on (the write-scope root). */
|
|
118
|
+
id: ElementId;
|
|
119
|
+
}
|
|
120
|
+
/** K-1 — a pointer delivered to the ACTIVE edit context, in FRAME-CONTENT
|
|
121
|
+
* coordinates (the editor inverted the frame's content transform). */
|
|
122
|
+
export interface ContentPointerEvent {
|
|
123
|
+
/** Pointer in frame-content points (origin = the content-box top-left,
|
|
124
|
+
* x right, y down). */
|
|
125
|
+
contentPoint: [number, number];
|
|
126
|
+
/** The frame the active context edits (the stack's scope root). */
|
|
127
|
+
elementId: string;
|
|
128
|
+
modifiers: {
|
|
129
|
+
shift: boolean;
|
|
130
|
+
alt: boolean;
|
|
131
|
+
cmd: boolean;
|
|
132
|
+
ctrl: boolean;
|
|
133
|
+
};
|
|
134
|
+
/** Mouse button (0 = primary). */
|
|
135
|
+
button: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A plugin-defined OBJECT TYPE (paged.web §9.1.2). A webFrame is an
|
|
139
|
+
* ordinary rectangle with attached `x-paged:media.paged.web` source
|
|
140
|
+
* metadata; registering an object type lets the shell recognize it
|
|
141
|
+
* (`matches`) and route a double-click to a SOURCE edit context
|
|
142
|
+
* (`editContextType`) instead of descending into a group. The metadata
|
|
143
|
+
* namespace is the matcher's domain — `matches` reads the candidate's
|
|
144
|
+
* pre-resolved (own-namespace) envelope.
|
|
145
|
+
*/
|
|
146
|
+
export interface ObjectTypeContribution {
|
|
147
|
+
/** The object-type name — must match a `contributes.objectTypes[].type`
|
|
148
|
+
* the manifest declares (the capability gate). */
|
|
27
149
|
type: string;
|
|
28
|
-
/**
|
|
150
|
+
/** Is this element an instance of this object type? Reads the
|
|
151
|
+
* candidate's metadata envelope (this plugin's `x-paged:<id>` carrier)
|
|
152
|
+
* — e.g. "has a `source` field" for a webFrame. */
|
|
153
|
+
matches(candidate: EditContextCandidate): boolean;
|
|
154
|
+
/** The edit-context type a double-click on a matching element enters,
|
|
155
|
+
* instead of group descent. Must be a context the SAME bundle
|
|
156
|
+
* registered via `contribute.editContext`. Absent = the object type is
|
|
157
|
+
* recognized for selection/chrome but double-click falls through to
|
|
158
|
+
* the default (group descent) — the honest partial. */
|
|
159
|
+
editContextType?: string;
|
|
160
|
+
/** What the baked IDML form degrades to without the plugin (the
|
|
161
|
+
* metadata-plus-baked-fallback contract; `ObjectTypeBaker` produces
|
|
162
|
+
* the derived children). Carried for the bake loop (still reserved)
|
|
163
|
+
* and for selection-chrome hints. */
|
|
29
164
|
bakedFallback: "group" | "rectangle" | "raster";
|
|
165
|
+
/** HOST-STAMPED (see `EditContextContribution.metadataKey`): the
|
|
166
|
+
* `x-paged:<manifest id>` key the host resolves the candidate's
|
|
167
|
+
* `metadata` from before calling `matches`. Authors leave it
|
|
168
|
+
* undefined; the SDK adapter fills it. */
|
|
169
|
+
metadataKey?: string;
|
|
30
170
|
}
|
|
171
|
+
/** Back-compat aliases (the v0 reserved descriptors) — the rich
|
|
172
|
+
* contributions above supersede them; kept so existing references
|
|
173
|
+
* resolve. New code uses `EditContextContribution` /
|
|
174
|
+
* `ObjectTypeContribution`. */
|
|
175
|
+
export type EditContextDescriptor = EditContextContribution;
|
|
176
|
+
export type ObjectTypeDescriptor = ObjectTypeContribution;
|
|
31
177
|
/**
|
|
32
178
|
* The contribution surface. Every method enforces the namespace rule
|
|
33
179
|
* (ids start with `<manifest.id>.`) and tracks the registration for
|
|
@@ -36,14 +182,79 @@ export interface ObjectTypeDescriptor {
|
|
|
36
182
|
export interface ContributionSurface {
|
|
37
183
|
tool(contribution: ToolContribution): Disposable;
|
|
38
184
|
panel(contribution: PanelContribution): Disposable;
|
|
185
|
+
/**
|
|
186
|
+
* Register a DECLARATIVE panel (W3.1, closes B-01): sections/rows/
|
|
187
|
+
* widgets from the catalog vocabulary, with visibility/enablement
|
|
188
|
+
* driven by the bundle's PUBLISHED bindings (`host.bindings`) — no
|
|
189
|
+
* React crosses the boundary (the isolate-ready panel form; see
|
|
190
|
+
* panel-schema.ts). Same namespace + capability gate as `panel`
|
|
191
|
+
* (`contributes.panels[]` must list the id). The host renders the
|
|
192
|
+
* schema from the catalog and subscribes to the bundle's bindings;
|
|
193
|
+
* an expert-leaf React `panel` stays the escape hatch for custom UI.
|
|
194
|
+
*/
|
|
195
|
+
schemaPanel(contribution: SchemaPanelContribution): Disposable;
|
|
39
196
|
command(contribution: CommandContribution): Disposable;
|
|
40
197
|
keybinding(contribution: KeybindingContribution): Disposable;
|
|
41
198
|
overlay(contribution: OverlayContribution): Disposable;
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Register an EDIT CONTEXT (W3.2, closes B-02): a double-click (or
|
|
201
|
+
* programmatic) entry on a content type that pushes a scoped context
|
|
202
|
+
* — restricted tool-set, emphasized panels, breadcrumb, narrowed
|
|
203
|
+
* write-scope, Esc-pops. Capability-gated: the `type` must be listed
|
|
204
|
+
* in `contributes.editContexts[]`. The shell owns the stack + chrome
|
|
205
|
+
* + scope; the plugin owns the matcher + the onEnter/onExit hooks.
|
|
206
|
+
*/
|
|
207
|
+
editContext(contribution: EditContextContribution): Disposable;
|
|
208
|
+
/**
|
|
209
|
+
* Register an OBJECT TYPE (W3.2, closes W-03): a plugin-defined object
|
|
210
|
+
* (a webFrame is a rectangle with attached source metadata). A
|
|
211
|
+
* double-click on a matching element enters its `editContextType`
|
|
212
|
+
* instead of descending into a group. Capability-gated: the `type`
|
|
213
|
+
* must be listed in `contributes.objectTypes[]`. The matcher reads the
|
|
214
|
+
* element's OWN-namespace metadata envelope (the `x-paged:<id>`
|
|
215
|
+
* carrier).
|
|
216
|
+
*/
|
|
217
|
+
objectType(contribution: ObjectTypeContribution): Disposable;
|
|
218
|
+
/**
|
|
219
|
+
* Register a document IMPORTER (K-2 / S-06): claim file extensions /
|
|
220
|
+
* MIME types so an opened file (File menu, drag-drop, or
|
|
221
|
+
* `host.shell.pickFile`) routes its bytes to THIS plugin's `import()`
|
|
222
|
+
* instead of the default IDML loader — the plugin owns what the file
|
|
223
|
+
* becomes (load into its own engine, lower a range, …; it does not
|
|
224
|
+
* replace the document unless it chooses to). Capability-gated: the
|
|
225
|
+
* `id` must be listed in `contributes.importers[]`. Probe
|
|
226
|
+
* `supports("contribute.importer@1")`.
|
|
227
|
+
*/
|
|
228
|
+
importer(contribution: ImporterContribution): Disposable;
|
|
229
|
+
/**
|
|
230
|
+
* Register a document EXPORTER (K-2 / S-06): produce bytes for a file
|
|
231
|
+
* type on demand (the export UI lists it and pulls on save).
|
|
232
|
+
* Capability-gated: the `id` must be listed in
|
|
233
|
+
* `contributes.exporters[]`.
|
|
234
|
+
*/
|
|
235
|
+
exporter(contribution: ExporterContribution): Disposable;
|
|
236
|
+
/**
|
|
237
|
+
* Open a SCENE-LAYER surface (C-1): submit vector content that renders
|
|
238
|
+
* INSIDE a frame, in frame-content coordinates — core applies the
|
|
239
|
+
* frame's `ItemTransform` and clips to the content box (§8.5), so the
|
|
240
|
+
* plugin never compensates for the transform. The layer lowers through
|
|
241
|
+
* the same display-list → GPU/CPU path as native content (colour-
|
|
242
|
+
* managed, print-correct). Capability-gated: `capabilities.rendering`
|
|
243
|
+
* must include `"sceneLayer"`. Probe `supports("rendering.sceneLayer@1")`
|
|
244
|
+
* — false when the host wires no scene channel (the surface then warns +
|
|
245
|
+
* no-ops). The returned surface is disposable: disposing it clears every
|
|
246
|
+
* layer it submitted.
|
|
247
|
+
*/
|
|
248
|
+
sceneLayer(): SceneLayerSurface;
|
|
249
|
+
}
|
|
250
|
+
/** The scene-layer surface (C-1) returned by `contribute.sceneLayer()`.
|
|
251
|
+
* `elementId` is the host `Self` id of the frame to render into. */
|
|
252
|
+
export interface SceneLayerSurface extends Disposable {
|
|
253
|
+
/** Submit (replacing any previous) the vector layer for `elementId`. */
|
|
254
|
+
submit(elementId: string, layer: SceneLayer): Promise<void>;
|
|
255
|
+
/** Clear the layer for `elementId` (returns the frame to native
|
|
256
|
+
* content). */
|
|
257
|
+
clear(elementId: string): Promise<void>;
|
|
47
258
|
}
|
|
48
259
|
/** Expected mutation failures are results, not throws — mirroring the
|
|
49
260
|
* editor's mutate-never-throws convention. */
|
|
@@ -58,6 +269,23 @@ export type MutationOutcome = {
|
|
|
58
269
|
export interface DocumentChangeEvent {
|
|
59
270
|
kind: "mutationApplied" | "undoApplied" | "redoApplied";
|
|
60
271
|
pageIds: PageId[];
|
|
272
|
+
/** Content-box reflow (protocol v38, C-2/S-05): present ONLY when the
|
|
273
|
+
* change RESIZED a frame's content box (a `resizeFrame`) — never on a
|
|
274
|
+
* pure transform (move/scale/rotate is display-only, §8.5). A
|
|
275
|
+
* pagination consumer re-splits on this and ignores transform-only
|
|
276
|
+
* changes (where it is absent). */
|
|
277
|
+
reflow?: {
|
|
278
|
+
frameId: string;
|
|
279
|
+
contentBox: [number, number, number, number];
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/** One link in a text-frame thread (protocol v38, C-2/S-05). `next` is
|
|
283
|
+
* the following frame's id (null at the tail); `overflow` marks the tail
|
|
284
|
+
* frame as overset (story content past the chain end). */
|
|
285
|
+
export interface FrameChainLink {
|
|
286
|
+
frameId: string;
|
|
287
|
+
next: string | null;
|
|
288
|
+
overflow: boolean;
|
|
61
289
|
}
|
|
62
290
|
/**
|
|
63
291
|
* Read-broad / write-through-one-door. `mutate` is the single write
|
|
@@ -75,6 +303,12 @@ export interface DocumentSurface {
|
|
|
75
303
|
hitTest(pageId: PageId, point: [number, number], filter?: HitFilter): Promise<HitResult | null>;
|
|
76
304
|
elementGeometry(ids: ElementId[]): Promise<ElementGeometryItem[]>;
|
|
77
305
|
tree(): Promise<SceneTreeNode[]>;
|
|
306
|
+
/** Read a text frame's thread topology (protocol v38, C-2/S-05) — the
|
|
307
|
+
* ordered chain of frames a story flows through, tail-overflow flagged.
|
|
308
|
+
* Empty when the story has no frame or no document is loaded. A
|
|
309
|
+
* pagination consumer reads this to know the real host chain (rather
|
|
310
|
+
* than a caller-supplied one). */
|
|
311
|
+
frameChain(storyId: string): Promise<FrameChainLink[]>;
|
|
78
312
|
onDidChange(listener: (e: DocumentChangeEvent) => void): Disposable;
|
|
79
313
|
/**
|
|
80
314
|
* Plugin-metadata carrier (protocol v33) — read this plugin's
|
|
@@ -143,6 +377,27 @@ export interface ViewportSurface {
|
|
|
143
377
|
* screen-tolerance idiom every tool needs). */
|
|
144
378
|
pxToPt(px: number): number;
|
|
145
379
|
}
|
|
380
|
+
/** Font advance + vertical metrics, in document points (pt). */
|
|
381
|
+
export interface TextMetrics {
|
|
382
|
+
/** Total advance width of the run at `sizePt`. */
|
|
383
|
+
advance: number;
|
|
384
|
+
/** Face ascender at `sizePt`. */
|
|
385
|
+
ascender: number;
|
|
386
|
+
/** Face descender at `sizePt` (negative below the baseline). */
|
|
387
|
+
descender: number;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Text measurement against the loaded document's fonts (S-13). A read
|
|
391
|
+
* door — no capability gate (like {@link ViewportSurface}); it wraps the
|
|
392
|
+
* engine's shaper (`paged-text::shape_run`) so a plugin can size grid
|
|
393
|
+
* columns / lower content to widths the page surface will agree with
|
|
394
|
+
* (the §8.3 cross-surface-consistency requirement). Resolves the face
|
|
395
|
+
* from the document's font registry; falls back to the default face when
|
|
396
|
+
* `family` is unknown.
|
|
397
|
+
*/
|
|
398
|
+
export interface TextSurface {
|
|
399
|
+
measureString(family: string, style: string | null, text: string, sizePt: number): Promise<TextMetrics>;
|
|
400
|
+
}
|
|
146
401
|
/** The v0 overlay channel: the shared tool-preview signal (polyline /
|
|
147
402
|
* rect). Retained plugin scene layers are the P2 channel — reserved,
|
|
148
403
|
* not faked. */
|
|
@@ -161,6 +416,29 @@ export interface ShellSurface {
|
|
|
161
416
|
* Window-menu / panel-rail path). */
|
|
162
417
|
openPanel(panelId: string): void;
|
|
163
418
|
closePanel(panelId: string): void;
|
|
419
|
+
/** Open the host's file picker and resolve to the chosen files' bytes
|
|
420
|
+
* (read at the host boundary — the contract never leaks a DOM `File`,
|
|
421
|
+
* so a bundle stays isolate-ready, K-5 / S-11). Resolves to `[]` when
|
|
422
|
+
* the user cancels OR no picker is wired (the honest no-picker door);
|
|
423
|
+
* probe `host.supports("shell.pickFile@1")` for the latter. */
|
|
424
|
+
pickFile(options?: FilePickerOptions): Promise<readonly PickedFile[]>;
|
|
425
|
+
}
|
|
426
|
+
/** Filter + multiplicity for `ShellSurface.pickFile` (K-5 / S-11). */
|
|
427
|
+
export interface FilePickerOptions {
|
|
428
|
+
/** Accept filter — extensions (leading dot) and/or MIME types, passed
|
|
429
|
+
* straight to the picker's `accept` (e.g. `[".xlsx"]`). Absent = any. */
|
|
430
|
+
accept?: readonly string[];
|
|
431
|
+
/** Allow choosing more than one file. Default `false`. */
|
|
432
|
+
multiple?: boolean;
|
|
433
|
+
}
|
|
434
|
+
/** A file the user chose through `pickFile`, bytes already read. */
|
|
435
|
+
export interface PickedFile {
|
|
436
|
+
/** File name incl. extension. */
|
|
437
|
+
name: string;
|
|
438
|
+
/** The file's raw bytes. */
|
|
439
|
+
bytes: Uint8Array;
|
|
440
|
+
/** MIME type the browser reported (may be `""`). */
|
|
441
|
+
mimeType: string;
|
|
164
442
|
}
|
|
165
443
|
/** Namespaced key-value persistence (`paged.plugin.<id>.*`), JSON
|
|
166
444
|
* values. Backing is host-provided (localStorage in-process;
|
|
@@ -171,6 +449,120 @@ export interface StorageSurface {
|
|
|
171
449
|
delete(key: string): void;
|
|
172
450
|
keys(): string[];
|
|
173
451
|
}
|
|
452
|
+
/** Per-plugin usage + the granted ceiling, in bytes (`BlobSurface.usage`). */
|
|
453
|
+
export interface BlobUsage {
|
|
454
|
+
/** Bytes this plugin currently stores. */
|
|
455
|
+
used: number;
|
|
456
|
+
/** The granted ceiling in bytes — the stricter of the host's hard
|
|
457
|
+
* per-plugin cap and the manifest's requested `storage.quotaBytes`.
|
|
458
|
+
* `0` when no store is wired. */
|
|
459
|
+
quota: number;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Persistent BINARY blob storage (K-4 / S-08): an OPFS-backed,
|
|
463
|
+
* per-plugin, quota-bounded store for bytes too large for the KV
|
|
464
|
+
* `host.storage` (multi-MB workbook bytes, decode spill). Keys are
|
|
465
|
+
* namespaced to THIS plugin (a bundle never sees another's bytes).
|
|
466
|
+
* Capability-gated: every door requires `capabilities.storage` ∋
|
|
467
|
+
* `blob: true`. Always present — when the host injects no backend a
|
|
468
|
+
* `read` answers `null`, `keys` is `[]`, `usage` is `{used:0,quota:0}`,
|
|
469
|
+
* and a `write` REJECTS (the honest no-store door; probe
|
|
470
|
+
* `supports("storage.blob@1")` first). A `write` that would exceed the
|
|
471
|
+
* granted quota rejects.
|
|
472
|
+
*/
|
|
473
|
+
export interface BlobSurface {
|
|
474
|
+
write(key: string, bytes: Uint8Array): Promise<void>;
|
|
475
|
+
read(key: string): Promise<Uint8Array | null>;
|
|
476
|
+
delete(key: string): Promise<void>;
|
|
477
|
+
keys(): Promise<string[]>;
|
|
478
|
+
usage(): Promise<BlobUsage>;
|
|
479
|
+
}
|
|
480
|
+
/** The per-origin outcome of a consent request. */
|
|
481
|
+
export interface ConsentResult {
|
|
482
|
+
/** Origins the user granted (a subset of the requested set). */
|
|
483
|
+
granted: readonly string[];
|
|
484
|
+
/** Origins denied (out-of-allow-list or user-declined). */
|
|
485
|
+
denied: readonly string[];
|
|
486
|
+
/** Whether the grant was remembered for this document (survives reopen). */
|
|
487
|
+
remembered: boolean;
|
|
488
|
+
}
|
|
489
|
+
export interface NetworkSurface {
|
|
490
|
+
/** Request consent to reach `origins` (`scheme://host[:port]`) for a stated
|
|
491
|
+
* `purpose`; the host renders the data-source manifest for review and
|
|
492
|
+
* resolves the per-origin decision. NOTHING fetches before this resolves.
|
|
493
|
+
* Origins outside the declared `capabilities.network` allow-list are denied.
|
|
494
|
+
* Requires `capabilities.network` to be declared (else a capability error). */
|
|
495
|
+
requestConsent(origins: readonly string[], purpose: string): Promise<ConsentResult>;
|
|
496
|
+
/** The currently-granted origins (session grants + remembered) — a bundle
|
|
497
|
+
* gates its own reach on this. */
|
|
498
|
+
consentedOrigins(): readonly string[];
|
|
499
|
+
}
|
|
500
|
+
/** A field of a provider's schema (Arrow-seam shape). */
|
|
501
|
+
export interface ProviderField {
|
|
502
|
+
name: string;
|
|
503
|
+
/** Arrow-aligned logical type: `text|int|float|bool|date|datetime|bytes|null`. */
|
|
504
|
+
ty: string;
|
|
505
|
+
nullable?: boolean;
|
|
506
|
+
}
|
|
507
|
+
/** A provider's schema descriptor (the half `discover` surfaces without rows). */
|
|
508
|
+
export interface ProviderSchema {
|
|
509
|
+
fields: ProviderField[];
|
|
510
|
+
}
|
|
511
|
+
/** The columnar row payload a provider serves (Arrow-aligned): one array per
|
|
512
|
+
* schema field. Opaque to the contract beyond its shape — the consumer maps it
|
|
513
|
+
* to its own model. */
|
|
514
|
+
export interface ProviderRecordSet {
|
|
515
|
+
schema: ProviderSchema;
|
|
516
|
+
columns: unknown[][];
|
|
517
|
+
rowCount: number;
|
|
518
|
+
}
|
|
519
|
+
/** What a provider hands `register`: a discovery descriptor + a LAZY snapshot
|
|
520
|
+
* getter (invoked only when a consumer pulls, in the provider's own realm under
|
|
521
|
+
* the provider's own capability/consent) + the current content revision. */
|
|
522
|
+
export interface DataProviderRegistration {
|
|
523
|
+
id: string;
|
|
524
|
+
category: string;
|
|
525
|
+
schema: ProviderSchema;
|
|
526
|
+
/** An opaque content etag; bump it via the handle when the data changes. */
|
|
527
|
+
revision: string;
|
|
528
|
+
getSnapshot(): Promise<ProviderRecordSet> | ProviderRecordSet;
|
|
529
|
+
}
|
|
530
|
+
/** The handle a provider holds to signal refresh / tear its provider down. */
|
|
531
|
+
export interface DataProviderHandle {
|
|
532
|
+
/** Announce a new revision — consumers subscribed via `onDidChange` re-pull. */
|
|
533
|
+
update(revision: string): void;
|
|
534
|
+
/** Remove the provider; `discover` stops listing it. */
|
|
535
|
+
dispose(): void;
|
|
536
|
+
}
|
|
537
|
+
/** A discovery record (schema + revision, NO rows). */
|
|
538
|
+
export interface DataProviderInfo {
|
|
539
|
+
id: string;
|
|
540
|
+
category: string;
|
|
541
|
+
schema: ProviderSchema;
|
|
542
|
+
revision: string;
|
|
543
|
+
}
|
|
544
|
+
/** A pulled snapshot (the rows). */
|
|
545
|
+
export interface DataProviderSnapshot {
|
|
546
|
+
id: string;
|
|
547
|
+
revision: string;
|
|
548
|
+
records: ProviderRecordSet;
|
|
549
|
+
}
|
|
550
|
+
export interface DataProvidersSurface {
|
|
551
|
+
/** PROVIDER side — register a named provider (gated on
|
|
552
|
+
* `capabilities.dataProviders.publish` ∋ category). Returns a handle to
|
|
553
|
+
* signal refresh / dispose. */
|
|
554
|
+
register(registration: DataProviderRegistration): DataProviderHandle;
|
|
555
|
+
/** CONSUMER side — enumerate providers by category (schema + revision, NO
|
|
556
|
+
* rows). Gated on `capabilities.dataProviders.consume`. Empty when no shared
|
|
557
|
+
* registry is wired (graceful absence). */
|
|
558
|
+
discover(category?: string): readonly DataProviderInfo[];
|
|
559
|
+
/** CONSUMER side — pull a provider's current snapshot, or `null` if it no
|
|
560
|
+
* longer exists. Gated on `consume`. */
|
|
561
|
+
get(id: string): Promise<DataProviderSnapshot | null>;
|
|
562
|
+
/** CONSUMER side — fire when a provider's revision changes; re-pull on your
|
|
563
|
+
* own schedule. Subscribing to an absent id is inert. */
|
|
564
|
+
onDidChange(id: string, listener: (revision: string) => void): Disposable;
|
|
565
|
+
}
|
|
174
566
|
export interface Diagnostic {
|
|
175
567
|
severity: "error" | "warning" | "info";
|
|
176
568
|
message: string;
|
|
@@ -188,6 +580,21 @@ export interface DiagnosticsSurface {
|
|
|
188
580
|
get(key: string): Diagnostic[];
|
|
189
581
|
onDidChange(listener: (key: string) => void): Disposable;
|
|
190
582
|
}
|
|
583
|
+
export interface BindingsSurface {
|
|
584
|
+
/** Publish (or update) a named reactive value. Schema rows reading
|
|
585
|
+
* `{ bind: name }` re-render on every change. JSON only. */
|
|
586
|
+
publish(name: string, value: unknown): void;
|
|
587
|
+
/** Read the current value of a published binding (or `undefined`).
|
|
588
|
+
* The host uses this when first rendering a row; bundles rarely
|
|
589
|
+
* need it. */
|
|
590
|
+
get(name: string): unknown;
|
|
591
|
+
/** Remove a published binding. Rows reading it fall back to the
|
|
592
|
+
* gate's "absent" semantics (visible / enabled). */
|
|
593
|
+
delete(name: string): void;
|
|
594
|
+
/** Subscribe to changes of ANY published binding (the host's render
|
|
595
|
+
* subscription; the argument is the changed name). */
|
|
596
|
+
onDidChange(listener: (name: string) => void): Disposable;
|
|
597
|
+
}
|
|
191
598
|
/**
|
|
192
599
|
* What `activate(host)` receives. Types from `@paged-media/plugin-api`,
|
|
193
600
|
* values from here — never import host values into a bundle's module
|
|
@@ -201,10 +608,53 @@ export interface BundleHost {
|
|
|
201
608
|
readonly document: DocumentSurface;
|
|
202
609
|
readonly selection: SelectionSurface;
|
|
203
610
|
readonly viewport: ViewportSurface;
|
|
611
|
+
/** Font measurement against the document's fonts (S-13). A read door,
|
|
612
|
+
* no capability gate; `supports("text.measure@1")` reports whether the
|
|
613
|
+
* host wired the engine shaper (it is false under a host that injects
|
|
614
|
+
* no measurement backend — the headless harness returns an estimate). */
|
|
615
|
+
readonly text: TextSurface;
|
|
204
616
|
readonly overlay: OverlaySurface;
|
|
205
617
|
readonly shell: ShellSurface;
|
|
206
618
|
readonly storage: StorageSurface;
|
|
619
|
+
/** The capability-gated BINARY blob store (K-4 / S-08): OPFS-backed,
|
|
620
|
+
* per-plugin, quota-bounded bytes for payloads too large for the KV
|
|
621
|
+
* `storage`. Always present; gated on `capabilities.storage` ∋ blob.
|
|
622
|
+
* When the host injects no backend, reads answer null / `[]` /
|
|
623
|
+
* `{used:0,quota:0}`, writes reject, and `supports("storage.blob@1")`
|
|
624
|
+
* is false (the honest no-store door). */
|
|
625
|
+
readonly blob: BlobSurface;
|
|
626
|
+
/** The capability-gated NETWORK CONSENT door (D-03; base-idea §11). Always
|
|
627
|
+
* present; gated on `capabilities.network` and per-origin user consent.
|
|
628
|
+
* When the host injects no consent backend, every request is DENIED (the
|
|
629
|
+
* honest no-consent posture) and `supports("network.consent@1")` is false. */
|
|
630
|
+
readonly network: NetworkSurface;
|
|
631
|
+
/** The cross-plugin DATA-PROVIDER registry (paged.data §7.1 / D-09). A bundle
|
|
632
|
+
* PUBLISHES a resolved dataset (gated on `capabilities.dataProviders.publish`)
|
|
633
|
+
* and/or DISCOVERS + reads others' (gated on `consume`) — the neutral
|
|
634
|
+
* rendezvous, never direct plugin contact. Always present; when the host wires
|
|
635
|
+
* no shared registry, `discover()` is empty + `register()` is a no-op and
|
|
636
|
+
* `supports("dataProviders@1")` is false (the honest no-registry posture). */
|
|
637
|
+
readonly dataProviders: DataProvidersSurface;
|
|
207
638
|
readonly diagnostics: DiagnosticsSurface;
|
|
639
|
+
/** Published reactive values (W3.1) — the dynamic half of schema
|
|
640
|
+
* panels: a bundle publishes named booleans (and JSON values) that
|
|
641
|
+
* schema rows reference for `visible`/`enabled`. The plugin owns the
|
|
642
|
+
* derivation; the host owns the lookup + re-render. Always present
|
|
643
|
+
* (in-memory store; trivially proxyable across the isolate). */
|
|
644
|
+
readonly bindings: BindingsSurface;
|
|
645
|
+
/** Host-provided panel widgets (W-04): the code editor and future
|
|
646
|
+
* heavy controls the host owns. Always present — a plain-textarea
|
|
647
|
+
* fallback stands in when the host app injects no widget catalog
|
|
648
|
+
* (probe with `host.supports("widgets.codeEditor@1")`). */
|
|
649
|
+
readonly widgets: WidgetSurface;
|
|
650
|
+
/** The capability-gated ASSET STORE (W-06): a READ-ONLY door over the
|
|
651
|
+
* bytes the DOCUMENT already embeds/loads. v1 serves font face bytes
|
|
652
|
+
* (`getFontFace`) so a bundle can compose real `@font-face`. Always
|
|
653
|
+
* present — when the host app injects no asset source, every read
|
|
654
|
+
* answers `null` (the honest no-bytes door) and
|
|
655
|
+
* `supports("assets.fonts@1")` is false. Capability-gated:
|
|
656
|
+
* `getFontFace` requires `capabilities.assets` ∋ `"fonts"`. */
|
|
657
|
+
readonly assets: AssetSurface;
|
|
208
658
|
/** Capability detection over version sniffing: feature strings of
|
|
209
659
|
* the form `"area.member@major"` (see HOST_FEATURES in plugin-sdk). */
|
|
210
660
|
supports(feature: string): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
export type { PluginId, PluginManifest, PluginCapabilities, PluginContributions, } from "./manifest";
|
|
1
|
+
export type { PluginId, PluginManifest, PluginCapabilities, PluginContributions, NetworkCapability, DataProvidersCapability, StorageCapability, WasmArtifact, WasmPurpose, } from "./manifest";
|
|
2
2
|
export type { BundleHandle, PagedBundle } from "./bundle";
|
|
3
|
-
export type { BundleHost, ContributionSurface, DocumentSurface, SelectionSurface, ViewportSurface, OverlaySurface, ShellSurface, StorageSurface, DiagnosticsSurface, Diagnostic, DocumentChangeEvent, MutationOutcome, Disposable, PluginLogger, EditContextDescriptor, ObjectTypeDescriptor, PluginMetadataEnvelope, ObjectTypeBaker, BakeContext, } from "./host";
|
|
3
|
+
export type { BundleHost, ContributionSurface, SceneLayerSurface, DocumentSurface, SelectionSurface, ViewportSurface, TextSurface, TextMetrics, FrameChainLink, OverlaySurface, ShellSurface, FilePickerOptions, PickedFile, StorageSurface, BlobSurface, BlobUsage, NetworkSurface, ConsentResult, DataProvidersSurface, DataProviderRegistration, DataProviderHandle, DataProviderInfo, DataProviderSnapshot, ProviderSchema, ProviderField, ProviderRecordSet, DiagnosticsSurface, BindingsSurface, Diagnostic, DocumentChangeEvent, MutationOutcome, Disposable, PluginLogger, EditContextContribution, ObjectTypeContribution, EditContextCandidate, EnteredEditContext, ContentPointerEvent, EditContextDescriptor, ObjectTypeDescriptor, PluginMetadataEnvelope, ObjectTypeBaker, BakeContext, } from "./host";
|
|
4
|
+
export type { PanelSchema, PanelSchemaSection, PanelSchemaRow, SchemaPanelContribution, SchemaPanelRenderer, SchemaPanelRendererProps, WidgetValueBinding, BindingRef, SchemaGate, } from "./panel-schema";
|
|
5
|
+
export type { WidgetSurface, CodeEditorProps, CodeEditorDiagnostic, CodeEditorLanguage, } from "./widgets";
|
|
6
|
+
export type { AssetSurface, AssetKind, FontFaceAsset, FontFaceFormat, } from "./assets";
|
|
4
7
|
export type * from "./contributions";
|
|
5
8
|
export type * from "./mutations";
|