wickes-css2 2.116.0 → 2.117.0-develop.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 (32) hide show
  1. package/build/css/pages/checkout-new.css +1 -1
  2. package/build/css/pages/checkout.css +1 -1
  3. package/build/css/pages/tradePro-signup.css +1 -1
  4. package/build/css/pdp-main-non-critical.css +1 -1
  5. package/build/img/file-pdf-solid-full.svg +3 -0
  6. package/build/img/lorem_ipsum.pdf +150 -0
  7. package/build/js/emulation.min.js +151 -11
  8. package/build/js/pdf-preview.min.js +1 -0
  9. package/package.json +1 -1
  10. package/src/components/modal-capture.hbs +1 -1
  11. package/src/components/modal-id-type.hbs +271 -0
  12. package/src/components/modal-pdf-preview.hbs +70 -0
  13. package/src/components/partner-signup-form.hbs +1 -231
  14. package/src/img/file-pdf-solid-full.svg +3 -0
  15. package/src/img/lorem_ipsum.pdf +150 -0
  16. package/src/js/emulation/tradepro-id-pdf.js +182 -0
  17. package/src/js/libs/pdf-preview.js +1177 -0
  18. package/src/page_checkout_confirmation-billie.html +5 -231
  19. package/src/page_checkout_confirmation-clearpay.html +5 -231
  20. package/src/page_checkout_confirmation-new-apple.html +5 -231
  21. package/src/page_checkout_confirmation-new-google.html +5 -231
  22. package/src/page_checkout_confirmation-new-klarna.html +5 -231
  23. package/src/page_checkout_confirmation-new-paypal.html +5 -231
  24. package/src/page_pdf-preview-example.html +955 -0
  25. package/src/page_tradePro-checkout-summary-klarna.html +4 -231
  26. package/src/page_tradePro-checkout-summary.html +4 -231
  27. package/src/page_tradePro-signup.html +5 -0
  28. package/src/scss/components/_id-type-modal.scss +39 -0
  29. package/src/scss/components/_pdf-preview-modal.scss +122 -0
  30. package/src/scss/pages/_checkout-tradepro.scss +1 -0
  31. package/src/scss/pages/tradePro-signup.scss +1 -0
  32. package/src/sitemap.html +1 -0
@@ -0,0 +1,955 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>PDF Preview - standalone example</title>
7
+ <style>
8
+ /* Preview decoration. The library handles scrolling, page stacking and
9
+ spacing; this just tints the gutter so the edge of the preview is visible
10
+ and puts a shadow on the pages. */
11
+ [data-pdf-preview-pages] {
12
+ background: #e8e8e8;
13
+ }
14
+
15
+ .example-page {
16
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
17
+ }
18
+
19
+ /* Documentation layout only. None of it reaches the previews. */
20
+ .docs {
21
+ max-width: 960px;
22
+ }
23
+
24
+ .docs .table-wrap {
25
+ overflow-x: auto;
26
+ }
27
+
28
+ .docs table {
29
+ width: 100%;
30
+ border-collapse: collapse;
31
+ margin-bottom: 1em;
32
+ }
33
+
34
+ .docs th,
35
+ .docs td {
36
+ padding: 6px 8px;
37
+ border: 1px solid #ccc;
38
+ text-align: left;
39
+ vertical-align: top;
40
+ }
41
+
42
+ .docs th {
43
+ background: #f3f3f3;
44
+ }
45
+
46
+ .docs td:first-child code,
47
+ .docs td:nth-child(2) code {
48
+ white-space: nowrap;
49
+ }
50
+
51
+ .docs pre {
52
+ padding: 12px;
53
+ background: #f6f6f6;
54
+ overflow-x: auto;
55
+ }
56
+
57
+ /* Thumbnail decoration. The library only hands back a data URL and the size
58
+ to show it at; the frame and the layout below are this page's. */
59
+ .example-tiles {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 24px;
63
+ align-items: flex-start;
64
+ margin: 12px 0;
65
+ }
66
+
67
+ .example-tile {
68
+ max-width: 160px;
69
+ }
70
+
71
+ .example-tile img {
72
+ display: block;
73
+ border: 1px solid #ccc;
74
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
75
+ }
76
+
77
+ .example-tile figcaption {
78
+ margin-top: 6px;
79
+ font-size: 13px;
80
+ }
81
+ </style>
82
+ </head>
83
+ <body>
84
+
85
+ <h1>PDF Preview - standalone example</h1>
86
+ <p>
87
+ No project CSS, no project bundles and no jQuery. The only script on this page is
88
+ <code>pdf-preview.min.js</code>, a self-contained UMD library with no dependencies (pdf.js is
89
+ fetched from a CDN on first use). Text and controls in the previews are browser defaults; the
90
+ preview CSS in the head only tints the gutter and adds a shadow to the pages, so you can see what
91
+ the library gives you and what is decoration.
92
+ </p>
93
+
94
+ <h2>1. Preview a PDF from your device</h2>
95
+ <p>The component takes a <code>File</code> object straight from an input.</p>
96
+
97
+ <input type="file" id="local-file" accept="application/pdf">
98
+
99
+ <div id="local-preview" data-pdf-preview data-pdf-preview-page-class="example-page">
100
+ <div>
101
+ <button type="button" data-pdf-preview-first>&laquo; First</button>
102
+ <button type="button" data-pdf-preview-prev>&lsaquo; Prev</button>
103
+ <input type="number" min="1" value="1" aria-label="Page number" data-pdf-preview-page>
104
+ / <span data-pdf-preview-total></span>
105
+ <button type="button" data-pdf-preview-next>Next &rsaquo;</button>
106
+ <button type="button" data-pdf-preview-last>Last &raquo;</button>
107
+ </div>
108
+ <div data-pdf-preview-pages></div>
109
+ </div>
110
+
111
+ <h2>2. Preview a PDF from a URL</h2>
112
+ <p>
113
+ Add <code>data-pdf-preview-src</code> and a single <code>PdfPreview.initAll()</code> call picks
114
+ it up and loads it. Options can be set declaratively on the root element.
115
+ </p>
116
+
117
+ <div
118
+ id="remote-preview"
119
+ data-pdf-preview
120
+ data-pdf-preview-src="img/lorem_ipsum.pdf"
121
+ data-pdf-preview-scale="1"
122
+ data-pdf-preview-height="500px"
123
+ data-pdf-preview-spacing="24"
124
+ data-pdf-preview-page-class="example-page"
125
+ >
126
+ <div>
127
+ <button type="button" data-pdf-preview-first>&laquo; First</button>
128
+ <button type="button" data-pdf-preview-prev>&lsaquo; Prev</button>
129
+ <input type="number" min="1" value="1" aria-label="Page number" data-pdf-preview-page>
130
+ / <span data-pdf-preview-total></span>
131
+ <button type="button" data-pdf-preview-next>Next &rsaquo;</button>
132
+ <button type="button" data-pdf-preview-last>Last &raquo;</button>
133
+ </div>
134
+ <div data-pdf-preview-pages></div>
135
+ </div>
136
+
137
+ <h2>3. Thumbnail of the first page</h2>
138
+ <p>
139
+ A thumbnail is one page drawn to an offscreen canvas and handed back as a data URL, ready for the
140
+ <code>src</code> of an <code>&lt;img&gt;</code>. It needs no preview and no root element. The tile
141
+ on the left is filled from markup alone; pick a file to fill the second one.
142
+ </p>
143
+
144
+ <div class="example-tiles">
145
+ <figure class="example-tile">
146
+ <img
147
+ data-pdf-thumbnail
148
+ data-pdf-thumbnail-src="img/lorem_ipsum.pdf"
149
+ data-pdf-thumbnail-width="120"
150
+ alt="First page of lorem_ipsum.pdf"
151
+ >
152
+ <figcaption>From markup: <code>data-pdf-thumbnail-src</code></figcaption>
153
+ </figure>
154
+
155
+ <figure class="example-tile">
156
+ <img id="local-thumbnail" alt="" hidden>
157
+ <input type="file" id="local-thumbnail-file" accept="application/pdf">
158
+ <figcaption id="local-thumbnail-caption">From a file on your device.</figcaption>
159
+ </figure>
160
+ </div>
161
+
162
+ <div class="docs">
163
+
164
+ <h2>Documentation</h2>
165
+
166
+ <h3>Getting started</h3>
167
+ <p>
168
+ Add a root element with a pages container inside it, create a preview for the root and load a
169
+ document into it. Every control is optional; leave out the ones you do not need.
170
+ </p>
171
+ <pre>&lt;div id="preview" data-pdf-preview&gt;
172
+ &lt;button type="button" data-pdf-preview-prev&gt;Prev&lt;/button&gt;
173
+ &lt;input type="number" data-pdf-preview-page&gt; / &lt;span data-pdf-preview-total&gt;&lt;/span&gt;
174
+ &lt;button type="button" data-pdf-preview-next&gt;Next&lt;/button&gt;
175
+ &lt;div data-pdf-preview-pages&gt;&lt;/div&gt;
176
+ &lt;/div&gt;
177
+
178
+ &lt;script src="pdf-preview.min.js"&gt;&lt;/script&gt;
179
+ &lt;script&gt;
180
+ var preview = new PdfPreview('#preview', { height: '70vh' });
181
+
182
+ preview.load(file); // a File, a Blob or a URL
183
+ &lt;/script&gt;</pre>
184
+ <p>
185
+ To set everything up from markup instead, put the options on the root as <code>data-</code>
186
+ attributes (see <a href="#options">Options</a>) and call <code>PdfPreview.initAll()</code> once.
187
+ A root with <code>data-pdf-preview-src</code> starts loading straight away.
188
+ </p>
189
+
190
+ <h3 id="options">Options</h3>
191
+ <p>
192
+ Pass options as the second argument of <code>new PdfPreview()</code> or
193
+ <code>PdfPreview.initAll()</code>, or as <code>data-</code> attributes on the root element. When
194
+ both are given, the JavaScript value wins. Options are read once, when the preview is created.
195
+ </p>
196
+ <div class="table-wrap">
197
+ <table>
198
+ <thead>
199
+ <tr>
200
+ <th>Option</th>
201
+ <th>Attribute</th>
202
+ <th>Type</th>
203
+ <th>Default</th>
204
+ <th>Description</th>
205
+ </tr>
206
+ </thead>
207
+ <tbody>
208
+ <tr>
209
+ <td><code>src</code></td>
210
+ <td><code>data-pdf-preview-src</code></td>
211
+ <td>string</td>
212
+ <td>none</td>
213
+ <td>URL of a PDF to load as soon as the preview is created. Same as calling <code>load(url)</code>.</td>
214
+ </tr>
215
+ <tr>
216
+ <td><code>fitWidth</code></td>
217
+ <td><code>data-pdf-preview-fit-width</code></td>
218
+ <td>boolean</td>
219
+ <td><code>true</code></td>
220
+ <td>
221
+ Sizes every page to the width of the pages container. <code>false</code> draws pages at
222
+ the PDF's own size multiplied by <code>scale</code>, never wider than the container. As
223
+ an attribute, only <code>"false"</code> turns it off.
224
+ </td>
225
+ </tr>
226
+ <tr>
227
+ <td><code>scale</code></td>
228
+ <td><code>data-pdf-preview-scale</code></td>
229
+ <td>number</td>
230
+ <td><code>1.5</code></td>
231
+ <td>
232
+ Page size relative to the PDF's own size. Used when <code>fitWidth</code> is
233
+ <code>false</code>, or when the container has no width at load time.
234
+ </td>
235
+ </tr>
236
+ <tr>
237
+ <td><code>maxPixelRatio</code></td>
238
+ <td><code>data-pdf-preview-max-pixel-ratio</code></td>
239
+ <td>number</td>
240
+ <td><code>2</code></td>
241
+ <td>
242
+ Upper limit on the screen density pages are drawn at. A higher value is sharper on dense
243
+ screens but uses more memory. See <a href="#sharpness">Sharpness</a>.
244
+ </td>
245
+ </tr>
246
+ <tr>
247
+ <td><code>height</code></td>
248
+ <td><code>data-pdf-preview-height</code></td>
249
+ <td>number | string</td>
250
+ <td><code>'50vh'</code></td>
251
+ <td>
252
+ Maximum height of the pages container, which scrolls once the pages are taller. Any CSS
253
+ length; bare numbers are px. <code>'none'</code> removes the limit, so the pages flow with
254
+ the page around them. Set as <code>--pdfp-height</code>.
255
+ </td>
256
+ </tr>
257
+ <tr>
258
+ <td><code>spacing</code></td>
259
+ <td><code>data-pdf-preview-spacing</code></td>
260
+ <td>number | string</td>
261
+ <td><code>16px</code></td>
262
+ <td>
263
+ Gap between pages and padding around them. Any CSS length; bare numbers are px. Give the
264
+ container a background colour to make the gutter visible. Set as
265
+ <code>--pdfp-spacing</code>.
266
+ </td>
267
+ </tr>
268
+ <tr>
269
+ <td><code>pageClass</code></td>
270
+ <td><code>data-pdf-preview-page-class</code></td>
271
+ <td>string</td>
272
+ <td><code>''</code></td>
273
+ <td>Extra class added to every page canvas, for your own styling. Separate several classes with spaces.</td>
274
+ </tr>
275
+ <tr>
276
+ <td><code>injectStyles</code></td>
277
+ <td>-</td>
278
+ <td>boolean</td>
279
+ <td><code>true</code></td>
280
+ <td>
281
+ Adds the base layout styles and the <code>pdfp-</code> classes. <code>false</code> leaves
282
+ all layout to your CSS. See <a href="#styling">Styling</a>.
283
+ </td>
284
+ </tr>
285
+ <tr>
286
+ <td><code>pdfjsLib</code></td>
287
+ <td>-</td>
288
+ <td>object</td>
289
+ <td>none</td>
290
+ <td>
291
+ pdf.js instance to use instead of fetching one. A <code>window.pdfjsLib</code> already on
292
+ the page is used the same way. Set its <code>GlobalWorkerOptions.workerSrc</code>
293
+ yourself.
294
+ </td>
295
+ </tr>
296
+ <tr>
297
+ <td><code>pdfjsUrl</code></td>
298
+ <td>-</td>
299
+ <td>string</td>
300
+ <td>pdf.js 3.11.174 on cdnjs</td>
301
+ <td>Script fetched when no pdf.js is available. It is fetched once per page, by the first preview that loads a document.</td>
302
+ </tr>
303
+ <tr>
304
+ <td><code>pdfjsWorkerUrl</code></td>
305
+ <td>-</td>
306
+ <td>string</td>
307
+ <td>pdf.js 3.11.174 worker on cdnjs</td>
308
+ <td>Worker script for the pdf.js fetched from <code>pdfjsUrl</code>.</td>
309
+ </tr>
310
+ <tr>
311
+ <td><code>selectors</code></td>
312
+ <td>-</td>
313
+ <td>object</td>
314
+ <td>see <a href="#markup">Markup hooks</a></td>
315
+ <td>
316
+ Replaces any of the markup hook selectors for this preview, for example
317
+ <code>{ next: '.js-next' }</code>. Keys you leave out keep their defaults.
318
+ </td>
319
+ </tr>
320
+ </tbody>
321
+ </table>
322
+ </div>
323
+
324
+ <h3 id="markup">Markup hooks</h3>
325
+ <p>
326
+ The library finds its elements with these selectors, inside the root. Everything except the root
327
+ is optional. Rename any of them with the <code>selectors</code> option, so another project does not
328
+ have to use these attribute names.
329
+ </p>
330
+ <div class="table-wrap">
331
+ <table>
332
+ <thead>
333
+ <tr>
334
+ <th>Key</th>
335
+ <th>Default selector</th>
336
+ <th>Element</th>
337
+ <th>Description</th>
338
+ </tr>
339
+ </thead>
340
+ <tbody>
341
+ <tr>
342
+ <td><code>root</code></td>
343
+ <td><code>[data-pdf-preview]</code></td>
344
+ <td>any</td>
345
+ <td>
346
+ Wraps the preview and its controls. <code>initAll()</code> looks for it; when you create
347
+ a preview yourself you pass the element, so no attribute is needed.
348
+ </td>
349
+ </tr>
350
+ <tr>
351
+ <td><code>pages</code></td>
352
+ <td><code>[data-pdf-preview-pages]</code></td>
353
+ <td>any</td>
354
+ <td>Container the pages are drawn into, and the one that scrolls. Falls back to the root when missing.</td>
355
+ </tr>
356
+ <tr>
357
+ <td><code>first</code></td>
358
+ <td><code>[data-pdf-preview-first]</code></td>
359
+ <td>button</td>
360
+ <td>Goes to the first page.</td>
361
+ </tr>
362
+ <tr>
363
+ <td><code>prev</code></td>
364
+ <td><code>[data-pdf-preview-prev]</code></td>
365
+ <td>button</td>
366
+ <td>Goes to the previous page.</td>
367
+ </tr>
368
+ <tr>
369
+ <td><code>next</code></td>
370
+ <td><code>[data-pdf-preview-next]</code></td>
371
+ <td>button</td>
372
+ <td>Goes to the next page.</td>
373
+ </tr>
374
+ <tr>
375
+ <td><code>last</code></td>
376
+ <td><code>[data-pdf-preview-last]</code></td>
377
+ <td>button</td>
378
+ <td>Goes to the last page.</td>
379
+ </tr>
380
+ <tr>
381
+ <td><code>pageInput</code></td>
382
+ <td><code>[data-pdf-preview-page]</code></td>
383
+ <td>input</td>
384
+ <td>
385
+ Shows the current page and follows scrolling. Entering a number goes to that page; an
386
+ out-of-range number is put back to the current page.
387
+ </td>
388
+ </tr>
389
+ <tr>
390
+ <td><code>pageTotal</code></td>
391
+ <td><code>[data-pdf-preview-total]</code></td>
392
+ <td>any</td>
393
+ <td>Its text is set to the number of pages.</td>
394
+ </tr>
395
+ </tbody>
396
+ </table>
397
+ </div>
398
+
399
+ <h3>Methods</h3>
400
+ <div class="table-wrap">
401
+ <table>
402
+ <thead>
403
+ <tr>
404
+ <th>Method</th>
405
+ <th>Returns</th>
406
+ <th>Description</th>
407
+ </tr>
408
+ </thead>
409
+ <tbody>
410
+ <tr>
411
+ <td><code>new PdfPreview(target, options)</code></td>
412
+ <td>preview</td>
413
+ <td>
414
+ Creates a preview on <code>target</code>: a selector, an element or a jQuery object. If
415
+ the element already has a preview, that one is returned and <code>options</code> are
416
+ ignored. Throws when the element is not found.
417
+ </td>
418
+ </tr>
419
+ <tr>
420
+ <td><code>load(source)</code></td>
421
+ <td>Promise</td>
422
+ <td>
423
+ Shows a PDF from a <code>File</code>, a <code>Blob</code> or a URL, replacing any document
424
+ already shown. Resolves with the pdf.js document once every page is drawn, or with
425
+ <code>undefined</code> when a later <code>load()</code>, <code>reset()</code> or
426
+ <code>destroy()</code> cancels it. Rejects when the PDF cannot be shown.
427
+ </td>
428
+ </tr>
429
+ <tr>
430
+ <td><code>reset()</code></td>
431
+ <td>-</td>
432
+ <td>Cancels any load in progress, removes the pages and frees the document. The preview stays usable.</td>
433
+ </tr>
434
+ <tr>
435
+ <td><code>goToPage(page)</code></td>
436
+ <td>preview</td>
437
+ <td>Scrolls to page <code>page</code>, counting from 1. Page numbers out of range are ignored.</td>
438
+ </tr>
439
+ <tr>
440
+ <td><code>getCurrentPage()</code></td>
441
+ <td>number</td>
442
+ <td>Page closest to the middle of the view. <code>1</code> when nothing is loaded.</td>
443
+ </tr>
444
+ <tr>
445
+ <td><code>getPageCount()</code></td>
446
+ <td>number</td>
447
+ <td>Number of pages in the document. <code>0</code> when nothing is loaded.</td>
448
+ </tr>
449
+ <tr>
450
+ <td><code>destroy()</code></td>
451
+ <td>-</td>
452
+ <td>
453
+ Resets the preview, removes its listeners and detaches it from the element. Your markup is
454
+ left in place, so a new preview can be created on it.
455
+ </td>
456
+ </tr>
457
+ <tr>
458
+ <td><code>getThumbnail(options)</code></td>
459
+ <td>Promise</td>
460
+ <td>
461
+ Thumbnail of the document this preview already has open, without reading the file again.
462
+ See <a href="#thumbnails">Thumbnails</a>.
463
+ </td>
464
+ </tr>
465
+ <tr>
466
+ <td><code>PdfPreview.get(target)</code></td>
467
+ <td>preview | null</td>
468
+ <td>The preview already created on <code>target</code>, or <code>null</code>.</td>
469
+ </tr>
470
+ <tr>
471
+ <td><code>PdfPreview.initAll(scope, options)</code></td>
472
+ <td>array</td>
473
+ <td>
474
+ Creates a preview for every root inside <code>scope</code> (default: the whole document),
475
+ passing <code>options</code> to each. Returns the previews.
476
+ </td>
477
+ </tr>
478
+ <tr>
479
+ <td><code>PdfPreview.thumbnail(source, options)</code></td>
480
+ <td>Promise</td>
481
+ <td>
482
+ Thumbnail of one page of a <code>File</code>, <code>Blob</code> or URL, as a data URL. No
483
+ preview and no element needed. See <a href="#thumbnails">Thumbnails</a>.
484
+ </td>
485
+ </tr>
486
+ <tr>
487
+ <td><code>PdfPreview.thumbnailInto(target, source, options)</code></td>
488
+ <td>Promise</td>
489
+ <td>
490
+ The same, rendered straight into an <code>&lt;img&gt;</code>. See
491
+ <a href="#thumbnails">Thumbnails</a>.
492
+ </td>
493
+ </tr>
494
+ <tr>
495
+ <td><code>PdfPreview.initThumbnails(scope, options)</code></td>
496
+ <td>array</td>
497
+ <td>
498
+ Fills every <code>[data-pdf-thumbnail]</code> inside <code>scope</code> (default: the
499
+ whole document) from its <code>data-pdf-thumbnail-src</code>. Returns a promise per
500
+ element. Elements already handled are skipped.
501
+ </td>
502
+ </tr>
503
+ <tr>
504
+ <td><code>PdfPreview.defaults</code></td>
505
+ <td>object</td>
506
+ <td>Default options. Changing a value before previews are created changes it for all of them.</td>
507
+ </tr>
508
+ <tr>
509
+ <td><code>PdfPreview.thumbnailDefaults</code></td>
510
+ <td>object</td>
511
+ <td>Default thumbnail options. Changing a value changes it for every thumbnail drawn afterwards.</td>
512
+ </tr>
513
+ <tr>
514
+ <td><code>PdfPreview.selectors</code></td>
515
+ <td>object</td>
516
+ <td>Default markup hook selectors. Changing a value before previews are created changes it for all of them.</td>
517
+ </tr>
518
+ <tr>
519
+ <td><code>PdfPreview.classes</code></td>
520
+ <td>object</td>
521
+ <td>Names of the classes the library adds, for reference. Do not change them.</td>
522
+ </tr>
523
+ </tbody>
524
+ </table>
525
+ </div>
526
+
527
+ <h3>Events</h3>
528
+ <p>Dispatched on the root element. All of them bubble, so you can also listen higher up.</p>
529
+ <div class="table-wrap">
530
+ <table>
531
+ <thead>
532
+ <tr>
533
+ <th>Event</th>
534
+ <th>Detail</th>
535
+ <th>Description</th>
536
+ </tr>
537
+ </thead>
538
+ <tbody>
539
+ <tr>
540
+ <td><code>pdfpreview:loaded</code></td>
541
+ <td><code>{ pageCount }</code></td>
542
+ <td>
543
+ The document has opened and its page count is known. Pages are drawn after this; the
544
+ promise from <code>load()</code> resolves once they are all drawn.
545
+ </td>
546
+ </tr>
547
+ <tr>
548
+ <td><code>pdfpreview:pagechange</code></td>
549
+ <td><code>{ page }</code></td>
550
+ <td>
551
+ The current page changed, by scrolling or through the controls. Currently only fired when
552
+ the preview has a <code>pageInput</code> element.
553
+ </td>
554
+ </tr>
555
+ <tr>
556
+ <td><code>pdfpreview:error</code></td>
557
+ <td><code>{ error }</code></td>
558
+ <td>
559
+ The PDF could not be shown: the file is damaged or password-protected, or pdf.js failed to
560
+ load. Not fired for loads that were cancelled.
561
+ </td>
562
+ </tr>
563
+ </tbody>
564
+ </table>
565
+ </div>
566
+ <pre>document.querySelector('#local-preview')
567
+ .addEventListener('pdfpreview:loaded', function (e) {
568
+ console.log('pages:', e.detail.pageCount);
569
+ });</pre>
570
+
571
+ <h3 id="thumbnails">Thumbnails</h3>
572
+ <p>
573
+ A thumbnail is one page of a PDF (the first, unless you ask for another) drawn to an offscreen
574
+ canvas and handed back as a data URL. The canvas is thrown away, so what you hold on to is a
575
+ string you can put in an <code>&lt;img&gt;</code>, store, or pass around. There is no pagination,
576
+ no scrolling container and no root element: a thumbnail is a still image, and sits anywhere an
577
+ image does.
578
+ </p>
579
+ <p>
580
+ Thumbnails resolve with the data URL and the size to show it at, in CSS px:
581
+ <code>{ dataUrl, width, height, page, pageCount }</code>.
582
+ </p>
583
+
584
+ <h4>Fill an &lt;img&gt; yourself</h4>
585
+ <p>
586
+ <code>PdfPreview.thumbnail()</code> takes the same sources as <code>load()</code>: a
587
+ <code>File</code>, a <code>Blob</code> or a URL.
588
+ </p>
589
+ <pre>&lt;img id="thumb" alt="First page of the document"&gt;
590
+
591
+ &lt;script src="pdf-preview.min.js"&gt;&lt;/script&gt;
592
+ &lt;script&gt;
593
+ var img = document.getElementById('thumb');
594
+
595
+ PdfPreview.thumbnail('invoice.pdf', { width: 120 })
596
+ .then(function (thumb) {
597
+ img.src = thumb.dataUrl;
598
+ img.width = thumb.width; // keeps the tile from jumping
599
+ img.height = thumb.height;
600
+ })
601
+ .catch(function (error) {
602
+ console.warn('no thumbnail:', error); // leave the fallback icon in place
603
+ });
604
+ &lt;/script&gt;</pre>
605
+
606
+ <h4>Straight from a file input</h4>
607
+ <p>
608
+ <code>PdfPreview.thumbnailInto()</code> does the same and sets <code>src</code>,
609
+ <code>width</code> and <code>height</code> on the element for you. On failure it leaves the
610
+ element alone, so whatever it already shows stays visible.
611
+ </p>
612
+ <pre>document.getElementById('file').addEventListener('change', function (event) {
613
+ var file = event.target.files[0];
614
+
615
+ if (file &amp;&amp; file.type === 'application/pdf') {
616
+ PdfPreview.thumbnailInto('#thumb', file, { width: 120 });
617
+ }
618
+ });</pre>
619
+
620
+ <h4>From markup</h4>
621
+ <p>
622
+ Put the source and any options on the <code>&lt;img&gt;</code> as <code>data-</code> attributes
623
+ and call <code>PdfPreview.initThumbnails()</code> once, the same way
624
+ <code>PdfPreview.initAll()</code> works for previews. Calling it again picks up newly added
625
+ elements and skips the ones already done, so it is safe after rendering more markup.
626
+ </p>
627
+ <pre>&lt;img
628
+ data-pdf-thumbnail
629
+ data-pdf-thumbnail-src="invoice.pdf"
630
+ data-pdf-thumbnail-width="120"
631
+ alt="First page of invoice.pdf"
632
+ &gt;
633
+
634
+ &lt;script&gt;PdfPreview.initThumbnails();&lt;/script&gt;</pre>
635
+
636
+ <h4>Alongside a preview</h4>
637
+ <p>
638
+ When a preview already has the document open, ask it for the thumbnail instead. The file is read
639
+ and parsed once and both come out of the same document, which is the cheapest option when you
640
+ show a tile and a full preview of the same upload.
641
+ </p>
642
+ <pre>var preview = new PdfPreview('#preview');
643
+
644
+ preview.load(file).then(function () {
645
+ return preview.getThumbnail({ width: 120 });
646
+ }).then(function (thumb) {
647
+ document.getElementById('thumb').src = thumb.dataUrl;
648
+ });</pre>
649
+
650
+ <h4 id="thumbnail-options">Thumbnail options</h4>
651
+ <p>
652
+ Pass these as the last argument of <code>thumbnail()</code>, <code>thumbnailInto()</code>,
653
+ <code>initThumbnails()</code> or <code>getThumbnail()</code>, or as <code>data-</code> attributes
654
+ on the element. When both are given, the JavaScript value wins.
655
+ </p>
656
+ <div class="table-wrap">
657
+ <table>
658
+ <thead>
659
+ <tr>
660
+ <th>Option</th>
661
+ <th>Attribute</th>
662
+ <th>Type</th>
663
+ <th>Default</th>
664
+ <th>Description</th>
665
+ </tr>
666
+ </thead>
667
+ <tbody>
668
+ <tr>
669
+ <td><code>src</code></td>
670
+ <td><code>data-pdf-thumbnail-src</code></td>
671
+ <td>string</td>
672
+ <td>none</td>
673
+ <td>
674
+ URL of the PDF. Used by <code>initThumbnails()</code>, and by
675
+ <code>thumbnailInto()</code> when no source is passed.
676
+ </td>
677
+ </tr>
678
+ <tr>
679
+ <td><code>width</code></td>
680
+ <td><code>data-pdf-thumbnail-width</code></td>
681
+ <td>number</td>
682
+ <td><code>160</code></td>
683
+ <td>Width in CSS px to draw the page at. The height follows from the page's aspect ratio.</td>
684
+ </tr>
685
+ <tr>
686
+ <td><code>height</code></td>
687
+ <td><code>data-pdf-thumbnail-height</code></td>
688
+ <td>number</td>
689
+ <td>none</td>
690
+ <td>
691
+ Height in CSS px. On its own it drives the size; with <code>width</code> the page is
692
+ fitted inside the box, so a landscape page comes out shorter than the box rather than
693
+ stretched.
694
+ </td>
695
+ </tr>
696
+ <tr>
697
+ <td><code>page</code></td>
698
+ <td><code>data-pdf-thumbnail-page</code></td>
699
+ <td>number</td>
700
+ <td><code>1</code></td>
701
+ <td>Page to draw, counting from 1. Numbers past the end are clamped to the last page.</td>
702
+ </tr>
703
+ <tr>
704
+ <td><code>type</code></td>
705
+ <td><code>data-pdf-thumbnail-type</code></td>
706
+ <td>string</td>
707
+ <td><code>'image/jpeg'</code></td>
708
+ <td>
709
+ Image format of the data URL. <code>'image/png'</code> is sharper on small text and much
710
+ larger; anything the browser's <code>canvas.toDataURL()</code> supports works.
711
+ </td>
712
+ </tr>
713
+ <tr>
714
+ <td><code>quality</code></td>
715
+ <td><code>data-pdf-thumbnail-quality</code></td>
716
+ <td>number</td>
717
+ <td><code>0.85</code></td>
718
+ <td>Quality from 0 to 1, for lossy formats. Ignored for PNG.</td>
719
+ </tr>
720
+ <tr>
721
+ <td><code>background</code></td>
722
+ <td>-</td>
723
+ <td>string</td>
724
+ <td><code>'#ffffff'</code></td>
725
+ <td>
726
+ Colour drawn behind the page. A PDF page carries no background of its own, so this is what
727
+ shows through its margins.
728
+ </td>
729
+ </tr>
730
+ <tr>
731
+ <td><code>maxPixelRatio</code></td>
732
+ <td>-</td>
733
+ <td>number</td>
734
+ <td><code>2</code></td>
735
+ <td>
736
+ As for previews: the limit on the screen density the page is drawn at. See
737
+ <a href="#sharpness">Sharpness</a>.
738
+ </td>
739
+ </tr>
740
+ <tr>
741
+ <td><code>pdfjsLib</code>, <code>pdfjsUrl</code>, <code>pdfjsWorkerUrl</code></td>
742
+ <td>-</td>
743
+ <td>object | string</td>
744
+ <td>as above</td>
745
+ <td>
746
+ Same meaning as for previews, and the same pdf.js: whichever of a preview or a thumbnail
747
+ runs first fetches it, and the rest reuse it.
748
+ </td>
749
+ </tr>
750
+ </tbody>
751
+ </table>
752
+ </div>
753
+
754
+ <h4>Thumbnail events</h4>
755
+ <p>
756
+ Dispatched on the <code>&lt;img&gt;</code> by <code>thumbnailInto()</code> and
757
+ <code>initThumbnails()</code>, so markup-driven thumbnails can be followed without holding on to
758
+ a promise. Both bubble.
759
+ </p>
760
+ <div class="table-wrap">
761
+ <table>
762
+ <thead>
763
+ <tr>
764
+ <th>Event</th>
765
+ <th>Detail</th>
766
+ <th>Description</th>
767
+ </tr>
768
+ </thead>
769
+ <tbody>
770
+ <tr>
771
+ <td><code>pdfthumbnail:loaded</code></td>
772
+ <td><code>{ dataUrl, width, height, page, pageCount }</code></td>
773
+ <td>The thumbnail is drawn and the element's <code>src</code> has been set.</td>
774
+ </tr>
775
+ <tr>
776
+ <td><code>pdfthumbnail:error</code></td>
777
+ <td><code>{ error }</code></td>
778
+ <td>
779
+ The thumbnail could not be drawn: the file is damaged or password-protected, the URL could
780
+ not be fetched, or pdf.js failed to load. The element is left as it was.
781
+ </td>
782
+ </tr>
783
+ </tbody>
784
+ </table>
785
+ </div>
786
+ <pre>document.addEventListener('pdfthumbnail:error', function (e) {
787
+ e.target.closest('.upload').classList.add('upload--no-thumbnail');
788
+ });</pre>
789
+
790
+ <h4>Notes</h4>
791
+ <ul>
792
+ <li>
793
+ Give the <code>&lt;img&gt;</code> a meaningful <code>alt</code>, naming the document the
794
+ thumbnail is of. The library never sets one, since only the calling code knows what the file is.
795
+ </li>
796
+ <li>
797
+ Nothing is kept alive once a thumbnail resolves: the document is closed and any object URL for a
798
+ <code>File</code> is revoked. The data URL is all that remains, so it is worth keeping tiles
799
+ small, which is why the default format is JPEG.
800
+ </li>
801
+ <li>
802
+ Unlike previews, thumbnails do not measure the page, so they can be drawn into a hidden or
803
+ not-yet-shown element, a modal included.
804
+ </li>
805
+ <li>
806
+ Thumbnails from <code>getThumbnail()</code> resolve with <code>undefined</code> when a later
807
+ <code>load()</code>, <code>reset()</code> or <code>destroy()</code> replaces the document while
808
+ the thumbnail is being drawn, matching how <code>load()</code> behaves.
809
+ </li>
810
+ </ul>
811
+
812
+ <h3 id="styling">Styling</h3>
813
+ <p>
814
+ The library brings layout only: a scrolling pages container with the pages stacked inside it.
815
+ Everything visual is up to you. The base styles are added at the very top of
816
+ <code>&lt;head&gt;</code>, so any rule in your own stylesheet wins over them. To change the
817
+ height or spacing from CSS, set the real property (<code>max-height</code>,
818
+ <code>padding</code>, <code>margin-top</code>) rather than the custom property, which the
819
+ options set on the element itself.
820
+ </p>
821
+ <div class="table-wrap">
822
+ <table>
823
+ <thead>
824
+ <tr>
825
+ <th>Hook</th>
826
+ <th>Set on</th>
827
+ <th>Description</th>
828
+ </tr>
829
+ </thead>
830
+ <tbody>
831
+ <tr>
832
+ <td><code>.pdfp-pages</code></td>
833
+ <td>pages container</td>
834
+ <td>Scrolling, maximum height and padding. Only added when <code>injectStyles</code> is on.</td>
835
+ </tr>
836
+ <tr>
837
+ <td><code>.pdfp-page</code></td>
838
+ <td>each page canvas</td>
839
+ <td>Stacks the pages and sets the gap between them. Only added when <code>injectStyles</code> is on.</td>
840
+ </tr>
841
+ <tr>
842
+ <td><code>.pdfp-page--auto</code></td>
843
+ <td>each page canvas</td>
844
+ <td>Natural-size pages, when <code>fitWidth</code> is <code>false</code>. Only added when <code>injectStyles</code> is on.</td>
845
+ </tr>
846
+ <tr>
847
+ <td><code>data-page</code></td>
848
+ <td>each page canvas</td>
849
+ <td>The page number, from 1. Always set.</td>
850
+ </tr>
851
+ <tr>
852
+ <td><code>--pdfp-height</code></td>
853
+ <td>pages container</td>
854
+ <td>Value of the <code>height</code> option.</td>
855
+ </tr>
856
+ <tr>
857
+ <td><code>--pdfp-spacing</code></td>
858
+ <td>pages container</td>
859
+ <td>Value of the <code>spacing</code> option. Only set when the option is given; the base styles fall back to <code>16px</code>.</td>
860
+ </tr>
861
+ <tr>
862
+ <td><code>--pdfp-page-width</code></td>
863
+ <td>each page canvas</td>
864
+ <td>
865
+ The width the page is meant to be shown at. The base styles use it for natural-size pages;
866
+ use it yourself when <code>injectStyles</code> is off.
867
+ </td>
868
+ </tr>
869
+ </tbody>
870
+ </table>
871
+ </div>
872
+ <p>
873
+ The custom properties are set even when <code>injectStyles</code> is off, so your own CSS can use
874
+ them, for example <code>max-height: var(--pdfp-height)</code>.
875
+ </p>
876
+
877
+ <h3 id="sharpness">Sharpness</h3>
878
+ <p>
879
+ Pages are drawn at the size they are shown multiplied by the device pixel ratio (capped by
880
+ <code>maxPixelRatio</code>), so they stay sharp on dense screens without wasting memory on others.
881
+ Very large pages are scaled down to stay within the largest canvas iOS Safari will draw.
882
+ </p>
883
+ <p>
884
+ The container width is measured when a document loads, so load into a visible container. In a
885
+ modal, call <code>load()</code> once the modal is shown. A container with no width falls back to
886
+ <code>scale</code>. Pages are not redrawn when the container is resized; the layout stays correct,
887
+ but they may look slightly soft until the next load.
888
+ </p>
889
+
890
+ <h3>Security</h3>
891
+ <p>
892
+ Every document is opened with pdf.js's <code>isEvalSupported</code> set to <code>false</code>,
893
+ for thumbnails as much as for previews.
894
+ With it on (the pdf.js default), pdf.js turns font glyphs into code with
895
+ <code>new Function()</code>, and in versions before 4.2.67 a crafted PDF can use that to run its
896
+ own script on the page showing it (CVE-2024-4367). With it off, glyphs are interpreted instead,
897
+ which is slightly slower. The setting is passed each time a document is opened, so it also covers a
898
+ pdf.js supplied through <code>pdfjsLib</code>. Treat this as a safeguard, not a substitute for
899
+ keeping pdf.js up to date, especially where staff open PDFs uploaded by customers.
900
+ </p>
901
+
902
+ <h3>Module formats</h3>
903
+ <p>
904
+ The library is wrapped in UMD, so it works as a global (<code>window.PdfPreview</code>), via
905
+ CommonJS (<code>require('pdf-preview')</code>) or with AMD.
906
+ </p>
907
+
908
+ </div>
909
+
910
+ <script src="./js/pdf-preview.min.js"></script>
911
+ <script>
912
+ // Picks up every [data-pdf-preview] on the page, including the one with
913
+ // data-pdf-preview-src, which starts loading straight away.
914
+ PdfPreview.initAll();
915
+
916
+ // Same again for thumbnails: every [data-pdf-thumbnail] is filled from its
917
+ // data-pdf-thumbnail-src.
918
+ PdfPreview.initThumbnails();
919
+
920
+ document.getElementById('local-file').addEventListener('change', function (event) {
921
+ var file = event.target.files && event.target.files[0];
922
+
923
+ if (file) {
924
+ new PdfPreview('#local-preview').load(file);
925
+ }
926
+ });
927
+
928
+ document.getElementById('local-thumbnail-file').addEventListener('change', function (event) {
929
+ var file = event.target.files && event.target.files[0];
930
+ var image = document.getElementById('local-thumbnail');
931
+ var caption = document.getElementById('local-thumbnail-caption');
932
+
933
+ if (!file) {
934
+ return;
935
+ }
936
+
937
+ caption.textContent = 'Drawing...';
938
+
939
+ PdfPreview.thumbnailInto(image, file, { width: 120 })
940
+ .then(function (thumbnail) {
941
+ image.alt = 'First page of ' + file.name;
942
+ image.hidden = false;
943
+ caption.textContent =
944
+ file.name + ' - page 1 of ' + thumbnail.pageCount + ', shown at ' +
945
+ thumbnail.width + ' x ' + thumbnail.height + ' px';
946
+ })
947
+ .catch(function (error) {
948
+ image.hidden = true;
949
+ caption.textContent = 'Could not draw a thumbnail: ' + error.message;
950
+ });
951
+ });
952
+ </script>
953
+
954
+ </body>
955
+ </html>