@getv.design/embed 0.0.0-stage → 0.1.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.
- package/LICENSE +173 -0
- package/README.md +422 -2
- package/THIRD_PARTY_NOTICES.txt +850 -0
- package/dist/chunks/chunk-2H24PH2F.js +2 -0
- package/dist/chunks/chunk-BBJ6N4ZS.js +2 -0
- package/dist/chunks/chunk-Q6QQ2HGJ.js +2 -0
- package/dist/chunks/chunk-QFL2QGB3.js +8 -0
- package/dist/chunks/fonts.js +4 -0
- package/dist/edit.d.ts +5 -0
- package/dist/edit.js +2381 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +2 -0
- package/dist/static.d.ts +7 -0
- package/dist/static.js +2 -0
- package/dist/types.d.ts +223 -0
- package/dist/version.d.ts +8 -0
- package/dist/view.d.ts +5 -0
- package/dist/view.js +100 -0
- package/edit.css +2185 -0
- package/fonts/Inter-Black.woff2 +0 -0
- package/fonts/Inter-BlackItalic.woff2 +0 -0
- package/fonts/Inter-Bold.woff2 +0 -0
- package/fonts/Inter-BoldItalic.woff2 +0 -0
- package/fonts/Inter-ExtraBold.woff2 +0 -0
- package/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
- package/fonts/Inter-ExtraLight.woff2 +0 -0
- package/fonts/Inter-ExtraLightItalic.woff2 +0 -0
- package/fonts/Inter-Italic.woff2 +0 -0
- package/fonts/Inter-Light.woff2 +0 -0
- package/fonts/Inter-LightItalic.woff2 +0 -0
- package/fonts/Inter-Medium.woff2 +0 -0
- package/fonts/Inter-MediumItalic.woff2 +0 -0
- package/fonts/Inter-Regular.woff2 +0 -0
- package/fonts/Inter-SemiBold.woff2 +0 -0
- package/fonts/Inter-SemiBoldItalic.woff2 +0 -0
- package/fonts/Inter-Thin.woff2 +0 -0
- package/fonts/Inter-ThinItalic.woff2 +0 -0
- package/fonts/OFL.txt +92 -0
- package/package.json +51 -4
- package/view.css +98 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The root entry: a thin front door that loads `/view`, `/edit` or the player
|
|
3
|
+
* only when asked (budget: 3 KB gzip). It imports nothing heavy statically:
|
|
4
|
+
* `/view` arrives through a dynamic `import()`, so a page that never mounts
|
|
5
|
+
* pays for none of it.
|
|
6
|
+
*
|
|
7
|
+
* `mode: 'play'` is a view with a presentation over it. Escape ends the
|
|
8
|
+
* presentation and leaves the view, as the player's own Escape does; the
|
|
9
|
+
* handle's `destroy()` takes both away, because the host holds no other handle
|
|
10
|
+
* to the view underneath. `mode: 'edit'` loads `/edit`, which loads the
|
|
11
|
+
* editor; neither comes with the view.
|
|
12
|
+
*/
|
|
13
|
+
import type { EditHandle, MountOptions, PlayHandle, Source, ViewHandle } from './types.js';
|
|
14
|
+
export type * from './types.js';
|
|
15
|
+
export { version } from './version.js';
|
|
16
|
+
/** Show a document in `el`, to view, present or edit. */
|
|
17
|
+
export declare function mount(el: HTMLElement, source: Source, options: MountOptions): Promise<ViewHandle | EditHandle | PlayHandle>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! @getv.design/embed v0.1.1. Free to use under the vDesign Embed Licence. © 2026 Sagar Saini. https://getv.design/docs/licence/ */
|
|
2
|
+
import{a as y}from"./chunks/chunk-BBJ6N4ZS.js";import"./chunks/chunk-Q6QQ2HGJ.js";var d=["view","edit","play"];async function l(a,i,e){let o=e?.mode;if(!d.includes(o))throw new TypeError(`mount: mode must be one of ${d.join(", ")}; got ${String(o)}.`);if(o==="edit"){let{edit:t}=await import("./edit.js");return t(a,i,e)}let{view:s}=await import("./view.js"),n=await s(a,i,e);if(o==="view")return n;let r;try{r=await n.play(e.page===void 0?{}:{page:e.page})}catch(t){throw n.destroy(),t}return{goTo:t=>r.goTo(t),destroy(){r.destroy(),n.destroy()}}}export{l as mount,y as version};
|
package/dist/static.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ParseResult, RenderSvgOptions, Source } from './types.js';
|
|
2
|
+
export type { ParseResult, Problem, RenderSvgOptions, Source, VdDocument } from './types.js';
|
|
3
|
+
export { version } from './version.js';
|
|
4
|
+
/** Read `.vd` text. Never throws: what is wrong comes back as `problems`. */
|
|
5
|
+
export declare function parse(text: string): ParseResult;
|
|
6
|
+
/** Draw a document, or one of its pages, as a standalone SVG. */
|
|
7
|
+
export declare function renderSvg(source: Source, options?: RenderSvgOptions): Promise<string>;
|
package/dist/static.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! @getv.design/embed v0.1.1. Free to use under the vDesign Embed Licence. © 2026 Sagar Saini. https://getv.design/docs/licence/ */
|
|
2
|
+
import{a as g,c as h,e as b,f as v,g as f}from"./chunks/chunk-2H24PH2F.js";import{a as P,b as l}from"./chunks/chunk-BBJ6N4ZS.js";import{j as d,x as m}from"./chunks/chunk-QFL2QGB3.js";import"./chunks/chunk-Q6QQ2HGJ.js";function A(e){return g(e)}async function F(e,t={}){let o=t.fonts??"approximate";if(!S.includes(o))throw new TypeError(`renderSvg: fonts must be one of ${S.join(", ")}; got ${String(o)}.`);let n=o==="exact"?v(t.fontBase,w()):void 0,{document:c,blocks:x,problems:y}=await h(e),u=t.page===void 0?c:O(c,t.page),p=s=>{let r=x.get(s.hash);return r===void 0?void 0:d(s.type,r)},i=[...y],a;if(o==="exact")if(n===void 0)i.push(f([],"no fontBase was given and this build has no default"));else{let{exactSvg:s}=await import("./chunks/fonts.js"),r=await s(u,{base:n,resolveAsset:p});"svg"in r?a=r.svg:i.push(f(r.failures))}return a??=m(u,{ids:!1,resolveAsset:p}),t.onProblems?.(i),a}var S=["approximate","exact"];function w(){let e=import.meta.url,o=typeof globalThis.process?.getBuiltinModule=="function";return e.startsWith("file:")&&o?new URL("../fonts/",e).href:l}function O(e,t){let o=b(e,t);return{...e,root:{...e.root,children:e.root.children.map(n=>n===o?n:{...n,hidden:!0})}}}export{A as parse,F as renderSvg,P as version};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embed's public types, and the only ones it publishes.
|
|
3
|
+
*
|
|
4
|
+
* Everything a host sees is declared here rather than re-exported from the
|
|
5
|
+
* workspaces it bundles, so the published `.d.ts` files name nothing internal:
|
|
6
|
+
* `build.test.ts` fails if any declaration under `out/dist` mentions one of
|
|
7
|
+
* their package names, comments included. That is what lets the workspaces
|
|
8
|
+
* change shape without the package's API changing with them, and it is why the
|
|
9
|
+
* document is an opaque branded type rather than the core's `VDocument`.
|
|
10
|
+
*
|
|
11
|
+
* Plan: docs/embed-and-docs.md §1.1. Still 0.x: the shape may change before
|
|
12
|
+
* the first release.
|
|
13
|
+
*/
|
|
14
|
+
declare const vdDocument: unique symbol;
|
|
15
|
+
/** A parsed document. Opaque: pass it back to any function that takes a `Source`. */
|
|
16
|
+
export interface VdDocument {
|
|
17
|
+
readonly [vdDocument]: true;
|
|
18
|
+
}
|
|
19
|
+
/** What a document can be given as: `.vd` text, a URL to fetch, a file, or a parsed document. */
|
|
20
|
+
export type Source = string | URL | Blob | VdDocument;
|
|
21
|
+
/** Something wrong with a document. Reading never throws; it reports these instead. */
|
|
22
|
+
export interface Problem {
|
|
23
|
+
/** The 1-based line in the `.vd` text, when the problem belongs to one. */
|
|
24
|
+
line?: number;
|
|
25
|
+
/** Stable and machine-readable; branch on this, not on `message`. */
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
severity: 'error' | 'warning';
|
|
29
|
+
}
|
|
30
|
+
export interface ParseResult {
|
|
31
|
+
document: VdDocument;
|
|
32
|
+
problems: Problem[];
|
|
33
|
+
}
|
|
34
|
+
export interface RenderSvgOptions {
|
|
35
|
+
/**
|
|
36
|
+
* One page to draw: its id, or its 0-based index among the pages. Omitted,
|
|
37
|
+
* the whole document is drawn.
|
|
38
|
+
*/
|
|
39
|
+
page?: string | number;
|
|
40
|
+
/**
|
|
41
|
+
* How text is measured. `'approximate'` (the default) needs no font files and
|
|
42
|
+
* runs anywhere; line breaks can differ slightly from the app's. `'exact'`
|
|
43
|
+
* lays text out from the font files the app's exports use, so lines break
|
|
44
|
+
* where theirs do: in Node they are read from the package's own `fonts/`
|
|
45
|
+
* folder, in a browser fetched from `fontBase`. If a face cannot be had, the
|
|
46
|
+
* drawing is approximate and `onProblems` hears a `fonts-unavailable`
|
|
47
|
+
* warning; it does not reject.
|
|
48
|
+
*/
|
|
49
|
+
fonts?: 'exact' | 'approximate';
|
|
50
|
+
/**
|
|
51
|
+
* The folder `'exact'` reads the faces from (`Inter-Regular.woff2` and so
|
|
52
|
+
* on): a URL, or a path resolved against the page. Default: in Node, the
|
|
53
|
+
* package's own `fonts/`; in a browser, the package's `fonts/` on jsDelivr.
|
|
54
|
+
*/
|
|
55
|
+
fontBase?: string | URL;
|
|
56
|
+
/**
|
|
57
|
+
* Called once, before the SVG is returned, with what is wrong: the
|
|
58
|
+
* document's own problems and, under `'exact'`, any face that would not
|
|
59
|
+
* load. Empty when nothing is.
|
|
60
|
+
*/
|
|
61
|
+
onProblems?: (problems: Problem[]) => void;
|
|
62
|
+
}
|
|
63
|
+
export interface ViewOptions {
|
|
64
|
+
/**
|
|
65
|
+
* What the camera shows. `'page'` (the default) fits the current page to the
|
|
66
|
+
* element; `'content'` fits everything; `'none'` leaves the camera at 100%.
|
|
67
|
+
* Applied on mount, by `fit()`, when the element is resized, and, for
|
|
68
|
+
* `'page'`, by `goTo()`; under the other two, `goTo()` centres the page at
|
|
69
|
+
* the current zoom.
|
|
70
|
+
*/
|
|
71
|
+
fit?: 'page' | 'content' | 'none';
|
|
72
|
+
/**
|
|
73
|
+
* The page to start on: its id, or its 0-based index among the pages. A
|
|
74
|
+
* page is a top-level frame that is not hidden, counted as `renderSvg` and
|
|
75
|
+
* the app's exports count them.
|
|
76
|
+
*/
|
|
77
|
+
page?: number | string;
|
|
78
|
+
/**
|
|
79
|
+
* Ctrl or ⌘ with the wheel (or a trackpad pinch) zooms; middle-drag or
|
|
80
|
+
* Space-drag pans. A plain wheel is left to the page, so the reader's scroll
|
|
81
|
+
* is never caught by the view. `false` turns all of it off. Default `true`.
|
|
82
|
+
*/
|
|
83
|
+
interactive?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* How text is measured. `'browser'` uses the page's own fonts. `'exact'`,
|
|
86
|
+
* the default, lays text out from the font files the app and its exports
|
|
87
|
+
* use, so lines break where theirs do: the view draws at once with the
|
|
88
|
+
* page's fonts, fetches only the faces the document uses, then lays the text
|
|
89
|
+
* out again once, when they arrive. If a face cannot be fetched the view
|
|
90
|
+
* stays on the page's fonts, `problems` gains a `fonts-unavailable` warning,
|
|
91
|
+
* and the `fonts` event says `'browser'`.
|
|
92
|
+
*/
|
|
93
|
+
fonts?: 'exact' | 'browser';
|
|
94
|
+
/**
|
|
95
|
+
* The folder `'exact'` fetches faces from (`Inter-Regular.woff2` and so on):
|
|
96
|
+
* a URL, or a path resolved against the page. Default: the package's
|
|
97
|
+
* `fonts/` on jsDelivr, which means the reader's browser asks jsDelivr for
|
|
98
|
+
* them. To keep that request on your own origin, serve the package's
|
|
99
|
+
* `fonts/` folder yourself and point this at it.
|
|
100
|
+
*/
|
|
101
|
+
fontBase?: string | URL;
|
|
102
|
+
/** The colour behind the pages. */
|
|
103
|
+
surface?: string;
|
|
104
|
+
/**
|
|
105
|
+
* A click on an `https:` or `mailto:` link in the document. Without it the
|
|
106
|
+
* link opens in a new tab. A `#page` link goes to that page either way.
|
|
107
|
+
*/
|
|
108
|
+
onLink?: (href: string) => void;
|
|
109
|
+
}
|
|
110
|
+
export interface PageInfo {
|
|
111
|
+
id: string;
|
|
112
|
+
name?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* `ready` and `problems` describe the document on screen, so a listener added
|
|
116
|
+
* late is told the current state at once. One added in the same tick as a
|
|
117
|
+
* `load()` can therefore hear `ready` and `problems` twice: once from that
|
|
118
|
+
* replay and once when the load lands.
|
|
119
|
+
*/
|
|
120
|
+
export interface ViewEvents {
|
|
121
|
+
/**
|
|
122
|
+
* A document is drawn: the first, and each one `load()` brings. A listener
|
|
123
|
+
* added after that is called once straight away.
|
|
124
|
+
*/
|
|
125
|
+
ready: () => void;
|
|
126
|
+
/**
|
|
127
|
+
* What is wrong with the document on screen, empty when nothing is; again
|
|
128
|
+
* after every `load()`. A listener added later is called with the current
|
|
129
|
+
* list straight away.
|
|
130
|
+
*/
|
|
131
|
+
problems: (problems: Problem[]) => void;
|
|
132
|
+
/** The current page changed. Not replayed. */
|
|
133
|
+
page: (page: PageInfo) => void;
|
|
134
|
+
/**
|
|
135
|
+
* What text is measured with, once that is settled: `'exact'` when the font
|
|
136
|
+
* files are in use, `'browser'` under `fonts: 'browser'` or when they could
|
|
137
|
+
* not be fetched. Fires when that is settled, and again if a later `load()`
|
|
138
|
+
* needs a face that cannot be fetched; a listener added later is told the
|
|
139
|
+
* current answer at once.
|
|
140
|
+
*/
|
|
141
|
+
fonts: (fonts: 'exact' | 'browser') => void;
|
|
142
|
+
}
|
|
143
|
+
export interface PlayOptions {
|
|
144
|
+
/** The page to start on. Default: the one the view is showing. */
|
|
145
|
+
page?: number | string;
|
|
146
|
+
}
|
|
147
|
+
export interface PlayHandle {
|
|
148
|
+
goTo(page: number | string): void;
|
|
149
|
+
/** Stop presenting. Escape does the same. */
|
|
150
|
+
destroy(): void;
|
|
151
|
+
}
|
|
152
|
+
export interface ViewHandle {
|
|
153
|
+
/**
|
|
154
|
+
* Show another document, or a new version of this one, in place: what is
|
|
155
|
+
* unchanged is not redrawn. The page on screen and the camera stay while
|
|
156
|
+
* that page is still there. Rejects, leaving the view as it was, if the
|
|
157
|
+
* source cannot be read. When loads overlap, the last one called wins: an
|
|
158
|
+
* earlier one that finishes later resolves without drawing.
|
|
159
|
+
*/
|
|
160
|
+
load(source: Source): Promise<void>;
|
|
161
|
+
pages(): PageInfo[];
|
|
162
|
+
/** Throws a `RangeError` for a page that is not there. */
|
|
163
|
+
goTo(page: number | string): void;
|
|
164
|
+
/** Apply the `fit` option again, for an element resized without the browser noticing. */
|
|
165
|
+
fit(): void;
|
|
166
|
+
/** Present over the view, one page at a time; Escape comes back. */
|
|
167
|
+
play(options?: PlayOptions): Promise<PlayHandle>;
|
|
168
|
+
/**
|
|
169
|
+
* Edit what is on screen, in place: the editor replaces the view in the same
|
|
170
|
+
* element, where the person was looking, and this handle is destroyed. The
|
|
171
|
+
* editor's code loads only now. `options` override the view's own. Rejects,
|
|
172
|
+
* leaving the view as it was (a presentation and a `load()` in flight
|
|
173
|
+
* included), if the editor cannot open, and rejects a second call made while
|
|
174
|
+
* one is opening. A `load()` that lands while the editor opens is dropped
|
|
175
|
+
* once it has: the editor shows the document from when `edit()` was called.
|
|
176
|
+
*/
|
|
177
|
+
edit(options?: EditOptions): Promise<EditHandle>;
|
|
178
|
+
/** Throws a `TypeError` for an event that is not one of these. */
|
|
179
|
+
on<E extends keyof ViewEvents>(event: E, callback: ViewEvents[E]): () => void;
|
|
180
|
+
/** Take the view away, leaving the element empty, and release its image URLs. */
|
|
181
|
+
destroy(): void;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* As for a view, with these differences: a link is followed on ⌘-click (Ctrl
|
|
185
|
+
* elsewhere), since a plain click selects; `fit` frames the document once,
|
|
186
|
+
* and again on a resize only until the person moves the camera.
|
|
187
|
+
*/
|
|
188
|
+
export interface EditOptions extends ViewOptions {
|
|
189
|
+
/** The floating toolbar and the context menu. Default `true`. */
|
|
190
|
+
toolbar?: boolean;
|
|
191
|
+
}
|
|
192
|
+
export interface ChangeEvent {
|
|
193
|
+
/** The whole `.vd` file after the change, as `getText()`; composed only when called. */
|
|
194
|
+
text(): string;
|
|
195
|
+
}
|
|
196
|
+
export interface EditHandle {
|
|
197
|
+
/** The whole `.vd` file: the design and its images. */
|
|
198
|
+
getText(): string;
|
|
199
|
+
/** The document as it stands, to pass to `renderSvg`, `view()` or `load()`. */
|
|
200
|
+
getDocument(): VdDocument;
|
|
201
|
+
/**
|
|
202
|
+
* One `change` per undo step: a whole drag is one, on pointerup, and so are
|
|
203
|
+
* an undo and a redo. Throws a `TypeError` for any other event.
|
|
204
|
+
*/
|
|
205
|
+
on(event: 'change', callback: (event: ChangeEvent) => void): () => void;
|
|
206
|
+
undo(): void;
|
|
207
|
+
redo(): void;
|
|
208
|
+
/**
|
|
209
|
+
* Back to a view of the document as edited, in the same element, keeping
|
|
210
|
+
* the camera; this handle is destroyed. Rejects, leaving the editor, if the
|
|
211
|
+
* view cannot open, and rejects a second call made while one is opening. The
|
|
212
|
+
* canvas takes no input meanwhile; a change that still lands (an `undo()`)
|
|
213
|
+
* is shown by the view.
|
|
214
|
+
*/
|
|
215
|
+
view(): Promise<ViewHandle>;
|
|
216
|
+
/** Take the editor away, leaving the element empty. Safe to call twice. */
|
|
217
|
+
destroy(): void;
|
|
218
|
+
}
|
|
219
|
+
export type MountMode = 'view' | 'edit' | 'play';
|
|
220
|
+
export type MountOptions = {
|
|
221
|
+
mode: MountMode;
|
|
222
|
+
} & EditOptions;
|
|
223
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The package's version, as published: `0.1.0`, say. */
|
|
2
|
+
export declare const version: string;
|
|
3
|
+
/**
|
|
4
|
+
* `https://cdn.jsdelivr.net/npm/<publishName>@<version>/fonts/`: the copy of
|
|
5
|
+
* `fonts/` npm publishes, served by jsDelivr (plan D5). A host that would
|
|
6
|
+
* rather its readers did not ask a third party sets `fontBase` instead.
|
|
7
|
+
*/
|
|
8
|
+
export declare const defaultFontBase: string | undefined;
|
package/dist/view.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Source, ViewHandle, ViewOptions } from './types.js';
|
|
2
|
+
export type * from './types.js';
|
|
3
|
+
export { version } from './version.js';
|
|
4
|
+
/** Show a document in `el`. Rejects, leaving `el` untouched, if the source cannot be read. */
|
|
5
|
+
export declare function view(el: HTMLElement, source: Source, options?: ViewOptions): Promise<ViewHandle>;
|
package/dist/view.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*! @getv.design/embed v0.1.1. Free to use under the vDesign Embed Licence. © 2026 Sagar Saini. https://getv.design/docs/licence/ */
|
|
2
|
+
import{b as Qe,c as Ae,d as ee,e as ue,f as et,g as ye}from"./chunks/chunk-2H24PH2F.js";import{a as Ft,b as Re}from"./chunks/chunk-BBJ6N4ZS.js";import{a as Ve,b as $e,c as ge,d as Se,e as He,f as Be,g as je,h as Ue,j as We,k as Ke,m as Ee,n as me,o as Ge,p as ke,s as Ye,t as Ze,u as qe,v as Xe,w as Je}from"./chunks/chunk-QFL2QGB3.js";import"./chunks/chunk-Q6QQ2HGJ.js";var It=.8,Nt=.2;function Oe(e,t){let i=e.createElement("canvas").getContext("2d"),n=Ge(),l=new Map,c=new Map,m=new Set;function u(f){return`${f.italic?"italic ":""}${f.weight} ${f.size}px ${f.family}`}function y(){l.clear(),c.clear()}return{advance(f,p){if(!i)return n.advance(f,p);let A=u(p),S=`${A}\0${p.letterSpacing}\0${f}`,E=l.get(S);if(E!==void 0)return E;i.font=A;let x=i.measureText(f).width+p.letterSpacing*[...f].length;return l.set(S,x),x},metrics(f){if(!i)return n.metrics(f);let p=u(f),A=c.get(p);if(A)return A;i.font=p;let S=i.measureText("Hxg"),E=S.fontBoundingBoxAscent??f.size*It,x=S.fontBoundingBoxDescent??f.size*Nt,C={ascent:E,descent:x,lineGap:0};return c.set(p,C),C},load(f,p){let A=e.fonts;if(!A||typeof FontFace!="function")return!1;let S=!1;for(let E of Object.values(f.fonts))for(let x of zt(E)){let C=`${E.family}\0${x.src}\0${x.weight??400}\0${x.style??"normal"}`;if(m.has(C))continue;m.add(C);let O=x.src.startsWith("data:")?void 0:p?.(x.src),_={weight:String(x.weight??400),style:x.style??"normal"},N=$=>{let P=new FontFace(E.family,typeof $=="string"?`url(${$})`:Rt($),_);A.add(P),P.load().then(()=>{y(),t?.()},()=>{A.delete(P)})};O===void 0?N(x.src):(S=!0,O.then(N,()=>{}))}return S},invalidate:y,destroy(){y(),m.clear()}}}function zt(e){return e.faces??[]}function Rt(e){return e instanceof Uint8Array?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):e}var we={x:0,y:0,zoom:1},tt=.02,nt=64;function Me(e){return Number.isFinite(e)?Math.min(Math.max(e,tt),nt):1}function ve(e,t){return{x:(t.x-e.x)/e.zoom,y:(t.y-e.y)/e.zoom}}function Te(e,t){return{x:t.x*e.zoom+e.x,y:t.y*e.zoom+e.y}}function xe(e,t,r){let i=Me(e.zoom*r),n=ve(e,t);return{zoom:i,x:t.x-n.x*i,y:t.y-n.y*i}}function fe(e,t,r){return{...e,x:e.x+t,y:e.y+r}}function _e(e){return`translate(${e.x} ${e.y}) scale(${e.zoom})`}function oe(e,t,r){let i={width:Math.max(1,t.width-r*2),height:Math.max(1,t.height-r*2)};if(e.width<=0||e.height<=0)return we;let n=Me(Math.min(i.width/e.width,i.height/e.height));return{zoom:n,x:(t.width-e.width*n)/2-(e.x??0)*n,y:(t.height-e.height*n)/2-(e.y??0)*n}}var j="http://www.w3.org/2000/svg",rt="vd-viewer-styles",it=`
|
|
3
|
+
.vd-viewer {
|
|
4
|
+
position: relative;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
touch-action: none;
|
|
7
|
+
user-select: none;
|
|
8
|
+
background: var(--vd-surface, #1b1b1f);
|
|
9
|
+
}
|
|
10
|
+
.vd-viewer__surface {
|
|
11
|
+
display: block;
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
/* Text was measured against real faces; a synthesised bold or slant is not
|
|
15
|
+
one of them, and would draw wider or narrower than it was laid out. */
|
|
16
|
+
font-synthesis: none;
|
|
17
|
+
}
|
|
18
|
+
/* Every space layout measured, drawn. \`xml:space="preserve"\` is also set, but
|
|
19
|
+
Chromium ignores it when set through setAttribute rather than parsed from
|
|
20
|
+
markup, and collapsed double spaces shifted the rest of the line. */
|
|
21
|
+
.vd-viewer__surface text {
|
|
22
|
+
white-space: pre;
|
|
23
|
+
}
|
|
24
|
+
.vd-viewer__camera {
|
|
25
|
+
/* Hints the compositor that this subtree is about to be transformed. */
|
|
26
|
+
will-change: transform;
|
|
27
|
+
}
|
|
28
|
+
.vd-viewer__page {
|
|
29
|
+
/* An embedder with a no-shadow brand sets --vd-page-shadow: none. */
|
|
30
|
+
filter: var(--vd-page-shadow, drop-shadow(0 6px 24px rgb(0 0 0 / 0.35)));
|
|
31
|
+
}
|
|
32
|
+
/* An asset whose bytes are not here. Visible, and obviously not a design choice. */
|
|
33
|
+
.vd-viewer__missing {
|
|
34
|
+
fill: none;
|
|
35
|
+
stroke: #94a3b8;
|
|
36
|
+
stroke-width: 1;
|
|
37
|
+
stroke-dasharray: 4 4;
|
|
38
|
+
}
|
|
39
|
+
/* The player: black around the slide, and nothing else on screen. */
|
|
40
|
+
.vd-player {
|
|
41
|
+
outline: none;
|
|
42
|
+
cursor: default;
|
|
43
|
+
}
|
|
44
|
+
/* A button or a link under the pointer. Before idle, which wins when both apply. */
|
|
45
|
+
.vd-player--link {
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
}
|
|
48
|
+
.vd-player--idle {
|
|
49
|
+
cursor: none;
|
|
50
|
+
}
|
|
51
|
+
/* Positioned, so a transition's still of the page being left can go under or
|
|
52
|
+
over it by document order alone. */
|
|
53
|
+
.vd-player .vd-viewer__surface {
|
|
54
|
+
position: relative;
|
|
55
|
+
}
|
|
56
|
+
/* The page being left, frozen for a transition. Opaque, or the new page would
|
|
57
|
+
show through it. More specific than the rule above, which it also matches. */
|
|
58
|
+
.vd-player .vd-player__still {
|
|
59
|
+
position: absolute;
|
|
60
|
+
inset: 0;
|
|
61
|
+
background: #000;
|
|
62
|
+
pointer-events: none;
|
|
63
|
+
}
|
|
64
|
+
/* Not on screen yet, or gone already: what motion is holding back. */
|
|
65
|
+
.vd-player [data-vd-hidden] {
|
|
66
|
+
visibility: hidden;
|
|
67
|
+
}
|
|
68
|
+
.vd-player .vd-viewer__page {
|
|
69
|
+
filter: none;
|
|
70
|
+
}
|
|
71
|
+
.vd-player__mask {
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
}
|
|
74
|
+
.vd-player__counter {
|
|
75
|
+
position: absolute;
|
|
76
|
+
right: 16px;
|
|
77
|
+
bottom: 16px;
|
|
78
|
+
padding: 4px 10px;
|
|
79
|
+
border-radius: 8px;
|
|
80
|
+
background: rgb(0 0 0 / 0.6);
|
|
81
|
+
color: #fff;
|
|
82
|
+
font: 500 12px/1.4 system-ui, sans-serif;
|
|
83
|
+
font-variant-numeric: tabular-nums;
|
|
84
|
+
opacity: 0;
|
|
85
|
+
transition: opacity 200ms;
|
|
86
|
+
pointer-events: none;
|
|
87
|
+
}
|
|
88
|
+
.vd-player__counter--shown {
|
|
89
|
+
opacity: 1;
|
|
90
|
+
}
|
|
91
|
+
@media (prefers-reduced-motion: reduce) {
|
|
92
|
+
.vd-player__counter {
|
|
93
|
+
transition: none;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/* Blur filters re-rasterise at every scale; drop it while the camera moves. */
|
|
97
|
+
.vd-viewer--interacting .vd-viewer__page {
|
|
98
|
+
filter: none;
|
|
99
|
+
}
|
|
100
|
+
`;function ot(e){if(e.getElementById(rt))return;let t=e.createElement("style");t.id=rt,t.textContent=it,e.head.appendChild(t)}function at(e,t,r,i){return t?$t(e,t,r,i):Vt(e,r,i)}function Vt(e,t,r){let i=Oe(e,r);return{measurer:i,update:n=>{i.load(n,t)},afterPaint:()=>{},destroy:()=>i.destroy()}}var st=new WeakMap;function $t(e,t,r,i){let n,l,c,m=()=>{if(!n)throw new Error("canvasFonts: update() before measuring");return n};return{measurer:{advance:(y,f)=>m().measurer.advance(y,f),metrics:y=>m().measurer.metrics(y),itemize:y=>m().measurer.itemize(y)},update(y){n&&y.fonts===l||(c?.(),n?.dispose(),n=t.forDocument(y,r?{loader:r}:{}),l=y.fonts,c=n.onChange(i))},afterPaint(){let y=e.fonts;if(!n||!y||typeof FontFace!="function")return;let f=st.get(e);f||st.set(e,f=new Set);for(let p of n.usedFaces()){if(f.has(p.id))continue;f.add(p.id);let A=new FontFace(p.id,Ht(p.bytes),{weight:String(p.weight),style:p.style});y.add(A),A.load().catch(()=>y.delete(A))}},destroy(){c?.(),n?.dispose(),n=void 0}}}function Ht(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}var Bt=.01,jt=.004,ct=40,Ut=16;function le(e,t){ot(e.ownerDocument);let r=t.document,i=a=>at(e.ownerDocument,a,t.loadFont,()=>{$(r)}),n=i(t.fonts),l={advance:(a,v)=>n.measurer.advance(a,v),metrics:a=>n.measurer.metrics(a),itemize:a=>n.measurer.itemize?.(a)??[a]};n.update(r);let c=me(r),m=()=>t.resolveAsset?{measure:l,resolveAsset:t.resolveAsset}:{measure:l},u=ke(r,c,m()),y=t.camera??we,f=t.interactive??!0,p=t.wheel??"always";e.classList.add("vd-viewer"),t.surface&&(e.style.background=t.surface);let A=e.ownerDocument.createElementNS(j,"svg");A.setAttribute("class","vd-viewer__surface"),A.setAttribute("width","100%"),A.setAttribute("height","100%");let S=e.ownerDocument.createElementNS(j,"g");S.setAttribute("class","vd-viewer__camera"),S.style.isolation="isolate",A.appendChild(S);let E=e.ownerDocument.createElementNS(j,"defs");S.appendChild(E);let x=e.ownerDocument.createElementNS(j,"rect");x.setAttribute("class","vd-viewer__page"),S.appendChild(x),e.appendChild(A);let C=new Map;function O(){S.setAttribute("transform",_e(y))}function _(){N();let a=u.background!==void 0;x.setAttribute("x",String(u.x)),x.setAttribute("y",String(u.y)),x.setAttribute("width",String(a?u.width:0)),x.setAttribute("height",String(a?u.height:0)),D(x,"fill",u.background??null);let v=new Set,M=x;for(let w of u.items){v.add(w.id);let L=C.get(w.id);(!L||L.tagName!==dt(w))&&(L?.remove(),L=e.ownerDocument.createElementNS(j,dt(w)),L.setAttribute("data-vd-id",w.id),C.set(w.id,L)),Kt(L,w),M.nextSibling!==L&&S.insertBefore(L,M.nextSibling),M=L}for(let[w,L]of C)v.has(w)||(L.remove(),C.delete(w));n.afterPaint(),t.onSceneChange?.(u,r)}function N(){E.replaceChildren();let a=u.items.filter(v=>v.shadows.length>0);if(u.gradients.length>0||a.length>0){let v=`<svg xmlns="${j}">${u.gradients.map(Ye).join("")}${a.map(w=>qe(w)).join("")}</svg>`,M=new DOMParser().parseFromString(v,"image/svg+xml");for(let w of[...M.documentElement.children])E.appendChild(e.ownerDocument.importNode(w,!0))}for(let v of u.clips){let M=e.ownerDocument.createElementNS(j,"clipPath");M.setAttribute("id",ft(v.id)),v.parent!==void 0&&M.setAttribute("clip-path",Pe(v.parent));let w=e.ownerDocument.createElementNS(j,"rect");w.setAttribute("x",String(v.x)),w.setAttribute("y",String(v.y)),w.setAttribute("width",String(v.w)),w.setAttribute("height",String(v.h)),M.appendChild(w),E.appendChild(M)}}function $(a){r=a,n.update(r),c=me(r),u=ke(r,c,m()),_()}function P(a){let v=e.getBoundingClientRect();return{x:a.clientX-v.left,y:a.clientY-v.top}}let F=0,I=0;function U(){e.classList.add("vd-viewer--interacting"),I&&clearTimeout(I),I=setTimeout(()=>{I=0,e.classList.remove("vd-viewer--interacting")},180)}function K(){F&&(cancelAnimationFrame(F),F=0),O(),t.onCameraChange?.(y)}function z(a){y=a,K()}function q(a){y=a,U(),!F&&(F=requestAnimationFrame(()=>{F=0,O(),t.onCameraChange?.(y)}))}let X=null,W=null,B=!1,te=a=>{if(p==="modifier"&&!a.ctrlKey&&!a.metaKey)return;a.preventDefault();let v=P(a),M=a.deltaMode===1?Ut:a.deltaMode===2?e.clientHeight||800:1,w=a.deltaX*M,L=a.deltaY*M;if(a.ctrlKey||a.metaKey){let s=a.ctrlKey?Bt:jt,d=Math.max(-ct,Math.min(ct,L));q(xe(y,v,Math.exp(-d*s)));return}if(a.shiftKey&&w===0){q(fe(y,-L,0));return}q(fe(y,-w,-L))},Z=a=>{(a.button===1||a.button===0&&B)&&(a.preventDefault(),X=a.pointerId,W=P(a),e.setPointerCapture(a.pointerId))},J=a=>{if(X!==a.pointerId||!W)return;let v=P(a);q(fe(y,v.x-W.x,v.y-W.y)),W=v},H=a=>{X===a.pointerId&&(X=null,W=null,e.hasPointerCapture(a.pointerId)&&e.releasePointerCapture(a.pointerId))},Q=a=>{a.code==="Space"&&(B=!0)},G=a=>{a.code==="Space"&&(B=!1)};f&&(e.addEventListener("wheel",te,{passive:!1}),e.addEventListener("pointerdown",Z),e.addEventListener("pointermove",J),e.addEventListener("pointerup",H),e.addEventListener("pointercancel",H),e.ownerDocument.addEventListener("keydown",Q),e.ownerDocument.addEventListener("keyup",G)),O(),_();let ne={element:e,surface:A,update:$,getDocument:()=>r,getScene:()=>u,getResolution:()=>c,getMeasurer:()=>l,setFonts(a){n.destroy(),n=i(a),$(r)},getCamera:()=>y,setCamera:z,zoomBy(a,v){let M=e.getBoundingClientRect(),w=v??{x:M.width/2,y:M.height/2};z(xe(y,w,a))},fitToContent(a=32){let v=e.getBoundingClientRect();z(oe({x:u.x,y:u.y,width:u.width,height:u.height},{width:v.width||u.width,height:v.height||u.height},a))},screenToDocument:a=>ve(y,a),documentToScreen:a=>Te(y,a),pointerPoint:P,hitTest(a,v){for(let M=u.items.length-1;M>=0;M--){let w=u.items[M];if(w&&tn(w,a,en/y.zoom)&&(!v||v(w.id)))return w.id}return null},linkAt(a,v){for(let M=u.items.length-1;M>=0;M--){let w=u.items[M];if(w?.kind!=="text"||v&&!v(w.id))continue;let L=w.rotation===0?a:Ee(a,{x:w.x+w.w/2,y:w.y+w.h/2},-w.rotation);for(let s of w.lines){if(L.y<s.y||L.y>s.y+s.h)continue;let d=s.spans.find(o=>L.x>=o.x&&L.x<=o.x+o.w);if(d)return d.style.link}}},itemOf:a=>u.items.find(v=>v.id===a),elementOf:a=>C.get(a),destroy(){f&&(e.removeEventListener("wheel",te),e.removeEventListener("pointerdown",Z),e.removeEventListener("pointermove",J),e.removeEventListener("pointerup",H),e.removeEventListener("pointercancel",H),e.ownerDocument.removeEventListener("keydown",Q),e.ownerDocument.removeEventListener("keyup",G)),F&&cancelAnimationFrame(F),I&&clearTimeout(I),F=0,I=0,n.destroy(),e.classList.remove("vd-viewer--interacting"),A.remove(),C.clear(),e.classList.remove("vd-viewer")}};return t.autoFit&&ne.fitToContent(),ne}var Wt="vd-clip-";function ft(e){return Wt+e}function Pe(e){return`url(#${ft(e)})`}function dt(e){return Je(e)?"g":Le(e)}function Le(e){switch(e.kind){case"ellipse":return"ellipse";case"frame":return"rect";case"image":return e.href===void 0?"rect":"image";case"rect":return"rect";case"text":return"text";case"vector":return"path"}}function Kt(e,t){if(e.tagName!=="g"){ut(e,t);return}D(e,"clip-path",t.clip===void 0?null:Pe(t.clip)),e.style.mixBlendMode=t.blend==="normal"?"":t.blend;let r=e.firstElementChild;(!r||r.tagName!==Le(t))&&(r?.remove(),r=e.ownerDocument.createElementNS(j,Le(t)),e.appendChild(r)),ut(r,{...t,clip:void 0,blend:"normal"})}function ut(e,t){switch(D(e,"clip-path",t.clip===void 0?null:Pe(t.clip)),D(e,"transform",t.rotation===0?null:Xe(t)),e.style.mixBlendMode=t.blend==="normal"?"":t.blend,e.style.filter=t.shadows.length>0?`url(#${Ze}${t.id})`:"",t.kind){case"ellipse":Jt(e,t);return;case"frame":Gt(e,t);return;case"image":Yt(e,t);return;case"rect":Xt(e,t);return;case"text":qt(e,t);return;case"vector":Qt(e,t);return}}function Gt(e,t){e.setAttribute("class","vd-viewer__page"),e.setAttribute("x",String(t.x)),e.setAttribute("y",String(t.y)),e.setAttribute("width",String(t.w)),e.setAttribute("height",String(t.h)),D(e,"fill",t.background??null)}function Yt(e,t){if(e.setAttribute("x",String(t.x)),e.setAttribute("y",String(t.y)),e.setAttribute("width",String(t.w)),e.setAttribute("height",String(t.h)),D(e,"opacity",t.opacity<1?String(t.opacity):null),t.href===void 0){e.setAttribute("class","vd-viewer__missing"),D(e,"rx",t.radius>0?String(t.radius):null);return}e.setAttribute("href",t.href),e.setAttribute("preserveAspectRatio",Zt[t.fit])}var Zt={cover:"xMidYMid slice",contain:"xMidYMid meet",fill:"none"};function qt(e,t){D(e,"opacity",t.opacity<1?String(t.opacity):null),e.setAttribute("xml:space","preserve");let r=t.lines.flatMap(n=>n.spans).filter(n=>n.text!==""),i=e.ownerDocument;for(;e.childNodes.length>r.length;)e.lastChild?.remove();for(;e.childNodes.length<r.length;)e.appendChild(i.createElementNS(j,"tspan"));r.forEach((n,l)=>{let c=e.childNodes[l];c.textContent=n.text,c.setAttribute("x",String(n.x)),c.setAttribute("y",String(n.y)),c.setAttribute("font-family",n.style.family),c.setAttribute("font-size",String(n.style.size)),c.setAttribute("fill",n.style.fill),D(c,"font-weight",n.style.weight===400?null:String(n.style.weight)),D(c,"font-style",n.style.italic?"italic":null),D(c,"letter-spacing",n.style.letterSpacing===0?null:String(n.style.letterSpacing)),D(c,"data-vd-link",n.style.link??null);let m=[n.style.underline?"underline":"",n.style.strike?"line-through":""].filter(Boolean).join(" ");D(c,"text-decoration",m===""?null:m)})}function Xt(e,t){e.removeAttribute("class"),e.setAttribute("x",String(t.x)),e.setAttribute("y",String(t.y)),e.setAttribute("width",String(t.w)),e.setAttribute("height",String(t.h)),e.setAttribute("fill",t.fill),D(e,"rx",t.radius>0?String(t.radius):null),D(e,"stroke",t.stroke??null),D(e,"stroke-width",t.stroke&&t.strokeWidth>0?String(t.strokeWidth):null),D(e,"opacity",t.opacity<1?String(t.opacity):null)}function lt(e,t){e.setAttribute("fill",t.fill),D(e,"stroke",t.stroke??null),D(e,"stroke-width",t.stroke&&t.strokeWidth>0?String(t.strokeWidth):null),D(e,"opacity",t.opacity<1?String(t.opacity):null)}function Jt(e,t){e.setAttribute("cx",String(t.x+t.w/2)),e.setAttribute("cy",String(t.y+t.h/2)),e.setAttribute("rx",String(t.w/2)),e.setAttribute("ry",String(t.h/2)),lt(e,t)}function Qt(e,t){e.setAttribute("d",t.d),lt(e,t),D(e,"fill-rule",t.rule==="nonzero"?null:t.rule),D(e,"stroke-linecap",t.cap==="butt"?null:t.cap),D(e,"stroke-linejoin",t.join==="miter"?null:t.join)}function D(e,t,r){r===null?e.removeAttribute(t):e.setAttribute(t,r)}var en=4;function tn(e,t,r){let i=e.rotation===0?t:Ee(t,{x:e.x+e.w/2,y:e.y+e.h/2},-e.rotation),n=i.x>=e.x&&i.x<=e.x+e.w&&i.y>=e.y&&i.y<=e.y+e.h;if(e.kind==="ellipse"){let l=e.stroke!==void 0?e.strokeWidth/2:0,c=e.w/2+l,m=e.h/2+l;if(c<=0||m<=0)return!1;let u=(i.x-(e.x+e.w/2))/c,y=(i.y-(e.y+e.h/2))/m;return u*u+y*y<=1}if(e.kind==="vector"){let l=e.stroke!==void 0&&e.strokeWidth>0;return Ue(e.contours,i,{fill:e.fill!=="none",rule:e.rule,reach:(l?e.strokeWidth/2:0)+r})}return n}function ae(e,t){let r=new Map;for(let n of t.items)n.kind==="frame"&&n.w>0&&n.h>0&&r.set(n.id,{id:n.id,x:n.x,y:n.y,w:n.w,h:n.h});let i=e.root.children.flatMap(n=>{let l=n.type==="frame"?r.get(n.id):void 0;return l&&n.type==="frame"?[{...l,skip:n.skip===!0}]:[]});return i.length===0?[{id:null,x:t.x,y:t.y,w:t.width,h:t.height,skip:!1}]:i.every(n=>n.skip)?i.map(n=>({...n,skip:!1})):i}function pt(e,t){return e.root.children.find(i=>i.type==="frame"&&$e(i,t)!==void 0)?.id}function ht(e,t){let r=t===void 0?-1:e.findIndex(i=>i.id===t);return r!==-1?r:Math.max(0,e.findIndex(i=>!i.skip))}function ce(e,t,r){for(let i=t+r;i>=0&&i<e.length;i+=r)if(!e[i]?.skip)return i;return t}function gt(e){return e.filter(t=>!t.skip).length}function Ce(e,t){return e[t]?.skip!==!1?null:e.slice(0,t+1).filter(r=>!r.skip).length}function mt(e,t){if(!/^\d+$/.test(e))return null;let r=Number(e),i=t.findIndex((n,l)=>Ce(t,l)===r);return i===-1?null:i}function yt(e,t,r){let i=pt(e,r),n=t.findIndex(l=>l.id!==null&&l.id===i);return n===-1?null:n}var nn="cubic-bezier(0.2, 0, 0, 1)",rn="cubic-bezier(0.4, 0, 1, 1)",wt="cubic-bezier(0.4, 0, 0.2, 1)";function vt(e,t,r,i,n){let l={opacity:r},c=on(e,t,i,n);if(e==="cut")return{keyframes:t==="enter"?[{visibility:"hidden"},{visibility:"hidden"}]:[{visibility:"visible"},{visibility:"visible"}],easing:"linear"};if(e==="pop"){let m=`${n.x}px ${n.y}px`;l.scale="1",l.transformOrigin=m}else(e==="rise"||e==="drop")&&(l.translate="0 0");return t==="enter"?{keyframes:[c,l],easing:nn}:{keyframes:[l,c],easing:rn}}function on(e,t,r,i){switch(e){case"rise":return{opacity:0,translate:`0 ${t==="enter"?r:-r}px`};case"drop":return{opacity:0,translate:`0 ${t==="enter"?-r:r}px`};case"pop":return{opacity:0,scale:String(.85),transformOrigin:`${i.x}px ${i.y}px`};case"fade":case"cut":return{opacity:0}}}function xt(e,t){let r=t==="forward"?"-100%":"100%",i=t==="forward"?"100%":"-100%";switch(e){case"cut":return null;case"fade":return{still:[{opacity:1},{opacity:0}],live:null,stillOnTop:!0};case"push":return{still:[{translate:"0 0"},{translate:`${r} 0`}],live:[{translate:`${i} 0`},{translate:"0 0"}],stillOnTop:!1};case"slide":return t==="forward"?{still:null,live:[{translate:"100% 0"},{translate:"0 0"}],stillOnTop:!1}:{still:[{translate:"0 0"},{translate:"100% 0"}],live:null,stillOnTop:!0}}}var sn={enter:"cut",duration:0,steps:[[]],clicks:new Map};function De(e){let t=new Map,r=new Map,i=new Map;Ve(e.root,(m,u)=>{u&&(r.set(m.id,u.id),i.set(u.id,[...i.get(u.id)??[],m.id]))});let n=je(e),l=Be(e);for(let[m,u]of Object.entries(e.motion??{})){if(!l.has(m))continue;let y=[[]],f=new Map;for(let p of u.lines){if(p.id===m||n.get(p.id)!==m)continue;let A=p.go===void 0?void 0:He(p.go);A&&f.set(p.id,A);let S=p.enter!==void 0?"enter":p.exit!==void 0?"exit":null,E=p.enter??p.exit;S===null||E===void 0||(p.step&&y.push([]),y.at(-1).push({id:p.id,kind:S,effect:E,duration:E==="cut"?0:p.duration??Se,delay:p.delay??0,together:p.together===!0}))}t.set(m,{enter:u.enter??"cut",duration:u.duration??Se,steps:y,clicks:f})}let c=m=>[m,...(i.get(m)??[]).flatMap(u=>c(u))];return{pages:t,parents:r,within:c}}function bt(e,t){let r=t?.id;return(r?e.pages.get(r):void 0)??sn}function Fe(e){let t=0,r=0;return e.map((i,n)=>(t=(n===0?0:i.together?t:r)+i.delay,r=t+i.duration,{build:i,at:t}))}function St(e){return Math.max(0,...Fe(e).map(({build:t,at:r})=>r+t.duration))}function se(e,t){let r=new Set,i=new Set;for(let n of e.steps.flat())i.has(n.id)||(i.add(n.id),n.kind==="enter"&&r.add(n.id));for(let n of e.steps.slice(0,t).flat())n.kind==="enter"?r.delete(n.id):r.add(n.id);return r}function Et(e,t,r){for(let i=r;i!==void 0;i=e.parents.get(i)){let n=t.clicks.get(i);if(n)return{id:i,target:n}}}function kt(e,t,r){let i=[...e];for(;i.length>0;){let n=i.pop(),l=t.findIndex(c=>c.id!==null&&c.id===n);if(l!==-1&&l!==r)return{index:l,history:i}}return null}var cn=1500,dn=2e3,un=50;function Ie(e,t){let r=e.ownerDocument;e.classList.add("vd-player"),e.tabIndex=-1;let i=new Set,n=new Set,l=!1,c=le(e,{document:t.document,interactive:!1,surface:"#000",...t.fonts?{fonts:t.fonts}:{},...t.loadFont?{loadFont:t.loadFont}:{},...t.resolveAsset?{resolveAsset:t.resolveAsset}:{},onSceneChange:()=>{l&&z()}}),m=r.createElementNS(j,"path");m.setAttribute("class","vd-player__mask"),m.setAttribute("fill","#000"),m.setAttribute("fill-rule","evenodd"),c.surface.appendChild(m);let u=r.createElement("div");u.className="vd-player__counter",u.setAttribute("aria-live","polite"),e.appendChild(u);let y=De(t.document),f=ae(t.document,c.getScene()),p=ht(f,t.start),A=[],S=0,E=[],x,C=0,O="",_,N,$=r.defaultView,P=()=>typeof c.surface.animate=="function"&&!($?.matchMedia?.("(prefers-reduced-motion: reduce)").matches??!1),F=()=>bt(y,f[p]);function I(){let s=e.getBoundingClientRect(),d=f[p];return{width:s.width||d?.w||1,height:s.height||d?.h||1}}function U(){let s=f[p];if(!s)return;let d=I(),o=oe({x:s.x,y:s.y,width:s.w,height:s.h},d,0);c.setCamera(o);let h=s.x*o.zoom+o.x,g=s.y*o.zoom+o.y,b=s.w*o.zoom,T=s.h*o.zoom;m.setAttribute("d",`M0 0H${d.width}V${d.height}H0ZM${h} ${g}h${b}v${T}h${-b}Z`),m.dataset.slide=s.id??""}function K(){let s=Ce(f,p),d=gt(f);u.textContent=s===null?"Skipped":`${s} / ${d}`,u.classList.add("vd-player__counter--shown"),_&&clearTimeout(_),_=setTimeout(()=>u.classList.remove("vd-player__counter--shown"),cn),t.onChange?.(s,d)}function z(){let s=new Set;for(let d of i)for(let o of y.within(d))s.add(o);n=s;for(let d of c.surface.querySelectorAll("[data-vd-hidden]")){let o=d.getAttribute("data-vd-id");(o===null||!s.has(o))&&d.removeAttribute("data-vd-hidden")}for(let d of s)c.elementOf(d)?.setAttribute("data-vd-hidden","")}function q(s){return y.within(s).flatMap(d=>{let o=c.elementOf(d);return o?[o]:[]})}function X(s){let d=1/0,o=1/0,h=-1/0,g=-1/0;for(let b of y.within(s)){let T=c.itemOf(b);T&&(d=Math.min(d,T.x),o=Math.min(o,T.y),h=Math.max(h,T.x+T.w),g=Math.max(g,T.y+T.h))}return Number.isFinite(d)?{x:(d+h)/2,y:(o+g)/2}:{x:0,y:0}}function W(){if(!(E.length===0&&!x)){C+=1,S===0&&(S=1),i=se(F(),S),z();for(let s of E)s.cancel();E=[],x?.remove(),x=void 0}}function B(){return E.length===0&&!x?!1:(W(),!0)}function te(s,d){return new Promise(o=>{let h=!1,g=()=>{h||(h=!0,o())};Promise.all(s.map(b=>b.finished)).then(g,()=>{h=!0}),setTimeout(()=>{if(!h){for(let b of s)(b.playState==="running"||b.playState==="paused")&&b.finish();g()}},d+un)})}function Z(s,d,o){if(s===p||!f[s])return;let h=F();p=s;let g=F(),b=o==="forward"?g:h,T=P()?xt(b.enter,o):null;if(T&&(x=c.surface.cloneNode(!0),x.classList.add("vd-player__still"),x.setAttribute("aria-hidden","true"),T.stillOnTop?c.surface.after(x):c.surface.before(x)),U(),S=d?0:g.steps.length,i=se(g,S),z(),K(),!T||!x){d&&J();return}let R={duration:b.duration,easing:wt},k=[];T.still&&k.push(x.animate(T.still,{...R,fill:"forwards"})),T.live&&k.push(c.surface.animate(T.live,R)),E.push(...k);let re=C;te(k,b.duration).then(()=>{if(re===C){E=E.filter(ie=>!k.includes(ie));for(let ie of k)ie.cancel();x?.remove(),x=void 0,d&&J()}})}function J(){let s=F(),d=s.steps[S];if(d===void 0)return;S+=1;let o=se(s,S);if(d.length===0)return;if(!P()){i=o,z();return}let h=new Set(d.filter(k=>k.kind==="enter").map(k=>k.id));i=new Set([...se(s,S-1)].filter(k=>!h.has(k))),z();let g=f[p],b=.04*Math.min(g?.w??0,g?.h??0),T=C,R=[];for(let{build:k,at:re}of Fe(d)){let ie=X(k.id),Y=[];for(let V of q(k.id)){let de=Number(V.getAttribute("opacity")??1),{keyframes:be,easing:he}=vt(k.effect,k.kind,Number.isFinite(de)?de:1,b,ie);Y.push(V.animate(be,{duration:k.duration,delay:re,easing:he,fill:k.kind==="enter"?"backwards":"forwards"}))}R.push(...Y),k.kind==="exit"&&Y.length>0&&te(Y,re+k.duration).then(()=>{if(T===C){i.add(k.id),z();for(let V of Y)V.cancel()}})}E.push(...R),te(R,St(d)).then(()=>{if(T===C){E=E.filter(k=>!R.includes(k)),i=o,z();for(let k of R)k.cancel()}})}function H(s){let d=Math.min(Math.max(0,s),f.length-1);if(d===p)return;let o=f[p]?.id;o&&A.push(o),Z(d,!0,"forward")}function Q(){if(!B()){if(S<F().steps.length){J();return}H(ce(f,p,1))}}function G(){if(B())return;let s=kt(A,f,p);if(s){A=s.history,Z(s.index,!1,"back");return}Z(ce(f,p,-1),!1,"back")}function ne(s){switch(s.kind){case"url":t.onLink?.(s.url);return;case"back":G();return;case"next":H(ce(f,p,1));return;case"frame":{let d=yt(c.getDocument(),f,s.id);d===null?Q():H(d)}}}function a(s){let d=f[p];if(!d||s.x<d.x||s.y<d.y||s.x>d.x+d.w||s.y>d.y+d.h)return;let o=T=>!n.has(T),h=c.hitTest(s,o),g=h===null?void 0:Et(y,F(),h);if(g)return g.target;let b=c.linkAt(s,o);return b===void 0?void 0:ge(b)}let v=s=>{if(s.stopPropagation(),s.metaKey||s.ctrlKey||s.altKey)return;let d=s.key;if(/^\d$/.test(d))O+=d;else if(d==="Enter"&&O!==""){let o=mt(O,f);O="",!B()&&o!==null&&H(o)}else if(d==="Escape")O!==""?O="":t.onExit?.();else if(["ArrowRight","ArrowDown","PageDown"," ","Enter"].includes(d))O="",Q();else if(["ArrowLeft","ArrowUp","PageUp","Backspace"].includes(d))O="",G();else if(d==="Home")B()||H(ce(f,-1,1));else if(d==="End")B()||H(ce(f,f.length,-1));else return;s.preventDefault()},M=s=>{if(B())return;let d=a(c.screenToDocument(c.pointerPoint(s)));d?ne(d):Q()},w=s=>{if(e.classList.remove("vd-player--idle"),N&&clearTimeout(N),N=setTimeout(()=>e.classList.add("vd-player--idle"),dn),!s)return;let d=c.screenToDocument(c.pointerPoint(s));e.classList.toggle("vd-player--link",a(d)!==void 0)},L=$&&"ResizeObserver"in $?new $.ResizeObserver(()=>U()):void 0;return L?.observe(e),e.addEventListener("keydown",v),e.addEventListener("click",M),e.addEventListener("pointermove",w),l=!0,U(),i=se(F(),0),z(),K(),w(),e.focus({preventScroll:!0}),J(),{viewer:c,index:()=>p,count:()=>f.length,next:Q,back:G,go(s){W(),H(s)},update(s){if(s===c.getDocument())return;W();let d=f[p]?.id;c.update(s),y=De(s),f=ae(s,c.getScene());let o=f.findIndex(h=>h.id===d);p=o===-1?Math.min(p,f.length-1):o,U(),S=F().steps.length,i=se(F(),S),z()},refit:U,destroy(){C+=1;for(let s of E)s.cancel();E=[],x?.remove(),L?.disconnect(),e.removeEventListener("keydown",v),e.removeEventListener("click",M),e.removeEventListener("pointermove",w),_&&clearTimeout(_),N&&clearTimeout(N),m.remove(),u.remove(),c.destroy(),e.classList.remove("vd-player","vd-player--idle","vd-player--link"),e.removeAttribute("tabindex")}}}function At(e){let t=e,r=new Map,i=typeof URL.createObjectURL=="function"&&typeof URL.revokeObjectURL=="function";return{resolve(n){let l=r.get(n.hash);if(l!==void 0)return l;let c=t.get(n.hash);if(c===void 0)return;if(!i)return We(n.type,c);let m;try{m=Ke(c)}catch{return}let u=URL.createObjectURL(new Blob([m],{type:n.type}));return r.set(n.hash,u),u},replace(n){t=n;for(let[l,c]of r)n.has(l)||(URL.revokeObjectURL(c),r.delete(l))},destroy(){for(let n of r.values())URL.revokeObjectURL(n);r.clear(),t=new Map}}}var Ne=["page","content","none"],Ot=24;function pe(e){let t=e.getBoundingClientRect();return{width:t.width,height:t.height}}function Mt(e,t){let r=t===void 0?void 0:e.itemOf(t);if(!(!r||r.w<=0||r.h<=0))return{x:r.x,y:r.y,width:r.w,height:r.h}}function Tt(e,t,r,i){if(r==="none")return;let n=r==="page"?Mt(e,i):void 0;if(!n){e.fitToContent(Ot);return}let l=pe(t);e.setCamera(oe(n,{width:l.width||n.width,height:l.height||n.height},Ot))}function _t(e,t,r){let i=Mt(e,r);if(!i)return;let n=e.getCamera(),l=pe(t),c=l.width||i.width*n.zoom,m=l.height||i.height*n.zoom;e.setCamera({zoom:n.zoom,x:c/2-(i.x+i.width/2)*n.zoom,y:m/2-(i.y+i.height/2)*n.zoom})}var ze=Symbol.for("vdesign.embed.handover");function Lt(e){return e[ze]}var Pt=["exact","browser"],Ct=["ready","problems","page","fonts"];async function fn(e,t){try{let{exactFontsAt:r}=await import("./chunks/fonts.js"),i=r(e);return(await i.ensure(t)).length===0?i:void 0}catch{return}}async function ur(e,t,r={}){let i=r.fit??"page";if(!Ne.includes(i))throw new TypeError(`view: fit must be one of ${Ne.join(", ")}; got ${String(i)}.`);let n=r.fonts??"exact";if(!Pt.includes(n))throw new TypeError(`view: fonts must be one of ${Pt.join(", ")}; got ${String(n)}.`);let l=n==="exact"?et(r.fontBase,Re,e.ownerDocument.baseURI):void 0,c=Lt(r),m=await Ae(t),u=c?.page!==void 0&&ee(m.document).some(o=>o.id===c.page)?c.page:r.page===void 0?ee(m.document)[0]?.id:ue(m.document,r.page).id,y=c?.exact&&l?await fn(l,m.document):void 0,f=e.ownerDocument,p=f.defaultView,A=At(m.blocks),S=m.blocks,E=[...m.problems],x,C=()=>x?[...E,x]:[...E],O=f.createElement("div");O.className="vd-embed",O.style.width="100%",O.style.height="100%",e.appendChild(O);let _=le(O,{document:m.document,interactive:r.interactive??!0,wheel:"modifier",resolveAsset:o=>A.resolve(o),...r.surface?{surface:r.surface}:{},...c?{camera:c.camera}:{},...y?{fonts:y.library}:{}}),N={ready:new Set,problems:new Set,page:new Set,fonts:new Set},$=!1,P=!1,F=0,I,U,K=y,z=n==="browser"?"browser":void 0,q;function X(){$=!0;for(let o of N.ready)o()}function W(){for(let o of N.problems)o(C())}function B(o){z=o;for(let h of N.fonts)h(o)}function te(){return q??=(async()=>{if(l)try{let{exactFontsAt:o}=await import("./chunks/fonts.js");return o(l)}catch{return}})(),q}function Z(o){K=void 0,_.setFonts(void 0),I?.fonts(void 0),x=o,W(),B("browser")}async function J(){let o=await te();if(!P){if(!o){Z(ye([],l?"the fonts chunk would not load":"no fontBase was given and this build has no default"));return}for(;;){let h=_.getDocument(),g=await o.ensure(h);if(P)return;if(g.length>0){Z(ye(g));return}if(_.getDocument()===h)break}K=o,_.setFonts(o.library),I?.fonts(o),B("exact")}}function H(){let o=Q(u);if(o)for(let h of N.page)h(o)}function Q(o){let h=ee(_.getDocument()).find(g=>g.id===o);if(h)return h.name===void 0?{id:h.id}:{id:h.id,name:h.name}}let G=()=>Tt(_,O,i,u),ne=()=>_t(_,O,u);function a(o){if(P)return;let h=ue(_.getDocument(),o).id,g=h!==u;u=h,i==="page"?G():ne(),g&&H()}function v(o){r.onLink?r.onLink(o):p?.open(o,"_blank","noopener,noreferrer")}let M=o=>{if(o.button!==0||I)return;let h=_.linkAt(_.screenToDocument(_.pointerPoint(o)));if(h===void 0)return;let g=ge(h);if(g){if(o.preventDefault(),g.kind==="frame"){ee(_.getDocument()).some(b=>b.id===g.id)&&a(g.id);return}v(g.url)}};O.addEventListener("click",M);let w=pe(O),L=p&&"ResizeObserver"in p?new p.ResizeObserver(()=>{let o=pe(O);o.width===w.width&&o.height===w.height||(w=o,G())}):void 0;L?.observe(O),c||(i==="none"&&u!==void 0&&r.page!==void 0?ne():G()),X(),y?B("exact"):n==="exact"&&J();let s={async load(o){if(P)throw new Error("view: this view was destroyed.");let h=++F,g=await Ae(o),b=K,T=b?await b.ensure(g.document):[];if(U&&await U||P||h!==F)return;T.length>0&&K===b&&Z(ye(T)),A.replace(g.blocks),S=g.blocks,_.update(g.document),E=[...g.problems],I?.update(g.document),ee(g.document).some(k=>k.id===u)||(u=ee(g.document)[0]?.id,i==="page"?G():ne(),H()),W(),X()},pages:()=>ee(_.getDocument()).map(o=>o.name===void 0?{id:o.id}:{id:o.id,name:o.name}),goTo:a,fit:()=>{P||G()},play(o={}){if(P)return Promise.reject(new Error("view: this view was destroyed."));try{return I?.stop(),Promise.resolve(d(_.getDocument(),o.page))}catch(h){return Promise.reject(h instanceof Error?h:new Error(String(h)))}},async edit(o={}){if(P)throw new Error("view: this view was destroyed.");if(U)throw new Error("view: edit() is already opening an editor.");let h;U=new Promise(b=>h=b);let g=!1;try{let{edit:b}=await import("./edit.js");if(P)throw new Error("view: this view was destroyed.");let T={camera:_.getCamera(),page:u,exact:K!==void 0},R=Qe(_.getDocument(),S,E),k=await b(e,R,{...r,...o,[ze]:T});if(P)throw k.destroy(),new Error("view: this view was destroyed.");return g=!0,s.destroy(),k}finally{U=void 0,h(g)}},on(o,h){if(!Ct.includes(o))throw new TypeError(`view: on() takes one of ${Ct.join(", ")}; got ${String(o)}.`);let g=N[o];if(g.add(h),o==="ready"&&$&&queueMicrotask(()=>{g.has(h)&&h()}),o==="problems"&&queueMicrotask(()=>{g.has(h)&&h(C())}),o==="fonts"&&z!==void 0){let b=z;queueMicrotask(()=>{g.has(h)&&h(b)})}return()=>{g.delete(h)}},destroy(){if(!P){P=!0,I?.stop(),O.removeEventListener("click",M),L?.disconnect(),_.destroy(),A.destroy(),O.remove();for(let o of Object.values(N))o.clear()}}};function d(o,h){let g=h===void 0?u:ue(o,h).id,b=f.createElement("div");b.className="vd-embed__play",b.style.position="absolute",b.style.inset="0";let T=V=>V.stopPropagation();b.addEventListener("wheel",T);let R=f.activeElement;O.appendChild(b);let k=!1,re=()=>{if(k)return;k=!0,I===ie&&(I=void 0),Y.destroy(),b.removeEventListener("wheel",T);let V=b.contains(f.activeElement);b.remove(),V&&R&&"focus"in R&&typeof R.focus=="function"&&R.focus({preventScroll:!0})},ie={stop:re,update:V=>Y.update(V),fonts:V=>Y.viewer.setFonts(V?.library)},Y=Ie(b,{document:o,resolveAsset:V=>A.resolve(V),...K?{fonts:K.library}:{},...g===void 0?{}:{start:g},onExit:re,onLink:v});return I=ie,{goTo(V){if(k)return;let de=Y.viewer.getDocument(),be=ue(de,V).id,he=ae(de,Y.viewer.getScene()).findIndex(Dt=>Dt.id===be);he!==-1&&Y.go(he)},destroy:re}}return s}export{Ft as version,ur as view};
|