@openpresentation/opf-editor 0.28.0 → 0.29.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 (53) hide show
  1. package/README.md +20 -6
  2. package/dist/canvas.d.ts +13 -1
  3. package/dist/canvas.js +39 -9
  4. package/dist/chart-options-panel.js +16 -16
  5. package/dist/codemirror-guard.js +69 -0
  6. package/dist/content-controls.js +127 -74
  7. package/dist/data-grid.js +15 -7
  8. package/dist/design-controls.d.ts +13 -0
  9. package/dist/design-controls.js +134 -124
  10. package/dist/exact-source.d.ts +30 -0
  11. package/dist/font-gate.js +20 -1
  12. package/dist/json-editor.js +8 -2
  13. package/dist/json-options.d.ts +2 -1
  14. package/dist/json-options.js +7 -6
  15. package/dist/layout-templates.d.ts +8 -3
  16. package/dist/layout-templates.js +30 -16
  17. package/dist/numbering-panel.js +2 -3
  18. package/dist/react.d.ts +12 -4
  19. package/dist/react.js +39 -5
  20. package/dist/slide-adapter.d.ts +49 -0
  21. package/dist/slide-adapter.js +289 -0
  22. package/dist/slide-edits.d.ts +46 -0
  23. package/dist/slide-edits.js +629 -0
  24. package/dist/slide-manager.js +2 -1
  25. package/dist/slide-scene.d.ts +96 -0
  26. package/dist/slide-scene.js +413 -0
  27. package/dist/source-checker.js +45 -6
  28. package/dist/source-completions.js +6 -4
  29. package/dist/source-pane.d.ts +18 -6
  30. package/dist/source-pane.js +45 -0
  31. package/dist/source-worker.js +8 -4
  32. package/dist/studio-canvas.d.ts +34 -0
  33. package/dist/studio-canvas.js +586 -0
  34. package/dist/studio-commands.d.ts +15 -0
  35. package/dist/studio-commands.js +155 -0
  36. package/dist/studio-design.d.ts +16 -0
  37. package/dist/studio-design.js +354 -0
  38. package/dist/studio-kit/dom.d.ts +16 -0
  39. package/dist/studio-kit/dom.js +42 -6
  40. package/dist/studio-layers.d.ts +12 -0
  41. package/dist/studio-layers.js +218 -0
  42. package/dist/studio.d.ts +31 -0
  43. package/dist/studio.js +1608 -0
  44. package/dist/styles.css +1546 -117
  45. package/dist/thumbnail-cache.d.ts +2 -0
  46. package/dist/thumbnail-cache.js +10 -1
  47. package/dist/workspace-measure.js +6 -4
  48. package/dist/workspace-parts.js +20 -0
  49. package/dist/workspace-shell.js +25 -15
  50. package/dist/workspace-theme.js +3 -0
  51. package/dist/workspace.d.ts +97 -9
  52. package/dist/workspace.js +325 -59
  53. package/package.json +29 -18
@@ -17,6 +17,8 @@ export interface ThumbnailCache {
17
17
  prepare(presentation: any, indices?: number[]): void;
18
18
  /** The SVG markup (or the text "Preview unavailable") of one slide. Entries are keyed by the slide's index, the slide count and the slide's own content. */
19
19
  html(presentation: any, index: number): string;
20
+ /** CE-20: the cached thumbnail of one slide, or undefined when it has not been drawn yet (a lazy strip calls `prepare` with the visible slides). */
21
+ peek(presentation: any, index: number): string | undefined;
20
22
  /** Forget everything, for example after fonts load. */
21
23
  clear(): void;
22
24
  }
@@ -6,6 +6,7 @@ export function createThumbnailCache({toSvg, getOptions}) {
6
6
  const cache = new Map();
7
7
  let context;
8
8
  let preparedDeck;
9
+ let peeked = { deck: null, same: false };
9
10
  const key = (deck, index) => JSON.stringify([index, deck.slides.length, deck.slides[index]]);
10
11
  const contextOf = (deck, options) => {
11
12
  const {slides, ...metadata} = deck;
@@ -19,6 +20,7 @@ export function createThumbnailCache({toSvg, getOptions}) {
19
20
  if (nextContext !== context) cache.clear();
20
21
  context = nextContext;
21
22
  preparedDeck = deck;
23
+ peeked = { deck: null, same: false };
22
24
  const keys = deck.slides.map((_, index) => key(deck, index));
23
25
  const wanted = indices === undefined ? keys.map((_, index) => index) : [...new Set(indices)].filter(index => Number.isInteger(index) && index >= 0 && index < keys.length);
24
26
  const missing = wanted.filter(index => !cache.has(keys[index]));
@@ -45,6 +47,13 @@ export function createThumbnailCache({toSvg, getOptions}) {
45
47
  if (deck !== preparedDeck || !cache.has(value)) prepare(deck);
46
48
  return cache.get(value);
47
49
  },
48
- clear: () => { cache.clear(); preparedDeck = undefined; },
50
+ /** CE-20: the cached thumbnail of a slide, or undefined when it has not been drawn yet (a lazy strip draws it with `prepare`). */
51
+ peek(deck, index) {
52
+ // The context of a deck is read once per deck (a strip peeks at every slide of it in one render).
53
+ if (peeked.deck !== deck) peeked = { deck, same: contextOf(deck, getOptions()) === context };
54
+ if (!peeked.same) return undefined;
55
+ return cache.get(key(deck, index));
56
+ },
57
+ clear: () => { cache.clear(); preparedDeck = undefined; peeked = { deck: null, same: false }; },
49
58
  };
50
59
  }
@@ -1,16 +1,18 @@
1
- // CE-06 (promoted from examples/playground.js): text measurement and font notes shared by the workspace parts.
2
- import { createScriptTextMeasurement } from "@openpresentation/opf-render/fonts";
1
+ // CE-06 (promoted from examples/playground.js): text measurement and font notes shared by the workspace parts. No renderer import: the script
2
+ // planner comes with the fonts handle (`textMeasurement.forScripts`, the renderer's font registry), so the `/workspace` entry, which re-exports
3
+ // `layoutOptionsFor`, loads no renderer code for a host that mounts only the source pane.
3
4
  import { resolveScriptFonts } from "@openpresentation/opf/composition";
4
5
 
5
6
  /**
6
7
  * The layout options for composing slide `index` of `deck`: the fonts handle's measurement, made script-aware for this document (Japanese
7
8
  * under Aptos measures with Noto Sans JP, where the plain strict measurement would throw "cannot display U+65E5" with every face loaded).
8
- * A fonts handle without a measurement is passed through.
9
+ * A fonts handle without a measurement, or whose measurement has no script planner (`forScripts`), is passed through.
9
10
  */
10
11
  export function layoutOptionsFor(fonts, deck, index, catalogs) {
11
12
  if (!fonts?.textMeasurement) return fonts ? { fonts } : {};
13
+ if (typeof fonts.textMeasurement.forScripts !== "function") return { fonts };
12
14
  try {
13
- return { fonts: { textMeasurement: createScriptTextMeasurement(fonts.textMeasurement, resolveScriptFonts(deck, { slideIndex: index, catalogs })) } };
15
+ return { fonts: { textMeasurement: fonts.textMeasurement.forScripts(resolveScriptFonts(deck, { slideIndex: index, catalogs })) } };
14
16
  } catch {
15
17
  return { fonts };
16
18
  }
@@ -0,0 +1,20 @@
1
+ // The slide half of `createOpfEditor` (src/workspace.js), loaded on demand: the renderer, every part that shows or edits slides and the Studio. A host
2
+ // whose editor mounts only the source pane never loads this chunk (and so never loads the renderer); every other layout loads it once, before
3
+ // its parts mount. Internal: only workspace.js imports it.
4
+ export { toSvg } from "@openpresentation/opf-render/svg";
5
+ export { createCanvasEditor } from "./canvas.js";
6
+ export { createSlideNavigator } from "./slide-navigator.js";
7
+ export { createThumbnailStrip } from "./thumbnail-strip.js";
8
+ export { createThumbnailCache } from "./thumbnail-cache.js";
9
+ export { createSlideManager } from "./slide-manager.js";
10
+ export { createOutlineView } from "./outline-view.js";
11
+ export { createExportMenu } from "./export-menu.js";
12
+ export { bindPresentShortcut, createPresentButton, createPresenter } from "./presenter.js";
13
+ export { createReviewPanel } from "./review-panel.js";
14
+ export { createFindPanel, installFindShortcuts } from "./find-panel.js";
15
+ export { createDesignControls } from "./design-controls.js";
16
+ export { prepareDimensionSwitch } from "./switches.js";
17
+ export { mergeSlides, splitSlideByBlocks } from "./content-actions.js";
18
+ export { installCanvasVariableEditing } from "./canvas-variables.js";
19
+ export { createLayoutStudio } from "./workspace-layouts.js";
20
+ export { buildStudioShell, createStudio } from "./studio.js";
@@ -50,25 +50,35 @@ export function buildWorkspaceShell(root, { parts, views, layout, labels = {} })
50
50
  if (parts.present) bar.append(slot("present", "div", { class: "opf-ws-present" }));
51
51
  const hasBar = bar.children.length > 1;
52
52
 
53
- // The main column: the slide (or another view) over the slide row.
54
- const stage = make(doc, "div", { class: "opf-ws-stage" });
55
- const frame = make(doc, "div", { class: "opf-ws-frame" }, slot("canvas", "div", { class: "opf-ws-canvas", "aria-label": "Slide preview" }));
56
- stage.append(frame);
57
- for (const view of ["sorter", "outline", "layouts"]) if (parts[view]) stage.append(slot(view, "div", { class: `opf-ws-view opf-ws-${view}`, hidden: true }));
58
- const main = make(doc, "section", { class: "opf-ws-main", "aria-label": "Slide workspace" });
59
- if (parts.find) main.append(slot("find", "div", { class: "opf-ws-find", hidden: true }));
60
- main.append(stage);
61
- if (parts.navigator || parts.thumbnails) {
62
- const dock = make(doc, "div", { class: "opf-ws-dock" });
63
- if (parts.navigator) dock.append(slot("navigator", "div", { class: "opf-ws-navigator" }));
64
- if (parts.thumbnails) dock.append(slot("thumbnails", "div", { class: "opf-ws-thumbnails" }));
65
- main.append(dock);
53
+ // The main column: the slide (or another view) over the slide row, and the status line. A source-only layout has none: the pane has its own
54
+ // bar, problems and status.
55
+ const viewParts = ["sorter", "outline", "layouts"].filter((view) => parts[view]);
56
+ const hasMain = parts.canvas || parts.find || parts.navigator || parts.thumbnails || viewParts.length > 0;
57
+ let stage;
58
+ let frame;
59
+ let main;
60
+ if (hasMain) {
61
+ stage = make(doc, "div", { class: "opf-ws-stage" });
62
+ if (parts.canvas) {
63
+ frame = make(doc, "div", { class: "opf-ws-frame" }, slot("canvas", "div", { class: "opf-ws-canvas", "aria-label": "Slide preview" }));
64
+ stage.append(frame);
65
+ }
66
+ for (const view of viewParts) stage.append(slot(view, "div", { class: `opf-ws-view opf-ws-${view}`, hidden: true }));
67
+ main = make(doc, "section", { class: "opf-ws-main", "aria-label": "Slide workspace" });
68
+ if (parts.find) main.append(slot("find", "div", { class: "opf-ws-find", hidden: true }));
69
+ main.append(stage);
70
+ if (parts.navigator || parts.thumbnails) {
71
+ const dock = make(doc, "div", { class: "opf-ws-dock" });
72
+ if (parts.navigator) dock.append(slot("navigator", "div", { class: "opf-ws-navigator" }));
73
+ if (parts.thumbnails) dock.append(slot("thumbnails", "div", { class: "opf-ws-thumbnails" }));
74
+ main.append(dock);
75
+ }
76
+ main.append(slot("status", "p", { class: "opf-ws-status", role: "status" }));
66
77
  }
67
- main.append(slot("status", "p", { class: "opf-ws-status", role: "status" }));
68
78
 
69
79
  const body = make(doc, "div", { class: "opf-ws-body" });
70
80
  if (parts.source) body.append(make(doc, "section", { class: "opf-ws-source", "aria-label": "OPF source" }, slot("source", "div", { class: "opf-ws-source-host" })));
71
- body.append(main);
81
+ if (main) body.append(main);
72
82
 
73
83
  // The side panel: Review and Design as tabs.
74
84
  const tabs = ["design", "review"].filter((name) => parts[name]);
@@ -23,6 +23,9 @@ export const THEME_TOKENS = Object.freeze({
23
23
  success: "--opf-ui-success",
24
24
  codeBackground: "--opf-ui-code-bg",
25
25
  codeBorder: "--opf-ui-code-border",
26
+ selection: "--opf-ui-selection",
27
+ hover: "--opf-ui-hover",
28
+ canvasBackground: "--opf-ui-studio-canvas-bg",
26
29
  font: "--opf-ui-font",
27
30
  mono: "--opf-ui-mono",
28
31
  radiusSmall: "--opf-ui-radius-sm",
@@ -13,7 +13,7 @@ import type { ReviewPanel, ReviewPanelOptions } from "./review-panel.js";
13
13
  import type { SlideManager } from "./slide-manager.js";
14
14
  import type { SourceCursor, SourceFormat, SourceFile, SourcePane, SourcePaneOptions } from "./source-pane.js";
15
15
 
16
- export type OpfEditorLayout = "full" | "canvas" | "source";
16
+ export type OpfEditorLayout = "full" | "canvas" | "source" | "studio" | "playground";
17
17
  export type OpfEditorView = "slide" | "sorter" | "outline" | "layouts";
18
18
  export type OpfEditorDensity = "comfortable" | "touch";
19
19
 
@@ -36,6 +36,9 @@ export declare const THEME_TOKENS: Readonly<{
36
36
  success: "--opf-ui-success";
37
37
  codeBackground: "--opf-ui-code-bg";
38
38
  codeBorder: "--opf-ui-code-border";
39
+ selection: "--opf-ui-selection";
40
+ hover: "--opf-ui-hover";
41
+ canvasBackground: "--opf-ui-studio-canvas-bg";
39
42
  font: "--opf-ui-font";
40
43
  mono: "--opf-ui-mono";
41
44
  radiusSmall: "--opf-ui-radius-sm";
@@ -140,6 +143,42 @@ export interface OpfEditorSlots {
140
143
  /** The status line: the editor writes its messages here. */
141
144
  status?: HTMLElement;
142
145
  overlay?: HTMLElement;
146
+ /** CE-20, the Studio: an element of the host placed at the end of the Studio's bar (Share, avatars). */
147
+ topbarEnd?: HTMLElement;
148
+ }
149
+
150
+ /** CE-20: one item of the Studio's selection. `key` is the scene key (the id path, `/slides/@intro/blocks/@kpi`; a layout region `<slide key>#<name>`). */
151
+ export interface OpfStudioSelectionItem { key: string; path: string; idPath?: string; kind: "slide" | "heading" | "region" | "group" | "block" | "part" | "implicit" }
152
+ /** CE-20: a command of the Studio's registry (`studio.group`, `studio.insert.chart`, ...). `when` returns true, or a reason string that disables it. */
153
+ export interface OpfCommand<Ctx = unknown> {
154
+ id: string;
155
+ label: string;
156
+ group?: string;
157
+ /** CodeMirror-style keys ("Mod-g", "Shift-Mod-z", "F2"); Mod is Cmd on macOS and Ctrl elsewhere. */
158
+ keys?: string[];
159
+ /** "canvas": only while focus is on the slide, the layers or the filmstrip; "global" (default) anywhere outside a field. */
160
+ scope?: "canvas" | "global" | ("canvas" | "global")[];
161
+ when?(ctx: Ctx): boolean | string;
162
+ run(ctx: Ctx): boolean | void;
163
+ }
164
+ export interface OpfCommandInfo { id: string; label: string; group?: string; keys: string[]; shortcut: string; enabled: boolean; reason: string }
165
+ /** CE-20: a host's panel in the Studio: a tab of the right panel (default) or a section of the left (`side: "left"`); `mount` returns its cleanup. */
166
+ export interface OpfStudioHostPanel { id: string; label: string; icon?: SVGElement | string; side?: "left" | "right"; mount(element: HTMLElement, editor: OpfEditor): void | (() => void) }
167
+ /** CE-20: the Studio's options (`layout: "studio"` or `"playground"`). */
168
+ export interface OpfStudioOptions {
169
+ /** Which panels the Studio shows; `source` is where the source split opens ("split-right" by default on wide screens, "split-bottom" below 1100px). */
170
+ panels?: { source?: "split-right" | "split-bottom" | "tab" | false };
171
+ hostPanels?: OpfStudioHostPanel[];
172
+ /** Items added to the File menu. */
173
+ fileItems?: { id: string; label: string; run(editor: OpfEditor): void }[];
174
+ /** More commands for the registry (a host palette lists them with the Studio's). */
175
+ commands?: OpfCommand[];
176
+ /** Rebind commands: `{ "studio.source.toggle": ["Mod-Alt-s"] }`; `null` unbinds. */
177
+ keymap?: Record<string, string[] | null>;
178
+ /** Panel sizes stored per host key (nothing is stored without `storage`). */
179
+ sizes?: { key: string; storage?: { get(key: string): string | null; set(key: string, value: string): void } };
180
+ /** Give a deck without ids its ids when the Studio opens it (default true; one undoable change named "Add ids"). Never in the Playground. */
181
+ assignIds?: boolean;
143
182
  }
144
183
 
145
184
  export interface OpfEditorPanels {
@@ -175,7 +214,7 @@ export interface OpfEditorSourceOptions {
175
214
  name?: string;
176
215
  /** The text of the document as the author wrote it, so its spelling is kept. A string `document` is used when this is not given. */
177
216
  text?: string;
178
- /** The Web Worker that runs the pane's text checks off the main thread: `true`, a `Worker`, or a function that returns one. Default: the main thread. */
217
+ /** The Web Worker that runs the pane's text checks off the main thread: `true`, a `Worker`, a function that returns one, or the URL of a worker script (docs/embedding.md, "The source worker"). Default: the main thread. */
179
218
  worker?: SourcePaneOptions["worker"];
180
219
  /** Core `validate` options for the verdict on the text (default the format and reference rules). */
181
220
  checks?: { only?: readonly string[]; [key: string]: unknown };
@@ -211,8 +250,15 @@ export interface OpfEditorOptions {
211
250
  /** `"authored"` (default): the canvas shows `{{variables}}` as written. `"resolved"`: filled in, except in a template deck; a press on filled-in text opens its properties form. */
212
251
  variables?: "authored" | "resolved";
213
252
 
214
- /** `"full"` (default), `"canvas"` or `"source"`: the editor builds the arrangement. Ignored when `slots` is given. */
253
+ /**
254
+ * `"full"` (default), `"canvas"` or `"source"`: the editor builds the arrangement (ignored when `slots` is given). CE-20: `"studio"` is the
255
+ * Presentation and Slide Studio and `"playground"` its first-contact preset (a host's `slots` then add parts, such as `topbarEnd`).
256
+ */
215
257
  layout?: OpfEditorLayout;
258
+ /** CE-20: the Studio's options. */
259
+ studio?: OpfStudioOptions;
260
+ /** CE-20: `import.pptx(editor)` adds "Import PowerPoint…" to the Studio's File menu. */
261
+ import?: { pptx?(editor: OpfEditor): void };
216
262
  slots?: OpfEditorSlots;
217
263
  panels?: OpfEditorPanels;
218
264
  /** The view shown first (default `"slide"`). */
@@ -277,7 +323,16 @@ export interface OpfEditorEvents {
277
323
  ready: { editor: OpfEditor };
278
324
  /** The document changed (an edit in the canvas or the source, undo, redo, a loaded document). Not fired for a catalogs change. */
279
325
  change: { document: unknown; canUndo: boolean; canRedo: boolean; event: EditorEvent };
280
- selection: { path: string; value: unknown; slideIndex: number; element: Element | undefined };
326
+ /** The canvas's selection; in the Studio, the list (`items`, the `primary` and what changed it: `canvas`, `layers`, `keyboard`, `source`, ...). */
327
+ selection: { path: string | undefined; value: unknown; slideIndex: number; element?: Element | undefined; items?: OpfStudioSelectionItem[]; primary?: OpfStudioSelectionItem | null; source?: string };
328
+ /** CE-20: the Studio's zoom changed (a factor of the fitted slide). */
329
+ zoom: { zoom: number };
330
+ /** CE-20: the Studio switched preset. */
331
+ layout: { layout: "studio" | "playground"; previous: "studio" | "playground" };
332
+ /** CE-20: a Studio command ran (`ok` false when it was off; `reason` says why). */
333
+ command: { id: string; ok: boolean; reason?: string };
334
+ /** CE-20: Layout Studio was opened from "Edit layout", or closed. */
335
+ layoutStudio: { open: boolean; recordId: string };
281
336
  /**
282
337
  * The caret or selection of the source pane moved, in JSON, YAML or Markdown, also while the pane has no focus: the path under it as a JSON Pointer
283
338
  * and by id, and the selection in source offsets. Quiet for `source.cursorDelay` first and not repeated for a place already reported; the detail is
@@ -328,6 +383,15 @@ export interface OpfEditorSetDocumentOptions {
328
383
  rebase?: boolean;
329
384
  }
330
385
 
386
+ /**
387
+ * The handle of a mounted editor. It is returned at once, before the parts have mounted (they wait for the fonts and, in a layout that shows
388
+ * slides, for the slide chunk), and every method works from the first moment: a setting (`setDensity`, `setExportMode`, `setView`, `setSlide`,
389
+ * `setReadOnly`, `setTheme`, `setName`) is kept and read when the parts mount, and a call that acts on a part (`select`, `goTo`, `showPanel`,
390
+ * `focus`, `openFind`, `present`, and the Studio's `setLayout`, `setZoom`, `fit`, `openLayout` and `commands.register`) is queued and runs, in
391
+ * order, as soon as the editor is mounted, before `mounted` is emitted; a later call to the same method replaces an earlier one. A queued call
392
+ * returns `true` (accepted) or, where it needs a part the editor does not have, `false`. Only `setDocument` and `setSourceText`, whose result
393
+ * depends on the document, throw before `ready`.
394
+ */
331
395
  export interface OpfEditor {
332
396
  /** The mount element and the node the editor built inside it. */
333
397
  readonly element: HTMLElement;
@@ -349,8 +413,19 @@ export interface OpfEditor {
349
413
  readonly layoutStudio: LayoutStudio | undefined;
350
414
  readonly fonts: EditorFonts | undefined;
351
415
  readonly slideIndex: number;
352
- /** The content last selected on the canvas. */
353
- readonly selection: { path: string; value: unknown } | null;
416
+ /** The content last selected on the canvas; in the Studio, the selection list. */
417
+ readonly selection: { path: string; value: unknown } | OpfStudioSelectionItem[] | null;
418
+ /** CE-20: the arrangement; `setLayout` switches the Studio between "studio" and "playground". */
419
+ readonly layout: OpfEditorLayout | "slots";
420
+ setLayout(layout: "studio" | "playground"): boolean;
421
+ /** CE-20: the Studio's zoom (1 is the slide fitted), `setZoom` and `fit` ("slide" or "width"). */
422
+ readonly zoom: number;
423
+ setZoom(zoom: number): void;
424
+ fit(mode?: "slide" | "width"): void;
425
+ /** CE-20: "Edit layout": open a layout of the slide (default the current slide's) in Layout Studio, forked into the deck when it comes from a catalog. */
426
+ openLayout(layoutId?: string, options?: { slide?: number }): boolean;
427
+ /** CE-20: the Studio's command registry; empty outside the Studio. */
428
+ readonly commands: { list(): OpfCommandInfo[]; run(id: string): boolean; register(command: OpfCommand): () => void };
354
429
  readonly view: OpfEditorView;
355
430
  readonly views: OpfEditorView[];
356
431
  readonly readOnly: boolean;
@@ -369,6 +444,14 @@ export interface OpfEditor {
369
444
  * as written. A document the session refuses is listed in the pane as a draft and `false` is returned. Throws before `ready`.
370
445
  */
371
446
  setDocument(document: unknown, options?: OpfEditorSetDocumentOptions): boolean;
447
+ /**
448
+ * Load raw source text into the source pane without converting it (a file as it was read, text that does not parse): what pasting it over
449
+ * everything does. `options.format` is the text's format (the pane switches to it), `options.name` the file name, `options.rebase` as in
450
+ * `setDocument` (only when the text applied). Text that reads as a document the session accepts is applied as one undoable change; anything
451
+ * else stays in the pane as a draft with its problems (the slide keeps the last valid document) and `false` is returned. An open canvas edit
452
+ * is committed first. Throws before `ready`, without a source pane, and while read-only.
453
+ */
454
+ setSourceText(text: string, options?: Omit<OpfEditorSetDocumentOptions, "text">): boolean;
372
455
  /** Switch the view. Commits an open canvas edit first; false when that failed or the view is not available. */
373
456
  setView(view: OpfEditorView, options?: { focus?: boolean }): boolean;
374
457
  /** Show slide `index` (0-based). Commits an open canvas edit first. */
@@ -380,10 +463,12 @@ export interface OpfEditor {
380
463
  /** Show a slide and select the content at `path` on it. */
381
464
  goTo(index: number, path?: string): boolean;
382
465
  /** Select the content at `path` on the current slide (or the closest content that can be selected); returns the path selected. */
383
- select(path: string, options?: { focus?: boolean }): string | null;
466
+ /** Select content by path (the canvas: returns the path it selected). In the Studio: scene keys or paths, several siblings at once; returns whether all were found. */
467
+ select(path: string | string[], options?: { focus?: boolean }): string | null | boolean;
384
468
  showPanel(panel: "review" | "design", focus?: boolean): boolean;
385
469
  /** Start the full-screen presentation at the slide on show. False when it cannot start (invalid source, no slides, already running). */
386
- present(): boolean;
470
+ /** Present from the slide on show (or from `from`, 0-based). */
471
+ present(from?: number): boolean;
387
472
  undo(): boolean;
388
473
  redo(): boolean;
389
474
  /** Commit an open canvas edit. False when it could not be committed. */
@@ -407,7 +492,10 @@ export interface OpfEditor {
407
492
  destroy(): void;
408
493
  }
409
494
 
410
- /** Mount the editor in `element` (its content is replaced). */
495
+ /**
496
+ * Mount the editor in `element` (its content is replaced). The parts mount once the fonts have arrived and, for a layout that shows slides,
497
+ * once the slide chunk (the renderer and the slide parts, imported on demand) has loaded; await `ready`. A source-only editor never loads that chunk.
498
+ */
411
499
  export declare function createOpfEditor(element: HTMLElement, options?: OpfEditorOptions): OpfEditor;
412
500
 
413
501
  export type { LayoutStudio } from "./workspace-layouts.js";