@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
package/dist/docs/readme.html
CHANGED
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
<li><a class="button" href="./migration.html">Migration guide</a></li>
|
|
38
38
|
<li><a class="button" href="./iiif.html">IIIF docs</a></li>
|
|
39
39
|
<li><a class="button" href="./authoring.html">Authoring</a></li>
|
|
40
|
+
<li><a class="button" href="./events.html">Events</a></li>
|
|
40
41
|
<li><a class="button" href="./api/index.html">API docs</a></li>
|
|
41
42
|
<li><a class="button" href="../index.html#help">Help</a></li>
|
|
42
43
|
</ul>
|
|
@@ -75,8 +76,10 @@ value of the storymap's <code>language</code> option must match the file nam
|
|
|
75
76
|
<p>Large images served over the IIIF Image API are rendered so when set to be map_as_image the entire image is shown. When set as cartography the zoom will set so that all the markers fit.</p>
|
|
76
77
|
<p>Points are set to only display on mouseover in image mode, but you can set map_as_image to false in the config options to always show the points. The points are hidden when the intent is an image so that nothing obstructs the image the viewer is looking at. Looking at a painting is hard with a bunch of points on it.</p>
|
|
77
78
|
<h2>Map Options</h2>
|
|
78
|
-
<p>To disable connecting lines on maps set <code>
|
|
79
|
-
options (the default <code>
|
|
79
|
+
<p>To disable connecting lines on maps set <code>show_lines: false</code> in the storymap
|
|
80
|
+
options (the default <code>true</code> renders cartography with <code>show_history_line</code>).
|
|
81
|
+
<code>map_as_image: true</code> is something else: image-map mode, only meaningful with
|
|
82
|
+
<code>map_type: "iiif"</code> (the image itself becomes the map).</p>
|
|
80
83
|
<p><code>storymap.map</code> is the raw OpenLayers map, typed with the re-exported <code>ol</code>
|
|
81
84
|
types, and <code>getBaseLayer()</code>, <code>getOverlayLayers()</code>, <code>getMinimap()</code>,
|
|
82
85
|
<code>getMarkers()</code> and friends hand out the layers the viewer built. Listen for
|
|
@@ -102,6 +105,72 @@ show_lines: true,
|
|
|
102
105
|
show_history_line: true,
|
|
103
106
|
</code></pre>
|
|
104
107
|
<p>To disable zoom calculation/edit zoom level set calculate_zoom to false in the config options.</p>
|
|
108
|
+
<h3>More data options</h3>
|
|
109
|
+
<p>Beyond the map options above, the storymap data takes <code>overlays[]</code>
|
|
110
|
+
(stacked raster layers over the basemap), <code>tilejson</code> (a TileJSON source for
|
|
111
|
+
the base layer), <code>overview_extent</code> (the overview slide's bounds),
|
|
112
|
+
<code>keyboard</code> (page-wide arrow-key navigation for multi-viewer pages),
|
|
113
|
+
per-slide <code>marker: { popup, audioBadge }</code> (the active marker's card, openable
|
|
114
|
+
via <code>storymap.openMarkerPopup(n)</code>, and the narration/audio dot) and
|
|
115
|
+
<code>narration: { url }</code> per slide. <code>autoplay_media</code> is global (wait for slide
|
|
116
|
+
media to end while autoplaying); the per-slide dwell is <code>slidetimeout</code>.
|
|
117
|
+
All are validated
|
|
118
|
+
against <code>schema/storymap.schema.json</code> — read it (or <code>src/types.ts</code>) for the
|
|
119
|
+
full list with defaults.</p>
|
|
120
|
+
<p><code>show_layers_control: true</code> adds a menubar disclosure button listing the
|
|
121
|
+
<code>overlays[]</code> as checkboxes and <code>basemaps[]</code> as basemap radios, so the
|
|
122
|
+
visitor can switch layers without touching code.</p>
|
|
123
|
+
<p><code>theme: "dark"</code> forces the dark palette, <code>"light"</code> pins the light one;
|
|
124
|
+
unset, the widget follows <code>prefers-color-scheme</code>.</p>
|
|
125
|
+
<h3>Slideshow-style tours</h3>
|
|
126
|
+
<p>Slides can carry per-slide presentation for image tours (a stop can restyle
|
|
127
|
+
the view while it is active; everything is optional and validated against
|
|
128
|
+
<code>schema/storymap.schema.json</code>):</p>
|
|
129
|
+
<pre><code>location: {
|
|
130
|
+
region: [x, y, w, h], // image-pixel stop (IIIF xywh); negative origins clamp to the canvas
|
|
131
|
+
rotation: 45, // view rotation in degrees clockwise
|
|
132
|
+
filter: { sepia: 40 }, // brightness/contrast/saturate 0-200 (%), hueRotate -180-180 (°), sepia 0-100 (%), blur 0-20 (px)
|
|
133
|
+
mask: { x: 0.1, y: 0.1, w: 0.8, h: 0.8, opacity: 0.5 }, // spotlight mask (fractions) + color/invert
|
|
134
|
+
basemap: "osm:bright", // per-slide basemap (any map_type, IIIF info.json URL or image file)
|
|
135
|
+
},
|
|
136
|
+
narration: { url, loop, offset, play: "auto"|"click", stopOnExit, stopAllPrevious },
|
|
137
|
+
slidetimeout: 9000, // per-slide autoplay dwell in ms (0 holds); default is the global autoplay
|
|
138
|
+
imgoverlay: { url, size, extent, opacity }, // image overlay while the slide is active
|
|
139
|
+
</code></pre>
|
|
140
|
+
<p>Audio/video media take the same <code>offset</code>/<code>loop</code>/<code>play</code>/<code>stopOnExit</code> flags
|
|
141
|
+
on the slide's <code>media</code> object (<code>stopAllPrevious</code> is narration-only).</p>
|
|
142
|
+
<p>When a slide's IIIF <code>info.json</code> cannot be loaded, <code>iiif: { width, height, fallbackUrl }</code> paints the static image instead of a blank basemap. Without
|
|
143
|
+
stated dimensions the viewer probes the fallback image's natural size first,
|
|
144
|
+
but only for slideshow tours (15s timeout); other documents keep the logged
|
|
145
|
+
error path. Per-slide static basemaps (<code>image_srv</code> pointing at a plain
|
|
146
|
+
image file, absolute or same-origin relative) probe the same way, and a
|
|
147
|
+
failed <code>info.json</code> fetch falls back to a probed static image in place.</p>
|
|
148
|
+
<p>The player chrome is opt-in storymap options (absent means the default
|
|
149
|
+
layout): <code>textmode: "left"|"right"|"bottom"</code> with <code>textsize</code> (10–80 %,
|
|
150
|
+
bottom dock only — the player drops side-dock sizes too),
|
|
151
|
+
<code>progressbar: "bar"|"dots"|"squares"|"block"|"thinblock"|"off"</code> (<code>true</code>
|
|
152
|
+
means <code>"bar"</code>, <code>false</code> means hidden),
|
|
153
|
+
<code>fxmode: "slide"|"fade"|"none"</code>, <code>mode: "static"</code> (stacked reading list with
|
|
154
|
+
scroll-spy map sync), <code>hudcolor</code>/<code>hudbgcolor</code>/<code>hudopacity</code>,
|
|
155
|
+
<code>shownav</code>/<code>show_headings</code>/<code>show_scrollbars</code>/<code>show_info</code> toggles and
|
|
156
|
+
<code>viewerheight: "400px"</code>.</p>
|
|
157
|
+
<p><strong>IIIF round-trip:</strong> the per-slide fields do survive — <code>rotation</code>,
|
|
158
|
+
<code>filter</code>, <code>mask</code>, <code>basemap</code>, <code>slidetimeout</code>, <code>imgoverlay</code>, <code>provenance</code>
|
|
159
|
+
and the playback bags travel as <code>storymap:</code> terms (see
|
|
160
|
+
<a href="./iiif.html">docs/storymap-as-iiif-manifest.md</a>).
|
|
161
|
+
The player chrome does <strong>not</strong>: it has no IIIF vocabulary and is
|
|
162
|
+
translator-only (a storymap→manifest→storymap cycle drops it).</p>
|
|
163
|
+
<p>These presentation fields render <strong>only for slideshow tours</strong> (documents
|
|
164
|
+
loaded from that format, which set the internal <code>slideshow_source</code> marker).
|
|
165
|
+
Hand-written storymap documents and IIIF manifests keep the long-standing
|
|
166
|
+
rendering even when they name the new keys — captions always show, the
|
|
167
|
+
autoplay interval stays global, the panel keeps its default dock. Hosts may
|
|
168
|
+
pass <code>slideshow_source: true</code> explicitly as an escape hatch (e.g. in tests).</p>
|
|
169
|
+
<p>Slideshow tours (W3C <code>AnnotationCollection</code> documents) load directly — by
|
|
170
|
+
object, file or URL, following <code>next</code> pages — or convert offline with
|
|
171
|
+
<code>npm run convert:slideshow -- [--settings settings.json] [--out out.json] <tour-url-or-file></code>
|
|
172
|
+
(see <a href="docs/slideshow.md">docs/slideshow.md</a> for the field mapping,
|
|
173
|
+
player-settings handling and loss table).</p>
|
|
105
174
|
<p>Images can now be used in place of map pins.
|
|
106
175
|
Use <code>image</code> inside the location object and include a url to use, together with
|
|
107
176
|
<code>use_custom_marker: true</code> in the location object (or set <code>use_custom_markers: true</code> globally in the storymap options). Same goes for custom icons except you
|
|
@@ -126,18 +195,27 @@ map_type: "https://tiles.openfreemap.org/styles/bright", // vector st
|
|
|
126
195
|
<p>Any value containing <code>{z}</code> renders as a raster XYZ layer; a path without <code>{z}</code>
|
|
127
196
|
that looks like a URL/path renders as a vector style layer; anything else falls
|
|
128
197
|
back to classic OSM raster — except <code>"none"</code>, which builds no map at all and
|
|
129
|
-
runs the story as text and media only
|
|
198
|
+
runs the story as text and media only. A full template naming a known provider
|
|
199
|
+
(<code>https://tile.openstreetmap.org/{z}/{x}/{y}.png</code>) is credited to that
|
|
200
|
+
provider; anything else gets the generic "Map data" line (add your own via
|
|
201
|
+
<code>attribution</code>).</p>
|
|
130
202
|
<h3>Switching the basemap at runtime</h3>
|
|
131
203
|
<p><code>storymap.setMapOption("map_type", next)</code> / <code>setMapOptions({...})</code> rebuilds the
|
|
132
204
|
main tile layer <strong>and</strong> the minimap (<code>ol/control/OverviewMap</code>) layer, keeping
|
|
133
205
|
the overview fitted to the marker bounds (zoomify/IIIF extents preserved). The
|
|
134
206
|
current slide is re-fitted after the swap.</p>
|
|
135
207
|
<h3>Icons</h3>
|
|
136
|
-
<p>Default pins use the bundled <code>vco-icons</code> font (<code>dist/css/icons/</code
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
208
|
+
<p>Default pins use the bundled <code>vco-icons</code> font (<code>dist/css/icons/</code>). The SCSS
|
|
209
|
+
source uses the absolute public path (<code>/css/icons/...</code>) so <code>vite dev</code> serves
|
|
210
|
+
the fonts directly; <code>vite build</code> rewrites them to relative <code>./icons/...</code> in
|
|
211
|
+
<code>dist/css/storymap.css</code>, so pins render on subpath deploys, for bundler
|
|
212
|
+
consumers and on <code>file://</code>/Electron hosts without extra configuration.
|
|
213
|
+
Import the stylesheet once
|
|
214
|
+
(<code>import "@projektemacher/storymapjs/css/storymap.css"</code>).</p>
|
|
215
|
+
<p>Font themes (<code>font_css: "stock:<name>"</code>) resolve via <code>import.meta.url</code>, so
|
|
216
|
+
they only work script-tagged, unbundled. A bundler consumer imports the theme
|
|
217
|
+
instead (<code>import "@projektemacher/storymapjs/css/fonts/font.default.css"</code>)
|
|
218
|
+
and passes <code>font_css: false</code> for no injected <code><link></code>.</p>
|
|
141
219
|
<h2>Custom HTML in slide content</h2>
|
|
142
220
|
<p>Slide text is rendered as HTML: the <code>text</code> (and <code>headline</code>) fields accept
|
|
143
221
|
arbitrary markup. If the text contains no <code><p></code> tag, it is wrapped in one
|
|
@@ -181,15 +259,38 @@ appear for services discovered later (e.g. a preloaded slide).</p>
|
|
|
181
259
|
<p>Decisions are stored in <code>localStorage</code> under <code>storymapjs-consent</code> and have no
|
|
182
260
|
expiry — clearing site data asks again.</p>
|
|
183
261
|
<p>The consent labels are <strong>not</strong> fully translated. <code>src/language/locale/en.json</code>
|
|
184
|
-
defines every string
|
|
185
|
-
|
|
186
|
-
|
|
262
|
+
defines every string (34 keys across 29 locale files: English plus 28
|
|
263
|
+
translations). German is missing 1 key, most locales are missing 9 (the audio
|
|
264
|
+
badge, autoplay, layer-switcher, iframe-title and narration-consent strings),
|
|
265
|
+
and five locales (<code>et</code>, <code>is</code>, <code>nn</code>, <code>ur</code>, <code>sr</code>) are missing 18–19 (additionally
|
|
266
|
+
the fullscreen, consent-dialog, error and overview strings). Run
|
|
187
267
|
<code>npm run check:locales</code> to see the current state — it reports the gap per
|
|
188
268
|
locale and is expected to be runnable without failing.</p>
|
|
189
269
|
<h2>Troubleshooting</h2>
|
|
190
270
|
<p>If a storymap fails to render, open the browser console: the viewer logs
|
|
191
271
|
fetch and validation errors (e.g. "could not load storymap data from ...").
|
|
192
|
-
The <code>error</code> event also fires for programmatic consumers
|
|
272
|
+
The <code>error</code> event also fires for programmatic consumers. The full event
|
|
273
|
+
reference (payloads included) is <a href="./events.html">docs/events.md</a>.</p>
|
|
274
|
+
<h2>Accessibility</h2>
|
|
275
|
+
<p>Supported, and covered by tests: text alternatives on slide images
|
|
276
|
+
(decorative <code>alt=""</code> included); real <code><button></code> menubar actions and slide
|
|
277
|
+
navigation; polite live-region slide announcements; reduced-motion handling
|
|
278
|
+
of the slide glide and autoplay; an embed page that does not disable zoom;
|
|
279
|
+
sanitized author tables that keep their semantics; slides hidden from
|
|
280
|
+
assistive tech while inactive (<code>aria-hidden</code> + <code>inert</code>), with a layer
|
|
281
|
+
switcher built from native checkboxes, radios and fieldsets; keyboard
|
|
282
|
+
operable map pins and message dismissal; a skip link to the slide content;
|
|
283
|
+
an autoplay pause/resume toggle; slide text pronounced in its own language
|
|
284
|
+
(<code>lang</code>); consent dialogs exposed with labels and focus; media errors
|
|
285
|
+
announced as alerts; and a motion kill-switch that also honors an
|
|
286
|
+
OS reduced-motion toggle flipped mid-story.</p>
|
|
287
|
+
<p>Known limitations (not fixed here): map markers are pointer-only; audio and
|
|
288
|
+
video have no viewer-side captions or transcripts; narration ships without a
|
|
289
|
+
transcript; focus moves only when the layer panel closes with Escape; labels
|
|
290
|
+
and announcements are hardcoded English; several muted text colors fall
|
|
291
|
+
below 4.5:1; third-party embeds are the vendor's conformance. No VPAT or
|
|
292
|
+
ACR is claimed — §508 conformance is decided per deliverable by an
|
|
293
|
+
external audit.</p>
|
|
193
294
|
<h2>Bundled credentials</h2>
|
|
194
295
|
<p>The viewer ships no credentials. Mapbox/Stadia tiles need a token passed via
|
|
195
296
|
<code>map_access_token</code>, and <code>flickr.com/photos</code> API URLs need <code>api_key_flickr</code>
|
package/dist/embed/index.html
CHANGED
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
}
|
|
64
64
|
.storymap-url-card button {
|
|
65
65
|
padding: 8px 16px;
|
|
66
|
+
min-height: 44px;
|
|
66
67
|
font-size: 1rem;
|
|
67
68
|
border: 1px solid #333;
|
|
68
69
|
border-radius: 4px;
|
|
@@ -128,6 +129,8 @@
|
|
|
128
129
|
const showEmbedError = (message) => {
|
|
129
130
|
const el = document.createElement("div");
|
|
130
131
|
el.className = "vco-consent-blocked";
|
|
132
|
+
// announce to AT (issue #385 wave)
|
|
133
|
+
el.setAttribute("role", "alert");
|
|
131
134
|
// inline fallback styles in case the widget CSS did not load
|
|
132
135
|
el.style.cssText =
|
|
133
136
|
"display:flex;align-items:center;justify-content:center;width:100%;height:100%;padding:20px;background-color:#fff;color:#333;font-family:sans-serif;text-align:center;";
|
|
@@ -173,6 +176,8 @@
|
|
|
173
176
|
error.id = "storymap-url-error";
|
|
174
177
|
error.className = "storymap-url-error";
|
|
175
178
|
error.hidden = true;
|
|
179
|
+
// the input describes its error slot (issue #385 wave)
|
|
180
|
+
input.setAttribute("aria-describedby", "storymap-url-error");
|
|
176
181
|
row.append(input, button);
|
|
177
182
|
form.append(label, row, error);
|
|
178
183
|
card.append(heading, hint, form);
|
|
@@ -191,6 +196,8 @@
|
|
|
191
196
|
} catch {
|
|
192
197
|
error.textContent = "Please enter a valid URL to a storymap.json file.";
|
|
193
198
|
error.hidden = false;
|
|
199
|
+
error.setAttribute("role", "alert");
|
|
200
|
+
input.setAttribute("aria-invalid", "true");
|
|
194
201
|
return;
|
|
195
202
|
}
|
|
196
203
|
urlParams.set("url", value);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"storymap": {
|
|
3
|
+
"map_type": "osm",
|
|
4
|
+
"font_css": false,
|
|
5
|
+
"slides": [
|
|
6
|
+
{
|
|
7
|
+
"type": "overview",
|
|
8
|
+
"date": "",
|
|
9
|
+
"text": {
|
|
10
|
+
"headline": "A story with font loading disabled",
|
|
11
|
+
"text": "The host page bundles its own font theme."
|
|
12
|
+
},
|
|
13
|
+
"media": {
|
|
14
|
+
"url": "",
|
|
15
|
+
"caption": "",
|
|
16
|
+
"credit": ""
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "",
|
|
21
|
+
"text": {
|
|
22
|
+
"headline": "Second slide",
|
|
23
|
+
"text": "<p>No font stylesheet is appended by the viewer.</p>"
|
|
24
|
+
},
|
|
25
|
+
"media": {
|
|
26
|
+
"url": "",
|
|
27
|
+
"caption": "",
|
|
28
|
+
"credit": ""
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"storymap": {
|
|
3
|
+
"map_type": "osm",
|
|
4
|
+
"keyboard": true,
|
|
5
|
+
"overlays": [
|
|
6
|
+
{
|
|
7
|
+
"map_type": "./tiles/historic/{z}/{x}/{y}.png",
|
|
8
|
+
"opacity": 0.6,
|
|
9
|
+
"attribution": "Historic sheet (demo overlay)"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"map_type": "./tiles/railway/{z}/{x}/{y}.png",
|
|
13
|
+
"visible": false,
|
|
14
|
+
"attribution": "Railway lines (demo overlay)"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"slides": [
|
|
18
|
+
{
|
|
19
|
+
"type": "overview",
|
|
20
|
+
"date": "1890",
|
|
21
|
+
"text": {
|
|
22
|
+
"headline": "Layers control",
|
|
23
|
+
"text": "A menubar disclosure button lists the overlays above so the visitor can toggle them. Arrow keys navigate the story."
|
|
24
|
+
},
|
|
25
|
+
"media": {
|
|
26
|
+
"url": "",
|
|
27
|
+
"caption": "",
|
|
28
|
+
"credit": ""
|
|
29
|
+
},
|
|
30
|
+
"location": { "lat": 51.5074, "lon": -0.1278, "zoom": 10 }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"date": "1900",
|
|
34
|
+
"text": {
|
|
35
|
+
"headline": "The historic sheet",
|
|
36
|
+
"text": "The first overlay starts visible; unchecking its row hides the layer and drops its credit."
|
|
37
|
+
},
|
|
38
|
+
"media": {
|
|
39
|
+
"url": "",
|
|
40
|
+
"caption": "",
|
|
41
|
+
"credit": ""
|
|
42
|
+
},
|
|
43
|
+
"location": { "lat": 51.5155, "lon": -0.0922, "zoom": 12, "line": true }
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"date": "1910",
|
|
47
|
+
"text": {
|
|
48
|
+
"headline": "The railway lines",
|
|
49
|
+
"text": "The second overlay starts hidden; checking its row paints it above the basemap."
|
|
50
|
+
},
|
|
51
|
+
"media": {
|
|
52
|
+
"url": "",
|
|
53
|
+
"caption": "",
|
|
54
|
+
"credit": ""
|
|
55
|
+
},
|
|
56
|
+
"location": { "lat": 51.4818, "lon": -0.0046, "zoom": 11, "line": true }
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"storymap": {
|
|
3
|
+
"map_type": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
4
|
+
"slides": [
|
|
5
|
+
{
|
|
6
|
+
"type": "overview",
|
|
7
|
+
"date": "",
|
|
8
|
+
"text": {
|
|
9
|
+
"headline": "A longhand OSM template",
|
|
10
|
+
"text": "The base layer names OpenStreetMap by its full tile template, and the credit line still credits it."
|
|
11
|
+
},
|
|
12
|
+
"media": {
|
|
13
|
+
"url": "",
|
|
14
|
+
"caption": "",
|
|
15
|
+
"credit": ""
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"date": "",
|
|
20
|
+
"text": {
|
|
21
|
+
"headline": "Paris",
|
|
22
|
+
"text": "<p>A stop on a template-credited map.</p>"
|
|
23
|
+
},
|
|
24
|
+
"location": {
|
|
25
|
+
"lat": 48.85,
|
|
26
|
+
"lon": 2.35
|
|
27
|
+
},
|
|
28
|
+
"media": {
|
|
29
|
+
"url": "",
|
|
30
|
+
"caption": "",
|
|
31
|
+
"credit": ""
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"storymap": {
|
|
3
|
+
"call_to_action": false,
|
|
4
|
+
"map_as_image": false,
|
|
5
|
+
"map_type": "osm",
|
|
6
|
+
"slides": [
|
|
7
|
+
{
|
|
8
|
+
"date": "",
|
|
9
|
+
"type": "overview",
|
|
10
|
+
"text": {
|
|
11
|
+
"headline": "Multiple media per slide",
|
|
12
|
+
"text": "A slide can carry extra visible media items after its primary one."
|
|
13
|
+
},
|
|
14
|
+
"media": {
|
|
15
|
+
"url": "/examples/assets/placeholder-landscape.jpg",
|
|
16
|
+
"caption": "Primary media",
|
|
17
|
+
"credit": ""
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"date": "",
|
|
22
|
+
"text": {
|
|
23
|
+
"headline": "Side by side",
|
|
24
|
+
"text": "Two items with media_layout row sit next to each other."
|
|
25
|
+
},
|
|
26
|
+
"location": {
|
|
27
|
+
"lat": 48.85,
|
|
28
|
+
"lon": 2.35,
|
|
29
|
+
"zoom": 6
|
|
30
|
+
},
|
|
31
|
+
"media": {
|
|
32
|
+
"url": "/examples/assets/placeholder-city.jpg",
|
|
33
|
+
"caption": "First item",
|
|
34
|
+
"credit": ""
|
|
35
|
+
},
|
|
36
|
+
"media_extra": [
|
|
37
|
+
{
|
|
38
|
+
"url": "https://example.com/iframe/embed/123",
|
|
39
|
+
"caption": "Second item",
|
|
40
|
+
"credit": ""
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"media_layout": "row"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"date": "",
|
|
47
|
+
"text": {
|
|
48
|
+
"headline": "Stacked with audio",
|
|
49
|
+
"text": "Items pile vertically by default, and an audible extra badges the marker."
|
|
50
|
+
},
|
|
51
|
+
"location": {
|
|
52
|
+
"lat": 52.52,
|
|
53
|
+
"lon": 13.4,
|
|
54
|
+
"zoom": 6
|
|
55
|
+
},
|
|
56
|
+
"media": {
|
|
57
|
+
"url": "/examples/assets/placeholder-portrait.jpg",
|
|
58
|
+
"caption": "First item",
|
|
59
|
+
"credit": ""
|
|
60
|
+
},
|
|
61
|
+
"media_extra": [
|
|
62
|
+
{
|
|
63
|
+
"url": "/examples/assets/tone.mp3",
|
|
64
|
+
"caption": "Second item",
|
|
65
|
+
"credit": ""
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -179,6 +179,22 @@
|
|
|
179
179
|
"y": 1500
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "https://example.org/storymap/annotated-image/canvas/1/annotation/105",
|
|
185
|
+
"type": "Annotation",
|
|
186
|
+
"motivation": "supplementing",
|
|
187
|
+
"body": {
|
|
188
|
+
"id": "https://example.org/audio/tour-narration.mp3",
|
|
189
|
+
"type": "Sound",
|
|
190
|
+
"format": "audio/mpeg",
|
|
191
|
+
"label": {
|
|
192
|
+
"none": [
|
|
193
|
+
"Spoken tour of the panel"
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"target": "https://example.org/storymap/annotated-image/canvas/1"
|
|
182
198
|
}
|
|
183
199
|
]
|
|
184
200
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@context": [
|
|
3
|
+
"http://iiif.io/api/extension/navplace/context.json",
|
|
4
|
+
"http://iiif.io/api/presentation/3/context.json",
|
|
5
|
+
"https://cmahnke.github.io/StoryMapJS/navplace-properties.json",
|
|
6
|
+
"https://cmahnke.github.io/StoryMapJS/context.json"
|
|
7
|
+
],
|
|
8
|
+
"id": "https://example.org/storymap/font-css-false",
|
|
9
|
+
"type": "Manifest",
|
|
10
|
+
"label": {
|
|
11
|
+
"none": [
|
|
12
|
+
"font-css-false"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"behavior": [
|
|
16
|
+
"paged"
|
|
17
|
+
],
|
|
18
|
+
"metadata": [
|
|
19
|
+
{
|
|
20
|
+
"label": {
|
|
21
|
+
"none": [
|
|
22
|
+
"Generated by"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"value": {
|
|
26
|
+
"none": [
|
|
27
|
+
"StoryMapJS"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"items": [
|
|
33
|
+
{
|
|
34
|
+
"id": "https://example.org/storymap/font-css-false/canvas/1",
|
|
35
|
+
"type": "Canvas",
|
|
36
|
+
"height": 1080,
|
|
37
|
+
"width": 1080,
|
|
38
|
+
"items": [
|
|
39
|
+
{
|
|
40
|
+
"id": "https://example.org/storymap/font-css-false/canvas/1/annotationpage/1",
|
|
41
|
+
"type": "AnnotationPage",
|
|
42
|
+
"items": [
|
|
43
|
+
{
|
|
44
|
+
"id": "https://example.org/storymap/font-css-false/canvas/1/annotation/1",
|
|
45
|
+
"type": "Annotation",
|
|
46
|
+
"motivation": "painting",
|
|
47
|
+
"body": {
|
|
48
|
+
"type": "TextualBody",
|
|
49
|
+
"format": "text/html",
|
|
50
|
+
"value": "The host page bundles its own font theme."
|
|
51
|
+
},
|
|
52
|
+
"target": "https://example.org/storymap/font-css-false/canvas/1"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"label": {
|
|
58
|
+
"none": [
|
|
59
|
+
"A story with font loading disabled"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"summary": {
|
|
63
|
+
"none": [
|
|
64
|
+
"The host page bundles its own font theme."
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"storymap:type": "overview"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "https://example.org/storymap/font-css-false/canvas/2",
|
|
71
|
+
"type": "Canvas",
|
|
72
|
+
"height": 1080,
|
|
73
|
+
"width": 1080,
|
|
74
|
+
"items": [
|
|
75
|
+
{
|
|
76
|
+
"id": "https://example.org/storymap/font-css-false/canvas/2/annotationpage/1",
|
|
77
|
+
"type": "AnnotationPage",
|
|
78
|
+
"items": [
|
|
79
|
+
{
|
|
80
|
+
"id": "https://example.org/storymap/font-css-false/canvas/2/annotation/1",
|
|
81
|
+
"type": "Annotation",
|
|
82
|
+
"motivation": "painting",
|
|
83
|
+
"body": {
|
|
84
|
+
"type": "TextualBody",
|
|
85
|
+
"format": "text/html",
|
|
86
|
+
"value": "<p>No font stylesheet is appended by the viewer.</p>"
|
|
87
|
+
},
|
|
88
|
+
"target": "https://example.org/storymap/font-css-false/canvas/2"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"label": {
|
|
94
|
+
"none": [
|
|
95
|
+
"Second slide"
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
"summary": {
|
|
99
|
+
"none": [
|
|
100
|
+
"<p>No font stylesheet is appended by the viewer.</p>"
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"service": [
|
|
106
|
+
{
|
|
107
|
+
"id": "https://example.org/storymap/font-css-false/map-config",
|
|
108
|
+
"type": "Service",
|
|
109
|
+
"profile": "https://cmahnke.github.io/StoryMapJS/context.json/mapconfig",
|
|
110
|
+
"storymap:basemap": "osm",
|
|
111
|
+
"storymap:fontCss": false
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|