@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.
- package/README.md +32 -1
- package/app/css/style.css +216 -42
- package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
- package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
- package/app/public/vendor/fonts.css +11 -1175
- package/dist-pkg/boot/create-game.d.ts +84 -33
- package/dist-pkg/boot/create-game.js +708 -307
- package/dist-pkg/core/a11y-sr.d.ts +1 -1
- package/dist-pkg/core/a11y-sr.js +3 -5
- package/dist-pkg/core/accommodations.d.ts +26 -8
- package/dist-pkg/core/accommodations.js +27 -10
- package/dist-pkg/core/actions.d.ts +39 -10
- package/dist-pkg/core/actions.js +28 -6
- package/dist-pkg/core/contract.d.ts +0 -2
- package/dist-pkg/core/contract.js +0 -2
- package/dist-pkg/core/i18n.d.ts +36 -71
- package/dist-pkg/core/i18n.js +131 -198
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/i18n/en.js +44 -49
- package/dist-pkg/i18n/es.js +44 -49
- package/dist-pkg/i18n/pt.js +49 -54
- package/dist-pkg/input/gamepad.d.ts +42 -11
- package/dist-pkg/input/gamepad.js +50 -15
- package/dist-pkg/input/key-default.d.ts +30 -0
- package/dist-pkg/input/key-default.js +60 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +0 -4
- package/dist-pkg/input/keyboard.d.ts +0 -1
- package/dist-pkg/input/keydown.d.ts +5 -11
- package/dist-pkg/input/keydown.js +3 -3
- package/dist-pkg/input/latch-edge.d.ts +10 -2
- package/dist-pkg/input/latch-edge.js +4 -3
- package/dist-pkg/input/latch-scope.d.ts +27 -22
- package/dist-pkg/input/latch-scope.js +25 -37
- package/dist-pkg/input/latch-store.d.ts +9 -12
- package/dist-pkg/input/latch-store.js +13 -18
- package/dist-pkg/input/latch-sync.d.ts +5 -4
- package/dist-pkg/input/latch-sync.js +5 -5
- package/dist-pkg/input/pad-reading.js +7 -2
- package/dist-pkg/input/pad-wizard.d.ts +4 -1
- package/dist-pkg/input/pad-wizard.js +60 -9
- package/dist-pkg/input/switch-scan.d.ts +29 -12
- package/dist-pkg/input/switch-scan.js +15 -2
- package/dist-pkg/input/touch-bindings.d.ts +3 -6
- package/dist-pkg/input/touch.d.ts +17 -2
- package/dist-pkg/input/touch.js +55 -17
- package/dist-pkg/input/transport-in-use.d.ts +5 -5
- package/dist-pkg/input/transport-in-use.js +5 -5
- package/dist-pkg/input/transports.d.ts +0 -9
- package/dist-pkg/input/transports.js +1 -1
- package/dist-pkg/input/virtual-controller.d.ts +39 -3
- package/dist-pkg/input/virtual-controller.js +32 -4
- package/dist-pkg/input/voice-map.d.ts +27 -11
- package/dist-pkg/input/voice-map.js +41 -43
- package/dist-pkg/platform/audio-ambient.d.ts +0 -1
- package/dist-pkg/platform/audio-ambient.js +3 -1
- package/dist-pkg/platform/audio-mixer.js +4 -9
- package/dist-pkg/platform/audio-sonar.d.ts +8 -94
- package/dist-pkg/platform/audio-sonar.js +22 -207
- package/dist-pkg/platform/audio.d.ts +10 -1
- package/dist-pkg/platform/audio.js +35 -2
- package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
- package/dist-pkg/platform/choose-by-voice.js +157 -0
- package/dist-pkg/platform/font-library.d.ts +77 -0
- package/dist-pkg/platform/font-library.js +98 -0
- package/dist-pkg/platform/font-library.json +721 -0
- package/dist-pkg/platform/heavy-catalogue.d.ts +46 -0
- package/dist-pkg/platform/heavy-catalogue.js +47 -14
- package/dist-pkg/platform/heavy-mirror.d.ts +3 -9
- package/dist-pkg/platform/heavy-mirror.js +14 -17
- package/dist-pkg/platform/heavy.d.ts +40 -8
- package/dist-pkg/platform/heavy.js +177 -22
- package/dist-pkg/platform/interruptible-speech.d.ts +15 -8
- package/dist-pkg/platform/interruptible-speech.js +37 -13
- package/dist-pkg/platform/listener-scope.js +22 -13
- package/dist-pkg/platform/locale-host.d.ts +7 -3
- package/dist-pkg/platform/locale-host.js +13 -2
- package/dist-pkg/platform/reading-in-worker.d.ts +24 -0
- package/dist-pkg/platform/reading-in-worker.js +38 -0
- package/dist-pkg/platform/reading-model.d.ts +21 -0
- package/dist-pkg/platform/reading-model.js +25 -0
- package/dist-pkg/platform/reading-runtime.js +13 -8
- package/dist-pkg/platform/reading.d.ts +12 -1
- package/dist-pkg/platform/reading.js +9 -1
- package/dist-pkg/platform/speech-recognition.d.ts +10 -1
- package/dist-pkg/platform/speech-recognition.js +29 -9
- package/dist-pkg/platform/speech.d.ts +10 -1
- package/dist-pkg/platform/speech.js +24 -13
- package/dist-pkg/platform/tts.d.ts +37 -4
- package/dist-pkg/platform/tts.js +279 -57
- package/dist-pkg/platform/voice-listener.d.ts +6 -2
- package/dist-pkg/platform/voice-listener.js +1 -1
- package/dist-pkg/platform/voice-plan.d.ts +13 -0
- package/dist-pkg/platform/voice-plan.js +57 -2
- package/dist-pkg/platform/vosk-runtime.d.ts +25 -0
- package/dist-pkg/platform/vosk-runtime.js +59 -1
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/crt.d.ts +11 -9
- package/dist-pkg/render/crt.js +6 -10
- package/dist-pkg/render/cvd-matrices.d.ts +5 -1
- package/dist-pkg/render/cvd-matrices.js +5 -1
- package/dist-pkg/render/high-contrast.d.ts +1 -2
- package/dist-pkg/render/high-contrast.js +5 -1
- package/dist-pkg/render/viz-axes.d.ts +9 -0
- package/dist-pkg/render/viz-axes.js +15 -2
- package/dist-pkg/ui/aac-sets.d.ts +29 -24
- package/dist-pkg/ui/aac-sets.js +22 -30
- package/dist-pkg/ui/audio-choices.d.ts +10 -5
- package/dist-pkg/ui/audio-choices.js +14 -10
- package/dist-pkg/ui/camera-control.d.ts +47 -0
- package/dist-pkg/ui/camera-control.js +35 -1
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/drawing-problems.js +4 -3
- package/dist-pkg/ui/eye-control.js +17 -17
- package/dist-pkg/ui/face-control.js +15 -15
- package/dist-pkg/ui/fonts.d.ts +42 -8
- package/dist-pkg/ui/fonts.js +58 -24
- package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
- package/dist-pkg/ui/footer-scroll-driver.js +201 -0
- package/dist-pkg/ui/footer-scroll.d.ts +38 -0
- package/dist-pkg/ui/footer-scroll.js +55 -0
- package/dist-pkg/ui/game-options.d.ts +14 -9
- package/dist-pkg/ui/game-options.js +41 -21
- package/dist-pkg/ui/hand-control.js +15 -15
- package/dist-pkg/ui/help-panel.d.ts +19 -8
- package/dist-pkg/ui/help-panel.js +15 -5
- package/dist-pkg/ui/hud-bands.d.ts +29 -12
- package/dist-pkg/ui/hud-bands.js +63 -25
- package/dist-pkg/ui/hud-row.d.ts +34 -0
- package/dist-pkg/ui/hud-row.js +80 -0
- package/dist-pkg/ui/hud.d.ts +0 -3
- package/dist-pkg/ui/layout.js +5 -2
- package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
- package/dist-pkg/ui/libras-avatar-clip.js +86 -0
- package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
- package/dist-pkg/ui/libras-avatar-load.js +134 -0
- package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
- package/dist-pkg/ui/libras-avatar-plan.js +211 -0
- package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
- package/dist-pkg/ui/libras-avatar-player.js +226 -0
- package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
- package/dist-pkg/ui/libras-avatar-stage.js +208 -0
- package/dist-pkg/ui/libras-glosses.d.ts +28 -0
- package/dist-pkg/ui/libras-glosses.js +161 -0
- package/dist-pkg/ui/menu-intent.d.ts +29 -0
- package/dist-pkg/ui/menu-intent.js +35 -1
- package/dist-pkg/ui/menu-items.d.ts +10 -0
- package/dist-pkg/ui/menu-items.js +29 -0
- package/dist-pkg/ui/menu-nav.d.ts +40 -4
- package/dist-pkg/ui/menu-nav.js +132 -47
- package/dist-pkg/ui/panel-widgets.d.ts +34 -0
- package/dist-pkg/ui/panel-widgets.js +86 -0
- package/dist-pkg/ui/pause-icons.d.ts +30 -14
- package/dist-pkg/ui/pause-icons.js +106 -45
- package/dist-pkg/ui/scan-overlay.d.ts +3 -3
- package/dist-pkg/ui/scan-overlay.js +11 -3
- package/dist-pkg/ui/screen-text.d.ts +25 -0
- package/dist-pkg/ui/screen-text.js +152 -0
- package/dist-pkg/ui/session-clock.d.ts +32 -0
- package/dist-pkg/ui/session-clock.js +67 -0
- package/dist-pkg/ui/settings-aac.d.ts +3 -1
- package/dist-pkg/ui/settings-aac.js +32 -13
- package/dist-pkg/ui/settings-audio.d.ts +10 -5
- package/dist-pkg/ui/settings-audio.js +101 -35
- package/dist-pkg/ui/settings-controls.d.ts +0 -4
- package/dist-pkg/ui/settings-mobility.d.ts +3 -6
- package/dist-pkg/ui/settings-mobility.js +4 -46
- package/dist-pkg/ui/settings-motion.js +2 -2
- package/dist-pkg/ui/settings-panel.d.ts +10 -0
- package/dist-pkg/ui/settings-panel.js +25 -1
- package/dist-pkg/ui/settings-typo.d.ts +5 -6
- package/dist-pkg/ui/settings-typo.js +20 -11
- package/dist-pkg/ui/settings-visual.js +2 -2
- package/dist-pkg/ui/shell.d.ts +1 -3
- package/dist-pkg/ui/shell.js +8 -4
- package/dist-pkg/ui/title.d.ts +2 -11
- package/dist-pkg/ui/title.js +39 -6
- package/dist-pkg/ui/top-band.d.ts +5 -3
- package/dist-pkg/ui/top-band.js +21 -25
- package/dist-pkg/ui/typo-choices.d.ts +3 -3
- package/dist-pkg/ui/typo-choices.js +9 -8
- package/dist-pkg/ui/vlibras.d.ts +71 -27
- package/dist-pkg/ui/vlibras.js +116 -44
- package/dist-pkg/ui/voice-control.d.ts +23 -1
- package/dist-pkg/ui/voice-control.js +149 -16
- package/dist-pkg/ui/voice-settings.d.ts +2 -3
- package/dist-pkg/ui/voice-settings.js +53 -3
- package/dist-pkg/ui/where-the-child-is.js +2 -2
- package/docs/CREDITS.md +122 -10
- package/docs/LICENSES.md +36 -7
- package/package.json +34 -9
- package/scripts/check-cartridge.mjs +78 -0
- package/scripts/game-build.d.mts +25 -0
- package/scripts/game-build.mjs +144 -0
- package/scripts/heavy-into-the-delivery.mjs +284 -40
- package/scripts/libras-avatar.json +680 -0
- package/scripts/libras-avatar.mjs +246 -0
- package/scripts/libras-glosses/gloss.py +95 -0
- package/scripts/libras-glosses/pyproject.toml +32 -0
- package/scripts/libras-glosses/uv.lock +781 -0
- package/scripts/libras-glosses.mjs +351 -0
- package/scripts/licences/OFL-1.1.txt +86 -0
- package/scripts/licences/UFL-1.0.txt +96 -0
- package/scripts/licences/fonts.mjs +389 -0
- package/scripts/licences/third-party.mjs +35 -21
- package/app/public/vendor/fonts/bitter-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bitter-var.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/bodonimoda-var.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-abril_fatface-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-adlam_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-agu_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-alfa_slab_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-are_you_serious-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-asimovian-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-atkinson_hyperlegible_next-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bakbak_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bangers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-barriecito-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-berkshire_swash-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bevan-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bitcount-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bowlby_one_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-bungee_shade-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-charm-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cherry_bomb_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chokokutai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-chonburi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-climate_crisis-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-cookie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-dela_gothic_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-fascinate_inline-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ga_maamli-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-itim-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-jacquard_24-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kablammo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-kalam-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-katibeh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lemonada-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lilita_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-lobster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-luckiest_guy-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-marhey-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-modak-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-momo_signature-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monofett-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monomakh-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-monoton-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-nerko_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_adlam-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_arabic-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_devanagari-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_hebrew-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_jp-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_khmer-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_kr-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_sc-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-noto_sans_thai-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ole-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pacifico-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-patrick_hand-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-petit_formal_script-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-pixelify_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-plaster-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ar_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_at_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_nsw_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_qld_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_sa_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_tas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_au_vic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_vlg_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_be_wal_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_br_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ca_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_co_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_cz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_grund_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_la_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_sas_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_de_va_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_loopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_dk_uloopet_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_deco_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_es_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_moderne_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_fr_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_j_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_gb_s_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hr_lijeva_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_hu_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_id_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ie_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_in_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_is_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_moderna_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_it_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_mx_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ng_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_no_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_basic_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_nz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pe_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pl_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_pt_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_ro_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_sk_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_tz_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_modern_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_us_trad_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_vn_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-playwrite_za_guides-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-potta_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranchers-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ranga-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-risque-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-rowdies-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruge_boogie-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-ruslan_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sacramento-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sancreek-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sankofa_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sedgwick_ave_display-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-shantell_sans-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-smokum-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-solitreo-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-spicy_rice-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-sriracha-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-srisakdi-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-stix_two_math-400-0.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-tillana-700.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-titan_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yatra_one-400.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/cat-yomogi-400.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/dmserifdisplay-400.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/domine-var.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fraunces-var.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fredoka-var.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/jakarta-var.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lora-var.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/merriweather-var.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/notosans-var.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/nunito-var.woff2 +0 -0
- package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/playfair-var.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/quicksand-var.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/robotoflex-var.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/sora-var.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spacegrotesk-var.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-400.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/spectral-700.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var-ext.woff2 +0 -0
- package/app/public/vendor/fonts/teachers-var.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-400.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/ubuntu-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/dist-pkg/platform/guide-intensity.d.ts +0 -39
- package/dist-pkg/platform/guide-intensity.js +0 -71
- package/dist-pkg/ui/latch-refusal.d.ts +0 -33
- package/dist-pkg/ui/latch-refusal.js +0 -60
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { readSession, clockWords, clockDigits } from '../core/session-clock.js';
|
|
3
|
+
/** One tick a second: the digits move by the second, and the hour's pie by a tenth of a degree, which reads as continuous. */
|
|
4
|
+
const TICK_MS = 1000;
|
|
5
|
+
/** Writes `text` into `node` only when it changed โ a rewrite is a repaint, and on school hardware a repaint costs. */
|
|
6
|
+
function write(node, text) {
|
|
7
|
+
if (node.textContent !== text)
|
|
8
|
+
node.textContent = text;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Builds the clock's three parts: the label and the digits in a column, the pie to their right.
|
|
12
|
+
*
|
|
13
|
+
* ๐ด THE PARTS ARE `aria-hidden`: they are the picture, and the image's name is what a listener gets. ARIA calls an image's
|
|
14
|
+
* children presentational, but not every accessibility API prunes them โ Gecko keeps a graphic's children unless it has exactly
|
|
15
|
+
* one text child, and NVDA then read ยซTEMPO. 56:07.ยป instead of the words (the Dev, 2026-09-25). Hidden here, no API has any
|
|
16
|
+
* text under the image to hand out. Gate: `tests/quiz-accessibility-tree.browser.test.js`, on the browser's own tree.
|
|
17
|
+
*/
|
|
18
|
+
function build(doc) {
|
|
19
|
+
const part = (cls) => { const n = doc.createElement('span'); n.className = cls; return n; };
|
|
20
|
+
const el = doc.createElement('div');
|
|
21
|
+
el.className = 'session-clock';
|
|
22
|
+
el.setAttribute('role', 'img');
|
|
23
|
+
const text = part('session-clock-text');
|
|
24
|
+
const label = part('session-clock-label');
|
|
25
|
+
const digits = part('session-clock-digits');
|
|
26
|
+
const pie = part('session-clock-pie');
|
|
27
|
+
text.setAttribute('aria-hidden', 'true');
|
|
28
|
+
pie.setAttribute('aria-hidden', 'true');
|
|
29
|
+
text.append(label, digits);
|
|
30
|
+
el.append(text, pie);
|
|
31
|
+
return { el, label, digits, pie };
|
|
32
|
+
}
|
|
33
|
+
/** Mounts the clock in its slot, draws it now, and redraws it every second until `remove()`; `null` where it cannot. */
|
|
34
|
+
export function mountSessionClock(ctx) {
|
|
35
|
+
const { slot, performance: clock, setInterval: every } = ctx;
|
|
36
|
+
if (!slot || typeof slot.appendChild !== 'function' || !clock || typeof every !== 'function')
|
|
37
|
+
return null;
|
|
38
|
+
const { el, label, digits, pie } = build(ctx.doc);
|
|
39
|
+
slot.appendChild(el);
|
|
40
|
+
const timer = clock; // the guard's answer, kept for the tick
|
|
41
|
+
const start = timer.now();
|
|
42
|
+
let look = null;
|
|
43
|
+
function refresh() {
|
|
44
|
+
const reading = readSession(timer.now() - start);
|
|
45
|
+
const next = reading.over ? 'red' : 'running';
|
|
46
|
+
pie.style.setProperty('--left', reading.left.toFixed(4));
|
|
47
|
+
write(label, ctx.t('clock.label'));
|
|
48
|
+
write(digits, clockDigits(reading.leftMs));
|
|
49
|
+
const words = clockWords(reading);
|
|
50
|
+
const name = ctx.t(words.key, { minutes: words.minutes });
|
|
51
|
+
if (el.getAttribute('aria-label') !== name)
|
|
52
|
+
el.setAttribute('aria-label', name);
|
|
53
|
+
if (next !== 'running' && look === 'running')
|
|
54
|
+
ctx.announce(name);
|
|
55
|
+
if (next !== look)
|
|
56
|
+
el.dataset.look = next;
|
|
57
|
+
look = next;
|
|
58
|
+
ctx.drawn();
|
|
59
|
+
}
|
|
60
|
+
refresh();
|
|
61
|
+
const handle = every(refresh, TICK_MS);
|
|
62
|
+
return {
|
|
63
|
+
el,
|
|
64
|
+
refresh,
|
|
65
|
+
remove: () => { ctx.clearInterval?.(handle); el.remove(); },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -25,7 +25,9 @@ export declare function lettersRowSpec(t: Translate): ControlRowSpec;
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function aacRowSpec(t: Translate, s: AacSet): ControlRowSpec;
|
|
27
27
|
/**
|
|
28
|
-
* The menu's
|
|
28
|
+
* The menu's two sections: what works now (the letters switch), and the pictogram sets, each only with a licence
|
|
29
|
+
* (ADR-0233). Whether a set row is locked is the row's own business (its reason and its `disabled`), so a licence that
|
|
30
|
+
* arrives changes one row, not the sections.
|
|
29
31
|
*
|
|
30
32
|
* ๐ Each produces its own rows instead of filtering the catalogue, because the first does not come from the catalogue
|
|
31
33
|
* โ the letters are a switch and not a set, the Dev's decision that took them out of the list. A table whose first row
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
2
|
import { DEFAULTS } from '../core/setting-defaults.js';
|
|
3
|
-
import { AAC_SETS, AAC_BY_KEY, aacReason } from './aac-sets.js';
|
|
3
|
+
import { AAC_SETS, AAC_BY_KEY, aacMenuLocked, aacReason, aacSelectable } from './aac-sets.js';
|
|
4
4
|
import { markChanged, markMenuChanged } from './changed-mark.js';
|
|
5
5
|
import { controlRow, labelRow, sectionHeader } from './panel-widgets.js';
|
|
6
6
|
import { toggleLabel } from './dom.js';
|
|
@@ -39,7 +39,9 @@ export function aacRowSpec(t, s) {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* The menu's
|
|
42
|
+
* The menu's two sections: what works now (the letters switch), and the pictogram sets, each only with a licence
|
|
43
|
+
* (ADR-0233). Whether a set row is locked is the row's own business (its reason and its `disabled`), so a licence that
|
|
44
|
+
* arrives changes one row, not the sections.
|
|
43
45
|
*
|
|
44
46
|
* ๐ Each produces its own rows instead of filtering the catalogue, because the first does not come from the catalogue
|
|
45
47
|
* โ the letters are a switch and not a set, the Dev's decision that took them out of the list. A table whose first row
|
|
@@ -48,14 +50,9 @@ export function aacRowSpec(t, s) {
|
|
|
48
50
|
export const AAC_SECTIONS = [
|
|
49
51
|
{ title: 'aac.secao.agora', tag: 'aac.secao.agoraTag', rows: (t) => [lettersRowSpec(t)] },
|
|
50
52
|
{
|
|
51
|
-
title: 'aac.
|
|
52
|
-
tag: 'aac.
|
|
53
|
-
rows: (t) => AAC_SETS.
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
title: 'aac.secao.negociacao',
|
|
57
|
-
tag: 'aac.secao.negociacaoTag',
|
|
58
|
-
rows: (t) => AAC_SETS.filter((s) => s.tier === 'negotiating').map((s) => aacRowSpec(t, s)),
|
|
53
|
+
title: 'aac.section.pictograms',
|
|
54
|
+
tag: 'aac.section.pictogramsTag',
|
|
55
|
+
rows: (t) => AAC_SETS.map((s) => aacRowSpec(t, s)),
|
|
59
56
|
},
|
|
60
57
|
];
|
|
61
58
|
/**
|
|
@@ -85,8 +82,8 @@ export function mountAacInside(t, ctx, list) {
|
|
|
85
82
|
/**
|
|
86
83
|
* A new row, with what the kit does not know about this panel: the set's key and the lock.
|
|
87
84
|
*
|
|
88
|
-
* No set is
|
|
89
|
-
* locked, and the reason is already in `ariaLabel` for whoever navigates by keyboard.
|
|
85
|
+
* No set is licensed today (ADR-0233). A button that does nothing is worse than absence, because it spends trust โ so an
|
|
86
|
+
* unlicensed set comes locked, and the reason is already in `ariaLabel` for whoever navigates by keyboard.
|
|
90
87
|
*/
|
|
91
88
|
function newRow(ctx, spec) {
|
|
92
89
|
const { row: row, control: control } = controlRow(ctx, spec);
|
|
@@ -96,7 +93,8 @@ function newRow(ctx, spec) {
|
|
|
96
93
|
}
|
|
97
94
|
const key = spec.id.replace('caa-set-', '');
|
|
98
95
|
control.setAttribute('data-caa', key);
|
|
99
|
-
|
|
96
|
+
const set = AAC_BY_KEY[key];
|
|
97
|
+
if (!set || !aacSelectable(set))
|
|
100
98
|
control.setAttribute('disabled', '');
|
|
101
99
|
return row;
|
|
102
100
|
}
|
|
@@ -137,7 +135,27 @@ export function initSettingsAac(ctx) {
|
|
|
137
135
|
markChanged(t, ctx.$('#caa-letras'), changed);
|
|
138
136
|
markMenuChanged(t, ctx.$('[data-act="caa"]'), [changed]);
|
|
139
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* THE MENU'S DOOR IS DISABLED while no pictogram set is licensed (ADR-0233 erratum), with the pause card's lock
|
|
140
|
+
* (ADR-0161): `aria-disabled` and the reason in `data-motivo`, which the menu navigation speaks on reach and writes in
|
|
141
|
+
* the footer. The reason is ONLY ยซmenu disabledยป: the licence story is not the child's to hear. No unlock branch: the
|
|
142
|
+
* catalogue is static, so a licensed set means the door is never locked in the first place.
|
|
143
|
+
*/
|
|
144
|
+
function lockDoor() {
|
|
145
|
+
const door = ctx.$('[data-act="caa"]');
|
|
146
|
+
if (!door || !aacMenuLocked())
|
|
147
|
+
return;
|
|
148
|
+
door.setAttribute('aria-disabled', 'true');
|
|
149
|
+
door.dataset.motivo = t('pause.motivo.caa');
|
|
150
|
+
}
|
|
140
151
|
function open() {
|
|
152
|
+
// A game that wires its own door to `open` meets the same lock: the reason is said and nothing opens, so no
|
|
153
|
+
// per-set licence row reaches the child.
|
|
154
|
+
if (aacMenuLocked()) {
|
|
155
|
+
lockDoor();
|
|
156
|
+
ctx.srSay(t('pause.motivo.caa'));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
141
159
|
const ov = ctx.$('#caa');
|
|
142
160
|
if (!ov)
|
|
143
161
|
return;
|
|
@@ -174,6 +192,7 @@ export function initSettingsAac(ctx) {
|
|
|
174
192
|
const closeBtn = ctx.$('#caa-close');
|
|
175
193
|
if (closeBtn)
|
|
176
194
|
closeBtn.addEventListener('click', close);
|
|
195
|
+
lockDoor();
|
|
177
196
|
// ---- reset THIS menu's defaults (ADR-0028) ----
|
|
178
197
|
// The menu has one choice, so the reset is one line โ but where it returns to is worth saying: the default case,
|
|
179
198
|
// where Brazilian literacy usually starts. A child who switched the case and can no longer read the screen needs a way
|
|
@@ -5,7 +5,6 @@ import type { PlayerAudioOut } from '../platform/audio-sonar.js';
|
|
|
5
5
|
import type { DomQuery } from '../core/dom-query.js';
|
|
6
6
|
import type { PanelShellCtx } from './panel-shell.js';
|
|
7
7
|
import { type TtsPanel, type VoiceSettingsStore } from './voice-settings.js';
|
|
8
|
-
export type { DomQuery } from '../core/dom-query.js';
|
|
9
8
|
/** Minimal platform/storage.ts shape this module needs (get/set only โ no direct localStorage access). */
|
|
10
9
|
export interface AudioStore {
|
|
11
10
|
get(key: string, fallback?: string | null): string | null;
|
|
@@ -115,9 +114,14 @@ export interface SettingsAudioApi {
|
|
|
115
114
|
renderAudio: () => void;
|
|
116
115
|
/** Refreshes the #opt-modocego button. Exported because the host's blind-mode setter calls it directly. */
|
|
117
116
|
reflectBlindMode: () => void;
|
|
118
|
-
/** Refreshes the #opt-tts button
|
|
119
|
-
* audioCat.tts.on itself and then calls this. */
|
|
117
|
+
/** Refreshes the #opt-tts button, the #tts-vol slider and the #tts-engine selection. */
|
|
120
118
|
reflectTts: () => void;
|
|
119
|
+
/**
|
|
120
|
+
* Shows ONE mixer category as the mixer holds it now โ its switch and its volume wherever this panel draws them, and the
|
|
121
|
+
* left-the-default marks โ without redrawing anything else. The host calls it for every change the mixer tells
|
|
122
|
+
* (`Audio.onCatChange`, ADR-0247): a category written by a game, the bar or another panel.
|
|
123
|
+
*/
|
|
124
|
+
reflectCategory: (cat: string) => void;
|
|
121
125
|
}
|
|
122
126
|
/**
|
|
123
127
|
* MOUNTS THIS PANEL'S INSIDE โ the controls and containers it reaches.
|
|
@@ -125,8 +129,9 @@ export interface SettingsAudioApi {
|
|
|
125
129
|
* ๐ด IT IS THE LARGEST INVISIBLE CONTRACT OF THE PANELS: this file looks for `#opt-modocego`, `#cane-div`,
|
|
126
130
|
* `#opt-menuindex`, `#opt-tts`, `#tts-vol` and more, and nothing in the type says so โ which is why it builds them.
|
|
127
131
|
*
|
|
128
|
-
* โ ๏ธ AND EACH ONE'S TAG MATTERS, which makes this the worst place to guess:
|
|
129
|
-
*
|
|
132
|
+
* โ ๏ธ AND EACH ONE'S TAG MATTERS, which makes this the worst place to guess: the voice selects have to be `<select>` โ the
|
|
133
|
+
* panel writes `.value` into them โ, the volumes `<input type=range>`, and `#cane-div` is the cycle row `caneRow` builds
|
|
134
|
+
* (a host's own `<select>` is still read). On a `<button>`,
|
|
130
135
|
* writing `.value` gives no error at all: it creates a property nobody reads, and the child's choice vanishes silently.
|
|
131
136
|
*
|
|
132
137
|
* ๐ THE ORDER IS THE DECISION (ADR-0044 ยง2), from general to particular (see the composition below).
|
|
@@ -13,7 +13,7 @@ import { toggleLabel } from './dom.js';
|
|
|
13
13
|
import { DEFAULTS } from '../core/setting-defaults.js';
|
|
14
14
|
import { markChanged, markMenuChanged } from './changed-mark.js';
|
|
15
15
|
import { defaultAudioCat } from '../platform/audio-mixer.js';
|
|
16
|
-
import { controlRow, labelRow } from './panel-widgets.js';
|
|
16
|
+
import { controlRow, labelRow, mountChoice, updateChoice } from './panel-widgets.js';
|
|
17
17
|
/*
|
|
18
18
|
* ๐ด THE VOICE SECTION LIVES IN `ui/voice-settings` (ADR-0221, issue #203): speech โ the narration switch, the engine, the
|
|
19
19
|
* voice, the rate, the spoken index and the test button โ and the sound categories, cane, blind mode and outputs never
|
|
@@ -27,14 +27,50 @@ import { createVoiceSettings } from './voice-settings.js';
|
|
|
27
27
|
* and the browser test drove the rest.
|
|
28
28
|
*/
|
|
29
29
|
import { NAV_CATS, GEN_CATS, volPercent, navMasterVolume, parseCaneDiv, caneDivMessage, sinksSupported, sinkOptionLabel, sinkSelectValue, } from './audio-choices.js';
|
|
30
|
+
/** The cane's two positions โ one tap per block, one every half block โ in the page's language. */
|
|
31
|
+
function canePositions(t) {
|
|
32
|
+
return [{ value: '1', label: t('audio.cane.block') }, { value: '2', label: t('audio.cane.halfBlock') }];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* THE CANE ROW, a CYCLE ROW ยซโ Batida da bengala: uma batida por bloco โถยป (ADR-0130 rule 3: two positions).
|
|
36
|
+
*
|
|
37
|
+
* ๐ด It was the kit's `escolha`, a `<select>` nobody filled: offered to every game with a walker, it opened on nothing to
|
|
38
|
+
* choose. Two positions are a cycle, and the positions are the engine's words.
|
|
39
|
+
*
|
|
40
|
+
* ๐ THE `<strong>` STAYS, HIDDEN: it is where the game's word for the cane lands (`ui/audio-rows-that-apply`, ADR-0153),
|
|
41
|
+
* and `renderAudio` reads it into the cycle's own text. `hidden` keeps it out of the accessibility tree, so the name is
|
|
42
|
+
* heard once โ from the control.
|
|
43
|
+
*/
|
|
44
|
+
function caneRow(t, ctx, spec) {
|
|
45
|
+
const row = ctx.create('div');
|
|
46
|
+
row.className = 'ctrl-row ctrl-row--passos';
|
|
47
|
+
const text = ctx.create('span');
|
|
48
|
+
const name = ctx.create('strong');
|
|
49
|
+
name.textContent = spec.label;
|
|
50
|
+
name.hidden = true;
|
|
51
|
+
text.appendChild(name);
|
|
52
|
+
if (spec.hint) {
|
|
53
|
+
const explanation = ctx.create('span');
|
|
54
|
+
explanation.className = 'opt-hint';
|
|
55
|
+
explanation.textContent = spec.hint;
|
|
56
|
+
text.appendChild(explanation);
|
|
57
|
+
}
|
|
58
|
+
row.appendChild(text);
|
|
59
|
+
// the pick is `initSettingsAudio`'s, which listens for the `change` every choice fires: this builder has no setter
|
|
60
|
+
const control = mountChoice(ctx, { label: spec.label, values: canePositions(t), current: '1' }, () => { });
|
|
61
|
+
control.id = spec.id;
|
|
62
|
+
row.appendChild(control);
|
|
63
|
+
return row;
|
|
64
|
+
}
|
|
30
65
|
/**
|
|
31
66
|
* MOUNTS THIS PANEL'S INSIDE โ the controls and containers it reaches.
|
|
32
67
|
*
|
|
33
68
|
* ๐ด IT IS THE LARGEST INVISIBLE CONTRACT OF THE PANELS: this file looks for `#opt-modocego`, `#cane-div`,
|
|
34
69
|
* `#opt-menuindex`, `#opt-tts`, `#tts-vol` and more, and nothing in the type says so โ which is why it builds them.
|
|
35
70
|
*
|
|
36
|
-
* โ ๏ธ AND EACH ONE'S TAG MATTERS, which makes this the worst place to guess:
|
|
37
|
-
*
|
|
71
|
+
* โ ๏ธ AND EACH ONE'S TAG MATTERS, which makes this the worst place to guess: the voice selects have to be `<select>` โ the
|
|
72
|
+
* panel writes `.value` into them โ, the volumes `<input type=range>`, and `#cane-div` is the cycle row `caneRow` builds
|
|
73
|
+
* (a host's own `<select>` is still read). On a `<button>`,
|
|
38
74
|
* writing `.value` gives no error at all: it creates a property nobody reads, and the child's choice vanishes silently.
|
|
39
75
|
*
|
|
40
76
|
* ๐ THE ORDER IS THE DECISION (ADR-0044 ยง2), from general to particular (see the composition below).
|
|
@@ -61,7 +97,8 @@ export function mountAudioInside(t, ctx, card, list) {
|
|
|
61
97
|
// โ ๏ธ Their own short keys, not the bar's `icon.blind`/`icon.tts`: those carry ยซ(navegaรงรฃo sonora)ยป and ยซ(TTS)ยป, and
|
|
62
98
|
// a row keeps no explanation in parentheses (ADR-0158).
|
|
63
99
|
{ id: 'opt-modocego', label: t('audio.modocego') },
|
|
64
|
-
|
|
100
|
+
// two positions, so a cycle row (ADR-0130 rule 3): built by `caneRow`, not by the kit
|
|
101
|
+
{ id: 'cane-div', label: t('audio.cane'), hint: t('audio.cane.dica') },
|
|
65
102
|
{ container: '@lista' }, // the shell's list: sonar, guard and guide
|
|
66
103
|
{ id: 'opt-tts', label: t('audio.narracao'), hint: t('audio.tts.dica') },
|
|
67
104
|
{ id: 'tts-vol', label: t('audio.ttsVol'), shape: 'cursor' },
|
|
@@ -115,7 +152,7 @@ export function mountAudioInside(t, ctx, card, list) {
|
|
|
115
152
|
labelRow(rowNode, piece);
|
|
116
153
|
continue;
|
|
117
154
|
}
|
|
118
|
-
card.insertBefore(controlRow(ctx, piece).row, actions);
|
|
155
|
+
card.insertBefore(piece.id === 'cane-div' ? caneRow(t, ctx, piece) : controlRow(ctx, piece).row, actions);
|
|
119
156
|
}
|
|
120
157
|
}
|
|
121
158
|
/**
|
|
@@ -364,31 +401,21 @@ export function initSettingsAudio(ctx) {
|
|
|
364
401
|
}
|
|
365
402
|
const players = ctx.getPlayers();
|
|
366
403
|
const n = Math.max(1, ctx.getNumPlayers());
|
|
404
|
+
/*
|
|
405
|
+
* ๐ด A PLAYER'S OUTPUT IS A CHOICE, AND ITS SIZE PICKS THE CONTROL (ADR-0130 rule 3): ยซsharedยป and up to four devices are
|
|
406
|
+
* a cycle row ยซโ Jogador 1: Fone USB โถยป, more a dropdown. The size is the room's today โ it is drawn again at every
|
|
407
|
+
* detection, so a fifth headset plugged in turns the rows into dropdowns.
|
|
408
|
+
*/
|
|
409
|
+
const outputs = [{ value: '', label: t('audio.sinkShared') }, ...devices.map((d, k) => ({ value: d.deviceId, label: sinkOptionLabel(t, d, k) }))];
|
|
367
410
|
for (let i = 0; i < n; i++) {
|
|
368
411
|
const p = players[i];
|
|
412
|
+
const name = t('audio.playerN', { n: i + 1 });
|
|
369
413
|
const row = make('div');
|
|
370
414
|
row.className = 'ctrl-row';
|
|
371
|
-
const
|
|
372
|
-
lbl.textContent = t('audio.playerN', { n: i + 1 });
|
|
373
|
-
lbl.htmlFor = 'sink-p' + i;
|
|
374
|
-
const sel = make('select');
|
|
375
|
-
sel.className = 'vol';
|
|
376
|
-
sel.id = 'sink-p' + i;
|
|
377
|
-
const o0 = make('option');
|
|
378
|
-
o0.value = '';
|
|
379
|
-
o0.textContent = t('audio.sinkShared');
|
|
380
|
-
sel.appendChild(o0);
|
|
381
|
-
devices.forEach((d, k) => {
|
|
382
|
-
const o = make('option');
|
|
383
|
-
o.value = d.deviceId;
|
|
384
|
-
o.textContent = sinkOptionLabel(t, d, k);
|
|
385
|
-
sel.appendChild(o);
|
|
386
|
-
});
|
|
387
|
-
sel.value = sinkSelectValue(p);
|
|
388
|
-
sel.addEventListener('change', () => {
|
|
415
|
+
const choice = mountChoice(kitCtx(el), { label: name, values: outputs, current: sinkSelectValue(p) }, (value) => {
|
|
389
416
|
if (!p)
|
|
390
417
|
return;
|
|
391
|
-
p.audioSink =
|
|
418
|
+
p.audioSink = value || null;
|
|
392
419
|
ctx.store.set('incl_sink_p' + i, p.audioSink || '');
|
|
393
420
|
if (p._ac) {
|
|
394
421
|
try {
|
|
@@ -400,8 +427,17 @@ export function initSettingsAudio(ctx) {
|
|
|
400
427
|
}
|
|
401
428
|
ctx.srSay(t(p.audioSink ? 'sr.audio.sinkChanged' : 'sr.audio.sinkDefault', { n: i + 1 }));
|
|
402
429
|
});
|
|
403
|
-
|
|
404
|
-
|
|
430
|
+
choice.id = 'sink-p' + i;
|
|
431
|
+
if (choice.tagName === 'SELECT') {
|
|
432
|
+
// a dropdown keeps its name beside it; a cycle row already carries it in its own text
|
|
433
|
+
const lbl = make('label');
|
|
434
|
+
lbl.textContent = name;
|
|
435
|
+
lbl.htmlFor = choice.id;
|
|
436
|
+
row.appendChild(lbl);
|
|
437
|
+
}
|
|
438
|
+
else
|
|
439
|
+
row.classList.add('ctrl-row--passos');
|
|
440
|
+
row.appendChild(choice);
|
|
405
441
|
el.appendChild(row);
|
|
406
442
|
}
|
|
407
443
|
}
|
|
@@ -438,9 +474,7 @@ export function initSettingsAudio(ctx) {
|
|
|
438
474
|
renderNavSound();
|
|
439
475
|
drawBlindMode();
|
|
440
476
|
voice.render();
|
|
441
|
-
|
|
442
|
-
if (cd)
|
|
443
|
-
cd.value = String(ctx.getCaneBlockDiv());
|
|
477
|
+
reflectCane();
|
|
444
478
|
void enumerateSinks(); // not awaited: fire and carry on (the asynchronous list updates by itself)
|
|
445
479
|
refreshMarks();
|
|
446
480
|
}
|
|
@@ -528,11 +562,28 @@ export function initSettingsAudio(ctx) {
|
|
|
528
562
|
ctx.srSay(t(ctx.getBlindMode() ? 'sr.blind.on' : 'sr.blind.off'));
|
|
529
563
|
});
|
|
530
564
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
565
|
+
/**
|
|
566
|
+
* The cane's position in use. A host's own `<select>` gets its value; the engine's cycle row (`caneRow`) its words and
|
|
567
|
+
* value, with its name read from the row's hidden `<strong>` โ where the game's word for the cane lands (ADR-0153).
|
|
568
|
+
*/
|
|
569
|
+
function reflectCane() {
|
|
570
|
+
const cd = ctx.$('#cane-div');
|
|
571
|
+
if (!cd)
|
|
572
|
+
return;
|
|
573
|
+
const current = String(ctx.getCaneBlockDiv());
|
|
574
|
+
if (cd.tagName === 'SELECT') {
|
|
575
|
+
cd.value = current;
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
const label = cd.closest('.ctrl-row')?.querySelector('strong')?.textContent || t('audio.cane');
|
|
579
|
+
updateChoice(cd, { label, values: canePositions(t), current });
|
|
580
|
+
}
|
|
581
|
+
const caneDiv = ctx.$('#cane-div');
|
|
582
|
+
if (caneDiv) {
|
|
583
|
+
reflectCane();
|
|
584
|
+
caneDiv.addEventListener('change', () => {
|
|
585
|
+
// a host's `<select>` holds its value; the engine's cycle row carries it in `data-value` (`mountChoice`)
|
|
586
|
+
const div = parseCaneDiv(caneDiv.tagName === 'SELECT' ? caneDiv.value : (caneDiv.dataset.value ?? ''));
|
|
536
587
|
ctx.setCaneBlockDiv(div);
|
|
537
588
|
ctx.srSay(caneDivMessage(t, div));
|
|
538
589
|
});
|
|
@@ -596,5 +647,20 @@ export function initSettingsAudio(ctx) {
|
|
|
596
647
|
* announce: the bar's icon already speaks for itself.
|
|
597
648
|
*/
|
|
598
649
|
ctx.on('blindMode', () => { drawBlindMode(); }); // through the root's door: released by its `dispose()`
|
|
599
|
-
|
|
650
|
+
/** One category, in place: the lists hold rows only once the panel has drawn them, and a row not there is not drawn here. */
|
|
651
|
+
function reflectCategory(k) {
|
|
652
|
+
if (k === 'tts')
|
|
653
|
+
voice.reflectTts();
|
|
654
|
+
for (const sel of ['#audio-list', '#navsound-list']) {
|
|
655
|
+
const list = ctx.$(sel);
|
|
656
|
+
if (list)
|
|
657
|
+
reflectCatRows(list, [k]);
|
|
658
|
+
}
|
|
659
|
+
const navMaster = ctx.$('#navsound-master');
|
|
660
|
+
const state = ctx.getAudioCat();
|
|
661
|
+
if (navMaster && state)
|
|
662
|
+
navMaster.value = String(navMasterVolume(state, NAV_CATS));
|
|
663
|
+
refreshMarks();
|
|
664
|
+
}
|
|
665
|
+
return { renderAudio, reflectBlindMode: drawBlindMode, reflectTts: voice.reflectTts, reflectCategory };
|
|
600
666
|
}
|
|
@@ -5,10 +5,6 @@ import type { KeyScheme } from '../core/entity.js';
|
|
|
5
5
|
import { type Action } from '../core/actions.js';
|
|
6
6
|
import type { KBDefaults } from '../input/keyboard.js';
|
|
7
7
|
import type { KeydownEventLike } from '../input/keydown.js';
|
|
8
|
-
/** Minimal DOM-selector shape (matches ui/dom.ts's `$`). */
|
|
9
|
-
export type { DomQuery } from '../core/dom-query.js';
|
|
10
|
-
/** action -> list of physical key codes (KeyboardEvent.code), e.g. {jump:['KeyJ','Space']}. */
|
|
11
|
-
export type { KeyScheme } from '../core/entity.js';
|
|
12
8
|
/** Opaque keyboard config (input/keyboard.ts's KBDefaults shape: {solo,p2,p3,p4}) โ never indexed directly here;
|
|
13
9
|
* all per-player reads go through the injected `kbFor`, so this module stays decoupled from its exact shape. */
|
|
14
10
|
/** `input/keyboard`'s `KBDefaults`, which is the owner. This module still does NOT INDEX the value โ every per-player
|
|
@@ -4,8 +4,6 @@ import type { Translate } from '../core/i18n.js';
|
|
|
4
4
|
import type { DomQuery } from '../core/dom-query.js';
|
|
5
5
|
import { type LatchPlayer as JogadorDaAlternanciaDaAresta } from '../input/latch-sync.js';
|
|
6
6
|
import type { PanelShellCtx } from './panel-shell.js';
|
|
7
|
-
/** Minimal DOM-selector shape (matches ui/dom.ts's `$`). */
|
|
8
|
-
export type { DomQuery } from '../core/dom-query.js';
|
|
9
7
|
/** Minimal platform/storage.ts shape this module needs. */
|
|
10
8
|
export interface MobilityStore {
|
|
11
9
|
setBool(key: string, on: boolean): void;
|
|
@@ -35,8 +33,7 @@ export interface SettingsMobilityCtx {
|
|
|
35
33
|
* panel.
|
|
36
34
|
*
|
|
37
35
|
* โ ๏ธ Not offering it means making the row absent for everyone, with `hidden`, which takes it off the screen AND out of
|
|
38
|
-
* the accessibility tree
|
|
39
|
-
* control EXISTS and is locked with a reason.
|
|
36
|
+
* the accessibility tree โ not an `aria-disabled` row that stays in the tab order doing nothing.
|
|
40
37
|
*
|
|
41
38
|
* โ ๏ธ REQUIRED, for the same reason as in `PauseIconsCtx`: there is no safe default. `true` leaves the row in a game
|
|
42
39
|
* where it does nothing; `false` hides it from a child who depends on it.
|
|
@@ -120,8 +117,8 @@ export declare function toggleMoveKey(i: number): string;
|
|
|
120
117
|
* flags. A minimal slice lets both pass without either carrying the other's.
|
|
121
118
|
*
|
|
122
119
|
* ๐ THE DEFINITION LIVES IN `input/latch-sync` (issue #127), beside the rule that uses it, and the NAME stays published
|
|
123
|
-
* here
|
|
124
|
-
*
|
|
120
|
+
* here, as an alias (ADR-0106 step 1a). Since issue #204 the names snapshot reads a re-export too, so either form keeps
|
|
121
|
+
* the name in this module's snapshot.
|
|
125
122
|
*/
|
|
126
123
|
export type LatchPlayer = JogadorDaAlternanciaDaAresta;
|
|
127
124
|
/** What the write needs to know. Everything here already lives in `SettingsMobilityCtx` and `PauseIconsCtx`. */
|
|
@@ -16,7 +16,6 @@ import { DEFAULTS } from '../core/setting-defaults.js';
|
|
|
16
16
|
import { KEYS } from '../platform/storage-keys.js';
|
|
17
17
|
import { writeLatch } from '../input/latch-store.js';
|
|
18
18
|
import { applyLatch, BASE_DA_MARCHA, } from '../input/latch-sync.js';
|
|
19
|
-
import { latchRefusal } from './latch-refusal.js';
|
|
20
19
|
import { clampSelPlayer, anyMobilityActive, onOffLabel, playerTabsHTML, easyAnnouncement, playerPrefix } from './mobility-choices.js';
|
|
21
20
|
import { controlRow, labelRow } from './panel-widgets.js';
|
|
22
21
|
// ---------------------------------------------------------------------------------------------
|
|
@@ -64,10 +63,8 @@ export function setMoveLatch(ctx, i, on) {
|
|
|
64
63
|
// reason: a cartridge may still READ it through `KEYS.toggleMoveP(i)`. Stopping writing it now would make the child
|
|
65
64
|
// lose the choice at the next boot โ the cost ADR-0113 names.
|
|
66
65
|
ctx.store.setBool(toggleMoveKey(i), on);
|
|
67
|
-
// ๐ And the NEW key, when the device is known
|
|
68
|
-
// choice
|
|
69
|
-
// Here the refusal changes nothing else: the in-memory value is still what the rule resolves, and the rule answers
|
|
70
|
-
// `true` on those four.
|
|
66
|
+
// ๐ And the NEW key, when the device is known โ on every device (ADR-0249): on eyes, face, gestures and speech this is the
|
|
67
|
+
// child's choice overriding the game's `holdsKeys()` default for that transport.
|
|
71
68
|
const transport = ctx.transportInUse ? ctx.transportInUse(i) : null;
|
|
72
69
|
if (transport)
|
|
73
70
|
writeLatch((key, isOn) => ctx.store.setBool(key, isOn), BASE_DA_MARCHA, i, transport, on);
|
|
@@ -164,32 +161,20 @@ export function initSettingsMobility(ctx) {
|
|
|
164
161
|
let selMovPlayer = 0; // the player selected in the mobility panel
|
|
165
162
|
const easyModeButton = ctx.$('#opt-facil');
|
|
166
163
|
const altMoveBtn = ctx.$('#opt-altmove');
|
|
167
|
-
/**
|
|
168
|
-
* THE ROW'S ORIGINAL HINT, kept once.
|
|
169
|
-
*
|
|
170
|
-
* โ ๏ธ HERE THE REFUSAL COMES AND GOES: this button is persistent, and the child may put the webcam down and go back to
|
|
171
|
-
* the keyboard โ without keeping the original text, the reason would pile up on the row with every device change.
|
|
172
|
-
*/
|
|
173
164
|
const altMoveRow = altMoveBtn?.closest('.ctrl-row') ?? null;
|
|
174
|
-
const altMoveHint = altMoveRow?.querySelector('.opt-hint') ?? null;
|
|
175
|
-
const originalHint = altMoveHint?.textContent ?? '';
|
|
176
165
|
/*
|
|
177
166
|
* ADR-0115 ยท THE ROW DISAPPEARS IN A GAME THAT HOLDS NOTHING โ and disappears for EVERYONE.
|
|
178
167
|
*
|
|
179
168
|
* ๐ด `hidden` and not `aria-disabled`: the child who depends on the latch opens this panel to switch it on, and in a
|
|
180
169
|
* quiz there is nothing to switch on. A control disabled with a reason is still a control that does nothing โ and it
|
|
181
170
|
* still takes a place in keyboard navigation, between two that work.
|
|
182
|
-
* ๐
|
|
183
|
-
*
|
|
171
|
+
* ๐ Where the game holds keys the row is offered on EVERY device, eyes and voice included (ADR-0249): there the latch
|
|
172
|
+
* starts as the game's answer, and this row is how the child changes it.
|
|
184
173
|
* โ ๏ธ `hidden` and not removal: the row may be the page's own markup, and `hidden` is reversible and idempotent where
|
|
185
174
|
* removing someone else's markup is neither.
|
|
186
175
|
*/
|
|
187
176
|
if (!ctx.holdsKeys && altMoveRow)
|
|
188
177
|
altMoveRow.hidden = true;
|
|
189
|
-
/** THIS player's refusal now, or `null`. Recomputed on every reflect: the device in use changes. */
|
|
190
|
-
function refusalFor(i) {
|
|
191
|
-
return ctx.transportInUse ? latchRefusal(ctx.transportInUse(i)) : null;
|
|
192
|
-
}
|
|
193
178
|
const toggleRunBtn = ctx.$('#opt-togglerun');
|
|
194
179
|
// the bar lights up if ANY player uses Easy Mode or a latch
|
|
195
180
|
function reflectMovementBtn() {
|
|
@@ -249,23 +234,6 @@ export function initSettingsMobility(ctx) {
|
|
|
249
234
|
altMoveBtn.classList.toggle('is-on', on);
|
|
250
235
|
altMoveBtn.setAttribute('aria-pressed', String(on));
|
|
251
236
|
altMoveBtn.textContent = onOffLabel(t, on);
|
|
252
|
-
/*
|
|
253
|
-
* โ ๏ธ CLAUSE 3 OF ADR-0113 ON SCREEN: where the latch is required, the control does NOT disappear โ it is
|
|
254
|
-
* `aria-disabled` and the reason goes into the hint, which the shell (`ui/settings-panel.fillExplain`) moves to the
|
|
255
|
-
* footer. Disappearing would teach that the thing does not exist; leaving it active would make the child press it
|
|
256
|
-
* and not understand why nothing changed.
|
|
257
|
-
*
|
|
258
|
-
* ๐ And `aria-disabled`, not `disabled`: a really disabled button LEAVES the tab order, and a keyboard user could no
|
|
259
|
-
* longer reach it โ so could no longer READ the reason. The same choice #128 names as a defect when made the other
|
|
260
|
-
* way (a CSS class only, no `aria`).
|
|
261
|
-
*/
|
|
262
|
-
const refusal = refusalFor(selMovPlayer);
|
|
263
|
-
if (refusal)
|
|
264
|
-
altMoveBtn.setAttribute('aria-disabled', 'true');
|
|
265
|
-
else
|
|
266
|
-
altMoveBtn.removeAttribute('aria-disabled');
|
|
267
|
-
if (altMoveHint)
|
|
268
|
-
altMoveHint.textContent = refusal ? `${originalHint} ${t(refusal.key)}`.trim() : originalHint;
|
|
269
237
|
}
|
|
270
238
|
reflectMovementBtn();
|
|
271
239
|
}
|
|
@@ -308,16 +276,6 @@ export function initSettingsMobility(ctx) {
|
|
|
308
276
|
}
|
|
309
277
|
if (altMoveBtn) {
|
|
310
278
|
altMoveBtn.addEventListener('click', () => {
|
|
311
|
-
/*
|
|
312
|
-
* โ ๏ธ REFUSE BY SAYING, NOT IN SILENCE. The listener is wired once, and a mute `return` would accept the click and
|
|
313
|
-
* ignore it โ the other half of what ADR-0076 forbids. So the refusal SPEAKS: whoever pressed learns why, even
|
|
314
|
-
* without seeing the hint.
|
|
315
|
-
*/
|
|
316
|
-
const refusal = refusalFor(selMovPlayer);
|
|
317
|
-
if (refusal) {
|
|
318
|
-
ctx.srSay(t(refusal.key));
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
279
|
setToggleMove(selMovPlayer, !ctx.players[selMovPlayer].toggleMove);
|
|
322
280
|
reflectAltMove();
|
|
323
281
|
});
|
|
@@ -16,8 +16,8 @@ import { SCENE_KEYS, CHARACTER_ANIMATIONS, readStoredScene, storeScene } from '.
|
|
|
16
16
|
* ๐ THE PURE HALF LIVES IN `ui/motion-choices` (ADR-0221), and the SUITE pointed at the seam:
|
|
17
17
|
* `tests/settings-motion.node.test.js` exercises exactly these names, and the node project mounts no document.
|
|
18
18
|
*
|
|
19
|
-
* โ ๏ธ NO ALIAS: a re-export would keep alive a path nothing in here uses
|
|
20
|
-
*
|
|
19
|
+
* โ ๏ธ NO ALIAS: a re-export would keep alive a published path nothing in here uses โ surface with no consumer
|
|
20
|
+
* (issue #204).
|
|
21
21
|
*/
|
|
22
22
|
import { RM_LABEL, CRT_LBL, CRT_ROUND_LEVELS, clampSelectedPlayer, allMotionFrozen, motionMasterLabel, sceneMotionAnnouncement, crtToggleAnnouncement, crtLevelLabel, crtRoundAnnouncement, stopResumeAllAnnouncement, } from './motion-choices.js';
|
|
23
23
|
/*
|
|
@@ -62,6 +62,16 @@ export interface SettingsPanelApi {
|
|
|
62
62
|
escapeTarget: () => string | null;
|
|
63
63
|
/** The highest VISIBLE overlay in the stack. A z tie: the last in the DOM wins. */
|
|
64
64
|
topVisibleOverlay: () => HTMLElement | null;
|
|
65
|
+
/**
|
|
66
|
+
* Draws the MODAL BOUNDARY at the front card (ADR-0130 rule 1): every visible layer under it โ the other overlays and
|
|
67
|
+
* the pause cards โ is `inert`, and nothing is when no overlay is open. Opening, `restoreFocus` and `closeById` call it themselves
|
|
68
|
+
* (the last two BEFORE any focus goes back, since an inert element refuses focus); a host whose dialogs can also be hidden by paths that
|
|
69
|
+
* return no focus calls it when a `hidden` changes โ `createGame` does, from its observer.
|
|
70
|
+
*
|
|
71
|
+
* OPTIONAL in the type only: `initSettingsPanel` always returns it, and an API built elsewhere (a host's own double of
|
|
72
|
+
* this shell) keeps compiling without a boundary to draw.
|
|
73
|
+
*/
|
|
74
|
+
syncLayers?: () => void;
|
|
65
75
|
/** Registered ids, in order โ for tests/debugging only. */
|
|
66
76
|
registeredIds: () => string[];
|
|
67
77
|
}
|