@filens/core 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 +21 -0
- package/README.md +215 -2
- package/dist/archive-volumes.d.ts +2 -0
- package/dist/archive-volumes.js +46 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +15145 -0
- package/dist/parser/archive-volumes.d.ts +18 -0
- package/dist/parser/archive.d.ts +13 -0
- package/dist/parser/attachments.d.ts +8 -0
- package/dist/parser/load-pptx.d.ts +3 -0
- package/dist/parser/load-source.d.ts +6 -0
- package/dist/parser/ordered-xml.d.ts +2 -0
- package/dist/parser/xml.d.ts +5 -0
- package/dist/parser/zip-reader.d.ts +17 -0
- package/dist/parser/zip.d.ts +4 -0
- package/dist/preview/attachment-session.d.ts +4 -0
- package/dist/preview/audio-lyrics.d.ts +15 -0
- package/dist/preview/audio-player.d.ts +40 -0
- package/dist/preview/containers.d.ts +12 -0
- package/dist/preview/font-loading.d.ts +11 -0
- package/dist/preview/font-matching.d.ts +17 -0
- package/dist/preview/font-metadata.d.ts +9 -0
- package/dist/preview/font-packs.d.ts +5 -0
- package/dist/preview/font-panose.d.ts +4 -0
- package/dist/preview/font-scenes.d.ts +8 -0
- package/dist/preview/fonts.d.ts +14 -0
- package/dist/preview/formats.d.ts +52 -0
- package/dist/preview/index.d.ts +17 -0
- package/dist/preview/native-drivers.d.ts +85 -0
- package/dist/preview/password.d.ts +7 -0
- package/dist/preview/pptx-driver.d.ts +29 -0
- package/dist/preview/previewer.d.ts +66 -0
- package/dist/preview/registry.d.ts +23 -0
- package/dist/preview/resource-resolver.d.ts +17 -0
- package/dist/preview/touch-gestures.d.ts +14 -0
- package/dist/preview/types.d.ts +571 -0
- package/dist/preview/video-controls.d.ts +28 -0
- package/dist/preview/video-player.d.ts +2 -0
- package/dist/render/dom.d.ts +17 -0
- package/dist/render/geometry.d.ts +138 -0
- package/dist/render/preset-definitions.d.ts +60 -0
- package/dist/render/preset-geometry.d.ts +17 -0
- package/dist/types.d.ts +380 -0
- package/dist/utils/colors.d.ts +8 -0
- package/dist/utils/common.d.ts +8 -0
- package/dist/utils/fonts.d.ts +2 -0
- package/dist/utils/units.d.ts +4 -0
- package/dist/viewer.d.ts +61 -0
- package/dist/zip-DI3roeYk.js +190 -0
- package/dist/zip.d.ts +3 -0
- package/dist/zip.js +5 -0
- package/package.json +61 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FiLens contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,216 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @filens/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ESM PPTX parsing and preview core for browser applications.
|
|
4
|
+
|
|
5
|
+
## What It Exposes
|
|
6
|
+
|
|
7
|
+
- `init(container, options)`
|
|
8
|
+
- `createViewer(container, options)`
|
|
9
|
+
- `loadPptx(source)`
|
|
10
|
+
- `renderSlideToElement(slide, presentation, options)`
|
|
11
|
+
|
|
12
|
+
The package also exports the core runtime types.
|
|
13
|
+
|
|
14
|
+
Workers can import `openZipArchive` and the `ZipEntry` type from
|
|
15
|
+
`@filens/core/zip`. This entry loads ZIP parsing without viewer code or CSS.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @filens/core
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { init } from '@filens/core';
|
|
27
|
+
import '@filens/core/style.css';
|
|
28
|
+
|
|
29
|
+
const mount = document.getElementById('mount');
|
|
30
|
+
if (!mount) {
|
|
31
|
+
throw new Error('Missing mount element.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const viewer = init(mount, {
|
|
35
|
+
fit: 'contain',
|
|
36
|
+
initialScale: 1,
|
|
37
|
+
minScale: 0.4,
|
|
38
|
+
maxScale: 4,
|
|
39
|
+
virtual: true
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await viewer.preview('/samples/sample-deck.pptx');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Source Types
|
|
46
|
+
|
|
47
|
+
`preview()` and `loadPptx()` support:
|
|
48
|
+
|
|
49
|
+
- `string`
|
|
50
|
+
- `ArrayBuffer`
|
|
51
|
+
- `Uint8Array`
|
|
52
|
+
- `Blob`
|
|
53
|
+
- `File`
|
|
54
|
+
|
|
55
|
+
For multi-format previews, `createPreviewer()` coordinates registered drivers and
|
|
56
|
+
converters. Opening another file or calling `destroy()` settles superseded
|
|
57
|
+
`preview()` calls, aborts their load signals, and ignores late results and events.
|
|
58
|
+
The signal remains active after the initial load for background resource work.
|
|
59
|
+
Custom drivers must release their own DOM and resources on destruction; work that
|
|
60
|
+
ignores cancellation may still finish. Rejected loads release their sessions and
|
|
61
|
+
expose the error through `getState()` and the `error` event.
|
|
62
|
+
|
|
63
|
+
Password-protected PDF and Office documents can be opened through `createPreviewer()`.
|
|
64
|
+
Register the Office drivers and configure the WASM converter for encrypted Office
|
|
65
|
+
packages. Set `requestPassword` to an async callback that receives `{ name, reason,
|
|
66
|
+
attempt, signal }` and returns a password or `null` to cancel. `reason` is
|
|
67
|
+
`password_required` or `password_invalid`; respect the signal when a file is replaced.
|
|
68
|
+
A known password can be supplied per load with
|
|
69
|
+
`previewer.preview(source, { name: 'document.docx', password })`.
|
|
70
|
+
Passwords retain spaces and Unicode, are not included in preview state, and are
|
|
71
|
+
not reused for subsequent documents. Stable `password_cancelled`, `password_required`
|
|
72
|
+
and `password_invalid` errors can be recognized with `previewPasswordErrorCode()`.
|
|
73
|
+
|
|
74
|
+
With `@filens/archive` registered, encrypted ZIP entries use the same password
|
|
75
|
+
callback. ZIP directories are listed without decrypting their files; a password
|
|
76
|
+
is requested when an encrypted entry is opened. Both ZipCrypto and AES ZIPs are
|
|
77
|
+
supported, including entries with different passwords. A cancelled entry returns
|
|
78
|
+
to the archive. Low-level callers can pass `{ password, signal }` as the second
|
|
79
|
+
argument to `openZipArchive()`, or supply a password to `entry.bytes(password)`.
|
|
80
|
+
|
|
81
|
+
DOCX, XLSX and PPTX previews expose files in their package's `embeddings` directory
|
|
82
|
+
in an **Attachments** panel. PDF drivers expose PDF attachments through the same
|
|
83
|
+
panel. Opening one reuses the registered drivers and converter, so a document can
|
|
84
|
+
contain an encrypted ZIP/RAR/7z, another document, or further attachments. OLE Package
|
|
85
|
+
objects are unwrapped to their original filename and payload; native OLE Office
|
|
86
|
+
objects are identified as DOC/XLS/PPT. Unsupported payloads can be downloaded.
|
|
87
|
+
Returning keeps the parent renderer and scroll position. The default nested
|
|
88
|
+
previewer shares the parent's registry and converter; custom `previewerFactory`
|
|
89
|
+
implementations must forward `containerContext`, `requestPassword`, and other
|
|
90
|
+
received options. Custom document drivers may implement `getAttachments()`.
|
|
91
|
+
|
|
92
|
+
Nested previews share limits of 8 levels, 20,000 entries per container, 128 MiB
|
|
93
|
+
per expanded entry, and 512 MiB of expanded data per top-level preview. Office
|
|
94
|
+
payloads are read on demand; PDF.js supplies PDF attachment contents when the
|
|
95
|
+
attachment list is requested. Linked external objects are not fetched as
|
|
96
|
+
attachments. Legacy Office conversion only exposes attachments preserved in its
|
|
97
|
+
OpenXML output. RAR 4/5 and 7z use a lazy-loaded 7-Zip WASM worker, including
|
|
98
|
+
encrypted filenames, encrypted entries and solid archives. Header passwords are
|
|
99
|
+
requested before listing; entry passwords are requested on opening. Cancelling
|
|
100
|
+
or exceeding the 60-second operation limit terminates the worker. Multi-volume
|
|
101
|
+
archives support RAR `.part01.rar` / `.rar` + `.r00`, 7z `.7z.001`,
|
|
102
|
+
byte-split ZIP `.zip.001`, and traditional ZIP `.z01` + `.zip` naming.
|
|
103
|
+
The demo and standalone picker accept all parts together in any order; nested
|
|
104
|
+
archives automatically find companion volumes in the same directory. Document
|
|
105
|
+
attachments can also collect companion parts, including OLE-wrapped parts.
|
|
106
|
+
Missing first/intermediate parts identify the missing filename; the WASM engine
|
|
107
|
+
validates the final volume. Each set is limited to 256 volumes and 512 MiB of
|
|
108
|
+
compressed input, in addition to the expanded-byte limits above.
|
|
109
|
+
|
|
110
|
+
Hosts can supply companions directly on a source descriptor:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
await previewer.preview({
|
|
114
|
+
source: firstFile, name: 'bundle.7z.001',
|
|
115
|
+
archiveVolumes: [{ name: 'bundle.7z.002', source: secondFile }]
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`selectArchiveVolumes(name, files)` is exported by `@filens/archive` and the
|
|
120
|
+
CSS-free `@filens/core/archive-volumes` entry for custom file pickers. It keeps
|
|
121
|
+
different families/directories separate and returns the primary part first.
|
|
122
|
+
Encrypted ZIP directory metadata is not supported. Corrupt embedded
|
|
123
|
+
OLE objects retain an original-byte download even when their preview fails.
|
|
124
|
+
|
|
125
|
+
PPTX and participating optional drivers also expose `PreviewItemState.fonts`
|
|
126
|
+
through the generic runtime. This includes discovered font references,
|
|
127
|
+
best-effort availability, application mappings, and layout-drift warnings.
|
|
128
|
+
Set `fontLoading: true` on `createPreviewer()` to load optional Latin/CJK webfonts
|
|
129
|
+
in the background and refresh layouts after loading. Custom packs and
|
|
130
|
+
`fontResolver` URL/byte assets support self-hosting and authorization; adaptive
|
|
131
|
+
mirrors and bounded backoff retain local fallback when loading fails.
|
|
132
|
+
See [font diagnostics and loading](../../docs/fonts.md) for supported formats,
|
|
133
|
+
configuration, helper APIs, provenance semantics, and detection limits.
|
|
134
|
+
|
|
135
|
+
## Viewer Options
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
interface ViewerOptions {
|
|
139
|
+
width?: number;
|
|
140
|
+
height?: number;
|
|
141
|
+
fit?: 'contain' | 'width' | 'none';
|
|
142
|
+
initialScale?: number;
|
|
143
|
+
minScale?: number;
|
|
144
|
+
maxScale?: number;
|
|
145
|
+
virtual?: boolean;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Viewer API
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
interface ViewerInstance {
|
|
153
|
+
preview(source: PptxSource): Promise<void>;
|
|
154
|
+
destroy(): void;
|
|
155
|
+
setScale(scale: number): void;
|
|
156
|
+
fit(mode?: FitMode): void;
|
|
157
|
+
goToSlide(index: number): void;
|
|
158
|
+
next(): void;
|
|
159
|
+
prev(): void;
|
|
160
|
+
getState(): ViewerState;
|
|
161
|
+
on(event, handler): () => void;
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Events
|
|
166
|
+
|
|
167
|
+
- `rendered`
|
|
168
|
+
- `error`
|
|
169
|
+
- `slidechange`
|
|
170
|
+
- `scalechange`
|
|
171
|
+
- `warnings`
|
|
172
|
+
|
|
173
|
+
## Rendering Strategy
|
|
174
|
+
|
|
175
|
+
The current implementation uses HTML + SVG:
|
|
176
|
+
|
|
177
|
+
- text, images, and tables render through DOM/CSS
|
|
178
|
+
- preset shapes, lines, and connectors render through SVG
|
|
179
|
+
- thumbnails reuse the same rendering pipeline as the main viewer
|
|
180
|
+
|
|
181
|
+
## Current Coverage
|
|
182
|
+
|
|
183
|
+
Good coverage today:
|
|
184
|
+
|
|
185
|
+
- common text boxes and placeholders
|
|
186
|
+
- images
|
|
187
|
+
- grouped shapes
|
|
188
|
+
- tables
|
|
189
|
+
- theme colors and fonts
|
|
190
|
+
- master/layout inheritance
|
|
191
|
+
- common preset arrows and polygon shapes
|
|
192
|
+
- slide links and external hyperlinks
|
|
193
|
+
- cached 2D column and pie charts, with titles and legends
|
|
194
|
+
|
|
195
|
+
Still limited:
|
|
196
|
+
|
|
197
|
+
- animations
|
|
198
|
+
- other chart types and advanced chart formatting
|
|
199
|
+
- SmartArt
|
|
200
|
+
- media playback objects
|
|
201
|
+
- embedded fonts
|
|
202
|
+
- some long-tail shape formulas
|
|
203
|
+
|
|
204
|
+
## Dist Output
|
|
205
|
+
|
|
206
|
+
Build output:
|
|
207
|
+
|
|
208
|
+
- `dist/index.js`
|
|
209
|
+
- `dist/index.css`
|
|
210
|
+
- `dist/index.d.ts`
|
|
211
|
+
|
|
212
|
+
Import CSS with:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import '@filens/core/style.css';
|
|
216
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const l = { maxVolumes: 256, maxBytes: 536870912 };
|
|
2
|
+
function d(r) {
|
|
3
|
+
let e = /^(.*\.part)(\d+)(\.rar)$/i.exec(r);
|
|
4
|
+
if (e) return { format: "rar", kind: "rar-part", key: `${e[1]}*.rar`.toLowerCase(), base: e[1], index: Number(e[2]) - 1, width: e[2].length };
|
|
5
|
+
if (e = /^(.*\.(7z|zip))\.(\d{3,})$/i.exec(r), e) return { format: e[2].toLowerCase(), kind: "numbered", key: `${e[1]}.*`.toLowerCase(), base: e[1], index: Number(e[3]) - 1, width: e[3].length };
|
|
6
|
+
if (e = /^(.*)\.([r-y])(\d{2})$/i.exec(r), e) return { format: "rar", kind: "rar-old", key: `${e[1]}.rar`.toLowerCase(), base: e[1], index: (e[2].toLowerCase().charCodeAt(0) - 114) * 100 + Number(e[3]) + 1, width: 2 };
|
|
7
|
+
if (e = /^(.*)\.rar$/i.exec(r), e) return { format: "rar", kind: "rar-old", key: r.toLowerCase(), base: e[1], index: 0, width: 2 };
|
|
8
|
+
if (e = /^(.*)\.z(\d{2,})$/i.exec(r), e) return { format: "zip", kind: "zip", key: `${e[1]}.zip`.toLowerCase(), base: e[1], index: Number(e[2]) - 1, width: e[2].length };
|
|
9
|
+
if (e = /^(.*)\.zip$/i.exec(r), e) return { format: "zip", kind: "zip", key: r.toLowerCase(), base: e[1], index: 1 / 0, width: 2 };
|
|
10
|
+
}
|
|
11
|
+
function f(r) {
|
|
12
|
+
const e = d(r);
|
|
13
|
+
return !!(e && (e.kind === "numbered" || e.kind === "rar-part" || !/\.(rar|zip)$/i.test(r)));
|
|
14
|
+
}
|
|
15
|
+
function c(r, e) {
|
|
16
|
+
const n = d(r);
|
|
17
|
+
if (!n) return;
|
|
18
|
+
const i = e.flatMap((t) => {
|
|
19
|
+
const a = d(t.name);
|
|
20
|
+
return (a == null ? void 0 : a.key) === n.key && a.kind === n.kind ? [{ file: t, info: a }] : [];
|
|
21
|
+
}).sort((t, a) => t.info.index - a.info.index);
|
|
22
|
+
if (!i.length || i.length === 1 && !f(r)) return;
|
|
23
|
+
if (i.length > l.maxVolumes) throw new Error("Archive contains too many volumes.");
|
|
24
|
+
const s = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const { info: t } of i) {
|
|
26
|
+
if (s.has(t.index)) throw new Error("Duplicate archive volume numbers.");
|
|
27
|
+
if (t.index < 0 || !Number.isSafeInteger(t.index) && !(t.kind === "zip" && t.index === 1 / 0)) throw new Error("Invalid archive volume number.");
|
|
28
|
+
s.add(t.index);
|
|
29
|
+
}
|
|
30
|
+
const u = i.filter((t) => t.info.index !== 1 / 0);
|
|
31
|
+
for (let t = 0; t < u.length; t++)
|
|
32
|
+
if (u[t].info.index !== t)
|
|
33
|
+
throw new Error(`Missing archive volume: ${h(n, t)}. Select all parts of the archive.`);
|
|
34
|
+
if (n.kind === "zip" && !i.some((t) => t.info.index === 1 / 0))
|
|
35
|
+
throw new Error(`Missing archive volume: ${n.base}.zip. Select all parts of the archive.`);
|
|
36
|
+
const o = n.kind === "zip" ? i[i.length - 1].file : i[0].file;
|
|
37
|
+
return { format: n.format, primary: o, files: [o, ...i.map((t) => t.file).filter((t) => t !== o)] };
|
|
38
|
+
}
|
|
39
|
+
function h(r, e) {
|
|
40
|
+
return r.kind === "rar-part" ? `${r.base}${String(e + 1).padStart(r.width, "0")}.rar` : r.kind === "numbered" ? `${r.base}.${String(e + 1).padStart(r.width, "0")}` : r.kind === "zip" ? `${r.base}.z${String(e + 1).padStart(r.width, "0")}` : e === 0 ? `${r.base}.rar` : `${r.base}.${String.fromCharCode(114 + Math.floor((e - 1) / 100))}${String((e - 1) % 100).padStart(2, "0")}`;
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
l as ARCHIVE_VOLUME_LIMITS,
|
|
44
|
+
f as isArchiveVolumeName,
|
|
45
|
+
c as selectArchiveVolumes
|
|
46
|
+
};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.pptxv-viewer{position:relative;display:flex;width:100%;height:100%;min-height:320px;background:#e6e9ef;overflow:hidden}.pptxv-scroll-area{flex:1;overflow:auto;padding:12px;scroll-behavior:smooth;scroll-padding:12px;scroll-snap-type:y proximity}.pptxv-loading{display:flex;align-items:center;justify-content:center;min-height:240px;color:#395170;font:600 15px/1.4 system-ui,sans-serif}.pptxv-loading--error{color:#8a1f1f}.pptxv-slide-shell{position:relative;contain:layout style;margin:0 auto 18px;scroll-snap-align:start}.pptxv-slide-stage{position:relative;border-radius:0;box-shadow:none;overflow:hidden}.pptxv-slide{position:relative;overflow:hidden;font-family:system-ui,sans-serif}.pptxv-slide--thumbnail{box-shadow:none}.pptxv-item{box-sizing:border-box}.pptxv-item--table,.pptxv-item--chart,.pptxv-item--unsupported{overflow:hidden}.pptxv-item--shape,.pptxv-item--media{overflow:visible}.pptxv-shape-svg{display:block;overflow:visible}.pptxv-text-frame{display:flex;flex-direction:column;width:100%;height:100%;box-sizing:border-box}.pptxv-shape-text{display:block;width:auto;height:auto;box-sizing:border-box}.pptxv-paragraph{margin:0;line-height:1;word-break:normal;overflow-wrap:break-word}.pptxv-run{white-space:pre-wrap}.pptxv-run--tab{display:inline-block;white-space:pre;min-width:4px}.pptxv-run--link{color:inherit;text-decoration-line:underline;text-decoration-color:currentcolor;text-underline-offset:.08em}.pptxv-item-link{cursor:pointer}.pptxv-item-link:focus-visible{outline:none;box-shadow:inset 0 0 0 2px #2f6bffd1,inset 0 0 0 4px #ffffffc2}.pptxv-run--bullet{display:inline-block;min-width:1.2em}.pptxv-run--bullet-auto{min-width:2.4em}.pptxv-image{display:block;-webkit-user-select:none;user-select:none}.pptxv-media-stage{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;background:transparent}.pptxv-media-poster-frame{position:absolute}.pptxv-media-poster,.pptxv-media-player{display:block}.pptxv-media-poster{-webkit-user-select:none;user-select:none;pointer-events:none}.pptxv-media-player--video{background:transparent}.pptxv-media-player--audio{min-width:220px}.pptxv-table{width:100%;height:100%;border-collapse:collapse;table-layout:fixed;background:transparent}.pptxv-table-cell{border:0 solid transparent;vertical-align:top;padding:0}.pptxv-chart-svg{display:block;width:100%;height:100%;overflow:hidden;font-family:Aptos,Calibri,Segoe UI,sans-serif}.pptxv-chart-title,.pptxv-chart-axis-label,.pptxv-chart-category-label,.pptxv-chart-legend{fill:#595959;font-weight:400}.pptxv-chart-gridline{stroke:#bfbfbf;stroke-width:1}.pptxv-chart-axis{stroke:#000;stroke-width:1.25}.pptxv-item--unsupported{display:flex;align-items:center;justify-content:center;border:1px dashed rgba(57,81,112,.35);background:#ffffffb8;color:#395170;font:600 12px/1.3 system-ui,sans-serif}.pptxv-native-preview{box-sizing:border-box;width:100%;height:100%;min-height:280px;font-family:system-ui,sans-serif}.pptxv-native-preview--image,.pptxv-native-preview--video,.pptxv-native-preview--audio{display:flex;align-items:center;justify-content:center;overflow:auto;padding:16px;background:#151923}.pptxv-native-preview--image{cursor:grab;touch-action:none}.pptxv-native-preview--image.is-panning{cursor:grabbing}.pptxv-native-preview--audio{background:radial-gradient(ellipse at 12% 10%,#e3eadd,transparent 65%),#f2f0eb;flex-direction:column;padding:clamp(16px,4%,48px);justify-content:safe center;container-type:inline-size}.pptxv-native-image{display:block;width:auto;height:auto;transform-origin:center center;-webkit-user-select:none;user-select:none}.pptxv-native-media{display:block;max-width:100%}.pptxv-native-media--video{max-height:100%;background:#000}.pptxv-has-video-controls{position:relative;container-type:inline-size;outline:none}.pptxv-native-preview--video.pptxv-has-video-controls{overflow:hidden;padding:0 0 110px;background:#11151c}.pptxv-has-video-controls:fullscreen{width:100%;height:100%}.pptxv-video-controls{position:absolute;right:12px;bottom:max(12px,env(safe-area-inset-bottom));left:12px;z-index:3;box-sizing:border-box;max-width:880px;margin:0 auto;padding:10px 14px 8px;border:1px solid rgba(255,255,255,.18);border-radius:20px;background:#141821e0;color:#f8fafc;font:13px/1.4 system-ui,sans-serif;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);box-shadow:0 6px 24px #0003}.pptxv-video-control-row{display:flex;align-items:center;gap:4px;min-width:0}.pptxv-video-controls button,.panoramav-view-controls button{display:inline-flex;align-items:center;justify-content:center;flex:0 0 36px;box-sizing:border-box;width:36px;height:36px;padding:7px;border:0;border-radius:50%;background:transparent;color:#f8fafc;cursor:pointer;touch-action:manipulation}.pptxv-video-controls button:hover,.panoramav-view-controls button:hover{background:#ffffff24}.pptxv-video-controls button:disabled,.panoramav-view-controls button:disabled{opacity:.4;cursor:default}.pptxv-video-controls :focus-visible,.panoramav-view-controls button:focus-visible,.pptxv-has-video-controls:focus-visible{outline:2px solid #9ec5ff;outline-offset:2px}.pptxv-video-time{flex-shrink:0;margin-left:5px;color:#e5e7eb;font:inherit;font-variant-numeric:tabular-nums;white-space:nowrap}.pptxv-video-control-spacer{flex:1}.pptxv-video-controls input[type=range]{min-width:0;padding:0;border:0;border-radius:2px;accent-color:#f8fafc;cursor:pointer;touch-action:pan-y}.pptxv-video-controls .pptxv-video-timeline{display:block;width:100%;height:18px;margin:0 0 4px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent}.pptxv-video-timeline::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(to right,#f8fafc var(--pptxv-video-progress, 0%),#ffffff40 var(--pptxv-video-progress, 0%))}.pptxv-video-timeline::-webkit-slider-thumb{width:12px;height:12px;margin-top:-4px;border-radius:50%;background:#fff;-webkit-appearance:none;-moz-appearance:none;appearance:none}.pptxv-video-timeline::-moz-range-track{height:4px;border-radius:2px;background:#ffffff40}.pptxv-video-timeline::-moz-range-progress{height:4px;background:#f8fafc}.pptxv-video-timeline::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:#fff}.pptxv-video-volume{display:flex;align-items:center;gap:4px}.pptxv-video-volume input{width:68px}.pptxv-video-rate{height:36px;padding:0 4px;border:0;border-radius:8px;background:transparent;color:#f8fafc;font:inherit;cursor:pointer}.pptxv-video-rate option{background:#202632;color:#f8fafc}.pptxv-video-captions{max-width:84px}.pptxv-video-controls [hidden]{display:none}@container (max-width: 540px){.pptxv-video-volume input{display:none}}@container (max-width: 420px){.pptxv-video-controls{right:8px;left:8px;padding:8px;border-radius:16px}.pptxv-video-controls .pptxv-video-skip,.pptxv-video-controls .pptxv-video-pip{display:none}.pptxv-video-captions{max-width:44px}.pptxv-video-control-row{gap:2px}.pptxv-video-time{margin-left:0;font-size:11px}}.pptxv-native-media--audio{width:min(640px,100%)}.pptxv-native-audio-cover{display:block;position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;height:100%;object-fit:cover;border-radius:inherit}.pptxv-audio-player{--audio-accent: #40634c;box-sizing:border-box;width:min(880px,100%);flex-shrink:0;margin:auto;color:#283c32;background:#fffefa;border:1px solid #d7dbd0;border-radius:22px;box-shadow:0 16px 56px #243b2c0c;font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;overflow:hidden}.pptxv-audio-player button,.pptxv-audio-player select{font:inherit;cursor:pointer;color:inherit}.pptxv-audio-player button:focus-visible,.pptxv-audio-player select:focus-visible,.pptxv-audio-lyrics:focus-visible{outline:2px solid var(--audio-accent);outline-offset:3px}.pptxv-audio-body{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);gap:clamp(24px,5%,56px);padding:clamp(24px,5%,44px)}.pptxv-audio-album{min-width:0}.pptxv-audio-artwork{position:relative;aspect-ratio:1;width:100%;max-width:280px;margin-bottom:26px;border-radius:14px;background:#45644e;box-shadow:0 10px 24px #223b3026;isolation:isolate}.pptxv-audio-placeholder{display:grid;place-items:center;height:100%;overflow:hidden;border-radius:inherit;background:radial-gradient(circle at 25% 15%,#9cab7c,transparent 50%),linear-gradient(145deg,#526c53,#1f3c37)}.pptxv-audio-placeholder span{display:grid;place-items:center;width:66%;aspect-ratio:1;border:1px solid #ffffff30;border-radius:50%;box-shadow:0 0 0 15px #ffffff06,0 0 0 30px #ffffff06;color:#e8e8cd;font-size:52px}.pptxv-audio-play{position:absolute;z-index:2;right:14px;bottom:14px;display:grid;place-items:center;width:48px;height:48px;padding:0;border:1px solid #ffffffa0;border-radius:50%;color:#293f32!important;background:#fffef4ee;box-shadow:0 4px 16px #0002}.pptxv-audio-play:hover{background:#fff;transform:scale(1.04)}.pptxv-audio-eyebrow{margin:0 0 10px;color:#697c63;font-size:10px;letter-spacing:.16em}.pptxv-audio-eyebrow:before{content:"";display:inline-block;width:6px;height:6px;margin-right:7px;border-radius:50%;background:#a7b19b}.is-playing .pptxv-audio-eyebrow:before{background:#52835b;box-shadow:0 0 0 4px #52835b18}.pptxv-audio-title{margin:0 0 8px;font-size:clamp(19px,2.4cqw,25px);font-weight:600;line-height:1.4;overflow-wrap:anywhere}.pptxv-audio-details{margin:0 0 18px;color:#6c756b;font-size:12px;line-height:1.6;overflow-wrap:anywhere}.pptxv-audio-import{padding:6px 10px;border:1px solid #dce0d4;border-radius:6px;background:transparent;font-size:11px!important}.pptxv-audio-import:hover{border-color:#95a48c;background:#f3f5ed}.pptxv-audio-lyric-panel{min-width:0;display:flex;flex-direction:column}.pptxv-audio-lyric-header{display:flex;justify-content:space-between;align-items:center;gap:12px;padding-bottom:14px;border-bottom:1px solid #e8e9e1}.pptxv-audio-lyric-header h3{margin:0;color:#6c756b;font-size:12px;font-weight:500;letter-spacing:.06em}.pptxv-audio-lyrics{position:relative;flex:1 0 auto;height:280px;max-height:340px;overflow:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:#cbd1c3 transparent;margin-top:12px;padding:40px 0;box-sizing:border-box}.pptxv-audio-lyrics.is-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:#7b8375;gap:12px}.pptxv-audio-empty-icon{font-size:42px;color:#a0ae93}.pptxv-audio-lyrics.is-empty p{margin:0;font-size:14px}.pptxv-audio-lyrics.is-empty small{color:#7b8375;font-size:11px;line-height:1.7}.pptxv-audio-lyric{display:block;width:100%;padding:12px 10px;margin:0;border:0;border-left:2px solid transparent;border-radius:0 6px 6px 0;background:transparent;color:#7c8378!important;text-align:left;font-size:14px!important;line-height:1.8;white-space:pre-line;overflow-wrap:anywhere;transition:color .18s,background .18s}.pptxv-audio-lyric:hover{color:#40634c!important;background:#f4f5ee}.pptxv-audio-lyric.is-active{border-left-color:var(--audio-accent);color:#304e39!important;background:#eff3e9;font-weight:600}.pptxv-audio-timing{display:flex;justify-content:flex-end;align-items:center;gap:10px;margin-top:12px;color:#6c756b;font-size:10px}.pptxv-audio-timing[hidden]{display:none}.pptxv-audio-timing button{padding:4px 7px;border:1px solid #e0e3d8;border-radius:4px;background:transparent}.pptxv-audio-timing output{min-width:38px;text-align:center;font-variant-numeric:tabular-nums}.pptxv-audio-status{margin:10px 0 0;color:#707969;font-size:11px;line-height:1.6}.pptxv-audio-status:empty{display:none}.pptxv-audio-footer{display:flex;align-items:center;gap:14px;padding:16px 24px;background:#f3f5ee;border-top:1px solid #e2e6d9}.pptxv-audio-footer audio{width:100%;min-width:0;height:44px;flex:1}.pptxv-audio-extras{display:flex;align-items:center;gap:10px}.pptxv-audio-repeat{width:30px;height:30px;border:1px solid transparent;border-radius:50%;background:transparent;font-size:22px!important}.pptxv-audio-repeat[aria-pressed=true]{color:#355d3e;border-color:#cad7bf;background:#e1ead7}.pptxv-audio-speed{max-width:68px;padding:4px;border:0;border-radius:4px;background:transparent;font-size:12px!important}@container (max-width: 560px){.pptxv-audio-body{grid-template-columns:minmax(0,1fr);gap:24px;padding:24px}.pptxv-audio-album{display:grid;grid-template-columns:112px minmax(0,1fr);column-gap:18px;align-content:center}.pptxv-audio-artwork{width:112px;grid-row:span 4;margin:0}.pptxv-audio-eyebrow{margin-bottom:6px;font-size:9px}.pptxv-audio-title{font-size:18px}.pptxv-audio-details{margin-bottom:10px;font-size:11px}.pptxv-audio-play{width:36px;height:36px;right:8px;bottom:8px}.pptxv-audio-placeholder span{font-size:28px}.pptxv-audio-lyrics{flex:none;height:230px}.pptxv-audio-footer{flex-wrap:wrap;gap:6px;padding:12px}.pptxv-audio-footer audio{flex-basis:100%}.pptxv-audio-extras{margin-left:auto}}@media (prefers-reduced-motion: reduce){.pptxv-audio-player *{transition:none!important}}.pptxv-native-preview--text{overflow:auto;background:#f8fafc}.pptxv-native-preview--html{overflow:hidden;background:#fff}.pptxv-native-html-frame{display:block;width:100%;height:100%;min-height:inherit;border:0;background:#fff}.pptxv-native-text-shell{box-sizing:border-box;min-width:100%;min-height:100%;padding:18px}.pptxv-native-text-body{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;min-width:max-content}.pptxv-native-text-gutter{box-sizing:border-box;position:sticky;left:0;z-index:1;white-space:pre;min-width:3.25rem;padding-right:14px;color:#64748b;background:#f8fafc;border-right:1px solid rgba(100,116,139,.2);font:13px/1.55 Consolas,SFMono-Regular,Liberation Mono,Menlo,monospace;text-align:right;-webkit-user-select:none;user-select:none}.pptxv-native-text{box-sizing:border-box;min-width:100%;margin:0;padding-left:14px;color:#1f2937;font:13px/1.55 Consolas,SFMono-Regular,Liberation Mono,Menlo,monospace;-moz-tab-size:2;tab-size:2;white-space:pre-wrap;overflow-wrap:anywhere}.pptxv-native-text[data-wrap=false]{white-space:pre;overflow-wrap:normal}.pptxv-native-text-shell[data-family=code]{color-scheme:dark;background:#0b1220}.pptxv-native-text-shell[data-family=code] .pptxv-native-text-gutter{color:#607089;background:#0b1220;border-right-color:#94a3b82e}.pptxv-native-text[data-family=code]{color:#d7e0ec}.pptxv-token--comment{color:#6f8f72;font-style:italic}.pptxv-token--keyword{color:#f08fc5}.pptxv-token--literal{color:#79b8ff}.pptxv-token--string{color:#e7a873}.pptxv-token--number{color:#a8d58d}.pptxv-token--property{color:#8bd5ff}.pptxv-token--tag,.pptxv-token--type{color:#67d4c0}.pptxv-token--function{color:#e8d17a}.pptxv-token--operator{color:#b9c5d6}.filens-attachments-shell,.filens-attachment-panel{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden}.filens-attachments-document,.filens-attachment-preview{flex:1;min-height:0;overflow:hidden}.filens-attachments-shell [hidden]{display:none!important}.filens-attachments,.filens-attachment-navigation{flex-shrink:0;box-sizing:border-box;padding:10px 14px;border-bottom:1px solid #d7dee8;background:#f8fafc;color:#1f2937;font:14px/1.4 system-ui,sans-serif}.filens-attachments summary{cursor:pointer}.filens-attachments ul{max-height:180px;overflow:auto;margin:8px 0 0;padding:0;list-style:none}.filens-attachments li,.filens-attachment-navigation{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.filens-attachment-navigation span{overflow-wrap:anywhere;flex:1}.filens-attachments button,.filens-attachment-navigation button{font:inherit;color:inherit;padding:5px 10px;border:1px solid #cbd5e1;border-radius:4px;background:#fff;cursor:pointer}.filens-attachments li button:first-child{text-align:left;overflow-wrap:anywhere}.filens-attachment-status{margin:12px 16px;font:14px/1.5 system-ui,sans-serif}.filens-attachment-status[role=alert]{color:#b91c1c}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { createViewer, init, PptxViewer } from './viewer';
|
|
2
|
+
export { loadPptx } from './parser/load-pptx';
|
|
3
|
+
export { openZipArchive } from './parser/zip';
|
|
4
|
+
export type { ZipEntry, ZipArchiveOptions } from './parser/zip';
|
|
5
|
+
export { attachmentFilename, readOfficeAttachments, unwrapOfficeAttachment } from './parser/attachments';
|
|
6
|
+
export * from './archive-volumes';
|
|
7
|
+
export { MediaRegistry, renderSlideToElement } from './render/dom';
|
|
8
|
+
export type { MediaResolver, RenderSlideOptions } from './render/dom';
|
|
9
|
+
export * from './preview';
|
|
10
|
+
export { bindPreviewTouchGestures, type PreviewTouchGestureOptions } from './preview/touch-gestures';
|
|
11
|
+
export { createVideoPlaybackControls, type VideoPlaybackActions, type VideoPlaybackState } from './preview/video-controls';
|
|
12
|
+
export { createVideoPreviewPlayer } from './preview/video-player';
|
|
13
|
+
export type { Model3dPreviewNode, Model3dPreviewState, PreviewDisplayMode, PreviewFontResolveRequest, PreviewFontResolveResult, PreviewFontResolver, PreviewMaterialInfo, PreviewSnapshotBackground, PreviewSectionInfo, PreviewerInstance, PreviewResourceResolveRequest, PreviewResourceResolveResult, PreviewResourceResolver, PreviewerFactory, PreviewSession } from './preview/types';
|
|
14
|
+
export type * from './types';
|