@projektemacher/storymapjs 0.10.8 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG +81 -0
- package/README.md +129 -12
- package/dist/assets/{demo-DBpeF31K.js → demo-bWnOyfUw.js} +1 -1
- package/dist/assets/harness-C3JUv5Ii.js +1 -0
- package/dist/assets/{harness-multi-CYHgI0a9.js → harness-multi-XZNex3tb.js} +1 -1
- package/dist/assets/{harness-support-Do7sIp2j.js → harness-support-CjfZIVeb.js} +1 -1
- package/dist/assets/main-DQ32hWBM.js +17 -0
- package/dist/context.json +13 -2
- package/dist/css/storymap.css +1 -1
- package/dist/demo.html +3 -2
- package/dist/docs/api/assets/navigation.js +1 -1
- package/dist/docs/api/assets/search.js +1 -1
- package/dist/docs/api/classes/StoryMap.html +777 -269
- package/dist/docs/api/functions/MediaType.html +1 -1
- package/dist/docs/api/functions/isPresentation3Collection.html +1 -1
- package/dist/docs/api/functions/isPresentation3Manifest.html +1 -1
- package/dist/docs/api/functions/isSlideshowCollection.html +51 -0
- package/dist/docs/api/functions/loadCSS.html +1 -1
- package/dist/docs/api/functions/manifestToStorymapData.html +1 -1
- package/dist/docs/api/functions/setLanguage.html +1 -1
- package/dist/docs/api/functions/slideshowToStorymapData.html +51 -0
- package/dist/docs/api/functions/slideshowVersion.html +48 -0
- package/dist/docs/api/functions/storymapToManifest.html +1 -1
- package/dist/docs/api/functions/validateStorymap.html +1 -1
- package/dist/docs/api/functions/validateStorymapAndReport.html +1 -1
- package/dist/docs/api/index.html +115 -12
- package/dist/docs/api/interfaces/AnimationHandle.html +2 -2
- package/dist/docs/api/interfaces/ImagereadyPayload.html +4 -4
- package/dist/docs/api/interfaces/LanguageEntry.html +6 -6
- package/dist/docs/api/interfaces/LatLngLiteral.html +4 -4
- package/dist/docs/api/interfaces/LoadOptions.html +2 -2
- package/dist/docs/api/interfaces/MapEvents.html +116 -0
- package/dist/docs/api/interfaces/MapMarkerEvents.html +66 -0
- package/dist/docs/api/interfaces/MarkerEventPayload.html +57 -0
- package/dist/docs/api/interfaces/MediaEvents.html +78 -0
- package/dist/docs/api/interfaces/MenuBarEvents.html +114 -0
- package/dist/docs/api/interfaces/MessageEvents.html +72 -0
- package/dist/docs/api/interfaces/OlLayer.html +1 -1
- package/dist/docs/api/interfaces/OlMap.html +1 -1
- package/dist/docs/api/interfaces/OlSource.html +1 -1
- package/dist/docs/api/interfaces/OlTileLayer.html +1 -1
- package/dist/docs/api/interfaces/OlVectorLayer.html +1 -1
- package/dist/docs/api/interfaces/OlView.html +1 -1
- package/dist/docs/api/interfaces/SlideBackgroundState.html +66 -0
- package/dist/docs/api/interfaces/SlideEvents.html +78 -0
- package/dist/docs/api/interfaces/SlideNavEvents.html +72 -0
- package/dist/docs/api/interfaces/SlideshowPlayerSettings.html +182 -0
- package/dist/docs/api/interfaces/SlideshowToStorymapResult.html +60 -0
- package/dist/docs/api/interfaces/SlideshowTranslatorOptions.html +65 -0
- package/dist/docs/api/interfaces/SlideshowWarning.html +72 -0
- package/dist/docs/api/interfaces/StoryMapEvents.html +146 -0
- package/dist/docs/api/interfaces/StoryMapMarker.html +763 -0
- package/dist/docs/api/interfaces/StorySliderEvents.html +102 -0
- package/dist/docs/api/interfaces/StorymapBasemap.html +69 -0
- package/dist/docs/api/interfaces/StorymapData.html +12 -6
- package/dist/docs/api/interfaces/StorymapDataWrapper.html +2 -2
- package/dist/docs/api/interfaces/StorymapDocument.html +2 -2
- package/dist/docs/api/interfaces/StorymapError.html +3 -3
- package/dist/docs/api/interfaces/StorymapGeoreference.html +5 -5
- package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +4 -4
- package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +4 -4
- package/dist/docs/api/interfaces/StorymapLanguageMap.html +2 -2
- package/dist/docs/api/interfaces/StorymapManifest.html +12 -12
- package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +43 -11
- package/dist/docs/api/interfaces/StorymapManifestBackground.html +6 -6
- package/dist/docs/api/interfaces/StorymapManifestCanvas.html +65 -17
- package/dist/docs/api/interfaces/StorymapManifestContentResource.html +8 -8
- package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +4 -4
- package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +7 -7
- package/dist/docs/api/interfaces/StorymapManifestImageService.html +4 -4
- package/dist/docs/api/interfaces/StorymapManifestRange.html +5 -5
- package/dist/docs/api/interfaces/StorymapManifestService.html +4 -4
- package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +4 -4
- package/dist/docs/api/interfaces/StorymapManifestStatement.html +3 -3
- package/dist/docs/api/interfaces/StorymapMapOptions.html +5 -5
- package/dist/docs/api/interfaces/StorymapOptions.html +277 -75
- package/dist/docs/api/interfaces/StorymapOverlayLayer.html +42 -11
- package/dist/docs/api/interfaces/StorymapSlide.html +70 -16
- package/dist/docs/api/interfaces/StorymapSlideBackground.html +4 -4
- package/dist/docs/api/interfaces/StorymapSlideLocation.html +58 -14
- package/dist/docs/api/interfaces/StorymapSlideMarker.html +8 -9
- package/dist/docs/api/interfaces/StorymapSlideMedia.html +49 -10
- package/dist/docs/api/interfaces/StorymapSlideNarration.html +61 -9
- package/dist/docs/api/interfaces/StorymapSlideText.html +4 -4
- package/dist/docs/api/interfaces/StorymapTilejson.html +8 -8
- package/dist/docs/api/interfaces/SwipableEvents.html +102 -0
- package/dist/docs/api/interfaces/TextEvents.html +66 -0
- package/dist/docs/api/media/events.md +66 -0
- package/dist/docs/api/media/migration-from-knightlab.md +89 -49
- package/dist/docs/api/media/slideshow.md +109 -0
- package/dist/docs/api/media/storymap-as-iiif-manifest.md +1007 -0
- package/dist/docs/api/modules.html +6 -6
- package/dist/docs/api/types/ContentState.html +3 -3
- package/dist/docs/api/types/FiredEvent.html +43 -0
- package/dist/docs/api/types/ImagereadyKind.html +1 -1
- package/dist/docs/api/types/MediaTypeMatch.html +5 -5
- package/dist/docs/api/types/SwipeDirection.html +36 -0
- package/dist/docs/api/types/TileSourceFactory.html +1 -1
- package/dist/docs/authoring.html +20 -7
- package/dist/docs/events.html +263 -0
- package/dist/docs/iiif.html +136 -22
- package/dist/docs/migration.html +66 -19
- package/dist/docs/readme.html +113 -12
- package/dist/embed/index.html +7 -0
- package/dist/examples/font-css-false.json +33 -0
- package/dist/examples/issue-image-region.json +1 -1
- package/dist/examples/layers-control.json +60 -0
- package/dist/examples/map-template-provider.json +36 -0
- package/dist/examples/multi-media.json +71 -0
- package/dist/examples-iiif/annotated-image.json +16 -0
- package/dist/examples-iiif/font-css-false.json +114 -0
- package/dist/examples-iiif/issue-image-region.json +1 -1
- package/dist/examples-iiif/layers-control.json +226 -0
- package/dist/examples-iiif/map-template-provider.json +133 -0
- package/dist/examples-iiif/multi-media.json +237 -0
- package/dist/examples-slideshow/single.json +79 -0
- package/dist/examples-slideshow/static/pixel.png +0 -0
- package/dist/examples-slideshow/static.json +44 -0
- package/dist/harness-multi.html +3 -3
- package/dist/harness.html +4 -3
- package/dist/index.html +3 -2
- package/dist/js/storymap.d.ts +1326 -289
- package/dist/js/storymap.js +6690 -4784
- package/dist/js/storymap.js.map +1 -1
- package/dist/navplace-properties.json +14 -0
- package/dist/site.css +54 -36
- package/docs/migration-from-knightlab.md +89 -49
- package/docs/storymap-as-iiif-manifest.md +199 -126
- package/package.json +4 -2
- package/schema/storymap.schema.json +334 -34
- package/src/core/Util.ts +3 -1
- package/src/core/mixins.ts +42 -28
- package/src/language/Language.ts +7 -0
- package/src/language/locale/.expected-gaps.json +287 -27
- package/src/language/locale/de.json +11 -1
- package/src/language/locale/en.json +11 -1
- package/src/main.ts +51 -0
- package/src/map/Map.ts +44 -6
- package/src/map/MapMarker.ts +16 -3
- package/src/map/openlayers/Map.OpenLayers.ts +787 -62
- package/src/map/openlayers/MapMarker.OpenLayers.ts +113 -13
- package/src/map/slideView.ts +149 -0
- package/src/map/types.ts +2 -0
- package/src/media/EmbedUtil.ts +27 -2
- package/src/media/Media.ts +27 -4
- package/src/media/embedId.ts +6 -0
- package/src/media/types/Flickr.ts +14 -3
- package/src/media/types/HtmlMedia.ts +66 -0
- package/src/media/types/Image.ts +15 -3
- package/src/media/types/SoundCloud.ts +1 -1
- package/src/media/types/Text.ts +27 -8
- package/src/media/types/Twitter.ts +9 -7
- package/src/media/types/Vimeo.ts +1 -1
- package/src/media/types/YouTube.ts +2 -2
- package/src/scss/Typography.scss +15 -15
- package/src/scss/VCO.StoryMap.scss +173 -8
- package/src/scss/core/Reset.scss +5 -18
- package/src/scss/map/VCO.Map.scss +1 -1
- package/src/scss/map/VCO.MapMarker.scss +20 -9
- package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +7 -4
- package/src/scss/media/VCO.Media.scss +7 -7
- package/src/scss/media/types/VCO.Media.Blockquote.scss +1 -1
- package/src/scss/media/types/VCO.Media.Text.scss +5 -5
- package/src/scss/media/types/VCO.Media.Twitter.scss +4 -4
- package/src/scss/media/types/VCO.Media.Wikipedia.scss +2 -19
- package/src/scss/site/site.scss +55 -36
- package/src/scss/slider/VCO.Slide.scss +49 -11
- package/src/scss/slider/VCO.SlideNav.scss +23 -7
- package/src/scss/slider/VCO.StorySlider.scss +50 -0
- package/src/scss/snapmap/VCO.SnapMap.scss +3 -3
- package/src/scss/ui/VCO.Consent.scss +20 -14
- package/src/scss/ui/VCO.Layers.scss +119 -0
- package/src/scss/ui/VCO.MenuBar.Button.scss +140 -19
- package/src/scss/ui/VCO.MenuBar.scss +9 -2
- package/src/scss/ui/VCO.Message.scss +14 -0
- package/src/slider/Slide.ts +232 -74
- package/src/slider/SlideNav.ts +15 -4
- package/src/slider/StorySlider.ts +203 -22
- package/src/storymap/Consent.ts +22 -0
- package/src/storymap/StoryMap.ts +944 -131
- package/src/storymap/content-state.ts +3 -8
- package/src/storymap/font-css.ts +72 -0
- package/src/storymap/from-slideshow.ts +785 -0
- package/src/storymap/iiif-shared.ts +228 -0
- package/src/storymap/iiif.ts +289 -100
- package/src/storymap/to-iiif.ts +131 -44
- package/src/types.ts +382 -17
- package/src/ui/LayersControl.ts +302 -0
- package/src/ui/MenuBar.ts +232 -21
- package/src/ui/Message.ts +36 -3
- package/src/ui/Swipable.ts +25 -7
- package/dist/assets/harness-Cr0rYpvt.js +0 -1
- package/dist/assets/main-DXalctuR.js +0 -17
- package/src/scss/VCO.StoryMap.Dark.scss +0 -150
- package/src/scss/Variables.Dark.scss +0 -57
|
@@ -138,6 +138,18 @@
|
|
|
138
138
|
"attribution": {
|
|
139
139
|
"type": "string"
|
|
140
140
|
},
|
|
141
|
+
"label": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"description": "Layer switcher row label (defaults to map_type)"
|
|
144
|
+
},
|
|
145
|
+
"locked": {
|
|
146
|
+
"type": "boolean",
|
|
147
|
+
"description": "Render the switcher row checked and disabled"
|
|
148
|
+
},
|
|
149
|
+
"control": {
|
|
150
|
+
"type": "boolean",
|
|
151
|
+
"description": "False hides the row from the switcher without removing the overlay"
|
|
152
|
+
},
|
|
141
153
|
"className": {
|
|
142
154
|
"type": "string",
|
|
143
155
|
"description": "CSS class of the layer container, isolating it from the shared ol-layer canvas (e.g. for blend modes)"
|
|
@@ -262,11 +274,83 @@
|
|
|
262
274
|
},
|
|
263
275
|
"attribution": {
|
|
264
276
|
"type": "string"
|
|
277
|
+
},
|
|
278
|
+
"width": {
|
|
279
|
+
"type": "number",
|
|
280
|
+
"exclusiveMinimum": 0,
|
|
281
|
+
"description": "Canvas width in pixels, enabling region clamping and the static fallback without another fetch"
|
|
282
|
+
},
|
|
283
|
+
"height": {
|
|
284
|
+
"type": "number",
|
|
285
|
+
"exclusiveMinimum": 0,
|
|
286
|
+
"description": "Canvas height in pixels, enabling region clamping and the static fallback without another fetch"
|
|
287
|
+
},
|
|
288
|
+
"fallbackUrl": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"format": "uri",
|
|
291
|
+
"description": "Full-size image used when info.json cannot be loaded (slideshow image_static)"
|
|
265
292
|
}
|
|
266
293
|
}
|
|
267
294
|
},
|
|
295
|
+
"tilejson": {
|
|
296
|
+
"type": "object",
|
|
297
|
+
"description": "TileJSON source for the base layer: tiles becomes the map_type template, the rest constrains the source/view where the map can act on it",
|
|
298
|
+
"required": ["tiles"],
|
|
299
|
+
"properties": {
|
|
300
|
+
"tiles": {
|
|
301
|
+
"anyOf": [
|
|
302
|
+
{ "type": "string" },
|
|
303
|
+
{ "type": "array", "items": { "type": "string" }, "minItems": 1 }
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
"minzoom": { "type": "number" },
|
|
307
|
+
"maxzoom": { "type": "number" },
|
|
308
|
+
"bounds": {
|
|
309
|
+
"type": "array",
|
|
310
|
+
"items": { "type": "number" },
|
|
311
|
+
"minItems": 4,
|
|
312
|
+
"maxItems": 4
|
|
313
|
+
},
|
|
314
|
+
"scheme": { "type": "string", "enum": ["xyz", "tms"] },
|
|
315
|
+
"center": {
|
|
316
|
+
"type": "array",
|
|
317
|
+
"items": { "type": "number" },
|
|
318
|
+
"minItems": 3,
|
|
319
|
+
"maxItems": 3
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
"see_also": {
|
|
324
|
+
"type": "array",
|
|
325
|
+
"description": "seeAlso targets recorded from a IIIF manifest (annotation collections/pages); recorded but not fetched on load",
|
|
326
|
+
"items": {
|
|
327
|
+
"type": "object",
|
|
328
|
+
"required": ["id", "type"],
|
|
329
|
+
"properties": {
|
|
330
|
+
"id": { "type": "string" },
|
|
331
|
+
"type": { "type": "string" }
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
"title": {
|
|
336
|
+
"type": "string",
|
|
337
|
+
"description": "Story title carried by IIIF manifests (label) and slideshow tours; extra on legacy documents"
|
|
338
|
+
},
|
|
339
|
+
"metadata": {
|
|
340
|
+
"type": "array",
|
|
341
|
+
"description": "Label/value pairs carried from a IIIF manifest or slideshow tour; data-only, handed on as data.metadata[]"
|
|
342
|
+
},
|
|
343
|
+
"logo": {
|
|
344
|
+
"description": "Publisher logo carried from a IIIF manifest; data-only, offered as data.logo"
|
|
345
|
+
},
|
|
268
346
|
"font_css": {
|
|
269
|
-
"type": "string"
|
|
347
|
+
"anyOf": [{ "type": "string" }, { "const": false }],
|
|
348
|
+
"description": "Font theme stylesheet (stock:<name> or URL); false disables the injected stylesheet because the host bundles the theme itself"
|
|
349
|
+
},
|
|
350
|
+
"theme": {
|
|
351
|
+
"type": "string",
|
|
352
|
+
"enum": ["dark", "light"],
|
|
353
|
+
"description": "Colour theme: dark forces the dark palette, light pins the light one; unset follows prefers-color-scheme"
|
|
270
354
|
},
|
|
271
355
|
"call_to_action": {
|
|
272
356
|
"type": "boolean"
|
|
@@ -286,6 +370,38 @@
|
|
|
286
370
|
"show_progress": {
|
|
287
371
|
"type": "boolean"
|
|
288
372
|
},
|
|
373
|
+
"progressbar": {
|
|
374
|
+
"anyOf": [
|
|
375
|
+
{ "type": "boolean" },
|
|
376
|
+
{
|
|
377
|
+
"type": "string",
|
|
378
|
+
"enum": ["bar", "dots", "squares", "block", "thinblock", "off"]
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
"description": "Progress indicator style (slideshow progressbar): false/off hides it, true/bar is the classic fill bar, dots/squares render one step per slide, block/thinblock are fill-bar height variants. Absent means show_progress decides with the bar style. Honored only with slideshow_source."
|
|
382
|
+
},
|
|
383
|
+
"show_layers_control": {
|
|
384
|
+
"type": "boolean",
|
|
385
|
+
"description": "Show the basemap/overlay switcher in the menubar"
|
|
386
|
+
},
|
|
387
|
+
"basemaps": {
|
|
388
|
+
"type": "array",
|
|
389
|
+
"description": "Selectable base maps for the layer switcher; entry 0 is the initial basemap unless map_type says otherwise",
|
|
390
|
+
"items": {
|
|
391
|
+
"type": "object",
|
|
392
|
+
"required": ["map_type"],
|
|
393
|
+
"properties": {
|
|
394
|
+
"map_type": {
|
|
395
|
+
"type": "string",
|
|
396
|
+
"description": "Any map_type value"
|
|
397
|
+
},
|
|
398
|
+
"label": {
|
|
399
|
+
"type": "string",
|
|
400
|
+
"description": "Control row label (defaults to map_type)"
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
},
|
|
289
405
|
"show_distance": {
|
|
290
406
|
"type": "boolean"
|
|
291
407
|
},
|
|
@@ -297,6 +413,62 @@
|
|
|
297
413
|
"enum": ["left", "center", "right"],
|
|
298
414
|
"description": "Default horizontal alignment for slide text"
|
|
299
415
|
},
|
|
416
|
+
"textmode": {
|
|
417
|
+
"type": "string",
|
|
418
|
+
"enum": ["left", "right", "bottom"],
|
|
419
|
+
"description": "Slide panel dock (slideshow textmode) in landscape: right (default) is the current layout, left mirrors it, bottom docks the panel below the map. Portrait layouts always behave like bottom. Honored only with slideshow_source."
|
|
420
|
+
},
|
|
421
|
+
"textsize": {
|
|
422
|
+
"type": "number",
|
|
423
|
+
"minimum": 10,
|
|
424
|
+
"maximum": 80,
|
|
425
|
+
"description": "Slide panel size as a percentage (slideshow textsize): percent of the width for side docks, of the height for the bottom dock. Absent keeps the built-in 50/50 split. Honored only with slideshow_source."
|
|
426
|
+
},
|
|
427
|
+
"fxmode": {
|
|
428
|
+
"type": "string",
|
|
429
|
+
"enum": ["slide", "fade", "none"],
|
|
430
|
+
"description": "Slide transition effect (slideshow fxmode): slide (default) is the current glide, fade cross-fades slides, none jumps without animation. prefers-reduced-motion still forces none. Honored only with slideshow_source."
|
|
431
|
+
},
|
|
432
|
+
"mode": {
|
|
433
|
+
"type": "string",
|
|
434
|
+
"enum": ["standard", "static"],
|
|
435
|
+
"description": "Reading mode (slideshow mode): standard (default) is the slider; static stacks all slides in a scrollable list and follows the map to the slide in view. Honored only with slideshow_source."
|
|
436
|
+
},
|
|
437
|
+
"hudcolor": {
|
|
438
|
+
"type": "string",
|
|
439
|
+
"description": "HUD foreground color override (slideshow hudcolor). Honored only with slideshow_source."
|
|
440
|
+
},
|
|
441
|
+
"hudbgcolor": {
|
|
442
|
+
"type": "string",
|
|
443
|
+
"description": "HUD background color override (slideshow hudbgcolor). Honored only with slideshow_source."
|
|
444
|
+
},
|
|
445
|
+
"hudopacity": {
|
|
446
|
+
"type": "number",
|
|
447
|
+
"minimum": 0,
|
|
448
|
+
"maximum": 100,
|
|
449
|
+
"description": "HUD opacity percent 0..100 (slideshow hudopacity), applied to the HUD background. Honored only with slideshow_source."
|
|
450
|
+
},
|
|
451
|
+
"shownav": {
|
|
452
|
+
"type": "boolean",
|
|
453
|
+
"description": "Show the previous/next slide navigation (slideshow shownav). Default true. Honored only with slideshow_source."
|
|
454
|
+
},
|
|
455
|
+
"show_headings": {
|
|
456
|
+
"type": "boolean",
|
|
457
|
+
"description": "Render slide headlines (slideshow showheadings). Default true; false hides headline elements. Honored only with slideshow_source."
|
|
458
|
+
},
|
|
459
|
+
"show_scrollbars": {
|
|
460
|
+
"type": "boolean",
|
|
461
|
+
"description": "Show scrollbars in the slide panel (slideshow showscrollbars). Default true; false hides them (content still scrolls). Honored only with slideshow_source."
|
|
462
|
+
},
|
|
463
|
+
"viewerheight": {
|
|
464
|
+
"type": "string",
|
|
465
|
+
"pattern": "^[0-9]+(\\.[0-9]+)?(px|%|vh)$",
|
|
466
|
+
"description": "Fixed viewer height (slideshow viewerheight), e.g. 400px: applied as a container height override when set. Honored only with slideshow_source."
|
|
467
|
+
},
|
|
468
|
+
"show_info": {
|
|
469
|
+
"type": "boolean",
|
|
470
|
+
"description": "Show media captions and credits (slideshow showinfo). Default true; false hides the caption/credit block. Honored only with slideshow_source."
|
|
471
|
+
},
|
|
300
472
|
"text_color": {
|
|
301
473
|
"type": "string"
|
|
302
474
|
},
|
|
@@ -355,6 +527,15 @@
|
|
|
355
527
|
"$ref": "#/$defs/slide"
|
|
356
528
|
}
|
|
357
529
|
},
|
|
530
|
+
"credit": {
|
|
531
|
+
"type": "object",
|
|
532
|
+
"description": "Authorship and rights for the story (slideshow creator/rights); rendered into the map attribution line for slideshow tours.",
|
|
533
|
+
"properties": {
|
|
534
|
+
"creator": { "type": "string" },
|
|
535
|
+
"rights": { "type": "string" },
|
|
536
|
+
"licenseUrl": { "type": "string", "format": "uri" }
|
|
537
|
+
}
|
|
538
|
+
},
|
|
358
539
|
"layout": {
|
|
359
540
|
"type": "string",
|
|
360
541
|
"enum": ["landscape", "portrait"],
|
|
@@ -364,6 +545,58 @@
|
|
|
364
545
|
}
|
|
365
546
|
},
|
|
366
547
|
"$defs": {
|
|
548
|
+
"media": {
|
|
549
|
+
"type": "object",
|
|
550
|
+
"properties": {
|
|
551
|
+
"url": {
|
|
552
|
+
"type": ["string", "null"]
|
|
553
|
+
},
|
|
554
|
+
"caption": {
|
|
555
|
+
"type": ["string", "null"]
|
|
556
|
+
},
|
|
557
|
+
"credit": {
|
|
558
|
+
"type": ["string", "null"]
|
|
559
|
+
},
|
|
560
|
+
"thumb": {
|
|
561
|
+
"type": "string"
|
|
562
|
+
},
|
|
563
|
+
"alt": {
|
|
564
|
+
"type": "string"
|
|
565
|
+
},
|
|
566
|
+
"srcset": {
|
|
567
|
+
"type": "string"
|
|
568
|
+
},
|
|
569
|
+
"sizes": {
|
|
570
|
+
"type": "string"
|
|
571
|
+
},
|
|
572
|
+
"subtitles": {
|
|
573
|
+
"type": ["string", "null"],
|
|
574
|
+
"format": "uri",
|
|
575
|
+
"description": "WebVTT subtitle file for an audio or video slide, rendered as a <track kind=\"subtitles\">."
|
|
576
|
+
},
|
|
577
|
+
"offset": {
|
|
578
|
+
"type": "number",
|
|
579
|
+
"minimum": 0,
|
|
580
|
+
"description": "Start offset in seconds for audio/video media (slideshow audio.offset). Honored only with slideshow_source"
|
|
581
|
+
},
|
|
582
|
+
"loop": {
|
|
583
|
+
"type": "boolean",
|
|
584
|
+
"description": "Loop audio/video media (slideshow audio.loop). Honored only with slideshow_source"
|
|
585
|
+
},
|
|
586
|
+
"play": {
|
|
587
|
+
"type": "string",
|
|
588
|
+
"enum": ["auto", "click"],
|
|
589
|
+
"description": "auto plays on activation; click arms paused for the visitor to start. Honored only with slideshow_source"
|
|
590
|
+
},
|
|
591
|
+
"stopOnExit": {
|
|
592
|
+
"type": "boolean",
|
|
593
|
+
"description": "Stop this media when leaving the slide (default true); false lets an audio bed continue. Honored only with slideshow_source"
|
|
594
|
+
},
|
|
595
|
+
"mediatype": {
|
|
596
|
+
"type": ["object", "null"]
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
},
|
|
367
600
|
"slide": {
|
|
368
601
|
"type": "object",
|
|
369
602
|
"properties": {
|
|
@@ -399,7 +632,41 @@
|
|
|
399
632
|
},
|
|
400
633
|
"minItems": 4,
|
|
401
634
|
"maxItems": 4,
|
|
402
|
-
"description": "Image region [x, y, w, h] in image pixels (IIIF xywh convention) for image maps; the view fits the region on navigation"
|
|
635
|
+
"description": "Image region [x, y, w, h] in image pixels (IIIF xywh convention) for image maps; the view fits the region on navigation. Negative origins are clamped to the canvas."
|
|
636
|
+
},
|
|
637
|
+
"rotation": {
|
|
638
|
+
"type": "number",
|
|
639
|
+
"description": "View rotation in degrees clockwise (slideshow rotation); absent means north-up. Honored only with slideshow_source"
|
|
640
|
+
},
|
|
641
|
+
"filter": {
|
|
642
|
+
"type": "object",
|
|
643
|
+
"description": "Per-slide image grading (slideshow filters), applied as a CSS filter() on the map viewport. Honored only with slideshow_source",
|
|
644
|
+
"properties": {
|
|
645
|
+
"brightness": { "type": "number", "minimum": 0, "maximum": 200 },
|
|
646
|
+
"contrast": { "type": "number", "minimum": 0, "maximum": 200 },
|
|
647
|
+
"saturate": { "type": "number", "minimum": 0, "maximum": 200 },
|
|
648
|
+
"hueRotate": { "type": "number", "minimum": -180, "maximum": 180 },
|
|
649
|
+
"sepia": { "type": "number", "minimum": 0, "maximum": 100 },
|
|
650
|
+
"blur": { "type": "number", "minimum": 0, "maximum": 20 }
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
"mask": {
|
|
654
|
+
"type": "object",
|
|
655
|
+
"description": "Spotlight mask (slideshow passepartout): normalized viewport fractions left visible while the rest is dimmed. Honored only with slideshow_source",
|
|
656
|
+
"required": ["x", "y", "w", "h"],
|
|
657
|
+
"properties": {
|
|
658
|
+
"x": { "type": "number" },
|
|
659
|
+
"y": { "type": "number" },
|
|
660
|
+
"w": { "type": "number", "exclusiveMinimum": 0 },
|
|
661
|
+
"h": { "type": "number", "exclusiveMinimum": 0 },
|
|
662
|
+
"color": { "type": "string" },
|
|
663
|
+
"invert": { "type": "boolean" },
|
|
664
|
+
"opacity": { "type": "number", "minimum": 0, "maximum": 1 }
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
"basemap": {
|
|
668
|
+
"type": "string",
|
|
669
|
+
"description": "Per-slide basemap override (multi-manifest tours): any map_type value or IIIF info.json URL. Absent keeps the story basemap. Honored only with slideshow_source."
|
|
403
670
|
},
|
|
404
671
|
"zoom": {
|
|
405
672
|
"type": "number"
|
|
@@ -432,39 +699,20 @@
|
|
|
432
699
|
}
|
|
433
700
|
},
|
|
434
701
|
"media": {
|
|
435
|
-
"
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
},
|
|
443
|
-
"credit": {
|
|
444
|
-
"type": ["string", "null"]
|
|
445
|
-
},
|
|
446
|
-
"thumb": {
|
|
447
|
-
"type": "string"
|
|
448
|
-
},
|
|
449
|
-
"alt": {
|
|
450
|
-
"type": "string"
|
|
451
|
-
},
|
|
452
|
-
"srcset": {
|
|
453
|
-
"type": "string"
|
|
454
|
-
},
|
|
455
|
-
"sizes": {
|
|
456
|
-
"type": "string"
|
|
457
|
-
},
|
|
458
|
-
"subtitles": {
|
|
459
|
-
"type": ["string", "null"],
|
|
460
|
-
"format": "uri",
|
|
461
|
-
"description": "WebVTT subtitle file for an audio or video slide, rendered as a <track kind=\"subtitles\">."
|
|
462
|
-
},
|
|
463
|
-
"mediatype": {
|
|
464
|
-
"type": ["object", "null"]
|
|
465
|
-
}
|
|
702
|
+
"$ref": "#/$defs/media"
|
|
703
|
+
},
|
|
704
|
+
"media_extra": {
|
|
705
|
+
"type": ["array", "null"],
|
|
706
|
+
"description": "Additional visible media for this slide (#358), rendered after media in order. Items without a non-empty url are skipped. In a IIIF manifest these are further painting annotations on the canvas.",
|
|
707
|
+
"items": {
|
|
708
|
+
"$ref": "#/$defs/media"
|
|
466
709
|
}
|
|
467
710
|
},
|
|
711
|
+
"media_layout": {
|
|
712
|
+
"type": "string",
|
|
713
|
+
"enum": ["stack", "row"],
|
|
714
|
+
"description": "Layout of a multi-media slide (#358): stack piles the items vertically (the panel scrolls), row puts two items side by side. Defaults to stack; row with anything but two items falls back to stack."
|
|
715
|
+
},
|
|
468
716
|
"text": {
|
|
469
717
|
"type": "object",
|
|
470
718
|
"properties": {
|
|
@@ -515,11 +763,54 @@
|
|
|
515
763
|
},
|
|
516
764
|
"narration": {
|
|
517
765
|
"type": ["object", "null"],
|
|
518
|
-
"description": "Spoken narration for this slide, played through a dedicated audio element.
|
|
766
|
+
"description": "Spoken narration for this slide, played through a dedicated audio element. In a IIIF manifest this is a motivation: supplementing Sound/Video body, read and written alongside the painting annotation.",
|
|
519
767
|
"properties": {
|
|
520
768
|
"url": {
|
|
521
769
|
"type": "string",
|
|
522
770
|
"format": "uri"
|
|
771
|
+
},
|
|
772
|
+
"loop": {
|
|
773
|
+
"type": "boolean",
|
|
774
|
+
"description": "Loop the narration (slideshow audio.loop). Honored only with slideshow_source"
|
|
775
|
+
},
|
|
776
|
+
"offset": {
|
|
777
|
+
"type": "number",
|
|
778
|
+
"minimum": 0,
|
|
779
|
+
"description": "Start offset in seconds (slideshow audio.offset). Honored only with slideshow_source"
|
|
780
|
+
},
|
|
781
|
+
"play": {
|
|
782
|
+
"type": "string",
|
|
783
|
+
"enum": ["auto", "click"],
|
|
784
|
+
"description": "auto plays on navigation; click arms paused for the visitor to start (slideshow audio.play). Honored only with slideshow_source"
|
|
785
|
+
},
|
|
786
|
+
"stopOnExit": {
|
|
787
|
+
"type": "boolean",
|
|
788
|
+
"description": "Stop when leaving the slide (default true); false keeps an audio bed across slides while the URL is unchanged. Honored only with slideshow_source"
|
|
789
|
+
},
|
|
790
|
+
"stopAllPrevious": {
|
|
791
|
+
"type": "boolean",
|
|
792
|
+
"description": "Stop any other playing track before starting (default true); false allows ambient overlap. Honored only with slideshow_source"
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
"required": ["url"]
|
|
796
|
+
},
|
|
797
|
+
"slidetimeout": {
|
|
798
|
+
"type": "number",
|
|
799
|
+
"minimum": 0,
|
|
800
|
+
"description": "Per-slide autoplay dwell in milliseconds (slideshow slidetimeout): overrides the global autoplay interval for this slide; 0 holds. Absent means the global interval. Honored only with slideshow_source."
|
|
801
|
+
},
|
|
802
|
+
"imgoverlay": {
|
|
803
|
+
"anyOf": [{ "type": "object" }, { "type": "null" }],
|
|
804
|
+
"description": "Per-slide image overlay on the map (slideshow imgoverlay), shown while this slide is active. Honored only with slideshow_source",
|
|
805
|
+
"properties": {
|
|
806
|
+
"url": { "type": "string", "format": "uri" },
|
|
807
|
+
"size": { "type": "number", "exclusiveMinimum": 0 },
|
|
808
|
+
"opacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
809
|
+
"extent": {
|
|
810
|
+
"type": "array",
|
|
811
|
+
"items": { "type": "number" },
|
|
812
|
+
"minItems": 4,
|
|
813
|
+
"maxItems": 4
|
|
523
814
|
}
|
|
524
815
|
},
|
|
525
816
|
"required": ["url"]
|
|
@@ -542,6 +833,15 @@
|
|
|
542
833
|
},
|
|
543
834
|
"uniqueid": {
|
|
544
835
|
"type": "string"
|
|
836
|
+
},
|
|
837
|
+
"provenance": {
|
|
838
|
+
"type": "object",
|
|
839
|
+
"description": "Provenance identifiers for the slide's source (slideshow manifest/canvas/image ids). Data-only, never rendered.",
|
|
840
|
+
"properties": {
|
|
841
|
+
"manifest": { "type": "string", "format": "uri" },
|
|
842
|
+
"canvas": { "type": "string", "format": "uri" },
|
|
843
|
+
"image": { "type": "string", "format": "uri" }
|
|
844
|
+
}
|
|
545
845
|
}
|
|
546
846
|
}
|
|
547
847
|
}
|
package/src/core/Util.ts
CHANGED
|
@@ -359,11 +359,13 @@ export function slideTransitionDuration(from: number, to: number): number {
|
|
|
359
359
|
* (`prefers-reduced-motion: reduce`) — slide/map glides collapse to
|
|
360
360
|
* instant changes and autoplay stays off.
|
|
361
361
|
*/
|
|
362
|
+
export const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
363
|
+
|
|
362
364
|
export function prefersReducedMotion(): boolean {
|
|
363
365
|
return (
|
|
364
366
|
typeof window !== "undefined" &&
|
|
365
367
|
typeof window.matchMedia === "function" &&
|
|
366
|
-
window.matchMedia(
|
|
368
|
+
window.matchMedia(REDUCED_MOTION_QUERY).matches
|
|
367
369
|
);
|
|
368
370
|
}
|
|
369
371
|
|
package/src/core/mixins.ts
CHANGED
|
@@ -8,12 +8,29 @@
|
|
|
8
8
|
/** Constructor shape accepted by the mixin functions. */
|
|
9
9
|
export type Constructor<T = object> = new (...args: any[]) => T;
|
|
10
10
|
|
|
11
|
+
/** What a listener receives: the payload, plus the framework's own fields.
|
|
12
|
+
*
|
|
13
|
+
* Kept as an intersection because `fire` merges them into one object — that
|
|
14
|
+
* is what a handler gets. As a side effect it also fixes the `type`
|
|
15
|
+
* clobbering at the type level: intersecting `type: "loaded"` with
|
|
16
|
+
* `type?: string` yields `"loaded"`.
|
|
17
|
+
*/
|
|
18
|
+
export type FiredEvent<M, K extends keyof M & string> = M[K] & { type: K; target: unknown };
|
|
19
|
+
|
|
11
20
|
/** Eventing members provided by the Evented mixin. */
|
|
12
|
-
export interface EventedInstance {
|
|
13
|
-
on
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
export interface EventedInstance<M = Record<string, unknown>> {
|
|
22
|
+
on<K extends keyof M & string>(
|
|
23
|
+
type: K,
|
|
24
|
+
fn: (e: FiredEvent<M, K>) => void,
|
|
25
|
+
context?: unknown,
|
|
26
|
+
): this;
|
|
27
|
+
off<K extends keyof M & string>(
|
|
28
|
+
type: K,
|
|
29
|
+
fn: (e: FiredEvent<M, K>) => void,
|
|
30
|
+
context?: unknown,
|
|
31
|
+
): this;
|
|
32
|
+
fire<K extends keyof M & string>(type: K, data?: M[K]): this;
|
|
33
|
+
hasEventListeners<K extends keyof M & string>(type: K): boolean;
|
|
17
34
|
}
|
|
18
35
|
|
|
19
36
|
/**
|
|
@@ -25,7 +42,7 @@ export interface EventedInstance {
|
|
|
25
42
|
* slider's live region). Requiring `Record<string, HTMLElement>` here would
|
|
26
43
|
* force every one of those back into an `{} as HTMLElement` placeholder.
|
|
27
44
|
*/
|
|
28
|
-
export interface DomMixedInstance extends EventedInstance {
|
|
45
|
+
export interface DomMixedInstance<M = Record<string, unknown>> extends EventedInstance<M> {
|
|
29
46
|
_el: Record<string, unknown>;
|
|
30
47
|
data?: unknown;
|
|
31
48
|
}
|
|
@@ -36,7 +53,7 @@ export interface DomMixedInstance extends EventedInstance {
|
|
|
36
53
|
================================================== */
|
|
37
54
|
|
|
38
55
|
/** Adds eventing (on/off/fire/hasEventListeners) to a class. */
|
|
39
|
-
export function Evented<T extends Constructor>(Base: T) {
|
|
56
|
+
export function Evented<M, T extends Constructor>(Base: T) {
|
|
40
57
|
return class extends Base {
|
|
41
58
|
declare "_vco_events"?: Record<string, { action: unknown; context: unknown }[]>;
|
|
42
59
|
|
|
@@ -70,31 +87,25 @@ export function Evented<T extends Constructor>(Base: T) {
|
|
|
70
87
|
string,
|
|
71
88
|
{ action: unknown; context: unknown }[]
|
|
72
89
|
>;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
90
|
+
events[type] = events[type].filter(
|
|
91
|
+
(listener) =>
|
|
92
|
+
!(listener.action === fn && (!context || listener.context === context)),
|
|
93
|
+
);
|
|
94
|
+
if (events[type].length === 0) {
|
|
95
|
+
delete events[type];
|
|
81
96
|
}
|
|
82
97
|
return this;
|
|
83
98
|
}
|
|
84
99
|
|
|
85
|
-
fire(
|
|
86
|
-
/*String*/ type: string,
|
|
87
|
-
/*(optional) Object*/ data?: unknown,
|
|
88
|
-
target?: unknown,
|
|
89
|
-
): this {
|
|
100
|
+
fire(/*String*/ type: string, /*(optional) Object*/ data?: unknown): this {
|
|
90
101
|
if (!this.hasEventListeners(type)) {
|
|
91
102
|
return this;
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
const event = {
|
|
95
|
-
type: type,
|
|
96
|
-
target: target || this,
|
|
97
106
|
...(data as Record<string, unknown> | undefined),
|
|
107
|
+
type,
|
|
108
|
+
target: this,
|
|
98
109
|
};
|
|
99
110
|
|
|
100
111
|
const listeners = (
|
|
@@ -111,7 +122,7 @@ export function Evented<T extends Constructor>(Base: T) {
|
|
|
111
122
|
constructor(...args: any[]) {
|
|
112
123
|
super(...args);
|
|
113
124
|
}
|
|
114
|
-
};
|
|
125
|
+
} as Constructor<EventedInstance<M>> & T;
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
/* DomMixed
|
|
@@ -121,7 +132,10 @@ export function Evented<T extends Constructor>(Base: T) {
|
|
|
121
132
|
|
|
122
133
|
/** Adds DOM container conveniences (addTo/removeFrom/setPosition/show/hide
|
|
123
134
|
* and the onAdd/onRemove/onLoaded lifecycle events) to a class. */
|
|
124
|
-
export function DomMixed<
|
|
135
|
+
export function DomMixed<
|
|
136
|
+
M extends { loaded: unknown; added: unknown; removed: unknown },
|
|
137
|
+
T extends Constructor<DomMixedInstance<M>>,
|
|
138
|
+
>(Base: T) {
|
|
125
139
|
return class extends Base {
|
|
126
140
|
/**
|
|
127
141
|
* The host element. Every DomMixed consumer keeps its root element
|
|
@@ -168,17 +182,17 @@ export function DomMixed<T extends Constructor<DomMixedInstance>>(Base: T) {
|
|
|
168
182
|
}
|
|
169
183
|
|
|
170
184
|
/* Lifecycle events
|
|
171
|
-
|
|
185
|
+
================================================== */
|
|
172
186
|
onLoaded(): void {
|
|
173
|
-
this.fire("loaded", this.data);
|
|
187
|
+
this.fire("loaded", this.data as M["loaded"]);
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
onAdd(): void {
|
|
177
|
-
this.fire("added", this.data);
|
|
191
|
+
this.fire("added", this.data as M["added"]);
|
|
178
192
|
}
|
|
179
193
|
|
|
180
194
|
onRemove(): void {
|
|
181
|
-
this.fire("removed", this.data);
|
|
195
|
+
this.fire("removed", this.data as M["removed"]);
|
|
182
196
|
}
|
|
183
197
|
|
|
184
198
|
constructor(...args: any[]) {
|
package/src/language/Language.ts
CHANGED
|
@@ -244,6 +244,13 @@ function setLanguage(code: string): LanguageEntry {
|
|
|
244
244
|
messages: (merged.messages as Record<string, string>) ?? FALLBACK.messages,
|
|
245
245
|
buttons: (merged.buttons as Record<string, string>) ?? FALLBACK.buttons,
|
|
246
246
|
};
|
|
247
|
+
// The page declares the language the viewer actually renders, so
|
|
248
|
+
// assistive tech pronounces chrome correctly. One effective locale per
|
|
249
|
+
// page (a second viewer claiming another throws), so this cannot fight
|
|
250
|
+
// a sibling viewer.
|
|
251
|
+
if (typeof document !== "undefined") {
|
|
252
|
+
document.documentElement.setAttribute("lang", code);
|
|
253
|
+
}
|
|
247
254
|
return Language;
|
|
248
255
|
}
|
|
249
256
|
|