@the-inclusionist/engine 10.0.0 → 11.0.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 (528) hide show
  1. package/README.md +32 -1
  2. package/app/css/style.css +216 -42
  3. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  4. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  5. package/app/public/vendor/fonts.css +11 -1175
  6. package/dist-pkg/boot/create-game.d.ts +84 -33
  7. package/dist-pkg/boot/create-game.js +708 -307
  8. package/dist-pkg/core/a11y-sr.d.ts +1 -1
  9. package/dist-pkg/core/a11y-sr.js +3 -5
  10. package/dist-pkg/core/accommodations.d.ts +26 -8
  11. package/dist-pkg/core/accommodations.js +27 -10
  12. package/dist-pkg/core/actions.d.ts +39 -10
  13. package/dist-pkg/core/actions.js +28 -6
  14. package/dist-pkg/core/contract.d.ts +0 -2
  15. package/dist-pkg/core/contract.js +0 -2
  16. package/dist-pkg/core/i18n.d.ts +36 -71
  17. package/dist-pkg/core/i18n.js +131 -198
  18. package/dist-pkg/core/session-clock.d.ts +23 -0
  19. package/dist-pkg/core/session-clock.js +37 -0
  20. package/dist-pkg/i18n/en.js +44 -49
  21. package/dist-pkg/i18n/es.js +44 -49
  22. package/dist-pkg/i18n/pt.js +49 -54
  23. package/dist-pkg/input/gamepad.d.ts +42 -11
  24. package/dist-pkg/input/gamepad.js +50 -15
  25. package/dist-pkg/input/key-default.d.ts +30 -0
  26. package/dist-pkg/input/key-default.js +60 -0
  27. package/dist-pkg/input/keyboard-runtime.d.ts +0 -4
  28. package/dist-pkg/input/keyboard.d.ts +0 -1
  29. package/dist-pkg/input/keydown.d.ts +5 -11
  30. package/dist-pkg/input/keydown.js +3 -3
  31. package/dist-pkg/input/latch-edge.d.ts +10 -2
  32. package/dist-pkg/input/latch-edge.js +4 -3
  33. package/dist-pkg/input/latch-scope.d.ts +27 -22
  34. package/dist-pkg/input/latch-scope.js +25 -37
  35. package/dist-pkg/input/latch-store.d.ts +9 -12
  36. package/dist-pkg/input/latch-store.js +13 -18
  37. package/dist-pkg/input/latch-sync.d.ts +5 -4
  38. package/dist-pkg/input/latch-sync.js +5 -5
  39. package/dist-pkg/input/pad-reading.js +7 -2
  40. package/dist-pkg/input/pad-wizard.d.ts +4 -1
  41. package/dist-pkg/input/pad-wizard.js +60 -9
  42. package/dist-pkg/input/switch-scan.d.ts +29 -12
  43. package/dist-pkg/input/switch-scan.js +15 -2
  44. package/dist-pkg/input/touch-bindings.d.ts +3 -6
  45. package/dist-pkg/input/touch.d.ts +17 -2
  46. package/dist-pkg/input/touch.js +55 -17
  47. package/dist-pkg/input/transport-in-use.d.ts +5 -5
  48. package/dist-pkg/input/transport-in-use.js +5 -5
  49. package/dist-pkg/input/transports.d.ts +0 -9
  50. package/dist-pkg/input/transports.js +1 -1
  51. package/dist-pkg/input/virtual-controller.d.ts +39 -3
  52. package/dist-pkg/input/virtual-controller.js +32 -4
  53. package/dist-pkg/input/voice-map.d.ts +27 -11
  54. package/dist-pkg/input/voice-map.js +41 -43
  55. package/dist-pkg/platform/audio-ambient.d.ts +0 -1
  56. package/dist-pkg/platform/audio-ambient.js +3 -1
  57. package/dist-pkg/platform/audio-mixer.js +4 -9
  58. package/dist-pkg/platform/audio-sonar.d.ts +8 -94
  59. package/dist-pkg/platform/audio-sonar.js +22 -207
  60. package/dist-pkg/platform/audio.d.ts +10 -1
  61. package/dist-pkg/platform/audio.js +35 -2
  62. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  63. package/dist-pkg/platform/choose-by-voice.js +157 -0
  64. package/dist-pkg/platform/font-library.d.ts +77 -0
  65. package/dist-pkg/platform/font-library.js +98 -0
  66. package/dist-pkg/platform/font-library.json +721 -0
  67. package/dist-pkg/platform/heavy-catalogue.d.ts +46 -0
  68. package/dist-pkg/platform/heavy-catalogue.js +47 -14
  69. package/dist-pkg/platform/heavy-mirror.d.ts +3 -9
  70. package/dist-pkg/platform/heavy-mirror.js +14 -17
  71. package/dist-pkg/platform/heavy.d.ts +40 -8
  72. package/dist-pkg/platform/heavy.js +177 -22
  73. package/dist-pkg/platform/interruptible-speech.d.ts +15 -8
  74. package/dist-pkg/platform/interruptible-speech.js +37 -13
  75. package/dist-pkg/platform/listener-scope.js +22 -13
  76. package/dist-pkg/platform/locale-host.d.ts +7 -3
  77. package/dist-pkg/platform/locale-host.js +13 -2
  78. package/dist-pkg/platform/reading-in-worker.d.ts +24 -0
  79. package/dist-pkg/platform/reading-in-worker.js +38 -0
  80. package/dist-pkg/platform/reading-model.d.ts +21 -0
  81. package/dist-pkg/platform/reading-model.js +25 -0
  82. package/dist-pkg/platform/reading-runtime.js +13 -8
  83. package/dist-pkg/platform/reading.d.ts +12 -1
  84. package/dist-pkg/platform/reading.js +9 -1
  85. package/dist-pkg/platform/speech-recognition.d.ts +10 -1
  86. package/dist-pkg/platform/speech-recognition.js +29 -9
  87. package/dist-pkg/platform/speech.d.ts +10 -1
  88. package/dist-pkg/platform/speech.js +24 -13
  89. package/dist-pkg/platform/tts.d.ts +37 -4
  90. package/dist-pkg/platform/tts.js +279 -57
  91. package/dist-pkg/platform/voice-listener.d.ts +6 -2
  92. package/dist-pkg/platform/voice-listener.js +1 -1
  93. package/dist-pkg/platform/voice-plan.d.ts +13 -0
  94. package/dist-pkg/platform/voice-plan.js +57 -2
  95. package/dist-pkg/platform/vosk-runtime.d.ts +25 -0
  96. package/dist-pkg/platform/vosk-runtime.js +59 -1
  97. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  98. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  99. package/dist-pkg/render/crt.d.ts +11 -9
  100. package/dist-pkg/render/crt.js +6 -10
  101. package/dist-pkg/render/cvd-matrices.d.ts +5 -1
  102. package/dist-pkg/render/cvd-matrices.js +5 -1
  103. package/dist-pkg/render/high-contrast.d.ts +1 -2
  104. package/dist-pkg/render/high-contrast.js +5 -1
  105. package/dist-pkg/render/viz-axes.d.ts +9 -0
  106. package/dist-pkg/render/viz-axes.js +15 -2
  107. package/dist-pkg/ui/aac-sets.d.ts +29 -24
  108. package/dist-pkg/ui/aac-sets.js +22 -30
  109. package/dist-pkg/ui/audio-choices.d.ts +10 -5
  110. package/dist-pkg/ui/audio-choices.js +14 -10
  111. package/dist-pkg/ui/camera-control.d.ts +47 -0
  112. package/dist-pkg/ui/camera-control.js +35 -1
  113. package/dist-pkg/ui/declared-words.d.ts +21 -0
  114. package/dist-pkg/ui/declared-words.js +66 -0
  115. package/dist-pkg/ui/drawing-problems.js +4 -3
  116. package/dist-pkg/ui/eye-control.js +17 -17
  117. package/dist-pkg/ui/face-control.js +15 -15
  118. package/dist-pkg/ui/fonts.d.ts +42 -8
  119. package/dist-pkg/ui/fonts.js +58 -24
  120. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  121. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  122. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  123. package/dist-pkg/ui/footer-scroll.js +55 -0
  124. package/dist-pkg/ui/game-options.d.ts +14 -9
  125. package/dist-pkg/ui/game-options.js +41 -21
  126. package/dist-pkg/ui/hand-control.js +15 -15
  127. package/dist-pkg/ui/help-panel.d.ts +19 -8
  128. package/dist-pkg/ui/help-panel.js +15 -5
  129. package/dist-pkg/ui/hud-bands.d.ts +29 -12
  130. package/dist-pkg/ui/hud-bands.js +63 -25
  131. package/dist-pkg/ui/hud-row.d.ts +34 -0
  132. package/dist-pkg/ui/hud-row.js +80 -0
  133. package/dist-pkg/ui/hud.d.ts +0 -3
  134. package/dist-pkg/ui/layout.js +5 -2
  135. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  136. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  137. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  138. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  139. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  140. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  141. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  142. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  143. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  144. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  145. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  146. package/dist-pkg/ui/libras-glosses.js +161 -0
  147. package/dist-pkg/ui/menu-intent.d.ts +29 -0
  148. package/dist-pkg/ui/menu-intent.js +35 -1
  149. package/dist-pkg/ui/menu-items.d.ts +10 -0
  150. package/dist-pkg/ui/menu-items.js +29 -0
  151. package/dist-pkg/ui/menu-nav.d.ts +40 -4
  152. package/dist-pkg/ui/menu-nav.js +132 -47
  153. package/dist-pkg/ui/panel-widgets.d.ts +34 -0
  154. package/dist-pkg/ui/panel-widgets.js +86 -0
  155. package/dist-pkg/ui/pause-icons.d.ts +30 -14
  156. package/dist-pkg/ui/pause-icons.js +106 -45
  157. package/dist-pkg/ui/scan-overlay.d.ts +3 -3
  158. package/dist-pkg/ui/scan-overlay.js +11 -3
  159. package/dist-pkg/ui/screen-text.d.ts +25 -0
  160. package/dist-pkg/ui/screen-text.js +152 -0
  161. package/dist-pkg/ui/session-clock.d.ts +32 -0
  162. package/dist-pkg/ui/session-clock.js +67 -0
  163. package/dist-pkg/ui/settings-aac.d.ts +3 -1
  164. package/dist-pkg/ui/settings-aac.js +32 -13
  165. package/dist-pkg/ui/settings-audio.d.ts +10 -5
  166. package/dist-pkg/ui/settings-audio.js +101 -35
  167. package/dist-pkg/ui/settings-controls.d.ts +0 -4
  168. package/dist-pkg/ui/settings-mobility.d.ts +3 -6
  169. package/dist-pkg/ui/settings-mobility.js +4 -46
  170. package/dist-pkg/ui/settings-motion.js +2 -2
  171. package/dist-pkg/ui/settings-panel.d.ts +10 -0
  172. package/dist-pkg/ui/settings-panel.js +25 -1
  173. package/dist-pkg/ui/settings-typo.d.ts +5 -6
  174. package/dist-pkg/ui/settings-typo.js +20 -11
  175. package/dist-pkg/ui/settings-visual.js +2 -2
  176. package/dist-pkg/ui/shell.d.ts +1 -3
  177. package/dist-pkg/ui/shell.js +8 -4
  178. package/dist-pkg/ui/title.d.ts +2 -11
  179. package/dist-pkg/ui/title.js +39 -6
  180. package/dist-pkg/ui/top-band.d.ts +5 -3
  181. package/dist-pkg/ui/top-band.js +21 -25
  182. package/dist-pkg/ui/typo-choices.d.ts +3 -3
  183. package/dist-pkg/ui/typo-choices.js +9 -8
  184. package/dist-pkg/ui/vlibras.d.ts +71 -27
  185. package/dist-pkg/ui/vlibras.js +116 -44
  186. package/dist-pkg/ui/voice-control.d.ts +23 -1
  187. package/dist-pkg/ui/voice-control.js +149 -16
  188. package/dist-pkg/ui/voice-settings.d.ts +2 -3
  189. package/dist-pkg/ui/voice-settings.js +53 -3
  190. package/dist-pkg/ui/where-the-child-is.js +2 -2
  191. package/docs/CREDITS.md +122 -10
  192. package/docs/LICENSES.md +36 -7
  193. package/package.json +34 -9
  194. package/scripts/check-cartridge.mjs +78 -0
  195. package/scripts/game-build.d.mts +25 -0
  196. package/scripts/game-build.mjs +144 -0
  197. package/scripts/heavy-into-the-delivery.mjs +284 -40
  198. package/scripts/libras-avatar.json +680 -0
  199. package/scripts/libras-avatar.mjs +246 -0
  200. package/scripts/libras-glosses/gloss.py +95 -0
  201. package/scripts/libras-glosses/pyproject.toml +32 -0
  202. package/scripts/libras-glosses/uv.lock +781 -0
  203. package/scripts/libras-glosses.mjs +351 -0
  204. package/scripts/licences/OFL-1.1.txt +86 -0
  205. package/scripts/licences/UFL-1.0.txt +96 -0
  206. package/scripts/licences/fonts.mjs +389 -0
  207. package/scripts/licences/third-party.mjs +35 -21
  208. package/app/public/vendor/fonts/bitter-var-ext.woff2 +0 -0
  209. package/app/public/vendor/fonts/bitter-var.woff2 +0 -0
  210. package/app/public/vendor/fonts/bodonimoda-var-ext.woff2 +0 -0
  211. package/app/public/vendor/fonts/bodonimoda-var.woff2 +0 -0
  212. package/app/public/vendor/fonts/cat-abril_fatface-400-ext.woff2 +0 -0
  213. package/app/public/vendor/fonts/cat-abril_fatface-400.woff2 +0 -0
  214. package/app/public/vendor/fonts/cat-adlam_display-400-ext.woff2 +0 -0
  215. package/app/public/vendor/fonts/cat-adlam_display-400.woff2 +0 -0
  216. package/app/public/vendor/fonts/cat-agu_display-400-ext.woff2 +0 -0
  217. package/app/public/vendor/fonts/cat-agu_display-400.woff2 +0 -0
  218. package/app/public/vendor/fonts/cat-alfa_slab_one-400-ext.woff2 +0 -0
  219. package/app/public/vendor/fonts/cat-alfa_slab_one-400.woff2 +0 -0
  220. package/app/public/vendor/fonts/cat-are_you_serious-400-ext.woff2 +0 -0
  221. package/app/public/vendor/fonts/cat-are_you_serious-400.woff2 +0 -0
  222. package/app/public/vendor/fonts/cat-asimovian-400-ext.woff2 +0 -0
  223. package/app/public/vendor/fonts/cat-asimovian-400.woff2 +0 -0
  224. package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400-ext.woff2 +0 -0
  225. package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400.woff2 +0 -0
  226. package/app/public/vendor/fonts/cat-bakbak_one-400-ext.woff2 +0 -0
  227. package/app/public/vendor/fonts/cat-bakbak_one-400.woff2 +0 -0
  228. package/app/public/vendor/fonts/cat-bangers-400-ext.woff2 +0 -0
  229. package/app/public/vendor/fonts/cat-bangers-400.woff2 +0 -0
  230. package/app/public/vendor/fonts/cat-barriecito-400-ext.woff2 +0 -0
  231. package/app/public/vendor/fonts/cat-barriecito-400.woff2 +0 -0
  232. package/app/public/vendor/fonts/cat-berkshire_swash-400-ext.woff2 +0 -0
  233. package/app/public/vendor/fonts/cat-berkshire_swash-400.woff2 +0 -0
  234. package/app/public/vendor/fonts/cat-bevan-400-ext.woff2 +0 -0
  235. package/app/public/vendor/fonts/cat-bevan-400.woff2 +0 -0
  236. package/app/public/vendor/fonts/cat-bitcount-400-ext.woff2 +0 -0
  237. package/app/public/vendor/fonts/cat-bitcount-400.woff2 +0 -0
  238. package/app/public/vendor/fonts/cat-bowlby_one_sc-400-ext.woff2 +0 -0
  239. package/app/public/vendor/fonts/cat-bowlby_one_sc-400.woff2 +0 -0
  240. package/app/public/vendor/fonts/cat-bungee_shade-400-ext.woff2 +0 -0
  241. package/app/public/vendor/fonts/cat-bungee_shade-400.woff2 +0 -0
  242. package/app/public/vendor/fonts/cat-charm-400-ext.woff2 +0 -0
  243. package/app/public/vendor/fonts/cat-charm-400.woff2 +0 -0
  244. package/app/public/vendor/fonts/cat-charm-700-ext.woff2 +0 -0
  245. package/app/public/vendor/fonts/cat-charm-700.woff2 +0 -0
  246. package/app/public/vendor/fonts/cat-cherry_bomb_one-400-ext.woff2 +0 -0
  247. package/app/public/vendor/fonts/cat-cherry_bomb_one-400.woff2 +0 -0
  248. package/app/public/vendor/fonts/cat-chokokutai-400-ext.woff2 +0 -0
  249. package/app/public/vendor/fonts/cat-chokokutai-400.woff2 +0 -0
  250. package/app/public/vendor/fonts/cat-chonburi-400-ext.woff2 +0 -0
  251. package/app/public/vendor/fonts/cat-chonburi-400.woff2 +0 -0
  252. package/app/public/vendor/fonts/cat-climate_crisis-400-ext.woff2 +0 -0
  253. package/app/public/vendor/fonts/cat-climate_crisis-400.woff2 +0 -0
  254. package/app/public/vendor/fonts/cat-cookie-400.woff2 +0 -0
  255. package/app/public/vendor/fonts/cat-dela_gothic_one-400-ext.woff2 +0 -0
  256. package/app/public/vendor/fonts/cat-dela_gothic_one-400.woff2 +0 -0
  257. package/app/public/vendor/fonts/cat-fascinate_inline-400-ext.woff2 +0 -0
  258. package/app/public/vendor/fonts/cat-fascinate_inline-400.woff2 +0 -0
  259. package/app/public/vendor/fonts/cat-ga_maamli-400-ext.woff2 +0 -0
  260. package/app/public/vendor/fonts/cat-ga_maamli-400.woff2 +0 -0
  261. package/app/public/vendor/fonts/cat-itim-400-ext.woff2 +0 -0
  262. package/app/public/vendor/fonts/cat-itim-400.woff2 +0 -0
  263. package/app/public/vendor/fonts/cat-jacquard_24-400-ext.woff2 +0 -0
  264. package/app/public/vendor/fonts/cat-jacquard_24-400.woff2 +0 -0
  265. package/app/public/vendor/fonts/cat-kablammo-400-ext.woff2 +0 -0
  266. package/app/public/vendor/fonts/cat-kablammo-400.woff2 +0 -0
  267. package/app/public/vendor/fonts/cat-kalam-400-ext.woff2 +0 -0
  268. package/app/public/vendor/fonts/cat-kalam-400.woff2 +0 -0
  269. package/app/public/vendor/fonts/cat-kalam-700-ext.woff2 +0 -0
  270. package/app/public/vendor/fonts/cat-kalam-700.woff2 +0 -0
  271. package/app/public/vendor/fonts/cat-katibeh-400-ext.woff2 +0 -0
  272. package/app/public/vendor/fonts/cat-katibeh-400.woff2 +0 -0
  273. package/app/public/vendor/fonts/cat-lemonada-400-ext.woff2 +0 -0
  274. package/app/public/vendor/fonts/cat-lemonada-400.woff2 +0 -0
  275. package/app/public/vendor/fonts/cat-lilita_one-400-ext.woff2 +0 -0
  276. package/app/public/vendor/fonts/cat-lilita_one-400.woff2 +0 -0
  277. package/app/public/vendor/fonts/cat-lobster-400-ext.woff2 +0 -0
  278. package/app/public/vendor/fonts/cat-lobster-400.woff2 +0 -0
  279. package/app/public/vendor/fonts/cat-luckiest_guy-400-ext.woff2 +0 -0
  280. package/app/public/vendor/fonts/cat-luckiest_guy-400.woff2 +0 -0
  281. package/app/public/vendor/fonts/cat-marhey-400-ext.woff2 +0 -0
  282. package/app/public/vendor/fonts/cat-marhey-400.woff2 +0 -0
  283. package/app/public/vendor/fonts/cat-modak-400-ext.woff2 +0 -0
  284. package/app/public/vendor/fonts/cat-modak-400.woff2 +0 -0
  285. package/app/public/vendor/fonts/cat-momo_signature-400-ext.woff2 +0 -0
  286. package/app/public/vendor/fonts/cat-momo_signature-400.woff2 +0 -0
  287. package/app/public/vendor/fonts/cat-monofett-400-ext.woff2 +0 -0
  288. package/app/public/vendor/fonts/cat-monofett-400.woff2 +0 -0
  289. package/app/public/vendor/fonts/cat-monomakh-400-ext.woff2 +0 -0
  290. package/app/public/vendor/fonts/cat-monomakh-400.woff2 +0 -0
  291. package/app/public/vendor/fonts/cat-monoton-400-ext.woff2 +0 -0
  292. package/app/public/vendor/fonts/cat-monoton-400.woff2 +0 -0
  293. package/app/public/vendor/fonts/cat-nerko_one-400-ext.woff2 +0 -0
  294. package/app/public/vendor/fonts/cat-nerko_one-400.woff2 +0 -0
  295. package/app/public/vendor/fonts/cat-noto_sans_adlam-400-ext.woff2 +0 -0
  296. package/app/public/vendor/fonts/cat-noto_sans_adlam-400.woff2 +0 -0
  297. package/app/public/vendor/fonts/cat-noto_sans_arabic-400-ext.woff2 +0 -0
  298. package/app/public/vendor/fonts/cat-noto_sans_arabic-400.woff2 +0 -0
  299. package/app/public/vendor/fonts/cat-noto_sans_devanagari-400-ext.woff2 +0 -0
  300. package/app/public/vendor/fonts/cat-noto_sans_devanagari-400.woff2 +0 -0
  301. package/app/public/vendor/fonts/cat-noto_sans_hebrew-400-ext.woff2 +0 -0
  302. package/app/public/vendor/fonts/cat-noto_sans_hebrew-400.woff2 +0 -0
  303. package/app/public/vendor/fonts/cat-noto_sans_jp-400-ext.woff2 +0 -0
  304. package/app/public/vendor/fonts/cat-noto_sans_jp-400.woff2 +0 -0
  305. package/app/public/vendor/fonts/cat-noto_sans_khmer-400-ext.woff2 +0 -0
  306. package/app/public/vendor/fonts/cat-noto_sans_khmer-400.woff2 +0 -0
  307. package/app/public/vendor/fonts/cat-noto_sans_kr-400-ext.woff2 +0 -0
  308. package/app/public/vendor/fonts/cat-noto_sans_kr-400.woff2 +0 -0
  309. package/app/public/vendor/fonts/cat-noto_sans_sc-400-ext.woff2 +0 -0
  310. package/app/public/vendor/fonts/cat-noto_sans_sc-400.woff2 +0 -0
  311. package/app/public/vendor/fonts/cat-noto_sans_thai-400-ext.woff2 +0 -0
  312. package/app/public/vendor/fonts/cat-noto_sans_thai-400.woff2 +0 -0
  313. package/app/public/vendor/fonts/cat-ole-400-ext.woff2 +0 -0
  314. package/app/public/vendor/fonts/cat-ole-400.woff2 +0 -0
  315. package/app/public/vendor/fonts/cat-pacifico-400-ext.woff2 +0 -0
  316. package/app/public/vendor/fonts/cat-pacifico-400.woff2 +0 -0
  317. package/app/public/vendor/fonts/cat-patrick_hand-400-ext.woff2 +0 -0
  318. package/app/public/vendor/fonts/cat-patrick_hand-400.woff2 +0 -0
  319. package/app/public/vendor/fonts/cat-petit_formal_script-400-ext.woff2 +0 -0
  320. package/app/public/vendor/fonts/cat-petit_formal_script-400.woff2 +0 -0
  321. package/app/public/vendor/fonts/cat-pixelify_sans-400-ext.woff2 +0 -0
  322. package/app/public/vendor/fonts/cat-pixelify_sans-400.woff2 +0 -0
  323. package/app/public/vendor/fonts/cat-plaster-400-ext.woff2 +0 -0
  324. package/app/public/vendor/fonts/cat-plaster-400.woff2 +0 -0
  325. package/app/public/vendor/fonts/cat-playwrite_ar_guides-400-0.woff2 +0 -0
  326. package/app/public/vendor/fonts/cat-playwrite_at-400-0.woff2 +0 -0
  327. package/app/public/vendor/fonts/cat-playwrite_at_guides-400-0.woff2 +0 -0
  328. package/app/public/vendor/fonts/cat-playwrite_au_nsw-400-0.woff2 +0 -0
  329. package/app/public/vendor/fonts/cat-playwrite_au_nsw_guides-400-0.woff2 +0 -0
  330. package/app/public/vendor/fonts/cat-playwrite_au_qld-400-0.woff2 +0 -0
  331. package/app/public/vendor/fonts/cat-playwrite_au_qld_guides-400-0.woff2 +0 -0
  332. package/app/public/vendor/fonts/cat-playwrite_au_sa-400-0.woff2 +0 -0
  333. package/app/public/vendor/fonts/cat-playwrite_au_sa_guides-400-0.woff2 +0 -0
  334. package/app/public/vendor/fonts/cat-playwrite_au_tas-400-0.woff2 +0 -0
  335. package/app/public/vendor/fonts/cat-playwrite_au_tas_guides-400-0.woff2 +0 -0
  336. package/app/public/vendor/fonts/cat-playwrite_au_vic-400-0.woff2 +0 -0
  337. package/app/public/vendor/fonts/cat-playwrite_au_vic_guides-400-0.woff2 +0 -0
  338. package/app/public/vendor/fonts/cat-playwrite_be_vlg-400-0.woff2 +0 -0
  339. package/app/public/vendor/fonts/cat-playwrite_be_vlg_guides-400-0.woff2 +0 -0
  340. package/app/public/vendor/fonts/cat-playwrite_be_wal-400-0.woff2 +0 -0
  341. package/app/public/vendor/fonts/cat-playwrite_be_wal_guides-400-0.woff2 +0 -0
  342. package/app/public/vendor/fonts/cat-playwrite_br_guides-400-0.woff2 +0 -0
  343. package/app/public/vendor/fonts/cat-playwrite_ca_guides-400-0.woff2 +0 -0
  344. package/app/public/vendor/fonts/cat-playwrite_cl_guides-400-0.woff2 +0 -0
  345. package/app/public/vendor/fonts/cat-playwrite_co_guides-400-0.woff2 +0 -0
  346. package/app/public/vendor/fonts/cat-playwrite_cu_guides-400-0.woff2 +0 -0
  347. package/app/public/vendor/fonts/cat-playwrite_cz-400-0.woff2 +0 -0
  348. package/app/public/vendor/fonts/cat-playwrite_cz_guides-400-0.woff2 +0 -0
  349. package/app/public/vendor/fonts/cat-playwrite_de_grund-400-0.woff2 +0 -0
  350. package/app/public/vendor/fonts/cat-playwrite_de_grund_guides-400-0.woff2 +0 -0
  351. package/app/public/vendor/fonts/cat-playwrite_de_la-400-0.woff2 +0 -0
  352. package/app/public/vendor/fonts/cat-playwrite_de_la_guides-400-0.woff2 +0 -0
  353. package/app/public/vendor/fonts/cat-playwrite_de_sas-400-0.woff2 +0 -0
  354. package/app/public/vendor/fonts/cat-playwrite_de_sas_guides-400-0.woff2 +0 -0
  355. package/app/public/vendor/fonts/cat-playwrite_de_va-400-0.woff2 +0 -0
  356. package/app/public/vendor/fonts/cat-playwrite_de_va_guides-400-0.woff2 +0 -0
  357. package/app/public/vendor/fonts/cat-playwrite_dk_loopet-400-0.woff2 +0 -0
  358. package/app/public/vendor/fonts/cat-playwrite_dk_loopet_guides-400-0.woff2 +0 -0
  359. package/app/public/vendor/fonts/cat-playwrite_dk_uloopet-400-0.woff2 +0 -0
  360. package/app/public/vendor/fonts/cat-playwrite_dk_uloopet_guides-400-0.woff2 +0 -0
  361. package/app/public/vendor/fonts/cat-playwrite_es_deco_guides-400-0.woff2 +0 -0
  362. package/app/public/vendor/fonts/cat-playwrite_es_guides-400-0.woff2 +0 -0
  363. package/app/public/vendor/fonts/cat-playwrite_fr_moderne-400-0.woff2 +0 -0
  364. package/app/public/vendor/fonts/cat-playwrite_fr_moderne_guides-400-0.woff2 +0 -0
  365. package/app/public/vendor/fonts/cat-playwrite_fr_trad-400-0.woff2 +0 -0
  366. package/app/public/vendor/fonts/cat-playwrite_fr_trad_guides-400-0.woff2 +0 -0
  367. package/app/public/vendor/fonts/cat-playwrite_gb_j_guides-400-0.woff2 +0 -0
  368. package/app/public/vendor/fonts/cat-playwrite_gb_s_guides-400-0.woff2 +0 -0
  369. package/app/public/vendor/fonts/cat-playwrite_hr-400-0.woff2 +0 -0
  370. package/app/public/vendor/fonts/cat-playwrite_hr_guides-400-0.woff2 +0 -0
  371. package/app/public/vendor/fonts/cat-playwrite_hr_lijeva-400-0.woff2 +0 -0
  372. package/app/public/vendor/fonts/cat-playwrite_hr_lijeva_guides-400-0.woff2 +0 -0
  373. package/app/public/vendor/fonts/cat-playwrite_hu-400-0.woff2 +0 -0
  374. package/app/public/vendor/fonts/cat-playwrite_hu_guides-400-0.woff2 +0 -0
  375. package/app/public/vendor/fonts/cat-playwrite_id-400-0.woff2 +0 -0
  376. package/app/public/vendor/fonts/cat-playwrite_id_guides-400-0.woff2 +0 -0
  377. package/app/public/vendor/fonts/cat-playwrite_ie-400-0.woff2 +0 -0
  378. package/app/public/vendor/fonts/cat-playwrite_ie_guides-400-0.woff2 +0 -0
  379. package/app/public/vendor/fonts/cat-playwrite_in-400-0.woff2 +0 -0
  380. package/app/public/vendor/fonts/cat-playwrite_in_guides-400-0.woff2 +0 -0
  381. package/app/public/vendor/fonts/cat-playwrite_is-400-0.woff2 +0 -0
  382. package/app/public/vendor/fonts/cat-playwrite_is_guides-400-0.woff2 +0 -0
  383. package/app/public/vendor/fonts/cat-playwrite_it_moderna-400-0.woff2 +0 -0
  384. package/app/public/vendor/fonts/cat-playwrite_it_moderna_guides-400-0.woff2 +0 -0
  385. package/app/public/vendor/fonts/cat-playwrite_it_trad-400-0.woff2 +0 -0
  386. package/app/public/vendor/fonts/cat-playwrite_it_trad_guides-400-0.woff2 +0 -0
  387. package/app/public/vendor/fonts/cat-playwrite_mx_guides-400-0.woff2 +0 -0
  388. package/app/public/vendor/fonts/cat-playwrite_ng_modern-400-0.woff2 +0 -0
  389. package/app/public/vendor/fonts/cat-playwrite_ng_modern_guides-400-0.woff2 +0 -0
  390. package/app/public/vendor/fonts/cat-playwrite_nl-400-0.woff2 +0 -0
  391. package/app/public/vendor/fonts/cat-playwrite_nl_guides-400-0.woff2 +0 -0
  392. package/app/public/vendor/fonts/cat-playwrite_no-400-0.woff2 +0 -0
  393. package/app/public/vendor/fonts/cat-playwrite_no_guides-400-0.woff2 +0 -0
  394. package/app/public/vendor/fonts/cat-playwrite_nz-400-0.woff2 +0 -0
  395. package/app/public/vendor/fonts/cat-playwrite_nz_basic-400-0.woff2 +0 -0
  396. package/app/public/vendor/fonts/cat-playwrite_nz_basic_guides-400-0.woff2 +0 -0
  397. package/app/public/vendor/fonts/cat-playwrite_nz_guides-400-0.woff2 +0 -0
  398. package/app/public/vendor/fonts/cat-playwrite_pe_guides-400-0.woff2 +0 -0
  399. package/app/public/vendor/fonts/cat-playwrite_pl-400-0.woff2 +0 -0
  400. package/app/public/vendor/fonts/cat-playwrite_pl_guides-400-0.woff2 +0 -0
  401. package/app/public/vendor/fonts/cat-playwrite_pt_guides-400-0.woff2 +0 -0
  402. package/app/public/vendor/fonts/cat-playwrite_ro-400-0.woff2 +0 -0
  403. package/app/public/vendor/fonts/cat-playwrite_ro_guides-400-0.woff2 +0 -0
  404. package/app/public/vendor/fonts/cat-playwrite_sk-400-0.woff2 +0 -0
  405. package/app/public/vendor/fonts/cat-playwrite_sk_guides-400-0.woff2 +0 -0
  406. package/app/public/vendor/fonts/cat-playwrite_tz-400-0.woff2 +0 -0
  407. package/app/public/vendor/fonts/cat-playwrite_tz_guides-400-0.woff2 +0 -0
  408. package/app/public/vendor/fonts/cat-playwrite_us_modern_guides-400-0.woff2 +0 -0
  409. package/app/public/vendor/fonts/cat-playwrite_us_trad_guides-400-0.woff2 +0 -0
  410. package/app/public/vendor/fonts/cat-playwrite_vn-400-0.woff2 +0 -0
  411. package/app/public/vendor/fonts/cat-playwrite_vn_guides-400-0.woff2 +0 -0
  412. package/app/public/vendor/fonts/cat-playwrite_za-400-0.woff2 +0 -0
  413. package/app/public/vendor/fonts/cat-playwrite_za_guides-400-0.woff2 +0 -0
  414. package/app/public/vendor/fonts/cat-potta_one-400-ext.woff2 +0 -0
  415. package/app/public/vendor/fonts/cat-potta_one-400.woff2 +0 -0
  416. package/app/public/vendor/fonts/cat-ranchers-400-ext.woff2 +0 -0
  417. package/app/public/vendor/fonts/cat-ranchers-400.woff2 +0 -0
  418. package/app/public/vendor/fonts/cat-ranga-400-ext.woff2 +0 -0
  419. package/app/public/vendor/fonts/cat-ranga-400.woff2 +0 -0
  420. package/app/public/vendor/fonts/cat-ranga-700-ext.woff2 +0 -0
  421. package/app/public/vendor/fonts/cat-ranga-700.woff2 +0 -0
  422. package/app/public/vendor/fonts/cat-risque-400-ext.woff2 +0 -0
  423. package/app/public/vendor/fonts/cat-risque-400.woff2 +0 -0
  424. package/app/public/vendor/fonts/cat-rowdies-400-ext.woff2 +0 -0
  425. package/app/public/vendor/fonts/cat-rowdies-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/cat-rowdies-700-ext.woff2 +0 -0
  427. package/app/public/vendor/fonts/cat-rowdies-700.woff2 +0 -0
  428. package/app/public/vendor/fonts/cat-ruge_boogie-400-ext.woff2 +0 -0
  429. package/app/public/vendor/fonts/cat-ruge_boogie-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/cat-ruslan_display-400-ext.woff2 +0 -0
  431. package/app/public/vendor/fonts/cat-ruslan_display-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/cat-sacramento-400-ext.woff2 +0 -0
  433. package/app/public/vendor/fonts/cat-sacramento-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/cat-sancreek-400-ext.woff2 +0 -0
  435. package/app/public/vendor/fonts/cat-sancreek-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/cat-sankofa_display-400-ext.woff2 +0 -0
  437. package/app/public/vendor/fonts/cat-sankofa_display-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/cat-sedgwick_ave_display-400-ext.woff2 +0 -0
  439. package/app/public/vendor/fonts/cat-sedgwick_ave_display-400.woff2 +0 -0
  440. package/app/public/vendor/fonts/cat-shantell_sans-400-ext.woff2 +0 -0
  441. package/app/public/vendor/fonts/cat-shantell_sans-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/cat-smokum-400-ext.woff2 +0 -0
  443. package/app/public/vendor/fonts/cat-smokum-400.woff2 +0 -0
  444. package/app/public/vendor/fonts/cat-solitreo-400-ext.woff2 +0 -0
  445. package/app/public/vendor/fonts/cat-solitreo-400.woff2 +0 -0
  446. package/app/public/vendor/fonts/cat-spicy_rice-400-ext.woff2 +0 -0
  447. package/app/public/vendor/fonts/cat-spicy_rice-400.woff2 +0 -0
  448. package/app/public/vendor/fonts/cat-sriracha-400-ext.woff2 +0 -0
  449. package/app/public/vendor/fonts/cat-sriracha-400.woff2 +0 -0
  450. package/app/public/vendor/fonts/cat-srisakdi-400-ext.woff2 +0 -0
  451. package/app/public/vendor/fonts/cat-srisakdi-400.woff2 +0 -0
  452. package/app/public/vendor/fonts/cat-srisakdi-700-ext.woff2 +0 -0
  453. package/app/public/vendor/fonts/cat-srisakdi-700.woff2 +0 -0
  454. package/app/public/vendor/fonts/cat-stix_two_math-400-0.woff2 +0 -0
  455. package/app/public/vendor/fonts/cat-tillana-400-ext.woff2 +0 -0
  456. package/app/public/vendor/fonts/cat-tillana-400.woff2 +0 -0
  457. package/app/public/vendor/fonts/cat-tillana-700-ext.woff2 +0 -0
  458. package/app/public/vendor/fonts/cat-tillana-700.woff2 +0 -0
  459. package/app/public/vendor/fonts/cat-titan_one-400-ext.woff2 +0 -0
  460. package/app/public/vendor/fonts/cat-titan_one-400.woff2 +0 -0
  461. package/app/public/vendor/fonts/cat-yatra_one-400-ext.woff2 +0 -0
  462. package/app/public/vendor/fonts/cat-yatra_one-400.woff2 +0 -0
  463. package/app/public/vendor/fonts/cat-yomogi-400-ext.woff2 +0 -0
  464. package/app/public/vendor/fonts/cat-yomogi-400.woff2 +0 -0
  465. package/app/public/vendor/fonts/dmserifdisplay-400-ext.woff2 +0 -0
  466. package/app/public/vendor/fonts/dmserifdisplay-400.woff2 +0 -0
  467. package/app/public/vendor/fonts/domine-var-ext.woff2 +0 -0
  468. package/app/public/vendor/fonts/domine-var.woff2 +0 -0
  469. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  470. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  471. package/app/public/vendor/fonts/fraunces-var-ext.woff2 +0 -0
  472. package/app/public/vendor/fonts/fraunces-var.woff2 +0 -0
  473. package/app/public/vendor/fonts/fredoka-var-ext.woff2 +0 -0
  474. package/app/public/vendor/fonts/fredoka-var.woff2 +0 -0
  475. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  476. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  477. package/app/public/vendor/fonts/jakarta-var-ext.woff2 +0 -0
  478. package/app/public/vendor/fonts/jakarta-var.woff2 +0 -0
  479. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  480. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  481. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  482. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  483. package/app/public/vendor/fonts/lora-var-ext.woff2 +0 -0
  484. package/app/public/vendor/fonts/lora-var.woff2 +0 -0
  485. package/app/public/vendor/fonts/merriweather-var-ext.woff2 +0 -0
  486. package/app/public/vendor/fonts/merriweather-var.woff2 +0 -0
  487. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  488. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  489. package/app/public/vendor/fonts/notosans-var-ext.woff2 +0 -0
  490. package/app/public/vendor/fonts/notosans-var.woff2 +0 -0
  491. package/app/public/vendor/fonts/nunito-var-ext.woff2 +0 -0
  492. package/app/public/vendor/fonts/nunito-var.woff2 +0 -0
  493. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  494. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  495. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  496. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  497. package/app/public/vendor/fonts/playfair-var-ext.woff2 +0 -0
  498. package/app/public/vendor/fonts/playfair-var.woff2 +0 -0
  499. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  500. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  501. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  502. package/app/public/vendor/fonts/quicksand-var-ext.woff2 +0 -0
  503. package/app/public/vendor/fonts/quicksand-var.woff2 +0 -0
  504. package/app/public/vendor/fonts/robotoflex-var-ext.woff2 +0 -0
  505. package/app/public/vendor/fonts/robotoflex-var.woff2 +0 -0
  506. package/app/public/vendor/fonts/sora-var-ext.woff2 +0 -0
  507. package/app/public/vendor/fonts/sora-var.woff2 +0 -0
  508. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  509. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  510. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  511. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  512. package/app/public/vendor/fonts/spacegrotesk-var-ext.woff2 +0 -0
  513. package/app/public/vendor/fonts/spacegrotesk-var.woff2 +0 -0
  514. package/app/public/vendor/fonts/spectral-400-ext.woff2 +0 -0
  515. package/app/public/vendor/fonts/spectral-400.woff2 +0 -0
  516. package/app/public/vendor/fonts/spectral-700-ext.woff2 +0 -0
  517. package/app/public/vendor/fonts/spectral-700.woff2 +0 -0
  518. package/app/public/vendor/fonts/teachers-var-ext.woff2 +0 -0
  519. package/app/public/vendor/fonts/teachers-var.woff2 +0 -0
  520. package/app/public/vendor/fonts/ubuntu-400-ext.woff2 +0 -0
  521. package/app/public/vendor/fonts/ubuntu-400.woff2 +0 -0
  522. package/app/public/vendor/fonts/ubuntu-700-ext.woff2 +0 -0
  523. package/app/public/vendor/fonts/ubuntu-700.woff2 +0 -0
  524. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  525. package/dist-pkg/platform/guide-intensity.d.ts +0 -39
  526. package/dist-pkg/platform/guide-intensity.js +0 -71
  527. package/dist-pkg/ui/latch-refusal.d.ts +0 -33
  528. package/dist-pkg/ui/latch-refusal.js +0 -60
@@ -0,0 +1,134 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // ui/libras-avatar-load — WHAT THE DELIVERY SHIPPED FOR THE FREE PLAYER, AND OPENING IT (ADR-0234, route B, phase B2).
3
+ //
4
+ // The half of `ui/libras-avatar-player` that talks to the delivery: where its files are, whether it shipped the avatar at all
5
+ // (its manifest, which only `inclusionist-heavy --libras` writes), the canvas the avatar is drawn on, the stage built on it from
6
+ // the avatar's bytes — within a time, or not at all — and the clips, each fetched and prepared once. Every answer is a value,
7
+ // never a throw: a delivery without the avatar, a device without WebGL and a clip that cannot be read are reasons, which the
8
+ // player hands to deaf mode and deaf mode to `problems` (ADR-0169).
9
+ import { LIBRAS_GLOSSES_FILE } from './libras-glosses.js';
10
+ import { LIBRAS_NOT_INSTALLED } from './vlibras.js';
11
+ import { LIBRAS_AVATAR_FOLDER, LIBRAS_AVATAR_MANIFEST, avatarManifestOf } from './libras-avatar-plan.js';
12
+ /**
13
+ * Why a delivery with no avatar cannot sign, and the fix (ADR-0169): the reason `NO_INTERPRETER` gives, word for word — the
14
+ * root's interpreter answers a delivery built without `--libras` exactly as a root with no player would.
15
+ */
16
+ export const NOT_SHIPPED = LIBRAS_NOT_INSTALLED;
17
+ /** Why a request that waited across a `hide()` or the root's end was not signed. */
18
+ export const RELEASED = 'the interpreter was taken off the screen before it signed';
19
+ /** The addresses under `base`, or `null` where it resolves nothing — a host whose document has no address finds no avatar. */
20
+ export function avatarPlace(base, folder = LIBRAS_AVATAR_FOLDER) {
21
+ try {
22
+ const at = new URL(folder, base);
23
+ return { folder: at.href, manifest: new URL(LIBRAS_AVATAR_MANIFEST, at).href, glosses: new URL(LIBRAS_GLOSSES_FILE, at).href };
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ /** A JSON file of the delivery, or `null` — no fetch, no file, not JSON. */
30
+ async function readJson(fetchFile, url) {
31
+ if (!fetchFile)
32
+ return null;
33
+ try {
34
+ const resp = await fetchFile(url);
35
+ return resp.ok ? await resp.json() : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /** The delivery's manifest, or `null` for a delivery that did not ship the avatar. */
42
+ export const readManifest = async (fetchFile, place) => avatarManifestOf(await readJson(fetchFile, place.manifest));
43
+ /** The canvas the avatar is drawn on: the bottom right, in front of the screen, watched and never operated. */
44
+ export function avatarCanvas(doc, title) {
45
+ const canvas = doc.createElement('canvas');
46
+ canvas.setAttribute('role', 'img');
47
+ canvas.setAttribute('aria-label', title);
48
+ canvas.tabIndex = -1; // the keyboard stays with the game
49
+ canvas.hidden = true;
50
+ Object.assign(canvas.style, {
51
+ position: 'fixed', right: '0', bottom: '0', width: 'max(25vw, 200px)', height: 'max(50vh, 200px)', border: '0',
52
+ background: 'transparent', pointerEvents: 'none', zIndex: '2147483000',
53
+ });
54
+ doc.body.append(canvas);
55
+ return canvas;
56
+ }
57
+ const reasonOf = (failure) => (failure instanceof Error ? failure.message : String(failure));
58
+ async function build(canvas, o, wanted) {
59
+ const { fetchFile } = o; // called bare, as `FetchFile` says
60
+ if (!fetchFile)
61
+ return { reason: NOT_SHIPPED };
62
+ try {
63
+ const resp = await fetchFile(o.avatarUrl);
64
+ if (!resp.ok) {
65
+ return { reason: `the Libras avatar could not be read from the delivery (HTTP ${resp.status}) — build it again with `
66
+ + '`inclusionist-heavy <folder> --libras`' };
67
+ }
68
+ const stage = await o.loadStage(canvas, await resp.arrayBuffer());
69
+ if (!wanted()) {
70
+ stage.dispose();
71
+ return { reason: RELEASED };
72
+ } // given up on or released meanwhile: nothing is kept
73
+ return { stage };
74
+ }
75
+ catch (failure) {
76
+ return { reason: `the Libras avatar cannot be drawn here: ${reasonOf(failure)}` };
77
+ }
78
+ }
79
+ /**
80
+ * Builds the stage on `canvas` from the delivery's avatar: the stage, or why not — an avatar the delivery cannot give, a device
81
+ * that cannot draw it, a load past `timeoutMs`. `wanted()` is asked when the stage arrives: false, and it is released at once.
82
+ * `cancel()` answers «released» now and clears the timer, so nothing of a released root outlives it.
83
+ */
84
+ export function openAvatar(canvas, o, wanted) {
85
+ let answer = () => { };
86
+ const stopped = new Promise((resolve) => { answer = resolve; });
87
+ const timer = o.win.setTimeout(() => {
88
+ answer({ reason: `the Libras avatar did not load within ${Math.round(o.timeoutMs / 1000)} s` });
89
+ }, o.timeoutMs);
90
+ const done = Promise.race([build(canvas, o, wanted), stopped]).then((r) => { o.win.clearTimeout(timer); return r; });
91
+ return { done, cancel: () => { o.win.clearTimeout(timer); answer({ reason: RELEASED }); } };
92
+ }
93
+ const isClipJson = (data) => {
94
+ const c = data;
95
+ return !!c && typeof c.duration === 'number' && Array.isArray(c.tracks);
96
+ };
97
+ /**
98
+ * A clip's address under the avatar's folder, SPELLED AS A URL SPELLS ITS NAME — which is the address the delivery's list keeps it
99
+ * under offline (`libras/offline-avatar.json`, ADR-0234 phase B3). Escaping the name first (`&` as `%26`, as `encodeURIComponent`
100
+ * does) asks another address, which the server answers online and the checked cache never holds: PRIMEIRO&ORDINAL and
101
+ * SEGUNDO&ORDINAL went unsigned offline. 📌 No clip name carries `%`, `#`, `?` or `\`, which a URL reads as something other than
102
+ * a name — `tests/libras-avatar-delivery.node.test.js` holds that over the pins.
103
+ */
104
+ const clipAddress = (file, folder) => new URL(file, folder).href;
105
+ /**
106
+ * Makes each clip of `names` playable on `stage`, fetching the ones it has not got — once each, remembered in `ready` — and
107
+ * answers the names whose file could not be read or prepared.
108
+ */
109
+ export async function prepareClips(stage, names, manifest, place, fetchFile, ready) {
110
+ const one = async (name) => {
111
+ const w = manifest.clips.get(name);
112
+ if (!w)
113
+ return false;
114
+ const json = await readJson(fetchFile, clipAddress(w.file, place.folder));
115
+ if (!isClipJson(json))
116
+ return false;
117
+ try {
118
+ stage.prepare(name, json, w.from);
119
+ return true;
120
+ }
121
+ catch {
122
+ return false;
123
+ }
124
+ };
125
+ const read = await Promise.all(names.map((name) => {
126
+ let loading = ready.get(name);
127
+ if (!loading) {
128
+ loading = one(name);
129
+ ready.set(name, loading);
130
+ }
131
+ return loading;
132
+ }));
133
+ return names.filter((_, i) => !read[i]);
134
+ }
@@ -0,0 +1,102 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /**
3
+ * Where the delivery puts the free player's avatar, clips, manifest and glosses, beside the game's page (`inclusionist-heavy --libras`):
4
+ * written in the catalogue, whose delivery list keeps these files offline (ADR-0234, phase B3), and re-exported here where the
5
+ * player and the delivery script already read it.
6
+ */
7
+ export { LIBRAS_AVATAR_FOLDER } from '../platform/heavy-catalogue.js';
8
+ /** The manifest the delivery writes in that folder: the avatar's file and every clip it carries, with its window. */
9
+ export declare const LIBRAS_AVATAR_MANIFEST = "manifest.json";
10
+ /**
11
+ * How long two clips overlap, fading one into the other, in seconds. Every clip is at least 1.2 s (📏 the 655 of the delivery:
12
+ * 1.2–7.1 s, median 2.47 s), and the overlap never exceeds half of either clip, so no clip is swallowed by its neighbours.
13
+ */
14
+ export declare const CROSS_FADE_S = 0.3;
15
+ /** One clip the delivery carries: its file under the folder, and the stretch of it that is played. */
16
+ export interface ClipWindow {
17
+ readonly file: string;
18
+ /** The clip's length in seconds, as exported. */
19
+ readonly duration: number;
20
+ /**
21
+ * Where the sign starts, in seconds — 0 for every clip but one: the export of FALA begins at a stray keyframe 1404 frames
22
+ * before the sign (46.8 s at 30 fps), which the delivery's pins name, so the player plays from the sign and not from the stray.
23
+ */
24
+ readonly from: number;
25
+ /**
26
+ * Where the hand is held up, `[up, down]` in seconds of the played window — only for the clips a word is spelled with (a letter
27
+ * or a digit): a chained letter starts at `up` and hands over at `down`. E's is its whole clip. Absent, the clip plays whole.
28
+ */
29
+ readonly held?: readonly [number, number];
30
+ }
31
+ /** The delivery's manifest, read: the avatar's file and the clips by name. */
32
+ export interface AvatarManifest {
33
+ readonly avatar: string;
34
+ readonly clips: ReadonlyMap<string, ClipWindow>;
35
+ }
36
+ /**
37
+ * The manifest the delivery wrote, or `null` for anything else — no file, a fallback page, another format: a delivery that did
38
+ * not ship the avatar. A clip entry of the wrong shape is left out, not trusted; a `held` of the wrong shape is dropped.
39
+ */
40
+ export declare function avatarManifestOf(data: unknown): AvatarManifest | null;
41
+ /** How long a clip plays: its window, from `from` to its end. */
42
+ export declare const playedLength: (w: ClipWindow) => number;
43
+ /**
44
+ * One clip to play: a sign, or a letter of a word being fingerspelled (`spells`, the word; `word`, its place in the gloss — two
45
+ * letters are of one word, and chained, only when both are the same).
46
+ */
47
+ export interface SignStep {
48
+ readonly clip: string;
49
+ readonly spells?: string;
50
+ readonly word?: number;
51
+ }
52
+ /** A word the avatar could not sign: no clip of its own, and letters it has no clip for. */
53
+ export interface UnsignedWord {
54
+ readonly word: string;
55
+ readonly missing: readonly string[];
56
+ }
57
+ export interface SignPlan {
58
+ readonly steps: readonly SignStep[];
59
+ readonly unsigned: readonly UnsignedWord[];
60
+ }
61
+ /**
62
+ * The clips a gloss is signed with, in order: a token with a clip is its clip; any other is fingerspelled from the letter and
63
+ * digit clips, as written (capitals, accents stripped, Ç kept); a word with a letter the avatar lacks is left out whole and
64
+ * listed.
65
+ */
66
+ export declare function planSigns(gloss: string, carried: (name: string) => boolean): SignPlan;
67
+ /**
68
+ * What the avatar left out of a text, said for `problems` (the `unsigned` of a `SignResult`): the words, and the letters it
69
+ * lacks clips for. `undefined` when it left nothing out.
70
+ */
71
+ export declare function unsignedText(unsigned: readonly UnsignedWord[]): string | undefined;
72
+ /**
73
+ * Everything a request left out: the words it could neither sign nor spell, and the clips the delivery could not give (`unread`).
74
+ * `undefined` when it left nothing out.
75
+ */
76
+ export declare function leftOutText(unsigned: readonly UnsignedWord[], unread: readonly string[]): string | undefined;
77
+ /** Why a request with nothing left to sign was not signed. */
78
+ export declare const nothingSigned: (leftOut: string | undefined) => string;
79
+ /** A clip to put on the stage now: fading in over `fade` seconds from what is there, starting `at` seconds into its window. */
80
+ export interface StartClip {
81
+ readonly clip: string;
82
+ readonly fade: number;
83
+ readonly at: number;
84
+ }
85
+ export interface SignSequencer {
86
+ /** Replaces whatever was being signed with `steps`; returns the clip to start now (none for no steps). */
87
+ readonly play: (steps: readonly SignStep[]) => StartClip[];
88
+ /** Moves the clock `dt` seconds: the clips to start, and whether the last one just reached its end («stopped»). */
89
+ readonly tick: (dt: number) => {
90
+ readonly starts: StartClip[];
91
+ readonly finished: boolean;
92
+ };
93
+ /** Drops the queue: nothing more starts, and nothing finishes. */
94
+ readonly stop: () => void;
95
+ }
96
+ /**
97
+ * The queue's clock. `lengthOf` is a clip's played length (`playedLength`), `heldOf` where a letter's hand is held up
98
+ * (`playedSpans`: a spelled word's letters are chained through it; none, and every clip plays whole). Two neighbours overlap by
99
+ * `fade`, never by more than half of the stretch either plays; the first clip of a queue fades in only when a pose is already on
100
+ * the stage (a queue that replaced another, or the one held since the last), and appears at once otherwise.
101
+ */
102
+ export declare function createSignSequencer(lengthOf: (clip: string) => number, fade?: number, heldOf?: (clip: string) => readonly [number, number] | undefined): SignSequencer;
@@ -0,0 +1,211 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // ui/libras-avatar-plan — WHAT THE FREE PLAYER SIGNS, IN WHICH ORDER, AND WHEN EACH CLIP STARTS (ADR-0234, route B, phase B2).
3
+ //
4
+ // Route B signs with LAViD-UFPB's own sign sources, exported once to ONE avatar and ONE three.js clip per sign
5
+ // (`scripts/libras-export.mjs`, phase B1). This module is the player's pure half — no three.js, no DOM — so the queue, the
6
+ // timing and the fingerspelling are held in node (`tests/libras-avatar-plan.node.test.js`); `ui/libras-avatar-stage` plays what
7
+ // it decides and `ui/libras-avatar-player` puts it behind the `Interpreter` port.
8
+ //
9
+ // THE GLOSS IS THE DELIVERY'S: its build-time glosses (`ui/libras-glosses`), where a word with no clip is already written as
10
+ // the child reads it on the screen. A token the delivery carries a clip for is signed; any other is FINGERSPELLED letter by
11
+ // letter from the clips named by a single letter or digit — the word as written, capitals, accents stripped but Ç kept, a letter
12
+ // of the manual alphabet with a clip of its own (`provisionalGloss`, the build's own spelling rule).
13
+ // 📌 A word whose letters the avatar does not all carry is LEFT OUT WHOLE, and said: spelling only the letters it has would
14
+ // show the child another word («ENTROU» with only its O is «O»).
15
+ //
16
+ // THE TIMING: each clip plays its window once, and the next one starts `CROSS_FADE_S` before it ends, fading in while the other
17
+ // fades out — almost every exported clip starts and ends in the same pose (arms down), so the overlap joins them without passing
18
+ // through the avatar's rest. 📏 13 of the 655 do not: the letter E holds its raised handshape from its first frame to its last,
19
+ // NÃO_OUVIR keeps the right arm at the avatar's rest, and eleven (CASA and SIM among them) rest their hands lower. The last one
20
+ // plays to its end and its final pose is held: that moment is the player's «stopped».
21
+ //
22
+ // 📌 A SPELLED WORD IS SIGNED WITH THE HAND HELD UP BETWEEN ITS LETTERS (the Dev, interface log 2026-09-26). Each letter's and
23
+ // digit's clip rises from the arms-down pose, holds its handshape and falls back; the delivery's manifest says where it is held
24
+ // (`ClipWindow.held`, measured on the clip: `scripts/libras-export.mjs` `heldWindow`). Inside one spelled word, a letter after the
25
+ // first starts where its hand is up, and a letter before the last hands over where its hand starts down — the cross-fade joins
26
+ // two held handshapes — so the hand rises at the first letter and comes down only after the last. E, still from its first frame
27
+ // to its last, is held for its whole clip and the chain passes through it. A sign keeps its whole clip, a word of one letter is
28
+ // unchanged, and a letter the manifest gives no window plays whole. 📏 On a served delivery «PÕE» went from 4.37 s to 2.86 s and
29
+ // «TRIÂNGULO» from 12.60 s to 5.35 s.
30
+ import { provisionalGloss } from './libras-glosses.js';
31
+ /**
32
+ * Where the delivery puts the free player's avatar, clips, manifest and glosses, beside the game's page (`inclusionist-heavy --libras`):
33
+ * written in the catalogue, whose delivery list keeps these files offline (ADR-0234, phase B3), and re-exported here where the
34
+ * player and the delivery script already read it.
35
+ */
36
+ export { LIBRAS_AVATAR_FOLDER } from '../platform/heavy-catalogue.js';
37
+ /** The manifest the delivery writes in that folder: the avatar's file and every clip it carries, with its window. */
38
+ export const LIBRAS_AVATAR_MANIFEST = 'manifest.json';
39
+ /**
40
+ * How long two clips overlap, fading one into the other, in seconds. Every clip is at least 1.2 s (📏 the 655 of the delivery:
41
+ * 1.2–7.1 s, median 2.47 s), and the overlap never exceeds half of either clip, so no clip is swallowed by its neighbours.
42
+ */
43
+ export const CROSS_FADE_S = 0.3;
44
+ const isWindow = (w) => {
45
+ const c = w;
46
+ return !!c && typeof c.file === 'string' && typeof c.duration === 'number' && c.duration > 0
47
+ && (c.from === undefined || (typeof c.from === 'number' && c.from >= 0 && c.from < c.duration));
48
+ };
49
+ /** A `held` inside the played window, up before down; anything else is no window, and the clip plays whole. */
50
+ const heldIn = (held, length) => {
51
+ if (!Array.isArray(held) || held.length !== 2)
52
+ return undefined;
53
+ const [up, down] = held;
54
+ return typeof up === 'number' && typeof down === 'number' && up >= 0 && down > up && down <= length ? [up, down] : undefined;
55
+ };
56
+ /**
57
+ * The manifest the delivery wrote, or `null` for anything else — no file, a fallback page, another format: a delivery that did
58
+ * not ship the avatar. A clip entry of the wrong shape is left out, not trusted; a `held` of the wrong shape is dropped.
59
+ */
60
+ export function avatarManifestOf(data) {
61
+ const m = data;
62
+ if (!m || m.format !== 1 || typeof m.avatar !== 'string' || !m.avatar || typeof m.clips !== 'object' || m.clips === null)
63
+ return null;
64
+ const clips = new Map();
65
+ for (const [name, w] of Object.entries(m.clips)) {
66
+ if (isWindow(w))
67
+ clips.set(name, windowRead(w));
68
+ }
69
+ return { avatar: m.avatar, clips };
70
+ }
71
+ /** A clip entry of the right shape, as the player keeps it: `from` defaulted, `held` only when it is inside the window. */
72
+ function windowRead(w) {
73
+ const from = w.from ?? 0;
74
+ const held = heldIn(w.held, w.duration - from);
75
+ return { file: w.file, duration: w.duration, from, ...(held ? { held } : {}) };
76
+ }
77
+ /** How long a clip plays: its window, from `from` to its end. */
78
+ export const playedLength = (w) => w.duration - w.from;
79
+ /** A gloss token that is not a sign: punctuation (`[PONTO]`) or a template hole the lookup left (`{n}`). */
80
+ const NOT_A_SIGN = /^\[.*\]$|^\{.*\}$/u;
81
+ /**
82
+ * The clips a gloss is signed with, in order: a token with a clip is its clip; any other is fingerspelled from the letter and
83
+ * digit clips, as written (capitals, accents stripped, Ç kept); a word with a letter the avatar lacks is left out whole and
84
+ * listed.
85
+ */
86
+ export function planSigns(gloss, carried) {
87
+ const steps = [];
88
+ const unsigned = [];
89
+ gloss.split(/\s+/u).forEach((token, word) => {
90
+ if (!token || NOT_A_SIGN.test(token))
91
+ return;
92
+ if (carried(token)) {
93
+ steps.push({ clip: token });
94
+ return;
95
+ }
96
+ const letters = [...provisionalGloss(token).replace(/\s+/gu, '')];
97
+ if (!letters.length)
98
+ return;
99
+ const missing = [...new Set(letters.filter((c) => !carried(c)))];
100
+ if (missing.length) {
101
+ unsigned.push({ word: token, missing });
102
+ return;
103
+ }
104
+ for (const c of letters)
105
+ steps.push({ clip: c, spells: token, word });
106
+ });
107
+ return { steps, unsigned };
108
+ }
109
+ /**
110
+ * What the avatar left out of a text, said for `problems` (the `unsigned` of a `SignResult`): the words, and the letters it
111
+ * lacks clips for. `undefined` when it left nothing out.
112
+ */
113
+ export function unsignedText(unsigned) {
114
+ if (!unsigned.length)
115
+ return undefined;
116
+ const words = [...new Set(unsigned.map((u) => `«${u.word}»`))];
117
+ const letters = [...new Set(unsigned.flatMap((u) => u.missing))].sort();
118
+ const one = words.length === 1;
119
+ return `${words.join(', ')} ${one ? 'lacks a sign of its' : 'lack a sign of their'} own and could not be fingerspelled: `
120
+ + `the avatar lacks the clips for ${letters.join(', ')}`;
121
+ }
122
+ /**
123
+ * Everything a request left out: the words it could neither sign nor spell, and the clips the delivery could not give (`unread`).
124
+ * `undefined` when it left nothing out.
125
+ */
126
+ export function leftOutText(unsigned, unread) {
127
+ const parts = [unsignedText(unsigned), unread.length ? `the clips of ${unread.map((n) => `«${n}»`).join(', ')} could not be read from the delivery` : ''];
128
+ return parts.filter(Boolean).join('; ') || undefined;
129
+ }
130
+ /** Why a request with nothing left to sign was not signed. */
131
+ export const nothingSigned = (leftOut) => `none of the text could be signed: ${leftOut ?? 'it holds not a single word'}`;
132
+ /**
133
+ * WHAT OF EACH CLIP IS PLAYED: all of it, except inside a spelled word, where two neighbouring letters are CHAINED — the first
134
+ * ends where its hand starts down, the next starts where its hand is up (`held`). Two steps are chained only when they spell the
135
+ * same word (`word`) and both have a window; so the first letter keeps its rise, the last its fall, a word of one letter and a
136
+ * sign are whole.
137
+ */
138
+ function playedSpans(steps, lengthOf, heldOf) {
139
+ const oneWord = (a, b) => a.spells !== undefined && a.word !== undefined
140
+ && b.word === a.word && b.spells === a.spells;
141
+ const chained = steps.map((s, i) => {
142
+ const next = steps[i + 1];
143
+ return !!next && oneWord(s, next) && !!heldOf(s.clip) && !!heldOf(next.clip);
144
+ });
145
+ return steps.map((s, i) => [
146
+ i > 0 && chained[i - 1] ? heldOf(s.clip)[0] : 0,
147
+ chained[i] ? heldOf(s.clip)[1] : lengthOf(s.clip),
148
+ ]);
149
+ }
150
+ /**
151
+ * The queue's clock. `lengthOf` is a clip's played length (`playedLength`), `heldOf` where a letter's hand is held up
152
+ * (`playedSpans`: a spelled word's letters are chained through it; none, and every clip plays whole). Two neighbours overlap by
153
+ * `fade`, never by more than half of the stretch either plays; the first clip of a queue fades in only when a pose is already on
154
+ * the stage (a queue that replaced another, or the one held since the last), and appears at once otherwise.
155
+ */
156
+ export function createSignSequencer(lengthOf, fade = CROSS_FADE_S, heldOf = () => undefined) {
157
+ let queue = [];
158
+ let spans = [];
159
+ /** The step on the stage now; -1 when none is playing. */
160
+ let index = -1;
161
+ /** Seconds into the current step's stretch. */
162
+ let elapsed = 0;
163
+ /** Whether a pose is on the stage: after the first clip, the last frame of the last one is held. */
164
+ let shown = false;
165
+ const lengthAt = (i) => spans[i][1] - spans[i][0];
166
+ const overlapAfter = (i) => (i + 1 < queue.length ? Math.min(fade, lengthAt(i) / 2, lengthAt(i + 1) / 2) : 0);
167
+ return {
168
+ play: (steps) => {
169
+ queue = steps;
170
+ spans = playedSpans(steps, lengthOf, heldOf);
171
+ elapsed = 0;
172
+ index = steps.length ? 0 : -1;
173
+ if (!steps.length)
174
+ return [];
175
+ const start = { clip: steps[0].clip, fade: shown ? Math.min(fade, lengthAt(0) / 2) : 0, at: spans[0][0] };
176
+ shown = true;
177
+ return [start];
178
+ },
179
+ tick: (dt) => {
180
+ const starts = [];
181
+ if (index < 0)
182
+ return { starts, finished: false };
183
+ elapsed += Math.max(0, dt);
184
+ for (;;) {
185
+ const length = lengthAt(index);
186
+ if (index + 1 < queue.length) {
187
+ const handOver = length - overlapAfter(index);
188
+ if (elapsed < handOver)
189
+ break;
190
+ elapsed -= handOver;
191
+ index += 1;
192
+ starts.push({ clip: queue[index].clip, fade: overlapAfter(index - 1), at: spans[index][0] + elapsed });
193
+ continue;
194
+ }
195
+ if (elapsed < length)
196
+ break;
197
+ index = -1;
198
+ queue = [];
199
+ spans = [];
200
+ return { starts, finished: true };
201
+ }
202
+ return { starts, finished: false };
203
+ },
204
+ stop: () => {
205
+ index = -1;
206
+ queue = [];
207
+ spans = [];
208
+ elapsed = 0;
209
+ },
210
+ };
211
+ }
@@ -0,0 +1,28 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import type { Interpreter } from './vlibras.js';
3
+ import type { AvatarStage } from './libras-avatar-stage.js';
4
+ /** What the free interpreter is built over. Every port is the host's. */
5
+ export interface LibrasAvatarPorts {
6
+ /** The host's document: the avatar's canvas is created in it and put in front of the screen. */
7
+ readonly doc: Document;
8
+ /** The host's window: it keeps the timers and draws the frames. */
9
+ readonly win: Pick<Window, 'setTimeout' | 'clearTimeout' | 'requestAnimationFrame' | 'cancelAnimationFrame'> & {
10
+ readonly devicePixelRatio?: number;
11
+ };
12
+ /** The host's `fetch`, for the delivery's manifest, avatar, clips and glosses; `undefined` where it has none. */
13
+ readonly fetch: ((url: string) => Promise<Response>) | undefined;
14
+ /** The page's address the delivery's folders are resolved against (`document.baseURI`). */
15
+ readonly base: string;
16
+ /** The avatar's accessible name, read when its canvas is made — the page's language at that moment. */
17
+ readonly title: () => string;
18
+ /** Where the avatar, the clips, the manifest and the glosses are, under `base`. The delivery's folder unless a test points elsewhere. */
19
+ readonly avatarFolder?: string;
20
+ /** How long the avatar may take to load before the request is answered «unavailable». */
21
+ readonly loadTimeoutMs?: number;
22
+ /** How long the avatar stays after it stopped signing before it leaves. `LEAVE_AFTER_MS` unless a test says. */
23
+ readonly leaveAfterMs?: number;
24
+ /** Builds the stage on the canvas from the avatar's bytes. `ui/libras-avatar-stage`, imported when first needed, unless a test says. */
25
+ readonly loadStage?: (canvas: HTMLCanvasElement, avatar: ArrayBuffer) => Promise<AvatarStage>;
26
+ }
27
+ /** Builds the free interpreter over the avatar the delivery shipped — or, where it shipped none, «signing unavailable». */
28
+ export declare function createLibrasAvatarInterpreter(ports: LibrasAvatarPorts): Interpreter;