@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
@@ -1,15 +1,22 @@
1
- import { mergeData, unique_ID, findArrayNumberByUniqueID, parseCssColor, slideTransitionDuration } from "../core/Util";
1
+ import {
2
+ mergeData,
3
+ unique_ID,
4
+ findArrayNumberByUniqueID,
5
+ parseCssColor,
6
+ slideTransitionDuration,
7
+ prefersReducedMotion,
8
+ } from "../core/Util";
2
9
  import { Evented, type EventedInstance } from "../core/mixins";
3
10
  import Dom from "../dom/Dom";
4
11
  import { DomEvent } from "../dom/DomEvent";
5
12
  import { easeInOutQuint } from "../animation/easings";
6
13
  import SlideNav from "./SlideNav";
7
14
  import Slide from "./Slide";
8
- import Animate from "morpheus";
15
+ import Animate from "../animation/tween";
9
16
  import Swipable from "../ui/Swipable";
10
17
  import Message from "../ui/Message";
11
18
  import { Browser } from "../core/Browser";
12
- import { Language } from "../language/Language";
19
+ import { Language, isRtl } from "../language/Language";
13
20
  import { AnimationHandle, StorymapData, StorymapSlide } from "../types";
14
21
 
15
22
  /* StorySlider
@@ -43,33 +50,64 @@ interface StorySliderOptions {
43
50
  skinny_size?: number;
44
51
  call_to_action?: boolean;
45
52
  call_to_action_text?: string;
46
- dragging?: boolean;
47
53
  trackResize?: boolean;
48
54
  [key: string]: unknown;
49
55
  }
50
56
 
57
+ /**
58
+ * The slider's element cache.
59
+ */
60
+ type StorySliderElements = {
61
+ container: HTMLElement;
62
+ /** Created in `_initLayout`; the slide background layer. */
63
+ background: HTMLElement;
64
+ slider_container_mask: HTMLElement;
65
+ slider_container: HTMLElement;
66
+ slider_item_container: HTMLElement;
67
+ live_region: HTMLElement | null;
68
+ };
69
+
51
70
  interface SlideBackgroundChange {
52
71
  color_value?: string;
53
72
  image?: boolean;
54
73
  }
55
74
 
75
+ export interface StorySliderEvents {
76
+ colorchange: SlideBackgroundChange;
77
+ nav_next: Partial<StorymapData>;
78
+ nav_previous: Partial<StorymapData>;
79
+ nav_left: Partial<StorymapData>;
80
+ nav_right: Partial<StorymapData>;
81
+ slideAdded: Partial<StorymapData>;
82
+ change: { current_slide: number; uniqueid: string | null | undefined };
83
+ loaded: Partial<StorymapData>;
84
+ title: { title: string };
85
+ }
86
+
56
87
  class StorySliderBase {
57
- declare "_el": Record<string, HTMLElement>;
88
+ declare "_el": StorySliderElements;
58
89
  declare "_nav": { previous: SlideNav; next: SlideNav };
59
90
  declare "slide_spacing": number;
60
91
  declare "_slides": Slide[];
61
92
  declare "_swipable": Swipable;
62
- declare "preloadTimer": ReturnType<typeof setTimeout>;
93
+ declare "preloadTimer": ReturnType<typeof setTimeout> | undefined;
94
+ declare "preloadIdleHandle": number | undefined;
63
95
  declare "_message": Message;
64
96
  declare "current_slide": number;
65
97
  declare "current_bg_color": string | null;
98
+ /** Layout the background gradient was built for; a portrait↔landscape
99
+ switch rebuilds it even when the color is unchanged. */
100
+ declare "current_bg_layout": string | null;
66
101
  declare "data": Partial<StorymapData>;
67
102
  declare "options": StorySliderOptions;
68
103
  declare "animator": AnimationHandle | null;
69
104
  declare "animator_background": AnimationHandle | null;
70
- declare "fire": EventedInstance["fire"];
105
+ declare "fire": EventedInstance<StorySliderEvents>["fire"];
71
106
  declare "_loaded": boolean;
72
- declare "hasEventListeners": EventedInstance["hasEventListeners"];
107
+ /** Scroll-spy observer for `mode: "static"`; null in standard mode. */
108
+ declare "_static_observer": IntersectionObserver | null;
109
+ /** True while a scroll-spy navigation is settling (suppresses echo scrolls). */
110
+ declare "_static_spying": boolean;
73
111
 
74
112
  /* Private Methods
75
113
  ================================================== */
@@ -82,10 +120,11 @@ class StorySliderBase {
82
120
  // DOM ELEMENTS
83
121
  this._el = {
84
122
  container: {} as HTMLElement,
85
- background: {} as HTMLElement,
86
123
  slider_container_mask: {} as HTMLElement,
87
124
  slider_container: {} as HTMLElement,
88
125
  slider_item_container: {} as HTMLElement,
126
+ background: {} as HTMLElement,
127
+ live_region: null,
89
128
  };
90
129
 
91
130
  this._nav = {
@@ -104,6 +143,7 @@ class StorySliderBase {
104
143
 
105
144
  // Current Background Color
106
145
  this.current_bg_color = null;
146
+ this.current_bg_layout = null;
107
147
 
108
148
  // Data Object
109
149
  this.data = {};
@@ -120,8 +160,6 @@ class StorySliderBase {
120
160
  // animation
121
161
  duration: 1000,
122
162
  ease: easeInOutQuint,
123
- // interaction
124
- dragging: true,
125
163
  trackResize: true,
126
164
  };
127
165
 
@@ -131,7 +169,11 @@ class StorySliderBase {
131
169
  this.options.id = unique_ID(6, "vco");
132
170
  } else {
133
171
  this.options.id = elem;
134
- this._el.container = Dom.get(elem);
172
+ const found = Dom.get(elem);
173
+ if (!found) {
174
+ throw new Error("StoryMapJS: no element with id " + elem);
175
+ }
176
+ this._el.container = found;
135
177
  }
136
178
 
137
179
  if (!this._el.container.id) {
@@ -141,6 +183,12 @@ class StorySliderBase {
141
183
  // Animation Object
142
184
  this.animator = null;
143
185
  this.animator_background = null;
186
+ this._static_observer = null;
187
+ this._static_spying = false;
188
+
189
+ // Preload scheduling handles, at most one of which is ever live
190
+ this.preloadTimer = undefined;
191
+ this.preloadIdleHandle = undefined;
144
192
 
145
193
  // Merge Data and Options
146
194
  mergeData(this.options, options);
@@ -183,14 +231,31 @@ class StorySliderBase {
183
231
  /* Create Slides
184
232
  ================================================== */
185
233
  _createSlides(array: StorymapData["slides"]) {
234
+ // a storymap with no slides array is a valid (if empty) document —
235
+ // the schema allows it and the map still renders
236
+ if (!array || array.length === 0) {
237
+ return;
238
+ }
186
239
  for (let i = 0; i < array.length; i++) {
187
- if (array[i].uniqueid === "") {
188
- array[i].uniqueid = unique_ID(6, "vco-slide");
189
- }
240
+ // The id is generated into a per-slide copy, not written back into
241
+ // `array`. StoryMap hands its own `this.data` down without cloning
242
+ // it, so writing here would be visible to every other viewer built
243
+ // from the same parsed document: the second one would find the id
244
+ // already set, adopt it, and emit a duplicate element id — the id
245
+ // becomes a DOM id in Slide, Text and Media.
246
+ //
247
+ // The guard is falsy rather than `=== ""`: `uniqueid` is optional
248
+ // in the schema and absent from 47 of the 48 bundled fixtures, so
249
+ // an empty-string test never fired and every slide ended up with
250
+ // an empty id.
251
+ const needs_id = !array[i].uniqueid;
252
+ const slide_data = needs_id
253
+ ? { ...array[i], uniqueid: unique_ID(6, "vco-slide") }
254
+ : array[i];
190
255
  if (i === 0) {
191
- this._createSlide(array[i], true);
256
+ this._createSlide(slide_data, true);
192
257
  } else {
193
- this._createSlide(array[i], false);
258
+ this._createSlide(slide_data, false);
194
259
  }
195
260
  }
196
261
  }
@@ -205,6 +270,11 @@ class StorySliderBase {
205
270
  slide.addTo(this._el.slider_item_container);
206
271
  slide.on("added", this._onSlideAdded, this);
207
272
  slide.on("background_change", this._onBackgroundChange, this);
273
+ // a slide added after layout (editor preview, StoryMap.createSlide)
274
+ // joins the scroll-spy in static mode
275
+ if (this._isStatic()) {
276
+ this._initStaticSpy();
277
+ }
208
278
  }
209
279
 
210
280
  /* Message
@@ -213,26 +283,72 @@ class StorySliderBase {
213
283
  /* Navigation
214
284
  ================================================== */
215
285
  goToId(n: string | number, fast?: boolean, displayupdate?: boolean) {
216
- let _n;
286
+ let _n: number;
217
287
  if (typeof n == "string" || (n as unknown) instanceof String) {
218
288
  _n = findArrayNumberByUniqueID(String(n), this._slides, "uniqueid");
289
+ if (_n === -1) {
290
+ // unknown id: stay where we are rather than jumping to slide 0
291
+ console.warn("StoryMapJS: no slide with uniqueid", n);
292
+ return;
293
+ }
219
294
  } else {
220
295
  _n = n;
221
296
  }
222
297
  this.goTo(_n, fast, displayupdate);
223
298
  }
224
299
 
225
- goTo(n: number, fast?: boolean, displayupdate?: boolean) {
226
- this.changeBackground({ color_value: "", image: false });
227
-
228
- // Clear Preloader Timer (covers both the setTimeout fallback and
229
- // the requestIdleCallback handle below — both are numbers)
230
- if (this.preloadTimer) {
300
+ /**
301
+ * Cancel the pending preload, whichever scheduling primitive queued it.
302
+ *
303
+ * The two handles are kept apart deliberately: they are both numbers, so
304
+ * calling `clearTimeout` on an idle-callback handle "works" by accident
305
+ * while actually leaking the callback, and the reverse leaves a live
306
+ * timeout behind.
307
+ */
308
+ _cancelPreload() {
309
+ if (this.preloadTimer !== undefined) {
231
310
  clearTimeout(this.preloadTimer);
311
+ this.preloadTimer = undefined;
312
+ }
313
+ if (this.preloadIdleHandle !== undefined) {
232
314
  (
233
315
  window as unknown as { cancelIdleCallback?: (handle: number) => void }
234
- ).cancelIdleCallback?.(this.preloadTimer as unknown as number);
316
+ ).cancelIdleCallback?.(this.preloadIdleHandle);
317
+ this.preloadIdleHandle = undefined;
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Release listeners, timers and running animations. Called by
323
+ * `StoryMap.dispose()`; the slider must not be used afterwards.
324
+ */
325
+ dispose() {
326
+ this._cancelPreload();
327
+ this._static_observer?.disconnect();
328
+ this._static_observer = null;
329
+ if (this._swipable) {
330
+ this._swipable.dispose();
235
331
  }
332
+ DomEvent.removeListener(this._el.container, "keydown", this._onKeyDown, this);
333
+ // Web Animations API (morpheus replacement): stop slide transitions
334
+ // mid-flight so they don't keep running against a detached tree
335
+ for (const el of [this._el.container, this._el.slider_container, this._el.background]) {
336
+ el?.getAnimations?.().forEach((a) => a.cancel());
337
+ }
338
+ for (const slide of this._slides) {
339
+ slide.dispose();
340
+ }
341
+ this._nav.previous?.dispose();
342
+ this._nav.next?.dispose();
343
+ this._message?.dispose();
344
+ this._slides = [];
345
+ }
346
+
347
+ goTo(n: number, fast?: boolean, displayupdate?: boolean, fromScroll = false) {
348
+ this.changeBackground({ color_value: "", image: false });
349
+
350
+ // Clear Preloader Timer
351
+ this._cancelPreload();
236
352
 
237
353
  // Set Slide Active State
238
354
  for (let i = 0; i < this._slides.length; i++) {
@@ -255,13 +371,46 @@ class StorySliderBase {
255
371
  this._swipable.stopMomentum();
256
372
  }
257
373
 
258
- if (fast) {
374
+ // Static reading mode: all slides are stacked in a scrollable
375
+ // list instead of a translating strip. Programmatic navigation
376
+ // scrolls the slide into view; scroll-spy navigation (fromScroll)
377
+ // only flips the active state, or scrolling would fight the
378
+ // visitor's own scroll position.
379
+ if (this._isStatic()) {
380
+ if (!fromScroll) {
381
+ this._static_spying = true;
382
+ this._scrollSlideIntoView(this.current_slide);
383
+ // longer than the smooth scroll it triggers: the
384
+ // observer must stay deaf until the list settles, or it
385
+ // echoes the programmatic scroll back as user input
386
+ window.setTimeout(() => {
387
+ this._static_spying = false;
388
+ }, 600);
389
+ }
390
+ // scroll-spy navigation must fire: the map follows the
391
+ // reading position through the change event (fromScroll only
392
+ // suppresses the echo scroll above, never the event)
393
+ this._onSlideChange(fromScroll ? false : displayupdate);
394
+ } else if (fast || prefersReducedMotion() || this.options.fxmode === "none") {
395
+ this._el.slider_container.style.opacity = "";
259
396
  this._el.slider_container.style.left = -(this.slide_spacing * n) + "px";
260
397
  this._onSlideChange(displayupdate);
398
+ } else if (this.options.fxmode === "fade") {
399
+ // fire the change event at animation start so the map and the
400
+ // slider animate simultaneously
401
+ this._onSlideChange(displayupdate);
402
+ this._el.slider_container.style.left = -(this.slide_spacing * n) + "px";
403
+ this._el.slider_container.style.opacity = "0";
404
+ this.animator = Animate(this._el.slider_container, {
405
+ opacity: 1,
406
+ duration: transition_duration,
407
+ easing: this.options.ease,
408
+ });
261
409
  } else {
262
410
  // fire the change event at animation start so the map and the
263
411
  // slider animate simultaneously
264
412
  this._onSlideChange(displayupdate);
413
+ this._el.slider_container.style.opacity = "";
265
414
  this.animator = Animate(this._el.slider_container, {
266
415
  left: -(this.slide_spacing * n) + "px",
267
416
  duration: transition_duration,
@@ -274,6 +423,14 @@ class StorySliderBase {
274
423
  this._slides[this.current_slide].setActive(true);
275
424
  }
276
425
 
426
+ // Announce the slide change to assistive tech (issue #385 wave):
427
+ // the headline or the slide number, replacing the previous text
428
+ if (this._el.live_region) {
429
+ const headline = this._slides[this.current_slide]?.title;
430
+ this._el.live_region.textContent =
431
+ headline || `Slide ${this.current_slide + 1} of ${this._slides.length}`;
432
+ }
433
+
277
434
  // Preload the next slide's media right away so its load clock,
278
435
  // network and iframe build elapse during this transition (and the
279
436
  // dwell time) instead of starting after arrival
@@ -304,9 +461,9 @@ class StorySliderBase {
304
461
  requestIdleCallback?: (cb: () => void, opts?: { timeout: number }) => number;
305
462
  };
306
463
  if (w.requestIdleCallback) {
307
- this.preloadTimer = w.requestIdleCallback(() => this.preloadSlides(), {
464
+ this.preloadIdleHandle = w.requestIdleCallback(() => this.preloadSlides(), {
308
465
  timeout: this.options.duration,
309
- }) as unknown as ReturnType<typeof setTimeout>;
466
+ });
310
467
  } else {
311
468
  this.preloadTimer = setTimeout(() => {
312
469
  this.preloadSlides();
@@ -368,6 +525,11 @@ class StorySliderBase {
368
525
  }
369
526
 
370
527
  showNav(nav_obj: SlideNav, show: boolean) {
528
+ // `shownav: false` (slideshow shownav) hides the previous/next
529
+ // chrome; keyboard, swipe and dots navigation still work
530
+ if (this.options.shownav === false) {
531
+ show = false;
532
+ }
371
533
  if (this.options.width <= 500 && Browser.mobile) {
372
534
  // hidden on small mobile screens
373
535
  } else {
@@ -389,26 +551,50 @@ class StorySliderBase {
389
551
  const bg_alpha_end = "0.87";
390
552
  const _bg_old = this._el.background.getAttribute("style");
391
553
 
554
+ // Dark theme without an explicit slide background: fade from the
555
+ // themed panel color. White (the light default) would wash the
556
+ // dark slide; the existing darkness heuristics below (less fade,
557
+ // inverted nav icons) then behave as they do for dark author
558
+ // backgrounds.
559
+ const dark =
560
+ !bg.color_value &&
561
+ (this.options.theme === "dark" ||
562
+ (this.options.theme !== "light" &&
563
+ typeof window.matchMedia === "function" &&
564
+ window.matchMedia("(prefers-color-scheme: dark)").matches));
392
565
  if (bg.color_value) {
393
566
  // any CSS color; unparseable values fall back to the default
394
567
  bg_color = parseCssColor(bg.color_value) || this.options.default_bg_color;
568
+ } else if (dark) {
569
+ bg_color = { r: 34, g: 34, b: 34 };
395
570
  } else {
396
571
  bg_color = this.options.default_bg_color;
397
572
  }
398
573
 
399
- // Stop animation
400
- if (this.animator_background) {
401
- this.animator_background.stop();
402
- }
403
-
404
574
  const bg_color_rgb = bg_color.r + "," + bg_color.g + "," + bg_color.b;
405
575
 
406
- if (!this.current_bg_color || this.current_bg_color !== bg_color_rgb) {
576
+ if (
577
+ !this.current_bg_color ||
578
+ this.current_bg_color !== bg_color_rgb ||
579
+ this.current_bg_layout !== this.options.layout
580
+ ) {
407
581
  this.current_bg_color = bg_color_rgb;
582
+ this.current_bg_layout = this.options.layout;
408
583
  do_animation = true;
409
584
  }
410
585
 
411
586
  if (do_animation) {
587
+ // Stop the in-flight fade only when replacing it: an early
588
+ // no-op call (same color, e.g. the empty reset at the top of
589
+ // goTo before the active slide fires background_change) must not
590
+ // kill the fade another call just started — stop() commits the
591
+ // partial opacity inline and the finish handler never runs, so
592
+ // the gradient below would never be applied and the panel would
593
+ // keep the opaque stylesheet fallback.
594
+ if (this.animator_background) {
595
+ this.animator_background.stop();
596
+ }
597
+
412
598
  // Figure out CSS
413
599
  if (this.options.layout === "landscape") {
414
600
  this._nav.next.setColor(false);
@@ -439,6 +625,8 @@ class StorySliderBase {
439
625
  } else {
440
626
  if (bg.color_value) {
441
627
  bg_css += "background-color:" + bg.color_value + ";";
628
+ } else if (dark) {
629
+ bg_css += "background-color:#222;";
442
630
  } else {
443
631
  bg_css += "background-color:#FFF;";
444
632
  }
@@ -455,7 +643,7 @@ class StorySliderBase {
455
643
  // FADE OUT IN
456
644
  this.animator_background = Animate(this._el.background, {
457
645
  opacity: 0,
458
- duration: this.options.duration / 2,
646
+ duration: prefersReducedMotion() ? 0 : this.options.duration / 2,
459
647
  easing: this.options.ease,
460
648
  complete: () => {
461
649
  this.fadeInBackground(bg_css);
@@ -475,14 +663,85 @@ class StorySliderBase {
475
663
 
476
664
  this.animator_background = Animate(this._el.background, {
477
665
  opacity: 1,
478
- duration: this.options.duration / 2,
666
+ duration: prefersReducedMotion() ? 0 : this.options.duration / 2,
479
667
  easing: this.options.ease,
668
+ complete: () => {
669
+ // Fold the end state into the inline style so the panel does
670
+ // not depend on a retained fill-forwards animation to stay
671
+ // visible: once the fill is dropped (cancel, GC) the element
672
+ // would snap back to the inline opacity:0 above.
673
+ this._el.background.style.opacity = "1";
674
+ this.animator_background?.stop();
675
+ this.animator_background = null;
676
+ },
480
677
  });
481
678
  }
482
679
 
483
680
  /* Private Methods
484
681
  ================================================== */
485
682
 
683
+ /** True in the stacked reading mode (`mode: "static"`): no strip translation. */
684
+ _isStatic(): boolean {
685
+ return (this.options as { mode?: unknown }).mode === "static";
686
+ }
687
+
688
+ /**
689
+ * Scroll-spy for the static reading mode: the most visible stacked slide
690
+ * becomes current, so the map follows the reading position. Programmatic
691
+ * scrolls set `_static_spying` while settling and are ignored, or the
692
+ * observer would echo them back.
693
+ */
694
+ _initStaticSpy(): void {
695
+ if (typeof IntersectionObserver === "undefined") return;
696
+ this._static_observer?.disconnect();
697
+ // the scrolling element is the observer root: the mask scrolls WITH
698
+ // the content (it is an ancestor chain member, not the scrollport),
699
+ // so intersections against it would never change
700
+ const root = this._isStatic() ? this._el.container : this._el.slider_container_mask;
701
+ this._static_observer = new IntersectionObserver(
702
+ (entries) => {
703
+ if (this._static_spying) return;
704
+ let best = -1;
705
+ let bestRatio = 0;
706
+ for (const entry of entries) {
707
+ const index = Number((entry.target as HTMLElement).dataset?.slideIndex ?? -1);
708
+ if (entry.isIntersecting && entry.intersectionRatio > bestRatio) {
709
+ best = index;
710
+ bestRatio = entry.intersectionRatio;
711
+ }
712
+ }
713
+ if (best >= 0 && best !== this.current_slide) {
714
+ this.goTo(best, true, false, true);
715
+ }
716
+ },
717
+ { root, threshold: [0, 0.25, 0.5, 0.75, 1] },
718
+ );
719
+ for (const child of Array.from(this._el.slider_item_container.children)) {
720
+ const index = [...this._el.slider_item_container.children].indexOf(child);
721
+ (child as HTMLElement).dataset.slideIndex = String(index);
722
+ this._static_observer.observe(child);
723
+ }
724
+ }
725
+
726
+ /** Scroll a stacked slide into view without moving the host page. */
727
+ _scrollSlideIntoView(n: number): void {
728
+ const slide = this._el.slider_item_container.children[n] as HTMLElement | undefined;
729
+ // the scrollport in static mode is the storyslider element itself
730
+ const scroller = this._isStatic() ? this._el.container : this._el.slider_container_mask;
731
+ if (!slide || !scroller || typeof slide.offsetTop !== "number") return;
732
+ const container = this._el.slider_item_container;
733
+ const top =
734
+ (typeof container.offsetTop === "number" ? container.offsetTop : 0) + slide.offsetTop;
735
+ try {
736
+ scroller.scrollTo({
737
+ top,
738
+ behavior: prefersReducedMotion() ? "auto" : "smooth",
739
+ });
740
+ } catch {
741
+ scroller.scrollTop = top;
742
+ }
743
+ }
744
+
486
745
  // Update Display
487
746
  _updateDisplay(width?: number, height?: number, animate?: unknown, layout?: string) {
488
747
  let _layout;
@@ -495,8 +754,6 @@ class StorySliderBase {
495
754
 
496
755
  this.options.layout = _layout;
497
756
 
498
- this.slide_spacing = this.options.width * 2;
499
-
500
757
  if (width) {
501
758
  this.options.width = width;
502
759
  } else {
@@ -509,15 +766,32 @@ class StorySliderBase {
509
766
  this.options.height = this._el.container.offsetHeight;
510
767
  }
511
768
 
769
+ // Slide positions and the goTo() translation are both derived from
770
+ // slide_spacing, so it has to be recomputed *after* the new width is
771
+ // known. Reading it before meant a bare updateDisplay() (no explicit
772
+ // width, i.e. after a container resize) positioned every slide for the
773
+ // previous width.
774
+ this.slide_spacing = this.options.width * 2;
775
+
512
776
  // position navigation
513
777
  const nav_pos = this.options.height / 2;
514
778
  this._nav.next.setPosition({ top: nav_pos });
515
779
  this._nav.previous.setPosition({ top: nav_pos });
516
780
 
517
781
  // Position slides
518
- for (let i = 0; i < this._slides.length; i++) {
519
- this._slides[i].updateDisplay(this.options.width, this.options.height, _layout);
520
- this._slides[i].setPosition({ left: this.slide_spacing * i, top: 0 });
782
+ if (this._isStatic()) {
783
+ // stacked reading mode: slides flow vertically (see .vco-static),
784
+ // so no strip positions — but keep the scroll-spy observing the
785
+ // current set of slides
786
+ for (let i = 0; i < this._slides.length; i++) {
787
+ this._slides[i].updateDisplay(this.options.width, this.options.height, _layout);
788
+ }
789
+ this._initStaticSpy();
790
+ } else {
791
+ for (let i = 0; i < this._slides.length; i++) {
792
+ this._slides[i].updateDisplay(this.options.width, this.options.height, _layout);
793
+ this._slides[i].setPosition({ left: this.slide_spacing * i, top: 0 });
794
+ }
521
795
  }
522
796
 
523
797
  // Go to the current slide
@@ -525,18 +799,19 @@ class StorySliderBase {
525
799
  }
526
800
 
527
801
  _introInterface() {
528
- if (this.options.call_to_action) {
529
- let _str = Language.messages.start;
530
- if (this.options.call_to_action_text !== "") {
531
- _str = this.options.call_to_action_text;
532
- }
533
- this._slides[0].addCallToAction(_str);
534
- this._slides[0].on("call_to_action", this.next, this);
535
- }
536
-
537
- if (this.options.width <= this.options.skinny_size) {
538
- // hidden when skinny
539
- } else {
802
+ if (this.options.call_to_action && this._slides.length > 0) {
803
+ // `!== ""` treated an absent key as a custom string, so a
804
+ // standalone StorySlider rendered the literal text "undefined".
805
+ const _str =
806
+ typeof this.options.call_to_action_text === "string" &&
807
+ this.options.call_to_action_text !== ""
808
+ ? this.options.call_to_action_text
809
+ : Language.messages.start;
810
+ this._slides[0]?.addCallToAction(_str);
811
+ this._slides[0]?.on("call_to_action", this.next, this);
812
+ }
813
+
814
+ if (!(this.options.width <= (this.options.skinny_size ?? 0))) {
540
815
  this._nav.next.updatePosition(
541
816
  { right: "130" },
542
817
  false,
@@ -560,6 +835,10 @@ class StorySliderBase {
560
835
  ================================================== */
561
836
  _initLayout() {
562
837
  this._el.container.className += " vco-storyslider";
838
+ // Static reading mode: stacked slides with scroll-spy navigation
839
+ if (this._isStatic()) {
840
+ this._el.container.classList.add("vco-static");
841
+ }
563
842
 
564
843
  // Create Layout
565
844
  this._el.slider_container_mask = Dom.create(
@@ -579,6 +858,12 @@ class StorySliderBase {
579
858
  this._el.slider_container,
580
859
  );
581
860
 
861
+ // Accessibility: a polite live region announcing slide changes to
862
+ // screen readers (visually hidden)
863
+ this._el.live_region = Dom.create("div", "vco-sr-only", this._el.container) as HTMLElement;
864
+ this._el.live_region.setAttribute("aria-live", "polite");
865
+ this._el.live_region.setAttribute("role", "status");
866
+
582
867
  // Update Size
583
868
  this.options.width = this._el.container.offsetWidth;
584
869
  this.options.height = this._el.container.offsetHeight;
@@ -611,11 +896,13 @@ class StorySliderBase {
611
896
  this._swipable.enable();
612
897
 
613
898
  // Message
899
+ // the swipe hint icon mirrors in right-to-left locales (issue #269)
900
+ const rtl = isRtl();
614
901
  this._message = new Message(
615
902
  {},
616
903
  {
617
904
  message_class: "vco-message-full",
618
- message_icon_class: "vco-icon-swipe-left",
905
+ message_icon_class: rtl ? "vco-icon-swipe-right" : "vco-icon-swipe-left",
619
906
  },
620
907
  );
621
908
  this._message.updateMessage(Language.buttons.swipe_to_navigate);
@@ -666,7 +953,7 @@ class StorySliderBase {
666
953
 
667
954
  _initData() {
668
955
  // Create Slides and then add them
669
- this._createSlides(this.data.slides);
956
+ this._createSlides(this.data.slides ?? []);
670
957
  }
671
958
 
672
959
  /* Events
@@ -685,13 +972,16 @@ class StorySliderBase {
685
972
  this.goTo(this.current_slide);
686
973
  }
687
974
 
688
- _onNavigation(e: { direction: string }) {
689
- if (e.direction === "next" || e.direction === "left") {
975
+ _onNavigation(e: { direction: string | null }) {
976
+ const direction = e.direction;
977
+ if (direction === "next" || direction === "left") {
690
978
  this.next();
691
- } else if (e.direction === "previous" || e.direction === "right") {
979
+ } else if (direction === "previous" || direction === "right") {
692
980
  this.previous();
981
+ } else {
982
+ return;
693
983
  }
694
- this.fire("nav_" + e.direction, this.data);
984
+ this.fire(`nav_${direction}`, this.data);
695
985
  }
696
986
 
697
987
  _onSlideAdded(e?: unknown) {
@@ -715,7 +1005,9 @@ class StorySliderBase {
715
1005
  }
716
1006
  }
717
1007
 
718
- export default class StorySlider extends Evented(StorySliderBase) {
1008
+ export default class StorySlider extends Evented<StorySliderEvents, typeof StorySliderBase>(
1009
+ StorySliderBase,
1010
+ ) {
719
1011
  constructor(...args: ConstructorParameters<typeof StorySliderBase>) {
720
1012
  super(...args);
721
1013
  }