@projektemacher/storymapjs 0.10.5 → 0.10.7

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 (148) hide show
  1. package/CHANGELOG +11 -0
  2. package/dist/assets/{demo-CVQ7kFek.js → demo-D6cTmzn6.js} +1 -1
  3. package/dist/assets/{harness-C-VZV-ou.js → harness-BPFlzutp.js} +1 -1
  4. package/dist/assets/main-Y-MYUSJ4.js +17 -0
  5. package/dist/css/fonts/font.oldstandard.css +14 -32
  6. package/dist/demo.html +2 -2
  7. package/dist/docs/migration.html +1 -1
  8. package/dist/embed/index.html +129 -4
  9. package/dist/harness.html +2 -2
  10. package/dist/index.html +17 -0
  11. package/dist/js/storymap.d.ts +126 -7
  12. package/dist/js/storymap.js +4518 -3613
  13. package/dist/js/storymap.js.map +1 -1
  14. package/docs/migration-from-knightlab.md +139 -0
  15. package/docs/storymap-as-iiif-manifest.md +510 -0
  16. package/package.json +6 -3
  17. package/src/animation/easings.ts +18 -0
  18. package/src/animation/morpheus.d.ts +41 -0
  19. package/src/core/Browser.ts +19 -0
  20. package/src/core/Load.ts +180 -0
  21. package/src/core/Util.ts +354 -0
  22. package/src/core/mixins.ts +171 -0
  23. package/src/dom/Dom.ts +31 -0
  24. package/src/dom/DomEvent.ts +61 -0
  25. package/src/globals.d.ts +16 -0
  26. package/src/language/Language.ts +107 -0
  27. package/src/language/locale/be.json +18 -0
  28. package/src/language/locale/bg.json +18 -0
  29. package/src/language/locale/cs.json +18 -0
  30. package/src/language/locale/de.json +20 -0
  31. package/src/language/locale/el.json +18 -0
  32. package/src/language/locale/en.json +28 -0
  33. package/src/language/locale/es.json +18 -0
  34. package/src/language/locale/et.json +18 -0
  35. package/src/language/locale/fr.json +18 -0
  36. package/src/language/locale/he.json +18 -0
  37. package/src/language/locale/hu.json +18 -0
  38. package/src/language/locale/is.json +18 -0
  39. package/src/language/locale/it.json +18 -0
  40. package/src/language/locale/jp.json +18 -0
  41. package/src/language/locale/ko.json +18 -0
  42. package/src/language/locale/nl.json +18 -0
  43. package/src/language/locale/nn.json +18 -0
  44. package/src/language/locale/no.json +18 -0
  45. package/src/language/locale/pl.json +18 -0
  46. package/src/language/locale/pt.json +18 -0
  47. package/src/language/locale/ru.json +18 -0
  48. package/src/language/locale/sk.json +18 -0
  49. package/src/language/locale/sr.json +17 -0
  50. package/src/language/locale/sv.json +18 -0
  51. package/src/language/locale/tr.json +18 -0
  52. package/src/language/locale/uk.json +18 -0
  53. package/src/language/locale/ur.json +18 -0
  54. package/src/language/locale/zh-cn.json +18 -0
  55. package/src/language/locale/zh-tw.json +18 -0
  56. package/src/main.ts +51 -0
  57. package/src/map/Map.ts +717 -0
  58. package/src/map/MapMarker.ts +149 -0
  59. package/src/map/openlayers/Map.OpenLayers.ts +1879 -0
  60. package/src/map/openlayers/MapMarker.OpenLayers.ts +176 -0
  61. package/src/map/openlayers/zoomifyTiles.ts +28 -0
  62. package/src/map/types.ts +17 -0
  63. package/src/media/EmbedUtil.ts +168 -0
  64. package/src/media/Media.ts +409 -0
  65. package/src/media/MediaType.ts +163 -0
  66. package/src/media/types/Audio.ts +87 -0
  67. package/src/media/types/Blockquote.ts +40 -0
  68. package/src/media/types/DailyMotion.ts +58 -0
  69. package/src/media/types/DocumentCloud.ts +41 -0
  70. package/src/media/types/Facebook.ts +41 -0
  71. package/src/media/types/Flickr.ts +115 -0
  72. package/src/media/types/GoogleDoc.ts +59 -0
  73. package/src/media/types/IFrame.ts +51 -0
  74. package/src/media/types/Image.ts +49 -0
  75. package/src/media/types/Juxtapose.ts +32 -0
  76. package/src/media/types/SoundCloud.ts +77 -0
  77. package/src/media/types/Text.ts +172 -0
  78. package/src/media/types/Twitter.ts +96 -0
  79. package/src/media/types/Video.ts +84 -0
  80. package/src/media/types/Vimeo.ts +65 -0
  81. package/src/media/types/Website.ts +36 -0
  82. package/src/media/types/Wikipedia.ts +124 -0
  83. package/src/media/types/YouTube.ts +192 -0
  84. package/src/scss/Typography.scss +237 -0
  85. package/src/scss/VCO.StoryMap.Dark.scss +138 -0
  86. package/src/scss/VCO.StoryMap.scss +164 -0
  87. package/src/scss/Variables.Dark.scss +56 -0
  88. package/src/scss/Variables.scss +47 -0
  89. package/src/scss/core/Mixins.scss +112 -0
  90. package/src/scss/core/Reset.scss +206 -0
  91. package/src/scss/fonts/_font.base.scss +113 -0
  92. package/src/scss/fonts/font.abril-droidsans.scss +75 -0
  93. package/src/scss/fonts/font.amatic-andika.scss +73 -0
  94. package/src/scss/fonts/font.bitter-raleway.scss +86 -0
  95. package/src/scss/fonts/font.clicker-garamond.scss +92 -0
  96. package/src/scss/fonts/font.dancing-ledger.scss +74 -0
  97. package/src/scss/fonts/font.default.scss +9 -0
  98. package/src/scss/fonts/font.fjalla-average.scss +80 -0
  99. package/src/scss/fonts/font.georgia-helvetica.scss +58 -0
  100. package/src/scss/fonts/font.knightlab.scss +97 -0
  101. package/src/scss/fonts/font.lustria-lato.scss +80 -0
  102. package/src/scss/fonts/font.medula-lato.scss +73 -0
  103. package/src/scss/fonts/font.oldstandard.scss +88 -0
  104. package/src/scss/fonts/font.opensans-gentiumbook.scss +80 -0
  105. package/src/scss/fonts/font.playfair-faunaone.scss +86 -0
  106. package/src/scss/fonts/font.playfair.scss +85 -0
  107. package/src/scss/fonts/font.pt.scss +90 -0
  108. package/src/scss/fonts/font.roboto-megrim.scss +73 -0
  109. package/src/scss/fonts/font.rufina-sintony.scss +73 -0
  110. package/src/scss/fonts/font.ubuntu.scss +78 -0
  111. package/src/scss/fonts/font.unicaone-vollkorn.scss +85 -0
  112. package/src/scss/icons/Icons.scss +239 -0
  113. package/src/scss/map/VCO.ImageMarker.scss +23 -0
  114. package/src/scss/map/VCO.Map.scss +21 -0
  115. package/src/scss/map/VCO.MapMarker.scss +147 -0
  116. package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +126 -0
  117. package/src/scss/media/VCO.Media.scss +222 -0
  118. package/src/scss/media/types/VCO.Media.Blockquote.scss +76 -0
  119. package/src/scss/media/types/VCO.Media.IFrame.scss +11 -0
  120. package/src/scss/media/types/VCO.Media.Image.scss +13 -0
  121. package/src/scss/media/types/VCO.Media.Instagram.scss +7 -0
  122. package/src/scss/media/types/VCO.Media.Profile.scss +5 -0
  123. package/src/scss/media/types/VCO.Media.Text.scss +90 -0
  124. package/src/scss/media/types/VCO.Media.Twitter.scss +87 -0
  125. package/src/scss/media/types/VCO.Media.Wikipedia.scss +64 -0
  126. package/src/scss/site/site.scss +748 -0
  127. package/src/scss/slider/VCO.Slide.scss +447 -0
  128. package/src/scss/slider/VCO.SlideNav.scss +338 -0
  129. package/src/scss/slider/VCO.StorySlider.scss +64 -0
  130. package/src/scss/snapmap/VCO.SnapMap.scss +103 -0
  131. package/src/scss/ui/VCO.Consent.scss +77 -0
  132. package/src/scss/ui/VCO.MenuBar.Button.scss +99 -0
  133. package/src/scss/ui/VCO.MenuBar.scss +20 -0
  134. package/src/scss/ui/VCO.Message.scss +104 -0
  135. package/src/site/site.ts +87 -0
  136. package/src/slider/Slide.ts +460 -0
  137. package/src/slider/SlideNav.ts +212 -0
  138. package/src/slider/StorySlider.ts +722 -0
  139. package/src/storymap/Consent.ts +146 -0
  140. package/src/storymap/StoryMap.ts +1108 -0
  141. package/src/storymap/iiif.ts +386 -0
  142. package/src/storymap/validate.ts +184 -0
  143. package/src/types.ts +297 -0
  144. package/src/ui/Draggable.ts +374 -0
  145. package/src/ui/MenuBar.ts +323 -0
  146. package/src/ui/Message.ts +118 -0
  147. package/src/ui/Swipable.ts +388 -0
  148. package/dist/assets/main-DwbXrrYn.js +0 -17
@@ -12,15 +12,6 @@
12
12
  ================================================== */
13
13
  /* Font Base
14
14
  ----------------------------------------------------- */
15
- /* old-standard-tt-latin-400-italic */
16
- @font-face {
17
- font-family: "Old Standard TT";
18
- font-style: italic;
19
- font-display: swap;
20
- font-weight: 400;
21
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
22
- src: url(files/old-standard-tt-latin-400-italic.woff2) format("woff2");
23
- }
24
15
  /* old-standard-tt-latin-400-normal */
25
16
  @font-face {
26
17
  font-family: "Old Standard TT";
@@ -30,15 +21,6 @@
30
21
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
31
22
  src: url(files/old-standard-tt-latin-400-normal.woff2) format("woff2");
32
23
  }
33
- /* old-standard-tt-latin-700-italic */
34
- @font-face {
35
- font-family: "Old Standard TT";
36
- font-style: italic;
37
- font-display: swap;
38
- font-weight: 700;
39
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
40
- src: url("@fontsource/old-standard-tt/files/old-standard-tt-latin-700-italic.woff2") format("woff2");
41
- }
42
24
  /* old-standard-tt-latin-700-normal */
43
25
  @font-face {
44
26
  font-family: "Old Standard TT";
@@ -48,41 +30,41 @@
48
30
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
49
31
  src: url(files/old-standard-tt-latin-700-normal.woff2) format("woff2");
50
32
  }
51
- /* old-standard-tt-latin-ext-400-italic */
33
+ /* old-standard-tt-latin-ext-400-normal */
52
34
  @font-face {
53
35
  font-family: "Old Standard TT";
54
- font-style: italic;
36
+ font-style: normal;
55
37
  font-display: swap;
56
38
  font-weight: 400;
57
39
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
58
- src: url(files/old-standard-tt-latin-ext-400-italic.woff2) format("woff2");
40
+ src: url(files/old-standard-tt-latin-ext-400-normal.woff2) format("woff2");
59
41
  }
60
- /* old-standard-tt-latin-ext-400-normal */
42
+ /* old-standard-tt-latin-ext-700-normal */
61
43
  @font-face {
62
44
  font-family: "Old Standard TT";
63
45
  font-style: normal;
64
46
  font-display: swap;
65
- font-weight: 400;
47
+ font-weight: 700;
66
48
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
67
- src: url(files/old-standard-tt-latin-ext-400-normal.woff2) format("woff2");
49
+ src: url(files/old-standard-tt-latin-ext-700-normal.woff2) format("woff2");
68
50
  }
69
- /* old-standard-tt-latin-ext-700-italic */
51
+ /* old-standard-tt-latin-400-italic */
70
52
  @font-face {
71
53
  font-family: "Old Standard TT";
72
54
  font-style: italic;
73
55
  font-display: swap;
74
- font-weight: 700;
75
- unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
76
- src: url("@fontsource/old-standard-tt/files/old-standard-tt-latin-ext-700-italic.woff2") format("woff2");
56
+ font-weight: 400;
57
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
58
+ src: url(files/old-standard-tt-latin-400-italic.woff2) format("woff2");
77
59
  }
78
- /* old-standard-tt-latin-ext-700-normal */
60
+ /* old-standard-tt-latin-ext-400-italic */
79
61
  @font-face {
80
62
  font-family: "Old Standard TT";
81
- font-style: normal;
63
+ font-style: italic;
82
64
  font-display: swap;
83
- font-weight: 700;
65
+ font-weight: 400;
84
66
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
85
- src: url(files/old-standard-tt-latin-ext-700-normal.woff2) format("woff2");
67
+ src: url(files/old-standard-tt-latin-ext-400-italic.woff2) format("woff2");
86
68
  }
87
69
  /* Font Old Standard
88
70
  https://fonts.google.com/specimen/Old+Standard+TT
package/dist/demo.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <title>StoryMapJS Demo</title>
5
5
  <meta charset="utf-8" />
6
6
  <style>*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0;padding:0}#storymap-embed{width:100%;height:100%}</style>
7
- <script type="module" crossorigin src="./assets/demo-CVQ7kFek.js"></script>
8
- <link rel="modulepreload" crossorigin href="./assets/main-DwbXrrYn.js">
7
+ <script type="module" crossorigin src="./assets/demo-D6cTmzn6.js"></script>
8
+ <link rel="modulepreload" crossorigin href="./assets/main-Y-MYUSJ4.js">
9
9
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-P2Xu9kJm.js">
10
10
  <link rel="stylesheet" href="./css/storymap.css" />
11
11
  </head>
@@ -151,7 +151,7 @@ are rendered wider with a visible track for contrast.</li>
151
151
  </tr>
152
152
  <tr>
153
153
  <td><code>font_css: &quot;stock:&lt;name&gt;&quot;</code> (or a path)</td>
154
- <td>unchanged, plus the font files ship via <code>@fontsource-utils/scss</code>; no separate font CSS link needed</td>
154
+ <td>paths now resolve against the page URL (not the library location), plus the font files ship via <code>@fontsource-utils/scss</code>; no separate font CSS link needed</td>
155
155
  </tr>
156
156
  </tbody></table>
157
157
  <h2>Removed globals and exports</h2>
@@ -16,6 +16,64 @@
16
16
  padding: 0;
17
17
  margin: 0;
18
18
  }
19
+ #storymap-embed {
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+ .storymap-url-prompt {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ width: 100%;
28
+ height: 100%;
29
+ padding: 20px;
30
+ box-sizing: border-box;
31
+ background-color: #fff;
32
+ color: #333;
33
+ font-family: sans-serif;
34
+ }
35
+ .storymap-url-card {
36
+ width: 100%;
37
+ max-width: 480px;
38
+ text-align: left;
39
+ }
40
+ .storymap-url-card h1 {
41
+ font-size: 1.25rem;
42
+ margin: 0 0 8px;
43
+ }
44
+ .storymap-url-card p {
45
+ margin: 0 0 12px;
46
+ }
47
+ .storymap-url-card label {
48
+ display: block;
49
+ margin-bottom: 6px;
50
+ font-weight: bold;
51
+ }
52
+ .storymap-url-row {
53
+ display: flex;
54
+ gap: 8px;
55
+ }
56
+ .storymap-url-card input {
57
+ flex: 1;
58
+ min-width: 0;
59
+ padding: 8px 10px;
60
+ font-size: 1rem;
61
+ border: 1px solid #999;
62
+ border-radius: 4px;
63
+ }
64
+ .storymap-url-card button {
65
+ padding: 8px 16px;
66
+ font-size: 1rem;
67
+ border: 1px solid #333;
68
+ border-radius: 4px;
69
+ background-color: #333;
70
+ color: #fff;
71
+ cursor: pointer;
72
+ }
73
+ .storymap-url-error {
74
+ margin-top: 8px;
75
+ color: #a00;
76
+ }
19
77
  </style>
20
78
  </head>
21
79
 
@@ -39,6 +97,12 @@
39
97
  const getStartSlide = () =>
40
98
  urlParams.has("start_at_slide") ? parseInt(urlParams.get("start_at_slide"), 10) : 0;
41
99
 
100
+ // slide duration in milliseconds; missing or invalid values disable autoplay
101
+ const getAutoplay = () => {
102
+ const value = parseInt(urlParams.get("autoplay"), 10);
103
+ return Number.isFinite(value) && value > 0 ? value : 0;
104
+ };
105
+
42
106
  const onStoryMapTitle = (e) => {
43
107
  document.title = "StoryMapJS: " + e.title;
44
108
  };
@@ -47,7 +111,7 @@
47
111
  if (!data || !data.storymap) {
48
112
  return;
49
113
  }
50
- const options = { start_at_slide: getStartSlide() };
114
+ const options = { start_at_slide: getStartSlide(), autoplay: getAutoplay() };
51
115
  // font theme loading is handled by the library (data.font_css / stock:default)
52
116
  storymap = new StoryMap("storymap-embed", data, options, {
53
117
  title: onStoryMapTitle,
@@ -71,10 +135,71 @@
71
135
  document.getElementById("storymap-embed").append(el);
72
136
  };
73
137
 
138
+ const showUrlPrompt = (message) => {
139
+ const container = document.getElementById("storymap-embed");
140
+ container.innerHTML = "";
141
+ const el = document.createElement("div");
142
+ el.className = "storymap-url-prompt";
143
+ const card = document.createElement("div");
144
+ card.className = "storymap-url-card";
145
+ const heading = document.createElement("h1");
146
+ heading.textContent = "Open a StoryMap";
147
+ const hint = document.createElement("p");
148
+ hint.textContent =
149
+ message || "Enter the URL of a storymap.json file to view it here.";
150
+ const form = document.createElement("form");
151
+ form.id = "storymap-url-form";
152
+ const label = document.createElement("label");
153
+ label.setAttribute("for", "storymap-url-input");
154
+ label.textContent = "Storymap JSON URL";
155
+ const row = document.createElement("div");
156
+ row.className = "storymap-url-row";
157
+ const input = document.createElement("input");
158
+ input.id = "storymap-url-input";
159
+ input.name = "url";
160
+ // type="text" (not "url") so relative storymap paths like
161
+ // "examples/katrina.json" pass native form validation; validity is
162
+ // checked via new URL(value, siteRoot) on submit instead.
163
+ input.type = "text";
164
+ input.inputMode = "url";
165
+ input.required = true;
166
+ input.placeholder = "https://example.com/storymap.json";
167
+ input.autocomplete = "off";
168
+ input.spellcheck = false;
169
+ const button = document.createElement("button");
170
+ button.type = "submit";
171
+ button.textContent = "Open storymap";
172
+ const error = document.createElement("p");
173
+ error.id = "storymap-url-error";
174
+ error.className = "storymap-url-error";
175
+ error.hidden = true;
176
+ row.append(input, button);
177
+ form.append(label, row, error);
178
+ card.append(heading, hint, form);
179
+ el.append(card);
180
+ container.append(el);
181
+ form.addEventListener("submit", (e) => {
182
+ e.preventDefault();
183
+ const value = input.value.trim();
184
+ if (!value) {
185
+ return;
186
+ }
187
+ try {
188
+ // validate + resolve like the viewer fetch below (supports
189
+ // relative, root-relative and absolute URLs)
190
+ new URL(value, siteRoot);
191
+ } catch {
192
+ error.textContent = "Please enter a valid URL to a storymap.json file.";
193
+ error.hidden = false;
194
+ return;
195
+ }
196
+ urlParams.set("url", value);
197
+ window.location.search = urlParams.toString();
198
+ });
199
+ };
200
+
74
201
  if (!urlParam) {
75
- showEmbedError(
76
- "No storymap url given. Append ?url=<storymap.json> to the embed url.",
77
- );
202
+ showUrlPrompt();
78
203
  } else {
79
204
  fetch(new URL(urlParam, siteRoot).href)
80
205
  .then((response) => {
package/dist/harness.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="utf-8" />
5
5
  <title>StoryMapJS Example Harness</title>
6
6
  <style>*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0;padding:0}#storymap-embed{width:100%;height:100%}</style>
7
- <script type="module" crossorigin src="./assets/harness-C-VZV-ou.js"></script>
8
- <link rel="modulepreload" crossorigin href="./assets/main-DwbXrrYn.js">
7
+ <script type="module" crossorigin src="./assets/harness-BPFlzutp.js"></script>
8
+ <link rel="modulepreload" crossorigin href="./assets/main-Y-MYUSJ4.js">
9
9
  <link rel="modulepreload" crossorigin href="./assets/modulepreload-polyfill-P2Xu9kJm.js">
10
10
  <link rel="stylesheet" href="./css/storymap.css" />
11
11
  </head>
package/dist/index.html CHANGED
@@ -259,6 +259,23 @@ new StoryMap("mapdiv", "my-storymap.json");</code></pre>
259
259
  </p>
260
260
  </div>
261
261
  </li>
262
+ <li>
263
+ <input type="checkbox" checked />
264
+ <i></i>
265
+ <h3>Can the storymap play automatically?</h3>
266
+ <div class="accordion-content">
267
+ <p>
268
+ Set the <code>autoplay</code> option to the number of
269
+ milliseconds each slide stays on screen (also available as
270
+ an embed URL parameter):
271
+ </p>
272
+ <pre><code>/embed/index.html?url=my-storymap.json&amp;autoplay=5000</code></pre>
273
+ <p>
274
+ Playback stops at the last slide, and any click, tap or
275
+ keypress hands control back to the viewer.
276
+ </p>
277
+ </div>
278
+ </li>
262
279
  <li>
263
280
  <input type="checkbox" checked />
264
281
  <i></i>
@@ -3,6 +3,7 @@ import { default as default_3 } from 'ol/Map';
3
3
  import { default as default_4 } from 'ol/Overlay';
4
4
  import { default as default_5 } from 'ol/tilegrid/TileGrid';
5
5
  import { default as default_6 } from 'ol/proj/Projection';
6
+ import { Extent } from 'ol/extent';
6
7
  import { Map as Map_3 } from 'ol';
7
8
  import { Style } from 'ol/style';
8
9
  import { Tile } from 'ol/layer';
@@ -409,6 +410,7 @@ declare class MenuBarBase {
409
410
  "options": MenuBarOptions;
410
411
  "animator": Record<string, unknown>;
411
412
  "fire": EventedInstance["fire"];
413
+ _fullscreenActive: boolean;
412
414
  constructor(elem: HTMLElement | string, parent_elem?: HTMLElement, options?: object);
413
415
  show(d?: number): void;
414
416
  hide(top: number): void;
@@ -418,6 +420,11 @@ declare class MenuBarBase {
418
420
  * Reflect the fullscreen state in the button label/icon.
419
421
  */
420
422
  setFullscreenState(active: boolean): void;
423
+ /**
424
+ * Repaint every text label from the active language (see `setLanguage`).
425
+ * Icon-only mobile buttons carry no text and are left untouched.
426
+ */
427
+ refreshLabels(): void;
421
428
  /**
422
429
  * Update the progress indicator (issue #247); no-op when disabled.
423
430
  */
@@ -509,9 +516,24 @@ declare class OpenLayers extends Map_2 {
509
516
  "_tile_layer_mini": Tile | null;
510
517
  "_mini_map": default_2;
511
518
  "_markers": OpenLayersMapMarker[];
519
+ /** App-level stacked overlays (see the `overlays` option) */
520
+ "_overlay_layers": Tile[];
512
521
  /** rAF handle of the running active-line draw animation */
513
522
  "_line_animation": number | null;
514
523
  _createMap(): void;
524
+ /** Extra attribution fragments (e.g. overlay credits), always listed last. */
525
+ "_extra_attributions": string[];
526
+ /**
527
+ * Append extra attribution fragments and refresh the line. Hosts with
528
+ * custom layers use this instead of rewriting `.vco-map-attribution`.
529
+ */
530
+ setExtraAttributions(parts: string[]): void;
531
+ /**
532
+ * (Re)render the attribution line for the current map type. Called at
533
+ * creation and on every `map_type` switch, which previously left the
534
+ * initial text stale.
535
+ */
536
+ _updateAttribution(): void;
515
537
  _getAttribution(map_type: string): string;
516
538
  /**
517
539
  * Create the tile layer and register its load handler. Deferred until
@@ -522,6 +544,37 @@ declare class OpenLayers extends Map_2 {
522
544
  * Ask for tile consent, then attach the layers if allowed.
523
545
  */
524
546
  _requestTileConsent(consent: ConsentManager, tile_service: string): Promise<void>;
547
+ /**
548
+ * (Re)build the stacked raster overlays from the `overlays` option.
549
+ * Overlays sit above the base tiles (z 1..n) and below the route lines
550
+ * (z 10/11); every entry accepts any `map_type` value plus declarative
551
+ * presentation, so hosts no longer capture and patch layer objects.
552
+ */
553
+ _buildOverlays(): void;
554
+ /**
555
+ * Convert a lon/lat clip box to view units. Only meaningful on
556
+ * mercator maps; image-space maps (iiif/zoomify) and malformed
557
+ * boxes yield null (no constraint).
558
+ */
559
+ _lonLatBboxToExtent(bbox: [number, number, number, number]): Extent | null;
560
+ /**
561
+ * Apply an overlay's blend mode to its layer container. The container
562
+ * div only exists once the layer has rendered, so retry on later
563
+ * frames (bounded: rendering settles within a frame or two of any
564
+ * add/visibility change).
565
+ */
566
+ _paintOverlayBlend(entry: {
567
+ className?: string;
568
+ blendMode?: string;
569
+ }, retries?: number): void;
570
+ /** Refresh the attribution line with the visible overlays' credits. */
571
+ _syncOverlayAttributions(): void;
572
+ /** Number of stacked overlay layers (see the `overlays` option). */
573
+ getOverlayCount(): number;
574
+ /** Show or hide a stacked overlay by index (re-syncs attribution). */
575
+ setOverlayVisible(index: number, visible: boolean): void;
576
+ /** Set a stacked overlay's opacity by index. */
577
+ setOverlayOpacity(index: number, opacity: number): void;
525
578
  /**
526
579
  * Map tiles were allowed: attach the main tile layer, create the
527
580
  * minimap's deferred layer if it was withheld, then re-fit.
@@ -921,6 +974,7 @@ declare class StoryMapBase {
921
974
  "animator_map": AnimationHandle | null;
922
975
  "animator_storyslider": AnimationHandle | null;
923
976
  "_autoplay_timer": ReturnType<typeof setTimeout> | null;
977
+ "_transition_timer": ReturnType<typeof setTimeout> | null;
924
978
  "_autoplay_stopped": boolean;
925
979
  "_hash_initialized": boolean;
926
980
  /** the data source was a IIIF Presentation manifest (legacy zoomify options are ignored) */
@@ -946,6 +1000,7 @@ declare class StoryMapBase {
946
1000
  _loadDataFromUrl(url: string, source: string): Promise<void>;
947
1001
  _initOptions(): void;
948
1002
  _loadLanguage(): void;
1003
+ refreshLanguage(code: string): void;
949
1004
  _loadFontCss(): Promise<void>;
950
1005
  _onFontLoaded(font: string): void;
951
1006
  /**
@@ -955,6 +1010,13 @@ declare class StoryMapBase {
955
1010
  * marker (or the overview when `n` is 0 for storymaps with one).
956
1011
  */
957
1012
  goTo(n: number): void;
1013
+ /**
1014
+ * Announce a slide transition: `transitionstart` now (with the glide
1015
+ * duration both animations were started with) and `transitionend` once
1016
+ * it elapses. Restarts on every navigation, so only the latest
1017
+ * transition ever ends.
1018
+ */
1019
+ _beginTransition(duration: number): void;
958
1020
  /**
959
1021
  * Re-measure the container and re-layout the map, slider and menubar.
960
1022
  * Called automatically on resize (see the `trackResize` option).
@@ -964,21 +1026,31 @@ declare class StoryMapBase {
964
1026
  * Change a single map option at runtime and apply its effect immediately.
965
1027
  *
966
1028
  * Runtime-changeable options: `map_type` (rebuilds the main + minimap tile
967
- * layers, keeping the overview fitted to the marker bounds),
968
- * `show_lines`, `line_color`, `line_color_inactive`, `line_weight`,
969
- * `line_opacity`, `line_dash`, `line_join`, `line_follows_path`,
970
- * `show_history_line` (restyled instantly), `map_center_offset` (applied on
971
- * the next navigation), `duration`, `ease`, `calculate_zoom`,
972
- * `map_background_color`. All other options only take effect on the next
973
- * navigation or require re-creating the StoryMap.
1029
+ * layers, keeping the overview fitted to the marker bounds), `overlays`
1030
+ * (rebuilds the stacked overlay layers), `show_lines`, `line_color`,
1031
+ * `line_color_inactive`, `line_weight`, `line_opacity`, `line_dash`,
1032
+ * `line_join`, `line_follows_path`, `show_history_line` (restyled
1033
+ * instantly), `map_center_offset` (applied on the next navigation),
1034
+ * `duration`, `ease`, `calculate_zoom`, `map_background_color`. All other
1035
+ * options only take effect on the next navigation or require re-creating
1036
+ * the StoryMap.
974
1037
  */
975
1038
  setMapOption(name: string, value: unknown): void;
1039
+ /**
1040
+ * Show or hide a stacked overlay by index (see the `overlays` option).
1041
+ */
1042
+ setOverlayVisible(index: number, visible: boolean): void;
1043
+ /**
1044
+ * Set a stacked overlay's opacity by index (see the `overlays` option).
1045
+ */
1046
+ setOverlayOpacity(index: number, opacity: number): void;
976
1047
  /**
977
1048
  * Change several map options at runtime (see setMapOption).
978
1049
  */
979
1050
  setMapOptions(options: Partial<StorymapOptions>): void;
980
1051
  _initLayout(): void;
981
1052
  _initEvents(): void;
1053
+ _onKeyDownGlobal(e: KeyboardEvent): void;
982
1054
  _updateDisplay(map_height?: number, animate?: boolean, d?: number): void;
983
1055
  _onDataLoaded(e?: unknown): void;
984
1056
  _startAutoplay(): void;
@@ -1091,6 +1163,12 @@ export declare interface StorymapOptions {
1091
1163
  ease: unknown;
1092
1164
  dragging: boolean;
1093
1165
  trackResize: boolean;
1166
+ /**
1167
+ * Navigate slides with arrow keys anywhere on the page (default false:
1168
+ * arrows only work when the slide panel has focus). Form elements and
1169
+ * the map itself (which pans) are always skipped. Read at construction.
1170
+ */
1171
+ keyboard: boolean;
1094
1172
  /** Re-fetch the source file on every load, bypassing caches (issue #417) */
1095
1173
  nocache: boolean;
1096
1174
  /** Advance slides automatically every N milliseconds; 0 disables (issue #380) */
@@ -1108,6 +1186,13 @@ export declare interface StorymapOptions {
1108
1186
  } | null;
1109
1187
  map_type: string;
1110
1188
  attribution: string;
1189
+ /**
1190
+ * Stacked raster overlays above the base map, below the route lines.
1191
+ * Each entry accepts any `map_type` value (XYZ template, `osm:style`,
1192
+ * …) plus per-layer presentation; see StorymapOverlayLayer. Empty
1193
+ * (default) means base map only.
1194
+ */
1195
+ overlays: StorymapOverlayLayer[];
1111
1196
  map_mini: boolean;
1112
1197
  map_subdomains: string;
1113
1198
  map_as_image: boolean;
@@ -1127,6 +1212,12 @@ export declare interface StorymapOptions {
1127
1212
  * constrained to the box; `null` (default) leaves the map unconstrained.
1128
1213
  */
1129
1214
  map_bbox: number[] | null;
1215
+ /**
1216
+ * Constrain the minimap overview to a bounding box `[west, south, east,
1217
+ * north]` in lon/lat (mercator maps only); `null` (default) leaves the
1218
+ * overview unconstrained.
1219
+ */
1220
+ overview_extent: [number, number, number, number] | null;
1130
1221
  /**
1131
1222
  * Legacy zoomify image pyramid (map_type: "zoomify"): the tiles are
1132
1223
  * placed at the standard mercator tile positions, stretched from the
@@ -1188,6 +1279,34 @@ export declare interface StorymapOptions {
1188
1279
  [key: string]: unknown;
1189
1280
  }
1190
1281
 
1282
+ /**
1283
+ * A stacked raster overlay above the base map (StorymapOptions.overlays).
1284
+ * Presentation is declarative: hosts no longer need to reach into the
1285
+ * layer objects for blend modes, clips or stacking tweaks.
1286
+ */
1287
+ declare interface StorymapOverlayLayer {
1288
+ /** Any `map_type` value the tile layer factory accepts */
1289
+ map_type: string;
1290
+ /** Layer opacity 0..1 (default 1) */
1291
+ opacity?: number;
1292
+ /** Initial visibility (default true) */
1293
+ visible?: boolean;
1294
+ /** Extra attribution fragment, listed while the overlay is visible */
1295
+ attribution?: string;
1296
+ /**
1297
+ * CSS class for the layer container. OpenLayers paints every layer
1298
+ * with the same class into one shared div/canvas, so a distinct
1299
+ * class isolates this layer (e.g. for blend modes). The class
1300
+ * replaces the default wholesale, so keep the `ol-layer` token
1301
+ * (e.g. `"ol-layer historic-sheet"`) unless you know why not.
1302
+ */
1303
+ className?: string;
1304
+ /** CSS mix-blend-mode for the layer container (needs className) */
1305
+ blendMode?: string;
1306
+ /** Clip box `[west, south, east, north]` in lon/lat (mercator maps) */
1307
+ extent?: [number, number, number, number];
1308
+ }
1309
+
1191
1310
  export declare interface StorymapSlide {
1192
1311
  type?: string;
1193
1312
  date?: string | Record<string, unknown> | null;