@projektemacher/storymapjs 0.10.7 → 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.
Files changed (587) hide show
  1. package/CHANGELOG +431 -19
  2. package/README.md +168 -17
  3. package/dist/assets/demo-bWnOyfUw.js +1 -0
  4. package/dist/assets/harness-C3JUv5Ii.js +1 -0
  5. package/dist/assets/harness-multi-XZNex3tb.js +1 -0
  6. package/dist/assets/harness-support-CjfZIVeb.js +1 -0
  7. package/dist/assets/index-wHPqGrBS.js +1 -0
  8. package/dist/assets/main-DQ32hWBM.js +17 -0
  9. package/dist/context.json +23 -9
  10. package/dist/css/fonts/files/amatic-sc-cyrillic-400-normal.woff2 +0 -0
  11. package/dist/css/fonts/files/amatic-sc-cyrillic-700-normal.woff2 +0 -0
  12. package/dist/css/fonts/files/amatic-sc-hebrew-400-normal.woff2 +0 -0
  13. package/dist/css/fonts/files/amatic-sc-hebrew-700-normal.woff2 +0 -0
  14. package/dist/css/fonts/files/amatic-sc-vietnamese-400-normal.woff2 +0 -0
  15. package/dist/css/fonts/files/amatic-sc-vietnamese-700-normal.woff2 +0 -0
  16. package/dist/css/fonts/files/bitter-cyrillic-100-italic.woff2 +0 -0
  17. package/dist/css/fonts/files/bitter-cyrillic-100-normal.woff2 +0 -0
  18. package/dist/css/fonts/files/bitter-cyrillic-200-italic.woff2 +0 -0
  19. package/dist/css/fonts/files/bitter-cyrillic-200-normal.woff2 +0 -0
  20. package/dist/css/fonts/files/bitter-cyrillic-300-italic.woff2 +0 -0
  21. package/dist/css/fonts/files/bitter-cyrillic-300-normal.woff2 +0 -0
  22. package/dist/css/fonts/files/bitter-cyrillic-400-italic.woff2 +0 -0
  23. package/dist/css/fonts/files/bitter-cyrillic-400-normal.woff2 +0 -0
  24. package/dist/css/fonts/files/bitter-cyrillic-500-italic.woff2 +0 -0
  25. package/dist/css/fonts/files/bitter-cyrillic-500-normal.woff2 +0 -0
  26. package/dist/css/fonts/files/bitter-cyrillic-600-italic.woff2 +0 -0
  27. package/dist/css/fonts/files/bitter-cyrillic-600-normal.woff2 +0 -0
  28. package/dist/css/fonts/files/bitter-cyrillic-700-italic.woff2 +0 -0
  29. package/dist/css/fonts/files/bitter-cyrillic-700-normal.woff2 +0 -0
  30. package/dist/css/fonts/files/bitter-cyrillic-800-italic.woff2 +0 -0
  31. package/dist/css/fonts/files/bitter-cyrillic-800-normal.woff2 +0 -0
  32. package/dist/css/fonts/files/bitter-cyrillic-900-italic.woff2 +0 -0
  33. package/dist/css/fonts/files/bitter-cyrillic-900-normal.woff2 +0 -0
  34. package/dist/css/fonts/files/bitter-cyrillic-ext-100-italic.woff2 +0 -0
  35. package/dist/css/fonts/files/bitter-cyrillic-ext-100-normal.woff2 +0 -0
  36. package/dist/css/fonts/files/bitter-cyrillic-ext-200-italic.woff2 +0 -0
  37. package/dist/css/fonts/files/bitter-cyrillic-ext-200-normal.woff2 +0 -0
  38. package/dist/css/fonts/files/bitter-cyrillic-ext-300-italic.woff2 +0 -0
  39. package/dist/css/fonts/files/bitter-cyrillic-ext-300-normal.woff2 +0 -0
  40. package/dist/css/fonts/files/bitter-cyrillic-ext-400-italic.woff2 +0 -0
  41. package/dist/css/fonts/files/bitter-cyrillic-ext-400-normal.woff2 +0 -0
  42. package/dist/css/fonts/files/bitter-cyrillic-ext-500-italic.woff2 +0 -0
  43. package/dist/css/fonts/files/bitter-cyrillic-ext-500-normal.woff2 +0 -0
  44. package/dist/css/fonts/files/bitter-cyrillic-ext-600-italic.woff2 +0 -0
  45. package/dist/css/fonts/files/bitter-cyrillic-ext-600-normal.woff2 +0 -0
  46. package/dist/css/fonts/files/bitter-cyrillic-ext-700-italic.woff2 +0 -0
  47. package/dist/css/fonts/files/bitter-cyrillic-ext-700-normal.woff2 +0 -0
  48. package/dist/css/fonts/files/bitter-cyrillic-ext-800-italic.woff2 +0 -0
  49. package/dist/css/fonts/files/bitter-cyrillic-ext-800-normal.woff2 +0 -0
  50. package/dist/css/fonts/files/bitter-cyrillic-ext-900-italic.woff2 +0 -0
  51. package/dist/css/fonts/files/bitter-cyrillic-ext-900-normal.woff2 +0 -0
  52. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-italic.woff2 +0 -0
  53. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-normal.woff2 +0 -0
  54. package/dist/css/fonts/files/bitter-cyrillic-wght-italic.woff2 +0 -0
  55. package/dist/css/fonts/files/bitter-cyrillic-wght-normal.woff2 +0 -0
  56. package/dist/css/fonts/files/bitter-vietnamese-100-italic.woff2 +0 -0
  57. package/dist/css/fonts/files/bitter-vietnamese-100-normal.woff2 +0 -0
  58. package/dist/css/fonts/files/bitter-vietnamese-200-italic.woff2 +0 -0
  59. package/dist/css/fonts/files/bitter-vietnamese-200-normal.woff2 +0 -0
  60. package/dist/css/fonts/files/bitter-vietnamese-300-italic.woff2 +0 -0
  61. package/dist/css/fonts/files/bitter-vietnamese-300-normal.woff2 +0 -0
  62. package/dist/css/fonts/files/bitter-vietnamese-400-italic.woff2 +0 -0
  63. package/dist/css/fonts/files/bitter-vietnamese-400-normal.woff2 +0 -0
  64. package/dist/css/fonts/files/bitter-vietnamese-500-italic.woff2 +0 -0
  65. package/dist/css/fonts/files/bitter-vietnamese-500-normal.woff2 +0 -0
  66. package/dist/css/fonts/files/bitter-vietnamese-600-italic.woff2 +0 -0
  67. package/dist/css/fonts/files/bitter-vietnamese-600-normal.woff2 +0 -0
  68. package/dist/css/fonts/files/bitter-vietnamese-700-italic.woff2 +0 -0
  69. package/dist/css/fonts/files/bitter-vietnamese-700-normal.woff2 +0 -0
  70. package/dist/css/fonts/files/bitter-vietnamese-800-italic.woff2 +0 -0
  71. package/dist/css/fonts/files/bitter-vietnamese-800-normal.woff2 +0 -0
  72. package/dist/css/fonts/files/bitter-vietnamese-900-italic.woff2 +0 -0
  73. package/dist/css/fonts/files/bitter-vietnamese-900-normal.woff2 +0 -0
  74. package/dist/css/fonts/files/bitter-vietnamese-wght-italic.woff2 +0 -0
  75. package/dist/css/fonts/files/bitter-vietnamese-wght-normal.woff2 +0 -0
  76. package/dist/css/fonts/files/cairo-arabic-200-normal.woff2 +0 -0
  77. package/dist/css/fonts/files/cairo-arabic-300-normal.woff2 +0 -0
  78. package/dist/css/fonts/files/cairo-arabic-400-normal.woff2 +0 -0
  79. package/dist/css/fonts/files/cairo-arabic-500-normal.woff2 +0 -0
  80. package/dist/css/fonts/files/cairo-arabic-600-normal.woff2 +0 -0
  81. package/dist/css/fonts/files/cairo-arabic-700-normal.woff2 +0 -0
  82. package/dist/css/fonts/files/cairo-arabic-800-normal.woff2 +0 -0
  83. package/dist/css/fonts/files/cairo-arabic-900-normal.woff2 +0 -0
  84. package/dist/css/fonts/files/cairo-latin-200-normal.woff2 +0 -0
  85. package/dist/css/fonts/files/cairo-latin-300-normal.woff2 +0 -0
  86. package/dist/css/fonts/files/cairo-latin-400-normal.woff2 +0 -0
  87. package/dist/css/fonts/files/cairo-latin-500-normal.woff2 +0 -0
  88. package/dist/css/fonts/files/cairo-latin-600-normal.woff2 +0 -0
  89. package/dist/css/fonts/files/cairo-latin-700-normal.woff2 +0 -0
  90. package/dist/css/fonts/files/cairo-latin-800-normal.woff2 +0 -0
  91. package/dist/css/fonts/files/cairo-latin-900-normal.woff2 +0 -0
  92. package/dist/css/fonts/files/cairo-latin-ext-200-normal.woff2 +0 -0
  93. package/dist/css/fonts/files/cairo-latin-ext-300-normal.woff2 +0 -0
  94. package/dist/css/fonts/files/cairo-latin-ext-400-normal.woff2 +0 -0
  95. package/dist/css/fonts/files/cairo-latin-ext-500-normal.woff2 +0 -0
  96. package/dist/css/fonts/files/cairo-latin-ext-600-normal.woff2 +0 -0
  97. package/dist/css/fonts/files/cairo-latin-ext-700-normal.woff2 +0 -0
  98. package/dist/css/fonts/files/cairo-latin-ext-800-normal.woff2 +0 -0
  99. package/dist/css/fonts/files/cairo-latin-ext-900-normal.woff2 +0 -0
  100. package/dist/css/fonts/files/dancing-script-vietnamese-wght-normal.woff2 +0 -0
  101. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-italic.woff2 +0 -0
  102. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-normal.woff2 +0 -0
  103. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-italic.woff2 +0 -0
  104. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-normal.woff2 +0 -0
  105. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-italic.woff2 +0 -0
  106. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-normal.woff2 +0 -0
  107. package/dist/css/fonts/files/eb-garamond-greek-wght-italic.woff2 +0 -0
  108. package/dist/css/fonts/files/eb-garamond-greek-wght-normal.woff2 +0 -0
  109. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-italic.woff2 +0 -0
  110. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-normal.woff2 +0 -0
  111. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-italic.woff2 +0 -0
  112. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-normal.woff2 +0 -0
  113. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-italic.woff2 +0 -0
  114. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-normal.woff2 +0 -0
  115. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-italic.woff2 +0 -0
  116. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-normal.woff2 +0 -0
  117. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-italic.woff2 +0 -0
  118. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-normal.woff2 +0 -0
  119. package/dist/css/fonts/files/gentium-book-plus-greek-400-italic.woff2 +0 -0
  120. package/dist/css/fonts/files/gentium-book-plus-greek-400-normal.woff2 +0 -0
  121. package/dist/css/fonts/files/gentium-book-plus-greek-700-italic.woff2 +0 -0
  122. package/dist/css/fonts/files/gentium-book-plus-greek-700-normal.woff2 +0 -0
  123. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-italic.woff2 +0 -0
  124. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-normal.woff2 +0 -0
  125. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-italic.woff2 +0 -0
  126. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-normal.woff2 +0 -0
  127. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-italic.woff2 +0 -0
  128. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-normal.woff2 +0 -0
  129. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-italic.woff2 +0 -0
  130. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-normal.woff2 +0 -0
  131. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-italic.woff2 +0 -0
  132. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-normal.woff2 +0 -0
  133. package/dist/css/fonts/files/old-standard-tt-cyrillic-700-normal.woff2 +0 -0
  134. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-italic.woff2 +0 -0
  135. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-normal.woff2 +0 -0
  136. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-700-normal.woff2 +0 -0
  137. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-italic.woff2 +0 -0
  138. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-normal.woff2 +0 -0
  139. package/dist/css/fonts/files/old-standard-tt-vietnamese-700-normal.woff2 +0 -0
  140. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-italic.woff2 +0 -0
  141. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-normal.woff2 +0 -0
  142. package/dist/css/fonts/files/open-sans-cyrillic-wght-italic.woff2 +0 -0
  143. package/dist/css/fonts/files/open-sans-cyrillic-wght-normal.woff2 +0 -0
  144. package/dist/css/fonts/files/open-sans-greek-ext-wght-italic.woff2 +0 -0
  145. package/dist/css/fonts/files/open-sans-greek-ext-wght-normal.woff2 +0 -0
  146. package/dist/css/fonts/files/open-sans-greek-wght-italic.woff2 +0 -0
  147. package/dist/css/fonts/files/open-sans-greek-wght-normal.woff2 +0 -0
  148. package/dist/css/fonts/files/open-sans-hebrew-wght-italic.woff2 +0 -0
  149. package/dist/css/fonts/files/open-sans-hebrew-wght-normal.woff2 +0 -0
  150. package/dist/css/fonts/files/open-sans-vietnamese-wght-italic.woff2 +0 -0
  151. package/dist/css/fonts/files/open-sans-vietnamese-wght-normal.woff2 +0 -0
  152. package/dist/css/fonts/files/playfair-display-cyrillic-wght-italic.woff2 +0 -0
  153. package/dist/css/fonts/files/playfair-display-cyrillic-wght-normal.woff2 +0 -0
  154. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-italic.woff2 +0 -0
  155. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-normal.woff2 +0 -0
  156. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-italic.woff2 +0 -0
  157. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-normal.woff2 +0 -0
  158. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-italic.woff2 +0 -0
  159. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-normal.woff2 +0 -0
  160. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-italic.woff2 +0 -0
  161. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-normal.woff2 +0 -0
  162. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-italic.woff2 +0 -0
  163. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-normal.woff2 +0 -0
  164. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-italic.woff2 +0 -0
  165. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-normal.woff2 +0 -0
  166. package/dist/css/fonts/files/playfair-display-vietnamese-wght-italic.woff2 +0 -0
  167. package/dist/css/fonts/files/playfair-display-vietnamese-wght-normal.woff2 +0 -0
  168. package/dist/css/fonts/files/pt-sans-cyrillic-400-italic.woff2 +0 -0
  169. package/dist/css/fonts/files/pt-sans-cyrillic-400-normal.woff2 +0 -0
  170. package/dist/css/fonts/files/pt-sans-cyrillic-700-italic.woff2 +0 -0
  171. package/dist/css/fonts/files/pt-sans-cyrillic-700-normal.woff2 +0 -0
  172. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-italic.woff2 +0 -0
  173. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-normal.woff2 +0 -0
  174. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-italic.woff2 +0 -0
  175. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-normal.woff2 +0 -0
  176. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-400-normal.woff2 +0 -0
  177. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-700-normal.woff2 +0 -0
  178. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-400-normal.woff2 +0 -0
  179. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-700-normal.woff2 +0 -0
  180. package/dist/css/fonts/files/pt-serif-cyrillic-400-italic.woff2 +0 -0
  181. package/dist/css/fonts/files/pt-serif-cyrillic-400-normal.woff2 +0 -0
  182. package/dist/css/fonts/files/pt-serif-cyrillic-700-italic.woff2 +0 -0
  183. package/dist/css/fonts/files/pt-serif-cyrillic-700-normal.woff2 +0 -0
  184. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-italic.woff2 +0 -0
  185. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-normal.woff2 +0 -0
  186. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-italic.woff2 +0 -0
  187. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-normal.woff2 +0 -0
  188. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-italic.woff2 +0 -0
  189. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-normal.woff2 +0 -0
  190. package/dist/css/fonts/files/raleway-cyrillic-wght-italic.woff2 +0 -0
  191. package/dist/css/fonts/files/raleway-cyrillic-wght-normal.woff2 +0 -0
  192. package/dist/css/fonts/files/raleway-vietnamese-wght-italic.woff2 +0 -0
  193. package/dist/css/fonts/files/raleway-vietnamese-wght-normal.woff2 +0 -0
  194. package/dist/css/fonts/files/roboto-slab-cyrillic-ext-wght-normal.woff2 +0 -0
  195. package/dist/css/fonts/files/roboto-slab-cyrillic-wght-normal.woff2 +0 -0
  196. package/dist/css/fonts/files/roboto-slab-greek-ext-wght-normal.woff2 +0 -0
  197. package/dist/css/fonts/files/roboto-slab-greek-wght-normal.woff2 +0 -0
  198. package/dist/css/fonts/files/roboto-slab-vietnamese-wght-normal.woff2 +0 -0
  199. package/dist/css/fonts/files/ubuntu-cyrillic-300-italic.woff2 +0 -0
  200. package/dist/css/fonts/files/ubuntu-cyrillic-300-normal.woff2 +0 -0
  201. package/dist/css/fonts/files/ubuntu-cyrillic-400-italic.woff2 +0 -0
  202. package/dist/css/fonts/files/ubuntu-cyrillic-400-normal.woff2 +0 -0
  203. package/dist/css/fonts/files/ubuntu-cyrillic-500-italic.woff2 +0 -0
  204. package/dist/css/fonts/files/ubuntu-cyrillic-500-normal.woff2 +0 -0
  205. package/dist/css/fonts/files/ubuntu-cyrillic-700-italic.woff2 +0 -0
  206. package/dist/css/fonts/files/ubuntu-cyrillic-700-normal.woff2 +0 -0
  207. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-italic.woff2 +0 -0
  208. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-normal.woff2 +0 -0
  209. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-italic.woff2 +0 -0
  210. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-normal.woff2 +0 -0
  211. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-italic.woff2 +0 -0
  212. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-normal.woff2 +0 -0
  213. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-italic.woff2 +0 -0
  214. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-normal.woff2 +0 -0
  215. package/dist/css/fonts/files/ubuntu-greek-300-italic.woff2 +0 -0
  216. package/dist/css/fonts/files/ubuntu-greek-300-normal.woff2 +0 -0
  217. package/dist/css/fonts/files/ubuntu-greek-400-italic.woff2 +0 -0
  218. package/dist/css/fonts/files/ubuntu-greek-400-normal.woff2 +0 -0
  219. package/dist/css/fonts/files/ubuntu-greek-500-italic.woff2 +0 -0
  220. package/dist/css/fonts/files/ubuntu-greek-500-normal.woff2 +0 -0
  221. package/dist/css/fonts/files/ubuntu-greek-700-italic.woff2 +0 -0
  222. package/dist/css/fonts/files/ubuntu-greek-700-normal.woff2 +0 -0
  223. package/dist/css/fonts/files/ubuntu-greek-ext-300-italic.woff2 +0 -0
  224. package/dist/css/fonts/files/ubuntu-greek-ext-300-normal.woff2 +0 -0
  225. package/dist/css/fonts/files/ubuntu-greek-ext-400-italic.woff2 +0 -0
  226. package/dist/css/fonts/files/ubuntu-greek-ext-400-normal.woff2 +0 -0
  227. package/dist/css/fonts/files/ubuntu-greek-ext-500-italic.woff2 +0 -0
  228. package/dist/css/fonts/files/ubuntu-greek-ext-500-normal.woff2 +0 -0
  229. package/dist/css/fonts/files/ubuntu-greek-ext-700-italic.woff2 +0 -0
  230. package/dist/css/fonts/files/ubuntu-greek-ext-700-normal.woff2 +0 -0
  231. package/dist/css/fonts/files/unica-one-vietnamese-400-normal.woff2 +0 -0
  232. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-italic.woff2 +0 -0
  233. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-normal.woff2 +0 -0
  234. package/dist/css/fonts/files/vollkorn-cyrillic-wght-italic.woff2 +0 -0
  235. package/dist/css/fonts/files/vollkorn-cyrillic-wght-normal.woff2 +0 -0
  236. package/dist/css/fonts/files/vollkorn-greek-wght-italic.woff2 +0 -0
  237. package/dist/css/fonts/files/vollkorn-greek-wght-normal.woff2 +0 -0
  238. package/dist/css/fonts/files/vollkorn-vietnamese-wght-italic.woff2 +0 -0
  239. package/dist/css/fonts/files/vollkorn-vietnamese-wght-normal.woff2 +0 -0
  240. package/dist/css/fonts/font.abril-droidsans.css +3 -0
  241. package/dist/css/fonts/font.amatic-andika.css +57 -0
  242. package/dist/css/fonts/font.bitter-raleway.css +111 -0
  243. package/dist/css/fonts/font.cairo.css +312 -0
  244. package/dist/css/fonts/font.clicker-garamond.css +93 -0
  245. package/dist/css/fonts/font.dancing-ledger.css +12 -0
  246. package/dist/css/fonts/font.default.css +183 -0
  247. package/dist/css/fonts/font.fjalla-average.css +3 -0
  248. package/dist/css/fonts/font.georgia-helvetica.css +3 -0
  249. package/dist/css/fonts/font.knightlab.css +642 -0
  250. package/dist/css/fonts/font.lustria-lato.css +3 -0
  251. package/dist/css/fonts/font.medula-lato.css +3 -0
  252. package/dist/css/fonts/font.oldstandard.css +84 -0
  253. package/dist/css/fonts/font.opensans-gentiumbook.css +183 -0
  254. package/dist/css/fonts/font.playfair-faunaone.css +39 -0
  255. package/dist/css/fonts/font.playfair.css +147 -0
  256. package/dist/css/fonts/font.pt.css +183 -0
  257. package/dist/css/fonts/font.roboto-megrim.css +3 -0
  258. package/dist/css/fonts/font.rufina-sintony.css +3 -0
  259. package/dist/css/fonts/font.ubuntu.css +291 -0
  260. package/dist/css/fonts/font.unicaone-vollkorn.css +84 -0
  261. package/dist/css/storymap.css +1 -1
  262. package/dist/demo.html +3 -2
  263. package/dist/docs/api/.nojekyll +1 -0
  264. package/dist/docs/api/assets/custom.css +47 -0
  265. package/dist/docs/api/assets/hierarchy.js +1 -0
  266. package/dist/docs/api/assets/highlight.css +57 -0
  267. package/dist/docs/api/assets/icons.js +18 -0
  268. package/dist/docs/api/assets/icons.svg +1 -0
  269. package/dist/docs/api/assets/main.js +60 -0
  270. package/dist/docs/api/assets/navigation.js +1 -0
  271. package/dist/docs/api/assets/search.js +1 -0
  272. package/dist/docs/api/assets/style.css +1648 -0
  273. package/dist/docs/api/classes/StoryMap.html +2112 -0
  274. package/dist/docs/api/functions/MediaType.html +51 -0
  275. package/dist/docs/api/functions/isPresentation3Collection.html +47 -0
  276. package/dist/docs/api/functions/isPresentation3Manifest.html +53 -0
  277. package/dist/docs/api/functions/isSlideshowCollection.html +51 -0
  278. package/dist/docs/api/functions/loadCSS.html +63 -0
  279. package/dist/docs/api/functions/manifestToStorymapData.html +49 -0
  280. package/dist/docs/api/functions/setLanguage.html +54 -0
  281. package/dist/docs/api/functions/slideshowToStorymapData.html +51 -0
  282. package/dist/docs/api/functions/slideshowVersion.html +48 -0
  283. package/dist/docs/api/functions/storymapToManifest.html +57 -0
  284. package/dist/docs/api/functions/validateStorymap.html +53 -0
  285. package/dist/docs/api/functions/validateStorymapAndReport.html +54 -0
  286. package/dist/docs/api/hierarchy.html +28 -0
  287. package/dist/docs/api/index.html +300 -0
  288. package/dist/docs/api/interfaces/AnimationHandle.html +60 -0
  289. package/dist/docs/api/interfaces/ImagereadyPayload.html +71 -0
  290. package/dist/docs/api/interfaces/LanguageEntry.html +102 -0
  291. package/dist/docs/api/interfaces/LatLngLiteral.html +73 -0
  292. package/dist/docs/api/interfaces/LoadOptions.html +59 -0
  293. package/dist/docs/api/interfaces/MapEvents.html +116 -0
  294. package/dist/docs/api/interfaces/MapMarkerEvents.html +66 -0
  295. package/dist/docs/api/interfaces/MarkerEventPayload.html +57 -0
  296. package/dist/docs/api/interfaces/MediaEvents.html +78 -0
  297. package/dist/docs/api/interfaces/MenuBarEvents.html +114 -0
  298. package/dist/docs/api/interfaces/MessageEvents.html +72 -0
  299. package/dist/docs/api/interfaces/OlLayer.html +1400 -0
  300. package/dist/docs/api/interfaces/OlMap.html +1656 -0
  301. package/dist/docs/api/interfaces/OlProjection.html +332 -0
  302. package/dist/docs/api/interfaces/OlSource.html +784 -0
  303. package/dist/docs/api/interfaces/OlTileLayer.html +1497 -0
  304. package/dist/docs/api/interfaces/OlVectorLayer.html +1559 -0
  305. package/dist/docs/api/interfaces/OlView.html +1958 -0
  306. package/dist/docs/api/interfaces/SlideBackgroundState.html +66 -0
  307. package/dist/docs/api/interfaces/SlideEvents.html +78 -0
  308. package/dist/docs/api/interfaces/SlideNavEvents.html +72 -0
  309. package/dist/docs/api/interfaces/SlideshowPlayerSettings.html +182 -0
  310. package/dist/docs/api/interfaces/SlideshowToStorymapResult.html +60 -0
  311. package/dist/docs/api/interfaces/SlideshowTranslatorOptions.html +65 -0
  312. package/dist/docs/api/interfaces/SlideshowWarning.html +72 -0
  313. package/dist/docs/api/interfaces/StoryMapEvents.html +146 -0
  314. package/dist/docs/api/interfaces/StoryMapMarker.html +763 -0
  315. package/dist/docs/api/interfaces/StorySliderEvents.html +102 -0
  316. package/dist/docs/api/interfaces/StorymapBasemap.html +69 -0
  317. package/dist/docs/api/interfaces/StorymapData.html +77 -0
  318. package/dist/docs/api/interfaces/StorymapDataWrapper.html +60 -0
  319. package/dist/docs/api/interfaces/StorymapDocument.html +68 -0
  320. package/dist/docs/api/interfaces/StorymapError.html +63 -0
  321. package/dist/docs/api/interfaces/StorymapGeoreference.html +93 -0
  322. package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +74 -0
  323. package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +69 -0
  324. package/dist/docs/api/interfaces/StorymapLanguageMap.html +57 -0
  325. package/dist/docs/api/interfaces/StorymapManifest.html +118 -0
  326. package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +137 -0
  327. package/dist/docs/api/interfaces/StorymapManifestBackground.html +81 -0
  328. package/dist/docs/api/interfaces/StorymapManifestCanvas.html +188 -0
  329. package/dist/docs/api/interfaces/StorymapManifestContentResource.html +97 -0
  330. package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +82 -0
  331. package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +87 -0
  332. package/dist/docs/api/interfaces/StorymapManifestImageService.html +69 -0
  333. package/dist/docs/api/interfaces/StorymapManifestRange.html +75 -0
  334. package/dist/docs/api/interfaces/StorymapManifestService.html +77 -0
  335. package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +69 -0
  336. package/dist/docs/api/interfaces/StorymapManifestStatement.html +63 -0
  337. package/dist/docs/api/interfaces/StorymapMapOptions.html +92 -0
  338. package/dist/docs/api/interfaces/StorymapOptions.html +734 -0
  339. package/dist/docs/api/interfaces/StorymapOverlayLayer.html +157 -0
  340. package/dist/docs/api/interfaces/StorymapSlide.html +186 -0
  341. package/dist/docs/api/interfaces/StorymapSlideBackground.html +72 -0
  342. package/dist/docs/api/interfaces/StorymapSlideLocation.html +161 -0
  343. package/dist/docs/api/interfaces/StorymapSlideMarker.html +103 -0
  344. package/dist/docs/api/interfaces/StorymapSlideMedia.html +149 -0
  345. package/dist/docs/api/interfaces/StorymapSlideNarration.html +117 -0
  346. package/dist/docs/api/interfaces/StorymapSlideText.html +72 -0
  347. package/dist/docs/api/interfaces/StorymapTilejson.html +105 -0
  348. package/dist/docs/api/interfaces/SwipableEvents.html +102 -0
  349. package/dist/docs/api/interfaces/TextEvents.html +66 -0
  350. package/dist/docs/api/media/es.json +31 -0
  351. package/dist/docs/api/media/events.md +66 -0
  352. package/dist/docs/api/media/migration-from-knightlab.md +399 -0
  353. package/dist/docs/api/media/slideshow.md +109 -0
  354. package/dist/docs/api/media/storymap-as-iiif-manifest.md +1007 -0
  355. package/dist/docs/api/modules.html +50 -0
  356. package/dist/docs/api/types/ContentState.html +70 -0
  357. package/dist/docs/api/types/FiredEvent.html +43 -0
  358. package/dist/docs/api/types/ImagereadyKind.html +34 -0
  359. package/dist/docs/api/types/MediaTypeMatch.html +78 -0
  360. package/dist/docs/api/types/SwipeDirection.html +36 -0
  361. package/dist/docs/api/types/TileSourceFactory.html +53 -0
  362. package/dist/docs/authoring.html +306 -0
  363. package/dist/docs/events.html +263 -0
  364. package/dist/docs/iiif.html +738 -69
  365. package/dist/docs/migration.html +360 -11
  366. package/dist/docs/readme.html +149 -17
  367. package/dist/embed/index.html +8 -1
  368. package/dist/examples/font-css-false.json +33 -0
  369. package/dist/examples/issue-242-nonlatin.json +55 -0
  370. package/dist/examples/issue-305-start-at-slide-data.json +96 -0
  371. package/dist/examples/issue-358-iframe.json +57 -0
  372. package/dist/examples/issue-iiif-geo.json +32 -0
  373. package/dist/examples/issue-image-alt.json +23 -0
  374. package/dist/examples/issue-image-region.json +42 -0
  375. package/dist/examples/issue-image-srcset.json +24 -0
  376. package/dist/examples/layers-control.json +60 -0
  377. package/dist/examples/map-area-overlays.json +68 -0
  378. package/dist/examples/map-template-provider.json +36 -0
  379. package/dist/examples/multi-media.json +71 -0
  380. package/dist/examples/no-map.json +44 -0
  381. package/dist/examples-iiif/annotated-image.json +204 -0
  382. package/dist/examples-iiif/bob-boilen.json +11 -5
  383. package/dist/examples-iiif/courbet.json +9 -6
  384. package/dist/examples-iiif/empty.json +8 -4
  385. package/dist/examples-iiif/flickr-drewvigal.json +248 -24
  386. package/dist/examples-iiif/flickr-zach.wise.json +8 -4
  387. package/dist/examples-iiif/font-css-false.json +114 -0
  388. package/dist/examples-iiif/georeferenced-layer-unsupported.json +153 -0
  389. package/dist/examples-iiif/georeferenced-layer.json +318 -0
  390. package/dist/examples-iiif/iiif-wellcome.json +9 -6
  391. package/dist/examples-iiif/instagram-chenpamela.json +381 -36
  392. package/dist/examples-iiif/instagram_brentfoster.json +429 -40
  393. package/dist/examples-iiif/instagram_couch.json +261 -26
  394. package/dist/examples-iiif/instagram_joegermuska.json +441 -41
  395. package/dist/examples-iiif/instagram_matteich.json +261 -26
  396. package/dist/examples-iiif/instagram_mirandamulligan.json +261 -26
  397. package/dist/examples-iiif/instagram_raymondmccrea.json +261 -26
  398. package/dist/examples-iiif/instagram_test.json +261 -26
  399. package/dist/examples-iiif/issue-134-no-lines.json +9 -5
  400. package/dist/examples-iiif/issue-177-color-vars.json +9 -5
  401. package/dist/examples-iiif/issue-211-rtl.json +9 -5
  402. package/dist/examples-iiif/issue-242-nonlatin.json +239 -0
  403. package/dist/examples-iiif/issue-272-facebook.json +9 -5
  404. package/dist/examples-iiif/issue-305-start-at-slide-data.json +305 -0
  405. package/dist/examples-iiif/issue-305-start-at-slide.json +9 -5
  406. package/dist/examples-iiif/issue-341-distance.json +9 -5
  407. package/dist/examples-iiif/issue-358-iframe.json +190 -0
  408. package/dist/examples-iiif/issue-360-juxtapose.json +22 -7
  409. package/dist/examples-iiif/issue-368-null-fields.json +9 -5
  410. package/dist/examples-iiif/issue-375-code-lists.json +9 -5
  411. package/dist/examples-iiif/issue-381-dateline.json +9 -5
  412. package/dist/examples-iiif/issue-405-custom-icon.json +203 -0
  413. package/dist/examples-iiif/issue-425-many-slides.json +9 -5
  414. package/dist/examples-iiif/issue-428-background.json +20 -8
  415. package/dist/examples-iiif/issue-435-googlemaps.json +9 -5
  416. package/dist/examples-iiif/issue-437-documentcloud.json +22 -7
  417. package/dist/examples-iiif/issue-451-webp.json +9 -5
  418. package/dist/examples-iiif/issue-455-audio.json +9 -5
  419. package/dist/examples-iiif/issue-480-shorts.json +9 -5
  420. package/dist/examples-iiif/issue-506-marker-sync.json +9 -5
  421. package/dist/examples-iiif/issue-iiif-geo.json +200 -0
  422. package/dist/examples-iiif/issue-image-alt.json +90 -0
  423. package/dist/examples-iiif/issue-image-region.json +203 -0
  424. package/dist/examples-iiif/issue-image-srcset.json +87 -0
  425. package/dist/examples-iiif/jansteen.json +9 -6
  426. package/dist/examples-iiif/katrina.json +197 -41
  427. package/dist/examples-iiif/layers-control.json +226 -0
  428. package/dist/examples-iiif/map-area-overlays.json +289 -0
  429. package/dist/examples-iiif/map-template-provider.json +133 -0
  430. package/dist/examples-iiif/marktwain.json +255 -58
  431. package/dist/examples-iiif/multi-media.json +237 -0
  432. package/dist/examples-iiif/no-map.json +148 -0
  433. package/dist/examples-iiif/population.json +440 -76
  434. package/dist/examples-iiif/president.json +456 -83
  435. package/dist/examples-iiif/scroll-hint.json +190 -0
  436. package/dist/examples-iiif/seurat.json +113 -22
  437. package/dist/examples-iiif/zoomify-clamp.json +153 -0
  438. package/dist/examples-slideshow/single.json +79 -0
  439. package/dist/examples-slideshow/static/pixel.png +0 -0
  440. package/dist/examples-slideshow/static.json +44 -0
  441. package/dist/harness-multi.html +17 -0
  442. package/dist/harness.html +4 -2
  443. package/dist/index.html +19 -12
  444. package/dist/js/storymap.d.ts +2669 -307
  445. package/dist/js/storymap.js +10820 -6196
  446. package/dist/js/storymap.js.map +1 -1
  447. package/dist/navplace-properties.json +54 -0
  448. package/dist/site.css +54 -36
  449. package/docs/migration-from-knightlab.md +279 -19
  450. package/docs/storymap-as-iiif-manifest.md +633 -136
  451. package/package.json +12 -7
  452. package/schema/storymap.schema.json +733 -80
  453. package/src/animation/easings.ts +8 -1
  454. package/src/animation/tween.ts +186 -0
  455. package/src/core/Browser.ts +6 -5
  456. package/src/core/Load.ts +54 -2
  457. package/src/core/Util.ts +257 -193
  458. package/src/core/mixins.ts +66 -35
  459. package/src/core/viewers.ts +94 -0
  460. package/src/dom/DomEvent.ts +27 -8
  461. package/src/globals.d.ts +8 -0
  462. package/src/language/Language.ts +206 -25
  463. package/src/language/locale/.expected-gaps.json +346 -0
  464. package/src/language/locale/be.json +15 -2
  465. package/src/language/locale/bg.json +15 -2
  466. package/src/language/locale/cs.json +15 -2
  467. package/src/language/locale/de.json +23 -2
  468. package/src/language/locale/el.json +15 -2
  469. package/src/language/locale/en.json +17 -3
  470. package/src/language/locale/es.json +15 -2
  471. package/src/language/locale/et.json +5 -1
  472. package/src/language/locale/fr.json +15 -2
  473. package/src/language/locale/he.json +16 -3
  474. package/src/language/locale/hu.json +15 -2
  475. package/src/language/locale/is.json +5 -1
  476. package/src/language/locale/it.json +15 -2
  477. package/src/language/locale/jp.json +15 -2
  478. package/src/language/locale/ko.json +15 -2
  479. package/src/language/locale/nl.json +15 -2
  480. package/src/language/locale/nn.json +5 -1
  481. package/src/language/locale/no.json +15 -2
  482. package/src/language/locale/pl.json +15 -2
  483. package/src/language/locale/pt.json +15 -2
  484. package/src/language/locale/ru.json +15 -2
  485. package/src/language/locale/sk.json +15 -2
  486. package/src/language/locale/sr.json +5 -1
  487. package/src/language/locale/sv.json +15 -2
  488. package/src/language/locale/tr.json +15 -2
  489. package/src/language/locale/uk.json +15 -2
  490. package/src/language/locale/ur.json +5 -1
  491. package/src/language/locale/zh-cn.json +15 -2
  492. package/src/language/locale/zh-tw.json +15 -2
  493. package/src/main.ts +143 -0
  494. package/src/map/Map.ts +227 -112
  495. package/src/map/MapMarker.ts +44 -8
  496. package/src/map/georeference.ts +325 -0
  497. package/src/map/openlayers/Map.OpenLayers.ts +1601 -263
  498. package/src/map/openlayers/MapMarker.OpenLayers.ts +348 -24
  499. package/src/map/openlayers/zoomifyTiles.ts +1 -4
  500. package/src/map/slideView.ts +149 -0
  501. package/src/map/types.ts +2 -0
  502. package/src/media/EmbedUtil.ts +333 -24
  503. package/src/media/Media.ts +270 -59
  504. package/src/media/embedId.ts +110 -0
  505. package/src/media/types/Audio.ts +9 -82
  506. package/src/media/types/Blockquote.ts +2 -3
  507. package/src/media/types/DailyMotion.ts +5 -10
  508. package/src/media/types/DocumentCloud.ts +6 -35
  509. package/src/media/types/Facebook.ts +3 -4
  510. package/src/media/types/Flickr.ts +23 -12
  511. package/src/media/types/GoogleDoc.ts +3 -4
  512. package/src/media/types/HtmlMedia.ts +233 -0
  513. package/src/media/types/IFrame.ts +3 -4
  514. package/src/media/types/Image.ts +87 -9
  515. package/src/media/types/Juxtapose.ts +14 -5
  516. package/src/media/types/SoundCloud.ts +28 -6
  517. package/src/media/types/Text.ts +46 -21
  518. package/src/media/types/Twitter.ts +35 -20
  519. package/src/media/types/Video.ts +9 -79
  520. package/src/media/types/Vimeo.ts +11 -11
  521. package/src/media/types/Website.ts +23 -13
  522. package/src/media/types/Wikipedia.ts +18 -8
  523. package/src/media/types/YouTube.ts +72 -40
  524. package/src/scss/Typography.scss +16 -18
  525. package/src/scss/VCO.StoryMap.scss +208 -12
  526. package/src/scss/Variables.scss +3 -2
  527. package/src/scss/core/Mixins.scss +5 -63
  528. package/src/scss/core/Reset.scss +5 -18
  529. package/src/scss/fonts/font.amatic-andika.scss +3 -0
  530. package/src/scss/fonts/font.bitter-raleway.scss +6 -0
  531. package/src/scss/fonts/font.cairo.scss +79 -0
  532. package/src/scss/fonts/font.clicker-garamond.scss +5 -0
  533. package/src/scss/fonts/font.dancing-ledger.scss +1 -0
  534. package/src/scss/fonts/font.knightlab.scss +14 -0
  535. package/src/scss/fonts/font.oldstandard.scss +6 -0
  536. package/src/scss/fonts/font.opensans-gentiumbook.scss +5 -0
  537. package/src/scss/fonts/font.playfair-faunaone.scss +2 -0
  538. package/src/scss/fonts/font.playfair.scss +4 -0
  539. package/src/scss/fonts/font.pt.scss +6 -0
  540. package/src/scss/fonts/font.ubuntu.scss +4 -0
  541. package/src/scss/fonts/font.unicaone-vollkorn.scss +5 -0
  542. package/src/scss/map/VCO.Map.scss +1 -1
  543. package/src/scss/map/VCO.MapMarker.scss +114 -8
  544. package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +7 -4
  545. package/src/scss/media/VCO.Media.scss +14 -17
  546. package/src/scss/media/types/VCO.Media.Blockquote.scss +1 -1
  547. package/src/scss/media/types/VCO.Media.Text.scss +13 -5
  548. package/src/scss/media/types/VCO.Media.Twitter.scss +4 -4
  549. package/src/scss/media/types/VCO.Media.Wikipedia.scss +3 -19
  550. package/src/scss/site/site.scss +55 -36
  551. package/src/scss/slider/VCO.Slide.scss +61 -13
  552. package/src/scss/slider/VCO.SlideNav.scss +34 -24
  553. package/src/scss/slider/VCO.StorySlider.scss +53 -1
  554. package/src/scss/snapmap/VCO.SnapMap.scss +3 -3
  555. package/src/scss/ui/VCO.Consent.scss +63 -13
  556. package/src/scss/ui/VCO.Layers.scss +119 -0
  557. package/src/scss/ui/VCO.MenuBar.Button.scss +143 -14
  558. package/src/scss/ui/VCO.MenuBar.scss +9 -2
  559. package/src/scss/ui/VCO.Message.scss +16 -5
  560. package/src/site/site.ts +2 -1
  561. package/src/slider/Slide.ts +326 -74
  562. package/src/slider/SlideNav.ts +54 -9
  563. package/src/slider/StorySlider.ts +352 -60
  564. package/src/storymap/Consent.ts +429 -82
  565. package/src/storymap/StoryMap.ts +2163 -340
  566. package/src/storymap/content-state.ts +180 -0
  567. package/src/storymap/font-css.ts +72 -0
  568. package/src/storymap/from-slideshow.ts +785 -0
  569. package/src/storymap/iiif-shared.ts +228 -0
  570. package/src/storymap/iiif.ts +1742 -95
  571. package/src/storymap/to-iiif.ts +1008 -0
  572. package/src/storymap/validate.ts +80 -7
  573. package/src/types.ts +591 -29
  574. package/src/ui/LayersControl.ts +302 -0
  575. package/src/ui/MenuBar.ts +325 -61
  576. package/src/ui/Message.ts +44 -2
  577. package/src/ui/Swipable.ts +170 -85
  578. package/dist/assets/demo-D6cTmzn6.js +0 -1
  579. package/dist/assets/harness-BPFlzutp.js +0 -1
  580. package/dist/assets/index-DDsPBPZA.js +0 -1
  581. package/dist/assets/main-Y-MYUSJ4.js +0 -17
  582. package/src/animation/morpheus.d.ts +0 -41
  583. package/src/scss/VCO.StoryMap.Dark.scss +0 -138
  584. package/src/scss/Variables.Dark.scss +0 -56
  585. package/src/scss/media/types/VCO.Media.Instagram.scss +0 -7
  586. package/src/scss/media/types/VCO.Media.Profile.scss +0 -5
  587. package/src/ui/Draggable.ts +0 -374
package/src/ui/MenuBar.ts CHANGED
@@ -4,8 +4,10 @@ import Dom from "../dom/Dom";
4
4
  import { easeInOutQuint } from "../animation/easings";
5
5
 
6
6
  import { DomEvent } from "../dom/DomEvent";
7
+ import { PROGRESSBAR_STYLES } from "../types";
7
8
  import { Browser } from "../core/Browser";
8
- import { Language } from "../language/Language";
9
+ import { Language, currentLocale } from "../language/Language";
10
+ import LayersControl, { type LayersControlDelegate } from "./LayersControl";
9
11
 
10
12
  /* MenuBar
11
13
  Buttons, progress and distance display for the storymap
@@ -20,13 +22,30 @@ interface MenuBarOptions {
20
22
  [key: string]: unknown;
21
23
  }
22
24
 
25
+ export interface MenuBarEvents {
26
+ overview: Event;
27
+ back_to_start: Event;
28
+ fullscreen: Event;
29
+ autoplay_toggle: undefined;
30
+ progress_go: { slide: number };
31
+ collapse: { y: number; collapsed: boolean };
32
+ basemapchange: { map_type: string };
33
+ overlaychange: { index: number; visible: boolean };
34
+ loaded: undefined;
35
+ added: undefined;
36
+ removed: undefined;
37
+ }
38
+
23
39
  class MenuBarBase {
24
40
  declare "_el": Record<string, HTMLElement>;
25
41
  declare "collapsed": boolean;
26
42
  declare "options": MenuBarOptions;
27
43
  declare "animator": Record<string, unknown>;
28
- declare "fire": EventedInstance["fire"];
44
+ declare "fire": EventedInstance<MenuBarEvents>["fire"];
29
45
  _fullscreenActive = false;
46
+ _autoplayStopped = false;
47
+ /** The layer switcher, if `show_layers_control` is on. */
48
+ declare "_layersControl": LayersControl | null;
30
49
 
31
50
  /* Constructor
32
51
  ================================================== */
@@ -53,7 +72,11 @@ class MenuBarBase {
53
72
  if (typeof elem === "object") {
54
73
  this._el.container = elem;
55
74
  } else {
56
- this._el.container = Dom.get(elem);
75
+ const found = Dom.get(elem);
76
+ if (!found) {
77
+ throw new Error("StoryMapJS: no element with id " + elem);
78
+ }
79
+ this._el.container = found;
57
80
  }
58
81
 
59
82
  if (parent_elem) {
@@ -72,6 +95,8 @@ class MenuBarBase {
72
95
  // Animation
73
96
  this.animator = {};
74
97
 
98
+ this._layersControl = null;
99
+
75
100
  // Merge Data and Options
76
101
  mergeData(this.options, options);
77
102
 
@@ -112,49 +137,217 @@ class MenuBarBase {
112
137
  this._el.button_fullscreen.innerHTML = `<span class='${icon}'></span>`;
113
138
  } else {
114
139
  const label = active ? Language.buttons.exit_fullscreen : Language.buttons.fullscreen;
115
- this._el.button_fullscreen.innerHTML = `${label} <span class='${icon}'></span>`;
140
+ this._el.button_fullscreen.innerHTML = `${label}<span class='${icon}'></span>`;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Repaint the overview button label. An image map has no interactive
146
+ * overview, so it gets the shorter wording. Icon-only on mobile.
147
+ */
148
+ _renderOverviewLabel(): void {
149
+ const label = this.options.map_as_image
150
+ ? Language.buttons.overview
151
+ : Language.buttons.map_overview;
152
+ if (Browser.mobile) {
153
+ this._el.button_overview.innerHTML = "<span class='vco-icon-mappin'></span>";
154
+ this._el.button_overview.setAttribute("aria-label", label);
155
+ } else {
156
+ this._el.button_overview.innerHTML = `${label}<span class='vco-icon-mappin'></span>`;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Repaint the "back to start" button label. Icon-only on mobile.
162
+ */
163
+ _renderBackToStartLabel(): void {
164
+ this._el.button_backtostart.innerHTML = Browser.mobile
165
+ ? "<span class='vco-icon-goback'></span>"
166
+ : Language.buttons.backtostart + "<span class='vco-icon-goback'></span>";
167
+ }
168
+
169
+ /**
170
+ * Repaint the collapse/expand toggle. Icon-only on mobile.
171
+ */
172
+ _renderCollapseLabel(collapsed: boolean): void {
173
+ const arrow = collapsed ? "arrow-down" : "arrow-up";
174
+ if (Browser.mobile) {
175
+ this._el.button_collapse_toggle.innerHTML = `<span class='vco-icon-${arrow}'></span>`;
176
+ } else {
177
+ const text = collapsed
178
+ ? Language.buttons.uncollapse_toggle
179
+ : Language.buttons.collapse_toggle;
180
+ this._el.button_collapse_toggle.innerHTML = `${text}<span class='vco-icon-${arrow}'></span>`;
116
181
  }
117
182
  }
118
183
 
184
+ /**
185
+ * Reflect the autoplay state in the toggle label.
186
+ */
187
+ setAutoplayState(stopped: boolean): void {
188
+ this._autoplayStopped = stopped;
189
+ if (!this._el.button_autoplay) return;
190
+ const label = stopped ? Language.buttons.autoplay_play : Language.buttons.autoplay_pause;
191
+ if (Browser.mobile) {
192
+ this._el.button_autoplay.setAttribute("aria-label", label);
193
+ } else {
194
+ this._el.button_autoplay.textContent = label;
195
+ }
196
+ this._el.button_autoplay.setAttribute("aria-pressed", String(!stopped));
197
+ }
198
+
119
199
  /**
120
200
  * Repaint every text label from the active language (see `setLanguage`).
121
- * Icon-only mobile buttons carry no text and are left untouched.
201
+ * Icon-only mobile buttons carry text via aria-label instead.
122
202
  */
123
203
  refreshLabels(): void {
204
+ // panel rows are always text, so the control repaints even where
205
+ // the buttons below go icon-only
206
+ this._layersControl?.refreshLabels();
124
207
  if (Browser.mobile) {
208
+ this._renderMobileLabels();
125
209
  return;
126
210
  }
127
- if (this.options.map_as_image) {
128
- this._el.button_overview.innerHTML = Language.buttons.overview;
129
- } else {
130
- this._el.button_overview.innerHTML = Language.buttons.map_overview;
131
- }
132
- this._el.button_backtostart.innerHTML =
133
- Language.buttons.backtostart + " <span class='vco-icon-goback'></span>";
211
+ this._renderOverviewLabel();
212
+ this._renderBackToStartLabel();
134
213
  this.setFullscreenState(this._fullscreenActive);
135
- if (this.collapsed) {
136
- this._el.button_collapse_toggle.innerHTML =
137
- Language.buttons.uncollapse_toggle + "<span class='vco-icon-arrow-down'></span>";
138
- } else {
139
- this._el.button_collapse_toggle.innerHTML =
140
- Language.buttons.collapse_toggle + "<span class='vco-icon-arrow-up'></span>";
214
+ this.setAutoplayState(this._autoplayStopped);
215
+ this._renderCollapseLabel(this.collapsed);
216
+ }
217
+
218
+ /**
219
+ * Icon-only mobile buttons expose their labels to assistive tech since
220
+ * the visible text is icon glyphs.
221
+ */
222
+ _renderMobileLabels(): void {
223
+ const labels: [string, string][] = [
224
+ [
225
+ "button_overview",
226
+ this.options.map_as_image
227
+ ? Language.buttons.overview
228
+ : Language.buttons.map_overview,
229
+ ],
230
+ ["button_backtostart", Language.buttons.backtostart],
231
+ [
232
+ "button_collapse_toggle",
233
+ this.collapsed
234
+ ? Language.buttons.uncollapse_toggle
235
+ : Language.buttons.collapse_toggle,
236
+ ],
237
+ [
238
+ "button_fullscreen",
239
+ this._fullscreenActive
240
+ ? Language.buttons.exit_fullscreen
241
+ : Language.buttons.fullscreen,
242
+ ],
243
+ [
244
+ "button_autoplay",
245
+ this._autoplayStopped
246
+ ? Language.buttons.autoplay_play
247
+ : Language.buttons.autoplay_pause,
248
+ ],
249
+ ];
250
+ for (const [key, label] of labels) {
251
+ this._el[key]?.setAttribute("aria-label", label);
141
252
  }
142
253
  }
143
254
 
255
+ /** Hand the layer switcher its state source (StoryMap wires this). */
256
+ setLayersDelegate(delegate: LayersControlDelegate): void {
257
+ this._layersControl?.setDelegate(delegate);
258
+ }
259
+
260
+ /** Re-pull the switcher rows (overlays, basemaps, consent state). */
261
+ refreshLayers(): void {
262
+ this._layersControl?.refresh();
263
+ }
264
+
144
265
  /**
145
- * Update the progress indicator (issue #247); no-op when disabled.
266
+ * Update the progress indicator; no-op when disabled. The `progressbar`
267
+ * option selects the style (slideshow `progressbar`): the classic fill
268
+ * `bar` (default), height variants `block`/`thinblock`, or per-slide
269
+ * `dots`/`squares` buttons that jump to their slide.
146
270
  */
147
271
  setProgress(current: number, total: number): void {
148
- if (!this.options.show_progress || !this._el.progress_fill) {
272
+ const style = this._progressStyle();
273
+ if (style === "off" || !this._el.progress) {
274
+ return;
275
+ }
276
+ if (style === "dots" || style === "squares") {
277
+ this._renderProgressSteps(style, current, total);
278
+ return;
279
+ }
280
+ if (!this._el.progress_fill) {
149
281
  return;
150
282
  }
151
- const percent = total > 1 ? Math.round((current / (total - 1)) * 100) : 100;
283
+ // a single slide (or none) is fully read by definition, but a
284
+ // progressbar over zero slides is invalid ARIA — clear it instead
285
+ if (!(total > 1)) {
286
+ this._el.progress_fill.style.width = "100%";
287
+ this._el.progress.removeAttribute("role");
288
+ this._el.progress.removeAttribute("aria-valuenow");
289
+ this._el.progress.removeAttribute("aria-valuemin");
290
+ this._el.progress.removeAttribute("aria-valuemax");
291
+ this._el.progress.setAttribute("aria-label", "1 / 1");
292
+ return;
293
+ }
294
+ const percent = Math.round((Math.min(current, total - 1) / (total - 1)) * 100);
152
295
  this._el.progress_fill.style.width = percent + "%";
153
296
  this._el.progress.setAttribute("role", "progressbar");
154
- this._el.progress.setAttribute("aria-valuenow", String(current + 1));
297
+ this._el.progress.setAttribute("aria-valuenow", String(Math.min(current, total - 1) + 1));
155
298
  this._el.progress.setAttribute("aria-valuemin", "1");
156
299
  this._el.progress.setAttribute("aria-valuemax", String(total));
157
- this._el.progress.setAttribute("aria-label", `${current + 1} / ${total}`);
300
+ this._el.progress.setAttribute(
301
+ "aria-label",
302
+ `${Math.min(current, total - 1) + 1} / ${total}`,
303
+ );
304
+ }
305
+
306
+ /** The resolved progress style: `progressbar` wins, `show_progress` decides the default. */
307
+ _progressStyle(): "off" | "bar" | "dots" | "squares" | "block" | "thinblock" {
308
+ const raw = this.options.progressbar as string | boolean | undefined;
309
+ if (raw === false || raw === "off") return "off";
310
+ if (typeof raw === "string" && (PROGRESSBAR_STYLES as readonly string[]).includes(raw)) {
311
+ return raw as "bar" | "dots" | "squares" | "block" | "thinblock";
312
+ }
313
+ return this.options.show_progress ? "bar" : "off";
314
+ }
315
+
316
+ /** Per-slide progress buttons for the `dots`/`squares` styles. */
317
+ _renderProgressSteps(style: "dots" | "squares", current: number, total: number): void {
318
+ const container = this._el.progress;
319
+ if (!(total > 0)) {
320
+ container.innerHTML = "";
321
+ container.removeAttribute("role");
322
+ container.setAttribute("aria-label", "No slides");
323
+ return;
324
+ }
325
+ const built = Number(container.getAttribute("data-steps") ?? "0");
326
+ if (built !== total) {
327
+ container.innerHTML = "";
328
+ container.setAttribute("role", "tablist");
329
+ container.setAttribute("aria-label", `Slides 1 / ${total}`);
330
+ for (let i = 0; i < total; i++) {
331
+ const step = document.createElement("button");
332
+ step.setAttribute("type", "button");
333
+ step.className = `vco-menubar-progress-step vco-menubar-progress-${style}`;
334
+ step.setAttribute("role", "tab");
335
+ step.setAttribute("aria-label", `Slide ${i + 1} / ${total}`);
336
+ step.setAttribute("data-slide", String(i));
337
+ step.addEventListener("click", () => {
338
+ this.fire("progress_go", { slide: i });
339
+ });
340
+ container.appendChild(step);
341
+ }
342
+ container.setAttribute("data-steps", String(total));
343
+ }
344
+ const steps = container.querySelectorAll("[data-slide]");
345
+ steps.forEach((entry, index) => {
346
+ const el = entry as HTMLElement;
347
+ el.setAttribute("aria-selected", String(index === current));
348
+ el.classList.toggle("vco-active", index === current);
349
+ el.classList.toggle("vco-past", index < current);
350
+ });
158
351
  }
159
352
 
160
353
  /**
@@ -171,7 +364,7 @@ class MenuBarBase {
171
364
  }
172
365
  this._el.distance.style.display = "";
173
366
  const miles = kilometers * 0.621371;
174
- const locale = typeof Language.lang === "string" && Language.lang ? Language.lang : "en";
367
+ const locale = currentLocale();
175
368
  this._el.distance.textContent =
176
369
  kilometers >= 10
177
370
  ? `${Math.round(kilometers).toLocaleString(locale)} km · ${Math.round(miles).toLocaleString("en-US")} mi`
@@ -199,32 +392,39 @@ class MenuBarBase {
199
392
  this.fire("fullscreen", e);
200
393
  }
201
394
 
395
+ _onButtonAutoplay() {
396
+ this.fire("autoplay_toggle");
397
+ }
398
+
399
+ _onLayersBasemap(e: { map_type: string }) {
400
+ this.fire("basemapchange", { map_type: e.map_type });
401
+ }
402
+
403
+ _onLayersOverlay(e: { index: number; visible: boolean }) {
404
+ this.fire("overlaychange", { index: e.index, visible: e.visible });
405
+ }
406
+
202
407
  _onButtonCollapseMap(e: Event) {
203
408
  if (this.collapsed) {
204
409
  this.collapsed = false;
205
410
  this.show();
206
- this._el.button_overview.style.display = "inline";
207
- this.fire("collapse", { y: this.options.menubar_default_y });
208
- if (Browser.mobile) {
209
- this._el.button_collapse_toggle.innerHTML =
210
- "<span class='vco-icon-arrow-up'></span>";
211
- } else {
212
- this._el.button_collapse_toggle.innerHTML =
213
- Language.buttons.collapse_toggle + "<span class='vco-icon-arrow-up'></span>";
214
- }
411
+ // Restore from the option, not unconditionally: a story with
412
+ // show_overview false (including every mapless story, which the
413
+ // viewer forces off) would otherwise resurrect a dead overview
414
+ // button on every un-collapse.
415
+ this._el.button_overview.style.display =
416
+ this.options.show_overview === false ? "none" : "inline";
417
+ // `collapsed` is the authoritative signal: `y` is the menubar
418
+ // position, and reading it back as a map height made the
419
+ // un-collapse pass shrink the map to the menubar's pixel height.
420
+ this.fire("collapse", { y: this.options.menubar_default_y, collapsed: false });
421
+ this._renderCollapseLabel(false);
215
422
  } else {
216
423
  this.collapsed = true;
217
424
  this.hide(25);
218
425
  this._el.button_overview.style.display = "none";
219
- this.fire("collapse", { y: 1 });
220
- if (Browser.mobile) {
221
- this._el.button_collapse_toggle.innerHTML =
222
- "<span class='vco-icon-arrow-down'></span>";
223
- } else {
224
- this._el.button_collapse_toggle.innerHTML =
225
- Language.buttons.uncollapse_toggle +
226
- "<span class='vco-icon-arrow-down'></span>";
227
- }
426
+ this.fire("collapse", { y: 1, collapsed: true });
427
+ this._renderCollapseLabel(true);
228
428
  }
229
429
  }
230
430
 
@@ -233,31 +433,53 @@ class MenuBarBase {
233
433
  _initLayout() {
234
434
  // Create Layout
235
435
 
236
- // Buttons
237
- this._el.button_overview = Dom.create("span", "vco-menubar-button", this._el.container);
436
+ // Buttons — real <button> elements for keyboard/AT operability
437
+ // (issue #385 wave); class styling carries the look
438
+ this._el.button_overview = Dom.create("button", "vco-menubar-button", this._el.container);
439
+ this._el.button_overview.setAttribute("type", "button");
238
440
  DomEvent.addListener(this._el.button_overview, "click", this._onButtonOverview, this);
239
441
  if (this.options.show_overview === false) {
240
442
  this._el.button_overview.style.display = "none";
241
443
  }
242
444
 
243
- this._el.button_backtostart = Dom.create("span", "vco-menubar-button", this._el.container);
445
+ this._el.button_backtostart = Dom.create(
446
+ "button",
447
+ "vco-menubar-button",
448
+ this._el.container,
449
+ );
450
+ this._el.button_backtostart.setAttribute("type", "button");
244
451
  DomEvent.addListener(this._el.button_backtostart, "click", this._onButtonBackToStart, this);
245
452
  if (this.options.show_back_to_start === false) {
246
453
  this._el.button_backtostart.style.display = "none";
247
454
  }
248
455
 
249
456
  // Fullscreen toggle (hidden via CSS/display when disabled by options)
250
- this._el.button_fullscreen = Dom.create("span", "vco-menubar-button", this._el.container);
457
+ this._el.button_fullscreen = Dom.create("button", "vco-menubar-button", this._el.container);
458
+ this._el.button_fullscreen.setAttribute("type", "button");
251
459
  DomEvent.addListener(this._el.button_fullscreen, "click", this._onButtonFullscreen, this);
252
460
  if (this.options.fullscreen === false) {
253
461
  this._el.button_fullscreen.style.display = "none";
254
462
  }
255
463
 
464
+ // Autoplay pause/resume toggle (only when the story auto-advances)
465
+ if (typeof this.options.autoplay === "number" && this.options.autoplay > 0) {
466
+ this._el.button_autoplay = Dom.create(
467
+ "button",
468
+ "vco-menubar-button vco-menubar-autoplay",
469
+ this._el.container,
470
+ );
471
+ this._el.button_autoplay.setAttribute("type", "button");
472
+ this._el.button_autoplay.setAttribute("aria-pressed", "true");
473
+ DomEvent.addListener(this._el.button_autoplay, "click", this._onButtonAutoplay, this);
474
+ this.setAutoplayState(false);
475
+ }
476
+
256
477
  this._el.button_collapse_toggle = Dom.create(
257
- "span",
478
+ "button",
258
479
  "vco-menubar-button",
259
480
  this._el.container,
260
481
  );
482
+ this._el.button_collapse_toggle.setAttribute("type", "button");
261
483
  DomEvent.addListener(
262
484
  this._el.button_collapse_toggle,
263
485
  "click",
@@ -265,15 +487,15 @@ class MenuBarBase {
265
487
  this,
266
488
  );
267
489
 
268
- if (this.options.map_as_image) {
269
- this._el.button_overview.innerHTML = Language.buttons.overview;
270
- } else {
271
- this._el.button_overview.innerHTML = Language.buttons.map_overview;
272
- }
490
+ this._renderOverviewLabel();
273
491
 
274
- // Progress indicator (issue #247)
275
- if (this.options.show_progress) {
492
+ // Progress indicator (issue #247; dots/squares/block/thinblock via progressbar)
493
+ if (this._progressStyle() !== "off") {
276
494
  this._el.progress = Dom.create("span", "vco-menubar-progress", this._el.container);
495
+ const style = this._progressStyle();
496
+ if (style !== "bar") {
497
+ this._el.progress.classList.add(`vco-menubar-progress-${style}`);
498
+ }
277
499
  this._el.progress_fill = Dom.create(
278
500
  "span",
279
501
  "vco-menubar-progress-fill",
@@ -292,17 +514,27 @@ class MenuBarBase {
292
514
  this._el.button_fullscreen.innerHTML = "<span class='vco-icon-resize-full'></span>";
293
515
  this._el.container.setAttribute("ontouchstart", " ");
294
516
  } else {
295
- this._el.button_backtostart.innerHTML =
296
- Language.buttons.backtostart + " <span class='vco-icon-goback'></span>";
297
- this._el.button_collapse_toggle.innerHTML =
298
- Language.buttons.collapse_toggle + "<span class='vco-icon-arrow-up'></span>";
517
+ this._renderBackToStartLabel();
518
+ this._renderCollapseLabel(this.collapsed);
299
519
  this._el.button_fullscreen.innerHTML =
300
- Language.buttons.fullscreen + " <span class='vco-icon-resize-full'></span>";
520
+ Language.buttons.fullscreen + "<span class='vco-icon-resize-full'></span>";
301
521
  }
302
522
 
303
- if (this.options.layout === "landscape") {
523
+ if (this.options.layout === "landscape" || this.options.map_type === "none") {
524
+ // Landscape has no map split to collapse; a mapless story has no
525
+ // map at all, so the toggle would flip its label while nothing
526
+ // on screen changes.
304
527
  this._el.button_collapse_toggle.style.display = "none";
305
528
  }
529
+
530
+ // Layer switcher (opt-in): the control renders nothing until a
531
+ // delegate hands it rows, so consent-denied and mapless stories
532
+ // show no button at all
533
+ if (this.options.show_layers_control) {
534
+ this._layersControl = new LayersControl(this._el.container);
535
+ this._layersControl.on("basemapchange", this._onLayersBasemap, this);
536
+ this._layersControl.on("overlaychange", this._onLayersOverlay, this);
537
+ }
306
538
  }
307
539
 
308
540
  // Update Display
@@ -314,9 +546,41 @@ class MenuBarBase {
314
546
  this.options.height = height;
315
547
  }
316
548
  }
549
+
550
+ /**
551
+ * Release the button listeners, the progress animation and the element.
552
+ * Called by `StoryMap.dispose()`; the menubar must not be used afterwards.
553
+ */
554
+ dispose(): void {
555
+ const buttons: [string, EventListener][] = [
556
+ ["button_overview", this._onButtonOverview as EventListener],
557
+ ["button_backtostart", this._onButtonBackToStart as EventListener],
558
+ ["button_fullscreen", this._onButtonFullscreen as EventListener],
559
+ ["button_autoplay", this._onButtonAutoplay as EventListener],
560
+ ["button_collapse_toggle", this._onButtonCollapseMap as EventListener],
561
+ ];
562
+ for (const [key, handler] of buttons) {
563
+ const el = this._el[key];
564
+ if (el) {
565
+ DomEvent.removeListener(el, "click", handler, this);
566
+ }
567
+ }
568
+ if (this._layersControl) {
569
+ this._layersControl.off("basemapchange", this._onLayersBasemap, this);
570
+ this._layersControl.off("overlaychange", this._onLayersOverlay, this);
571
+ this._layersControl.dispose();
572
+ this._layersControl = null;
573
+ }
574
+ this._el.container?.getAnimations?.().forEach((a) => a.cancel());
575
+ this._el.container?.remove();
576
+ }
317
577
  }
318
578
 
319
- export default class MenuBar extends DomMixed(Evented(MenuBarBase)) {
579
+ const EventedMenuBarBase = Evented<MenuBarEvents, typeof MenuBarBase>(MenuBarBase);
580
+
581
+ export default class MenuBar extends DomMixed<MenuBarEvents, typeof EventedMenuBarBase>(
582
+ EventedMenuBarBase,
583
+ ) {
320
584
  constructor(...args: ConstructorParameters<typeof MenuBarBase>) {
321
585
  super(...args);
322
586
  }
package/src/ui/Message.ts CHANGED
@@ -15,12 +15,19 @@ interface MessageOptions {
15
15
  [key: string]: unknown;
16
16
  }
17
17
 
18
+ export interface MessageEvents {
19
+ clicked: MessageOptions;
20
+ loaded: Record<string, unknown>;
21
+ added: Record<string, unknown>;
22
+ removed: Record<string, unknown>;
23
+ }
24
+
18
25
  class MessageBase {
19
26
  declare "_el": Record<string, HTMLElement>;
20
27
  declare "options": MessageOptions;
21
28
  "data": Record<string, unknown>;
22
29
  declare "animator": Record<string, unknown>;
23
- declare "fire": EventedInstance["fire"];
30
+ declare "fire": EventedInstance<MessageEvents>["fire"];
24
31
 
25
32
  /* Constructor
26
33
  ================================================== */
@@ -82,6 +89,12 @@ class MessageBase {
82
89
  } else {
83
90
  this._el.message.innerHTML = t;
84
91
  }
92
+ // the container dismisses on click, so it is a button to assistive
93
+ // tech too; its name tracks the message text
94
+ const label = this._el.message.textContent?.trim() ?? "";
95
+ if (label !== "") {
96
+ this._el.container.setAttribute("aria-label", label);
97
+ }
85
98
  }
86
99
 
87
100
  /* Events
@@ -91,10 +104,24 @@ class MessageBase {
91
104
  this.fire("clicked", this.options);
92
105
  }
93
106
 
107
+ _onKeyDown(e: Event) {
108
+ const key = (e as KeyboardEvent).key;
109
+ if (key === "Enter" || key === " " || key === "Spacebar") {
110
+ e.preventDefault();
111
+ this._onMouseClick();
112
+ }
113
+ }
114
+
94
115
  /* Private Methods
95
116
  ================================================== */
96
117
  _initLayout() {
97
118
  // Create Layout
119
+ // Dismissable by click and keyboard alike (see _onKeyDown): the
120
+ // fixed hook below carries the focus ring, whatever message_class
121
+ // the host configured.
122
+ this._el.container.classList.add("vco-message-dismiss");
123
+ this._el.container.setAttribute("role", "button");
124
+ this._el.container.setAttribute("tabindex", "0");
98
125
  this._el.message_container = Dom.create("div", "vco-message-container", this._el.container);
99
126
  this._el.loading_icon = Dom.create(
100
127
  "div",
@@ -108,10 +135,25 @@ class MessageBase {
108
135
 
109
136
  _initEvents() {
110
137
  DomEvent.addListener(this._el.container, "click", this._onMouseClick, this);
138
+ DomEvent.addListener(this._el.container, "keydown", this._onKeyDown, this);
139
+ }
140
+
141
+ /**
142
+ * Release the listeners and drop the element. Called by
143
+ * `StorySlider.dispose()`; the message must not be used afterwards.
144
+ */
145
+ dispose() {
146
+ DomEvent.removeListener(this._el.container, "click", this._onMouseClick, this);
147
+ DomEvent.removeListener(this._el.container, "keydown", this._onKeyDown, this);
148
+ this._el.container.remove();
111
149
  }
112
150
  }
113
151
 
114
- export default class Message extends DomMixed(Evented(MessageBase)) {
152
+ const EventedMessageBase = Evented<MessageEvents, typeof MessageBase>(MessageBase);
153
+
154
+ export default class Message extends DomMixed<MessageEvents, typeof EventedMessageBase>(
155
+ EventedMessageBase,
156
+ ) {
115
157
  constructor(...args: ConstructorParameters<typeof MessageBase>) {
116
158
  super(...args);
117
159
  }