@the-inclusionist/engine 9.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 +120 -78
- package/app/css/style.css +761 -377
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- 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 +36 -84
- package/dist-pkg/boot/create-game.d.ts +499 -219
- package/dist-pkg/boot/create-game.js +3944 -562
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +38 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +125 -0
- package/dist-pkg/core/accommodations.js +195 -0
- package/dist-pkg/core/actions.d.ts +108 -55
- package/dist-pkg/core/actions.js +122 -71
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +142 -164
- package/dist-pkg/core/contract.js +222 -208
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +71 -60
- package/dist-pkg/core/i18n.js +186 -200
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +324 -223
- package/dist-pkg/i18n/es.js +323 -223
- package/dist-pkg/i18n/pt.js +348 -226
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +195 -145
- package/dist-pkg/input/gamepad.js +383 -556
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- 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 +15 -21
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -63
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +123 -137
- package/dist-pkg/input/keydown.js +284 -289
- package/dist-pkg/input/latch-edge.d.ts +33 -21
- package/dist-pkg/input/latch-edge.js +34 -35
- package/dist-pkg/input/latch-scope.d.ts +51 -50
- package/dist-pkg/input/latch-scope.js +61 -82
- package/dist-pkg/input/latch-store.d.ts +26 -30
- package/dist-pkg/input/latch-store.js +42 -50
- package/dist-pkg/input/latch-sync.d.ts +29 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +169 -0
- package/dist-pkg/input/pad-wizard.d.ts +99 -0
- package/dist-pkg/input/pad-wizard.js +256 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +59 -0
- package/dist-pkg/input/switch-scan.js +67 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -116
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +147 -72
- package/dist-pkg/input/touch.js +362 -126
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +90 -117
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +82 -0
- package/dist-pkg/input/virtual-controller.js +69 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +59 -0
- package/dist-pkg/input/voice-map.js +123 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -2
- package/dist-pkg/platform/audio-ambient.js +14 -14
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +31 -39
- package/dist-pkg/platform/audio-sonar.d.ts +49 -152
- package/dist-pkg/platform/audio-sonar.js +124 -302
- package/dist-pkg/platform/audio.d.ts +62 -19
- package/dist-pkg/platform/audio.js +193 -168
- 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/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -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 +77 -0
- package/dist-pkg/platform/heavy-catalogue.js +256 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
- package/dist-pkg/platform/heavy-mirror.js +73 -0
- package/dist-pkg/platform/heavy.d.ts +136 -0
- package/dist-pkg/platform/heavy.js +324 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
- package/dist-pkg/platform/interruptible-speech.js +77 -54
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +90 -0
- package/dist-pkg/platform/locale-host.d.ts +14 -0
- package/dist-pkg/platform/locale-host.js +45 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
- package/dist-pkg/platform/reading-in-worker.js +125 -0
- package/dist-pkg/platform/reading-model.d.ts +94 -0
- package/dist-pkg/platform/reading-model.js +272 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +164 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +80 -0
- package/dist-pkg/platform/reading.js +136 -0
- package/dist-pkg/platform/speech-recognition.d.ts +60 -0
- package/dist-pkg/platform/speech-recognition.js +104 -0
- package/dist-pkg/platform/speech.d.ts +23 -1
- package/dist-pkg/platform/speech.js +29 -18
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +85 -39
- package/dist-pkg/platform/tts.js +447 -127
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +40 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +15 -98
- package/dist-pkg/platform/voice-plan.js +56 -143
- package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
- package/dist-pkg/platform/vosk-runtime.js +151 -0
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +48 -12
- package/dist-pkg/render/crt.js +78 -80
- package/dist-pkg/render/cvd-matrices.d.ts +22 -18
- package/dist-pkg/render/cvd-matrices.js +37 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +67 -56
- package/dist-pkg/render/high-contrast.js +226 -217
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +89 -86
- package/dist-pkg/render/viz-axes.js +128 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +45 -0
- package/dist-pkg/ui/aac-sets.js +41 -0
- package/dist-pkg/ui/audio-choices.d.ts +68 -0
- package/dist-pkg/ui/audio-choices.js +98 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +53 -0
- package/dist-pkg/ui/camera-control.js +48 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +94 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +157 -68
- package/dist-pkg/ui/fonts.js +305 -115
- 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 +47 -0
- package/dist-pkg/ui/game-options.js +158 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +87 -0
- package/dist-pkg/ui/help-panel.js +242 -0
- package/dist-pkg/ui/hud-bands.d.ts +62 -0
- package/dist-pkg/ui/hud-bands.js +146 -0
- 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 +73 -73
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +117 -99
- 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/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +61 -0
- package/dist-pkg/ui/menu-intent.js +88 -0
- package/dist-pkg/ui/menu-items.d.ts +20 -0
- package/dist-pkg/ui/menu-items.js +51 -0
- package/dist-pkg/ui/menu-nav.d.ts +98 -92
- package/dist-pkg/ui/menu-nav.js +398 -286
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +150 -0
- package/dist-pkg/ui/panel-widgets.js +294 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +261 -347
- package/dist-pkg/ui/pause-icons.js +671 -601
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +50 -0
- 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 +70 -0
- package/dist-pkg/ui/settings-aac.js +208 -0
- package/dist-pkg/ui/settings-audio.d.ts +97 -114
- package/dist-pkg/ui/settings-audio.js +493 -425
- package/dist-pkg/ui/settings-controls.d.ts +53 -96
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +192 -0
- package/dist-pkg/ui/settings-mobility.js +332 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +58 -45
- package/dist-pkg/ui/settings-panel.js +189 -94
- package/dist-pkg/ui/settings-typo.d.ts +29 -78
- package/dist-pkg/ui/settings-typo.js +158 -129
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +112 -135
- package/dist-pkg/ui/shell.js +148 -217
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +3 -12
- package/dist-pkg/ui/title.js +49 -18
- package/dist-pkg/ui/top-band.d.ts +26 -0
- package/dist-pkg/ui/top-band.js +96 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +85 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +77 -10
- package/dist-pkg/ui/vlibras.js +130 -81
- package/dist-pkg/ui/voice-control.d.ts +68 -0
- package/dist-pkg/ui/voice-control.js +276 -0
- package/dist-pkg/ui/voice-settings.d.ts +95 -0
- package/dist-pkg/ui/voice-settings.js +352 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +300 -44
- package/docs/LICENSES.md +189 -145
- package/package.json +51 -27
- 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 +388 -0
- 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/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -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 +301 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.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/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.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/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.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/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/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/ufmag-400.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/guide-intensity.d.ts +0 -40
- package/dist-pkg/platform/guide-intensity.js +0 -73
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/latch-refusal.d.ts +0 -32
- package/dist-pkg/ui/latch-refusal.js +0 -60
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// ui/top-band.ts — HOW MUCH SPACE THE ENGINE KEEPS FOR ITSELF AT THE TOP OF THE SCREEN (ADR-0148 §3; issue #160).
|
|
3
|
+
//
|
|
4
|
+
// The engine draws things over the game — the accessibility bar, the name of the pointed icon, the HUD's mission line
|
|
5
|
+
// under the bar (the rest of the HUD is a row at the bottom, `ui/hud-row`) and the scan chip — and the game has to know how much of the top is not its own. This module measures what is there and
|
|
6
|
+
// writes three variables on the region: `--barra-a11y-h`, the whole band, `--scan-top`, where the chip sits, and
|
|
7
|
+
// `--hud-mission-top`, where the mission stands under the bar (0 with no bar) — which the stylesheet reads for the bands a
|
|
8
|
+
// caller mounts on the region with no HUD row, since those never pass through here.
|
|
9
|
+
//
|
|
10
|
+
// 📌 It is a calculation, not wiring, which is exactly what a composition root should not hold (Seemann; Fowler): a root
|
|
11
|
+
// is large because it connects many things, not because it decides (ADR-0221).
|
|
12
|
+
//
|
|
13
|
+
// ⚠️ IT RECEIVES THE NODES AND THE MEASURER, and never reaches a global: this module's global reach is ZERO, which is
|
|
14
|
+
// what lets it be measured in a document that is not the browser's.
|
|
15
|
+
//
|
|
16
|
+
// 🔴 THE ORDER OF THE TWO WRITES IS THE DECISION: the chip is placed by `--scan-top`, which does NOT depend on it; only the
|
|
17
|
+
// band does. Placing it by the band it makes grow creates a loop — the chip pushes the band, the band pushes the chip,
|
|
18
|
+
// and it walks down the screen on every measurement. A loop is invisible to a single measurement, so the case that
|
|
19
|
+
// holds it measures the chip, lets the scan advance three steps — which is what re-measures the band in real use — and
|
|
20
|
+
// demands the same place.
|
|
21
|
+
/** A quarter of the scale's base, resolved BY THE STYLESHEET through a probe, so the rule has one home. */
|
|
22
|
+
function breathingRoom(region, fallback) {
|
|
23
|
+
const probe = region.ownerDocument.createElement('div');
|
|
24
|
+
// A quarter of the scale's base size, not of the name's: a face with a higher floor grows its TEXT, not this gap
|
|
25
|
+
// (#172). `--espaco-fixo` is what shrinks with Ctrl −.
|
|
26
|
+
probe.style.cssText = 'position:absolute;visibility:hidden;height:calc(var(--ui-fs,16px) / 4 * var(--espaco-fixo,1))';
|
|
27
|
+
region.appendChild(probe);
|
|
28
|
+
const h = probe.getBoundingClientRect().height || fallback;
|
|
29
|
+
probe.remove();
|
|
30
|
+
return h;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The room the bar asks for: its bottom, or the bottom of the pointed icon's NAME line, plus breathing room.
|
|
34
|
+
*
|
|
35
|
+
* 📌 The name line counts whether or not it is showing a name — reserving only while pointing would move the game under
|
|
36
|
+
* the child's finger, and leaving it out lets the name cover the top of the game.
|
|
37
|
+
*/
|
|
38
|
+
function barRoom(ctx, top) {
|
|
39
|
+
const { region, bar, computedStyle } = ctx;
|
|
40
|
+
if (!region || !bar || typeof bar.getBoundingClientRect !== 'function')
|
|
41
|
+
return { room: 0, breath: 4 };
|
|
42
|
+
let bottom = bar.getBoundingClientRect().bottom;
|
|
43
|
+
let breath = 0;
|
|
44
|
+
const name = bar.querySelector('.pause-icons-cap');
|
|
45
|
+
if (name && computedStyle) {
|
|
46
|
+
const cs = computedStyle(name);
|
|
47
|
+
const fs = parseFloat(cs.fontSize) || 16;
|
|
48
|
+
const line = (parseFloat(cs.lineHeight) || fs * 1.2) + (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
|
|
49
|
+
bottom = name.getBoundingClientRect().top + line;
|
|
50
|
+
breath = breathingRoom(region, fs / 4);
|
|
51
|
+
}
|
|
52
|
+
return { room: bottom - top + breath, breath };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Where the mission sits, and the room it asks for: TOP CENTRE, just under the quick bar (ADR-0239 erratum), a light gap
|
|
56
|
+
* below the bar's own box. 📌 The bar's momentary name line may cover it while a name shows — the Dev's call: «a legenda é
|
|
57
|
+
* momentânea, a escrita da missão aparece o tempo todo» — so the mission is placed by the BAR and not by the name line, and
|
|
58
|
+
* the room below the top counts whichever of the two reaches lower.
|
|
59
|
+
*/
|
|
60
|
+
function hudRoom(ctx, top, breath, room, under) {
|
|
61
|
+
const { region, hud } = ctx;
|
|
62
|
+
if (!region || !hud || hud.left.hidden)
|
|
63
|
+
return room;
|
|
64
|
+
hud.left.style.top = under;
|
|
65
|
+
return Math.max(room, hud.left.getBoundingClientRect().bottom - top + Math.max(breath, 4));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Measures the top and writes `--hud-mission-top`, `--scan-top` and `--barra-a11y-h` on the region.
|
|
69
|
+
*
|
|
70
|
+
* 🔴 THE SCAN CHIP TAKES ROOM FOR THE SAME REASON AS THE NAME LINE (ADR-0218): it is HUD, and HUD that does not reserve its
|
|
71
|
+
* space is the engine writing over the game. But it is PLACED by `--scan-top`, written BEFORE it widens the room; see
|
|
72
|
+
* the loop in the header.
|
|
73
|
+
*/
|
|
74
|
+
export function reserveTopBand(ctx) {
|
|
75
|
+
const { region } = ctx;
|
|
76
|
+
if (!region || typeof region.style?.setProperty !== 'function')
|
|
77
|
+
return;
|
|
78
|
+
const measures = typeof region.getBoundingClientRect === 'function';
|
|
79
|
+
if (!measures) {
|
|
80
|
+
region.style.setProperty('--barra-a11y-h', '0px');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const top = region.getBoundingClientRect().top;
|
|
84
|
+
const { room: barPart, breath } = barRoom(ctx, top);
|
|
85
|
+
// the mission's place: just under the bar's own box, by the light gap — also for bands a caller mounts on the region with no
|
|
86
|
+
// row, which the stylesheet places by `--hud-mission-top`; with no bar there is nothing to stand under, and '' removes it
|
|
87
|
+
const barBox = ctx.bar && typeof ctx.bar.getBoundingClientRect === 'function' ? ctx.bar.getBoundingClientRect() : null;
|
|
88
|
+
const under = barBox ? `${Math.ceil(barBox.bottom - top + Math.max(breath, 4))}px` : '';
|
|
89
|
+
region.style.setProperty('--hud-mission-top', under);
|
|
90
|
+
let room = hudRoom(ctx, top, breath, barPart, under);
|
|
91
|
+
region.style.setProperty('--scan-top', `${Math.ceil(Math.max(0, room - breath))}px`);
|
|
92
|
+
const chip = region.querySelector('.scan-now');
|
|
93
|
+
if (chip && !chip.hidden)
|
|
94
|
+
room = Math.max(0, room - breath) + chip.getBoundingClientRect().height + breath;
|
|
95
|
+
region.style.setProperty('--barra-a11y-h', `${Math.ceil(room)}px`);
|
|
96
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Translate } from '../core/i18n.js';
|
|
3
|
+
import { type FontItem } from './fonts.js';
|
|
4
|
+
import type { ControlRowSpec } from './panel-widgets.js';
|
|
5
|
+
/**
|
|
6
|
+
* A key is selectable when it exists in the catalog, is not marked `.off` (licence pending, etc.) — and is
|
|
7
|
+
* `geral`.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ WITHOUT THE THIRD TERM (issue #87) the menu would stop OFFERING the handwriting faces and they would stay
|
|
10
|
+
* SELECTABLE by any other path — `resolveFontKey` of a stored key, a `data-font` in a consumer's markup. "Not in the
|
|
11
|
+
* list" and "cannot be chosen" have to be the same statement, or the list is only a suggestion.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isSelectableFont(k: string, installed?: (family: string) => boolean): boolean;
|
|
14
|
+
export interface FontCssTarget {
|
|
15
|
+
/** Value written to root.dataset.fonte. */
|
|
16
|
+
font: 'padrao' | 'alfabetizacao' | 'dislexia' | 'custom';
|
|
17
|
+
/** Value for the --font-custom CSS property, or null to remove the property. */
|
|
18
|
+
customFamily: string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Is this a JOINED face? (ADR-0149 §3.)
|
|
21
|
+
*
|
|
22
|
+
* 🔴 It drives `data-cursiva` on the root, which is what removes the BDA letter/word spacing. Letter
|
|
23
|
+
* spacing on a joined face pulls the letters apart at exactly the joins that make it cursive — the spacing
|
|
24
|
+
* meant to help reading would destroy the thing being read. The Dev's words: «para manter os conectores».
|
|
25
|
+
*
|
|
26
|
+
* 📌 Read off `FontItem.fb` rather than a new field: the catalogue already tells cursive faces apart, and a
|
|
27
|
+
* second source for the same fact is a second place for it to drift.
|
|
28
|
+
*/
|
|
29
|
+
cursive: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Maps a selectable font key to the CSS it drives. The three canonical fonts (atkinson/andika/lexend) use
|
|
33
|
+
* dedicated data-fonte values (Lexend's keeps the BDA letter/word spacing tied to data-fonte="dislexia"); every
|
|
34
|
+
* other catalog font goes through --font-custom with a generic fallback by family (serif/cursive/none).
|
|
35
|
+
*/
|
|
36
|
+
export declare function fontCssTarget(k: string, it: FontItem): FontCssTarget;
|
|
37
|
+
export interface TypoRow {
|
|
38
|
+
key: string;
|
|
39
|
+
fam: string;
|
|
40
|
+
selected: boolean;
|
|
41
|
+
disabled: boolean;
|
|
42
|
+
/** Description (+ "— <notice>") (+ "— <off reason>" when disabled), or '' when there is none. */
|
|
43
|
+
note: string;
|
|
44
|
+
}
|
|
45
|
+
export interface TypoGroupView {
|
|
46
|
+
g: string;
|
|
47
|
+
rows: TypoRow[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* ONE row of the list, from a catalogue face. A function of its own so the gate of the `.off` mechanism can exercise it
|
|
51
|
+
* with a FAKE face: a case that depends on the catalogue's composition fails every time the roster changes.
|
|
52
|
+
*
|
|
53
|
+
* The note is up to three halves: the description, the `notice` that always speaks (the ronde's three faces to install,
|
|
54
|
+
* ADR-0154), and the `off` reason while the face is disabled.
|
|
55
|
+
*/
|
|
56
|
+
export declare function fontRow(t: Translate, it: FontItem, fontKey: string, installed?: (family: string) => boolean): TypoRow;
|
|
57
|
+
/** Pure view-model for the typography list: which row is selected/disabled and its note, per catalog group. */
|
|
58
|
+
export declare function typoGroups(t: Translate, fontKey: string, installed?: (family: string) => boolean): TypoGroupView[];
|
|
59
|
+
/** The id of a face's button. It comes from the catalogue KEY, which is unique by construction (`FONT_BY_KEY`). */
|
|
60
|
+
export declare const typoControlId: (key: string) => string;
|
|
61
|
+
/**
|
|
62
|
+
* What a font row SAYS, before any node exists — the shape the kit consumes.
|
|
63
|
+
*
|
|
64
|
+
* ⚠️ `shape: 'radio'` and not a switch: independent switches announcing on/off to choose ONE font say the opposite of
|
|
65
|
+
* the ADR-0012 amendment, «THE MENU IS A CHOICE, NOT A TOGGLE […] One font is active; the others are alternatives, not
|
|
66
|
+
* switches.»
|
|
67
|
+
*
|
|
68
|
+
* 📌 The note goes into the HINT — which `fillExplain` takes to the footer — and ALSO into the accessible name, because
|
|
69
|
+
* whoever does not see the row needs to hear who that face is for without hunting for the footer.
|
|
70
|
+
*/
|
|
71
|
+
export declare function typoRowSpec(row: TypoRow): ControlRowSpec;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { FONT_GROUPS, FONT_BY_KEY, fontRole, faceAvailable, familyStack } from './fonts.js';
|
|
3
|
+
/**
|
|
4
|
+
* A key is selectable when it exists in the catalog, is not marked `.off` (licence pending, etc.) — and is
|
|
5
|
+
* `geral`.
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ WITHOUT THE THIRD TERM (issue #87) the menu would stop OFFERING the handwriting faces and they would stay
|
|
8
|
+
* SELECTABLE by any other path — `resolveFontKey` of a stored key, a `data-font` in a consumer's markup. "Not in the
|
|
9
|
+
* list" and "cannot be chosen" have to be the same statement, or the list is only a suggestion.
|
|
10
|
+
*/
|
|
11
|
+
export function isSelectableFont(k, installed) {
|
|
12
|
+
const it = FONT_BY_KEY[k];
|
|
13
|
+
return !!it && faceAvailable(it, installed) && fontRole(it) === 'geral';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Maps a selectable font key to the CSS it drives. The three canonical fonts (atkinson/andika/lexend) use
|
|
17
|
+
* dedicated data-fonte values (Lexend's keeps the BDA letter/word spacing tied to data-fonte="dislexia"); every
|
|
18
|
+
* other catalog font goes through --font-custom with a generic fallback by family (serif/cursive/none).
|
|
19
|
+
*/
|
|
20
|
+
export function fontCssTarget(k, it) {
|
|
21
|
+
// ⚠️ THE THREE CANONICAL FACES ARE NOT CURSIVE, and answering `false` for them is a statement, not an oversight:
|
|
22
|
+
// Atkinson, Andika and Lexend are reading faces, and it is exactly on them that the BDA spacing must hold.
|
|
23
|
+
if (k === 'atkinson')
|
|
24
|
+
return { font: 'padrao', customFamily: null, cursive: false };
|
|
25
|
+
if (k === 'andika')
|
|
26
|
+
return { font: 'alfabetizacao', customFamily: null, cursive: false };
|
|
27
|
+
if (k === 'lexend')
|
|
28
|
+
return { font: 'dislexia', customFamily: null, cursive: false };
|
|
29
|
+
// `joined` is the word the field's own documentation uses — "is this a JOINED face?".
|
|
30
|
+
const joined = it.fb === 'cursive';
|
|
31
|
+
const suffix = it.fb === 'serif' ? ',Georgia,serif' : joined ? ',cursive' : '';
|
|
32
|
+
// Each family quoted on its own (`familyStack`): the ronde's stack must reach Cookie, its packaged fallback (ADR-0154).
|
|
33
|
+
return { font: 'custom', customFamily: `${familyStack(it.fam)}${suffix}`, cursive: joined };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* ONE row of the list, from a catalogue face. A function of its own so the gate of the `.off` mechanism can exercise it
|
|
37
|
+
* with a FAKE face: a case that depends on the catalogue's composition fails every time the roster changes.
|
|
38
|
+
*
|
|
39
|
+
* The note is up to three halves: the description, the `notice` that always speaks (the ronde's three faces to install,
|
|
40
|
+
* ADR-0154), and the `off` reason while the face is disabled.
|
|
41
|
+
*/
|
|
42
|
+
export function fontRow(t, it, fontKey, installed) {
|
|
43
|
+
// ⚠️ THE SAME question `isSelectableFont` asks, through the SAME function. Two answers would give a clickable row the
|
|
44
|
+
// click refuses — or, worse, a grey row that `resolveFontKey` accepts by another path. "Not available" and "cannot be
|
|
45
|
+
// chosen" have to be the same statement.
|
|
46
|
+
const disabled = !faceAvailable(it, installed);
|
|
47
|
+
// `d`, `notice` and `off` hold KEYS too. The dash joining them is punctuation, not a sentence — the halves are
|
|
48
|
+
// independent and each translates on its own.
|
|
49
|
+
const note = [it.d, it.notice, disabled ? it.off : undefined]
|
|
50
|
+
.filter((k) => !!k).map((k) => t(k)).join(' — ');
|
|
51
|
+
return { key: it.k, fam: it.fam, selected: fontKey === it.k, disabled, note };
|
|
52
|
+
}
|
|
53
|
+
/** Pure view-model for the typography list: which row is selected/disabled and its note, per catalog group. */
|
|
54
|
+
export function typoGroups(t, fontKey, installed) {
|
|
55
|
+
// ⚠️ ONLY THE GENERAL FACES ENTER THE LIST (ADR-0012 amendment, issue #87). The handwriting faces exist for the child
|
|
56
|
+
// to LEARN to read cursive — that is subject matter, and it lives INSIDE the activities, on buttons of their own.
|
|
57
|
+
// Offering them here would hand the child the subject as an obstacle everywhere they only want to navigate the menu.
|
|
58
|
+
//
|
|
59
|
+
// A group left with no general face disappears from the list, instead of appearing as an empty heading.
|
|
60
|
+
return FONT_GROUPS.map((g) => ({
|
|
61
|
+
g: t(g.g), // `g` holds an i18n KEY (see ui/fonts)
|
|
62
|
+
rows: g.items.filter((it) => fontRole(it) === 'geral').map((it) => fontRow(t, it, fontKey, installed)),
|
|
63
|
+
})).filter((group) => group.rows.length > 0);
|
|
64
|
+
}
|
|
65
|
+
/** The id of a face's button. It comes from the catalogue KEY, which is unique by construction (`FONT_BY_KEY`). */
|
|
66
|
+
export const typoControlId = (key) => `typo-font-${key}`;
|
|
67
|
+
/**
|
|
68
|
+
* What a font row SAYS, before any node exists — the shape the kit consumes.
|
|
69
|
+
*
|
|
70
|
+
* ⚠️ `shape: 'radio'` and not a switch: independent switches announcing on/off to choose ONE font say the opposite of
|
|
71
|
+
* the ADR-0012 amendment, «THE MENU IS A CHOICE, NOT A TOGGLE […] One font is active; the others are alternatives, not
|
|
72
|
+
* switches.»
|
|
73
|
+
*
|
|
74
|
+
* 📌 The note goes into the HINT — which `fillExplain` takes to the footer — and ALSO into the accessible name, because
|
|
75
|
+
* whoever does not see the row needs to hear who that face is for without hunting for the footer.
|
|
76
|
+
*/
|
|
77
|
+
export function typoRowSpec(row) {
|
|
78
|
+
return {
|
|
79
|
+
id: typoControlId(row.key),
|
|
80
|
+
label: row.fam,
|
|
81
|
+
...(row.note ? { hint: row.note } : {}),
|
|
82
|
+
shape: 'radio',
|
|
83
|
+
ariaLabel: row.fam + (row.note ? ' — ' + row.note : ''),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -1,48 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
5
|
-
|
|
6
|
-
export declare const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* é o que mantém a mesma palavra nos dois sítios.
|
|
14
|
-
*/
|
|
15
|
-
export declare const CURTO_DO_TEMA: Readonly<Record<Tema, string>>;
|
|
16
|
-
export declare const CURTO_DA_CORRECAO: Readonly<Record<Correcao, string>>;
|
|
17
|
-
/** Os dois eixos, como o painel os identifica no DOM. */
|
|
18
|
-
export type EixoVisual = 'tema' | 'correcao';
|
|
19
|
-
/** Um tradutor, igual ao que o resto da interface recebe. */
|
|
20
|
-
export type Tradutor = (chave: string, params?: Record<string, string | number>) => string;
|
|
21
|
-
/**
|
|
22
|
-
* As linhas de UM eixo, no formato de rádio que o painel já usa.
|
|
23
|
-
*
|
|
24
|
-
* ⚠️ RÁDIO E NÃO SETE BOTÕES, e o motivo sobrevive à divisão: DENTRO de um eixo os valores continuam
|
|
25
|
-
* exclusivos — um tema de cada vez, uma correção de cada vez. O que deixou de ser exclusivo é a relação
|
|
26
|
-
* ENTRE os eixos, e é por isso que eles viram dois rádios em vez de um.
|
|
27
|
-
*
|
|
28
|
-
* ⚠️ E MANTÉM-SE A FORMA DE LINHA VISÍVEL, não um `<select>`. O `settings-visual` regista o erro que o Dev
|
|
29
|
-
* apanhou na primeira tentativa: dentro de uma caixa fechada, um controle cuja razão de existir é ser ACHADO
|
|
30
|
-
* por quem enxerga mal fica «quase o mesmo que não ter movido».
|
|
31
|
-
*/
|
|
32
|
-
export declare function linhasDoEixo(eixo: EixoVisual, valores: readonly string[], rotulos: Readonly<Record<string, string>>, atual: string, t: Tradutor): string;
|
|
33
|
-
/**
|
|
34
|
-
* Os DOIS eixos, um a seguir ao outro, com um título cada.
|
|
35
|
-
*
|
|
36
|
-
* O título existe porque dois rádios seguidos sem nome são um rádio de oito para quem lê depressa — e essa
|
|
37
|
-
* leitura é exactamente o mal-entendido que a divisão existe para desfazer.
|
|
38
|
-
*/
|
|
39
|
-
export declare function eixosHtml(v: VisualState, t: Tradutor): string;
|
|
40
|
-
/** O que um clique num botão do painel quer dizer. `null` quando o botão não é de eixo nenhum. */
|
|
41
|
-
export interface EscolhaDeEixo {
|
|
42
|
-
readonly eixo: EixoVisual;
|
|
43
|
-
readonly valor: string;
|
|
44
|
-
}
|
|
45
|
-
export declare function escolhaDoBotao(dataset: {
|
|
46
|
-
eixo?: string;
|
|
47
|
-
valor?: string;
|
|
48
|
-
}): EscolhaDeEixo | null;
|
|
2
|
+
import { axisRows as linhasDoEixoDeRender, axesHtml as eixosHtmlDeRender, buttonChoice as escolhaDoBotaoDeRender, type VisualAxis as EixoVisualDeRender, type Translator as TradutorDeRender, type AxisChoice as EscolhaDeEixoDeRender } from '../render/viz-axes-labels.js';
|
|
3
|
+
export declare const THEME_LABEL: Readonly<Record<import("../core/visual-state.js").Theme, string>>;
|
|
4
|
+
export declare const CORRECTION_LABEL: Readonly<Record<import("../core/visual-state.js").Correction, string>>;
|
|
5
|
+
export declare const SHORT_THEME: Readonly<Record<import("../core/visual-state.js").Theme, string>>;
|
|
6
|
+
export declare const SHORT_CORRECTION: Readonly<Record<import("../core/visual-state.js").Correction, string>>;
|
|
7
|
+
export declare const axisRows: typeof linhasDoEixoDeRender;
|
|
8
|
+
export declare const axesHtml: typeof eixosHtmlDeRender;
|
|
9
|
+
export declare const buttonChoice: typeof escolhaDoBotaoDeRender;
|
|
10
|
+
export type VisualAxis = EixoVisualDeRender;
|
|
11
|
+
export type Translator = TradutorDeRender;
|
|
12
|
+
export type AxisChoice = EscolhaDeEixoDeRender;
|
|
@@ -1,95 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// ui/visual-axes-panel —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// outro. O controle único era a forma honesta de contar uma exclusividade REAL; mantê-lo agora seria contar
|
|
15
|
-
// uma exclusividade que já não existe — e continuar a negar os dois a quem precisa dos dois.
|
|
16
|
-
//
|
|
17
|
-
// ========================= OS NOMES DOS PADRÕES SÃO DECISÃO, NÃO ROTINA =========================
|
|
18
|
-
// ⚠️ «Tema padrão» e «Visão tricromática», e o ADR-0076 fecha a *definition of done* com a regra que os
|
|
19
|
-
// escolheu: **nenhum rótulo de padrão diagnostica quem lê**. `modo sem deficiência visual` foi oferecido e
|
|
20
|
-
// recusado — ele diz à criança o que ela NÃO é, no menu que ela abriu para conseguir jogar. Um padrão
|
|
21
|
-
// chama-se pelo que ele É.
|
|
22
|
-
//
|
|
23
|
-
// E `Modo padrão` (o `viz.normal` de hoje) deixa de servir aqui: era o neutro PARTILHADO, de quando os dois
|
|
24
|
-
// eixos eram um só. Com dois controles, um «padrão» sem dizer padrão de QUÊ é ambíguo em ambos.
|
|
25
|
-
//
|
|
26
|
-
// Módulo puro: devolve HTML e chaves i18n, não toca documento nenhum. Quem monta é o `render/viz-setters`.
|
|
27
|
-
import { TEMAS, CORRECOES } from '../render/viz-axes.js';
|
|
28
|
-
/** O rótulo de cada tema. Chave i18n — quem exibe resolve, como todo o resto do menu. */
|
|
29
|
-
export const ROTULO_DO_TEMA = Object.freeze({
|
|
30
|
-
padrao: 'eixo.tema.padrao',
|
|
31
|
-
hc3: 'viz.hc-direto',
|
|
32
|
-
hc45: 'viz.hc-direto-45',
|
|
33
|
-
hc7: 'viz.hc-direto-7',
|
|
34
|
-
});
|
|
35
|
-
/** O rótulo de cada correção de cor. */
|
|
36
|
-
export const ROTULO_DA_CORRECAO = Object.freeze({
|
|
37
|
-
tricro: 'eixo.correcao.tricro',
|
|
38
|
-
protan: 'viz.fix-protan',
|
|
39
|
-
deuter: 'viz.fix-deuter',
|
|
40
|
-
tritan: 'viz.fix-tritan',
|
|
41
|
-
});
|
|
42
|
-
/**
|
|
43
|
-
* Os rótulos CURTOS, para os ícones da barra rápida — «7:1», «deuteranopia».
|
|
44
|
-
*
|
|
45
|
-
* ⚠️ SÃO AS CHAVES QUE JÁ EXISTIAM (`contrast.*`, `cvd.*`), re-chaveadas por eixo. A barra rápida sempre
|
|
46
|
-
* falou curto porque anuncia UM ícone de cada vez, e o painel sempre falou por extenso porque a criança está
|
|
47
|
-
* a ler uma lista — a diferença é de contexto e sobrevive à divisão. Reaproveitar em vez de traduzir de novo
|
|
48
|
-
* é o que mantém a mesma palavra nos dois sítios.
|
|
49
|
-
*/
|
|
50
|
-
export const CURTO_DO_TEMA = Object.freeze({
|
|
51
|
-
padrao: 'contrast.off', hc3: 'contrast.3', hc45: 'contrast.45', hc7: 'contrast.7',
|
|
52
|
-
});
|
|
53
|
-
export const CURTO_DA_CORRECAO = Object.freeze({
|
|
54
|
-
tricro: 'cvd.off', protan: 'cvd.protan', deuter: 'cvd.deuter', tritan: 'cvd.tritan',
|
|
55
|
-
});
|
|
56
|
-
/**
|
|
57
|
-
* As linhas de UM eixo, no formato de rádio que o painel já usa.
|
|
58
|
-
*
|
|
59
|
-
* ⚠️ RÁDIO E NÃO SETE BOTÕES, e o motivo sobrevive à divisão: DENTRO de um eixo os valores continuam
|
|
60
|
-
* exclusivos — um tema de cada vez, uma correção de cada vez. O que deixou de ser exclusivo é a relação
|
|
61
|
-
* ENTRE os eixos, e é por isso que eles viram dois rádios em vez de um.
|
|
62
|
-
*
|
|
63
|
-
* ⚠️ E MANTÉM-SE A FORMA DE LINHA VISÍVEL, não um `<select>`. O `settings-visual` regista o erro que o Dev
|
|
64
|
-
* apanhou na primeira tentativa: dentro de uma caixa fechada, um controle cuja razão de existir é ser ACHADO
|
|
65
|
-
* por quem enxerga mal fica «quase o mesmo que não ter movido».
|
|
66
|
-
*/
|
|
67
|
-
export function linhasDoEixo(eixo, valores, rotulos, atual, t) {
|
|
68
|
-
return valores.map((valor) => {
|
|
69
|
-
const sel = valor === atual;
|
|
70
|
-
return `<div class="ctrl-row"><span><strong>${t(rotulos[valor])}</strong></span>`
|
|
71
|
-
+ `<button class="mode-btn${sel ? ' is-on' : ''}" role="radio" aria-checked="${sel}"`
|
|
72
|
-
+ ` data-eixo="${eixo}" data-valor="${valor}" type="button">${sel ? t('viz.escolhido') : t('viz.escolher')}</button></div>`;
|
|
73
|
-
}).join('');
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Os DOIS eixos, um a seguir ao outro, com um título cada.
|
|
77
|
-
*
|
|
78
|
-
* O título existe porque dois rádios seguidos sem nome são um rádio de oito para quem lê depressa — e essa
|
|
79
|
-
* leitura é exactamente o mal-entendido que a divisão existe para desfazer.
|
|
80
|
-
*/
|
|
81
|
-
export function eixosHtml(v, t) {
|
|
82
|
-
return `<h3 class="opt-sub">${t('eixo.tema.titulo')}</h3>`
|
|
83
|
-
+ linhasDoEixo('tema', TEMAS, ROTULO_DO_TEMA, v.tema, t)
|
|
84
|
-
+ `<h3 class="opt-sub">${t('eixo.correcao.titulo')}</h3>`
|
|
85
|
-
+ linhasDoEixo('correcao', CORRECOES, ROTULO_DA_CORRECAO, v.correcao, t);
|
|
86
|
-
}
|
|
87
|
-
export function escolhaDoBotao(dataset) {
|
|
88
|
-
const { eixo, valor } = dataset;
|
|
89
|
-
if (eixo !== 'tema' && eixo !== 'correcao')
|
|
90
|
-
return null;
|
|
91
|
-
if (!valor)
|
|
92
|
-
return null;
|
|
93
|
-
const validos = eixo === 'tema' ? TEMAS : CORRECOES;
|
|
94
|
-
return validos.includes(valor) ? { eixo, valor } : null;
|
|
95
|
-
}
|
|
2
|
+
// ui/visual-axes-panel — the two visual axes' labels, rows and click reading (ADR-0076): the names cartridges import from ui.
|
|
3
|
+
//
|
|
4
|
+
// The module lives in `render/viz-axes-labels` since issue #167: `render/viz-setters` uses it, and render may not import ui
|
|
5
|
+
// (ADR-0173). These names stay, bound to the same values and types.
|
|
6
|
+
import { THEME_LABEL as ROTULO_DO_TEMADeRender, CORRECTION_LABEL as ROTULO_DA_CORRECAODeRender, SHORT_THEME as CURTO_DO_TEMADeRender, SHORT_CORRECTION as CURTO_DA_CORRECAODeRender, axisRows as linhasDoEixoDeRender, axesHtml as eixosHtmlDeRender, buttonChoice as escolhaDoBotaoDeRender, } from '../render/viz-axes-labels.js';
|
|
7
|
+
export const THEME_LABEL = ROTULO_DO_TEMADeRender;
|
|
8
|
+
export const CORRECTION_LABEL = ROTULO_DA_CORRECAODeRender;
|
|
9
|
+
export const SHORT_THEME = CURTO_DO_TEMADeRender;
|
|
10
|
+
export const SHORT_CORRECTION = CURTO_DA_CORRECAODeRender;
|
|
11
|
+
export const axisRows = linhasDoEixoDeRender;
|
|
12
|
+
export const axesHtml = eixosHtmlDeRender;
|
|
13
|
+
export const buttonChoice = escolhaDoBotaoDeRender;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Translate } from '../core/i18n.js';
|
|
3
|
+
import type { HcRoleKey } from '../render/hc-role-data.js';
|
|
4
|
+
import { type VizMode } from '../render/viz-modes.js';
|
|
5
|
+
export type { HcRoleKey as RoleKey } from '../render/hc-role-data.js';
|
|
6
|
+
type RoleKey = HcRoleKey;
|
|
7
|
+
export type RGB = readonly [number, number, number];
|
|
8
|
+
/**
|
|
9
|
+
* EVERYTHING this menu writes into `p.viz`: the 4 contrast levels PLUS the 3 colour-blindness corrections, which live
|
|
10
|
+
* here by the Dev's decision (#60) — in the empathy panel a colour-blind child would have had to enter the menu for
|
|
11
|
+
* "feeling what a disability is like" to find the correction for the one they have.
|
|
12
|
+
*
|
|
13
|
+
* The seven live in ONE control, and that is not about saving space: `p.viz` holds ONE value. Two separate controls
|
|
14
|
+
* would overwrite each other silently — the child would pick the correction, then the contrast, and lose the
|
|
15
|
+
* correction with nothing saying so. One list tells the truth about the exclusivity.
|
|
16
|
+
*/
|
|
17
|
+
export declare const VISUAL_MODES: readonly string[];
|
|
18
|
+
/** Short announcement labels. */
|
|
19
|
+
export declare const CONTRAST_LABELS: Readonly<Record<string, string>>;
|
|
20
|
+
export declare const ROLE_KEYS: readonly RoleKey[];
|
|
21
|
+
/** Readable labels for the color-blocking roles. */
|
|
22
|
+
export declare const ROLE_LABELS: Readonly<Record<RoleKey, string>>;
|
|
23
|
+
/**
|
|
24
|
+
* The 7 modes as the panel OFFERS them: a radio list, with a name and a description on each row.
|
|
25
|
+
*
|
|
26
|
+
* Not a `<select>`, and the Dev caught that immediately: inside a `<select>` the corrections become one closed line in
|
|
27
|
+
* a closed box. For a control whose reason to exist is to be FOUND by someone who sees poorly, hiding it behind a
|
|
28
|
+
* click is almost the same as not offering it.
|
|
29
|
+
*
|
|
30
|
+
* Radio, and not seven buttons: `p.viz` holds ONE value, and the exclusivity is said by the shape of the control
|
|
31
|
+
* instead of being discovered by losing the correction just chosen.
|
|
32
|
+
*/
|
|
33
|
+
export declare const VISUAL_MODE_LIST: readonly VizMode[];
|
|
34
|
+
/**
|
|
35
|
+
* `viz` when it is a mode of THIS menu (contrast or correction), otherwise 'normal'.
|
|
36
|
+
*
|
|
37
|
+
* Named for what it returns: a name that said "contrast" would lie when it returns `fix-deuter`, and a name that lies
|
|
38
|
+
* about what it returns is worse than a long one.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveVisualMode(viz: string): string;
|
|
41
|
+
/** i18n KEY of a contrast level's label; unknown modes fall back to the 'off' key. Resolve with `t()`. */
|
|
42
|
+
export declare function contrastLabel(mode: string): string;
|
|
43
|
+
export declare function clamp01(t: number): number;
|
|
44
|
+
/**
|
|
45
|
+
* i18n KEY of the L->Q slider label ('lq.off'/'lq.linear'/'lq.mixed'/'lq.quadratic'). The label belongs to the L->Q
|
|
46
|
+
* feature, so it lives with the filter that owns it (render/lq-filter) and is re-exported here under the name this
|
|
47
|
+
* overlay has always used. Two copies of one rule is one copy too many: only the owner may change what the levels
|
|
48
|
+
* mean. Callers resolve with `t()` — see the note on lqName about the `t` shadowing.
|
|
49
|
+
*/
|
|
50
|
+
export { lqName as lqLabel } from '../render/lq-filter.js';
|
|
51
|
+
/**
|
|
52
|
+
* THE FOUR POSITIONS OF THE CONTRAST BOOST, chosen with left and right (ADR-0151): off, linear, mixed and quadratic —
|
|
53
|
+
* «da mesma forma que se troca o número de jogadores, e não através de uma barra».
|
|
54
|
+
*
|
|
55
|
+
* ⚠️ THE "LINEAR" VALUE CANNOT BE ZERO: `setLq(0)` turns the filter off, and any value above turns the curve on. 0.05
|
|
56
|
+
* is the most linear value that still turns the filter on. Mixed is the middle, and quadratic is the whole S-curve.
|
|
57
|
+
* Each position falls within the range `lqName` already gives its name.
|
|
58
|
+
*/
|
|
59
|
+
export declare const LQ_STEPS: readonly number[];
|
|
60
|
+
/**
|
|
61
|
+
* Which position a continuous value is in — including one STORED by the old slider (0.35, 0.7…). By `lqName`'s range,
|
|
62
|
+
* not by the nearest value: the NAME the child heard has to stay the name now.
|
|
63
|
+
*/
|
|
64
|
+
export declare function lqPosition(amount: number): number;
|
|
65
|
+
/** t (0..1) -> slider percent (0..100, rounded) — mirrors `Math.round(lqT*100)`.
|
|
66
|
+
* @deprecated Since ADR-0151 the boost is chosen by STEPS (`LQ_STEPS`/`lqPosition`); kept for consumers.
|
|
67
|
+
* ⚠️ It has no reader inside the engine: that debt is said here so that it stays in view. */
|
|
68
|
+
export declare function lqPercent(t: number): number;
|
|
69
|
+
/** slider percent (any number) -> clamped t (0..1) — mirrors `+lq.value/100` fed into setLq's clamp.
|
|
70
|
+
* @deprecated Since ADR-0151 the boost is chosen by STEPS; kept for consumers. */
|
|
71
|
+
export declare function lqFromPercent(pct: number): number;
|
|
72
|
+
/** Defensive clamp when the player count shrank — mirrors `if(selVizPlayer>=numPlayers)selVizPlayer=0`. */
|
|
73
|
+
export declare function clampSelectedPlayer(selected: number, playerCount: number): number;
|
|
74
|
+
/** [r,g,b] (0..255) -> '#rrggbb'. */
|
|
75
|
+
export declare function rgbToHex(rgb: RGB): string;
|
|
76
|
+
/** Shared on/off button label used by this panel's toggle buttons. */
|
|
77
|
+
export declare function onOffLabel(t: Translate, on: boolean): string;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// ui/visual-choices — WHAT A VISUAL CHOICE IS, with no document anywhere near it.
|
|
3
|
+
//
|
|
4
|
+
// 📌 THE SUITE HAD ALREADY DRAWN THIS SEAM, which is what makes the cut a reading and not an opinion:
|
|
5
|
+
// `tests/settings-visual.node.test.js` imports exactly these names and nothing else, and the node project mounts no
|
|
6
|
+
// document — so whoever wrote those cases had to know where the panel stopped being a panel. It is the fourth module to
|
|
7
|
+
// come out this way, after `ui/audio-choices`, `ui/typo-choices` and `ui/control-choices`.
|
|
8
|
+
//
|
|
9
|
+
// What lives here answers «what are the positions, what is each one called, and what does a value mean»; what stayed in
|
|
10
|
+
// `ui/settings-visual` is the work its name never mentioned — finding the controls, wiring them, and reflecting the
|
|
11
|
+
// choice on three surfaces.
|
|
12
|
+
import { toggleLabel } from './dom.js';
|
|
13
|
+
import { CONTRAST_LEVELS } from '../core/visual-cycles.js';
|
|
14
|
+
import { HC_ROLE_KEYS } from '../render/hc-role-data.js';
|
|
15
|
+
import { VIZ_CORRECTIONS, VIZ_MODES } from '../render/viz-modes.js';
|
|
16
|
+
/**
|
|
17
|
+
* EVERYTHING this menu writes into `p.viz`: the 4 contrast levels PLUS the 3 colour-blindness corrections, which live
|
|
18
|
+
* here by the Dev's decision (#60) — in the empathy panel a colour-blind child would have had to enter the menu for
|
|
19
|
+
* "feeling what a disability is like" to find the correction for the one they have.
|
|
20
|
+
*
|
|
21
|
+
* The seven live in ONE control, and that is not about saving space: `p.viz` holds ONE value. Two separate controls
|
|
22
|
+
* would overwrite each other silently — the child would pick the correction, then the contrast, and lose the
|
|
23
|
+
* correction with nothing saying so. One list tells the truth about the exclusivity.
|
|
24
|
+
*/
|
|
25
|
+
export const VISUAL_MODES = [...CONTRAST_LEVELS, ...VIZ_CORRECTIONS.map((m) => m.key)];
|
|
26
|
+
const VISUAL_MODE_SET = new Set(VISUAL_MODES);
|
|
27
|
+
/** Short announcement labels. */
|
|
28
|
+
// i18n keys, not text. The ratios look like universal numbers, but '4,5:1' uses the pt-BR decimal comma and becomes
|
|
29
|
+
// '4.5:1' in English — and 'off' is a word in each language.
|
|
30
|
+
export const CONTRAST_LABELS = { normal: 'contrast.off', 'hc-direto': 'contrast.3', 'hc-direto-45': 'contrast.45', 'hc-direto-7': 'contrast.7' };
|
|
31
|
+
export const ROLE_KEYS = HC_ROLE_KEYS;
|
|
32
|
+
/** Readable labels for the color-blocking roles. */
|
|
33
|
+
export const ROLE_LABELS = { hazard: 'perigo (lava)', climb: 'escalável (escada/trampolim)', water: 'água', gate: 'portão' };
|
|
34
|
+
/**
|
|
35
|
+
* The 7 modes as the panel OFFERS them: a radio list, with a name and a description on each row.
|
|
36
|
+
*
|
|
37
|
+
* Not a `<select>`, and the Dev caught that immediately: inside a `<select>` the corrections become one closed line in
|
|
38
|
+
* a closed box. For a control whose reason to exist is to be FOUND by someone who sees poorly, hiding it behind a
|
|
39
|
+
* click is almost the same as not offering it.
|
|
40
|
+
*
|
|
41
|
+
* Radio, and not seven buttons: `p.viz` holds ONE value, and the exclusivity is said by the shape of the control
|
|
42
|
+
* instead of being discovered by losing the correction just chosen.
|
|
43
|
+
*/
|
|
44
|
+
export const VISUAL_MODE_LIST = VIZ_MODES.filter((m) => m.kind === 'normal' || m.kind === 'hcnew').concat(VIZ_CORRECTIONS);
|
|
45
|
+
/**
|
|
46
|
+
* `viz` when it is a mode of THIS menu (contrast or correction), otherwise 'normal'.
|
|
47
|
+
*
|
|
48
|
+
* Named for what it returns: a name that said "contrast" would lie when it returns `fix-deuter`, and a name that lies
|
|
49
|
+
* about what it returns is worse than a long one.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveVisualMode(viz) {
|
|
52
|
+
return VISUAL_MODE_SET.has(viz) ? viz : 'normal';
|
|
53
|
+
}
|
|
54
|
+
/** i18n KEY of a contrast level's label; unknown modes fall back to the 'off' key. Resolve with `t()`. */
|
|
55
|
+
export function contrastLabel(mode) {
|
|
56
|
+
return CONTRAST_LABELS[mode] ?? CONTRAST_LABELS.normal;
|
|
57
|
+
}
|
|
58
|
+
export function clamp01(t) {
|
|
59
|
+
return Math.max(0, Math.min(1, t));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* i18n KEY of the L->Q slider label ('lq.off'/'lq.linear'/'lq.mixed'/'lq.quadratic'). The label belongs to the L->Q
|
|
63
|
+
* feature, so it lives with the filter that owns it (render/lq-filter) and is re-exported here under the name this
|
|
64
|
+
* overlay has always used. Two copies of one rule is one copy too many: only the owner may change what the levels
|
|
65
|
+
* mean. Callers resolve with `t()` — see the note on lqName about the `t` shadowing.
|
|
66
|
+
*/
|
|
67
|
+
export { lqName as lqLabel } from '../render/lq-filter.js';
|
|
68
|
+
import { lqName } from '../render/lq-filter.js';
|
|
69
|
+
/**
|
|
70
|
+
* THE FOUR POSITIONS OF THE CONTRAST BOOST, chosen with left and right (ADR-0151): off, linear, mixed and quadratic —
|
|
71
|
+
* «da mesma forma que se troca o número de jogadores, e não através de uma barra».
|
|
72
|
+
*
|
|
73
|
+
* ⚠️ THE "LINEAR" VALUE CANNOT BE ZERO: `setLq(0)` turns the filter off, and any value above turns the curve on. 0.05
|
|
74
|
+
* is the most linear value that still turns the filter on. Mixed is the middle, and quadratic is the whole S-curve.
|
|
75
|
+
* Each position falls within the range `lqName` already gives its name.
|
|
76
|
+
*/
|
|
77
|
+
export const LQ_STEPS = [0, 0.05, 0.5, 1];
|
|
78
|
+
/**
|
|
79
|
+
* Which position a continuous value is in — including one STORED by the old slider (0.35, 0.7…). By `lqName`'s range,
|
|
80
|
+
* not by the nearest value: the NAME the child heard has to stay the name now.
|
|
81
|
+
*/
|
|
82
|
+
export function lqPosition(amount) {
|
|
83
|
+
return Math.max(0, ['lq.off', 'lq.linear', 'lq.mixed', 'lq.quadratic'].indexOf(lqName(amount)));
|
|
84
|
+
}
|
|
85
|
+
/** t (0..1) -> slider percent (0..100, rounded) — mirrors `Math.round(lqT*100)`.
|
|
86
|
+
* @deprecated Since ADR-0151 the boost is chosen by STEPS (`LQ_STEPS`/`lqPosition`); kept for consumers.
|
|
87
|
+
* ⚠️ It has no reader inside the engine: that debt is said here so that it stays in view. */
|
|
88
|
+
export function lqPercent(t) {
|
|
89
|
+
return Math.round(clamp01(t) * 100);
|
|
90
|
+
}
|
|
91
|
+
/** slider percent (any number) -> clamped t (0..1) — mirrors `+lq.value/100` fed into setLq's clamp.
|
|
92
|
+
* @deprecated Since ADR-0151 the boost is chosen by STEPS; kept for consumers. */
|
|
93
|
+
export function lqFromPercent(pct) {
|
|
94
|
+
return clamp01(pct / 100);
|
|
95
|
+
}
|
|
96
|
+
/** Defensive clamp when the player count shrank — mirrors `if(selVizPlayer>=numPlayers)selVizPlayer=0`. */
|
|
97
|
+
export function clampSelectedPlayer(selected, playerCount) {
|
|
98
|
+
return selected >= playerCount ? 0 : selected;
|
|
99
|
+
}
|
|
100
|
+
/** [r,g,b] (0..255) -> '#rrggbb'. */
|
|
101
|
+
export function rgbToHex(rgb) {
|
|
102
|
+
return '#' + rgb.map((n) => n.toString(16).padStart(2, '0')).join('');
|
|
103
|
+
}
|
|
104
|
+
/** Shared on/off button label used by this panel's toggle buttons. */
|
|
105
|
+
export function onOffLabel(t, on) {
|
|
106
|
+
return toggleLabel(t, on);
|
|
107
|
+
}
|